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

55-freebsd-126-freebsd-12
Last change on this file since d4bf70e was d4bf70e, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 15, 2018 at 9:06:00 AM

Disable or make static kern_* functions

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