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

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

Use accept() from FreeBSD

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