]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/tcpip/v2_0/src/sys/kern/uipc_syscalls.c
Initial revision
[karo-tx-redboot.git] / packages / net / tcpip / v2_0 / src / sys / kern / uipc_syscalls.c
1 //==========================================================================
2 //
3 //      sys/kern/uipc_syscalls.c
4 //
5 //     
6 //
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 //
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
14 //
15 // -------------------------------------------
16 //
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
20 //
21 // Author(s):    gthomas
22 // Contributors: gthomas
23 // Date:         2000-01-10
24 // Purpose:      
25 // Description:  
26 //              
27 //
28 //####DESCRIPTIONEND####
29 //
30 //==========================================================================
31
32
33 /*      $OpenBSD: uipc_syscalls.c,v 1.29 1999/12/08 06:50:17 itojun Exp $       */
34 /*      $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $      */
35
36 /*
37  * Copyright (c) 1982, 1986, 1989, 1990, 1993
38  *      The Regents of the University of California.  All rights reserved.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. All advertising materials mentioning features or use of this software
49  *    must display the following acknowledgement:
50  *      This product includes software developed by the University of
51  *      California, Berkeley and its contributors.
52  * 4. Neither the name of the University nor the names of its contributors
53  *    may be used to endorse or promote products derived from this software
54  *    without specific prior written permission.
55  *
56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66  * SUCH DAMAGE.
67  *
68  *      @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
69  */
70
71 #include <sys/param.h>
72 #ifdef __ECOS
73 #include <cyg/io/file.h>
74 static int ecos_getsock(int fdes, struct file **fpp);
75 #define getsock(fdp, fdes, fpp) ecos_getsock(fdes, fpp)
76 #else
77 #include <sys/systm.h>
78 #include <sys/proc.h>
79 #include <sys/filedesc.h>
80 #include <sys/file.h>
81 #include <sys/buf.h>
82 #endif
83 #include <sys/malloc.h>
84 #include <sys/mbuf.h>
85 #include <sys/protosw.h>
86 #include <sys/socket.h>
87 #include <sys/socketvar.h>
88 #ifndef __ECOS
89 #include <sys/signalvar.h>
90 #include <sys/un.h>
91 #endif
92 #ifdef KTRACE
93 #include <sys/ktrace.h>
94 #endif
95
96 #ifndef __ECOS
97 #include <sys/mount.h>
98 #endif
99 #include <sys/syscallargs.h>
100
101 /*
102  * System call interface to the socket abstraction.
103  */
104 extern  struct fileops socketops;
105
106 #ifdef __ECOS
107 int
108 sys_socket(struct sys_socket_args *uap, register_t *retval)
109 {
110 #else
111 int
112 sys_socket(p, v, retval)
113         struct proc *p;
114         void *v;
115         register_t *retval;
116 {
117         register struct sys_socket_args /* {
118                 syscallarg(int) domain;
119                 syscallarg(int) type;
120                 syscallarg(int) protocol;
121         } */ *uap = v;
122         struct filedesc *fdp = p->p_fd;
123 #endif // __ECOS
124         struct socket *so;
125         struct file *fp;
126         int fd, error;
127
128 #ifdef __ECOS
129         if ((error = falloc(&fp, &fd)) != 0)
130 #else
131         if ((error = falloc(p, &fp, &fd)) != 0)
132 #endif
133                 return (error);
134         fp->f_flag = FREAD|FWRITE;
135         fp->f_type = DTYPE_SOCKET;
136         fp->f_ops = &socketops;
137         error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
138                          SCARG(uap, protocol));
139         if (error) {
140 #ifndef __ECOS
141                 fdremove(fdp, fd);
142 #endif
143                 ffree(fp);
144         } else {
145 #ifdef __ECOS
146                 fp->f_data = (CYG_ADDRWORD)so;
147 #else
148                 fp->f_data = (caddr_t)so;
149 #endif
150                 *retval = fd;
151         }
152         return (error);
153 }
154
155 #ifdef __ECOS
156 int
157 sys_bind(struct sys_bind_args *uap, register_t *retval)
158     {
159 #else
160 /* ARGSUSED */
161 int
162 sys_bind(p, v, retval)
163         struct proc *p;
164         void *v;
165         register_t *retval;
166 {
167         register struct sys_bind_args /* {
168                 syscallarg(int) s;
169                 syscallarg(struct sockaddr *) name;
170                 syscallarg(socklen_t) namelen;
171         } */ *uap = v;
172 #endif // __ECOS
173         struct file *fp;
174         struct mbuf *nam;
175         int error;
176
177         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
178                 return (error);
179         error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen),
180                          MT_SONAME);
181         if (error)
182                 return (error);
183         error = sobind((struct socket *)fp->f_data, nam);
184         m_freem(nam);
185         return (error);
186 }
187
188 /* ARGSUSED */
189 #ifdef __ECOS
190 int
191 sys_listen(struct sys_listen_args *uap, register_t *retval)
192 {
193 #else
194 int
195 sys_listen(p, v, retval)
196         struct proc *p;
197         void *v;
198         register_t *retval;
199 {
200         register struct sys_listen_args /* {
201                 syscallarg(int) s;
202                 syscallarg(int) backlog;
203         } */ *uap = v;
204 #endif // __ECOS
205         struct file *fp;
206         int error;
207
208         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
209                 return (error);
210         return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog)));
211 }
212
213 #ifdef __ECOS
214 int
215     sys_accept(struct sys_accept_args *uap, register_t *retval)
216 {
217 #else
218 int
219 sys_accept(p, v, retval)
220         struct proc *p;
221         void *v;
222         register_t *retval;
223 {
224         register struct sys_accept_args /* {
225                 syscallarg(int) s;
226                 syscallarg(struct sockaddr *) name;
227                 syscallarg(socklen_t *) anamelen;
228         } */ *uap = v;
229 #endif
230         struct file *fp;
231         struct mbuf *nam;
232         socklen_t namelen;
233         int error, s, tmpfd;
234         register struct socket *so;
235
236         if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
237             (caddr_t)&namelen, sizeof (namelen))))
238                 return (error);
239         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
240                 return (error);
241         s = splsoftnet();
242         so = (struct socket *)fp->f_data;
243         if ((so->so_options & SO_ACCEPTCONN) == 0) {
244                 splx(s);
245                 return (EINVAL);
246         }
247         if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
248                 splx(s);
249                 return (EWOULDBLOCK);
250         }
251         while (so->so_qlen == 0 && so->so_error == 0) {
252                 if (so->so_state & SS_CANTRCVMORE) {
253                         so->so_error = ECONNABORTED;
254                         break;
255                 }
256                 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
257                                netcon, 0);
258                 if (error) {
259                         splx(s);
260                         return (error);
261                 }
262         }
263         if (so->so_error) {
264                 error = so->so_error;
265                 so->so_error = 0;
266                 splx(s);
267                 return (error);
268         }
269 #ifdef __ECOS
270         if ((error = falloc(&fp, &tmpfd)) != 0) {
271 #else
272         if ((error = falloc(p, &fp, &tmpfd)) != 0) {
273 #endif
274                 splx(s);
275                 return (error);
276         }
277         *retval = tmpfd;
278         { struct socket *aso = so->so_q;
279           if (soqremque(aso, 1) == 0)
280                 panic("accept");
281           so = aso;
282         }
283         fp->f_type = DTYPE_SOCKET;
284         fp->f_flag = FREAD|FWRITE;
285         fp->f_ops = &socketops;
286 #ifdef __ECOS
287         fp->f_data = (CYG_ADDRWORD)so;
288 #else
289         fp->f_data = (caddr_t)so;
290 #endif
291         nam = m_get(M_WAIT, MT_SONAME);
292         (void) soaccept(so, nam);
293         if (SCARG(uap, name)) {
294                 if (namelen > nam->m_len)
295                         namelen = nam->m_len;
296                 /* SHOULD COPY OUT A CHAIN HERE */
297                 if ((error = copyout(mtod(nam, caddr_t),
298                     (caddr_t)SCARG(uap, name), namelen)) == 0)
299                         error = copyout((caddr_t)&namelen,
300                             (caddr_t)SCARG(uap, anamelen),
301                             sizeof (*SCARG(uap, anamelen)));
302         }
303         m_freem(nam);
304         splx(s);
305         return (error);
306 }
307
308 #ifdef __ECOS
309 int
310 sys_connect(struct sys_connect_args *uap, register_t *retval)
311 {
312 #else
313 /* ARGSUSED */
314 int
315 sys_connect(p, v, retval)
316         struct proc *p;
317         void *v;
318         register_t *retval;
319 {
320         register struct sys_connect_args /* {
321                 syscallarg(int) s;
322                 syscallarg(struct sockaddr *) name;
323                 syscallarg(socklen_t) namelen;
324         } */ *uap = v;
325 #endif // __ECOS
326         struct file *fp;
327         register struct socket *so;
328         struct mbuf *nam;
329         int error, s;
330
331         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
332                 return (error);
333         so = (struct socket *)fp->f_data;
334         if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
335                 return (EALREADY);
336         error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen),
337                          MT_SONAME);
338         if (error)
339                 return (error);
340         error = soconnect(so, nam);
341         if (error)
342                 goto bad;
343         if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
344                 m_freem(nam);
345                 return (EINPROGRESS);
346         }
347         s = splsoftnet();
348         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
349                 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
350                                netcon, 0);
351                 if (error)
352                         break;
353         }
354         if (error == 0) {
355                 error = so->so_error;
356                 so->so_error = 0;
357         }
358         splx(s);
359 bad:
360         so->so_state &= ~SS_ISCONNECTING;
361         m_freem(nam);
362 #ifndef __ECOS
363         if (error == ERESTART)
364                 error = EINTR;
365 #endif
366         return (error);
367 }
368
369 #ifndef __ECOS
370 int
371 sys_socketpair(p, v, retval)
372         struct proc *p;
373         void *v;
374         register_t *retval;
375 {
376         register struct sys_socketpair_args /* {
377                 syscallarg(int) domain;
378                 syscallarg(int) type;
379                 syscallarg(int) protocol;
380                 syscallarg(int *) rsv;
381         } */ *uap = v;
382         register struct filedesc *fdp = p->p_fd;
383         struct file *fp1, *fp2;
384         struct socket *so1, *so2;
385         int fd, error, sv[2];
386
387         error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
388                          SCARG(uap, protocol));
389         if (error)
390                 return (error);
391         error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
392                          SCARG(uap, protocol));
393         if (error)
394                 goto free1;
395         if ((error = falloc(p, &fp1, &fd)) != 0)
396                 goto free2;
397         sv[0] = fd;
398         fp1->f_flag = FREAD|FWRITE;
399         fp1->f_type = DTYPE_SOCKET;
400         fp1->f_ops = &socketops;
401         fp1->f_data = (caddr_t)so1;
402         if ((error = falloc(p, &fp2, &fd)) != 0)
403                 goto free3;
404         fp2->f_flag = FREAD|FWRITE;
405         fp2->f_type = DTYPE_SOCKET;
406         fp2->f_ops = &socketops;
407         fp2->f_data = (caddr_t)so2;
408         sv[1] = fd;
409         if ((error = soconnect2(so1, so2)) != 0)
410                 goto free4;
411         if (SCARG(uap, type) == SOCK_DGRAM) {
412                 /*
413                  * Datagram socket connection is asymmetric.
414                  */
415                  if ((error = soconnect2(so2, so1)) != 0)
416                         goto free4;
417         }
418         error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
419             2 * sizeof (int));
420         if (error == 0)
421                 return (error);
422 free4:
423         ffree(fp2);
424         fdremove(fdp, sv[1]);
425 free3:
426         ffree(fp1);
427         fdremove(fdp, sv[0]);
428 free2:
429         (void)soclose(so2);
430 free1:
431         (void)soclose(so1);
432         return (error);
433 }
434 #endif
435
436 #ifdef __ECOS
437 int
438 sys_sendto(struct sys_sendto_args *uap, register_t *retval)
439 {
440 #else
441 int
442 sys_sendto(p, v, retval)
443         struct proc *p;
444         void *v;
445         register_t *retval;
446 {
447         register struct sys_sendto_args /* {
448                 syscallarg(int) s;
449                 syscallarg(caddr_t) buf;
450                 syscallarg(size_t) len;
451                 syscallarg(int) flags;
452                 syscallarg(struct sockaddr *) to;
453                 syscallarg(socklen_t) tolen;
454         } */ *uap = v;
455 #endif // __ECOS
456         struct msghdr msg;
457         struct iovec aiov;
458
459         msg.msg_name = (caddr_t)SCARG(uap, to);
460         msg.msg_namelen = SCARG(uap, tolen);
461         msg.msg_iov = &aiov;
462         msg.msg_iovlen = 1;
463         msg.msg_control = 0;
464 #ifdef COMPAT_OLDSOCK
465         msg.msg_flags = 0;
466 #endif
467         aiov.iov_base = (char *)SCARG(uap, buf);
468         aiov.iov_len = SCARG(uap, len);
469 #ifdef __ECOS
470         return (sendit(SCARG(uap, s), &msg, SCARG(uap, flags), retval));
471 #else
472         return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
473 #endif
474 }
475
476 #ifndef __ECOS
477 int
478 sys_sendmsg(p, v, retval)
479         struct proc *p;
480         void *v;
481         register_t *retval;
482 {
483         register struct sys_sendmsg_args /* {
484                 syscallarg(int) s;
485                 syscallarg(caddr_t) msg;
486                 syscallarg(int) flags;
487         } */ *uap = v;
488         struct msghdr msg;
489         struct iovec aiov[UIO_SMALLIOV], *iov;
490         int error;
491
492         error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg));
493         if (error)
494                 return (error);
495         if (msg.msg_iovlen <= 0 || msg.msg_iovlen > IOV_MAX)
496                 return (EMSGSIZE);
497         if (msg.msg_iovlen > UIO_SMALLIOV)
498                 MALLOC(iov, struct iovec *,
499                        sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
500         else
501                 iov = aiov;
502         if (msg.msg_iovlen &&
503             (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
504             (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
505                 goto done;
506         msg.msg_iov = iov;
507 #ifdef COMPAT_OLDSOCK
508         msg.msg_flags = 0;
509 #endif
510         error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
511 done:
512         if (iov != aiov)
513                 FREE(iov, M_IOV);
514         return (error);
515 }
516 #endif
517
518 #ifdef __ECOS
519 int
520 sendit(int s, struct msghdr *mp, int flags, register_t *retsize)
521 {
522 #else
523 int
524 sendit(p, s, mp, flags, retsize)
525         register struct proc *p;
526         int s;
527         register struct msghdr *mp;
528         int flags;
529         register_t *retsize;
530 {
531 #endif // __ECOS
532         struct file *fp;
533         struct uio auio;
534         register struct iovec *iov;
535         register int i;
536         struct mbuf *to, *control;
537         int len, error;
538 #ifdef KTRACE
539         struct iovec *ktriov = NULL;
540 #endif
541         
542         if ((error = getsock(p->p_fd, s, &fp)) != 0)
543                 return (error);
544         auio.uio_iov = mp->msg_iov;
545         auio.uio_iovcnt = mp->msg_iovlen;
546         auio.uio_segflg = UIO_USERSPACE;
547         auio.uio_rw = UIO_WRITE;
548 #ifndef __ECOS
549         auio.uio_procp = p;
550 #endif
551         auio.uio_offset = 0;                    /* XXX */
552         auio.uio_resid = 0;
553         iov = mp->msg_iov;
554         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
555                 /* Don't allow sum > SSIZE_MAX */
556                 if (iov->iov_len > SSIZE_MAX ||
557                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
558                         return (EINVAL);
559         }
560         if (mp->msg_name) {
561                 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
562                                  MT_SONAME);
563                 if (error)
564                         return (error);
565         } else
566                 to = 0;
567         if (mp->msg_control) {
568                 if (mp->msg_controllen < sizeof(struct cmsghdr)
569 #ifdef COMPAT_OLDSOCK
570                     && mp->msg_flags != MSG_COMPAT
571 #endif
572                 ) {
573                         error = EINVAL;
574                         goto bad;
575                 }
576                 error = sockargs(&control, mp->msg_control,
577                                  mp->msg_controllen, MT_CONTROL);
578                 if (error)
579                         goto bad;
580 #ifdef COMPAT_OLDSOCK
581                 if (mp->msg_flags == MSG_COMPAT) {
582                         register struct cmsghdr *cm;
583
584                         M_PREPEND(control, sizeof(*cm), M_WAIT);
585                         if (control == 0) {
586                                 error = ENOBUFS;
587                                 goto bad;
588                         } else {
589                                 cm = mtod(control, struct cmsghdr *);
590                                 cm->cmsg_len = control->m_len;
591                                 cm->cmsg_level = SOL_SOCKET;
592                                 cm->cmsg_type = SCM_RIGHTS;
593                         }
594                 }
595 #endif
596         } else
597                 control = 0;
598 #ifdef KTRACE
599         if (KTRPOINT(p, KTR_GENIO)) {
600                 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
601
602                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
603                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
604         }
605 #endif
606         len = auio.uio_resid;
607         error = sosend((struct socket *)fp->f_data, to, &auio,
608                        NULL, control, flags);
609         if (error) {
610 #ifdef __ECOS
611                 if (auio.uio_resid != len && 
612                     (error == EINTR || error == EWOULDBLOCK))
613 #else
614                 if (auio.uio_resid != len && (error == ERESTART ||
615                     error == EINTR || error == EWOULDBLOCK))
616 #endif
617                         error = 0;
618 #ifndef __ECOS
619                 if (error == EPIPE)
620                         psignal(p, SIGPIPE);
621 #endif
622         }
623         if (error == 0)
624                 *retsize = len - auio.uio_resid;
625 #ifdef KTRACE
626         if (ktriov != NULL) {
627                 if (error == 0)
628                         ktrgenio(p->p_tracep, s, UIO_WRITE,
629                                 ktriov, *retsize, error);
630                 FREE(ktriov, M_TEMP);
631         }
632 #endif
633 bad:
634         if (to)
635                 m_freem(to);
636         return (error);
637 }
638
639 #ifdef __ECOS
640 int 
641 sys_recvfrom(struct sys_recvfrom_args *uap, register_t *retval)
642 {
643 #else
644 int
645 sys_recvfrom(p, v, retval)
646         struct proc *p;
647         void *v;
648         register_t *retval;
649 {
650         register struct sys_recvfrom_args /* {
651                 syscallarg(int) s;
652                 syscallarg(caddr_t) buf;
653                 syscallarg(size_t) len;
654                 syscallarg(int) flags;
655                 syscallarg(struct sockaddr *) from;
656                 syscallarg(socklen_t *) fromlenaddr;
657         } */ *uap = v;
658 #endif // __ECOS
659         struct msghdr msg;
660         struct iovec aiov;
661         int error;
662
663         if (SCARG(uap, fromlenaddr)) {
664                 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
665                                (caddr_t)&msg.msg_namelen,
666                                sizeof (msg.msg_namelen));
667                 if (error)
668                         return (error);
669         } else
670                 msg.msg_namelen = 0;
671         msg.msg_name = (caddr_t)SCARG(uap, from);
672         msg.msg_iov = &aiov;
673         msg.msg_iovlen = 1;
674         aiov.iov_base = SCARG(uap, buf);
675         aiov.iov_len = SCARG(uap, len);
676         msg.msg_control = 0;
677         msg.msg_flags = SCARG(uap, flags);
678 #ifdef __ECOS
679         return (recvit(SCARG(uap, s), &msg,
680                        (caddr_t)SCARG(uap, fromlenaddr), retval));
681 #else
682         return (recvit(p, SCARG(uap, s), &msg,
683                        (caddr_t)SCARG(uap, fromlenaddr), retval));
684 #endif
685 }
686
687 #ifndef __ECOS
688 int
689 sys_recvmsg(p, v, retval)
690         struct proc *p;
691         void *v;
692         register_t *retval;
693 {
694         register struct sys_recvmsg_args /* {
695                 syscallarg(int) s;
696                 syscallarg(struct msghdr *) msg;
697                 syscallarg(int) flags;
698         } */ *uap = v;
699         struct msghdr msg;
700         struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
701         register int error;
702
703         error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
704                        sizeof (msg));
705         if (error)
706                 return (error);
707         if (msg.msg_iovlen <= 0 || msg.msg_iovlen > IOV_MAX)
708                 return (EMSGSIZE);
709         if (msg.msg_iovlen > UIO_SMALLIOV)
710                 MALLOC(iov, struct iovec *,
711                        sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
712         else
713                 iov = aiov;
714 #ifdef COMPAT_OLDSOCK
715         msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
716 #else
717         msg.msg_flags = SCARG(uap, flags);
718 #endif
719         uiov = msg.msg_iov;
720         msg.msg_iov = iov;
721         error = copyin((caddr_t)uiov, (caddr_t)iov,
722                        (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
723         if (error)
724                 goto done;
725         if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
726                 msg.msg_iov = uiov;
727                 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
728                     sizeof(msg));
729         }
730 done:
731         if (iov != aiov)
732                 FREE(iov, M_IOV);
733         return (error);
734 }
735 #endif
736
737 #ifdef __ECOS
738 int
739 recvit(int s, struct msghdr *mp, caddr_t namelenp, register_t *retsize)
740 {
741 #else
742 int
743 recvit(p, s, mp, namelenp, retsize)
744         register struct proc *p;
745         int s;
746         register struct msghdr *mp;
747         caddr_t namelenp;
748         register_t *retsize;
749 {
750 #endif // __ECOS
751         struct file *fp;
752         struct uio auio;
753         register struct iovec *iov;
754         register int i;
755         size_t len;
756         int error;
757         struct mbuf *from = 0, *control = 0;
758 #ifdef KTRACE
759         struct iovec *ktriov = NULL;
760 #endif
761
762         if ((error = getsock(p->p_fd, s, &fp)) != 0)
763                 return (error);
764         auio.uio_iov = mp->msg_iov;
765         auio.uio_iovcnt = mp->msg_iovlen;
766         auio.uio_segflg = UIO_USERSPACE;
767         auio.uio_rw = UIO_READ;
768 #ifndef __ECOS
769         auio.uio_procp = p;
770 #endif
771         auio.uio_offset = 0;                    /* XXX */
772         auio.uio_resid = 0;
773         iov = mp->msg_iov;
774         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
775                 /* Don't allow sum > SSIZE_MAX */
776                 if (iov->iov_len > SSIZE_MAX ||
777                     (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
778                         return (EINVAL);
779         }
780 #ifdef KTRACE
781         if (KTRPOINT(p, KTR_GENIO)) {
782                 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
783
784                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
785                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
786         }
787 #endif
788         len = auio.uio_resid;
789         error = soreceive((struct socket *)fp->f_data, &from, &auio,
790                           NULL, mp->msg_control ? &control : NULL,
791                           &mp->msg_flags);
792         if (error) {
793 #ifdef __ECOS
794                 if (auio.uio_resid != len && 
795                     (error == EINTR || error == EWOULDBLOCK))
796 #else
797                 if (auio.uio_resid != len && (error == ERESTART ||
798                     error == EINTR || error == EWOULDBLOCK))
799 #endif
800                         error = 0;
801         }
802 #ifdef KTRACE
803         if (ktriov != NULL) {
804                 if (error == 0)
805                         ktrgenio(p->p_tracep, s, UIO_READ,
806                                 ktriov, len - auio.uio_resid, error);
807                 FREE(ktriov, M_TEMP);
808         }
809 #endif
810         if (error)
811                 goto out;
812         *retsize = len - auio.uio_resid;
813         if (mp->msg_name) {
814                 len = mp->msg_namelen;
815                 if (len <= 0 || from == 0)
816                         len = 0;
817                 else {
818                         /* save sa_len before it is destroyed by MSG_COMPAT */
819                         if (len > from->m_len)
820                                 len = from->m_len;
821                         /* else if len < from->m_len ??? */
822 #ifdef COMPAT_OLDSOCK
823                         if (mp->msg_flags & MSG_COMPAT)
824                                 mtod(from, struct osockaddr *)->sa_family =
825                                     mtod(from, struct sockaddr *)->sa_family;
826 #endif
827                         error = copyout(mtod(from, caddr_t),
828                             (caddr_t)mp->msg_name, (unsigned)len);
829                         if (error)
830                                 goto out;
831                 }
832                 mp->msg_namelen = len;
833                 if (namelenp &&
834                     (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
835 #ifdef COMPAT_OLDSOCK
836                         if (mp->msg_flags & MSG_COMPAT)
837                                 error = 0;      /* old recvfrom didn't check */
838                         else
839 #endif
840                         goto out;
841                 }
842         }
843         if (mp->msg_control) {
844 #ifdef COMPAT_OLDSOCK
845                 /*
846                  * We assume that old recvmsg calls won't receive access
847                  * rights and other control info, esp. as control info
848                  * is always optional and those options didn't exist in 4.3.
849                  * If we receive rights, trim the cmsghdr; anything else
850                  * is tossed.
851                  */
852                 if (control && mp->msg_flags & MSG_COMPAT) {
853                         if (mtod(control, struct cmsghdr *)->cmsg_level !=
854                             SOL_SOCKET ||
855                             mtod(control, struct cmsghdr *)->cmsg_type !=
856                             SCM_RIGHTS) {
857                                 mp->msg_controllen = 0;
858                                 goto out;
859                         }
860                         control->m_len -= sizeof (struct cmsghdr);
861                         control->m_data += sizeof (struct cmsghdr);
862                 }
863 #endif
864                 len = mp->msg_controllen;
865                 if (len <= 0 || control == 0)
866                         len = 0;
867                 else {
868                         struct mbuf *m = control;
869                         caddr_t p = (caddr_t)mp->msg_control;
870
871                         do {
872                                 i = m->m_len;
873                                 if (len < i) {
874                                         mp->msg_flags |= MSG_CTRUNC;
875                                         i = len;
876                                 }
877                                 error = copyout(mtod(m, caddr_t), p,
878                                     (unsigned)i);
879                                 if (m->m_next)
880                                         i = ALIGN(i);
881                                 p += i;
882                                 len -= i;
883                                 if (error != 0 || len <= 0)
884                                         break;
885                         } while ((m = m->m_next) != NULL);
886                         len = p - (caddr_t)mp->msg_control;
887                 }
888                 mp->msg_controllen = len;
889         }
890 out:
891         if (from)
892                 m_freem(from);
893         if (control)
894                 m_freem(control);
895         return (error);
896 }
897
898 /* ARGSUSED */
899 #ifdef __ECOS
900 int
901 sys_shutdown(struct sys_shutdown_args *uap, register_t *retval)
902 {
903 #else
904 int
905 sys_shutdown(p, v, retval)
906         struct proc *p;
907         void *v;
908         register_t *retval;
909 {
910         register struct sys_shutdown_args /* {
911                 syscallarg(int) s;
912                 syscallarg(int) how;
913         } */ *uap = v;
914 #endif // __ECOS
915         struct file *fp;
916         int error;
917
918         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
919                 return (error);
920         return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how)));
921 }
922
923 #ifdef __ECOS
924 int
925 sys_setsockopt(struct sys_setsockopt_args *uap, register_t *retval)
926 {
927 #else
928 /* ARGSUSED */
929 int
930 sys_setsockopt(p, v, retval)
931         struct proc *p;
932         void *v;
933         register_t *retval;
934 {
935         register struct sys_setsockopt_args /* {
936                 syscallarg(int) s;
937                 syscallarg(int) level;
938                 syscallarg(int) name;
939                 syscallarg(caddr_t) val;
940                 syscallarg(socklen_t) valsize;
941         } */ *uap = v;
942 #endif // __ECOS
943         struct file *fp;
944         struct mbuf *m = NULL;
945         int error;
946
947         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
948                 return (error);
949         if (SCARG(uap, valsize) > MCLBYTES)
950                 return (EINVAL);
951         if (SCARG(uap, val)) {
952                 m = m_get(M_WAIT, MT_SOOPTS);
953                 if (SCARG(uap, valsize) > MLEN) {
954                         MCLGET(m, M_DONTWAIT);
955                         if ((m->m_flags & M_EXT) == 0) {
956                                 m_freem(m);
957                                 return (ENOBUFS);
958                         }
959                 }
960                 if (m == NULL)
961                         return (ENOBUFS);
962                 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
963                                SCARG(uap, valsize));
964                 if (error) {
965                         (void) m_free(m);
966                         return (error);
967                 }
968                 m->m_len = SCARG(uap, valsize);
969         }
970         return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
971                          SCARG(uap, name), m));
972 }
973
974 #ifdef __ECOS
975 int
976 sys_getsockopt(struct sys_getsockopt_args *uap, register_t *retval)
977 {
978 #else
979 /* ARGSUSED */
980 int
981 sys_getsockopt(p, v, retval)
982         struct proc *p;
983         void *v;
984         register_t *retval;
985 {
986         register struct sys_getsockopt_args /* {
987                 syscallarg(int) s;
988                 syscallarg(int) level;
989                 syscallarg(int) name;
990                 syscallarg(caddr_t) val;
991                 syscallarg(socklen_t *) avalsize;
992         } */ *uap = v;
993 #endif // __ECOS
994         struct file *fp;
995         struct mbuf *m = NULL;
996         socklen_t valsize;
997         int error;
998
999         if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1000                 return (error);
1001         if (SCARG(uap, val)) {
1002                 error = copyin((caddr_t)SCARG(uap, avalsize),
1003                                (caddr_t)&valsize, sizeof (valsize));
1004                 if (error)
1005                         return (error);
1006         } else
1007                 valsize = 0;
1008         if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
1009             SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
1010             m != NULL) {
1011                 if (valsize > m->m_len)
1012                         valsize = m->m_len;
1013                 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1014                 if (error == 0)
1015                         error = copyout((caddr_t)&valsize,
1016                             (caddr_t)SCARG(uap, avalsize), sizeof (valsize));
1017         }
1018         if (m != NULL)
1019                 (void) m_free(m);
1020         return (error);
1021 }
1022
1023 #ifndef __ECOS
1024 int
1025 sys_pipe(p, v, retval)
1026         struct proc *p;
1027         void *v;
1028         register_t *retval;
1029 {
1030         register struct sys_pipe_args /* {
1031                 syscallarg(int *) fdp;
1032         } */ *uap = v;
1033         int error, fds[2];
1034         register_t rval[2];
1035
1036         if ((error = sys_opipe(p, v, rval)) == -1)
1037                 return (error);
1038         
1039         fds[0] = rval[0];
1040         fds[1] = rval[1];
1041         error = copyout((caddr_t)fds, (caddr_t)SCARG(uap, fdp),
1042             2 * sizeof (int));
1043         if (error) {
1044                 fdrelease(p, retval[0]);
1045                 fdrelease(p, retval[1]);
1046         }
1047         return (error);
1048 }
1049
1050 #ifdef OLD_PIPE
1051
1052 /* ARGSUSED */
1053 int
1054 sys_opipe(p, v, retval)
1055         struct proc *p;
1056         void *v;
1057         register_t *retval;
1058 {
1059         register struct filedesc *fdp = p->p_fd;
1060         struct file *rf, *wf;
1061         struct socket *rso, *wso;
1062         int fd, error;
1063
1064         if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0)
1065                 return (error);
1066         if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0)
1067                 goto free1;
1068         if ((error = falloc(p, &rf, &fd)) != 0)
1069                 goto free2;
1070         retval[0] = fd;
1071         rf->f_flag = FREAD;
1072         rf->f_type = DTYPE_SOCKET;
1073         rf->f_ops = &socketops;
1074         rf->f_data = (caddr_t)rso;
1075         if ((error = falloc(p, &wf, &fd)) != 0)
1076                 goto free3;
1077         wf->f_flag = FWRITE;
1078         wf->f_type = DTYPE_SOCKET;
1079         wf->f_ops = &socketops;
1080         wf->f_data = (caddr_t)wso;
1081         retval[1] = fd;
1082         if ((error = unp_connect2(wso, rso)) != 0)
1083                 goto free4;
1084         return (0);
1085 free4:
1086         ffree(wf);
1087         fdremove(fdp, retval[1]);
1088 free3:
1089         ffree(rf);
1090         fdremove(fdp, retval[0]);
1091 free2:
1092         (void)soclose(wso);
1093 free1:
1094         (void)soclose(rso);
1095         return (error);
1096 }
1097 #endif
1098 #endif // __ECOS
1099
1100 /*
1101  * Get socket name.
1102  */
1103 #ifdef __ECOS
1104 int
1105 sys_getsockname(struct sys_getsockname_args *uap, register_t *retval)
1106 {
1107 #else
1108 /* ARGSUSED */
1109 int
1110 sys_getsockname(p, v, retval)
1111         struct proc *p;
1112         void *v;
1113         register_t *retval;
1114 {
1115         register struct sys_getsockname_args /* {
1116                 syscallarg(int) fdes;
1117                 syscallarg(caddr_t) asa;
1118                 syscallarg(socklen_t *) alen;
1119         } */ *uap = v;
1120 #endif // __ECOS
1121         struct file *fp;
1122         register struct socket *so;
1123         struct mbuf *m;
1124         socklen_t len;
1125         int error;
1126
1127         if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1128                 return (error);
1129         error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len));
1130         if (error)
1131                 return (error);
1132         so = (struct socket *)fp->f_data;
1133         m = m_getclr(M_WAIT, MT_SONAME);
1134         if (m == NULL)
1135                 return (ENOBUFS);
1136         error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
1137         if (error)
1138                 goto bad;
1139         if (len > m->m_len)
1140                 len = m->m_len;
1141         error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1142         if (error == 0)
1143                 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
1144                     sizeof (len));
1145 bad:
1146         m_freem(m);
1147         return (error);
1148 }
1149
1150 /*
1151  * Get name of peer for connected socket.
1152  */
1153 /* ARGSUSED */
1154 #ifdef __ECOS
1155 int
1156 sys_getpeername(struct sys_getpeername_args *uap, register_t *retval)
1157 {
1158 #else
1159 int
1160 sys_getpeername(p, v, retval)
1161         struct proc *p;
1162         void *v;
1163         register_t *retval;
1164 {
1165         register struct sys_getpeername_args /* {
1166                 syscallarg(int) fdes;
1167                 syscallarg(caddr_t) asa;
1168                 syscallarg(socklen_t *) alen;
1169         } */ *uap = v;
1170 #endif // __ECOS
1171         struct file *fp;
1172         register struct socket *so;
1173         struct mbuf *m;
1174         socklen_t len;
1175         int error;
1176
1177         if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1178                 return (error);
1179         so = (struct socket *)fp->f_data;
1180         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
1181                 return (ENOTCONN);
1182         error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len));
1183         if (error)
1184                 return (error);
1185         m = m_getclr(M_WAIT, MT_SONAME);
1186         if (m == NULL)
1187                 return (ENOBUFS);
1188         error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
1189         if (error)
1190                 goto bad;
1191         if (len > m->m_len)
1192                 len = m->m_len;
1193         error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1194         if (error == 0)
1195                 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
1196                     sizeof (len));
1197 bad:
1198         m_freem(m);
1199         return (error);
1200 }
1201
1202 int
1203 sockargs(mp, buf, buflen, type)
1204         struct mbuf **mp;
1205         caddr_t buf;
1206         socklen_t buflen;
1207         int type;
1208 {
1209         register struct sockaddr *sa;
1210         register struct mbuf *m;
1211         int error;
1212
1213         if (buflen > MLEN) {
1214 #ifdef COMPAT_OLDSOCK
1215                 if (type == MT_SONAME && buflen <= 112)
1216                         buflen = MLEN;          /* unix domain compat. hack */
1217                 else
1218 #endif
1219                 return (EINVAL);
1220         }
1221         m = m_get(M_WAIT, type);
1222         if (m == NULL)
1223                 return (ENOBUFS);
1224         m->m_len = buflen;
1225         error = copyin(buf, mtod(m, caddr_t), buflen);
1226         if (error) {
1227                 (void) m_free(m);
1228                 return (error);
1229         }
1230         *mp = m;
1231         if (type == MT_SONAME) {
1232                 sa = mtod(m, struct sockaddr *);
1233
1234 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1235                 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1236                         sa->sa_family = sa->sa_len;
1237 #endif
1238                 sa->sa_len = buflen;
1239         }
1240         return (0);
1241 }
1242
1243 #ifdef __ECOS
1244 static int
1245 ecos_getsock(int fdes, struct file **fpp)
1246 {
1247     struct file *fp;
1248     if (getfp(fdes, &fp))
1249         return (EBADF);
1250     if (fp->f_type != DTYPE_SOCKET)
1251         return (ENOTSOCK);
1252     *fpp = fp;
1253     return (0);
1254 }
1255 #else
1256 int
1257 getsock(fdp, fdes, fpp)
1258         struct filedesc *fdp;
1259         int fdes;
1260         struct file **fpp;
1261 {
1262         register struct file *fp;
1263
1264         if ((unsigned)fdes >= fdp->fd_nfiles ||
1265             (fp = fdp->fd_ofiles[fdes]) == NULL)
1266                 return (EBADF);
1267         if (fp->f_type != DTYPE_SOCKET)
1268                 return (ENOTSOCK);
1269         *fpp = fp;
1270         return (0);
1271 }
1272 #endif