Sync usage with man page.
[netbsd-mini2440.git] / tests / syscall / t_cmsg.c
blob124c45285680560cc60c5f6b91fed3d7396d1a22
1 /* $NetBSD: t_cmsg.c,v 1.12 2009/11/26 17:33:23 pooka Exp $ */
3 #include <sys/types.h>
4 #include <sys/mount.h>
5 #include <sys/socket.h>
6 #include <sys/un.h>
8 #include <rump/rump.h>
9 #include <rump/rump_syscalls.h>
11 #include <atf-c.h>
12 #include <fcntl.h>
13 #include <err.h>
14 #include <errno.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <util.h>
21 #include "../h_macros.h"
23 ATF_TC(cmsg_sendfd_bounds);
24 ATF_TC_HEAD(cmsg_sendfd_bounds, tc)
26 atf_tc_set_md_var(tc, "descr", "Checks that attempting to pass an "
27 "invalid fd returns an error");
30 ATF_TC_BODY(cmsg_sendfd_bounds, tc)
32 struct cmsghdr *cmp;
33 struct msghdr msg;
34 struct iovec iov;
35 int s[2];
36 int fd;
38 rump_init();
40 if (rump_sys_socketpair(AF_LOCAL, SOCK_STREAM, 0, s) == -1)
41 atf_tc_fail("rump_sys_socket");
43 cmp = malloc(CMSG_SPACE(sizeof(int)));
45 iov.iov_base = &fd;
46 iov.iov_len = sizeof(int);
48 cmp->cmsg_level = SOL_SOCKET;
49 cmp->cmsg_type = SCM_RIGHTS;
50 cmp->cmsg_len = CMSG_LEN(sizeof(int));
52 msg.msg_iov = &iov;
53 msg.msg_iovlen = 1;
54 msg.msg_name = NULL;
55 msg.msg_namelen = 0;
56 msg.msg_control = cmp;
57 msg.msg_controllen = CMSG_SPACE(sizeof(int));
60 * ERROR HERE: trying to pass invalid fd
61 * (This value was previously directly used to index the fd
62 * array and therefore we are passing a hyperspace index)
64 *(int *)CMSG_DATA(cmp) = 0x12345678;
66 rump_sys_sendmsg(s[0], &msg, 0);
67 if (errno != EBADF)
68 atf_tc_fail("descriptor passing failed: expected EBADF (9), "
69 "got %d\n(%s)", errno, strerror(errno));
73 ATF_TC(cmsg_sendfd);
74 ATF_TC_HEAD(cmsg_sendfd, tc)
76 atf_tc_set_md_var(tc, "descr", "Checks that fd passing works");
77 atf_tc_set_md_var(tc, "timeout", "2");
80 ATF_TC_BODY(cmsg_sendfd, tc)
82 char buf[128];
83 struct cmsghdr *cmp;
84 struct msghdr msg;
85 struct sockaddr_un sun;
86 struct lwp *l1, *l2;
87 struct iovec iov;
88 socklen_t sl;
89 int s1, s2, sgot;
90 int rfd, fd[2], storage;
92 rump_init();
94 /* create first (non-proc0) process to be used in test */
95 l1 = rump_pub_newproc_switch();
97 /* create unix socket and bind it to a path */
98 memset(&sun, 0, sizeof(sun));
99 sun.sun_family = AF_LOCAL;
100 #define SOCKPATH "/com"
101 strncpy(sun.sun_path, SOCKPATH, sizeof(SOCKPATH));
102 s1 = rump_sys_socket(AF_LOCAL, SOCK_STREAM, 0);
103 if (s1 == -1)
104 atf_tc_fail_errno("socket 1");
105 if (rump_sys_bind(s1, (struct sockaddr *)&sun, SUN_LEN(&sun)) == -1)
106 atf_tc_fail_errno("socket 1 bind");
107 if (rump_sys_listen(s1, 1) == -1)
108 atf_tc_fail_errno("socket 1 listen");
110 /* create second process for test */
111 l2 = rump_pub_newproc_switch();
113 /* connect to unix domain socket */
114 memset(&sun, 0, sizeof(sun));
115 sun.sun_family = AF_LOCAL;
116 strncpy(sun.sun_path, SOCKPATH, sizeof(SOCKPATH));
117 s2 = rump_sys_socket(AF_LOCAL, SOCK_STREAM, 0);
118 if (s2 == -1)
119 atf_tc_fail_errno("socket 2");
120 if (rump_sys_connect(s2, (struct sockaddr *)&sun, SUN_LEN(&sun)) == -1)
121 atf_tc_fail_errno("socket 2 connect");
123 /* open a pipe and write stuff to it */
124 if (rump_sys_pipe(fd) == -1)
125 atf_tc_fail_errno("can't open pipe");
126 #define MAGICSTRING "duam xnaht"
127 if (rump_sys_write(fd[1], MAGICSTRING, sizeof(MAGICSTRING)) !=
128 sizeof(MAGICSTRING))
129 atf_tc_fail_errno("pipe write"); /* XXX: errno */
131 cmp = malloc(CMSG_SPACE(sizeof(int)));
133 iov.iov_base = &storage;
134 iov.iov_len = sizeof(int);
136 cmp->cmsg_level = SOL_SOCKET;
137 cmp->cmsg_type = SCM_RIGHTS;
138 cmp->cmsg_len = CMSG_SPACE(sizeof(int));
140 msg.msg_iov = &iov;
141 msg.msg_iovlen = 1;
142 msg.msg_name = NULL;
143 msg.msg_namelen = 0;
144 msg.msg_control = cmp;
145 msg.msg_controllen = CMSG_LEN(sizeof(int));
146 *(int *)CMSG_DATA(cmp) = fd[0];
148 /* pass the fd */
149 if (rump_sys_sendmsg(s2, &msg, 0) == -1)
150 atf_tc_fail_errno("sendmsg failed");
153 * We will read to the same cmsg space. Overwrite the space
154 * with an invalid fd to make sure we get an explicit error
155 * if we don't manage to read the fd.
157 *(int *)CMSG_DATA(cmp) = -1;
159 /* switch back to original proc */
160 rump_pub_lwp_switch(l1);
162 /* accept connection and read fd */
163 sl = sizeof(sun);
164 sgot = rump_sys_accept(s1, (struct sockaddr *)&sun, &sl);
165 if (sgot == -1)
166 atf_tc_fail_errno("accept");
167 if (rump_sys_recvmsg(sgot, &msg, 0) == -1)
168 atf_tc_fail_errno("recvmsg failed");
169 rfd = *(int *)CMSG_DATA(cmp);
171 /* read from the fd */
172 memset(buf, 0, sizeof(buf));
173 if (rump_sys_read(rfd, buf, sizeof(buf)) == -1)
174 atf_tc_fail_errno("read rfd");
176 /* check that we got the right stuff */
177 if (strcmp(buf, MAGICSTRING) != 0)
178 atf_tc_fail("expected \"%s\", got \"%s\"", MAGICSTRING, buf);
181 ATF_TP_ADD_TCS(tp)
183 ATF_TP_ADD_TC(tp, cmsg_sendfd);
184 ATF_TP_ADD_TC(tp, cmsg_sendfd_bounds);
186 return atf_no_error();