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

55-freebsd-126-freebsd-12
Last change on this file since 1af372a was 3489e3b, checked in by Sebastian Huber <sebastian.huber@…>, on 08/22/18 at 12:59:50

Update to FreeBSD head 2018-09-17

Git mirror commit 6c2192b1ef8c50788c751f878552526800b1e319.

Update #3472.

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