OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [kern/] [uipc_syscalls.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.