All pastes #3755236 Raw Edit

Miscellany

public unlisted c v1 · immutable
#3755236 ·published 2017-01-08 21:23 UTC
rendered paste body
/* child process opens a connection and sends the socket fd back to the parent */#include <stdio.h>#include <sys/types.h> // socketpair#include <sys/socket.h> // socketpair#include <unistd.h> // close/fork#include <string.h> // memsetint send_socket(int sock, int dest){	struct msghdr msg;	struct cmsghdr *cmsg;	union {		struct cmsghdr align;		char msgbuf[CMSG_SPACE(sizeof(int))];	} u;	struct iovec iov[1];	char iov_data[] = { 0 };	memset(&msg, 0, sizeof(struct msghdr));	memset(iov, 0, sizeof(struct iovec));	iov[0].iov_base = iov_data;	iov[0].iov_len = 1;	msg.msg_control = u.msgbuf;	msg.msg_controllen = sizeof(u.msgbuf);	msg.msg_iov = iov;	msg.msg_iovlen = 1;	cmsg = CMSG_FIRSTHDR(&msg);	cmsg->cmsg_level = SOL_SOCKET;	cmsg->cmsg_type = SCM_RIGHTS;	cmsg->cmsg_len = CMSG_LEN(sizeof(int));	*((int*)CMSG_DATA(cmsg)) = sock;	if (sendmsg(dest, &msg, 0) == -1) {		perror("sendmsg()");		return 1;	}	printf("sent socket %i to parent as message type %i\n", sock, SCM_RIGHTS);	return 0;}int receive_socket(int src){	struct msghdr msg;	struct cmsghdr *cmsg;	union {		struct cmsghdr align;		char msgbuf[CMSG_SPACE(sizeof(int))];	} u;	struct iovec iov[1];	char iov_data[1];	memset(&msg, 0, sizeof(struct msghdr));	memset(iov, 0, sizeof(struct iovec));	iov[0].iov_base = iov_data;	iov[0].iov_len = 1;	msg.msg_control = u.msgbuf;	msg.msg_controllen = sizeof(u.msgbuf);	msg.msg_iov = iov;	msg.msg_iovlen = 1;	if (recvmsg(src, &msg, 0) == -1) {		perror("recvmsg()");		return -1;	}	printf("parent reading message\n");	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {		printf("next message type is %i\n", cmsg->cmsg_type);		if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len >= sizeof(int))			return *((int*)CMSG_DATA(cmsg));	}	printf("parent did not receive expected message\n");	return -1;}int child(int sock_parent){	int sock_inet = socket(PF_INET, SOCK_STREAM, 0);	if (sock_inet == -1) {		perror("socket()");		close(sock_parent);		return 1;	}	printf("child made socket %i\n", sock_inet);	// do things with inet socket -- set params, connect()	// then send it back to the parent	int result = send_socket(sock_inet, sock_parent);	close(sock_parent);	if (result != 0)		close(sock_inet);	return result;}int parent(int sock_child){	int sock_inet = receive_socket(sock_child);	close(sock_child);	if (sock_inet == -1)		return 1;	printf("parent receives socket %i\n", sock_inet);	// do things with the (connected) socket	// then clean up	close(sock_inet);	return 0;}int main(){	// make a socketpair for the parent & child to communicate via	int socks[2];	if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, socks) == -1) {		perror("socketpair()");		return 1;	}	switch (fork()) {		case -1:			perror("fork()");			close(socks[0]);			close(socks[1]);			return 1;		case 0:			return child(socks[0]);			break;		default:			return parent(socks[1]);	}}