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/] [sockio.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      sys/kern/sockio.c
4
//
5
//     Socket interface to Fileio subsystem
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):    nickg
22
// Contributors: nickg
23
// Date:         2000-06-06
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
/*
33
 * Copyright (c) 1982, 1986, 1991, 1993
34
 *      The Regents of the University of California.  All rights reserved.
35
 * (c) UNIX System Laboratories, Inc.
36
 * All or some portions of this file are derived from material licensed
37
 * to the University of California by American Telephone and Telegraph
38
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39
 * the permission of UNIX System Laboratories, Inc.
40
 *
41
 * Redistribution and use in source and binary forms, with or without
42
 * modification, are permitted provided that the following conditions
43
 * are met:
44
 * 1. Redistributions of source code must retain the above copyright
45
 *    notice, this list of conditions and the following disclaimer.
46
 * 2. Redistributions in binary form must reproduce the above copyright
47
 *    notice, this list of conditions and the following disclaimer in the
48
 *    documentation and/or other materials provided with the distribution.
49
 * 3. All advertising materials mentioning features or use of this software
50
 *    must display the following acknowledgement:
51
 *      This product includes software developed by the University of
52
 *      California, Berkeley and its contributors.
53
 * 4. Neither the name of the University nor the names of its contributors
54
 *    may be used to endorse or promote products derived from this software
55
 *    without specific prior written permission.
56
 *
57
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67
 * SUCH DAMAGE.
68
 *
69
 */
70
//==========================================================================
71
 
72
#include <pkgconf/net.h>
73
#include <pkgconf/io_fileio.h>
74
 
75
#include <sys/types.h>
76
 
77
#include <cyg/io/file.h>
78
 
79
#include <cyg/fileio/fileio.h>
80
#include <cyg/fileio/sockio.h>
81
 
82
#include <sys/param.h>
83
#include <sys/mbuf.h>
84
#include <sys/protosw.h>
85
#include <sys/socket.h>
86
#include <sys/socketvar.h>
87
#include <sys/ioctl.h>
88
 
89
#include <net/if.h>
90
#include <net/route.h>
91
 
92
//==========================================================================
93
// Forward definitions
94
 
95
static int     bsd_init( cyg_nstab_entry *nste );
96
static int     bsd_socket( cyg_nstab_entry *nste, int domain, int type,
97
                       int protocol, cyg_file *file );
98
 
99
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len );
100
static int bsd_connect   ( cyg_file *fp, const sockaddr *sa, socklen_t len );
101
static int bsd_accept    ( cyg_file *fp, cyg_file *new_fp,
102
                           struct sockaddr *name, socklen_t *anamelen );
103
static int bsd_listen    ( cyg_file *fp, int len );
104
static int bsd_getname   ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer );
105
static int bsd_shutdown  ( cyg_file *fp, int flags );
106
static int bsd_getsockopt( cyg_file *fp, int level, int optname,
107
                           void *optval, socklen_t *optlen);
108
static int bsd_setsockopt( cyg_file *fp, int level, int optname,
109
                           const void *optval, socklen_t optlen);
110
static int bsd_sendmsg   ( cyg_file *fp, const struct msghdr *m,
111
                               int flags, ssize_t *retsize );
112
static int bsd_recvmsg   ( cyg_file *fp, struct msghdr *m,
113
                               socklen_t *namelen, ssize_t *retsize );
114
 
115
 
116
// File operations
117
static int bsd_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
118
static int bsd_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
119
static int bsd_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
120
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
121
                                CYG_ADDRWORD data);
122
static int bsd_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);
123
static int bsd_fsync     (struct CYG_FILE_TAG *fp, int mode );
124
static int bsd_close     (struct CYG_FILE_TAG *fp);
125
static int bsd_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf );
126
static int bsd_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
127
static int bsd_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
128
 
129
static int
130
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize);
131
static int
132
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize);
133
 
134
 
135
//==========================================================================
136
// Table entrys
137
 
138
NSTAB_ENTRY( bsd_nste, 0,
139
             "bsd_tcpip",
140
             "",
141
             0,
142
             bsd_init,
143
             bsd_socket);
144
 
145
struct cyg_sock_ops bsd_sockops =
146
{
147
    bsd_bind,
148
    bsd_connect,
149
    bsd_accept,
150
    bsd_listen,
151
    bsd_getname,
152
    bsd_shutdown,
153
    bsd_getsockopt,
154
    bsd_setsockopt,
155
    bsd_sendmsg,
156
    bsd_recvmsg
157
};
158
 
159
cyg_fileops bsd_sock_fileops =
160
{
161
    bsd_read,
162
    bsd_write,
163
    bsd_lseek,
164
    bsd_ioctl,
165
    bsd_select,
166
    bsd_fsync,
167
    bsd_close,
168
    bsd_fstat,
169
    bsd_getinfo,
170
    bsd_setinfo
171
};
172
 
173
//==========================================================================
174
// NStab functions
175
 
176
 
177
 
178
// -------------------------------------------------------------------------
179
 
180
static int     bsd_init( cyg_nstab_entry *nste )
181
{
182
    // Initialization already handled via constructor
183
 
184
    return ENOERR;
185
}
186
 
187
// -------------------------------------------------------------------------
188
 
189
static int     bsd_socket( cyg_nstab_entry *nste, int domain, int type,
190
                       int protocol, cyg_file *file )
191
{
192
    int error = 0;
193
    struct socket *so;
194
 
195
    error = socreate( domain, &so, type, protocol );
196
 
197
    if( error == ENOERR )
198
    {
199
 
200
        cyg_selinit(&so->so_rcv.sb_sel);
201
        cyg_selinit(&so->so_snd.sb_sel);
202
 
203
        file->f_flag   |= CYG_FREAD|CYG_FWRITE;
204
        file->f_type    = CYG_FILE_TYPE_SOCKET;
205
        file->f_ops     = &bsd_sock_fileops;
206
        file->f_offset  = 0;
207
        file->f_data    = (CYG_ADDRWORD)so;
208
        file->f_xops    = (CYG_ADDRWORD)&bsd_sockops;
209
    }
210
 
211
    return error;
212
}
213
 
214
 
215
//==========================================================================
216
// Sockops functions
217
 
218
// -------------------------------------------------------------------------
219
 
220
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len )
221
{
222
    struct mbuf *nam;
223
    int error;
224
 
225
    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);
226
 
227
    if (error)
228
        return (error);
229
 
230
    error = sobind((struct socket *)fp->f_data, nam);
231
 
232
    m_freem(nam);
233
 
234
    return error;
235
}
236
 
237
// -------------------------------------------------------------------------
238
 
239
static int bsd_connect   ( cyg_file *fp, const sockaddr *sa, socklen_t len )
240
{
241
    register struct socket *so;
242
    struct mbuf *nam;
243
    int error, s;
244
 
245
    so = (struct socket *)fp->f_data;
246
 
247
    if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
248
        return (EALREADY);
249
 
250
    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);
251
 
252
    if (error)
253
        return (error);
254
 
255
    error = soconnect(so, nam);
256
    if (error)
257
        goto bad;
258
 
259
    if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
260
        m_freem(nam);
261
        return (EINPROGRESS);
262
    }
263
 
264
    s = splsoftnet();
265
    while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
266
        error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
267
                       netcon, 0);
268
        if (error)
269
            break;
270
    }
271
 
272
    if (error == 0) {
273
        error = so->so_error;
274
        so->so_error = 0;
275
    }
276
 
277
    splx(s);
278
 
279
bad:
280
    so->so_state &= ~SS_ISCONNECTING;
281
    m_freem(nam);
282
 
283
    return error;
284
}
285
 
286
// -------------------------------------------------------------------------
287
 
288
static int bsd_accept    ( cyg_file *fp, cyg_file *new_fp,
289
                           struct sockaddr *name, socklen_t *anamelen )
290
{
291
    struct mbuf *nam;
292
    socklen_t namelen = 0;
293
    int error = 0, s;
294
    register struct socket *so;
295
 
296
    if( anamelen != NULL )
297
        namelen = *anamelen;
298
 
299
    s = splsoftnet();
300
    so = (struct socket *)fp->f_data;
301
 
302
    if ((so->so_options & SO_ACCEPTCONN) == 0) {
303
        splx(s);
304
        return (EINVAL);
305
    }
306
 
307
    if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
308
        splx(s);
309
        return (EWOULDBLOCK);
310
    }
311
 
312
    while (so->so_qlen == 0 && so->so_error == 0) {
313
        if (so->so_state & SS_CANTRCVMORE) {
314
            so->so_error = ECONNABORTED;
315
            break;
316
        }
317
        error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
318
                       netcon, 0);
319
        if (error) {
320
            splx(s);
321
            return (error);
322
        }
323
    }
324
 
325
    if (so->so_error) {
326
        error = so->so_error;
327
        so->so_error = 0;
328
        splx(s);
329
        return (error);
330
    }
331
 
332
    {
333
        struct socket *aso = so->so_q;
334
        if (soqremque(aso, 1) == 0)
335
            panic("accept");
336
        so = aso;
337
    }
338
 
339
    cyg_selinit(&so->so_rcv.sb_sel);
340
    cyg_selinit(&so->so_snd.sb_sel);
341
 
342
    new_fp->f_type      = DTYPE_SOCKET;
343
    new_fp->f_flag     |= FREAD|FWRITE;
344
    new_fp->f_offset    = 0;
345
    new_fp->f_ops       = &bsd_sock_fileops;
346
    new_fp->f_data      = (CYG_ADDRWORD)so;
347
    new_fp->f_xops      = (CYG_ADDRWORD)&bsd_sockops;
348
 
349
    nam = m_get(M_WAIT, MT_SONAME);
350
    (void) soaccept(so, nam);
351
    if (name) {
352
        if (namelen > nam->m_len)
353
            namelen = nam->m_len;
354
        /* SHOULD COPY OUT A CHAIN HERE */
355
        if ((error = copyout(mtod(nam, caddr_t),
356
                             (caddr_t)name, namelen)) == 0)
357
            *anamelen = namelen;
358
    }
359
    m_freem(nam);
360
    splx(s);
361
 
362
    return (error);
363
}
364
 
365
// -------------------------------------------------------------------------
366
 
367
static int bsd_listen    ( cyg_file *fp, int backlog )
368
{
369
    return (solisten((struct socket *)fp->f_data, backlog));
370
}
371
 
372
// -------------------------------------------------------------------------
373
 
374
static int bsd_getname   ( cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer )
375
{
376
    register struct socket *so;
377
    struct mbuf *m;
378
    socklen_t len = 0;
379
    int error;
380
    int type = peer ? PRU_PEERADDR : PRU_SOCKADDR;
381
 
382
    if( alen != NULL )
383
        len = *alen;
384
 
385
    so = (struct socket *)fp->f_data;
386
 
387
    if ( peer && (so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
388
        return (ENOTCONN);
389
 
390
    m = m_getclr(M_WAIT, MT_SONAME);
391
    if (m == NULL)
392
        return (ENOBUFS);
393
 
394
    error = (*so->so_proto->pr_usrreq)(so, type, 0, m, 0);
395
    if (error)
396
        goto bad;
397
 
398
    if (len > m->m_len)
399
        len = m->m_len;
400
 
401
    error = copyout(mtod(m, caddr_t), (caddr_t)asa, len);
402
 
403
    if (error == 0)
404
        *alen = len;
405
 
406
bad:
407
    m_freem(m);
408
 
409
    return (error);
410
}
411
 
412
// -------------------------------------------------------------------------
413
 
414
static int bsd_shutdown  ( cyg_file *fp, int how )
415
{
416
    return (soshutdown((struct socket *)fp->f_data, how));
417
}
418
 
419
// -------------------------------------------------------------------------
420
 
421
static int bsd_getsockopt( cyg_file *fp, int level, int optname,
422
                           void *optval, socklen_t *optlen)
423
{
424
    struct mbuf *m = NULL;
425
    socklen_t valsize = 0;
426
    int error;
427
 
428
    if( optval != NULL && optlen != NULL )
429
        valsize = *optlen;
430
 
431
    error = sogetopt((struct socket *)fp->f_data, level, optname, &m);
432
 
433
    if( error == ENOERR && valsize != 0 && m != NULL)
434
    {
435
        if (valsize > m->m_len)
436
            valsize = m->m_len;
437
 
438
        error = copyout(mtod(m, caddr_t), optval, valsize);
439
 
440
        if( error == ENOERR )
441
            *optlen = valsize;
442
 
443
    }
444
 
445
    if (m != NULL)
446
        (void) m_free(m);
447
    return (error);
448
}
449
 
450
// -------------------------------------------------------------------------
451
 
452
static int bsd_setsockopt( cyg_file *fp, int level, int optname,
453
                           const void *optval, socklen_t optlen)
454
{
455
    int error;
456
    struct mbuf *m = NULL;
457
 
458
    if( optlen > MCLBYTES )
459
        return EINVAL;
460
 
461
    if (optval != NULL) {
462
        m = m_get(M_WAIT, MT_SOOPTS);
463
        if (optlen > MLEN) {
464
            MCLGET(m, M_DONTWAIT);
465
            if ((m->m_flags & M_EXT) == 0) {
466
                m_freem(m);
467
                return (ENOBUFS);
468
            }
469
        }
470
        if (m == NULL)
471
            return (ENOBUFS);
472
        error = copyin(optval, mtod(m, caddr_t), optlen);
473
        if (error) {
474
            (void) m_free(m);
475
            return (error);
476
        }
477
        m->m_len = optlen;
478
    }
479
 
480
    return (sosetopt((struct socket *)fp->f_data, level, optname, m));
481
}
482
 
483
// -------------------------------------------------------------------------
484
 
485
static int bsd_sendmsg   ( cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize )
486
{
487
    return bsd_sendit( fp, m, flags, retsize);
488
}
489
 
490
// -------------------------------------------------------------------------
491
 
492
static int bsd_recvmsg   ( cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize )
493
{
494
    return bsd_recvit( fp, m, namelen, retsize);
495
}
496
 
497
//==========================================================================
498
// File system call functions
499
 
500
// -------------------------------------------------------------------------
501
 
502
static int bsd_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
503
{
504
    return (soreceive((struct socket *)fp->f_data, (struct mbuf **)0,
505
                      uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0));
506
}
507
 
508
// -------------------------------------------------------------------------
509
 
510
static int bsd_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
511
{
512
        return (sosend((struct socket *)fp->f_data, (struct mbuf *)0,
513
                uio, (struct mbuf *)0, (struct mbuf *)0, 0));
514
}
515
 
516
// -------------------------------------------------------------------------
517
 
518
static int bsd_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
519
{
520
    return ESPIPE;
521
}
522
 
523
// -------------------------------------------------------------------------
524
 
525
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd,
526
                                CYG_ADDRWORD data)
527
{
528
        register struct socket *so = (struct socket *)fp->f_data;
529
        void *p = 0;
530
 
531
        switch (cmd) {
532
 
533
        case FIONBIO:
534
                if (*(int *)data)
535
                        so->so_state |= SS_NBIO;
536
                else
537
                        so->so_state &= ~SS_NBIO;
538
                return (0);
539
 
540
        case FIOASYNC:
541
                if (*(int *)data) {
542
                        so->so_state |= SS_ASYNC;
543
                        so->so_rcv.sb_flags |= SB_ASYNC;
544
                        so->so_snd.sb_flags |= SB_ASYNC;
545
                } else {
546
                        so->so_state &= ~SS_ASYNC;
547
                        so->so_rcv.sb_flags &= ~SB_ASYNC;
548
                        so->so_snd.sb_flags &= ~SB_ASYNC;
549
                }
550
                return (0);
551
 
552
        case FIONREAD:
553
                *(int *)data = so->so_rcv.sb_cc;
554
                return (0);
555
 
556
        case SIOCATMARK:
557
                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
558
                return (0);
559
        }
560
        /*
561
         * Interface/routing/protocol specific ioctls:
562
         * interface and routing ioctls should have a
563
         * different entry since a socket's unnecessary
564
         */
565
        if (IOCGROUP(cmd) == 'i')
566
                return (ifioctl(so, (u_long)cmd, (caddr_t)data, p));
567
        if (IOCGROUP(cmd) == 'r')
568
                return (rtioctl((u_long)cmd, (caddr_t)data, p));
569
        return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
570
            (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));
571
 
572
}
573
 
574
// -------------------------------------------------------------------------
575
 
576
static int bsd_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
577
{
578
    register struct socket *so = (struct socket *)fp->f_data;
579
    register int s = splsoftnet();
580
 
581
    switch (which) {
582
 
583
    case FREAD:
584
        if (soreadable(so)) {
585
            splx(s);
586
            return (1);
587
        }
588
        cyg_selrecord(info, &so->so_rcv.sb_sel);
589
        so->so_rcv.sb_flags |= SB_SEL;
590
        break;
591
 
592
    case FWRITE:
593
        if (sowriteable(so)) {
594
            splx(s);
595
            return (1);
596
        }
597
        cyg_selrecord(info, &so->so_snd.sb_sel);
598
        so->so_snd.sb_flags |= SB_SEL;
599
        break;
600
 
601
    case 0:
602
        if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
603
            splx(s);
604
            return (1);
605
        }
606
        cyg_selrecord(info, &so->so_rcv.sb_sel);
607
        so->so_rcv.sb_flags |= SB_SEL;
608
        break;
609
    }
610
    splx(s);
611
 
612
    return ENOERR;
613
}
614
 
615
// -------------------------------------------------------------------------
616
 
617
static int bsd_fsync     (struct CYG_FILE_TAG *fp, int mode )
618
{
619
    // FIXME: call some sort of flush IOCTL?
620
    return 0;
621
}
622
 
623
// -------------------------------------------------------------------------
624
 
625
static int bsd_close     (struct CYG_FILE_TAG *fp)
626
{
627
    int error = 0;
628
 
629
    if (fp->f_data)
630
        error = soclose((struct socket *)fp->f_data);
631
    fp->f_data = 0;
632
    return (error);
633
}
634
 
635
// -------------------------------------------------------------------------
636
 
637
static int bsd_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf )
638
{
639
    register struct socket *so = (struct socket *)fp->f_data;
640
 
641
    bzero((caddr_t)buf, sizeof (*buf));
642
 
643
    // Mark socket as a fifo for now. We need to add socket types to
644
    // sys/stat.h.
645
    buf->st_mode = __stat_mode_FIFO;
646
 
647
    return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
648
                                       (struct mbuf *)buf,
649
                                       (struct mbuf *)0,
650
                                       (struct mbuf *)0));
651
}
652
 
653
// -------------------------------------------------------------------------
654
 
655
static int bsd_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
656
{
657
    return ENOSYS;
658
}
659
 
660
// -------------------------------------------------------------------------
661
 
662
static int bsd_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
663
{
664
    return ENOSYS;
665
}
666
 
667
 
668
 
669
//==========================================================================
670
// Select support
671
 
672
// -------------------------------------------------------------------------
673
// This function is called by the lower layers to record the
674
// fact that a particular 'select' event is being requested.
675
//
676
 
677
void
678
selrecord(void *selector, struct selinfo *info)
679
{
680
    // Unused by this implementation
681
}
682
 
683
// -------------------------------------------------------------------------
684
// This function is called to indicate that a 'select' event
685
// may have occurred.
686
//
687
 
688
void
689
selwakeup(struct selinfo *info)
690
{
691
    cyg_selwakeup( info );
692
}
693
 
694
//==========================================================================
695
// Misc support functions
696
 
697
int
698
sockargs(mp, buf, buflen, type)
699
        struct mbuf **mp;
700
        caddr_t buf;
701
        socklen_t buflen;
702
        int type;
703
{
704
        register struct sockaddr *sa;
705
        register struct mbuf *m;
706
        int error;
707
 
708
        if (buflen > MLEN) {
709
#ifdef COMPAT_OLDSOCK
710
                if (type == MT_SONAME && buflen <= 112)
711
                        buflen = MLEN;          /* unix domain compat. hack */
712
                else
713
#endif
714
                return (EINVAL);
715
        }
716
        m = m_get(M_WAIT, type);
717
        if (m == NULL)
718
                return (ENOBUFS);
719
        m->m_len = buflen;
720
        error = copyin(buf, mtod(m, caddr_t), buflen);
721
        if (error) {
722
                (void) m_free(m);
723
                return (error);
724
        }
725
        *mp = m;
726
        if (type == MT_SONAME) {
727
                sa = mtod(m, struct sockaddr *);
728
 
729
#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
730
                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
731
                        sa->sa_family = sa->sa_len;
732
#endif
733
                sa->sa_len = buflen;
734
        }
735
        return (0);
736
}
737
 
738
 
739
// -------------------------------------------------------------------------
740
// bsd_recvit()
741
// Support for message reception. This is a lightly edited version of the
742
// recvit() function is uipc_syscalls.c.
743
 
744
static int
745
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize)
746
{
747
        struct uio auio;
748
        register struct iovec *iov;
749
        register int i;
750
        size_t len;
751
        int error;
752
        struct mbuf *from = 0, *control = 0;
753
 
754
        auio.uio_iov = mp->msg_iov;
755
        auio.uio_iovcnt = mp->msg_iovlen;
756
        auio.uio_segflg = UIO_USERSPACE;
757
        auio.uio_rw = UIO_READ;
758
        auio.uio_offset = 0;                     /* XXX */
759
        auio.uio_resid = 0;
760
        iov = mp->msg_iov;
761
        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
762
                /* Don't allow sum > SSIZE_MAX */
763
                if (iov->iov_len > SSIZE_MAX ||
764
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
765
                        return (EINVAL);
766
        }
767
 
768
        len = auio.uio_resid;
769
        error = soreceive((struct socket *)fp->f_data, &from, &auio,
770
                          NULL, mp->msg_control ? &control : NULL,
771
                          &mp->msg_flags);
772
        if (error) {
773
                if (auio.uio_resid != len &&
774
                    (error == EINTR || error == EWOULDBLOCK))
775
                        error = 0;
776
        }
777
        if (error)
778
                goto out;
779
        *retsize = len - auio.uio_resid;
780
        if (mp->msg_name) {
781
                len = mp->msg_namelen;
782
                if (len <= 0 || from == 0)
783
                        len = 0;
784
                else {
785
                        /* save sa_len before it is destroyed by MSG_COMPAT */
786
                        if (len > from->m_len)
787
                                len = from->m_len;
788
                        /* else if len < from->m_len ??? */
789
#ifdef COMPAT_OLDSOCK
790
                        if (mp->msg_flags & MSG_COMPAT)
791
                                mtod(from, struct osockaddr *)->sa_family =
792
                                    mtod(from, struct sockaddr *)->sa_family;
793
#endif
794
                        error = copyout(mtod(from, caddr_t),
795
                            (caddr_t)mp->msg_name, (unsigned)len);
796
                        if (error)
797
                                goto out;
798
                }
799
                mp->msg_namelen = len;
800
                if (namelenp ) {
801
                        *namelenp = len;
802
#ifdef COMPAT_OLDSOCK
803
                        if (mp->msg_flags & MSG_COMPAT)
804
                                error = 0;       /* old recvfrom didn't check */
805
                        else
806
#endif
807
                        goto out;
808
                }
809
        }
810
        if (mp->msg_control) {
811
#ifdef COMPAT_OLDSOCK
812
                /*
813
                 * We assume that old recvmsg calls won't receive access
814
                 * rights and other control info, esp. as control info
815
                 * is always optional and those options didn't exist in 4.3.
816
                 * If we receive rights, trim the cmsghdr; anything else
817
                 * is tossed.
818
                 */
819
                if (control && mp->msg_flags & MSG_COMPAT) {
820
                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
821
                            SOL_SOCKET ||
822
                            mtod(control, struct cmsghdr *)->cmsg_type !=
823
                            SCM_RIGHTS) {
824
                                mp->msg_controllen = 0;
825
                                goto out;
826
                        }
827
                        control->m_len -= sizeof (struct cmsghdr);
828
                        control->m_data += sizeof (struct cmsghdr);
829
                }
830
#endif
831
                len = mp->msg_controllen;
832
                if (len <= 0 || control == 0)
833
                        len = 0;
834
                else {
835
                        struct mbuf *m = control;
836
                        caddr_t p = (caddr_t)mp->msg_control;
837
 
838
                        do {
839
                                i = m->m_len;
840
                                if (len < i) {
841
                                        mp->msg_flags |= MSG_CTRUNC;
842
                                        i = len;
843
                                }
844
                                error = copyout(mtod(m, caddr_t), p,
845
                                    (unsigned)i);
846
                                if (m->m_next)
847
                                        i = ALIGN(i);
848
                                p += i;
849
                                len -= i;
850
                                if (error != 0 || len <= 0)
851
                                        break;
852
                        } while ((m = m->m_next) != NULL);
853
                        len = p - (caddr_t)mp->msg_control;
854
                }
855
                mp->msg_controllen = len;
856
        }
857
out:
858
        if (from)
859
                m_freem(from);
860
        if (control)
861
                m_freem(control);
862
        return (error);
863
}
864
 
865
// -------------------------------------------------------------------------
866
// sendit()
867
// Support for message transmission. This is a lightly edited version of the
868
// synonymous function is uipc_syscalls.c.
869
 
870
static int
871
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize)
872
{
873
        struct uio auio;
874
        register struct iovec *iov;
875
        register int i;
876
        struct mbuf *to, *control;
877
        int len, error;
878
 
879
        auio.uio_iov = mp->msg_iov;
880
        auio.uio_iovcnt = mp->msg_iovlen;
881
        auio.uio_segflg = UIO_USERSPACE;
882
        auio.uio_rw = UIO_WRITE;
883
        auio.uio_offset = 0;                     /* XXX */
884
        auio.uio_resid = 0;
885
        iov = mp->msg_iov;
886
        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
887
                /* Don't allow sum > SSIZE_MAX */
888
                if (iov->iov_len > SSIZE_MAX ||
889
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
890
                        return (EINVAL);
891
        }
892
        if (mp->msg_name) {
893
                error = sockargs(&to, mp->msg_name, mp->msg_namelen,
894
                                 MT_SONAME);
895
                if (error)
896
                        return (error);
897
        } else
898
                to = 0;
899
        if (mp->msg_control) {
900
                if (mp->msg_controllen < sizeof(struct cmsghdr)
901
#ifdef COMPAT_OLDSOCK
902
                    && mp->msg_flags != MSG_COMPAT
903
#endif
904
                ) {
905
                        error = EINVAL;
906
                        goto bad;
907
                }
908
                error = sockargs(&control, mp->msg_control,
909
                                 mp->msg_controllen, MT_CONTROL);
910
                if (error)
911
                        goto bad;
912
#ifdef COMPAT_OLDSOCK
913
                if (mp->msg_flags == MSG_COMPAT) {
914
                        register struct cmsghdr *cm;
915
 
916
                        M_PREPEND(control, sizeof(*cm), M_WAIT);
917
                        if (control == 0) {
918
                                error = ENOBUFS;
919
                                goto bad;
920
                        } else {
921
                                cm = mtod(control, struct cmsghdr *);
922
                                cm->cmsg_len = control->m_len;
923
                                cm->cmsg_level = SOL_SOCKET;
924
                                cm->cmsg_type = SCM_RIGHTS;
925
                        }
926
                }
927
#endif
928
        } else
929
                control = 0;
930
 
931
        len = auio.uio_resid;
932
        error = sosend((struct socket *)fp->f_data, to, &auio,
933
                       NULL, control, flags);
934
        if (error) {
935
                if (auio.uio_resid != len &&
936
                    (error == EINTR || error == EWOULDBLOCK))
937
                        error = 0;
938
#ifndef __ECOS
939
                if (error == EPIPE)
940
                        psignal(p, SIGPIPE);
941
#endif
942
        }
943
        if (error == 0)
944
                *retsize = len - auio.uio_resid;
945
bad:
946
        if (to)
947
                m_freem(to);
948
        return (error);
949
}
950
 
951
 
952
//==========================================================================
953
// End of sockio.c

powered by: WebSVN 2.1.0

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