source: rtems-libbsd/freebsd/sys/kern/uipc_syscalls.c @ 9d9bfaf

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 9d9bfaf was 9d9bfaf, checked in by Sebastian Huber <sebastian.huber@…>, on 10/14/13 at 14:14:19

Use send/recv functions from FreeBSD

Use recvfrom(), recvmsg(), sendto() and sendmsg() from FreeBSD.

  • Property mode set to 100644
File size: 68.4 KB
Line 
1#include <machine/rtems-bsd-config.h>
2
3/*-
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * sendfile(2) and related extensions:
8 * Copyright (c) 1998, David Greenman. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *      @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD$");
39
40#include <rtems/bsd/local/opt_inet.h>
41#include <rtems/bsd/local/opt_inet6.h>
42#include <rtems/bsd/local/opt_sctp.h>
43#include <rtems/bsd/local/opt_compat.h>
44#include <rtems/bsd/local/opt_ktrace.h>
45
46#include <rtems/bsd/sys/param.h>
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <rtems/bsd/sys/lock.h>
50#include <sys/mutex.h>
51#include <sys/sysproto.h>
52#include <sys/malloc.h>
53#include <sys/filedesc.h>
54#include <sys/event.h>
55#include <sys/proc.h>
56#include <sys/fcntl.h>
57#include <sys/file.h>
58#include <sys/filio.h>
59#include <sys/jail.h>
60#include <sys/mount.h>
61#include <sys/mbuf.h>
62#include <sys/protosw.h>
63#include <sys/sf_buf.h>
64#include <sys/sysent.h>
65#include <sys/socket.h>
66#include <sys/socketvar.h>
67#include <sys/signalvar.h>
68#include <sys/syscallsubr.h>
69#include <sys/sysctl.h>
70#include <sys/uio.h>
71#include <sys/vnode.h>
72#ifdef KTRACE
73#include <sys/ktrace.h>
74#endif
75#ifdef COMPAT_FREEBSD32
76#include <compat/freebsd32/freebsd32_util.h>
77#endif
78
79#include <net/vnet.h>
80
81#include <security/audit/audit.h>
82#include <security/mac/mac_framework.h>
83
84#include <vm/vm.h>
85#include <vm/vm_object.h>
86#include <vm/vm_page.h>
87#include <vm/vm_pageout.h>
88#include <vm/vm_kern.h>
89#include <vm/vm_extern.h>
90
91#if defined(INET) || defined(INET6)
92#ifdef SCTP
93#include <netinet/sctp.h>
94#include <netinet/sctp_peeloff.h>
95#endif /* SCTP */
96#endif /* INET || INET6 */
97#ifdef __rtems__
98#include <machine/rtems-bsd-syscall-api.h>
99#endif /* __rtems__ */
100
101static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
102static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
103
104#ifndef __rtems__
105static int accept1(struct thread *td, struct accept_args *uap, int compat);
106static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat);
107static int getsockname1(struct thread *td, struct getsockname_args *uap,
108                        int compat);
109static int getpeername1(struct thread *td, struct getpeername_args *uap,
110                        int compat);
111
112/*
113 * NSFBUFS-related variables and associated sysctls
114 */
115int nsfbufs;
116int nsfbufspeak;
117int nsfbufsused;
118
119SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0,
120    "Maximum number of sendfile(2) sf_bufs available");
121SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0,
122    "Number of sendfile(2) sf_bufs at peak usage");
123SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
124    "Number of sendfile(2) sf_bufs in use");
125
126/*
127 * Convert a user file descriptor to a kernel file entry.  A reference on the
128 * file entry is held upon returning.  This is lighter weight than
129 * fgetsock(), which bumps the socket reference drops the file reference
130 * count instead, as this approach avoids several additional mutex operations
131 * associated with the additional reference count.  If requested, return the
132 * open file flags.
133 */
134static int
135getsock(struct filedesc *fdp, int fd, struct file **fpp, u_int *fflagp)
136{
137        struct file *fp;
138        int error;
139
140        fp = NULL;
141        if (fdp == NULL || (fp = fget_unlocked(fdp, fd)) == NULL) {
142                error = EBADF;
143        } else if (fp->f_type != DTYPE_SOCKET) {
144                fdrop(fp, curthread);
145                fp = NULL;
146                error = ENOTSOCK;
147        } else {
148                if (fflagp != NULL)
149                        *fflagp = fp->f_flag;
150                error = 0;
151        }
152        *fpp = fp;
153        return (error);
154}
155#else /* __rtems__ */
156static int
157rtems_bsd_getsock(int fd, struct file **fpp, u_int *fflagp)
158{
159        struct file *fp;
160        int error;
161
162        if ((uint32_t) fd < rtems_libio_number_iops) {
163                fp = rtems_bsd_fd_to_fp(fd);
164                if ((fp->f_io.flags & LIBIO_FLAGS_OPEN) != LIBIO_FLAGS_OPEN) {
165                        fp = NULL;
166                        error = EBADF;
167                } else if (fp->f_io.pathinfo.handlers != &socketops) {
168                        fp = NULL;
169                        error = ENOTSOCK;
170                } else {
171                        if (fflagp != NULL) {
172                                *fflagp = rtems_bsd_libio_flags_to_fflag(
173                                    fp->f_io.flags);
174                        }
175
176                        error = 0;
177                }
178        } else {
179                fp = NULL;
180                error = EBADF;
181        }
182
183        *fpp = fp;
184
185        return (error);
186}
187
188#define getsock(fdp, fd, fpp, fflagp) rtems_bsd_getsock(fd, fpp, fflagp)
189#endif /* __rtems__ */
190
191/*
192 * System call interface to the socket abstraction.
193 */
194#if defined(COMPAT_43)
195#define COMPAT_OLDSOCK
196#endif
197
198#ifndef __rtems__
199int
200socket(td, uap)
201#else /* __rtems__ */
202static int
203rtems_bsd_socket(td, uap)
204#endif /* __rtems__ */
205        struct thread *td;
206        struct socket_args /* {
207                int     domain;
208                int     type;
209                int     protocol;
210        } */ *uap;
211{
212#ifndef __rtems__
213        struct filedesc *fdp;
214#endif /* __rtems__ */
215        struct socket *so;
216        struct file *fp;
217        int fd, error;
218
219        AUDIT_ARG_SOCKET(uap->domain, uap->type, uap->protocol);
220#ifdef MAC
221        error = mac_socket_check_create(td->td_ucred, uap->domain, uap->type,
222            uap->protocol);
223        if (error)
224                return (error);
225#endif
226#ifndef __rtems__
227        fdp = td->td_proc->p_fd;
228#endif /* __rtems__ */
229        error = falloc(td, &fp, &fd);
230        if (error)
231                return (error);
232        /* An extra reference on `fp' has been held for us by falloc(). */
233        error = socreate(uap->domain, &so, uap->type, uap->protocol,
234            td->td_ucred, td);
235        if (error) {
236                fdclose(fdp, fp, fd, td);
237        } else {
238                finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &socketops);
239                td->td_retval[0] = fd;
240        }
241        fdrop(fp, td);
242        return (error);
243}
244#ifdef __rtems__
245int
246socket(int domain, int type, int protocol)
247{
248        struct thread *td = rtems_bsd_get_curthread_or_null();
249        struct socket_args ua = {
250                .domain = domain,
251                .type = type,
252                .protocol = protocol
253        };
254        int error;
255
256        if (td != NULL) {
257                error = rtems_bsd_socket(td, &ua);
258        } else {
259                error = ENOMEM;
260        }
261
262        if (error == 0) {
263                return td->td_retval[0];
264        } else {
265                rtems_set_errno_and_return_minus_one(error);
266        }
267}
268#endif /* __rtems__ */
269
270#ifndef __rtems__
271/* ARGSUSED */
272int
273bind(td, uap)
274#else /* __rtems__ */
275static int kern_bind(struct thread *, int, struct sockaddr *);
276
277static int
278rtems_bsd_bind(td, uap)
279#endif /* __rtems__ */
280        struct thread *td;
281        struct bind_args /* {
282                int     s;
283                caddr_t name;
284                int     namelen;
285        } */ *uap;
286{
287        struct sockaddr *sa;
288        int error;
289
290        if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0)
291                return (error);
292
293        error = kern_bind(td, uap->s, sa);
294        free(sa, M_SONAME);
295        return (error);
296}
297#ifdef __rtems__
298int
299bind(int socket, const struct sockaddr *address, socklen_t address_len)
300{
301        struct thread *td = rtems_bsd_get_curthread_or_null();
302        struct bind_args ua = {
303                .s = socket,
304                .name = (caddr_t) address,
305                .namelen = address_len
306        };
307        int error;
308
309        if (td != NULL) {
310                error = rtems_bsd_bind(td, &ua);
311        } else {
312                error = ENOMEM;
313        }
314
315        return rtems_bsd_error_to_status_and_errno(error);
316}
317#endif /* __rtems__ */
318
319int
320kern_bind(td, fd, sa)
321        struct thread *td;
322        int fd;
323        struct sockaddr *sa;
324{
325        struct socket *so;
326        struct file *fp;
327        int error;
328
329        AUDIT_ARG_FD(fd);
330        error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
331        if (error)
332                return (error);
333        so = fp->f_data;
334#ifdef KTRACE
335        if (KTRPOINT(td, KTR_STRUCT))
336                ktrsockaddr(sa);
337#endif
338#ifdef MAC
339        error = mac_socket_check_bind(td->td_ucred, so, sa);
340        if (error == 0)
341#endif
342                error = sobind(so, sa, td);
343        fdrop(fp, td);
344        return (error);
345}
346
347/* ARGSUSED */
348#ifndef __rtems__
349int
350listen(td, uap)
351#else /* __rtems__ */
352static int
353rtems_bsd_listen(td, uap)
354#endif /* __rtems__ */
355        struct thread *td;
356        struct listen_args /* {
357                int     s;
358                int     backlog;
359        } */ *uap;
360{
361        struct socket *so;
362        struct file *fp;
363        int error;
364
365        AUDIT_ARG_FD(uap->s);
366        error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL);
367        if (error == 0) {
368                so = fp->f_data;
369#ifdef MAC
370                error = mac_socket_check_listen(td->td_ucred, so);
371                if (error == 0) {
372#endif
373                        CURVNET_SET(so->so_vnet);
374                        error = solisten(so, uap->backlog, td);
375                        CURVNET_RESTORE();
376#ifdef MAC
377                }
378#endif
379                fdrop(fp, td);
380        }
381        return(error);
382}
383#ifdef __rtems__
384int
385listen(int socket, int backlog)
386{
387        struct thread *td = rtems_bsd_get_curthread_or_null();
388        struct listen_args ua = {
389                .s = socket,
390                .backlog = backlog
391        };
392        int error;
393
394        if (td != NULL) {
395                error = rtems_bsd_listen(td, &ua);
396        } else {
397                error = ENOMEM;
398        }
399
400        return rtems_bsd_error_to_status_and_errno(error);
401}
402#endif /* __rtems__ */
403
404#ifdef __rtems__
405static int
406kern_accept(struct thread *td, int s, struct sockaddr **name,
407    socklen_t *namelen, struct file **fp);
408#endif /* __rtems__ */
409/*
410 * accept1()
411 */
412static int
413accept1(td, uap, compat)
414        struct thread *td;
415        struct accept_args /* {
416                int     s;
417                struct sockaddr * __restrict name;
418                socklen_t       * __restrict anamelen;
419        } */ *uap;
420        int compat;
421{
422        struct sockaddr *name;
423        socklen_t namelen;
424        struct file *fp;
425        int error;
426
427        if (uap->name == NULL)
428                return (kern_accept(td, uap->s, NULL, NULL, NULL));
429
430        error = copyin(uap->anamelen, &namelen, sizeof (namelen));
431        if (error)
432                return (error);
433
434        error = kern_accept(td, uap->s, &name, &namelen, &fp);
435
436        /*
437         * return a namelen of zero for older code which might
438         * ignore the return value from accept.
439         */
440        if (error) {
441                (void) copyout(&namelen,
442                    uap->anamelen, sizeof(*uap->anamelen));
443                return (error);
444        }
445
446        if (error == 0 && name != NULL) {
447#ifdef COMPAT_OLDSOCK
448                if (compat)
449                        ((struct osockaddr *)name)->sa_family =
450                            name->sa_family;
451#endif
452                error = copyout(name, uap->name, namelen);
453        }
454        if (error == 0)
455                error = copyout(&namelen, uap->anamelen,
456                    sizeof(namelen));
457        if (error)
458                fdclose(td->td_proc->p_fd, fp, td->td_retval[0], td);
459        fdrop(fp, td);
460        free(name, M_SONAME);
461        return (error);
462}
463#ifdef __rtems__
464int
465accept(int socket, struct sockaddr *__restrict address,
466    socklen_t *__restrict address_len)
467{
468        struct thread *td = rtems_bsd_get_curthread_or_null();
469        struct accept_args ua = {
470                .s = socket,
471                .name = address,
472                .anamelen = address_len
473        };
474        int error;
475
476        if (td != NULL) {
477                error = accept1(td, &ua);
478        } else {
479                error = ENOMEM;
480        }
481
482        if (error == 0) {
483                return td->td_retval[0];
484        } else {
485                rtems_set_errno_and_return_minus_one(error);
486        }
487}
488#endif /* __rtems__ */
489
490int
491kern_accept(struct thread *td, int s, struct sockaddr **name,
492    socklen_t *namelen, struct file **fp)
493{
494#ifndef __rtems__
495        struct filedesc *fdp;
496#endif /* __rtems__ */
497        struct file *headfp, *nfp = NULL;
498        struct sockaddr *sa = NULL;
499        int error;
500        struct socket *head, *so;
501        int fd;
502        u_int fflag;
503        pid_t pgid;
504        int tmp;
505
506        if (name) {
507                *name = NULL;
508                if (*namelen < 0)
509                        return (EINVAL);
510        }
511
512        AUDIT_ARG_FD(s);
513#ifndef __rtems__
514        fdp = td->td_proc->p_fd;
515#endif /* __rtems__ */
516        error = getsock(fdp, s, &headfp, &fflag);
517        if (error)
518                return (error);
519        head = headfp->f_data;
520        if ((head->so_options & SO_ACCEPTCONN) == 0) {
521                error = EINVAL;
522                goto done;
523        }
524#ifdef MAC
525        error = mac_socket_check_accept(td->td_ucred, head);
526        if (error != 0)
527                goto done;
528#endif
529        error = falloc(td, &nfp, &fd);
530        if (error)
531                goto done;
532        ACCEPT_LOCK();
533        if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
534                ACCEPT_UNLOCK();
535                error = EWOULDBLOCK;
536                goto noconnection;
537        }
538        while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
539                if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
540                        head->so_error = ECONNABORTED;
541                        break;
542                }
543                error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
544                    "accept", 0);
545                if (error) {
546                        ACCEPT_UNLOCK();
547                        goto noconnection;
548                }
549        }
550        if (head->so_error) {
551                error = head->so_error;
552                head->so_error = 0;
553                ACCEPT_UNLOCK();
554                goto noconnection;
555        }
556        so = TAILQ_FIRST(&head->so_comp);
557        KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
558        KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
559
560        /*
561         * Before changing the flags on the socket, we have to bump the
562         * reference count.  Otherwise, if the protocol calls sofree(),
563         * the socket will be released due to a zero refcount.
564         */
565        SOCK_LOCK(so);                  /* soref() and so_state update */
566        soref(so);                      /* file descriptor reference */
567
568        TAILQ_REMOVE(&head->so_comp, so, so_list);
569        head->so_qlen--;
570        so->so_state |= (head->so_state & SS_NBIO);
571        so->so_qstate &= ~SQ_COMP;
572        so->so_head = NULL;
573
574        SOCK_UNLOCK(so);
575        ACCEPT_UNLOCK();
576
577        /* An extra reference on `nfp' has been held for us by falloc(). */
578        td->td_retval[0] = fd;
579
580        /* connection has been removed from the listen queue */
581        KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
582
583        pgid = fgetown(&head->so_sigio);
584        if (pgid != 0)
585                fsetown(pgid, &so->so_sigio);
586
587        finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
588        /* Sync socket nonblocking/async state with file flags */
589        tmp = fflag & FNONBLOCK;
590        (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
591        tmp = fflag & FASYNC;
592        (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
593        sa = 0;
594        CURVNET_SET(so->so_vnet);
595        error = soaccept(so, &sa);
596        CURVNET_RESTORE();
597        if (error) {
598                /*
599                 * return a namelen of zero for older code which might
600                 * ignore the return value from accept.
601                 */
602                if (name)
603                        *namelen = 0;
604                goto noconnection;
605        }
606        if (sa == NULL) {
607                if (name)
608                        *namelen = 0;
609                goto done;
610        }
611        if (name) {
612                /* check sa_len before it is destroyed */
613                if (*namelen > sa->sa_len)
614                        *namelen = sa->sa_len;
615#ifdef KTRACE
616                if (KTRPOINT(td, KTR_STRUCT))
617                        ktrsockaddr(sa);
618#endif
619                *name = sa;
620                sa = NULL;
621        }
622noconnection:
623        if (sa)
624                free(sa, M_SONAME);
625
626        /*
627         * close the new descriptor, assuming someone hasn't ripped it
628         * out from under us.
629         */
630        if (error)
631                fdclose(fdp, nfp, fd, td);
632
633        /*
634         * Release explicitly held references before returning.  We return
635         * a reference on nfp to the caller on success if they request it.
636         */
637done:
638        if (fp != NULL) {
639                if (error == 0) {
640                        *fp = nfp;
641                        nfp = NULL;
642                } else
643                        *fp = NULL;
644        }
645        if (nfp != NULL)
646                fdrop(nfp, td);
647        fdrop(headfp, td);
648        return (error);
649}
650
651#ifndef __rtems__
652int
653accept(td, uap)
654        struct thread *td;
655        struct accept_args *uap;
656{
657
658        return (accept1(td, uap, 0));
659}
660
661#ifdef COMPAT_OLDSOCK
662int
663oaccept(td, uap)
664        struct thread *td;
665        struct accept_args *uap;
666{
667
668        return (accept1(td, uap, 1));
669}
670#endif /* COMPAT_OLDSOCK */
671#endif /* __rtems__ */
672
673/* ARGSUSED */
674#ifndef __rtems__
675int
676#else /* __rtems__ */
677static int kern_connect(struct thread *, int, struct sockaddr *);
678
679static int
680rtems_bsd_connect(td, uap)
681#endif /* __rtems__ */
682        struct thread *td;
683        struct connect_args /* {
684                int     s;
685                caddr_t name;
686                int     namelen;
687        } */ *uap;
688{
689        struct sockaddr *sa;
690        int error;
691
692        error = getsockaddr(&sa, uap->name, uap->namelen);
693        if (error)
694                return (error);
695
696        error = kern_connect(td, uap->s, sa);
697        free(sa, M_SONAME);
698        return (error);
699}
700#ifdef __rtems__
701int
702connect(int socket, const struct sockaddr *address, socklen_t address_len)
703{
704        struct thread *td = rtems_bsd_get_curthread_or_null();
705        struct connect_args ua = {
706                .s = socket,
707                .name = (caddr_t) address,
708                .namelen = address_len
709        };
710        int error;
711
712        if (td != NULL) {
713                error = rtems_bsd_connect(td, &ua);
714        } else {
715                error = ENOMEM;
716        }
717
718        return rtems_bsd_error_to_status_and_errno(error);
719}
720#endif /* __rtems__ */
721
722
723int
724kern_connect(td, fd, sa)
725        struct thread *td;
726        int fd;
727        struct sockaddr *sa;
728{
729        struct socket *so;
730        struct file *fp;
731        int error;
732        int interrupted = 0;
733
734        AUDIT_ARG_FD(fd);
735        error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
736        if (error)
737                return (error);
738        so = fp->f_data;
739        if (so->so_state & SS_ISCONNECTING) {
740                error = EALREADY;
741                goto done1;
742        }
743#ifdef KTRACE
744        if (KTRPOINT(td, KTR_STRUCT))
745                ktrsockaddr(sa);
746#endif
747#ifdef MAC
748        error = mac_socket_check_connect(td->td_ucred, so, sa);
749        if (error)
750                goto bad;
751#endif
752        error = soconnect(so, sa, td);
753        if (error)
754                goto bad;
755        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
756                error = EINPROGRESS;
757                goto done1;
758        }
759        SOCK_LOCK(so);
760        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
761                error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH,
762                    "connec", 0);
763                if (error) {
764                        if (error == EINTR || error == ERESTART)
765                                interrupted = 1;
766                        break;
767                }
768        }
769        if (error == 0) {
770                error = so->so_error;
771                so->so_error = 0;
772        }
773        SOCK_UNLOCK(so);
774bad:
775        if (!interrupted)
776                so->so_state &= ~SS_ISCONNECTING;
777        if (error == ERESTART)
778                error = EINTR;
779done1:
780        fdrop(fp, td);
781        return (error);
782}
783
784#ifndef __rtems__
785int
786kern_socketpair(struct thread *td, int domain, int type, int protocol,
787    int *rsv)
788{
789        struct filedesc *fdp = td->td_proc->p_fd;
790        struct file *fp1, *fp2;
791        struct socket *so1, *so2;
792        int fd, error;
793
794        AUDIT_ARG_SOCKET(domain, type, protocol);
795#ifdef MAC
796        /* We might want to have a separate check for socket pairs. */
797        error = mac_socket_check_create(td->td_ucred, domain, type,
798            protocol);
799        if (error)
800                return (error);
801#endif
802        error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
803        if (error)
804                return (error);
805        error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
806        if (error)
807                goto free1;
808        /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
809        error = falloc(td, &fp1, &fd);
810        if (error)
811                goto free2;
812        rsv[0] = fd;
813        fp1->f_data = so1;      /* so1 already has ref count */
814        error = falloc(td, &fp2, &fd);
815        if (error)
816                goto free3;
817        fp2->f_data = so2;      /* so2 already has ref count */
818        rsv[1] = fd;
819        error = soconnect2(so1, so2);
820        if (error)
821                goto free4;
822        if (type == SOCK_DGRAM) {
823                /*
824                 * Datagram socket connection is asymmetric.
825                 */
826                 error = soconnect2(so2, so1);
827                 if (error)
828                        goto free4;
829        }
830        finit(fp1, FREAD | FWRITE, DTYPE_SOCKET, fp1->f_data, &socketops);
831        finit(fp2, FREAD | FWRITE, DTYPE_SOCKET, fp2->f_data, &socketops);
832        fdrop(fp1, td);
833        fdrop(fp2, td);
834        return (0);
835free4:
836        fdclose(fdp, fp2, rsv[1], td);
837        fdrop(fp2, td);
838free3:
839        fdclose(fdp, fp1, rsv[0], td);
840        fdrop(fp1, td);
841free2:
842        if (so2 != NULL)
843                (void)soclose(so2);
844free1:
845        if (so1 != NULL)
846                (void)soclose(so1);
847        return (error);
848}
849
850int
851socketpair(struct thread *td, struct socketpair_args *uap)
852{
853        int error, sv[2];
854
855        error = kern_socketpair(td, uap->domain, uap->type,
856            uap->protocol, sv);
857        if (error)
858                return (error);
859        error = copyout(sv, uap->rsv, 2 * sizeof(int));
860        if (error) {
861                (void)kern_close(td, sv[0]);
862                (void)kern_close(td, sv[1]);
863        }
864        return (error);
865}
866#endif /* __rtems__ */
867
868#ifdef __rtems__
869static int
870kern_sendit( struct thread *td, int s, struct msghdr *mp, int flags,
871    struct mbuf *control, enum uio_seg segflg);
872#endif /* __rtems__ */
873static int
874sendit(td, s, mp, flags)
875        struct thread *td;
876        int s;
877        struct msghdr *mp;
878        int flags;
879{
880        struct mbuf *control;
881        struct sockaddr *to;
882        int error;
883
884        if (mp->msg_name != NULL) {
885                error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
886                if (error) {
887                        to = NULL;
888                        goto bad;
889                }
890                mp->msg_name = to;
891        } else {
892                to = NULL;
893        }
894
895        if (mp->msg_control) {
896                if (mp->msg_controllen < sizeof(struct cmsghdr)
897#ifdef COMPAT_OLDSOCK
898                    && mp->msg_flags != MSG_COMPAT
899#endif
900                ) {
901                        error = EINVAL;
902                        goto bad;
903                }
904                error = sockargs(&control, mp->msg_control,
905                    mp->msg_controllen, MT_CONTROL);
906                if (error)
907                        goto bad;
908#ifdef COMPAT_OLDSOCK
909                if (mp->msg_flags == MSG_COMPAT) {
910                        struct cmsghdr *cm;
911
912                        M_PREPEND(control, sizeof(*cm), M_WAIT);
913                        cm = mtod(control, struct cmsghdr *);
914                        cm->cmsg_len = control->m_len;
915                        cm->cmsg_level = SOL_SOCKET;
916                        cm->cmsg_type = SCM_RIGHTS;
917                }
918#endif
919        } else {
920                control = NULL;
921        }
922
923        error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
924
925bad:
926        if (to)
927                free(to, M_SONAME);
928        return (error);
929}
930
931int
932kern_sendit(td, s, mp, flags, control, segflg)
933        struct thread *td;
934        int s;
935        struct msghdr *mp;
936        int flags;
937        struct mbuf *control;
938        enum uio_seg segflg;
939{
940        struct file *fp;
941        struct uio auio;
942        struct iovec *iov;
943        struct socket *so;
944        int i;
945        int len, error;
946#ifdef KTRACE
947        struct uio *ktruio = NULL;
948#endif
949
950        AUDIT_ARG_FD(s);
951        error = getsock(td->td_proc->p_fd, s, &fp, NULL);
952        if (error)
953                return (error);
954        so = (struct socket *)fp->f_data;
955
956#ifdef MAC
957        if (mp->msg_name != NULL) {
958                error = mac_socket_check_connect(td->td_ucred, so,
959                    mp->msg_name);
960                if (error)
961                        goto bad;
962        }
963        error = mac_socket_check_send(td->td_ucred, so);
964        if (error)
965                goto bad;
966#endif
967
968        auio.uio_iov = mp->msg_iov;
969        auio.uio_iovcnt = mp->msg_iovlen;
970        auio.uio_segflg = segflg;
971        auio.uio_rw = UIO_WRITE;
972        auio.uio_td = td;
973        auio.uio_offset = 0;                    /* XXX */
974        auio.uio_resid = 0;
975        iov = mp->msg_iov;
976        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
977                if ((auio.uio_resid += iov->iov_len) < 0) {
978                        error = EINVAL;
979                        goto bad;
980                }
981        }
982#ifdef KTRACE
983        if (KTRPOINT(td, KTR_GENIO))
984                ktruio = cloneuio(&auio);
985#endif
986        len = auio.uio_resid;
987        error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
988        if (error) {
989                if (auio.uio_resid != len && (error == ERESTART ||
990                    error == EINTR || error == EWOULDBLOCK))
991                        error = 0;
992                /* Generation of SIGPIPE can be controlled per socket */
993                if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
994                    !(flags & MSG_NOSIGNAL)) {
995#ifndef __rtems__
996                        PROC_LOCK(td->td_proc);
997                        tdksignal(td, SIGPIPE, NULL);
998                        PROC_UNLOCK(td->td_proc);
999#else /* __rtems__ */
1000                /* FIXME: Determine if we really want to use signals */
1001#endif /* __rtems__ */
1002                }
1003        }
1004        if (error == 0)
1005                td->td_retval[0] = len - auio.uio_resid;
1006#ifdef KTRACE
1007        if (ktruio != NULL) {
1008                ktruio->uio_resid = td->td_retval[0];
1009                ktrgenio(s, UIO_WRITE, ktruio, error);
1010        }
1011#endif
1012bad:
1013        fdrop(fp, td);
1014        return (error);
1015}
1016
1017#ifndef __rtems__
1018int
1019sendto(td, uap)
1020#else /* __rtems__ */
1021static int
1022rtems_bsd_sendto(td, uap)
1023#endif /* __rtems__ */
1024        struct thread *td;
1025        struct sendto_args /* {
1026                int     s;
1027                caddr_t buf;
1028                size_t  len;
1029                int     flags;
1030                caddr_t to;
1031                int     tolen;
1032        } */ *uap;
1033{
1034        struct msghdr msg;
1035        struct iovec aiov;
1036        int error;
1037
1038        msg.msg_name = uap->to;
1039        msg.msg_namelen = uap->tolen;
1040        msg.msg_iov = &aiov;
1041        msg.msg_iovlen = 1;
1042        msg.msg_control = 0;
1043#ifdef COMPAT_OLDSOCK
1044        msg.msg_flags = 0;
1045#endif
1046        aiov.iov_base = uap->buf;
1047        aiov.iov_len = uap->len;
1048        error = sendit(td, uap->s, &msg, uap->flags);
1049        return (error);
1050}
1051#ifdef __rtems__
1052ssize_t
1053sendto(int socket, const void *message, size_t length, int flags,
1054    const struct sockaddr *dest_addr, socklen_t dest_len)
1055{
1056        struct thread *td = rtems_bsd_get_curthread_or_null();
1057        struct sendto_args ua = {
1058                .s = socket,
1059                .buf = (caddr_t) message,
1060                .len = length,
1061                .flags = flags,
1062                .to = (caddr_t) dest_addr,
1063                .tolen = dest_len
1064        };
1065        int error;
1066
1067        if (td != NULL) {
1068                error = rtems_bsd_sendto(td, &ua);
1069        } else {
1070                error = ENOMEM;
1071        }
1072
1073        if (error == 0) {
1074                return td->td_retval[0];
1075        } else {
1076                rtems_set_errno_and_return_minus_one(error);
1077        }
1078}
1079#endif /* __rtems__ */
1080
1081#ifndef __rtems__
1082#ifdef COMPAT_OLDSOCK
1083int
1084osend(td, uap)
1085        struct thread *td;
1086        struct osend_args /* {
1087                int     s;
1088                caddr_t buf;
1089                int     len;
1090                int     flags;
1091        } */ *uap;
1092{
1093        struct msghdr msg;
1094        struct iovec aiov;
1095        int error;
1096
1097        msg.msg_name = 0;
1098        msg.msg_namelen = 0;
1099        msg.msg_iov = &aiov;
1100        msg.msg_iovlen = 1;
1101        aiov.iov_base = uap->buf;
1102        aiov.iov_len = uap->len;
1103        msg.msg_control = 0;
1104        msg.msg_flags = 0;
1105        error = sendit(td, uap->s, &msg, uap->flags);
1106        return (error);
1107}
1108
1109int
1110osendmsg(td, uap)
1111        struct thread *td;
1112        struct osendmsg_args /* {
1113                int     s;
1114                caddr_t msg;
1115                int     flags;
1116        } */ *uap;
1117{
1118        struct msghdr msg;
1119        struct iovec *iov;
1120        int error;
1121
1122        error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
1123        if (error)
1124                return (error);
1125        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1126        if (error)
1127                return (error);
1128        msg.msg_iov = iov;
1129        msg.msg_flags = MSG_COMPAT;
1130        error = sendit(td, uap->s, &msg, uap->flags);
1131        free(iov, M_IOV);
1132        return (error);
1133}
1134#endif
1135#endif /* __rtems__ */
1136
1137#ifndef __rtems__
1138int
1139sendmsg(td, uap)
1140#else /* __rtems__ */
1141static int
1142rtems_bsd_sendmsg(td, uap)
1143#endif /* __rtems__ */
1144        struct thread *td;
1145        struct sendmsg_args /* {
1146                int     s;
1147                caddr_t msg;
1148                int     flags;
1149        } */ *uap;
1150{
1151        struct msghdr msg;
1152        struct iovec *iov;
1153        int error;
1154
1155        error = copyin(uap->msg, &msg, sizeof (msg));
1156        if (error)
1157                return (error);
1158        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1159        if (error)
1160                return (error);
1161        msg.msg_iov = iov;
1162#ifdef COMPAT_OLDSOCK
1163        msg.msg_flags = 0;
1164#endif
1165        error = sendit(td, uap->s, &msg, uap->flags);
1166        free(iov, M_IOV);
1167        return (error);
1168}
1169#ifdef __rtems__
1170ssize_t
1171sendmsg(int socket, const struct msghdr *message, int flags)
1172{
1173        struct thread *td = rtems_bsd_get_curthread_or_null();
1174        struct sendmsg_args ua = {
1175                .s = socket,
1176                .msg = message,
1177                .flags = flags
1178        };
1179        int error;
1180
1181        if (td != NULL) {
1182                error = rtems_bsd_sendmsg(td, &ua);
1183        } else {
1184                error = ENOMEM;
1185        }
1186
1187        if (error == 0) {
1188                return td->td_retval[0];
1189        } else {
1190                rtems_set_errno_and_return_minus_one(error);
1191        }
1192}
1193#endif /* __rtems__ */
1194
1195#ifdef __rtems__
1196static
1197#endif /* __rtems__ */
1198int
1199kern_recvit(td, s, mp, fromseg, controlp)
1200        struct thread *td;
1201        int s;
1202        struct msghdr *mp;
1203        enum uio_seg fromseg;
1204        struct mbuf **controlp;
1205{
1206        struct uio auio;
1207        struct iovec *iov;
1208        int i;
1209        socklen_t len;
1210        int error;
1211        struct mbuf *m, *control = 0;
1212        caddr_t ctlbuf;
1213        struct file *fp;
1214        struct socket *so;
1215        struct sockaddr *fromsa = 0;
1216#ifdef KTRACE
1217        struct uio *ktruio = NULL;
1218#endif
1219
1220        if(controlp != NULL)
1221                *controlp = 0;
1222
1223        AUDIT_ARG_FD(s);
1224        error = getsock(td->td_proc->p_fd, s, &fp, NULL);
1225        if (error)
1226                return (error);
1227        so = fp->f_data;
1228
1229#ifdef MAC
1230        error = mac_socket_check_receive(td->td_ucred, so);
1231        if (error) {
1232                fdrop(fp, td);
1233                return (error);
1234        }
1235#endif
1236
1237        auio.uio_iov = mp->msg_iov;
1238        auio.uio_iovcnt = mp->msg_iovlen;
1239        auio.uio_segflg = UIO_USERSPACE;
1240        auio.uio_rw = UIO_READ;
1241        auio.uio_td = td;
1242        auio.uio_offset = 0;                    /* XXX */
1243        auio.uio_resid = 0;
1244        iov = mp->msg_iov;
1245        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1246                if ((auio.uio_resid += iov->iov_len) < 0) {
1247                        fdrop(fp, td);
1248                        return (EINVAL);
1249                }
1250        }
1251#ifdef KTRACE
1252        if (KTRPOINT(td, KTR_GENIO))
1253                ktruio = cloneuio(&auio);
1254#endif
1255        len = auio.uio_resid;
1256        CURVNET_SET(so->so_vnet);
1257        error = soreceive(so, &fromsa, &auio, (struct mbuf **)0,
1258            (mp->msg_control || controlp) ? &control : (struct mbuf **)0,
1259            &mp->msg_flags);
1260        CURVNET_RESTORE();
1261        if (error) {
1262                if (auio.uio_resid != (int)len && (error == ERESTART ||
1263                    error == EINTR || error == EWOULDBLOCK))
1264                        error = 0;
1265        }
1266#ifdef KTRACE
1267        if (ktruio != NULL) {
1268                ktruio->uio_resid = (int)len - auio.uio_resid;
1269                ktrgenio(s, UIO_READ, ktruio, error);
1270        }
1271#endif
1272        if (error)
1273                goto out;
1274        td->td_retval[0] = (int)len - auio.uio_resid;
1275        if (mp->msg_name) {
1276                len = mp->msg_namelen;
1277                if (len <= 0 || fromsa == 0)
1278                        len = 0;
1279                else {
1280                        /* save sa_len before it is destroyed by MSG_COMPAT */
1281                        len = MIN(len, fromsa->sa_len);
1282#ifdef COMPAT_OLDSOCK
1283                        if (mp->msg_flags & MSG_COMPAT)
1284                                ((struct osockaddr *)fromsa)->sa_family =
1285                                    fromsa->sa_family;
1286#endif
1287                        if (fromseg == UIO_USERSPACE) {
1288                                error = copyout(fromsa, mp->msg_name,
1289                                    (unsigned)len);
1290                                if (error)
1291                                        goto out;
1292                        } else
1293                                bcopy(fromsa, mp->msg_name, len);
1294                }
1295                mp->msg_namelen = len;
1296        }
1297        if (mp->msg_control && controlp == NULL) {
1298#ifdef COMPAT_OLDSOCK
1299                /*
1300                 * We assume that old recvmsg calls won't receive access
1301                 * rights and other control info, esp. as control info
1302                 * is always optional and those options didn't exist in 4.3.
1303                 * If we receive rights, trim the cmsghdr; anything else
1304                 * is tossed.
1305                 */
1306                if (control && mp->msg_flags & MSG_COMPAT) {
1307                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
1308                            SOL_SOCKET ||
1309                            mtod(control, struct cmsghdr *)->cmsg_type !=
1310                            SCM_RIGHTS) {
1311                                mp->msg_controllen = 0;
1312                                goto out;
1313                        }
1314                        control->m_len -= sizeof (struct cmsghdr);
1315                        control->m_data += sizeof (struct cmsghdr);
1316                }
1317#endif
1318                len = mp->msg_controllen;
1319                m = control;
1320                mp->msg_controllen = 0;
1321                ctlbuf = mp->msg_control;
1322
1323                while (m && len > 0) {
1324                        unsigned int tocopy;
1325
1326                        if (len >= m->m_len)
1327                                tocopy = m->m_len;
1328                        else {
1329                                mp->msg_flags |= MSG_CTRUNC;
1330                                tocopy = len;
1331                        }
1332
1333                        if ((error = copyout(mtod(m, caddr_t),
1334                                        ctlbuf, tocopy)) != 0)
1335                                goto out;
1336
1337                        ctlbuf += tocopy;
1338                        len -= tocopy;
1339                        m = m->m_next;
1340                }
1341                mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
1342        }
1343out:
1344        fdrop(fp, td);
1345#ifdef KTRACE
1346        if (fromsa && KTRPOINT(td, KTR_STRUCT))
1347                ktrsockaddr(fromsa);
1348#endif
1349        if (fromsa)
1350                free(fromsa, M_SONAME);
1351
1352        if (error == 0 && controlp != NULL) 
1353                *controlp = control;
1354        else  if (control)
1355                m_freem(control);
1356
1357        return (error);
1358}
1359
1360static int
1361recvit(td, s, mp, namelenp)
1362        struct thread *td;
1363        int s;
1364        struct msghdr *mp;
1365        void *namelenp;
1366{
1367        int error;
1368
1369        error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
1370        if (error)
1371                return (error);
1372        if (namelenp) {
1373                error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
1374#ifdef COMPAT_OLDSOCK
1375                if (mp->msg_flags & MSG_COMPAT)
1376                        error = 0;      /* old recvfrom didn't check */
1377#endif
1378        }
1379        return (error);
1380}
1381
1382#ifndef __rtems__
1383int
1384recvfrom(td, uap)
1385#else /* __rtems__ */
1386static int
1387rtems_bsd_recvfrom(td, uap)
1388#endif /* __rtems__ */
1389        struct thread *td;
1390        struct recvfrom_args /* {
1391                int     s;
1392                caddr_t buf;
1393                size_t  len;
1394                int     flags;
1395                struct sockaddr * __restrict    from;
1396                socklen_t * __restrict fromlenaddr;
1397        } */ *uap;
1398{
1399        struct msghdr msg;
1400        struct iovec aiov;
1401        int error;
1402
1403        if (uap->fromlenaddr) {
1404                error = copyin(uap->fromlenaddr,
1405                    &msg.msg_namelen, sizeof (msg.msg_namelen));
1406                if (error)
1407                        goto done2;
1408        } else {
1409                msg.msg_namelen = 0;
1410        }
1411        msg.msg_name = uap->from;
1412        msg.msg_iov = &aiov;
1413        msg.msg_iovlen = 1;
1414        aiov.iov_base = uap->buf;
1415        aiov.iov_len = uap->len;
1416        msg.msg_control = 0;
1417        msg.msg_flags = uap->flags;
1418        error = recvit(td, uap->s, &msg, uap->fromlenaddr);
1419done2:
1420        return(error);
1421}
1422#ifdef __rtems__
1423ssize_t
1424recvfrom(int socket, void *__restrict buffer, size_t length, int flags,
1425    struct sockaddr *__restrict address, socklen_t *__restrict address_len)
1426{
1427        struct thread *td = rtems_bsd_get_curthread_or_null();
1428        struct recvfrom_args ua = {
1429                .s = socket,
1430                .buf = buffer,
1431                .len = length,
1432                .flags = flags,
1433                .from = address,
1434                .fromlenaddr = address_len
1435        };
1436        int error;
1437
1438        if (td != NULL) {
1439                error = rtems_bsd_recvfrom(td, &ua);
1440        } else {
1441                error = ENOMEM;
1442        }
1443
1444        if (error == 0) {
1445                return td->td_retval[0];
1446        } else {
1447                rtems_set_errno_and_return_minus_one(error);
1448        }
1449}
1450#endif /* __rtems__ */
1451
1452#ifndef __rtems__
1453#ifdef COMPAT_OLDSOCK
1454int
1455orecvfrom(td, uap)
1456        struct thread *td;
1457        struct recvfrom_args *uap;
1458{
1459
1460        uap->flags |= MSG_COMPAT;
1461        return (recvfrom(td, uap));
1462}
1463#endif
1464
1465#ifdef COMPAT_OLDSOCK
1466int
1467orecv(td, uap)
1468        struct thread *td;
1469        struct orecv_args /* {
1470                int     s;
1471                caddr_t buf;
1472                int     len;
1473                int     flags;
1474        } */ *uap;
1475{
1476        struct msghdr msg;
1477        struct iovec aiov;
1478        int error;
1479
1480        msg.msg_name = 0;
1481        msg.msg_namelen = 0;
1482        msg.msg_iov = &aiov;
1483        msg.msg_iovlen = 1;
1484        aiov.iov_base = uap->buf;
1485        aiov.iov_len = uap->len;
1486        msg.msg_control = 0;
1487        msg.msg_flags = uap->flags;
1488        error = recvit(td, uap->s, &msg, NULL);
1489        return (error);
1490}
1491
1492/*
1493 * Old recvmsg.  This code takes advantage of the fact that the old msghdr
1494 * overlays the new one, missing only the flags, and with the (old) access
1495 * rights where the control fields are now.
1496 */
1497int
1498orecvmsg(td, uap)
1499        struct thread *td;
1500        struct orecvmsg_args /* {
1501                int     s;
1502                struct  omsghdr *msg;
1503                int     flags;
1504        } */ *uap;
1505{
1506        struct msghdr msg;
1507        struct iovec *iov;
1508        int error;
1509
1510        error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
1511        if (error)
1512                return (error);
1513        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1514        if (error)
1515                return (error);
1516        msg.msg_flags = uap->flags | MSG_COMPAT;
1517        msg.msg_iov = iov;
1518        error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
1519        if (msg.msg_controllen && error == 0)
1520                error = copyout(&msg.msg_controllen,
1521                    &uap->msg->msg_accrightslen, sizeof (int));
1522        free(iov, M_IOV);
1523        return (error);
1524}
1525#endif
1526#endif /* __rtems__ */
1527
1528#ifndef __rtems__
1529int
1530recvmsg(td, uap)
1531#else /* __rtems__ */
1532static int
1533rtems_bsd_recvmsg(td, uap)
1534#endif /* __rtems__ */
1535        struct thread *td;
1536        struct recvmsg_args /* {
1537                int     s;
1538                struct  msghdr *msg;
1539                int     flags;
1540        } */ *uap;
1541{
1542        struct msghdr msg;
1543        struct iovec *uiov, *iov;
1544        int error;
1545
1546        error = copyin(uap->msg, &msg, sizeof (msg));
1547        if (error)
1548                return (error);
1549        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1550        if (error)
1551                return (error);
1552        msg.msg_flags = uap->flags;
1553#ifdef COMPAT_OLDSOCK
1554        msg.msg_flags &= ~MSG_COMPAT;
1555#endif
1556        uiov = msg.msg_iov;
1557        msg.msg_iov = iov;
1558        error = recvit(td, uap->s, &msg, NULL);
1559        if (error == 0) {
1560                msg.msg_iov = uiov;
1561                error = copyout(&msg, uap->msg, sizeof(msg));
1562        }
1563        free(iov, M_IOV);
1564        return (error);
1565}
1566#ifdef __rtems__
1567ssize_t
1568recvmsg(int socket, struct msghdr *message, int flags)
1569{
1570        struct thread *td = rtems_bsd_get_curthread_or_null();
1571        struct recvmsg_args ua = {
1572                .s = socket,
1573                .msg = message,
1574                .flags = flags
1575        };
1576        int error;
1577
1578        if (td != NULL) {
1579                error = rtems_bsd_recvmsg(td, &ua);
1580        } else {
1581                error = ENOMEM;
1582        }
1583
1584        if (error == 0) {
1585                return td->td_retval[0];
1586        } else {
1587                rtems_set_errno_and_return_minus_one(error);
1588        }
1589}
1590#endif /* __rtems__ */
1591
1592/* ARGSUSED */
1593#ifndef __rtems__
1594int
1595shutdown(td, uap)
1596#else /* __rtems__ */
1597static int
1598rtems_bsd_shutdown(td, uap)
1599#endif /* __rtems__ */
1600        struct thread *td;
1601        struct shutdown_args /* {
1602                int     s;
1603                int     how;
1604        } */ *uap;
1605{
1606        struct socket *so;
1607        struct file *fp;
1608        int error;
1609
1610        AUDIT_ARG_FD(uap->s);
1611        error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL);
1612        if (error == 0) {
1613                so = fp->f_data;
1614                error = soshutdown(so, uap->how);
1615                fdrop(fp, td);
1616        }
1617        return (error);
1618}
1619#ifdef __rtems__
1620int
1621shutdown(int socket, int how)
1622{
1623        struct shutdown_args ua = {
1624                .s = socket,
1625                .how = how
1626        };
1627        int error = rtems_bsd_shutdown(NULL, &ua);
1628
1629        return rtems_bsd_error_to_status_and_errno(error);
1630}
1631#endif /* __rtems__ */
1632
1633/* ARGSUSED */
1634#ifndef __rtems__
1635int
1636setsockopt(td, uap)
1637#else /* __rtems__ */
1638static int
1639kern_setsockopt( struct thread *td, int s, int level, int name, void *val,
1640    enum uio_seg valseg, socklen_t valsize);
1641
1642static int
1643rtems_bsd_setsockopt(td, uap)
1644#endif /* __rtems__ */
1645        struct thread *td;
1646        struct setsockopt_args /* {
1647                int     s;
1648                int     level;
1649                int     name;
1650                caddr_t val;
1651                int     valsize;
1652        } */ *uap;
1653{
1654
1655        return (kern_setsockopt(td, uap->s, uap->level, uap->name,
1656            uap->val, UIO_USERSPACE, uap->valsize));
1657}
1658#ifdef __rtems__
1659int
1660setsockopt(int socket, int level, int option_name, const void *option_value,
1661    socklen_t option_len)
1662{
1663        struct thread *td = rtems_bsd_get_curthread_or_null();
1664        struct setsockopt_args ua = {
1665                .s = socket,
1666                .level = level,
1667                .name = option_name,
1668                .val = __DECONST(void *, option_value),
1669                .valsize = option_len
1670        };
1671        int error;
1672
1673        if (td != NULL) {
1674                error = rtems_bsd_setsockopt(td, &ua);
1675        } else {
1676                error = ENOMEM;
1677        }
1678
1679        return rtems_bsd_error_to_status_and_errno(error);
1680}
1681#endif /* __rtems__ */
1682
1683int
1684kern_setsockopt(td, s, level, name, val, valseg, valsize)
1685        struct thread *td;
1686        int s;
1687        int level;
1688        int name;
1689        void *val;
1690        enum uio_seg valseg;
1691        socklen_t valsize;
1692{
1693        int error;
1694        struct socket *so;
1695        struct file *fp;
1696        struct sockopt sopt;
1697
1698        if (val == NULL && valsize != 0)
1699                return (EFAULT);
1700        if ((int)valsize < 0)
1701                return (EINVAL);
1702
1703        sopt.sopt_dir = SOPT_SET;
1704        sopt.sopt_level = level;
1705        sopt.sopt_name = name;
1706        sopt.sopt_val = val;
1707        sopt.sopt_valsize = valsize;
1708        switch (valseg) {
1709        case UIO_USERSPACE:
1710                sopt.sopt_td = td;
1711                break;
1712        case UIO_SYSSPACE:
1713                sopt.sopt_td = NULL;
1714                break;
1715        default:
1716                panic("kern_setsockopt called with bad valseg");
1717        }
1718
1719        AUDIT_ARG_FD(s);
1720        error = getsock(td->td_proc->p_fd, s, &fp, NULL);
1721        if (error == 0) {
1722                so = fp->f_data;
1723                CURVNET_SET(so->so_vnet);
1724                error = sosetopt(so, &sopt);
1725                CURVNET_RESTORE();
1726                fdrop(fp, td);
1727        }
1728        return(error);
1729}
1730
1731/* ARGSUSED */
1732#ifndef __rtems__
1733int
1734getsockopt(td, uap)
1735#else /* __rtems__ */
1736static int
1737kern_getsockopt( struct thread *td, int s, int level, int name, void *val,
1738   enum uio_seg valseg, socklen_t *valsize);
1739
1740static int
1741rtems_bsd_getsockopt(td, uap)
1742#endif /* __rtems__ */
1743        struct thread *td;
1744        struct getsockopt_args /* {
1745                int     s;
1746                int     level;
1747                int     name;
1748                void * __restrict       val;
1749                socklen_t * __restrict avalsize;
1750        } */ *uap;
1751{
1752        socklen_t valsize;
1753        int     error;
1754
1755        if (uap->val) {
1756                error = copyin(uap->avalsize, &valsize, sizeof (valsize));
1757                if (error)
1758                        return (error);
1759        }
1760
1761        error = kern_getsockopt(td, uap->s, uap->level, uap->name,
1762            uap->val, UIO_USERSPACE, &valsize);
1763
1764        if (error == 0)
1765                error = copyout(&valsize, uap->avalsize, sizeof (valsize));
1766        return (error);
1767}
1768#ifdef __rtems__
1769int
1770getsockopt(int socket, int level, int option_name, void *__restrict
1771    option_value, socklen_t *__restrict option_len)
1772{
1773        struct thread *td = rtems_bsd_get_curthread_or_null();
1774        struct getsockopt_args ua = {
1775                .s = socket,
1776                .level = level,
1777                .name = option_name,
1778                .val = (caddr_t) option_value,
1779                .avalsize = option_len
1780        };
1781        int error;
1782
1783        if (td != NULL) {
1784                error = rtems_bsd_getsockopt(td, &ua);
1785        } else {
1786                error = ENOMEM;
1787        }
1788
1789        return rtems_bsd_error_to_status_and_errno(error);
1790}
1791#endif /* __rtems__ */
1792
1793/*
1794 * Kernel version of getsockopt.
1795 * optval can be a userland or userspace. optlen is always a kernel pointer.
1796 */
1797int
1798kern_getsockopt(td, s, level, name, val, valseg, valsize)
1799        struct thread *td;
1800        int s;
1801        int level;
1802        int name;
1803        void *val;
1804        enum uio_seg valseg;
1805        socklen_t *valsize;
1806{
1807        int error;
1808        struct  socket *so;
1809        struct file *fp;
1810        struct  sockopt sopt;
1811
1812        if (val == NULL)
1813                *valsize = 0;
1814        if ((int)*valsize < 0)
1815                return (EINVAL);
1816
1817        sopt.sopt_dir = SOPT_GET;
1818        sopt.sopt_level = level;
1819        sopt.sopt_name = name;
1820        sopt.sopt_val = val;
1821        sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */
1822        switch (valseg) {
1823        case UIO_USERSPACE:
1824                sopt.sopt_td = td;
1825                break;
1826        case UIO_SYSSPACE:
1827                sopt.sopt_td = NULL;
1828                break;
1829        default:
1830                panic("kern_getsockopt called with bad valseg");
1831        }
1832
1833        AUDIT_ARG_FD(s);
1834        error = getsock(td->td_proc->p_fd, s, &fp, NULL);
1835        if (error == 0) {
1836                so = fp->f_data;
1837                CURVNET_SET(so->so_vnet);
1838                error = sogetopt(so, &sopt);
1839                CURVNET_RESTORE();
1840                *valsize = sopt.sopt_valsize;
1841                fdrop(fp, td);
1842        }
1843        return (error);
1844}
1845
1846#ifdef __rtems__
1847int
1848kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
1849    socklen_t *alen);
1850#endif /* __rtems__ */
1851/*
1852 * getsockname1() - Get socket name.
1853 */
1854/* ARGSUSED */
1855static int
1856getsockname1(td, uap, compat)
1857        struct thread *td;
1858        struct getsockname_args /* {
1859                int     fdes;
1860                struct sockaddr * __restrict asa;
1861                socklen_t * __restrict alen;
1862        } */ *uap;
1863        int compat;
1864{
1865        struct sockaddr *sa;
1866        socklen_t len;
1867        int error;
1868
1869        error = copyin(uap->alen, &len, sizeof(len));
1870        if (error)
1871                return (error);
1872
1873        error = kern_getsockname(td, uap->fdes, &sa, &len);
1874        if (error)
1875                return (error);
1876
1877        if (len != 0) {
1878#ifdef COMPAT_OLDSOCK
1879                if (compat)
1880                        ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1881#endif
1882                error = copyout(sa, uap->asa, (u_int)len);
1883        }
1884        free(sa, M_SONAME);
1885        if (error == 0)
1886                error = copyout(&len, uap->alen, sizeof(len));
1887        return (error);
1888}
1889#ifdef __rtems__
1890int
1891getsockname(int socket, struct sockaddr *__restrict address,
1892    socklen_t *__restrict address_len)
1893{
1894        struct thread *td = rtems_bsd_get_curthread_or_null();
1895        struct getsockname_args ua = {
1896                .fdes = socket,
1897                .asa = address,
1898                .alen = address_len
1899        };
1900        int error;
1901
1902        if (td != NULL) {
1903                error = getsockname1(td, &ua);
1904        } else {
1905                error = ENOMEM;
1906        }
1907
1908        return rtems_bsd_error_to_status_and_errno(error);
1909}
1910#endif /* __rtems__ */
1911
1912int
1913kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
1914    socklen_t *alen)
1915{
1916        struct socket *so;
1917        struct file *fp;
1918        socklen_t len;
1919        int error;
1920
1921        if (*alen < 0)
1922                return (EINVAL);
1923
1924        AUDIT_ARG_FD(fd);
1925        error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
1926        if (error)
1927                return (error);
1928        so = fp->f_data;
1929        *sa = NULL;
1930        CURVNET_SET(so->so_vnet);
1931        error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
1932        CURVNET_RESTORE();
1933        if (error)
1934                goto bad;
1935        if (*sa == NULL)
1936                len = 0;
1937        else
1938                len = MIN(*alen, (*sa)->sa_len);
1939        *alen = len;
1940#ifdef KTRACE
1941        if (KTRPOINT(td, KTR_STRUCT))
1942                ktrsockaddr(*sa);
1943#endif
1944bad:
1945        fdrop(fp, td);
1946        if (error && *sa) {
1947                free(*sa, M_SONAME);
1948                *sa = NULL;
1949        }
1950        return (error);
1951}
1952
1953#ifndef __rtems__
1954int
1955getsockname(td, uap)
1956        struct thread *td;
1957        struct getsockname_args *uap;
1958{
1959
1960        return (getsockname1(td, uap, 0));
1961}
1962
1963#ifdef COMPAT_OLDSOCK
1964int
1965ogetsockname(td, uap)
1966        struct thread *td;
1967        struct getsockname_args *uap;
1968{
1969
1970        return (getsockname1(td, uap, 1));
1971}
1972#endif /* COMPAT_OLDSOCK */
1973#endif /* __rtems__ */
1974
1975#ifdef __rtems__
1976static int
1977kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
1978    socklen_t *alen);
1979#endif /* __rtems__ */
1980/*
1981 * getpeername1() - Get name of peer for connected socket.
1982 */
1983/* ARGSUSED */
1984static int
1985getpeername1(td, uap, compat)
1986        struct thread *td;
1987        struct getpeername_args /* {
1988                int     fdes;
1989                struct sockaddr * __restrict    asa;
1990                socklen_t * __restrict  alen;
1991        } */ *uap;
1992        int compat;
1993{
1994        struct sockaddr *sa;
1995        socklen_t len;
1996        int error;
1997
1998        error = copyin(uap->alen, &len, sizeof (len));
1999        if (error)
2000                return (error);
2001
2002        error = kern_getpeername(td, uap->fdes, &sa, &len);
2003        if (error)
2004                return (error);
2005
2006        if (len != 0) {
2007#ifdef COMPAT_OLDSOCK
2008                if (compat)
2009                        ((struct osockaddr *)sa)->sa_family = sa->sa_family;
2010#endif
2011                error = copyout(sa, uap->asa, (u_int)len);
2012        }
2013        free(sa, M_SONAME);
2014        if (error == 0)
2015                error = copyout(&len, uap->alen, sizeof(len));
2016        return (error);
2017}
2018#ifdef __rtems__
2019int
2020getpeername(int socket, struct sockaddr *__restrict address,
2021    socklen_t *__restrict address_len)
2022{
2023        struct thread *td = rtems_bsd_get_curthread_or_null();
2024        struct getpeername_args ua = {
2025                .fdes = socket,
2026                .asa = address,
2027                .alen = address_len
2028        };
2029        int error;
2030
2031        if (td != NULL) {
2032                error = getpeername1(td, &ua);
2033        } else {
2034                error = ENOMEM;
2035        }
2036
2037        return rtems_bsd_error_to_status_and_errno(error);
2038}
2039#endif /* __rtems__ */
2040
2041int
2042kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
2043    socklen_t *alen)
2044{
2045        struct socket *so;
2046        struct file *fp;
2047        socklen_t len;
2048        int error;
2049
2050        if (*alen < 0)
2051                return (EINVAL);
2052
2053        AUDIT_ARG_FD(fd);
2054        error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
2055        if (error)
2056                return (error);
2057        so = fp->f_data;
2058        if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
2059                error = ENOTCONN;
2060                goto done;
2061        }
2062        *sa = NULL;
2063        CURVNET_SET(so->so_vnet);
2064        error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
2065        CURVNET_RESTORE();
2066        if (error)
2067                goto bad;
2068        if (*sa == NULL)
2069                len = 0;
2070        else
2071                len = MIN(*alen, (*sa)->sa_len);
2072        *alen = len;
2073#ifdef KTRACE
2074        if (KTRPOINT(td, KTR_STRUCT))
2075                ktrsockaddr(*sa);
2076#endif
2077bad:
2078        if (error && *sa) {
2079                free(*sa, M_SONAME);
2080                *sa = NULL;
2081        }
2082done:
2083        fdrop(fp, td);
2084        return (error);
2085}
2086
2087#ifndef __rtems__
2088int
2089getpeername(td, uap)
2090        struct thread *td;
2091        struct getpeername_args *uap;
2092{
2093
2094        return (getpeername1(td, uap, 0));
2095}
2096
2097#ifdef COMPAT_OLDSOCK
2098int
2099ogetpeername(td, uap)
2100        struct thread *td;
2101        struct ogetpeername_args *uap;
2102{
2103
2104        /* XXX uap should have type `getpeername_args *' to begin with. */
2105        return (getpeername1(td, (struct getpeername_args *)uap, 1));
2106}
2107#endif /* COMPAT_OLDSOCK */
2108#endif /* __rtems__ */
2109
2110int
2111sockargs(mp, buf, buflen, type)
2112        struct mbuf **mp;
2113        caddr_t buf;
2114        int buflen, type;
2115{
2116        struct sockaddr *sa;
2117        struct mbuf *m;
2118        int error;
2119
2120        if ((u_int)buflen > MLEN) {
2121#ifdef COMPAT_OLDSOCK
2122                if (type == MT_SONAME && (u_int)buflen <= 112)
2123                        buflen = MLEN;          /* unix domain compat. hack */
2124                else
2125#endif
2126                        if ((u_int)buflen > MCLBYTES)
2127                                return (EINVAL);
2128        }
2129        m = m_get(M_WAIT, type);
2130        if ((u_int)buflen > MLEN)
2131                MCLGET(m, M_WAIT);
2132        m->m_len = buflen;
2133        error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
2134        if (error)
2135                (void) m_free(m);
2136        else {
2137                *mp = m;
2138                if (type == MT_SONAME) {
2139                        sa = mtod(m, struct sockaddr *);
2140
2141#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
2142                        if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
2143                                sa->sa_family = sa->sa_len;
2144#endif
2145                        sa->sa_len = buflen;
2146                }
2147        }
2148        return (error);
2149}
2150
2151int
2152getsockaddr(namp, uaddr, len)
2153        struct sockaddr **namp;
2154        caddr_t uaddr;
2155        size_t len;
2156{
2157        struct sockaddr *sa;
2158        int error;
2159
2160        if (len > SOCK_MAXADDRLEN)
2161                return (ENAMETOOLONG);
2162        if (len < offsetof(struct sockaddr, sa_data[0]))
2163                return (EINVAL);
2164        sa = malloc(len, M_SONAME, M_WAITOK);
2165        error = copyin(uaddr, sa, len);
2166        if (error) {
2167                free(sa, M_SONAME);
2168        } else {
2169#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
2170                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
2171                        sa->sa_family = sa->sa_len;
2172#endif
2173                sa->sa_len = len;
2174                *namp = sa;
2175        }
2176        return (error);
2177}
2178
2179#ifndef __rtems__
2180#include <sys/condvar.h>
2181
2182struct sendfile_sync {
2183        struct mtx      mtx;
2184        struct cv       cv;
2185        unsigned        count;
2186};
2187
2188/*
2189 * Detach mapped page and release resources back to the system.
2190 */
2191void
2192sf_buf_mext(void *addr, void *args)
2193{
2194        vm_page_t m;
2195        struct sendfile_sync *sfs;
2196
2197        m = sf_buf_page(args);
2198        sf_buf_free(args);
2199        vm_page_lock_queues();
2200        vm_page_unwire(m, 0);
2201        /*
2202         * Check for the object going away on us. This can
2203         * happen since we don't hold a reference to it.
2204         * If so, we're responsible for freeing the page.
2205         */
2206        if (m->wire_count == 0 && m->object == NULL)
2207                vm_page_free(m);
2208        vm_page_unlock_queues();
2209        if (addr == NULL)
2210                return;
2211        sfs = addr;
2212        mtx_lock(&sfs->mtx);
2213        KASSERT(sfs->count> 0, ("Sendfile sync botchup count == 0"));
2214        if (--sfs->count == 0)
2215                cv_signal(&sfs->cv);
2216        mtx_unlock(&sfs->mtx);
2217}
2218
2219/*
2220 * sendfile(2)
2221 *
2222 * int sendfile(int fd, int s, off_t offset, size_t nbytes,
2223 *       struct sf_hdtr *hdtr, off_t *sbytes, int flags)
2224 *
2225 * Send a file specified by 'fd' and starting at 'offset' to a socket
2226 * specified by 's'. Send only 'nbytes' of the file or until EOF if nbytes ==
2227 * 0.  Optionally add a header and/or trailer to the socket output.  If
2228 * specified, write the total number of bytes sent into *sbytes.
2229 */
2230int
2231sendfile(struct thread *td, struct sendfile_args *uap)
2232{
2233
2234        return (do_sendfile(td, uap, 0));
2235}
2236
2237static int
2238do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
2239{
2240        struct sf_hdtr hdtr;
2241        struct uio *hdr_uio, *trl_uio;
2242        int error;
2243
2244        hdr_uio = trl_uio = NULL;
2245
2246        if (uap->hdtr != NULL) {
2247                error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
2248                if (error)
2249                        goto out;
2250                if (hdtr.headers != NULL) {
2251                        error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio);
2252                        if (error)
2253                                goto out;
2254                }
2255                if (hdtr.trailers != NULL) {
2256                        error = copyinuio(hdtr.trailers, hdtr.trl_cnt, &trl_uio);
2257                        if (error)
2258                                goto out;
2259
2260                }
2261        }
2262
2263        error = kern_sendfile(td, uap, hdr_uio, trl_uio, compat);
2264out:
2265        if (hdr_uio)
2266                free(hdr_uio, M_IOV);
2267        if (trl_uio)
2268                free(trl_uio, M_IOV);
2269        return (error);
2270}
2271
2272#ifdef COMPAT_FREEBSD4
2273int
2274freebsd4_sendfile(struct thread *td, struct freebsd4_sendfile_args *uap)
2275{
2276        struct sendfile_args args;
2277
2278        args.fd = uap->fd;
2279        args.s = uap->s;
2280        args.offset = uap->offset;
2281        args.nbytes = uap->nbytes;
2282        args.hdtr = uap->hdtr;
2283        args.sbytes = uap->sbytes;
2284        args.flags = uap->flags;
2285
2286        return (do_sendfile(td, &args, 1));
2287}
2288#endif /* COMPAT_FREEBSD4 */
2289
2290int
2291kern_sendfile(struct thread *td, struct sendfile_args *uap,
2292    struct uio *hdr_uio, struct uio *trl_uio, int compat)
2293{
2294        struct file *sock_fp;
2295        struct vnode *vp;
2296        struct vm_object *obj = NULL;
2297        struct socket *so = NULL;
2298        struct mbuf *m = NULL;
2299        struct sf_buf *sf;
2300        struct vm_page *pg;
2301        off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0;
2302        int error, hdrlen = 0, mnw = 0;
2303        int vfslocked;
2304        struct sendfile_sync *sfs = NULL;
2305
2306        /*
2307         * The file descriptor must be a regular file and have a
2308         * backing VM object.
2309         * File offset must be positive.  If it goes beyond EOF
2310         * we send only the header/trailer and no payload data.
2311         */
2312        AUDIT_ARG_FD(uap->fd);
2313        if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
2314                goto out;
2315        vfslocked = VFS_LOCK_GIANT(vp->v_mount);
2316        vn_lock(vp, LK_SHARED | LK_RETRY);
2317        if (vp->v_type == VREG) {
2318                obj = vp->v_object;
2319                if (obj != NULL) {
2320                        /*
2321                         * Temporarily increase the backing VM
2322                         * object's reference count so that a forced
2323                         * reclamation of its vnode does not
2324                         * immediately destroy it.
2325                         */
2326                        VM_OBJECT_LOCK(obj);
2327                        if ((obj->flags & OBJ_DEAD) == 0) {
2328                                vm_object_reference_locked(obj);
2329                                VM_OBJECT_UNLOCK(obj);
2330                        } else {
2331                                VM_OBJECT_UNLOCK(obj);
2332                                obj = NULL;
2333                        }
2334                }
2335        }
2336        VOP_UNLOCK(vp, 0);
2337        VFS_UNLOCK_GIANT(vfslocked);
2338        if (obj == NULL) {
2339                error = EINVAL;
2340                goto out;
2341        }
2342        if (uap->offset < 0) {
2343                error = EINVAL;
2344                goto out;
2345        }
2346
2347        /*
2348         * The socket must be a stream socket and connected.
2349         * Remember if it a blocking or non-blocking socket.
2350         */
2351        if ((error = getsock(td->td_proc->p_fd, uap->s, &sock_fp,
2352            NULL)) != 0)
2353                goto out;
2354        so = sock_fp->f_data;
2355        if (so->so_type != SOCK_STREAM) {
2356                error = EINVAL;
2357                goto out;
2358        }
2359        if ((so->so_state & SS_ISCONNECTED) == 0) {
2360                error = ENOTCONN;
2361                goto out;
2362        }
2363        /*
2364         * Do not wait on memory allocations but return ENOMEM for
2365         * caller to retry later.
2366         * XXX: Experimental.
2367         */
2368        if (uap->flags & SF_MNOWAIT)
2369                mnw = 1;
2370
2371        if (uap->flags & SF_SYNC) {
2372                sfs = malloc(sizeof *sfs, M_TEMP, M_WAITOK);
2373                memset(sfs, 0, sizeof *sfs);
2374                mtx_init(&sfs->mtx, "sendfile", NULL, MTX_DEF);
2375                cv_init(&sfs->cv, "sendfile");
2376        }
2377
2378#ifdef MAC
2379        error = mac_socket_check_send(td->td_ucred, so);
2380        if (error)
2381                goto out;
2382#endif
2383
2384        /* If headers are specified copy them into mbufs. */
2385        if (hdr_uio != NULL) {
2386                hdr_uio->uio_td = td;
2387                hdr_uio->uio_rw = UIO_WRITE;
2388                if (hdr_uio->uio_resid > 0) {
2389                        /*
2390                         * In FBSD < 5.0 the nbytes to send also included
2391                         * the header.  If compat is specified subtract the
2392                         * header size from nbytes.
2393                         */
2394                        if (compat) {
2395                                if (uap->nbytes > hdr_uio->uio_resid)
2396                                        uap->nbytes -= hdr_uio->uio_resid;
2397                                else
2398                                        uap->nbytes = 0;
2399                        }
2400                        m = m_uiotombuf(hdr_uio, (mnw ? M_NOWAIT : M_WAITOK),
2401                            0, 0, 0);
2402                        if (m == NULL) {
2403                                error = mnw ? EAGAIN : ENOBUFS;
2404                                goto out;
2405                        }
2406                        hdrlen = m_length(m, NULL);
2407                }
2408        }
2409
2410        /*
2411         * Protect against multiple writers to the socket.
2412         *
2413         * XXXRW: Historically this has assumed non-interruptibility, so now
2414         * we implement that, but possibly shouldn't.
2415         */
2416        (void)sblock(&so->so_snd, SBL_WAIT | SBL_NOINTR);
2417
2418        /*
2419         * Loop through the pages of the file, starting with the requested
2420         * offset. Get a file page (do I/O if necessary), map the file page
2421         * into an sf_buf, attach an mbuf header to the sf_buf, and queue
2422         * it on the socket.
2423         * This is done in two loops.  The inner loop turns as many pages
2424         * as it can, up to available socket buffer space, without blocking
2425         * into mbufs to have it bulk delivered into the socket send buffer.
2426         * The outer loop checks the state and available space of the socket
2427         * and takes care of the overall progress.
2428         */
2429        for (off = uap->offset, rem = uap->nbytes; ; ) {
2430                int loopbytes = 0;
2431                int space = 0;
2432                int done = 0;
2433
2434                /*
2435                 * Check the socket state for ongoing connection,
2436                 * no errors and space in socket buffer.
2437                 * If space is low allow for the remainder of the
2438                 * file to be processed if it fits the socket buffer.
2439                 * Otherwise block in waiting for sufficient space
2440                 * to proceed, or if the socket is nonblocking, return
2441                 * to userland with EAGAIN while reporting how far
2442                 * we've come.
2443                 * We wait until the socket buffer has significant free
2444                 * space to do bulk sends.  This makes good use of file
2445                 * system read ahead and allows packet segmentation
2446                 * offloading hardware to take over lots of work.  If
2447                 * we were not careful here we would send off only one
2448                 * sfbuf at a time.
2449                 */
2450                SOCKBUF_LOCK(&so->so_snd);
2451                if (so->so_snd.sb_lowat < so->so_snd.sb_hiwat / 2)
2452                        so->so_snd.sb_lowat = so->so_snd.sb_hiwat / 2;
2453retry_space:
2454                if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
2455                        error = EPIPE;
2456                        SOCKBUF_UNLOCK(&so->so_snd);
2457                        goto done;
2458                } else if (so->so_error) {
2459                        error = so->so_error;
2460                        so->so_error = 0;
2461                        SOCKBUF_UNLOCK(&so->so_snd);
2462                        goto done;
2463                }
2464                space = sbspace(&so->so_snd);
2465                if (space < rem &&
2466                    (space <= 0 ||
2467                     space < so->so_snd.sb_lowat)) {
2468                        if (so->so_state & SS_NBIO) {
2469                                SOCKBUF_UNLOCK(&so->so_snd);
2470                                error = EAGAIN;
2471                                goto done;
2472                        }
2473                        /*
2474                         * sbwait drops the lock while sleeping.
2475                         * When we loop back to retry_space the
2476                         * state may have changed and we retest
2477                         * for it.
2478                         */
2479                        error = sbwait(&so->so_snd);
2480                        /*
2481                         * An error from sbwait usually indicates that we've
2482                         * been interrupted by a signal. If we've sent anything
2483                         * then return bytes sent, otherwise return the error.
2484                         */
2485                        if (error) {
2486                                SOCKBUF_UNLOCK(&so->so_snd);
2487                                goto done;
2488                        }
2489                        goto retry_space;
2490                }
2491                SOCKBUF_UNLOCK(&so->so_snd);
2492
2493                /*
2494                 * Reduce space in the socket buffer by the size of
2495                 * the header mbuf chain.
2496                 * hdrlen is set to 0 after the first loop.
2497                 */
2498                space -= hdrlen;
2499
2500                /*
2501                 * Loop and construct maximum sized mbuf chain to be bulk
2502                 * dumped into socket buffer.
2503                 */
2504                while(space > loopbytes) {
2505                        vm_pindex_t pindex;
2506                        vm_offset_t pgoff;
2507                        struct mbuf *m0;
2508
2509                        VM_OBJECT_LOCK(obj);
2510                        /*
2511                         * Calculate the amount to transfer.
2512                         * Not to exceed a page, the EOF,
2513                         * or the passed in nbytes.
2514                         */
2515                        pgoff = (vm_offset_t)(off & PAGE_MASK);
2516                        xfsize = omin(PAGE_SIZE - pgoff,
2517                            obj->un_pager.vnp.vnp_size - uap->offset -
2518                            fsbytes - loopbytes);
2519                        if (uap->nbytes)
2520                                rem = (uap->nbytes - fsbytes - loopbytes);
2521                        else
2522                                rem = obj->un_pager.vnp.vnp_size -
2523                                    uap->offset - fsbytes - loopbytes;
2524                        xfsize = omin(rem, xfsize);
2525                        xfsize = omin(space - loopbytes, xfsize);
2526                        if (xfsize <= 0) {
2527                                VM_OBJECT_UNLOCK(obj);
2528                                done = 1;               /* all data sent */
2529                                break;
2530                        }
2531
2532                        /*
2533                         * Attempt to look up the page.  Allocate
2534                         * if not found or wait and loop if busy.
2535                         */
2536                        pindex = OFF_TO_IDX(off);
2537                        pg = vm_page_grab(obj, pindex, VM_ALLOC_NOBUSY |
2538                            VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_RETRY);
2539
2540                        /*
2541                         * Check if page is valid for what we need,
2542                         * otherwise initiate I/O.
2543                         * If we already turned some pages into mbufs,
2544                         * send them off before we come here again and
2545                         * block.
2546                         */
2547                        if (pg->valid && vm_page_is_valid(pg, pgoff, xfsize))
2548                                VM_OBJECT_UNLOCK(obj);
2549                        else if (m != NULL)
2550                                error = EAGAIN; /* send what we already got */
2551                        else if (uap->flags & SF_NODISKIO)
2552                                error = EBUSY;
2553                        else {
2554                                int bsize, resid;
2555
2556                                /*
2557                                 * Ensure that our page is still around
2558                                 * when the I/O completes.
2559                                 */
2560                                vm_page_io_start(pg);
2561                                VM_OBJECT_UNLOCK(obj);
2562
2563                                /*
2564                                 * Get the page from backing store.
2565                                 */
2566                                vfslocked = VFS_LOCK_GIANT(vp->v_mount);
2567                                error = vn_lock(vp, LK_SHARED);
2568                                if (error != 0)
2569                                        goto after_read;
2570                                bsize = vp->v_mount->mnt_stat.f_iosize;
2571
2572                                /*
2573                                 * XXXMAC: Because we don't have fp->f_cred
2574                                 * here, we pass in NOCRED.  This is probably
2575                                 * wrong, but is consistent with our original
2576                                 * implementation.
2577                                 */
2578                                error = vn_rdwr(UIO_READ, vp, NULL, MAXBSIZE,
2579                                    trunc_page(off), UIO_NOCOPY, IO_NODELOCKED |
2580                                    IO_VMIO | ((MAXBSIZE / bsize) << IO_SEQSHIFT),
2581                                    td->td_ucred, NOCRED, &resid, td);
2582                                VOP_UNLOCK(vp, 0);
2583                        after_read:
2584                                VFS_UNLOCK_GIANT(vfslocked);
2585                                VM_OBJECT_LOCK(obj);
2586                                vm_page_io_finish(pg);
2587                                if (!error)
2588                                        VM_OBJECT_UNLOCK(obj);
2589                                mbstat.sf_iocnt++;
2590                        }
2591                        if (error) {
2592                                vm_page_lock_queues();
2593                                vm_page_unwire(pg, 0);
2594                                /*
2595                                 * See if anyone else might know about
2596                                 * this page.  If not and it is not valid,
2597                                 * then free it.
2598                                 */
2599                                if (pg->wire_count == 0 && pg->valid == 0 &&
2600                                    pg->busy == 0 && !(pg->oflags & VPO_BUSY) &&
2601                                    pg->hold_count == 0) {
2602                                        vm_page_free(pg);
2603                                }
2604                                vm_page_unlock_queues();
2605                                VM_OBJECT_UNLOCK(obj);
2606                                if (error == EAGAIN)
2607                                        error = 0;      /* not a real error */
2608                                break;
2609                        }
2610
2611                        /*
2612                         * Get a sendfile buf.  We usually wait as long
2613                         * as necessary, but this wait can be interrupted.
2614                         */
2615                        if ((sf = sf_buf_alloc(pg,
2616                            (mnw ? SFB_NOWAIT : SFB_CATCH))) == NULL) {
2617                                mbstat.sf_allocfail++;
2618                                vm_page_lock_queues();
2619                                vm_page_unwire(pg, 0);
2620                                /*
2621                                 * XXX: Not same check as above!?
2622                                 */
2623                                if (pg->wire_count == 0 && pg->object == NULL)
2624                                        vm_page_free(pg);
2625                                vm_page_unlock_queues();
2626                                error = (mnw ? EAGAIN : EINTR);
2627                                break;
2628                        }
2629
2630                        /*
2631                         * Get an mbuf and set it up as having
2632                         * external storage.
2633                         */
2634                        m0 = m_get((mnw ? M_NOWAIT : M_WAITOK), MT_DATA);
2635                        if (m0 == NULL) {
2636                                error = (mnw ? EAGAIN : ENOBUFS);
2637                                sf_buf_mext((void *)sf_buf_kva(sf), sf);
2638                                break;
2639                        }
2640                        MEXTADD(m0, sf_buf_kva(sf), PAGE_SIZE, sf_buf_mext,
2641                            sfs, sf, M_RDONLY, EXT_SFBUF);
2642                        m0->m_data = (char *)sf_buf_kva(sf) + pgoff;
2643                        m0->m_len = xfsize;
2644
2645                        /* Append to mbuf chain. */
2646                        if (m != NULL)
2647                                m_cat(m, m0);
2648                        else
2649                                m = m0;
2650
2651                        /* Keep track of bits processed. */
2652                        loopbytes += xfsize;
2653                        off += xfsize;
2654
2655                        if (sfs != NULL) {
2656                                mtx_lock(&sfs->mtx);
2657                                sfs->count++;
2658                                mtx_unlock(&sfs->mtx);
2659                        }
2660                }
2661
2662                /* Add the buffer chain to the socket buffer. */
2663                if (m != NULL) {
2664                        int mlen, err;
2665
2666                        mlen = m_length(m, NULL);
2667                        SOCKBUF_LOCK(&so->so_snd);
2668                        if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
2669                                error = EPIPE;
2670                                SOCKBUF_UNLOCK(&so->so_snd);
2671                                goto done;
2672                        }
2673                        SOCKBUF_UNLOCK(&so->so_snd);
2674                        CURVNET_SET(so->so_vnet);
2675                        /* Avoid error aliasing. */
2676                        err = (*so->so_proto->pr_usrreqs->pru_send)
2677                                    (so, 0, m, NULL, NULL, td);
2678                        CURVNET_RESTORE();
2679                        if (err == 0) {
2680                                /*
2681                                 * We need two counters to get the
2682                                 * file offset and nbytes to send
2683                                 * right:
2684                                 * - sbytes contains the total amount
2685                                 *   of bytes sent, including headers.
2686                                 * - fsbytes contains the total amount
2687                                 *   of bytes sent from the file.
2688                                 */
2689                                sbytes += mlen;
2690                                fsbytes += mlen;
2691                                if (hdrlen) {
2692                                        fsbytes -= hdrlen;
2693                                        hdrlen = 0;
2694                                }
2695                        } else if (error == 0)
2696                                error = err;
2697                        m = NULL;       /* pru_send always consumes */
2698                }
2699
2700                /* Quit outer loop on error or when we're done. */
2701                if (done)
2702                        break;
2703                if (error)
2704                        goto done;
2705        }
2706
2707        /*
2708         * Send trailers. Wimp out and use writev(2).
2709         */
2710        if (trl_uio != NULL) {
2711                sbunlock(&so->so_snd);
2712                error = kern_writev(td, uap->s, trl_uio);
2713                if (error == 0)
2714                        sbytes += td->td_retval[0];
2715                goto out;
2716        }
2717
2718done:
2719        sbunlock(&so->so_snd);
2720out:
2721        /*
2722         * If there was no error we have to clear td->td_retval[0]
2723         * because it may have been set by writev.
2724         */
2725        if (error == 0) {
2726                td->td_retval[0] = 0;
2727        }
2728        if (uap->sbytes != NULL) {
2729                copyout(&sbytes, uap->sbytes, sizeof(off_t));
2730        }
2731        if (obj != NULL)
2732                vm_object_deallocate(obj);
2733        if (vp != NULL) {
2734                vfslocked = VFS_LOCK_GIANT(vp->v_mount);
2735                vrele(vp);
2736                VFS_UNLOCK_GIANT(vfslocked);
2737        }
2738        if (so)
2739                fdrop(sock_fp, td);
2740        if (m)
2741                m_freem(m);
2742
2743        if (sfs != NULL) {
2744                mtx_lock(&sfs->mtx);
2745                if (sfs->count != 0)
2746                        cv_wait(&sfs->cv, &sfs->mtx);
2747                KASSERT(sfs->count == 0, ("sendfile sync still busy"));
2748                cv_destroy(&sfs->cv);
2749                mtx_destroy(&sfs->mtx);
2750                free(sfs, M_TEMP);
2751        }
2752
2753        if (error == ERESTART)
2754                error = EINTR;
2755
2756        return (error);
2757}
2758
2759/*
2760 * SCTP syscalls.
2761 * Functionality only compiled in if SCTP is defined in the kernel Makefile,
2762 * otherwise all return EOPNOTSUPP.
2763 * XXX: We should make this loadable one day.
2764 */
2765int
2766sctp_peeloff(td, uap)
2767        struct thread *td;
2768        struct sctp_peeloff_args /* {
2769                int     sd;
2770                caddr_t name;
2771        } */ *uap;
2772{
2773#if (defined(INET) || defined(INET6)) && defined(SCTP)
2774        struct filedesc *fdp;
2775        struct file *nfp = NULL;
2776        int error;
2777        struct socket *head, *so;
2778        int fd;
2779        u_int fflag;
2780
2781        fdp = td->td_proc->p_fd;
2782        AUDIT_ARG_FD(uap->sd);
2783        error = fgetsock(td, uap->sd, &head, &fflag);
2784        if (error)
2785                goto done2;
2786        error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
2787        if (error)
2788                goto done2;
2789        /*
2790         * At this point we know we do have a assoc to pull
2791         * we proceed to get the fd setup. This may block
2792         * but that is ok.
2793         */
2794
2795        error = falloc(td, &nfp, &fd);
2796        if (error)
2797                goto done;
2798        td->td_retval[0] = fd;
2799
2800        CURVNET_SET(head->so_vnet);
2801        so = sonewconn(head, SS_ISCONNECTED);
2802        if (so == NULL)
2803                goto noconnection;
2804        /*
2805         * Before changing the flags on the socket, we have to bump the
2806         * reference count.  Otherwise, if the protocol calls sofree(),
2807         * the socket will be released due to a zero refcount.
2808         */
2809        SOCK_LOCK(so);
2810        soref(so);                      /* file descriptor reference */
2811        SOCK_UNLOCK(so);
2812
2813        ACCEPT_LOCK();
2814
2815        TAILQ_REMOVE(&head->so_comp, so, so_list);
2816        head->so_qlen--;
2817        so->so_state |= (head->so_state & SS_NBIO);
2818        so->so_state &= ~SS_NOFDREF;
2819        so->so_qstate &= ~SQ_COMP;
2820        so->so_head = NULL;
2821        ACCEPT_UNLOCK();
2822        finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
2823        error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
2824        if (error)
2825                goto noconnection;
2826        if (head->so_sigio != NULL)
2827                fsetown(fgetown(&head->so_sigio), &so->so_sigio);
2828
2829noconnection:
2830        /*
2831         * close the new descriptor, assuming someone hasn't ripped it
2832         * out from under us.
2833         */
2834        if (error)
2835                fdclose(fdp, nfp, fd, td);
2836
2837        /*
2838         * Release explicitly held references before returning.
2839         */
2840        CURVNET_RESTORE();
2841done:
2842        if (nfp != NULL)
2843                fdrop(nfp, td);
2844        fputsock(head);
2845done2:
2846        return (error);
2847#else  /* SCTP */
2848        return (EOPNOTSUPP);
2849#endif /* SCTP */
2850}
2851
2852int
2853sctp_generic_sendmsg (td, uap)
2854        struct thread *td;
2855        struct sctp_generic_sendmsg_args /* {
2856                int sd,
2857                caddr_t msg,
2858                int mlen,
2859                caddr_t to,
2860                __socklen_t tolen,
2861                struct sctp_sndrcvinfo *sinfo,
2862                int flags
2863        } */ *uap;
2864{
2865#if (defined(INET) || defined(INET6)) && defined(SCTP)
2866        struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
2867        struct socket *so;
2868        struct file *fp = NULL;
2869        int error = 0, len;
2870        struct sockaddr *to = NULL;
2871#ifdef KTRACE
2872        struct uio *ktruio = NULL;
2873#endif
2874        struct uio auio;
2875        struct iovec iov[1];
2876
2877        if (uap->sinfo) {
2878                error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
2879                if (error)
2880                        return (error);
2881                u_sinfo = &sinfo;
2882        }
2883        if (uap->tolen) {
2884                error = getsockaddr(&to, uap->to, uap->tolen);
2885                if (error) {
2886                        to = NULL;
2887                        goto sctp_bad2;
2888                }
2889        }
2890
2891        AUDIT_ARG_FD(uap->sd);
2892        error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
2893        if (error)
2894                goto sctp_bad;
2895#ifdef KTRACE
2896        if (to && (KTRPOINT(td, KTR_STRUCT)))
2897                ktrsockaddr(to);
2898#endif
2899
2900        iov[0].iov_base = uap->msg;
2901        iov[0].iov_len = uap->mlen;
2902
2903        so = (struct socket *)fp->f_data;
2904#ifdef MAC
2905        error = mac_socket_check_send(td->td_ucred, so);
2906        if (error)
2907                goto sctp_bad;
2908#endif /* MAC */
2909
2910        auio.uio_iov =  iov;
2911        auio.uio_iovcnt = 1;
2912        auio.uio_segflg = UIO_USERSPACE;
2913        auio.uio_rw = UIO_WRITE;
2914        auio.uio_td = td;
2915        auio.uio_offset = 0;                    /* XXX */
2916        auio.uio_resid = 0;
2917        len = auio.uio_resid = uap->mlen;
2918        CURVNET_SET(so->so_vnet);
2919        error = sctp_lower_sosend(so, to, &auio,
2920                    (struct mbuf *)NULL, (struct mbuf *)NULL,
2921                    uap->flags, u_sinfo, td);
2922        CURVNET_RESTORE();
2923        if (error) {
2924                if (auio.uio_resid != len && (error == ERESTART ||
2925                    error == EINTR || error == EWOULDBLOCK))
2926                        error = 0;
2927                /* Generation of SIGPIPE can be controlled per socket. */
2928                if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
2929                    !(uap->flags & MSG_NOSIGNAL)) {
2930                        PROC_LOCK(td->td_proc);
2931                        tdksignal(td, SIGPIPE, NULL);
2932                        PROC_UNLOCK(td->td_proc);
2933                }
2934        }
2935        if (error == 0)
2936                td->td_retval[0] = len - auio.uio_resid;
2937#ifdef KTRACE
2938        if (ktruio != NULL) {
2939                ktruio->uio_resid = td->td_retval[0];
2940                ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
2941        }
2942#endif /* KTRACE */
2943sctp_bad:
2944        if (fp)
2945                fdrop(fp, td);
2946sctp_bad2:
2947        if (to)
2948                free(to, M_SONAME);
2949        return (error);
2950#else  /* SCTP */
2951        return (EOPNOTSUPP);
2952#endif /* SCTP */
2953}
2954
2955int
2956sctp_generic_sendmsg_iov(td, uap)
2957        struct thread *td;
2958        struct sctp_generic_sendmsg_iov_args /* {
2959                int sd,
2960                struct iovec *iov,
2961                int iovlen,
2962                caddr_t to,
2963                __socklen_t tolen,
2964                struct sctp_sndrcvinfo *sinfo,
2965                int flags
2966        } */ *uap;
2967{
2968#if (defined(INET) || defined(INET6)) && defined(SCTP)
2969        struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
2970        struct socket *so;
2971        struct file *fp = NULL;
2972        int error=0, len, i;
2973        struct sockaddr *to = NULL;
2974#ifdef KTRACE
2975        struct uio *ktruio = NULL;
2976#endif
2977        struct uio auio;
2978        struct iovec *iov, *tiov;
2979
2980        if (uap->sinfo) {
2981                error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
2982                if (error)
2983                        return (error);
2984                u_sinfo = &sinfo;
2985        }
2986        if (uap->tolen) {
2987                error = getsockaddr(&to, uap->to, uap->tolen);
2988                if (error) {
2989                        to = NULL;
2990                        goto sctp_bad2;
2991                }
2992        }
2993
2994        AUDIT_ARG_FD(uap->sd);
2995        error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
2996        if (error)
2997                goto sctp_bad1;
2998
2999#ifdef COMPAT_FREEBSD32
3000        if (SV_CURPROC_FLAG(SV_ILP32))
3001                error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
3002                    uap->iovlen, &iov, EMSGSIZE);
3003        else
3004#endif
3005                error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
3006        if (error)
3007                goto sctp_bad1;
3008#ifdef KTRACE
3009        if (to && (KTRPOINT(td, KTR_STRUCT)))
3010                ktrsockaddr(to);
3011#endif
3012
3013        so = (struct socket *)fp->f_data;
3014#ifdef MAC
3015        error = mac_socket_check_send(td->td_ucred, so);
3016        if (error)
3017                goto sctp_bad;
3018#endif /* MAC */
3019
3020        auio.uio_iov = iov;
3021        auio.uio_iovcnt = uap->iovlen;
3022        auio.uio_segflg = UIO_USERSPACE;
3023        auio.uio_rw = UIO_WRITE;
3024        auio.uio_td = td;
3025        auio.uio_offset = 0;                    /* XXX */
3026        auio.uio_resid = 0;
3027        tiov = iov;
3028        for (i = 0; i <uap->iovlen; i++, tiov++) {
3029                if ((auio.uio_resid += tiov->iov_len) < 0) {
3030                        error = EINVAL;
3031                        goto sctp_bad;
3032                }
3033        }
3034        len = auio.uio_resid;
3035        CURVNET_SET(so->so_vnet);
3036        error = sctp_lower_sosend(so, to, &auio,
3037                    (struct mbuf *)NULL, (struct mbuf *)NULL,
3038                    uap->flags, u_sinfo, td);
3039        CURVNET_RESTORE();
3040        if (error) {
3041                if (auio.uio_resid != len && (error == ERESTART ||
3042                    error == EINTR || error == EWOULDBLOCK))
3043                        error = 0;
3044                /* Generation of SIGPIPE can be controlled per socket */
3045                if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
3046                    !(uap->flags & MSG_NOSIGNAL)) {
3047                        PROC_LOCK(td->td_proc);
3048                        tdksignal(td, SIGPIPE, NULL);
3049                        PROC_UNLOCK(td->td_proc);
3050                }
3051        }
3052        if (error == 0)
3053                td->td_retval[0] = len - auio.uio_resid;
3054#ifdef KTRACE
3055        if (ktruio != NULL) {
3056                ktruio->uio_resid = td->td_retval[0];
3057                ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
3058        }
3059#endif /* KTRACE */
3060sctp_bad:
3061        free(iov, M_IOV);
3062sctp_bad1:
3063        if (fp)
3064                fdrop(fp, td);
3065sctp_bad2:
3066        if (to)
3067                free(to, M_SONAME);
3068        return (error);
3069#else  /* SCTP */
3070        return (EOPNOTSUPP);
3071#endif /* SCTP */
3072}
3073
3074int
3075sctp_generic_recvmsg(td, uap)
3076        struct thread *td;
3077        struct sctp_generic_recvmsg_args /* {
3078                int sd,
3079                struct iovec *iov,
3080                int iovlen,
3081                struct sockaddr *from,
3082                __socklen_t *fromlenaddr,
3083                struct sctp_sndrcvinfo *sinfo,
3084                int *msg_flags
3085        } */ *uap;
3086{
3087#if (defined(INET) || defined(INET6)) && defined(SCTP)
3088        u_int8_t sockbufstore[256];
3089        struct uio auio;
3090        struct iovec *iov, *tiov;
3091        struct sctp_sndrcvinfo sinfo;
3092        struct socket *so;
3093        struct file *fp = NULL;
3094        struct sockaddr *fromsa;
3095        int fromlen;
3096        int len, i, msg_flags;
3097        int error = 0;
3098#ifdef KTRACE
3099        struct uio *ktruio = NULL;
3100#endif
3101
3102        AUDIT_ARG_FD(uap->sd);
3103        error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
3104        if (error) {
3105                return (error);
3106        }
3107#ifdef COMPAT_FREEBSD32
3108        if (SV_CURPROC_FLAG(SV_ILP32))
3109                error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
3110                    uap->iovlen, &iov, EMSGSIZE);
3111        else
3112#endif
3113                error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
3114        if (error)
3115                goto out1;
3116
3117        so = fp->f_data;
3118#ifdef MAC
3119        error = mac_socket_check_receive(td->td_ucred, so);
3120        if (error) {
3121                goto out;
3122        }
3123#endif /* MAC */
3124
3125        if (uap->fromlenaddr) {
3126                error = copyin(uap->fromlenaddr,
3127                    &fromlen, sizeof (fromlen));
3128                if (error) {
3129                        goto out;
3130                }
3131        } else {
3132                fromlen = 0;
3133        }
3134        if (uap->msg_flags) {
3135                error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
3136                if (error) {
3137                        goto out;
3138                }
3139        } else {
3140                msg_flags = 0;
3141        }
3142        auio.uio_iov = iov;
3143        auio.uio_iovcnt = uap->iovlen;
3144        auio.uio_segflg = UIO_USERSPACE;
3145        auio.uio_rw = UIO_READ;
3146        auio.uio_td = td;
3147        auio.uio_offset = 0;                    /* XXX */
3148        auio.uio_resid = 0;
3149        tiov = iov;
3150        for (i = 0; i <uap->iovlen; i++, tiov++) {
3151                if ((auio.uio_resid += tiov->iov_len) < 0) {
3152                        error = EINVAL;
3153                        goto out;
3154                }
3155        }
3156        len = auio.uio_resid;
3157        fromsa = (struct sockaddr *)sockbufstore;
3158
3159#ifdef KTRACE
3160        if (KTRPOINT(td, KTR_GENIO))
3161                ktruio = cloneuio(&auio);
3162#endif /* KTRACE */
3163        memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
3164        CURVNET_SET(so->so_vnet);
3165        error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
3166                    fromsa, fromlen, &msg_flags,
3167                    (struct sctp_sndrcvinfo *)&sinfo, 1);
3168        CURVNET_RESTORE();
3169        if (error) {
3170                if (auio.uio_resid != (int)len && (error == ERESTART ||
3171                    error == EINTR || error == EWOULDBLOCK))
3172                        error = 0;
3173        } else {
3174                if (uap->sinfo)
3175                        error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
3176        }
3177#ifdef KTRACE
3178        if (ktruio != NULL) {
3179                ktruio->uio_resid = (int)len - auio.uio_resid;
3180                ktrgenio(uap->sd, UIO_READ, ktruio, error);
3181        }
3182#endif /* KTRACE */
3183        if (error)
3184                goto out;
3185        td->td_retval[0] = (int)len - auio.uio_resid;
3186
3187        if (fromlen && uap->from) {
3188                len = fromlen;
3189                if (len <= 0 || fromsa == 0)
3190                        len = 0;
3191                else {
3192                        len = MIN(len, fromsa->sa_len);
3193                        error = copyout(fromsa, uap->from, (unsigned)len);
3194                        if (error)
3195                                goto out;
3196                }
3197                error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
3198                if (error) {
3199                        goto out;
3200                }
3201        }
3202#ifdef KTRACE
3203        if (KTRPOINT(td, KTR_STRUCT))
3204                ktrsockaddr(fromsa);
3205#endif
3206        if (uap->msg_flags) {
3207                error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
3208                if (error) {
3209                        goto out;
3210                }
3211        }
3212out:
3213        free(iov, M_IOV);
3214out1:
3215        if (fp)
3216                fdrop(fp, td);
3217
3218        return (error);
3219#else  /* SCTP */
3220        return (EOPNOTSUPP);
3221#endif /* SCTP */
3222}
3223#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.