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. 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 * The original versions of these syscalls used to live in
32 * kern/uipc_syscalls.c. These are heavily modified to use the
36 #include "opt_compat.h"
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/sysproto.h>
42 #include <sys/kern_syscall.h>
43 #include <sys/malloc.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
50 #include <sys/mplock2.h>
52 #include "43bsd_socket.h"
55 * System call interface to the socket abstraction.
59 compat_43_getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
65 if (len > SOCK_MAXADDRLEN)
67 if (len < offsetof(struct sockaddr, sa_data[0]))
69 sa = kmalloc(len, M_SONAME, M_WAITOK);
70 error = copyin(uaddr, sa, len);
75 * Convert to the 4.4BSD sockaddr structure.
77 sa->sa_family = sa->sa_len;
85 compat_43_copyout_sockaddr(struct sockaddr *sa, caddr_t uaddr, int sa_len)
89 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
90 error = copyout(sa, uaddr, sa_len);
99 sys_oaccept(struct accept_args *uap)
101 struct sockaddr *sa = NULL;
106 error = copyin(uap->anamelen, &sa_len, sizeof(sa_len));
111 error = kern_accept(uap->s, 0, &sa, &sa_len,
112 &uap->sysmsg_iresult, 0);
117 * return a namelen of zero for older code which
118 * might ignore the return value from accept.
121 copyout(&sa_len, uap->anamelen, sizeof(*uap->anamelen));
123 compat_43_copyout_sockaddr(sa, uap->name, sa_len);
125 error = copyout(&sa_len, uap->anamelen,
126 sizeof(*uap->anamelen));
133 error = kern_accept(uap->s, 0, NULL, 0, &uap->sysmsg_iresult, 0);
143 sys_ogetsockname(struct getsockname_args *uap)
145 struct sockaddr *sa = NULL;
148 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
153 error = kern_getsockname(uap->fdes, &sa, &sa_len);
157 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
159 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
170 sys_ogetpeername(struct ogetpeername_args *uap)
172 struct sockaddr *sa = NULL;
175 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
180 error = kern_getpeername(uap->fdes, &sa, &sa_len);
184 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
187 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
197 sys_osend(struct osend_args *uap)
199 struct thread *td = curthread;
204 aiov.iov_base = uap->buf;
205 aiov.iov_len = uap->len;
206 auio.uio_iov = &aiov;
209 auio.uio_resid = uap->len;
210 auio.uio_segflg = UIO_USERSPACE;
211 auio.uio_rw = UIO_WRITE;
215 error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags,
216 &uap->sysmsg_szresult);
226 sys_osendmsg(struct osendmsg_args *uap)
228 struct thread *td = curthread;
231 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
232 struct sockaddr *sa = NULL;
233 struct mbuf *control = NULL;
237 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
242 * Conditionally copyin msg.msg_name.
245 error = compat_43_getsockaddr(&sa, msg.msg_name,
254 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
259 auio.uio_iovcnt = msg.msg_iovlen;
261 auio.uio_segflg = UIO_USERSPACE;
262 auio.uio_rw = UIO_WRITE;
266 * Conditionally copyin msg.msg_control.
268 if (msg.msg_control) {
269 if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) {
273 control = m_get(M_WAITOK, MT_CONTROL);
274 if (control == NULL) {
278 control->m_len = msg.msg_controllen;
279 error = copyin(msg.msg_control, mtod(control, caddr_t),
286 * In 4.3BSD, the only type of ancillary data was
287 * access rights and this data did not use a header
288 * to identify it's type. Thus, we must prepend the
289 * control data with the proper cmsghdr structure
290 * so that the kernel recognizes it as access rights.
292 M_PREPEND(control, sizeof(*cm), M_WAITOK);
293 if (control == NULL) {
297 cm = mtod(control, struct cmsghdr *);
298 cm->cmsg_len = control->m_len;
299 cm->cmsg_level = SOL_SOCKET;
300 cm->cmsg_type = SCM_RIGHTS;
305 error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags,
306 &uap->sysmsg_szresult);
310 iovec_free(&iov, aiov);
321 sys_orecv(struct orecv_args *uap)
323 struct thread *td = curthread;
328 aiov.iov_base = uap->buf;
329 aiov.iov_len = uap->len;
330 auio.uio_iov = &aiov;
333 auio.uio_resid = uap->len;
334 auio.uio_segflg = UIO_USERSPACE;
335 auio.uio_rw = UIO_READ;
339 error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags,
340 &uap->sysmsg_szresult);
350 sys_orecvfrom(struct recvfrom_args *uap)
352 struct thread *td = curthread;
355 struct sockaddr *sa = NULL;
358 if (uap->from && uap->fromlenaddr) {
359 error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen));
367 aiov.iov_base = uap->buf;
368 aiov.iov_len = uap->len;
369 auio.uio_iov = &aiov;
372 auio.uio_resid = uap->len;
373 auio.uio_segflg = UIO_USERSPACE;
374 auio.uio_rw = UIO_READ;
378 error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL,
379 &uap->flags, &uap->sysmsg_szresult);
382 if (error == 0 && uap->from) {
384 fromlen = MIN(fromlen, sa->sa_len);
385 error = compat_43_copyout_sockaddr(sa, uap->from,
391 * Old recvfrom didn't signal an error if this
392 * next copyout failed.
394 copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen));
406 sys_orecvmsg(struct orecvmsg_args *uap)
408 struct thread *td = curthread;
411 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
412 struct mbuf *m, *control = NULL;
413 struct sockaddr *sa = NULL;
415 socklen_t *ufromlenp, *ucontrollenp;
416 int error, fromlen, controllen, len, flags, *uflagsp;
419 * This copyin handles everything except the iovec.
421 error = copyin(uap->msg, &msg, sizeof(struct omsghdr));
425 if (msg.msg_name && msg.msg_namelen < 0)
427 if (msg.msg_control && msg.msg_controllen < 0)
430 ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
432 ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
434 uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr,
440 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
445 auio.uio_iovcnt = msg.msg_iovlen;
447 auio.uio_segflg = UIO_USERSPACE;
448 auio.uio_rw = UIO_READ;
451 flags = msg.msg_flags;
454 error = kern_recvmsg(uap->s, (msg.msg_name ? &sa : NULL), &auio,
455 (msg.msg_control ? &control : NULL), &flags,
456 &uap->sysmsg_szresult);
460 * Copyout msg.msg_name and msg.msg_namelen.
462 if (error == 0 && msg.msg_name) {
464 fromlen = MIN(msg.msg_namelen, sa->sa_len);
465 error = compat_43_copyout_sockaddr(sa, msg.msg_name,
471 * Old recvfrom didn't signal an error if this
472 * next copyout failed.
474 copyout(&fromlen, ufromlenp, sizeof(*ufromlenp));
478 * Copyout msg.msg_control and msg.msg_controllen.
480 if (error == 0 && msg.msg_control) {
482 * If we receive access rights, trim the cmsghdr; anything
485 if (mtod((struct mbuf *)msg.msg_control,
486 struct cmsghdr *)->cmsg_level != SOL_SOCKET ||
487 mtod((struct mbuf *)msg.msg_control,
488 struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
490 error = copyout(&temp, ucontrollenp,
491 sizeof(*ucontrollenp));
494 ((struct mbuf *)msg.msg_control)->m_len -=
495 sizeof(struct cmsghdr);
496 ((struct mbuf *)msg.msg_control)->m_data +=
497 sizeof(struct cmsghdr);
499 len = msg.msg_controllen;
501 ctlbuf = (caddr_t)msg.msg_control;
503 while(m && len > 0) {
506 if (len >= m->m_len) {
509 msg.msg_flags |= MSG_CTRUNC;
513 error = copyout(mtod(m, caddr_t), ctlbuf,
522 controllen = ctlbuf - (caddr_t)msg.msg_control;
523 error = copyout(&controllen, ucontrollenp,
524 sizeof(*ucontrollenp));
528 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
533 iovec_free(&iov, aiov);