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

55-freebsd-126-freebsd-12
Last change on this file since bcdce02 was bcdce02, checked in by Sebastian Huber <sebastian.huber@…>, on 08/21/18 at 11:47:02

Update to FreeBSD head 2018-06-01

Git mirror commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9.

Update #3472.

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