1 /* $NetBSD: uipc_syscalls_43.c,v 1.43 2008/04/29 19:02:14 ad Exp $ */
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
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
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>
43 #include <sys/socket.h>
44 #include <sys/socketvar.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>
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
80 * connect(2), bind(2), sendto(2)
83 static int compat_43_sa_put(void *);
86 compat_43_sys_accept(struct lwp
*l
, const struct compat_43_sys_accept_args
*uap
, register_t
*retval
)
90 syscallarg(void *) name;
91 syscallarg(int *) anamelen;
95 if ((error
= sys_accept(l
, (const void *)uap
, retval
)) != 0)
99 && (error
= compat_43_sa_put(SCARG(uap
, name
))))
106 compat_43_sys_getpeername(struct lwp
*l
, const struct compat_43_sys_getpeername_args
*uap
, register_t
*retval
)
109 syscallarg(int) fdes;
110 syscallarg(void *) asa;
111 syscallarg(int *) alen;
116 if ((error
= sys_getpeername(l
, (const void *)uap
, retval
)) != 0)
119 if ((error
= compat_43_sa_put(SCARG(uap
, asa
))))
126 compat_43_sys_getsockname(struct lwp
*l
, const struct compat_43_sys_getsockname_args
*uap
, register_t
*retval
)
129 syscallarg(int) fdes;
130 syscallarg(void *) asa;
131 syscallarg(int *) alen;
135 if ((error
= sys_getsockname(l
, (const void *)uap
, retval
)) != 0)
138 if ((error
= compat_43_sa_put(SCARG(uap
, asa
))))
145 compat_43_sys_recv(struct lwp
*l
, const struct compat_43_sys_recv_args
*uap
, register_t
*retval
)
149 syscallarg(void *) buf;
151 syscallarg(int) flags;
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
)
170 syscallarg(void *) buf;
171 syscallarg(size_t) len;
172 syscallarg(int) flags;
173 syscallarg(void *) from;
174 syscallarg(int *) fromlenaddr;
178 if ((error
= sys_recvfrom(l
, (const void *)uap
, retval
)))
181 if (SCARG(uap
, from
) && (error
= compat_43_sa_put(SCARG(uap
, from
))))
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
)
196 syscallarg(struct omsghdr *) msg;
197 syscallarg(int) flags;
201 struct mbuf
*from
, *control
;
204 error
= copyin(SCARG(uap
, msg
), &omsg
, sizeof (struct omsghdr
));
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
)
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
);
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
);
241 omsg
.msg_accrightslen
= 0;
242 free_control_mbuf(l
, control
, control
);
245 omsg
.msg_accrightslen
= 0;
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
);
257 error
= copyout(&omsg
, SCARG(uap
, msg
), sizeof(omsg
));
263 compat_43_sys_send(struct lwp
*l
, const struct compat_43_sys_send_args
*uap
, register_t
*retval
)
267 syscallarg(void *) buf;
269 syscallarg(int) flags;
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
;
291 if (accrights
== NULL
|| accrightslen
== 0) {
292 msg
->msg_control
= NULL
;
293 msg
->msg_controllen
= 0;
297 clen
= CMSG_SPACE(accrightslen
);
298 /* it was (almost) this way in 4.4BSD */
299 if (accrightslen
< 0 || clen
> MLEN
)
302 ctl
= m_get(M_WAIT
, MT_CONTROL
);
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
);
315 msg
->msg_control
= ctl
;
316 msg
->msg_controllen
= clen
;
317 msg
->msg_flags
|= MSG_CONTROLMBUF
;
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
)
330 syscallarg(void *) msg;
331 syscallarg(int) flags;
337 struct osockaddr
*osa
;
340 error
= copyin(SCARG(uap
, msg
), &omsg
, sizeof (struct omsghdr
));
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
);
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
;
359 msg
.msg_namelen
= omsg
.msg_namelen
;
360 error
= compat43_set_accrights(&msg
, omsg
.msg_accrights
,
361 omsg
.msg_accrightslen
);
365 return do_sys_sendmsg(l
, SCARG(uap
, s
), &msg
, SCARG(uap
, flags
), retval
);
375 compat_43_sa_put(void *from
)
377 struct osockaddr
*osa
= (struct osockaddr
*) from
;
379 struct osockaddr
*kosa
;
383 * Only read/write the sockaddr family and length, the rest is
386 len
= sizeof(sa
.sa_len
) + sizeof(sa
.sa_family
);
388 error
= copyin((void *) osa
, (void *) &sa
, len
);
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
);