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

55-freebsd-126-freebsd-12
Last change on this file since 3c967ca was 3c967ca, checked in by Sebastian Huber <sebastian.huber@…>, on 06/08/17 at 11:15:12

Use <sys/lock.h> provided by Newlib

  • Property mode set to 100644
File size: 45.4 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *      @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include <rtems/bsd/local/opt_capsicum.h>
38#include <rtems/bsd/local/opt_inet.h>
39#include <rtems/bsd/local/opt_inet6.h>
40#include <rtems/bsd/local/opt_compat.h>
41#include <rtems/bsd/local/opt_ktrace.h>
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/capsicum.h>
46#include <sys/kernel.h>
47#include <sys/lock.h>
48#include <sys/mutex.h>
49#include <sys/sysproto.h>
50#include <sys/malloc.h>
51#include <sys/filedesc.h>
52#include <sys/proc.h>
53#include <sys/filio.h>
54#include <sys/jail.h>
55#include <sys/mbuf.h>
56#include <sys/protosw.h>
57#include <sys/rwlock.h>
58#include <sys/socket.h>
59#include <sys/socketvar.h>
60#include <sys/syscallsubr.h>
61#ifdef KTRACE
62#include <sys/ktrace.h>
63#endif
64#ifdef COMPAT_FREEBSD32
65#include <compat/freebsd32/freebsd32_util.h>
66#endif
67
68#include <net/vnet.h>
69
70#include <security/audit/audit.h>
71#include <security/mac/mac_framework.h>
72
73/*
74 * Flags for accept1() and kern_accept4(), in addition to SOCK_CLOEXEC
75 * and SOCK_NONBLOCK.
76 */
77#define ACCEPT4_INHERIT 0x1
78#define ACCEPT4_COMPAT  0x2
79
80static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
81static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
82
83#ifndef __rtems__
84static int accept1(struct thread *td, int s, struct sockaddr *uname,
85                   socklen_t *anamelen, int flags);
86static int getsockname1(struct thread *td, struct getsockname_args *uap,
87                        int compat);
88static int getpeername1(struct thread *td, struct getpeername_args *uap,
89                        int compat);
90#endif /* __rtems__ */
91static int sockargs(struct mbuf **, char *, socklen_t, int);
92
93#ifndef __rtems__
94/*
95 * Convert a user file descriptor to a kernel file entry and check if required
96 * capability rights are present.
97 * If required copy of current set of capability rights is returned.
98 * A reference on the file entry is held upon returning.
99 */
100int
101getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
102    struct file **fpp, u_int *fflagp, struct filecaps *havecapsp)
103{
104        struct file *fp;
105        int error;
106
107        error = fget_cap(td, fd, rightsp, &fp, havecapsp);
108        if (error != 0)
109                return (error);
110        if (fp->f_type != DTYPE_SOCKET) {
111                fdrop(fp, td);
112                if (havecapsp != NULL)
113                        filecaps_free(havecapsp);
114                return (ENOTSOCK);
115        }
116        if (fflagp != NULL)
117                *fflagp = fp->f_flag;
118        *fpp = fp;
119        return (0);
120}
121#else /* __rtems__ */
122static int
123rtems_bsd_getsock(int fd, struct file **fpp, u_int *fflagp)
124{
125        struct file *fp;
126        int error;
127
128        if ((uint32_t) fd < rtems_libio_number_iops) {
129                fp = rtems_bsd_fd_to_fp(fd);
130                if ((fp->f_io.flags & LIBIO_FLAGS_OPEN) != LIBIO_FLAGS_OPEN) {
131                        fp = NULL;
132                        error = EBADF;
133                } else if (fp->f_io.pathinfo.handlers != &socketops) {
134                        fp = NULL;
135                        error = ENOTSOCK;
136                } else {
137                        if (fflagp != NULL) {
138                                *fflagp = rtems_bsd_libio_flags_to_fflag(
139                                    fp->f_io.flags);
140                        }
141
142                        error = 0;
143                }
144        } else {
145                fp = NULL;
146                error = EBADF;
147        }
148
149        *fpp = fp;
150
151        return (error);
152}
153
154#define getsock_cap(td, fd, rights, fpp, fflagp, havecapsp) rtems_bsd_getsock(fd, fpp, fflagp)
155#endif /* __rtems__ */
156
157/*
158 * System call interface to the socket abstraction.
159 */
160#if defined(COMPAT_43)
161#define COMPAT_OLDSOCK
162#endif
163
164#ifdef __rtems__
165static
166#endif /* __rtems__ */
167int
168sys_socket(struct thread *td, struct socket_args *uap)
169{
170
171        return (kern_socket(td, uap->domain, uap->type, uap->protocol));
172}
173
174int
175kern_socket(struct thread *td, int domain, int type, int protocol)
176{
177        struct socket *so;
178        struct file *fp;
179        int fd, error, oflag, fflag;
180
181        AUDIT_ARG_SOCKET(domain, type, protocol);
182
183        oflag = 0;
184        fflag = 0;
185        if ((type & SOCK_CLOEXEC) != 0) {
186                type &= ~SOCK_CLOEXEC;
187                oflag |= O_CLOEXEC;
188        }
189        if ((type & SOCK_NONBLOCK) != 0) {
190                type &= ~SOCK_NONBLOCK;
191                fflag |= FNONBLOCK;
192        }
193
194#ifdef MAC
195        error = mac_socket_check_create(td->td_ucred, domain, type, protocol);
196        if (error != 0)
197                return (error);
198#endif
199        error = falloc(td, &fp, &fd, oflag);
200        if (error != 0)
201                return (error);
202        /* An extra reference on `fp' has been held for us by falloc(). */
203        error = socreate(domain, &so, type, protocol, td->td_ucred, td);
204        if (error != 0) {
205                fdclose(td, fp, fd);
206        } else {
207                finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops);
208                if ((fflag & FNONBLOCK) != 0)
209                        (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
210                td->td_retval[0] = fd;
211        }
212        fdrop(fp, td);
213        return (error);
214}
215#ifdef __rtems__
216int
217socket(int domain, int type, int protocol)
218{
219        struct thread *td = rtems_bsd_get_curthread_or_null();
220        struct socket_args ua = {
221                .domain = domain,
222                .type = type,
223                .protocol = protocol
224        };
225        int error;
226
227        if (td != NULL) {
228                error = sys_socket(td, &ua);
229        } else {
230                error = ENOMEM;
231        }
232
233        if (error == 0) {
234                return td->td_retval[0];
235        } else {
236                rtems_set_errno_and_return_minus_one(error);
237        }
238}
239#endif /* __rtems__ */
240
241#ifdef __rtems__
242static int kern_bindat(struct thread *td, int dirfd, int fd,
243    struct sockaddr *sa);
244
245static
246#endif /* __rtems__ */
247int
248sys_bind(struct thread *td, struct bind_args *uap)
249{
250        struct sockaddr *sa;
251        int error;
252
253        error = getsockaddr(&sa, uap->name, uap->namelen);
254        if (error == 0) {
255                error = kern_bindat(td, AT_FDCWD, uap->s, sa);
256                free(sa, M_SONAME);
257        }
258        return (error);
259}
260#ifdef __rtems__
261int
262bind(int socket, const struct sockaddr *address, socklen_t address_len)
263{
264        struct thread *td = rtems_bsd_get_curthread_or_null();
265        struct bind_args ua = {
266                .s = socket,
267                .name = (caddr_t) address,
268                .namelen = address_len
269        };
270        int error;
271
272        if (td != NULL) {
273                error = sys_bind(td, &ua);
274        } else {
275                error = ENOMEM;
276        }
277
278        return rtems_bsd_error_to_status_and_errno(error);
279}
280#endif /* __rtems__ */
281
282int
283kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
284{
285        struct socket *so;
286        struct file *fp;
287        cap_rights_t rights;
288        int error;
289
290        AUDIT_ARG_FD(fd);
291        AUDIT_ARG_SOCKADDR(td, dirfd, sa);
292        error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
293            &fp, NULL, NULL);
294        if (error != 0)
295                return (error);
296        so = fp->f_data;
297#ifdef KTRACE
298        if (KTRPOINT(td, KTR_STRUCT))
299                ktrsockaddr(sa);
300#endif
301#ifdef MAC
302        error = mac_socket_check_bind(td->td_ucred, so, sa);
303        if (error == 0) {
304#endif
305                if (dirfd == AT_FDCWD)
306                        error = sobind(so, sa, td);
307                else
308                        error = sobindat(dirfd, so, sa, td);
309#ifdef MAC
310        }
311#endif
312        fdrop(fp, td);
313        return (error);
314}
315
316#ifndef __rtems__
317static
318int
319sys_bindat(struct thread *td, struct bindat_args *uap)
320{
321        struct sockaddr *sa;
322        int error;
323
324        error = getsockaddr(&sa, uap->name, uap->namelen);
325        if (error == 0) {
326                error = kern_bindat(td, uap->fd, uap->s, sa);
327                free(sa, M_SONAME);
328        }
329        return (error);
330}
331#endif /* __rtems__ */
332
333int
334sys_listen(struct thread *td, struct listen_args *uap)
335{
336
337        return (kern_listen(td, uap->s, uap->backlog));
338}
339
340int
341kern_listen(struct thread *td, int s, int backlog)
342{
343        struct socket *so;
344        struct file *fp;
345        cap_rights_t rights;
346        int error;
347
348        AUDIT_ARG_FD(s);
349        error = getsock_cap(td, s, cap_rights_init(&rights, CAP_LISTEN),
350            &fp, NULL, NULL);
351        if (error == 0) {
352                so = fp->f_data;
353#ifdef MAC
354                error = mac_socket_check_listen(td->td_ucred, so);
355                if (error == 0)
356#endif
357                        error = solisten(so, backlog, td);
358                fdrop(fp, td);
359        }
360        return (error);
361}
362#ifdef __rtems__
363int
364listen(int socket, int backlog)
365{
366        struct thread *td = rtems_bsd_get_curthread_or_null();
367        struct listen_args ua = {
368                .s = socket,
369                .backlog = backlog
370        };
371        int error;
372
373        if (td != NULL) {
374                error = sys_listen(td, &ua);
375        } else {
376                error = ENOMEM;
377        }
378
379        return rtems_bsd_error_to_status_and_errno(error);
380}
381#endif /* __rtems__ */
382
383#ifdef __rtems__
384static int kern_accept4(struct thread *td, int s, struct sockaddr **name,
385    socklen_t *namelen, int flags, struct file **fp);
386#endif /* __rtems__ */
387/*
388 * accept1()
389 */
390static int
391accept1(td, s, uname, anamelen, flags)
392        struct thread *td;
393        int s;
394        struct sockaddr *uname;
395        socklen_t *anamelen;
396        int flags;
397{
398        struct sockaddr *name;
399        socklen_t namelen;
400        struct file *fp;
401        int error;
402
403        if (uname == NULL)
404                return (kern_accept4(td, s, NULL, NULL, flags, NULL));
405
406        error = copyin(anamelen, &namelen, sizeof (namelen));
407        if (error != 0)
408                return (error);
409
410        error = kern_accept4(td, s, &name, &namelen, flags, &fp);
411
412        if (error != 0)
413                return (error);
414
415        if (error == 0 && uname != NULL) {
416#ifdef COMPAT_OLDSOCK
417                if (flags & ACCEPT4_COMPAT)
418                        ((struct osockaddr *)name)->sa_family =
419                            name->sa_family;
420#endif
421                error = copyout(name, uname, namelen);
422        }
423        if (error == 0)
424                error = copyout(&namelen, anamelen,
425                    sizeof(namelen));
426        if (error != 0)
427                fdclose(td, fp, td->td_retval[0]);
428        fdrop(fp, td);
429        free(name, M_SONAME);
430        return (error);
431}
432#ifdef __rtems__
433int
434accept(int socket, struct sockaddr *__restrict address,
435    socklen_t *__restrict address_len)
436{
437        struct thread *td = rtems_bsd_get_curthread_or_null();
438        int error;
439
440        if (td != NULL) {
441                error = accept1(td, socket, address, address_len,
442                    ACCEPT4_INHERIT);
443        } else {
444                error = ENOMEM;
445        }
446
447        if (error == 0) {
448                return td->td_retval[0];
449        } else {
450                rtems_set_errno_and_return_minus_one(error);
451        }
452}
453#endif /* __rtems__ */
454
455#ifndef __rtems__
456int
457kern_accept(struct thread *td, int s, struct sockaddr **name,
458    socklen_t *namelen, struct file **fp)
459{
460        return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp));
461}
462#endif /* __rtems__ */
463
464int
465kern_accept4(struct thread *td, int s, struct sockaddr **name,
466    socklen_t *namelen, int flags, struct file **fp)
467{
468        struct file *headfp, *nfp = NULL;
469        struct sockaddr *sa = NULL;
470        struct socket *head, *so;
471        struct filecaps fcaps;
472        cap_rights_t rights;
473        u_int fflag;
474        pid_t pgid;
475        int error, fd, tmp;
476
477        if (name != NULL)
478                *name = NULL;
479
480        AUDIT_ARG_FD(s);
481        error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT),
482            &headfp, &fflag, &fcaps);
483        if (error != 0)
484                return (error);
485        head = headfp->f_data;
486        if ((head->so_options & SO_ACCEPTCONN) == 0) {
487                error = EINVAL;
488                goto done;
489        }
490#ifdef MAC
491        error = mac_socket_check_accept(td->td_ucred, head);
492        if (error != 0)
493                goto done;
494#endif
495        error = falloc_caps(td, &nfp, &fd,
496            (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps);
497        if (error != 0)
498                goto done;
499        ACCEPT_LOCK();
500        if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
501                ACCEPT_UNLOCK();
502                error = EWOULDBLOCK;
503                goto noconnection;
504        }
505        while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
506                if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
507                        head->so_error = ECONNABORTED;
508                        break;
509                }
510                error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
511                    "accept", 0);
512                if (error != 0) {
513                        ACCEPT_UNLOCK();
514                        goto noconnection;
515                }
516        }
517        if (head->so_error) {
518                error = head->so_error;
519                head->so_error = 0;
520                ACCEPT_UNLOCK();
521                goto noconnection;
522        }
523        so = TAILQ_FIRST(&head->so_comp);
524        KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
525        KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
526
527        /*
528         * Before changing the flags on the socket, we have to bump the
529         * reference count.  Otherwise, if the protocol calls sofree(),
530         * the socket will be released due to a zero refcount.
531         */
532        SOCK_LOCK(so);                  /* soref() and so_state update */
533        soref(so);                      /* file descriptor reference */
534
535        TAILQ_REMOVE(&head->so_comp, so, so_list);
536        head->so_qlen--;
537        if (flags & ACCEPT4_INHERIT)
538                so->so_state |= (head->so_state & SS_NBIO);
539        else
540                so->so_state |= (flags & SOCK_NONBLOCK) ? SS_NBIO : 0;
541        so->so_qstate &= ~SQ_COMP;
542        so->so_head = NULL;
543
544        SOCK_UNLOCK(so);
545        ACCEPT_UNLOCK();
546
547        /* An extra reference on `nfp' has been held for us by falloc(). */
548        td->td_retval[0] = fd;
549
550        /* connection has been removed from the listen queue */
551        KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
552
553        if (flags & ACCEPT4_INHERIT) {
554                pgid = fgetown(&head->so_sigio);
555                if (pgid != 0)
556                        fsetown(pgid, &so->so_sigio);
557        } else {
558                fflag &= ~(FNONBLOCK | FASYNC);
559                if (flags & SOCK_NONBLOCK)
560                        fflag |= FNONBLOCK;
561        }
562
563        finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
564        /* Sync socket nonblocking/async state with file flags */
565        tmp = fflag & FNONBLOCK;
566        (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
567        tmp = fflag & FASYNC;
568        (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
569        sa = NULL;
570        error = soaccept(so, &sa);
571        if (error != 0)
572                goto noconnection;
573        if (sa == NULL) {
574                if (name)
575                        *namelen = 0;
576                goto done;
577        }
578        AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
579        if (name) {
580                /* check sa_len before it is destroyed */
581                if (*namelen > sa->sa_len)
582                        *namelen = sa->sa_len;
583#ifdef KTRACE
584                if (KTRPOINT(td, KTR_STRUCT))
585                        ktrsockaddr(sa);
586#endif
587                *name = sa;
588                sa = NULL;
589        }
590noconnection:
591        free(sa, M_SONAME);
592
593        /*
594         * close the new descriptor, assuming someone hasn't ripped it
595         * out from under us.
596         */
597        if (error != 0)
598                fdclose(td, nfp, fd);
599
600        /*
601         * Release explicitly held references before returning.  We return
602         * a reference on nfp to the caller on success if they request it.
603         */
604done:
605        if (nfp == NULL)
606                filecaps_free(&fcaps);
607        if (fp != NULL) {
608                if (error == 0) {
609                        *fp = nfp;
610                        nfp = NULL;
611                } else
612                        *fp = NULL;
613        }
614        if (nfp != NULL)
615                fdrop(nfp, td);
616        fdrop(headfp, td);
617        return (error);
618}
619
620#ifndef __rtems__
621int
622sys_accept(td, uap)
623        struct thread *td;
624        struct accept_args *uap;
625{
626
627        return (accept1(td, uap->s, uap->name, uap->anamelen, ACCEPT4_INHERIT));
628}
629
630int
631sys_accept4(td, uap)
632        struct thread *td;
633        struct accept4_args *uap;
634{
635
636        if (uap->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
637                return (EINVAL);
638
639        return (accept1(td, uap->s, uap->name, uap->anamelen, uap->flags));
640}
641
642#ifdef COMPAT_OLDSOCK
643int
644oaccept(td, uap)
645        struct thread *td;
646        struct accept_args *uap;
647{
648
649        return (accept1(td, uap->s, uap->name, uap->anamelen,
650            ACCEPT4_INHERIT | ACCEPT4_COMPAT));
651}
652#endif /* COMPAT_OLDSOCK */
653#endif /* __rtems__ */
654
655#ifdef __rtems__
656static int kern_connectat(struct thread *td, int dirfd, int fd,
657    struct sockaddr *sa);
658
659static
660#endif /* __rtems__ */
661int
662sys_connect(struct thread *td, struct connect_args *uap)
663{
664        struct sockaddr *sa;
665        int error;
666
667        error = getsockaddr(&sa, uap->name, uap->namelen);
668        if (error == 0) {
669                error = kern_connectat(td, AT_FDCWD, uap->s, sa);
670                free(sa, M_SONAME);
671        }
672        return (error);
673}
674#ifdef __rtems__
675int
676connect(int socket, const struct sockaddr *address, socklen_t address_len)
677{
678        struct thread *td = rtems_bsd_get_curthread_or_null();
679        struct connect_args ua = {
680                .s = socket,
681                .name = (caddr_t) address,
682                .namelen = address_len
683        };
684        int error;
685
686        if (td != NULL) {
687                error = sys_connect(td, &ua);
688        } else {
689                error = ENOMEM;
690        }
691
692        return rtems_bsd_error_to_status_and_errno(error);
693}
694#endif /* __rtems__ */
695
696int
697kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
698{
699        struct socket *so;
700        struct file *fp;
701        cap_rights_t rights;
702        int error, interrupted = 0;
703
704        AUDIT_ARG_FD(fd);
705        AUDIT_ARG_SOCKADDR(td, dirfd, sa);
706        error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT),
707            &fp, NULL, NULL);
708        if (error != 0)
709                return (error);
710        so = fp->f_data;
711        if (so->so_state & SS_ISCONNECTING) {
712                error = EALREADY;
713                goto done1;
714        }
715#ifdef KTRACE
716        if (KTRPOINT(td, KTR_STRUCT))
717                ktrsockaddr(sa);
718#endif
719#ifdef MAC
720        error = mac_socket_check_connect(td->td_ucred, so, sa);
721        if (error != 0)
722                goto bad;
723#endif
724        if (dirfd == AT_FDCWD)
725                error = soconnect(so, sa, td);
726        else
727                error = soconnectat(dirfd, so, sa, td);
728        if (error != 0)
729                goto bad;
730        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
731                error = EINPROGRESS;
732                goto done1;
733        }
734        SOCK_LOCK(so);
735        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
736                error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH,
737                    "connec", 0);
738                if (error != 0) {
739                        if (error == EINTR || error == ERESTART)
740                                interrupted = 1;
741                        break;
742                }
743        }
744        if (error == 0) {
745                error = so->so_error;
746                so->so_error = 0;
747        }
748        SOCK_UNLOCK(so);
749bad:
750        if (!interrupted)
751                so->so_state &= ~SS_ISCONNECTING;
752        if (error == ERESTART)
753                error = EINTR;
754done1:
755        fdrop(fp, td);
756        return (error);
757}
758
759#ifndef __rtems__
760int
761sys_connectat(struct thread *td, struct connectat_args *uap)
762{
763        struct sockaddr *sa;
764        int error;
765
766        error = getsockaddr(&sa, uap->name, uap->namelen);
767        if (error == 0) {
768                error = kern_connectat(td, uap->fd, uap->s, sa);
769                free(sa, M_SONAME);
770        }
771        return (error);
772}
773#endif /* __rtems__ */
774
775int
776kern_socketpair(struct thread *td, int domain, int type, int protocol,
777    int *rsv)
778{
779        struct file *fp1, *fp2;
780        struct socket *so1, *so2;
781        int fd, error, oflag, fflag;
782
783        AUDIT_ARG_SOCKET(domain, type, protocol);
784
785        oflag = 0;
786        fflag = 0;
787        if ((type & SOCK_CLOEXEC) != 0) {
788                type &= ~SOCK_CLOEXEC;
789                oflag |= O_CLOEXEC;
790        }
791        if ((type & SOCK_NONBLOCK) != 0) {
792                type &= ~SOCK_NONBLOCK;
793                fflag |= FNONBLOCK;
794        }
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 != 0)
800                return (error);
801#endif
802        error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
803        if (error != 0)
804                return (error);
805        error = socreate(domain, &so2, type, protocol, td->td_ucred, td);
806        if (error != 0)
807                goto free1;
808        /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
809        error = falloc(td, &fp1, &fd, oflag);
810        if (error != 0)
811                goto free2;
812        rsv[0] = fd;
813        fp1->f_data = so1;      /* so1 already has ref count */
814        error = falloc(td, &fp2, &fd, oflag);
815        if (error != 0)
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 != 0)
821                goto free4;
822        if (type == SOCK_DGRAM) {
823                /*
824                 * Datagram socket connection is asymmetric.
825                 */
826                 error = soconnect2(so2, so1);
827                 if (error != 0)
828                        goto free4;
829        }
830        finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
831            &socketops);
832        finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data,
833            &socketops);
834        if ((fflag & FNONBLOCK) != 0) {
835                (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
836                (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
837        }
838        fdrop(fp1, td);
839        fdrop(fp2, td);
840        return (0);
841free4:
842        fdclose(td, fp2, rsv[1]);
843        fdrop(fp2, td);
844free3:
845        fdclose(td, fp1, rsv[0]);
846        fdrop(fp1, td);
847free2:
848        if (so2 != NULL)
849                (void)soclose(so2);
850free1:
851        if (so1 != NULL)
852                (void)soclose(so1);
853        return (error);
854}
855
856#ifdef __rtems__
857static
858#endif /* __rtems__ */
859int
860sys_socketpair(struct thread *td, struct socketpair_args *uap)
861{
862#ifndef __rtems__
863        int error, sv[2];
864#else /* __rtems__ */
865        int error;
866        int *sv = uap->rsv;
867#endif /* __rtems__ */
868
869        error = kern_socketpair(td, uap->domain, uap->type,
870            uap->protocol, sv);
871        if (error != 0)
872                return (error);
873#ifndef __rtems__
874        error = copyout(sv, uap->rsv, 2 * sizeof(int));
875        if (error != 0) {
876                (void)kern_close(td, sv[0]);
877                (void)kern_close(td, sv[1]);
878        }
879#endif /* __rtems__ */
880        return (error);
881}
882#ifdef __rtems__
883int
884socketpair(int domain, int type, int protocol, int *socket_vector)
885{
886        struct thread *td = rtems_bsd_get_curthread_or_null();
887        struct socketpair_args ua = {
888                .domain = domain,
889                .type = type,
890                .protocol = protocol,
891                .rsv = socket_vector
892        };
893        int error;
894
895        if (td != NULL) {
896                error = sys_socketpair(td, &ua);
897        } else {
898                error = ENOMEM;
899        }
900
901        return rtems_bsd_error_to_status_and_errno(error);
902}
903#endif /* __rtems__ */
904
905#ifdef __rtems__
906static int
907kern_sendit( struct thread *td, int s, struct msghdr *mp, int flags,
908    struct mbuf *control, enum uio_seg segflg);
909#endif /* __rtems__ */
910static int
911sendit(struct thread *td, int s, struct msghdr *mp, int flags)
912{
913        struct mbuf *control;
914        struct sockaddr *to;
915        int error;
916
917#ifdef CAPABILITY_MODE
918        if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
919                return (ECAPMODE);
920#endif
921
922        if (mp->msg_name != NULL) {
923                error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
924                if (error != 0) {
925                        to = NULL;
926                        goto bad;
927                }
928                mp->msg_name = to;
929        } else {
930                to = NULL;
931        }
932
933        if (mp->msg_control) {
934                if (mp->msg_controllen < sizeof(struct cmsghdr)
935#ifdef COMPAT_OLDSOCK
936                    && mp->msg_flags != MSG_COMPAT
937#endif
938                ) {
939                        error = EINVAL;
940                        goto bad;
941                }
942                error = sockargs(&control, mp->msg_control,
943                    mp->msg_controllen, MT_CONTROL);
944                if (error != 0)
945                        goto bad;
946#ifdef COMPAT_OLDSOCK
947                if (mp->msg_flags == MSG_COMPAT) {
948                        struct cmsghdr *cm;
949
950                        M_PREPEND(control, sizeof(*cm), M_WAITOK);
951                        cm = mtod(control, struct cmsghdr *);
952                        cm->cmsg_len = control->m_len;
953                        cm->cmsg_level = SOL_SOCKET;
954                        cm->cmsg_type = SCM_RIGHTS;
955                }
956#endif
957        } else {
958                control = NULL;
959        }
960
961        error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE);
962
963bad:
964        free(to, M_SONAME);
965        return (error);
966}
967
968int
969kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
970    struct mbuf *control, enum uio_seg segflg)
971{
972        struct file *fp;
973        struct uio auio;
974        struct iovec *iov;
975        struct socket *so;
976#ifndef __rtems__
977        cap_rights_t rights;
978#endif /* __rtems__ */
979#ifdef KTRACE
980        struct uio *ktruio = NULL;
981#endif
982        ssize_t len;
983        int i, error;
984
985        AUDIT_ARG_FD(s);
986#ifndef __rtems__
987        cap_rights_init(&rights, CAP_SEND);
988        if (mp->msg_name != NULL) {
989                AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
990                cap_rights_set(&rights, CAP_CONNECT);
991        }
992#endif /* __rtems__ */
993        error = getsock_cap(td, s, &rights, &fp, NULL, NULL);
994        if (error != 0) {
995                m_freem(control);
996                return (error);
997        }
998        so = (struct socket *)fp->f_data;
999
1000#ifdef KTRACE
1001        if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT))
1002                ktrsockaddr(mp->msg_name);
1003#endif
1004#ifdef MAC
1005        if (mp->msg_name != NULL) {
1006                error = mac_socket_check_connect(td->td_ucred, so,
1007                    mp->msg_name);
1008                if (error != 0) {
1009                        m_freem(control);
1010                        goto bad;
1011                }
1012        }
1013        error = mac_socket_check_send(td->td_ucred, so);
1014        if (error != 0) {
1015                m_freem(control);
1016                goto bad;
1017        }
1018#endif
1019
1020        auio.uio_iov = mp->msg_iov;
1021        auio.uio_iovcnt = mp->msg_iovlen;
1022        auio.uio_segflg = segflg;
1023        auio.uio_rw = UIO_WRITE;
1024        auio.uio_td = td;
1025        auio.uio_offset = 0;                    /* XXX */
1026        auio.uio_resid = 0;
1027        iov = mp->msg_iov;
1028        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1029                if ((auio.uio_resid += iov->iov_len) < 0) {
1030                        error = EINVAL;
1031                        m_freem(control);
1032                        goto bad;
1033                }
1034        }
1035#ifdef KTRACE
1036        if (KTRPOINT(td, KTR_GENIO))
1037                ktruio = cloneuio(&auio);
1038#endif
1039        len = auio.uio_resid;
1040        error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
1041        if (error != 0) {
1042                if (auio.uio_resid != len && (error == ERESTART ||
1043                    error == EINTR || error == EWOULDBLOCK))
1044                        error = 0;
1045                /* Generation of SIGPIPE can be controlled per socket */
1046                if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
1047                    !(flags & MSG_NOSIGNAL)) {
1048#ifndef __rtems__
1049                        PROC_LOCK(td->td_proc);
1050                        tdsignal(td, SIGPIPE);
1051                        PROC_UNLOCK(td->td_proc);
1052#else /* __rtems__ */
1053                /* FIXME: Determine if we really want to use signals */
1054#endif /* __rtems__ */
1055                }
1056        }
1057        if (error == 0)
1058                td->td_retval[0] = len - auio.uio_resid;
1059#ifdef KTRACE
1060        if (ktruio != NULL) {
1061                ktruio->uio_resid = td->td_retval[0];
1062                ktrgenio(s, UIO_WRITE, ktruio, error);
1063        }
1064#endif
1065bad:
1066        fdrop(fp, td);
1067        return (error);
1068}
1069
1070#ifdef __rtems__
1071static
1072#endif /* __rtems__ */
1073int
1074sys_sendto(struct thread *td, struct sendto_args *uap)
1075{
1076        struct msghdr msg;
1077        struct iovec aiov;
1078
1079        msg.msg_name = uap->to;
1080        msg.msg_namelen = uap->tolen;
1081        msg.msg_iov = &aiov;
1082        msg.msg_iovlen = 1;
1083        msg.msg_control = 0;
1084#ifdef COMPAT_OLDSOCK
1085        msg.msg_flags = 0;
1086#endif
1087        aiov.iov_base = uap->buf;
1088        aiov.iov_len = uap->len;
1089        return (sendit(td, uap->s, &msg, uap->flags));
1090}
1091#ifdef __rtems__
1092ssize_t
1093sendto(int socket, const void *message, size_t length, int flags,
1094    const struct sockaddr *dest_addr, socklen_t dest_len)
1095{
1096        struct thread *td = rtems_bsd_get_curthread_or_null();
1097        struct sendto_args ua = {
1098                .s = socket,
1099                .buf = (caddr_t) message,
1100                .len = length,
1101                .flags = flags,
1102                .to = (caddr_t) dest_addr,
1103                .tolen = dest_len
1104        };
1105        int error;
1106
1107        if (td != NULL) {
1108                error = sys_sendto(td, &ua);
1109        } else {
1110                error = ENOMEM;
1111        }
1112
1113        if (error == 0) {
1114                return td->td_retval[0];
1115        } else {
1116                rtems_set_errno_and_return_minus_one(error);
1117        }
1118}
1119
1120int
1121rtems_bsd_sendto(int socket, struct mbuf *m, int flags,
1122    const struct sockaddr *dest_addr)
1123{
1124        struct thread *td = rtems_bsd_get_curthread_or_null();
1125        struct file *fp;
1126        struct socket *so;
1127        int error;
1128
1129        error = getsock_cap(td->td_proc->p_fd, socket, CAP_WRITE, &fp, NULL, NULL);
1130        if (error)
1131                return (error);
1132        so = (struct socket *)fp->f_data;
1133
1134        if (td != NULL) {
1135                error = sosend(so, __DECONST(struct sockaddr *, dest_addr),
1136                    NULL, m, NULL, flags, td);
1137        } else {
1138                error = ENOMEM;
1139        }
1140
1141        return (error);
1142}
1143#endif /* __rtems__ */
1144
1145#ifndef __rtems__
1146#ifdef COMPAT_OLDSOCK
1147int
1148osend(struct thread *td, struct osend_args *uap)
1149{
1150        struct msghdr msg;
1151        struct iovec aiov;
1152
1153        msg.msg_name = 0;
1154        msg.msg_namelen = 0;
1155        msg.msg_iov = &aiov;
1156        msg.msg_iovlen = 1;
1157        aiov.iov_base = uap->buf;
1158        aiov.iov_len = uap->len;
1159        msg.msg_control = 0;
1160        msg.msg_flags = 0;
1161        return (sendit(td, uap->s, &msg, uap->flags));
1162}
1163
1164int
1165osendmsg(struct thread *td, struct osendmsg_args *uap)
1166{
1167        struct msghdr msg;
1168        struct iovec *iov;
1169        int error;
1170
1171        error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
1172        if (error != 0)
1173                return (error);
1174        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1175        if (error != 0)
1176                return (error);
1177        msg.msg_iov = iov;
1178        msg.msg_flags = MSG_COMPAT;
1179        error = sendit(td, uap->s, &msg, uap->flags);
1180        free(iov, M_IOV);
1181        return (error);
1182}
1183#endif
1184#endif /* __rtems__ */
1185
1186#ifdef __rtems__
1187static
1188#endif /* __rtems__ */
1189int
1190sys_sendmsg(struct thread *td, struct sendmsg_args *uap)
1191{
1192        struct msghdr msg;
1193        struct iovec *iov;
1194        int error;
1195
1196        error = copyin(uap->msg, &msg, sizeof (msg));
1197        if (error != 0)
1198                return (error);
1199        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1200        if (error != 0)
1201                return (error);
1202        msg.msg_iov = iov;
1203#ifdef COMPAT_OLDSOCK
1204        msg.msg_flags = 0;
1205#endif
1206        error = sendit(td, uap->s, &msg, uap->flags);
1207        free(iov, M_IOV);
1208        return (error);
1209}
1210#ifdef __rtems__
1211ssize_t
1212sendmsg(int socket, const struct msghdr *message, int flags)
1213{
1214        struct thread *td = rtems_bsd_get_curthread_or_null();
1215        struct sendmsg_args ua = {
1216                .s = socket,
1217                .msg = message,
1218                .flags = flags
1219        };
1220        int error;
1221
1222        if (td != NULL) {
1223                error = sys_sendmsg(td, &ua);
1224        } else {
1225                error = ENOMEM;
1226        }
1227
1228        if (error == 0) {
1229                return td->td_retval[0];
1230        } else {
1231                rtems_set_errno_and_return_minus_one(error);
1232        }
1233}
1234#endif /* __rtems__ */
1235
1236#ifdef __rtems__
1237static
1238#endif /* __rtems__ */
1239int
1240kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg,
1241    struct mbuf **controlp)
1242{
1243        struct uio auio;
1244        struct iovec *iov;
1245        struct mbuf *m, *control = NULL;
1246        caddr_t ctlbuf;
1247        struct file *fp;
1248        struct socket *so;
1249        struct sockaddr *fromsa = NULL;
1250        cap_rights_t rights;
1251#ifdef KTRACE
1252        struct uio *ktruio = NULL;
1253#endif
1254        ssize_t len;
1255        int error, i;
1256
1257        if (controlp != NULL)
1258                *controlp = NULL;
1259
1260        AUDIT_ARG_FD(s);
1261        error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV),
1262            &fp, NULL, NULL);
1263        if (error != 0)
1264                return (error);
1265        so = fp->f_data;
1266
1267#ifdef MAC
1268        error = mac_socket_check_receive(td->td_ucred, so);
1269        if (error != 0) {
1270                fdrop(fp, td);
1271                return (error);
1272        }
1273#endif
1274
1275        auio.uio_iov = mp->msg_iov;
1276        auio.uio_iovcnt = mp->msg_iovlen;
1277        auio.uio_segflg = UIO_USERSPACE;
1278        auio.uio_rw = UIO_READ;
1279        auio.uio_td = td;
1280        auio.uio_offset = 0;                    /* XXX */
1281        auio.uio_resid = 0;
1282        iov = mp->msg_iov;
1283        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1284                if ((auio.uio_resid += iov->iov_len) < 0) {
1285                        fdrop(fp, td);
1286                        return (EINVAL);
1287                }
1288        }
1289#ifdef KTRACE
1290        if (KTRPOINT(td, KTR_GENIO))
1291                ktruio = cloneuio(&auio);
1292#endif
1293        len = auio.uio_resid;
1294        error = soreceive(so, &fromsa, &auio, NULL,
1295            (mp->msg_control || controlp) ? &control : NULL,
1296            &mp->msg_flags);
1297        if (error != 0) {
1298                if (auio.uio_resid != len && (error == ERESTART ||
1299                    error == EINTR || error == EWOULDBLOCK))
1300                        error = 0;
1301        }
1302        if (fromsa != NULL)
1303                AUDIT_ARG_SOCKADDR(td, AT_FDCWD, fromsa);
1304#ifdef KTRACE
1305        if (ktruio != NULL) {
1306                ktruio->uio_resid = len - auio.uio_resid;
1307                ktrgenio(s, UIO_READ, ktruio, error);
1308        }
1309#endif
1310        if (error != 0)
1311                goto out;
1312        td->td_retval[0] = len - auio.uio_resid;
1313        if (mp->msg_name) {
1314                len = mp->msg_namelen;
1315                if (len <= 0 || fromsa == NULL)
1316                        len = 0;
1317                else {
1318                        /* save sa_len before it is destroyed by MSG_COMPAT */
1319                        len = MIN(len, fromsa->sa_len);
1320#ifdef COMPAT_OLDSOCK
1321                        if (mp->msg_flags & MSG_COMPAT)
1322                                ((struct osockaddr *)fromsa)->sa_family =
1323                                    fromsa->sa_family;
1324#endif
1325                        if (fromseg == UIO_USERSPACE) {
1326                                error = copyout(fromsa, mp->msg_name,
1327                                    (unsigned)len);
1328                                if (error != 0)
1329                                        goto out;
1330                        } else
1331                                bcopy(fromsa, mp->msg_name, len);
1332                }
1333                mp->msg_namelen = len;
1334        }
1335        if (mp->msg_control && controlp == NULL) {
1336#ifdef COMPAT_OLDSOCK
1337                /*
1338                 * We assume that old recvmsg calls won't receive access
1339                 * rights and other control info, esp. as control info
1340                 * is always optional and those options didn't exist in 4.3.
1341                 * If we receive rights, trim the cmsghdr; anything else
1342                 * is tossed.
1343                 */
1344                if (control && mp->msg_flags & MSG_COMPAT) {
1345                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
1346                            SOL_SOCKET ||
1347                            mtod(control, struct cmsghdr *)->cmsg_type !=
1348                            SCM_RIGHTS) {
1349                                mp->msg_controllen = 0;
1350                                goto out;
1351                        }
1352                        control->m_len -= sizeof (struct cmsghdr);
1353                        control->m_data += sizeof (struct cmsghdr);
1354                }
1355#endif
1356                len = mp->msg_controllen;
1357                m = control;
1358                mp->msg_controllen = 0;
1359                ctlbuf = mp->msg_control;
1360
1361                while (m && len > 0) {
1362                        unsigned int tocopy;
1363
1364                        if (len >= m->m_len)
1365                                tocopy = m->m_len;
1366                        else {
1367                                mp->msg_flags |= MSG_CTRUNC;
1368                                tocopy = len;
1369                        }
1370
1371                        if ((error = copyout(mtod(m, caddr_t),
1372                                        ctlbuf, tocopy)) != 0)
1373                                goto out;
1374
1375                        ctlbuf += tocopy;
1376                        len -= tocopy;
1377                        m = m->m_next;
1378                }
1379                mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
1380        }
1381out:
1382        fdrop(fp, td);
1383#ifdef KTRACE
1384        if (fromsa && KTRPOINT(td, KTR_STRUCT))
1385                ktrsockaddr(fromsa);
1386#endif
1387        free(fromsa, M_SONAME);
1388
1389        if (error == 0 && controlp != NULL)
1390                *controlp = control;
1391        else  if (control)
1392                m_freem(control);
1393
1394        return (error);
1395}
1396
1397static int
1398recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp)
1399{
1400        int error;
1401
1402        error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL);
1403        if (error != 0)
1404                return (error);
1405        if (namelenp != NULL) {
1406                error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t));
1407#ifdef COMPAT_OLDSOCK
1408                if (mp->msg_flags & MSG_COMPAT)
1409                        error = 0;      /* old recvfrom didn't check */
1410#endif
1411        }
1412        return (error);
1413}
1414
1415#ifdef __rtems__
1416static
1417#endif /* __rtems__ */
1418int
1419sys_recvfrom(struct thread *td, struct recvfrom_args *uap)
1420{
1421        struct msghdr msg;
1422        struct iovec aiov;
1423        int error;
1424
1425        if (uap->fromlenaddr) {
1426                error = copyin(uap->fromlenaddr,
1427                    &msg.msg_namelen, sizeof (msg.msg_namelen));
1428                if (error != 0)
1429                        goto done2;
1430        } else {
1431                msg.msg_namelen = 0;
1432        }
1433        msg.msg_name = uap->from;
1434        msg.msg_iov = &aiov;
1435        msg.msg_iovlen = 1;
1436        aiov.iov_base = uap->buf;
1437        aiov.iov_len = uap->len;
1438        msg.msg_control = 0;
1439        msg.msg_flags = uap->flags;
1440        error = recvit(td, uap->s, &msg, uap->fromlenaddr);
1441done2:
1442        return (error);
1443}
1444#ifdef __rtems__
1445ssize_t
1446recvfrom(int socket, void *__restrict buffer, size_t length, int flags,
1447    struct sockaddr *__restrict address, socklen_t *__restrict address_len)
1448{
1449        struct thread *td = rtems_bsd_get_curthread_or_null();
1450        struct recvfrom_args ua = {
1451                .s = socket,
1452                .buf = buffer,
1453                .len = length,
1454                .flags = flags,
1455                .from = address,
1456                .fromlenaddr = address_len
1457        };
1458        int error;
1459
1460        if (td != NULL) {
1461                error = sys_recvfrom(td, &ua);
1462        } else {
1463                error = ENOMEM;
1464        }
1465
1466        if (error == 0) {
1467                return td->td_retval[0];
1468        } else {
1469                rtems_set_errno_and_return_minus_one(error);
1470        }
1471}
1472#endif /* __rtems__ */
1473
1474#ifndef __rtems__
1475#ifdef COMPAT_OLDSOCK
1476int
1477orecvfrom(struct thread *td, struct recvfrom_args *uap)
1478{
1479
1480        uap->flags |= MSG_COMPAT;
1481        return (sys_recvfrom(td, uap));
1482}
1483#endif
1484
1485#ifdef COMPAT_OLDSOCK
1486int
1487orecv(struct thread *td, struct orecv_args *uap)
1488{
1489        struct msghdr msg;
1490        struct iovec aiov;
1491
1492        msg.msg_name = 0;
1493        msg.msg_namelen = 0;
1494        msg.msg_iov = &aiov;
1495        msg.msg_iovlen = 1;
1496        aiov.iov_base = uap->buf;
1497        aiov.iov_len = uap->len;
1498        msg.msg_control = 0;
1499        msg.msg_flags = uap->flags;
1500        return (recvit(td, uap->s, &msg, NULL));
1501}
1502
1503/*
1504 * Old recvmsg.  This code takes advantage of the fact that the old msghdr
1505 * overlays the new one, missing only the flags, and with the (old) access
1506 * rights where the control fields are now.
1507 */
1508int
1509orecvmsg(struct thread *td, struct orecvmsg_args *uap)
1510{
1511        struct msghdr msg;
1512        struct iovec *iov;
1513        int error;
1514
1515        error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
1516        if (error != 0)
1517                return (error);
1518        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1519        if (error != 0)
1520                return (error);
1521        msg.msg_flags = uap->flags | MSG_COMPAT;
1522        msg.msg_iov = iov;
1523        error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
1524        if (msg.msg_controllen && error == 0)
1525                error = copyout(&msg.msg_controllen,
1526                    &uap->msg->msg_accrightslen, sizeof (int));
1527        free(iov, M_IOV);
1528        return (error);
1529}
1530#endif
1531#endif /* __rtems__ */
1532
1533#ifdef __rtems__
1534static
1535#endif /* __rtems__ */
1536int
1537sys_recvmsg(struct thread *td, struct recvmsg_args *uap)
1538{
1539        struct msghdr msg;
1540        struct iovec *uiov, *iov;
1541        int error;
1542
1543        error = copyin(uap->msg, &msg, sizeof (msg));
1544        if (error != 0)
1545                return (error);
1546        error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1547        if (error != 0)
1548                return (error);
1549        msg.msg_flags = uap->flags;
1550#ifdef COMPAT_OLDSOCK
1551        msg.msg_flags &= ~MSG_COMPAT;
1552#endif
1553        uiov = msg.msg_iov;
1554        msg.msg_iov = iov;
1555        error = recvit(td, uap->s, &msg, NULL);
1556        if (error == 0) {
1557                msg.msg_iov = uiov;
1558                error = copyout(&msg, uap->msg, sizeof(msg));
1559        }
1560        free(iov, M_IOV);
1561        return (error);
1562}
1563#ifdef __rtems__
1564ssize_t
1565recvmsg(int socket, struct msghdr *message, int flags)
1566{
1567        struct thread *td = rtems_bsd_get_curthread_or_null();
1568        struct recvmsg_args ua = {
1569                .s = socket,
1570                .msg = message,
1571                .flags = flags
1572        };
1573        int error;
1574
1575        if (td != NULL) {
1576                error = sys_recvmsg(td, &ua);
1577        } else {
1578                error = ENOMEM;
1579        }
1580
1581        if (error == 0) {
1582                return td->td_retval[0];
1583        } else {
1584                rtems_set_errno_and_return_minus_one(error);
1585        }
1586}
1587#endif /* __rtems__ */
1588
1589#ifdef __rtems__
1590static
1591#endif /* __rtems__ */
1592int
1593sys_shutdown(struct thread *td, struct shutdown_args *uap)
1594{
1595
1596        return (kern_shutdown(td, uap->s, uap->how));
1597}
1598
1599int
1600kern_shutdown(struct thread *td, int s, int how)
1601{
1602        struct socket *so;
1603        struct file *fp;
1604        cap_rights_t rights;
1605        int error;
1606
1607        AUDIT_ARG_FD(s);
1608        error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SHUTDOWN),
1609            &fp, NULL, NULL);
1610        if (error == 0) {
1611                so = fp->f_data;
1612                error = soshutdown(so, how);
1613#ifndef __rtems__
1614                /*
1615                 * Previous versions did not return ENOTCONN, but 0 in
1616                 * case the socket was not connected. Some important
1617                 * programs like syslogd up to r279016, 2015-02-19,
1618                 * still depend on this behavior.
1619                 */
1620                if (error == ENOTCONN &&
1621                    td->td_proc->p_osrel < P_OSREL_SHUTDOWN_ENOTCONN)
1622                        error = 0;
1623#endif /* __rtems__ */
1624                fdrop(fp, td);
1625        }
1626        return (error);
1627}
1628#ifdef __rtems__
1629int
1630shutdown(int socket, int how)
1631{
1632        struct shutdown_args ua = {
1633                .s = socket,
1634                .how = how
1635        };
1636        int error = sys_shutdown(NULL, &ua);
1637
1638        return rtems_bsd_error_to_status_and_errno(error);
1639}
1640#endif /* __rtems__ */
1641
1642#ifdef __rtems__
1643static int kern_setsockopt( struct thread *td, int s, int level, int name,
1644    void *val, enum uio_seg valseg, socklen_t valsize);
1645
1646static
1647#endif /* __rtems__ */
1648int
1649sys_setsockopt(struct thread *td, struct setsockopt_args *uap)
1650{
1651
1652        return (kern_setsockopt(td, uap->s, uap->level, uap->name,
1653            uap->val, UIO_USERSPACE, uap->valsize));
1654}
1655#ifdef __rtems__
1656int
1657setsockopt(int socket, int level, int option_name, const void *option_value,
1658    socklen_t option_len)
1659{
1660        struct thread *td = rtems_bsd_get_curthread_or_null();
1661        struct setsockopt_args ua = {
1662                .s = socket,
1663                .level = level,
1664                .name = option_name,
1665                .val = __DECONST(void *, option_value),
1666                .valsize = option_len
1667        };
1668        int error;
1669
1670        if (td != NULL) {
1671                error = sys_setsockopt(td, &ua);
1672        } else {
1673                error = ENOMEM;
1674        }
1675
1676        return rtems_bsd_error_to_status_and_errno(error);
1677}
1678#endif /* __rtems__ */
1679
1680int
1681kern_setsockopt(struct thread *td, int s, int level, int name, void *val,
1682    enum uio_seg valseg, socklen_t valsize)
1683{
1684        struct socket *so;
1685        struct file *fp;
1686        struct sockopt sopt;
1687        cap_rights_t rights;
1688        int error;
1689
1690        if (val == NULL && valsize != 0)
1691                return (EFAULT);
1692        if ((int)valsize < 0)
1693                return (EINVAL);
1694
1695        sopt.sopt_dir = SOPT_SET;
1696        sopt.sopt_level = level;
1697        sopt.sopt_name = name;
1698        sopt.sopt_val = val;
1699        sopt.sopt_valsize = valsize;
1700        switch (valseg) {
1701        case UIO_USERSPACE:
1702                sopt.sopt_td = td;
1703                break;
1704        case UIO_SYSSPACE:
1705                sopt.sopt_td = NULL;
1706                break;
1707        default:
1708                panic("kern_setsockopt called with bad valseg");
1709        }
1710
1711        AUDIT_ARG_FD(s);
1712        error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT),
1713            &fp, NULL, NULL);
1714        if (error == 0) {
1715                so = fp->f_data;
1716                error = sosetopt(so, &sopt);
1717                fdrop(fp, td);
1718        }
1719        return(error);
1720}
1721
1722#ifdef __rtems__
1723static int kern_getsockopt( struct thread *td, int s, int level, int name,
1724    void *val, enum uio_seg valseg, socklen_t *valsize);
1725
1726static
1727#endif /* __rtems__ */
1728int
1729sys_getsockopt(struct thread *td, struct getsockopt_args *uap)
1730{
1731        socklen_t valsize;
1732        int error;
1733
1734        if (uap->val) {
1735                error = copyin(uap->avalsize, &valsize, sizeof (valsize));
1736                if (error != 0)
1737                        return (error);
1738        }
1739
1740        error = kern_getsockopt(td, uap->s, uap->level, uap->name,
1741            uap->val, UIO_USERSPACE, &valsize);
1742
1743        if (error == 0)
1744                error = copyout(&valsize, uap->avalsize, sizeof (valsize));
1745        return (error);
1746}
1747#ifdef __rtems__
1748int
1749getsockopt(int socket, int level, int option_name, void *__restrict
1750    option_value, socklen_t *__restrict option_len)
1751{
1752        struct thread *td = rtems_bsd_get_curthread_or_null();
1753        struct getsockopt_args ua = {
1754                .s = socket,
1755                .level = level,
1756                .name = option_name,
1757                .val = (caddr_t) option_value,
1758                .avalsize = option_len
1759        };
1760        int error;
1761
1762        if (td != NULL) {
1763                error = sys_getsockopt(td, &ua);
1764        } else {
1765                error = ENOMEM;
1766        }
1767
1768        return rtems_bsd_error_to_status_and_errno(error);
1769}
1770#endif /* __rtems__ */
1771
1772/*
1773 * Kernel version of getsockopt.
1774 * optval can be a userland or userspace. optlen is always a kernel pointer.
1775 */
1776int
1777kern_getsockopt(struct thread *td, int s, int level, int name, void *val,
1778    enum uio_seg valseg, socklen_t *valsize)
1779{
1780        struct socket *so;
1781        struct file *fp;
1782        struct sockopt sopt;
1783        cap_rights_t rights;
1784        int error;
1785
1786        if (val == NULL)
1787                *valsize = 0;
1788        if ((int)*valsize < 0)
1789                return (EINVAL);
1790
1791        sopt.sopt_dir = SOPT_GET;
1792        sopt.sopt_level = level;
1793        sopt.sopt_name = name;
1794        sopt.sopt_val = val;
1795        sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */
1796        switch (valseg) {
1797        case UIO_USERSPACE:
1798                sopt.sopt_td = td;
1799                break;
1800        case UIO_SYSSPACE:
1801                sopt.sopt_td = NULL;
1802                break;
1803        default:
1804                panic("kern_getsockopt called with bad valseg");
1805        }
1806
1807        AUDIT_ARG_FD(s);
1808        error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT),
1809            &fp, NULL, NULL);
1810        if (error == 0) {
1811                so = fp->f_data;
1812                error = sogetopt(so, &sopt);
1813                *valsize = sopt.sopt_valsize;
1814                fdrop(fp, td);
1815        }
1816        return (error);
1817}
1818
1819#ifdef __rtems__
1820int
1821kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
1822    socklen_t *alen);
1823#endif /* __rtems__ */
1824/*
1825 * getsockname1() - Get socket name.
1826 */
1827static int
1828getsockname1(struct thread *td, struct getsockname_args *uap, int compat)
1829{
1830        struct sockaddr *sa;
1831        socklen_t len;
1832        int error;
1833
1834        error = copyin(uap->alen, &len, sizeof(len));
1835        if (error != 0)
1836                return (error);
1837
1838        error = kern_getsockname(td, uap->fdes, &sa, &len);
1839        if (error != 0)
1840                return (error);
1841
1842        if (len != 0) {
1843#ifdef COMPAT_OLDSOCK
1844                if (compat)
1845                        ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1846#endif
1847                error = copyout(sa, uap->asa, (u_int)len);
1848        }
1849        free(sa, M_SONAME);
1850        if (error == 0)
1851                error = copyout(&len, uap->alen, sizeof(len));
1852        return (error);
1853}
1854#ifdef __rtems__
1855int
1856getsockname(int socket, struct sockaddr *__restrict address,
1857    socklen_t *__restrict address_len)
1858{
1859        struct thread *td = rtems_bsd_get_curthread_or_null();
1860        struct getsockname_args ua = {
1861                .fdes = socket,
1862                .asa = address,
1863                .alen = address_len
1864        };
1865        int error;
1866
1867        if (td != NULL) {
1868                error = getsockname1(td, &ua, 0);
1869        } else {
1870                error = ENOMEM;
1871        }
1872
1873        return rtems_bsd_error_to_status_and_errno(error);
1874}
1875#endif /* __rtems__ */
1876
1877int
1878kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
1879    socklen_t *alen)
1880{
1881        struct socket *so;
1882        struct file *fp;
1883        cap_rights_t rights;
1884        socklen_t len;
1885        int error;
1886
1887        AUDIT_ARG_FD(fd);
1888        error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME),
1889            &fp, NULL, NULL);
1890        if (error != 0)
1891                return (error);
1892        so = fp->f_data;
1893        *sa = NULL;
1894        CURVNET_SET(so->so_vnet);
1895        error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
1896        CURVNET_RESTORE();
1897        if (error != 0)
1898                goto bad;
1899        if (*sa == NULL)
1900                len = 0;
1901        else
1902                len = MIN(*alen, (*sa)->sa_len);
1903        *alen = len;
1904#ifdef KTRACE
1905        if (KTRPOINT(td, KTR_STRUCT))
1906                ktrsockaddr(*sa);
1907#endif
1908bad:
1909        fdrop(fp, td);
1910        if (error != 0 && *sa != NULL) {
1911                free(*sa, M_SONAME);
1912                *sa = NULL;
1913        }
1914        return (error);
1915}
1916
1917#ifndef __rtems__
1918int
1919sys_getsockname(struct thread *td, struct getsockname_args *uap)
1920{
1921
1922        return (getsockname1(td, uap, 0));
1923}
1924
1925#ifdef COMPAT_OLDSOCK
1926int
1927ogetsockname(struct thread *td, struct getsockname_args *uap)
1928{
1929
1930        return (getsockname1(td, uap, 1));
1931}
1932#endif /* COMPAT_OLDSOCK */
1933#endif /* __rtems__ */
1934
1935#ifdef __rtems__
1936static int
1937kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
1938    socklen_t *alen);
1939#endif /* __rtems__ */
1940/*
1941 * getpeername1() - Get name of peer for connected socket.
1942 */
1943static int
1944getpeername1(struct thread *td, struct getpeername_args *uap, int compat)
1945{
1946        struct sockaddr *sa;
1947        socklen_t len;
1948        int error;
1949
1950        error = copyin(uap->alen, &len, sizeof (len));
1951        if (error != 0)
1952                return (error);
1953
1954        error = kern_getpeername(td, uap->fdes, &sa, &len);
1955        if (error != 0)
1956                return (error);
1957
1958        if (len != 0) {
1959#ifdef COMPAT_OLDSOCK
1960                if (compat)
1961                        ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1962#endif
1963                error = copyout(sa, uap->asa, (u_int)len);
1964        }
1965        free(sa, M_SONAME);
1966        if (error == 0)
1967                error = copyout(&len, uap->alen, sizeof(len));
1968        return (error);
1969}
1970#ifdef __rtems__
1971int
1972getpeername(int socket, struct sockaddr *__restrict address,
1973    socklen_t *__restrict address_len)
1974{
1975        struct thread *td = rtems_bsd_get_curthread_or_null();
1976        struct getpeername_args ua = {
1977                .fdes = socket,
1978                .asa = address,
1979                .alen = address_len
1980        };
1981        int error;
1982
1983        if (td != NULL) {
1984                error = getpeername1(td, &ua, 0);
1985        } else {
1986                error = ENOMEM;
1987        }
1988
1989        return rtems_bsd_error_to_status_and_errno(error);
1990}
1991#endif /* __rtems__ */
1992
1993int
1994kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
1995    socklen_t *alen)
1996{
1997        struct socket *so;
1998        struct file *fp;
1999        cap_rights_t rights;
2000        socklen_t len;
2001        int error;
2002
2003        AUDIT_ARG_FD(fd);
2004        error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME),
2005            &fp, NULL, NULL);
2006        if (error != 0)
2007                return (error);
2008        so = fp->f_data;
2009        if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
2010                error = ENOTCONN;
2011                goto done;
2012        }
2013        *sa = NULL;
2014        CURVNET_SET(so->so_vnet);
2015        error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
2016        CURVNET_RESTORE();
2017        if (error != 0)
2018                goto bad;
2019        if (*sa == NULL)
2020                len = 0;
2021        else
2022                len = MIN(*alen, (*sa)->sa_len);
2023        *alen = len;
2024#ifdef KTRACE
2025        if (KTRPOINT(td, KTR_STRUCT))
2026                ktrsockaddr(*sa);
2027#endif
2028bad:
2029        if (error != 0 && *sa != NULL) {
2030                free(*sa, M_SONAME);
2031                *sa = NULL;
2032        }
2033done:
2034        fdrop(fp, td);
2035        return (error);
2036}
2037
2038#ifndef __rtems__
2039int
2040sys_getpeername(struct thread *td, struct getpeername_args *uap)
2041{
2042
2043        return (getpeername1(td, uap, 0));
2044}
2045
2046#ifdef COMPAT_OLDSOCK
2047int
2048ogetpeername(struct thread *td, struct ogetpeername_args *uap)
2049{
2050
2051        /* XXX uap should have type `getpeername_args *' to begin with. */
2052        return (getpeername1(td, (struct getpeername_args *)uap, 1));
2053}
2054#endif /* COMPAT_OLDSOCK */
2055#endif /* __rtems__ */
2056
2057static int
2058sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type)
2059{
2060        struct sockaddr *sa;
2061        struct mbuf *m;
2062        int error;
2063
2064        if (buflen > MLEN) {
2065#ifdef COMPAT_OLDSOCK
2066                if (type == MT_SONAME && buflen <= 112)
2067                        buflen = MLEN;          /* unix domain compat. hack */
2068                else
2069#endif
2070                        if (buflen > MCLBYTES)
2071                                return (EINVAL);
2072        }
2073        m = m_get2(buflen, M_WAITOK, type, 0);
2074        m->m_len = buflen;
2075        error = copyin(buf, mtod(m, void *), buflen);
2076        if (error != 0)
2077                (void) m_free(m);
2078        else {
2079                *mp = m;
2080                if (type == MT_SONAME) {
2081                        sa = mtod(m, struct sockaddr *);
2082
2083#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
2084                        if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
2085                                sa->sa_family = sa->sa_len;
2086#endif
2087                        sa->sa_len = buflen;
2088                }
2089        }
2090        return (error);
2091}
2092
2093int
2094getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
2095{
2096        struct sockaddr *sa;
2097        int error;
2098
2099        if (len > SOCK_MAXADDRLEN)
2100                return (ENAMETOOLONG);
2101        if (len < offsetof(struct sockaddr, sa_data[0]))
2102                return (EINVAL);
2103        sa = malloc(len, M_SONAME, M_WAITOK);
2104        error = copyin(uaddr, sa, len);
2105        if (error != 0) {
2106                free(sa, M_SONAME);
2107        } else {
2108#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
2109                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
2110                        sa->sa_family = sa->sa_len;
2111#endif
2112                sa->sa_len = len;
2113                *namp = sa;
2114        }
2115        return (error);
2116}
Note: See TracBrowser for help on using the repository browser.