xref: /netbsd-src/sys/compat/common/uipc_syscalls_43.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /*	$NetBSD: uipc_syscalls_43.c,v 1.44 2008/11/14 23:10:57 ad Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1989, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)uipc_syscalls.c	8.4 (Berkeley) 2/21/94
32  */
33 
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_43.c,v 1.44 2008/11/14 23:10:57 ad Exp $");
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/filedesc.h>
40 #include <sys/kernel.h>
41 #include <sys/proc.h>
42 #include <sys/file.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/stat.h>
46 #include <sys/ioctl.h>
47 #include <sys/fcntl.h>
48 #include <sys/malloc.h>
49 #include <sys/syslog.h>
50 #include <sys/unistd.h>
51 #include <sys/resourcevar.h>
52 #include <sys/mbuf.h>		/* for MLEN */
53 #include <sys/protosw.h>
54 
55 #include <sys/mount.h>
56 #include <sys/syscallargs.h>
57 
58 #include <net/if.h>
59 #include <net/bpf.h>
60 #include <net/route.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <net/if_gre.h>
65 #include <net/if_atm.h>
66 #include <net/if_tap.h>
67 #include <net80211/ieee80211_ioctl.h>
68 #include <netinet6/in6_var.h>
69 #include <netinet6/nd6.h>
70 #include <compat/sys/socket.h>
71 #include <compat/sys/sockio.h>
72 
73 #include <compat/common/compat_util.h>
74 
75 #include <uvm/uvm_extern.h>
76 
77 /*
78  * Following 4.3 syscalls were not versioned, even through they should
79  * have been:
80  * connect(2), bind(2), sendto(2)
81  */
82 
83 static int compat_43_sa_put(void *);
84 
85 int
86 compat_43_sys_accept(struct lwp *l, const struct compat_43_sys_accept_args *uap, register_t *retval)
87 {
88 	/* {
89 		syscallarg(int) s;
90 		syscallarg(void *) name;
91 		syscallarg(int *) anamelen;
92 	} */
93 	int error;
94 
95 	if ((error = sys_accept(l, (const void *)uap, retval)) != 0)
96 		return error;
97 
98 	if (SCARG(uap, name)
99 	    && (error = compat_43_sa_put(SCARG(uap, name))))
100 		return (error);
101 
102 	return 0;
103 }
104 
105 int
106 compat_43_sys_getpeername(struct lwp *l, const struct compat_43_sys_getpeername_args *uap, register_t *retval)
107 {
108 	/* {
109 		syscallarg(int) fdes;
110 		syscallarg(void *) asa;
111 		syscallarg(int *) alen;
112 	} */
113 
114 	int error;
115 
116 	if ((error = sys_getpeername(l, (const void *)uap, retval)) != 0)
117 		return error;
118 
119 	if ((error = compat_43_sa_put(SCARG(uap, asa))))
120 		return (error);
121 
122 	return 0;
123 }
124 
125 int
126 compat_43_sys_getsockname(struct lwp *l, const struct compat_43_sys_getsockname_args *uap, register_t *retval)
127 {
128 	/* {
129 		syscallarg(int) fdes;
130 		syscallarg(void *) asa;
131 		syscallarg(int *) alen;
132 	} */
133 	int error;
134 
135 	if ((error = sys_getsockname(l, (const void *)uap, retval)) != 0)
136 		return error;
137 
138 	if ((error = compat_43_sa_put(SCARG(uap, asa))))
139 		return (error);
140 
141 	return 0;
142 }
143 
144 int
145 compat_43_sys_recv(struct lwp *l, const struct compat_43_sys_recv_args *uap, register_t *retval)
146 {
147 	/* {
148 		syscallarg(int) s;
149 		syscallarg(void *) buf;
150 		syscallarg(int) len;
151 		syscallarg(int) flags;
152 	} */
153 	struct sys_recvfrom_args bra;
154 
155 	SCARG(&bra, s) = SCARG(uap, s);
156 	SCARG(&bra, buf) = SCARG(uap, buf);
157 	SCARG(&bra, len) = (size_t) SCARG(uap, len);
158 	SCARG(&bra, flags) = SCARG(uap, flags);
159 	SCARG(&bra, from) = NULL;
160 	SCARG(&bra, fromlenaddr) = NULL;
161 
162 	return (sys_recvfrom(l, &bra, retval));
163 }
164 
165 int
166 compat_43_sys_recvfrom(struct lwp *l, const struct compat_43_sys_recvfrom_args *uap, register_t *retval)
167 {
168 	/* {
169 		syscallarg(int) s;
170 		syscallarg(void *) buf;
171 		syscallarg(size_t) len;
172 		syscallarg(int) flags;
173 		syscallarg(void *) from;
174 		syscallarg(int *) fromlenaddr;
175 	} */
176 	int error;
177 
178 	if ((error = sys_recvfrom(l, (const void *)uap, retval)))
179 		return (error);
180 
181 	if (SCARG(uap, from) && (error = compat_43_sa_put(SCARG(uap, from))))
182 		return (error);
183 
184 	return (0);
185 }
186 
187 /*
188  * Old recvmsg. Arrange necessary structures, calls generic code and
189  * adjusts results accordingly.
190  */
191 int
192 compat_43_sys_recvmsg(struct lwp *l, const struct compat_43_sys_recvmsg_args *uap, register_t *retval)
193 {
194 	/* {
195 		syscallarg(int) s;
196 		syscallarg(struct omsghdr *) msg;
197 		syscallarg(int) flags;
198 	} */
199 	struct omsghdr omsg;
200 	struct msghdr msg;
201 	struct mbuf *from, *control;
202 	int error;
203 
204 	error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr));
205 	if (error)
206 		return (error);
207 
208 	if (omsg.msg_accrights == NULL)
209 		omsg.msg_accrightslen = 0;
210 	/* it was this way in 4.4BSD */
211 	if (omsg.msg_accrightslen > MLEN)
212 		return EINVAL;
213 
214 	msg.msg_name	= omsg.msg_name;
215 	msg.msg_namelen = omsg.msg_namelen;
216 	msg.msg_iovlen	= omsg.msg_iovlen;
217 	msg.msg_iov	= omsg.msg_iov;
218 	msg.msg_flags	= (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
219 
220 	error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
221 	    omsg.msg_accrights != NULL ? &control : NULL, retval);
222 	if (error != 0)
223 		return error;
224 
225 	/*
226 	 * If there is any control information and it's SCM_RIGHTS,
227 	 * pass it back to the program.
228 	 * XXX: maybe there can be more than one chunk of control data?
229 	 */
230 	if (omsg.msg_accrights && control != NULL) {
231 		struct cmsghdr *cmsg = mtod(control, void *);
232 
233 		if (cmsg->cmsg_level == SOL_SOCKET
234 		    && cmsg->cmsg_type == SCM_RIGHTS
235 		    && cmsg->cmsg_len < omsg.msg_accrightslen
236 		    && copyout(CMSG_DATA(cmsg), omsg.msg_accrights,
237 			    cmsg->cmsg_len) == 0) {
238 			omsg.msg_accrightslen = cmsg->cmsg_len;
239 			free_control_mbuf(l, control, control->m_next);
240 		} else {
241 			omsg.msg_accrightslen = 0;
242 			free_control_mbuf(l, control, control);
243 		}
244 	} else
245 		omsg.msg_accrightslen = 0;
246 
247 	if (from != NULL)
248 		/* convert from sockaddr sa_family to osockaddr one here */
249 		mtod(from, struct osockaddr *)->sa_family =
250 				    mtod(from, struct sockaddr *)->sa_family;
251 
252 	error = copyout_sockname(omsg.msg_name, &omsg.msg_namelen, 0, from);
253 	if (from != NULL)
254 		m_free(from);
255 
256 	if (error != 0)
257 		 error = copyout(&omsg, SCARG(uap, msg), sizeof(omsg));
258 
259 	return error;
260 }
261 
262 int
263 compat_43_sys_send(struct lwp *l, const struct compat_43_sys_send_args *uap, register_t *retval)
264 {
265 	/* {
266 		syscallarg(int) s;
267 		syscallarg(void *) buf;
268 		syscallarg(int) len;
269 		syscallarg(int) flags;
270 	} */
271 	struct sys_sendto_args bsa;
272 
273 	SCARG(&bsa, s)		= SCARG(uap, s);
274 	SCARG(&bsa, buf)	= SCARG(uap, buf);
275 	SCARG(&bsa, len)	= SCARG(uap, len);
276 	SCARG(&bsa, flags)	= SCARG(uap, flags);
277 	SCARG(&bsa, to)		= NULL;
278 	SCARG(&bsa, tolen)	= 0;
279 
280 	return (sys_sendto(l, &bsa, retval));
281 }
282 
283 int
284 compat43_set_accrights(struct msghdr *msg, void *accrights, int accrightslen)
285 {
286 	struct cmsghdr *cmsg;
287 	int error;
288 	struct mbuf *ctl;
289 	u_int clen;
290 
291 	if (accrights == NULL || accrightslen == 0) {
292 		msg->msg_control = NULL;
293 		msg->msg_controllen = 0;
294 		return 0;
295 	}
296 
297 	clen = CMSG_SPACE(accrightslen);
298 	/* it was (almost) this way in 4.4BSD */
299 	if (accrightslen < 0 || clen > MLEN)
300 		return EINVAL;
301 
302 	ctl = m_get(M_WAIT, MT_CONTROL);
303 	ctl->m_len = clen;
304 	cmsg = mtod(ctl, void *);
305 	cmsg->cmsg_len		= CMSG_SPACE(accrightslen);
306 	cmsg->cmsg_level	= SOL_SOCKET;
307 	cmsg->cmsg_type 	= SCM_RIGHTS;
308 
309 	error = copyin(accrights, CMSG_DATA(cmsg), accrightslen);
310 	if (error) {
311 		m_free(ctl);
312 		return error;
313 	}
314 
315 	msg->msg_control = ctl;
316 	msg->msg_controllen = clen;
317 	msg->msg_flags |= MSG_CONTROLMBUF;
318 	return 0;
319 }
320 
321 /*
322  * Old sendmsg. Arrange necessary structures, call generic code and
323  * adjust the results accordingly for old code.
324  */
325 int
326 compat_43_sys_sendmsg(struct lwp *l, const struct compat_43_sys_sendmsg_args *uap, register_t *retval)
327 {
328 	/* {
329 		syscallarg(int) s;
330 		syscallarg(void *) msg;
331 		syscallarg(int) flags;
332 	} */
333 	struct omsghdr omsg;
334 	struct msghdr msg;
335 	int error;
336 	struct mbuf *nam;
337 	struct osockaddr *osa;
338 	struct sockaddr *sa;
339 
340 	error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr));
341 	if (error != 0)
342 		return (error);
343 
344 	msg.msg_iovlen = omsg.msg_iovlen;
345 	msg.msg_iov = omsg.msg_iov;
346 
347 	error = sockargs(&nam, omsg.msg_name, omsg.msg_namelen, MT_SONAME);
348 	if (error != 0)
349 		return (error);
350 
351 	sa = mtod(nam, void *);
352 	osa = mtod(nam, void *);
353 	sa->sa_family = osa->sa_family;
354 	sa->sa_len = omsg.msg_namelen;
355 
356 	msg.msg_flags = MSG_IOVUSRSPACE | MSG_NAMEMBUF;
357 
358 	msg.msg_name = nam;
359 	msg.msg_namelen = omsg.msg_namelen;
360 	error = compat43_set_accrights(&msg, omsg.msg_accrights,
361 	    omsg.msg_accrightslen);
362 	if (error != 0)
363 		goto bad;
364 
365 	return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
366 
367     bad:
368 	if (nam != NULL)
369 		m_free(nam);
370 
371 	return (error);
372 }
373 
374 static int
375 compat_43_sa_put(void *from)
376 {
377 	struct osockaddr *osa = (struct osockaddr *) from;
378 	struct sockaddr sa;
379 	struct osockaddr *kosa;
380 	int error, len;
381 
382 	/*
383 	 * Only read/write the sockaddr family and length, the rest is
384 	 * not changed.
385 	 */
386 	len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
387 
388 	error = copyin((void *) osa, (void *) &sa, len);
389 	if (error)
390 		return (error);
391 
392 	/* Note: we convert from sockaddr sa_family to osockaddr one here */
393 	kosa = (struct osockaddr *) &sa;
394 	kosa->sa_family = sa.sa_family;
395 	error = copyout(kosa, osa, len);
396 	if (error)
397 		return (error);
398 
399 	return (0);
400 }
401