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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since caf8ede was caf8ede, checked in by Sebastian Huber <sebastian.huber@…>, on 10/10/13 at 09:29:33

Import socket() implementation from FreeBSD

Add new test syscalls01.

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