xref: /dflybsd-src/test/unix/passdesc/passdesc.c (revision de05ab5fb2b60315f8867441b393a3e11c54be17)
17dd6b35fSSepherosa Ziehau #include <sys/types.h>
27dd6b35fSSepherosa Ziehau #include <sys/socket.h>
37dd6b35fSSepherosa Ziehau #include <sys/stat.h>
47dd6b35fSSepherosa Ziehau #include <sys/un.h>
57dd6b35fSSepherosa Ziehau #include <sys/wait.h>
67dd6b35fSSepherosa Ziehau 
77dd6b35fSSepherosa Ziehau #include <err.h>
87dd6b35fSSepherosa Ziehau #include <stdint.h>
97dd6b35fSSepherosa Ziehau #include <stdio.h>
107dd6b35fSSepherosa Ziehau #include <stdlib.h>
117dd6b35fSSepherosa Ziehau #include <string.h>
127dd6b35fSSepherosa Ziehau #include <unistd.h>
137dd6b35fSSepherosa Ziehau 
147dd6b35fSSepherosa Ziehau #define TEST_FILENAME	"/tmp/passdesc"
157dd6b35fSSepherosa Ziehau 
16*de05ab5fSSepherosa Ziehau static int	test_buflen;
17*de05ab5fSSepherosa Ziehau static void	*test_buf;
18*de05ab5fSSepherosa Ziehau 
197dd6b35fSSepherosa Ziehau static void
test_send_desc(int s,int fd)207dd6b35fSSepherosa Ziehau test_send_desc(int s, int fd)
217dd6b35fSSepherosa Ziehau {
227dd6b35fSSepherosa Ziehau 	struct msghdr msg;
237dd6b35fSSepherosa Ziehau 	struct iovec iov;
247dd6b35fSSepherosa Ziehau 	union {
257dd6b35fSSepherosa Ziehau 		struct cmsghdr cm;
267dd6b35fSSepherosa Ziehau 		uint8_t data[CMSG_SPACE(sizeof(int))];
277dd6b35fSSepherosa Ziehau 	} ctrl;
287dd6b35fSSepherosa Ziehau 	struct cmsghdr *cm;
297dd6b35fSSepherosa Ziehau 	int n;
307dd6b35fSSepherosa Ziehau 
31*de05ab5fSSepherosa Ziehau 	iov.iov_base = test_buf;
32*de05ab5fSSepherosa Ziehau 	iov.iov_len = test_buflen;
337dd6b35fSSepherosa Ziehau 
347dd6b35fSSepherosa Ziehau 	memset(&msg, 0, sizeof(msg));
357dd6b35fSSepherosa Ziehau 	msg.msg_iov = &iov;
367dd6b35fSSepherosa Ziehau 	msg.msg_iovlen = 1;
377dd6b35fSSepherosa Ziehau 	msg.msg_control = ctrl.data;
387dd6b35fSSepherosa Ziehau 	msg.msg_controllen = sizeof(ctrl.data);
397dd6b35fSSepherosa Ziehau 
407dd6b35fSSepherosa Ziehau 	memset(&ctrl, 0, sizeof(ctrl));
417dd6b35fSSepherosa Ziehau 	cm = CMSG_FIRSTHDR(&msg);
427dd6b35fSSepherosa Ziehau 	cm->cmsg_len = CMSG_LEN(sizeof(int));
437dd6b35fSSepherosa Ziehau 	cm->cmsg_level = SOL_SOCKET;
447dd6b35fSSepherosa Ziehau 	cm->cmsg_type = SCM_RIGHTS;
457dd6b35fSSepherosa Ziehau 	*((int *)CMSG_DATA(cm)) = fd;
467dd6b35fSSepherosa Ziehau 
477dd6b35fSSepherosa Ziehau 	n = sendmsg(s, &msg, 0);
487dd6b35fSSepherosa Ziehau 	if (n < 0)
497dd6b35fSSepherosa Ziehau 		err(1, "sendmsg failed");
50*de05ab5fSSepherosa Ziehau 	else if (n != test_buflen)
517dd6b35fSSepherosa Ziehau 		errx(1, "sendmsg sent %d", n);
527dd6b35fSSepherosa Ziehau 	close(fd);
537dd6b35fSSepherosa Ziehau }
547dd6b35fSSepherosa Ziehau 
557dd6b35fSSepherosa Ziehau static void
test_recv_desc(int s)567dd6b35fSSepherosa Ziehau test_recv_desc(int s)
577dd6b35fSSepherosa Ziehau {
587dd6b35fSSepherosa Ziehau 	struct msghdr msg;
597dd6b35fSSepherosa Ziehau 	struct iovec iov;
607dd6b35fSSepherosa Ziehau 	union {
617dd6b35fSSepherosa Ziehau 		struct cmsghdr cm;
627dd6b35fSSepherosa Ziehau 		uint8_t data[CMSG_SPACE(sizeof(int))];
637dd6b35fSSepherosa Ziehau 	} ctrl;
647dd6b35fSSepherosa Ziehau 	struct cmsghdr *cm;
65*de05ab5fSSepherosa Ziehau 	int n, fd;
667dd6b35fSSepherosa Ziehau 	char data[16];
677dd6b35fSSepherosa Ziehau 
68*de05ab5fSSepherosa Ziehau 	iov.iov_base = test_buf;
69*de05ab5fSSepherosa Ziehau 	iov.iov_len = test_buflen;
707dd6b35fSSepherosa Ziehau 
717dd6b35fSSepherosa Ziehau 	memset(&msg, 0, sizeof(msg));
727dd6b35fSSepherosa Ziehau 	msg.msg_iov = &iov;
737dd6b35fSSepherosa Ziehau 	msg.msg_iovlen = 1;
747dd6b35fSSepherosa Ziehau 	msg.msg_control = ctrl.data;
757dd6b35fSSepherosa Ziehau 	msg.msg_controllen = sizeof(ctrl.data);
767dd6b35fSSepherosa Ziehau 
77*de05ab5fSSepherosa Ziehau 	n = recvmsg(s, &msg, MSG_WAITALL);
787dd6b35fSSepherosa Ziehau 	if (n < 0)
797dd6b35fSSepherosa Ziehau 		err(1, "recvmsg failed");
80*de05ab5fSSepherosa Ziehau 	else if (n != test_buflen)
817dd6b35fSSepherosa Ziehau 		errx(1, "recvmsg received %d", n);
827dd6b35fSSepherosa Ziehau 
837dd6b35fSSepherosa Ziehau 	cm = CMSG_FIRSTHDR(&msg);
847dd6b35fSSepherosa Ziehau 	if (cm == NULL)
857dd6b35fSSepherosa Ziehau 		errx(1, "no cmsg");
867dd6b35fSSepherosa Ziehau 	if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
877dd6b35fSSepherosa Ziehau 		errx(1, "cmsg len mismatch");
887dd6b35fSSepherosa Ziehau 	if (cm->cmsg_level != SOL_SOCKET)
897dd6b35fSSepherosa Ziehau 		errx(1, "cmsg level mismatch");
907dd6b35fSSepherosa Ziehau 	if (cm->cmsg_type != SCM_RIGHTS)
917dd6b35fSSepherosa Ziehau 		errx(1, "cmsg type mismatch");
927dd6b35fSSepherosa Ziehau 
937dd6b35fSSepherosa Ziehau 	fd = *((int *)CMSG_DATA(cm));
947dd6b35fSSepherosa Ziehau 
957dd6b35fSSepherosa Ziehau 	n = read(fd, data, sizeof(data) - 1);
967dd6b35fSSepherosa Ziehau 	if (n < 0)
977dd6b35fSSepherosa Ziehau 		err(1, "read failed");
987dd6b35fSSepherosa Ziehau 	data[n] = '\0';
997dd6b35fSSepherosa Ziehau 
1007dd6b35fSSepherosa Ziehau 	fprintf(stderr, "fd content: %s\n", data);
1017dd6b35fSSepherosa Ziehau }
1027dd6b35fSSepherosa Ziehau 
103317e95feSSepherosa Ziehau static void
usage(const char * cmd)104317e95feSSepherosa Ziehau usage(const char *cmd)
1057dd6b35fSSepherosa Ziehau {
106*de05ab5fSSepherosa Ziehau 	fprintf(stderr, "%s [-d] [-s] [-p payload_len]\n", cmd);
107317e95feSSepherosa Ziehau 	exit(1);
108317e95feSSepherosa Ziehau }
109317e95feSSepherosa Ziehau 
110317e95feSSepherosa Ziehau int
main(int argc,char * argv[])111317e95feSSepherosa Ziehau main(int argc, char *argv[])
112317e95feSSepherosa Ziehau {
113e62cfe62SSepherosa Ziehau 	int s[2], fd, status, n, discard, skipfd;
114317e95feSSepherosa Ziehau 	int opt;
1157dd6b35fSSepherosa Ziehau 	off_t ofs;
1167dd6b35fSSepherosa Ziehau 
117317e95feSSepherosa Ziehau 	discard = 0;
118e62cfe62SSepherosa Ziehau 	skipfd = 0;
119*de05ab5fSSepherosa Ziehau 	while ((opt = getopt(argc, argv, "dp:s")) != -1) {
120317e95feSSepherosa Ziehau 		switch (opt) {
121317e95feSSepherosa Ziehau 		case 'd':
122317e95feSSepherosa Ziehau 			discard = 1;
123317e95feSSepherosa Ziehau 			break;
124317e95feSSepherosa Ziehau 
125*de05ab5fSSepherosa Ziehau 		case 'p':
126*de05ab5fSSepherosa Ziehau 			test_buflen = strtoul(optarg, NULL, 10);
127*de05ab5fSSepherosa Ziehau 			break;
128*de05ab5fSSepherosa Ziehau 
129e62cfe62SSepherosa Ziehau 		case 's':
130e62cfe62SSepherosa Ziehau 			skipfd = 1;
131e62cfe62SSepherosa Ziehau 			break;
132e62cfe62SSepherosa Ziehau 
133317e95feSSepherosa Ziehau 		default:
134317e95feSSepherosa Ziehau 			usage(argv[0]);
135317e95feSSepherosa Ziehau 		}
136317e95feSSepherosa Ziehau 	}
137317e95feSSepherosa Ziehau 
138*de05ab5fSSepherosa Ziehau 	if (test_buflen <= 0)
139*de05ab5fSSepherosa Ziehau 		test_buflen = sizeof(int);
140*de05ab5fSSepherosa Ziehau 	test_buf = malloc(test_buflen);
141*de05ab5fSSepherosa Ziehau 	if (test_buf == NULL)
142*de05ab5fSSepherosa Ziehau 		err(1, "malloc %d failed", test_buflen);
143*de05ab5fSSepherosa Ziehau 
1447dd6b35fSSepherosa Ziehau 	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, s) < 0)
1457dd6b35fSSepherosa Ziehau 		err(1, "socketpair(LOCAL, STREAM) failed");
1467dd6b35fSSepherosa Ziehau 
1477dd6b35fSSepherosa Ziehau 	if (fork() == 0) {
1487dd6b35fSSepherosa Ziehau 		close(s[0]);
149e62cfe62SSepherosa Ziehau 		if (!discard && !skipfd) {
1507dd6b35fSSepherosa Ziehau 			test_recv_desc(s[1]);
151e62cfe62SSepherosa Ziehau 		} else if (skipfd) {
152e62cfe62SSepherosa Ziehau 			int buf;
153e62cfe62SSepherosa Ziehau 
154e62cfe62SSepherosa Ziehau 			fprintf(stderr, "skipfd\n");
155e62cfe62SSepherosa Ziehau 			n = read(s[1], &buf, sizeof(buf));
156e62cfe62SSepherosa Ziehau 			if (n < 0)
157e62cfe62SSepherosa Ziehau 				err(1, "read failed");
158e62cfe62SSepherosa Ziehau 		} else {
159e62cfe62SSepherosa Ziehau 			fprintf(stderr, "discard msg\n");
160317e95feSSepherosa Ziehau 			sleep(5);
161e62cfe62SSepherosa Ziehau 		}
1627dd6b35fSSepherosa Ziehau 		exit(0);
1637dd6b35fSSepherosa Ziehau 	}
1647dd6b35fSSepherosa Ziehau 	close(s[1]);
1657dd6b35fSSepherosa Ziehau 
1667dd6b35fSSepherosa Ziehau 	fd = open(TEST_FILENAME, O_RDWR | O_TRUNC | O_CREAT,
1677dd6b35fSSepherosa Ziehau 	    S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
1687dd6b35fSSepherosa Ziehau 	if (fd < 0)
1697dd6b35fSSepherosa Ziehau 		err(1, "open " TEST_FILENAME " failed");
1707dd6b35fSSepherosa Ziehau 
1717dd6b35fSSepherosa Ziehau 	n = write(fd, TEST_FILENAME, strlen(TEST_FILENAME));
1727dd6b35fSSepherosa Ziehau 	if (n < 0)
1737dd6b35fSSepherosa Ziehau 		err(1, "write failed");
1747dd6b35fSSepherosa Ziehau 	else if (n != strlen(TEST_FILENAME))
1757dd6b35fSSepherosa Ziehau 		errx(1, "write %d", n);
1767dd6b35fSSepherosa Ziehau 
1777dd6b35fSSepherosa Ziehau 	ofs = lseek(fd, 0, SEEK_SET);
1787dd6b35fSSepherosa Ziehau 	if (ofs < 0)
1797dd6b35fSSepherosa Ziehau 		err(1, "lseek failed");
1807dd6b35fSSepherosa Ziehau 	else if (ofs != 0)
1817dd6b35fSSepherosa Ziehau 		errx(1, "lseek offset %jd", (intmax_t)ofs);
1827dd6b35fSSepherosa Ziehau 
1837dd6b35fSSepherosa Ziehau 	test_send_desc(s[0], fd);
1847dd6b35fSSepherosa Ziehau 
1857dd6b35fSSepherosa Ziehau 	wait(&status);
1867dd6b35fSSepherosa Ziehau 	exit(0);
1877dd6b35fSSepherosa Ziehau }
188