2 * 43BSD_SOCKET.C - 4.3BSD compatibility socket syscalls
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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * $DragonFly: src/sys/emulation/43bsd/43bsd_socket.c,v 1.7 2006/06/05 07:26:07 dillon Exp $
36 * from: DragonFly kern/uipc_syscalls.c,v 1.13
38 * The original versions of these syscalls used to live in
39 * kern/uipc_syscalls.c. These are heavily modified to use the
43 #include "opt_compat.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/sysproto.h>
49 #include <sys/kern_syscall.h>
50 #include <sys/malloc.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
57 #include "43bsd_socket.h"
60 * System call interface to the socket abstraction.
64 compat_43_getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
70 if (len > SOCK_MAXADDRLEN)
72 if (len < offsetof(struct sockaddr, sa_data[0]))
74 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
75 error = copyin(uaddr, sa, len);
80 * Convert to the 4.4BSD sockaddr structure.
82 sa->sa_family = sa->sa_len;
90 compat_43_copyout_sockaddr(struct sockaddr *sa, caddr_t uaddr, int sa_len)
94 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
95 error = copyout(sa, uaddr, sa_len);
101 sys_oaccept(struct accept_args *uap)
103 struct sockaddr *sa = NULL;
108 error = copyin(uap->anamelen, &sa_len, sizeof(sa_len));
112 error = kern_accept(uap->s, &sa, &sa_len, &uap->sysmsg_result);
116 * return a namelen of zero for older code which
117 * might ignore the return value from accept.
120 copyout(&sa_len, uap->anamelen, sizeof(*uap->anamelen));
122 compat_43_copyout_sockaddr(sa, uap->name, sa_len);
124 error = copyout(&sa_len, uap->anamelen,
125 sizeof(*uap->anamelen));
131 error = kern_accept(uap->s, NULL, 0, &uap->sysmsg_result);
137 sys_ogetsockname(struct getsockname_args *uap)
139 struct sockaddr *sa = NULL;
142 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
146 error = kern_getsockname(uap->fdes, &sa, &sa_len);
149 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
151 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
159 sys_ogetpeername(struct ogetpeername_args *uap)
161 struct sockaddr *sa = NULL;
164 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
168 error = kern_getpeername(uap->fdes, &sa, &sa_len);
171 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
174 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
181 sys_osend(struct osend_args *uap)
183 struct thread *td = curthread;
188 aiov.iov_base = uap->buf;
189 aiov.iov_len = uap->len;
190 auio.uio_iov = &aiov;
193 auio.uio_resid = uap->len;
194 auio.uio_segflg = UIO_USERSPACE;
195 auio.uio_rw = UIO_WRITE;
198 error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags,
199 &uap->sysmsg_result);
205 sys_osendmsg(struct osendmsg_args *uap)
207 struct thread *td = curthread;
210 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
211 struct sockaddr *sa = NULL;
212 struct mbuf *control = NULL;
216 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
221 * Conditionally copyin msg.msg_name.
224 error = compat_43_getsockaddr(&sa, msg.msg_name,
233 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
238 auio.uio_iovcnt = msg.msg_iovlen;
240 auio.uio_segflg = UIO_USERSPACE;
241 auio.uio_rw = UIO_WRITE;
245 * Conditionally copyin msg.msg_control.
247 if (msg.msg_control) {
248 if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) {
252 control = m_get(MB_WAIT, MT_CONTROL);
253 if (control == NULL) {
257 control->m_len = msg.msg_controllen;
258 error = copyin(msg.msg_control, mtod(control, caddr_t),
265 * In 4.3BSD, the only type of ancillary data was
266 * access rights and this data did not use a header
267 * to identify it's type. Thus, we must prepend the
268 * control data with the proper cmsghdr structure
269 * so that the kernel recognizes it as access rights.
271 M_PREPEND(control, sizeof(*cm), MB_WAIT);
272 if (control == NULL) {
276 cm = mtod(control, struct cmsghdr *);
277 cm->cmsg_len = control->m_len;
278 cm->cmsg_level = SOL_SOCKET;
279 cm->cmsg_type = SCM_RIGHTS;
283 error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags,
284 &uap->sysmsg_result);
289 iovec_free(&iov, aiov);
294 sys_orecv(struct orecv_args *uap)
296 struct thread *td = curthread;
301 aiov.iov_base = uap->buf;
302 aiov.iov_len = uap->len;
303 auio.uio_iov = &aiov;
306 auio.uio_resid = uap->len;
307 auio.uio_segflg = UIO_USERSPACE;
308 auio.uio_rw = UIO_READ;
311 error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags,
312 &uap->sysmsg_result);
318 sys_orecvfrom(struct recvfrom_args *uap)
320 struct thread *td = curthread;
323 struct sockaddr *sa = NULL;
326 if (uap->from && uap->fromlenaddr) {
327 error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen));
335 aiov.iov_base = uap->buf;
336 aiov.iov_len = uap->len;
337 auio.uio_iov = &aiov;
340 auio.uio_resid = uap->len;
341 auio.uio_segflg = UIO_USERSPACE;
342 auio.uio_rw = UIO_READ;
345 error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL,
346 &uap->flags, &uap->sysmsg_result);
348 if (error == 0 && uap->from) {
349 fromlen = MIN(fromlen, sa->sa_len);
350 error = compat_43_copyout_sockaddr(sa, uap->from, fromlen);
353 * Old recvfrom didn't signal an error if this
354 * next copyout failed.
356 copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen));
365 sys_orecvmsg(struct orecvmsg_args *uap)
367 struct thread *td = curthread;
370 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
371 struct mbuf *m, *control = NULL;
372 struct sockaddr *sa = NULL;
374 socklen_t *ufromlenp, *ucontrollenp;
375 int error, fromlen, controllen, len, flags, *uflagsp;
378 * This copyin handles everything except the iovec.
380 error = copyin(uap->msg, &msg, sizeof(struct omsghdr));
384 if (msg.msg_name && msg.msg_namelen < 0)
386 if (msg.msg_control && msg.msg_controllen < 0)
389 ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
391 ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
393 uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr,
399 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
404 auio.uio_iovcnt = msg.msg_iovlen;
406 auio.uio_segflg = UIO_USERSPACE;
407 auio.uio_rw = UIO_READ;
410 flags = msg.msg_flags;
412 error = kern_recvmsg(uap->s, msg.msg_name ? &sa : NULL, &auio,
413 msg.msg_control ? &control : NULL, &flags, &uap->sysmsg_result);
416 * Copyout msg.msg_name and msg.msg_namelen.
418 if (error == 0 && msg.msg_name) {
419 fromlen = MIN(msg.msg_namelen, sa->sa_len);
420 error = compat_43_copyout_sockaddr(sa, msg.msg_name, fromlen);
423 * Old recvfrom didn't signal an error if this
424 * next copyout failed.
426 copyout(&fromlen, ufromlenp, sizeof(*ufromlenp));
430 * Copyout msg.msg_control and msg.msg_controllen.
432 if (error == 0 && msg.msg_control) {
434 * If we receive access rights, trim the cmsghdr; anything
437 if (mtod((struct mbuf *)msg.msg_control,
438 struct cmsghdr *)->cmsg_level != SOL_SOCKET ||
439 mtod((struct mbuf *)msg.msg_control,
440 struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
442 error = copyout(&temp, ucontrollenp,
443 sizeof(*ucontrollenp));
446 ((struct mbuf *)msg.msg_control)->m_len -=
447 sizeof(struct cmsghdr);
448 ((struct mbuf *)msg.msg_control)->m_data +=
449 sizeof(struct cmsghdr);
451 len = msg.msg_controllen;
453 ctlbuf = (caddr_t)msg.msg_control;
455 while(m && len > 0) {
458 if (len >= m->m_len) {
461 msg.msg_flags |= MSG_CTRUNC;
465 error = copyout(mtod(m, caddr_t), ctlbuf,
474 controllen = ctlbuf - (caddr_t)msg.msg_control;
475 error = copyout(&controllen, ucontrollenp,
476 sizeof(*ucontrollenp));
480 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
485 iovec_free(&iov, aiov);