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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [kern/] [sockio.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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