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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [bsd_tcpip/] [current/] [src/] [sys/] [kern/] [sockio.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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