No empty .Rs/.Re
[netbsd-mini2440.git] / sys / compat / common / uipc_syscalls_43.c
blob089289276483785cf6e7fb218356686e27538a98
1 /* $NetBSD: uipc_syscalls_43.c,v 1.43 2008/04/29 19:02:14 ad Exp $ */
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
31 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_43.c,v 1.43 2008/04/29 19:02:14 ad Exp $");
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>
55 #include <sys/mount.h>
56 #include <sys/syscallargs.h>
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>
73 #include <compat/common/compat_util.h>
75 #include <uvm/uvm_extern.h>
78 * Following 4.3 syscalls were not versioned, even through they should
79 * have been:
80 * connect(2), bind(2), sendto(2)
83 static int compat_43_sa_put(void *);
85 int
86 compat_43_sys_accept(struct lwp *l, const struct compat_43_sys_accept_args *uap, register_t *retval)
88 /* {
89 syscallarg(int) s;
90 syscallarg(void *) name;
91 syscallarg(int *) anamelen;
92 } */
93 int error;
95 if ((error = sys_accept(l, (const void *)uap, retval)) != 0)
96 return error;
98 if (SCARG(uap, name)
99 && (error = compat_43_sa_put(SCARG(uap, name))))
100 return (error);
102 return 0;
106 compat_43_sys_getpeername(struct lwp *l, const struct compat_43_sys_getpeername_args *uap, register_t *retval)
108 /* {
109 syscallarg(int) fdes;
110 syscallarg(void *) asa;
111 syscallarg(int *) alen;
112 } */
114 int error;
116 if ((error = sys_getpeername(l, (const void *)uap, retval)) != 0)
117 return error;
119 if ((error = compat_43_sa_put(SCARG(uap, asa))))
120 return (error);
122 return 0;
126 compat_43_sys_getsockname(struct lwp *l, const struct compat_43_sys_getsockname_args *uap, register_t *retval)
128 /* {
129 syscallarg(int) fdes;
130 syscallarg(void *) asa;
131 syscallarg(int *) alen;
132 } */
133 int error;
135 if ((error = sys_getsockname(l, (const void *)uap, retval)) != 0)
136 return error;
138 if ((error = compat_43_sa_put(SCARG(uap, asa))))
139 return (error);
141 return 0;
145 compat_43_sys_recv(struct lwp *l, const struct compat_43_sys_recv_args *uap, register_t *retval)
147 /* {
148 syscallarg(int) s;
149 syscallarg(void *) buf;
150 syscallarg(int) len;
151 syscallarg(int) flags;
152 } */
153 struct sys_recvfrom_args bra;
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;
162 return (sys_recvfrom(l, &bra, retval));
166 compat_43_sys_recvfrom(struct lwp *l, const struct compat_43_sys_recvfrom_args *uap, register_t *retval)
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;
178 if ((error = sys_recvfrom(l, (const void *)uap, retval)))
179 return (error);
181 if (SCARG(uap, from) && (error = compat_43_sa_put(SCARG(uap, from))))
182 return (error);
184 return (0);
188 * Old recvmsg. Arrange necessary structures, calls generic code and
189 * adjusts results accordingly.
192 compat_43_sys_recvmsg(struct lwp *l, const struct compat_43_sys_recvmsg_args *uap, register_t *retval)
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;
204 error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr));
205 if (error)
206 return (error);
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;
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;
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;
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?
230 if (omsg.msg_accrights && control != NULL) {
231 struct cmsghdr *cmsg = mtod(control, void *);
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);
244 } else
245 omsg.msg_accrightslen = 0;
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;
252 error = copyout_sockname(omsg.msg_name, &omsg.msg_namelen, 0, from);
253 if (from != NULL)
254 m_free(from);
256 if (error != 0)
257 error = copyout(&omsg, SCARG(uap, msg), sizeof(omsg));
259 return error;
263 compat_43_sys_send(struct lwp *l, const struct compat_43_sys_send_args *uap, register_t *retval)
265 /* {
266 syscallarg(int) s;
267 syscallarg(void *) buf;
268 syscallarg(int) len;
269 syscallarg(int) flags;
270 } */
271 struct sys_sendto_args bsa;
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;
280 return (sys_sendto(l, &bsa, retval));
284 compat43_set_accrights(struct msghdr *msg, void *accrights, int accrightslen)
286 struct cmsghdr *cmsg;
287 int error;
288 struct mbuf *ctl;
289 u_int clen;
291 if (accrights == NULL || accrightslen == 0) {
292 msg->msg_control = NULL;
293 msg->msg_controllen = 0;
294 return 0;
297 clen = CMSG_SPACE(accrightslen);
298 /* it was (almost) this way in 4.4BSD */
299 if (accrightslen < 0 || clen > MLEN)
300 return EINVAL;
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;
309 error = copyin(accrights, CMSG_DATA(cmsg), accrightslen);
310 if (error) {
311 m_free(ctl);
312 return error;
315 msg->msg_control = ctl;
316 msg->msg_controllen = clen;
317 msg->msg_flags |= MSG_CONTROLMBUF;
318 return 0;
322 * Old sendmsg. Arrange necessary structures, call generic code and
323 * adjust the results accordingly for old code.
326 compat_43_sys_sendmsg(struct lwp *l, const struct compat_43_sys_sendmsg_args *uap, register_t *retval)
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;
340 error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr));
341 if (error != 0)
342 return (error);
344 msg.msg_iovlen = omsg.msg_iovlen;
345 msg.msg_iov = omsg.msg_iov;
347 error = sockargs(&nam, omsg.msg_name, omsg.msg_namelen, MT_SONAME);
348 if (error != 0)
349 return (error);
351 sa = mtod(nam, void *);
352 osa = mtod(nam, void *);
353 sa->sa_family = osa->sa_family;
354 sa->sa_len = omsg.msg_namelen;
356 msg.msg_flags = MSG_IOVUSRSPACE | MSG_NAMEMBUF;
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;
365 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
367 bad:
368 if (nam != NULL)
369 m_free(nam);
371 return (error);
374 static int
375 compat_43_sa_put(void *from)
377 struct osockaddr *osa = (struct osockaddr *) from;
378 struct sockaddr sa;
379 struct osockaddr *kosa;
380 int error, len;
383 * Only read/write the sockaddr family and length, the rest is
384 * not changed.
386 len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
388 error = copyin((void *) osa, (void *) &sa, len);
389 if (error)
390 return (error);
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);
399 return (0);