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/] [uipc_socket.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/uipc_socket.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
 * Copyright (c) 1982, 1986, 1988, 1990, 1993
22
 *      The Regents of the University of California.  All rights reserved.
23
 *
24
 * Redistribution and use in source and binary forms, with or without
25
 * modification, are permitted provided that the following conditions
26
 * are met:
27
 * 1. Redistributions of source code must retain the above copyright
28
 *    notice, this list of conditions and the following disclaimer.
29
 * 2. Redistributions in binary form must reproduce the above copyright
30
 *    notice, this list of conditions and the following disclaimer in the
31
 *    documentation and/or other materials provided with the distribution.
32
 * 3. All advertising materials mentioning features or use of this software
33
 *    must display the following acknowledgement:
34
 *      This product includes software developed by the University of
35
 *      California, Berkeley and its contributors.
36
 * 4. Neither the name of the University nor the names of its contributors
37
 *    may be used to endorse or promote products derived from this software
38
 *    without specific prior written permission.
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
 * SUCH DAMAGE.
51
 *
52
 *      @(#)uipc_socket.c       8.3 (Berkeley) 4/15/94
53
 * $FreeBSD: src/sys/kern/uipc_socket.c,v 1.68.2.16 2001/06/14 20:46:06 ume Exp $
54
 */
55
 
56
#include <sys/param.h>
57
#include <sys/malloc.h>
58
#include <sys/mbuf.h>
59
#include <sys/domain.h>
60
#include <sys/malloc.h>
61
#include <sys/protosw.h>
62
#include <sys/socket.h>
63
#include <sys/socketvar.h>
64
 
65
#include <cyg/io/file.h>
66
#include <sys/time.h>
67
 
68
#ifdef INET
69
static int       do_setopt_accept_filter(struct socket *so, struct sockopt *sopt);
70
#endif /* INET */
71
 
72
#if 0  // FILT
73
static void     filt_sordetach(struct knote *kn);
74
static int      filt_soread(struct knote *kn, long hint);
75
static void     filt_sowdetach(struct knote *kn);
76
static int      filt_sowrite(struct knote *kn, long hint);
77
static int      filt_solisten(struct knote *kn, long hint);
78
 
79
static struct filterops solisten_filtops =
80
        { 1, NULL, filt_sordetach, filt_solisten };
81
static struct filterops soread_filtops =
82
        { 1, NULL, filt_sordetach, filt_soread };
83
static struct filterops sowrite_filtops =
84
        { 1, NULL, filt_sowdetach, filt_sowrite };
85
#endif
86
 
87
struct  vm_zone *socket_zone;
88
so_gen_t        so_gencnt;      /* generation count for sockets */
89
 
90
static int somaxconn = SOMAXCONN;
91
 
92
/*
93
 * Socket operation routines.
94
 * These routines are called by the routines in
95
 * sys_socket.c or from a system process, and
96
 * implement the semantics of socket operations by
97
 * switching out to the protocol specific routines.
98
 */
99
 
100
/*
101
 * Get a socket structure from our zone, and initialize it.
102
 * 'waitok' has been implemented for eCos, with [currently] some
103
 * rather fixed strategy - it will retry some number of times (10)
104
 * after at most 2 minutes.  This seems sufficient for sockets which
105
 * are tied up in the TCP close process.
106
 */
107
struct socket *
108
soalloc(int waitok)
109
{
110
    struct socket *so = NULL;
111
    int maxtries = waitok ? 10 : 1;
112
 
113
    while (maxtries-- > 0) {
114
        so = zalloci(socket_zone);
115
        if (so) {
116
            /* XXX race condition for reentrant kernel */
117
            bzero(so, sizeof *so);
118
            so->so_gencnt = ++so_gencnt;
119
            so->so_zone = socket_zone;
120
            TAILQ_INIT(&so->so_aiojobq);
121
            return so;
122
        }
123
        if (waitok) {
124
            diag_printf("DEBUG: Out of sockets - waiting\n");
125
            tsleep(socket_zone, PVM|PCATCH, "soalloc", 120*100);
126
            diag_printf("DEBUG: ... retry sockets\n");
127
        }
128
    }
129
    return so;
130
}
131
 
132
int
133
socreate(dom, aso, type, proto, p)
134
        int dom;
135
        struct socket **aso;
136
        register int type;
137
        int proto;
138
        struct proc *p;
139
{
140
        register struct protosw *prp;
141
        register struct socket *so;
142
        register int error;
143
 
144
        if (proto)
145
                prp = pffindproto(dom, proto, type);
146
        else
147
                prp = pffindtype(dom, type);
148
 
149
        if (prp == 0 || prp->pr_usrreqs->pru_attach == 0)
150
                return (EPROTONOSUPPORT);
151
 
152
        if (prp->pr_type != type)
153
                return (EPROTOTYPE);
154
        so = soalloc(p != 0);
155
        if (so == 0) {
156
                return (ENOBUFS);
157
        }
158
 
159
        TAILQ_INIT(&so->so_incomp);
160
        TAILQ_INIT(&so->so_comp);
161
        so->so_type = type;
162
        so->so_proto = prp;
163
        error = (*prp->pr_usrreqs->pru_attach)(so, proto, p);
164
        if (error) {
165
                so->so_state |= SS_NOFDREF;
166
                sofree(so);
167
                return (error);
168
        }
169
        *aso = so;
170
        return (0);
171
}
172
 
173
int
174
sobind(so, nam, p)
175
        struct socket *so;
176
        struct sockaddr *nam;
177
        struct proc *p;
178
{
179
        int s = splnet();
180
        int error;
181
 
182
        error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, p);
183
        splx(s);
184
        return (error);
185
}
186
 
187
void
188
sodealloc(so)
189
        struct socket *so;
190
 
191
{
192
        vm_zone_t zone;
193
 
194
        so->so_gencnt = ++so_gencnt;
195
#ifdef INET
196
        if (so->so_accf != NULL) {
197
                if (so->so_accf->so_accept_filter != NULL &&
198
                        so->so_accf->so_accept_filter->accf_destroy != NULL) {
199
                        so->so_accf->so_accept_filter->accf_destroy(so);
200
                }
201
                if (so->so_accf->so_accept_filter_str != NULL)
202
                        FREE(so->so_accf->so_accept_filter_str, M_ACCF);
203
                FREE(so->so_accf, M_ACCF);
204
        }
205
#endif /* INET */
206
        zone = so->so_zone;
207
        zfreei(zone, so);
208
        wakeup(zone);
209
}
210
 
211
int
212
solisten(so, backlog, p)
213
        register struct socket *so;
214
        int backlog;
215
        struct proc *p;
216
{
217
        int s, error;
218
 
219
        s = splnet();
220
        error = (*so->so_proto->pr_usrreqs->pru_listen)(so, p);
221
        if (error) {
222
                splx(s);
223
                return (error);
224
        }
225
        if (TAILQ_EMPTY(&so->so_comp))
226
                so->so_options |= SO_ACCEPTCONN;
227
        if (backlog < 0 || backlog > somaxconn)
228
                backlog = somaxconn;
229
        so->so_qlimit = backlog;
230
        splx(s);
231
        return (0);
232
}
233
 
234
void
235
sofree(so)
236
        register struct socket *so;
237
{
238
        struct socket *head = so->so_head;
239
 
240
        if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
241
                return;
242
        if (head != NULL) {
243
                if (so->so_state & SS_INCOMP) {
244
                        TAILQ_REMOVE(&head->so_incomp, so, so_list);
245
                        head->so_incqlen--;
246
                } else if (so->so_state & SS_COMP) {
247
                        /*
248
                         * We must not decommission a socket that's
249
                         * on the accept(2) queue.  If we do, then
250
                         * accept(2) may hang after select(2) indicated
251
                         * that the listening socket was ready.
252
                         */
253
                        return;
254
                } else {
255
                        panic("sofree: not queued");
256
                }
257
                head->so_qlen--;
258
                so->so_state &= ~SS_INCOMP;
259
                so->so_head = NULL;
260
        }
261
        sbrelease(&so->so_snd, so);
262
        sorflush(so);
263
        sodealloc(so);
264
}
265
 
266
/*
267
 * Close a socket on last file table reference removal.
268
 * Initiate disconnect if connected.
269
 * Free socket when disconnect complete.
270
 */
271
int
272
soclose(so)
273
        register struct socket *so;
274
{
275
        int s = splnet();               /* conservative */
276
        int error = 0;
277
 
278
        if (so->so_options & SO_ACCEPTCONN) {
279
                struct socket *sp, *sonext;
280
 
281
                sp = TAILQ_FIRST(&so->so_incomp);
282
                for (; sp != NULL; sp = sonext) {
283
                        sonext = TAILQ_NEXT(sp, so_list);
284
                        (void) soabort(sp);
285
                }
286
                for (sp = TAILQ_FIRST(&so->so_comp); sp != NULL; sp = sonext) {
287
                        sonext = TAILQ_NEXT(sp, so_list);
288
                        /* Dequeue from so_comp since sofree() won't do it */
289
                        TAILQ_REMOVE(&so->so_comp, sp, so_list);
290
                        so->so_qlen--;
291
                        sp->so_state &= ~SS_COMP;
292
                        sp->so_head = NULL;
293
                        (void) soabort(sp);
294
                }
295
        }
296
        if (so->so_pcb == 0)
297
                goto discard;
298
        if (so->so_state & SS_ISCONNECTED) {
299
                if ((so->so_state & SS_ISDISCONNECTING) == 0) {
300
                        error = sodisconnect(so);
301
                        if (error)
302
                                goto drop;
303
                }
304
                if (so->so_options & SO_LINGER) {
305
                        if ((so->so_state & SS_ISDISCONNECTING) &&
306
                            (so->so_state & SS_NBIO))
307
                                goto drop;
308
                        while (so->so_state & SS_ISCONNECTED) {
309
                                error = tsleep((caddr_t)&so->so_timeo,
310
                                    PSOCK | PCATCH, "soclos", so->so_linger * hz);
311
                                if (error)
312
                                        break;
313
                        }
314
                }
315
        }
316
drop:
317
        if (so->so_pcb) {
318
                int error2 = (*so->so_proto->pr_usrreqs->pru_detach)(so);
319
                if (error == 0)
320
                        error = error2;
321
        }
322
discard:
323
        if (so->so_state & SS_NOFDREF)
324
                panic("soclose: NOFDREF");
325
        so->so_state |= SS_NOFDREF;
326
        sofree(so);
327
        splx(s);
328
        return (error);
329
}
330
 
331
/*
332
 * Must be called at splnet...
333
 */
334
int
335
soabort(so)
336
        struct socket *so;
337
{
338
        int error;
339
 
340
        error = (*so->so_proto->pr_usrreqs->pru_abort)(so);
341
        if (error) {
342
                sofree(so);
343
                return error;
344
        }
345
        return (0);
346
}
347
 
348
int
349
soaccept(so, nam)
350
        register struct socket *so;
351
        struct sockaddr **nam;
352
{
353
        int s = splnet();
354
        int error;
355
 
356
        if ((so->so_state & SS_NOFDREF) == 0)
357
                panic("soaccept: !NOFDREF");
358
        so->so_state &= ~SS_NOFDREF;
359
        error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
360
        splx(s);
361
        return (error);
362
}
363
 
364
int
365
soconnect(so, nam, p)
366
        register struct socket *so;
367
        struct sockaddr *nam;
368
        struct proc *p;
369
{
370
        int s;
371
        int error;
372
 
373
        if (so->so_options & SO_ACCEPTCONN)
374
                return (EOPNOTSUPP);
375
        s = splnet();
376
        /*
377
         * If protocol is connection-based, can only connect once.
378
         * Otherwise, if connected, try to disconnect first.
379
         * This allows user to disconnect by connecting to, e.g.,
380
         * a null address.
381
         */
382
        if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
383
            ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
384
            (error = sodisconnect(so))))
385
                error = EISCONN;
386
        else
387
                error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, p);
388
        splx(s);
389
        return (error);
390
}
391
 
392
int
393
soconnect2(so1, so2)
394
        register struct socket *so1;
395
        struct socket *so2;
396
{
397
        int s = splnet();
398
        int error;
399
 
400
        error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
401
        splx(s);
402
        return (error);
403
}
404
 
405
int
406
sodisconnect(so)
407
        register struct socket *so;
408
{
409
        int s = splnet();
410
        int error;
411
 
412
        if ((so->so_state & SS_ISCONNECTED) == 0) {
413
                error = ENOTCONN;
414
                goto bad;
415
        }
416
        if (so->so_state & SS_ISDISCONNECTING) {
417
                error = EALREADY;
418
                goto bad;
419
        }
420
        error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
421
bad:
422
        splx(s);
423
        return (error);
424
}
425
 
426
#define SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
427
/*
428
 * Send on a socket.
429
 * If send must go all at once and message is larger than
430
 * send buffering, then hard error.
431
 * Lock against other senders.
432
 * If must go all at once and not enough room now, then
433
 * inform user that this would block and do nothing.
434
 * Otherwise, if nonblocking, send as much as possible.
435
 * The data to be sent is described by "uio" if nonzero,
436
 * otherwise by the mbuf chain "top" (which must be null
437
 * if uio is not).  Data provided in mbuf chain must be small
438
 * enough to send all at once.
439
 *
440
 * Returns nonzero on error, timeout or signal; callers
441
 * must check for short counts if EINTR/ERESTART are returned.
442
 * Data and control buffers are freed on return.
443
 */
444
int
445
sosend(so, addr, uio, top, control, flags, p)
446
        register struct socket *so;
447
        struct sockaddr *addr;
448
        struct uio *uio;
449
        struct mbuf *top;
450
        struct mbuf *control;
451
        int flags;
452
        struct proc *p;
453
{
454
        struct mbuf **mp;
455
        register struct mbuf *m;
456
        register long space, len, resid;
457
        int clen = 0, error, s, dontroute, mlen;
458
        int atomic = sosendallatonce(so) || top;
459
 
460
        if (uio)
461
                resid = uio->uio_resid;
462
        else
463
                resid = top->m_pkthdr.len;
464
        /*
465
         * In theory resid should be unsigned.
466
         * However, space must be signed, as it might be less than 0
467
         * if we over-committed, and we must use a signed comparison
468
         * of space and resid.  On the other hand, a negative resid
469
         * causes us to loop sending 0-length segments to the protocol.
470
         *
471
         * Also check to make sure that MSG_EOR isn't used on SOCK_STREAM
472
         * type sockets since that's an error.
473
         */
474
        if (resid < 0 || (so->so_type == SOCK_STREAM && (flags & MSG_EOR))) {
475
                error = EINVAL;
476
                goto out;
477
        }
478
 
479
        dontroute =
480
            (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
481
            (so->so_proto->pr_flags & PR_ATOMIC);
482
        if (control)
483
                clen = control->m_len;
484
#define snderr(errno)   { error = errno; splx(s); goto release; }
485
 
486
restart:
487
        error = sblock(&so->so_snd, SBLOCKWAIT(flags));
488
        if (error)
489
                goto out;
490
        do {
491
                s = splnet();
492
                if (so->so_state & SS_CANTSENDMORE)
493
                        snderr(EPIPE);
494
                if (so->so_error) {
495
                        error = so->so_error;
496
                        so->so_error = 0;
497
                        splx(s);
498
                        goto release;
499
                }
500
                if ((so->so_state & SS_ISCONNECTED) == 0) {
501
                        /*
502
                         * `sendto' and `sendmsg' is allowed on a connection-
503
                         * based socket if it supports implied connect.
504
                         * Return ENOTCONN if not connected and no address is
505
                         * supplied.
506
                         */
507
                        if ((so->so_proto->pr_flags & PR_CONNREQUIRED) &&
508
                            (so->so_proto->pr_flags & PR_IMPLOPCL) == 0) {
509
                                if ((so->so_state & SS_ISCONFIRMING) == 0 &&
510
                                    !(resid == 0 && clen != 0))
511
                                        snderr(ENOTCONN);
512
                        } else if (addr == 0)
513
                            snderr(so->so_proto->pr_flags & PR_CONNREQUIRED ?
514
                                   ENOTCONN : EDESTADDRREQ);
515
                }
516
                space = sbspace(&so->so_snd);
517
                if (flags & MSG_OOB)
518
                        space += 1024;
519
                if ((atomic && resid > so->so_snd.sb_hiwat) ||
520
                    clen > so->so_snd.sb_hiwat)
521
                        snderr(EMSGSIZE);
522
                if (space < resid + clen && uio &&
523
                    (atomic || space < so->so_snd.sb_lowat || space < clen)) {
524
                        if (so->so_state & SS_NBIO)
525
                                snderr(EWOULDBLOCK);
526
                        sbunlock(&so->so_snd);
527
                        error = sbwait(&so->so_snd);
528
                        splx(s);
529
                        if (error)
530
                                goto out;
531
                        goto restart;
532
                }
533
                splx(s);
534
                mp = &top;
535
                space -= clen;
536
                do {
537
                    if (uio == NULL) {
538
                        /*
539
                         * Data is prepackaged in "top".
540
                         */
541
                        resid = 0;
542
                        if (flags & MSG_EOR)
543
                                top->m_flags |= M_EOR;
544
                    } else do {
545
                        if (top == 0) {
546
                                MGETHDR(m, M_WAIT, MT_DATA);
547
                                if (m == NULL) {
548
                                        error = ENOBUFS;
549
                                        goto release;
550
                                }
551
                                mlen = MHLEN;
552
                                m->m_pkthdr.len = 0;
553
                                m->m_pkthdr.rcvif = (struct ifnet *)0;
554
                        } else {
555
                                MGET(m, M_WAIT, MT_DATA);
556
                                if (m == NULL) {
557
                                        error = ENOBUFS;
558
                                        goto release;
559
                                }
560
                                mlen = MLEN;
561
                        }
562
                        if (resid >= MINCLSIZE) {
563
                                MCLGET(m, M_WAIT);
564
                                if ((m->m_flags & M_EXT) == 0)
565
                                        goto nopages;
566
                                mlen = MCLBYTES;
567
                                len = min(min(mlen, resid), space);
568
                        } else {
569
nopages:
570
                                len = min(min(mlen, resid), space);
571
                                /*
572
                                 * For datagram protocols, leave room
573
                                 * for protocol headers in first mbuf.
574
                                 */
575
                                if (atomic && top == 0 && len < mlen)
576
                                        MH_ALIGN(m, len);
577
                        }
578
                        space -= len;
579
                        error = uiomove(mtod(m, caddr_t), (int)len, uio);
580
                        resid = uio->uio_resid;
581
                        m->m_len = len;
582
                        *mp = m;
583
                        top->m_pkthdr.len += len;
584
                        if (error)
585
                                goto release;
586
                        mp = &m->m_next;
587
                        if (resid <= 0) {
588
                                if (flags & MSG_EOR)
589
                                        top->m_flags |= M_EOR;
590
                                break;
591
                        }
592
                    } while (space > 0 && atomic);
593
                    if (dontroute)
594
                            so->so_options |= SO_DONTROUTE;
595
                    s = splnet();                               /* XXX */
596
                    /*
597
                     * XXX all the SS_CANTSENDMORE checks previously
598
                     * done could be out of date.  We could have recieved
599
                     * a reset packet in an interrupt or maybe we slept
600
                     * while doing page faults in uiomove() etc. We could
601
                     * probably recheck again inside the splnet() protection
602
                     * here, but there are probably other places that this
603
                     * also happens.  We must rethink this.
604
                     */
605
                    error = (*so->so_proto->pr_usrreqs->pru_send)(so,
606
                        (flags & MSG_OOB) ? PRUS_OOB :
607
                        /*
608
                         * If the user set MSG_EOF, the protocol
609
                         * understands this flag and nothing left to
610
                         * send then use PRU_SEND_EOF instead of PRU_SEND.
611
                         */
612
                        ((flags & MSG_EOF) &&
613
                         (so->so_proto->pr_flags & PR_IMPLOPCL) &&
614
                         (resid <= 0)) ?
615
                                PRUS_EOF :
616
                        /* If there is more to send set PRUS_MORETOCOME */
617
                        (resid > 0 && space > 0) ? PRUS_MORETOCOME : 0,
618
                        top, addr, control, p);
619
                    splx(s);
620
                    if (dontroute)
621
                            so->so_options &= ~SO_DONTROUTE;
622
                    clen = 0;
623
                    control = 0;
624
                    top = 0;
625
                    mp = &top;
626
                    if (error)
627
                        goto release;
628
                } while (resid && space > 0);
629
        } while (resid);
630
 
631
release:
632
        sbunlock(&so->so_snd);
633
out:
634
        if (top)
635
                m_freem(top);
636
        if (control)
637
                m_freem(control);
638
        return (error);
639
}
640
 
641
/*
642
 * Implement receive operations on a socket.
643
 * We depend on the way that records are added to the sockbuf
644
 * by sbappend*.  In particular, each record (mbufs linked through m_next)
645
 * must begin with an address if the protocol so specifies,
646
 * followed by an optional mbuf or mbufs containing ancillary data,
647
 * and then zero or more mbufs of data.
648
 * In order to avoid blocking network interrupts for the entire time here,
649
 * we splx() while doing the actual copy to user space.
650
 * Although the sockbuf is locked, new data may still be appended,
651
 * and thus we must maintain consistency of the sockbuf during that time.
652
 *
653
 * The caller may receive the data as a single mbuf chain by supplying
654
 * an mbuf **mp0 for use in returning the chain.  The uio is then used
655
 * only for the count in uio_resid.
656
 */
657
int
658
soreceive(so, psa, uio, mp0, controlp, flagsp)
659
        register struct socket *so;
660
        struct sockaddr **psa;
661
        struct uio *uio;
662
        struct mbuf **mp0;
663
        struct mbuf **controlp;
664
        int *flagsp;
665
{
666
        register struct mbuf *m, **mp;
667
        register int flags, len, error, s, offset;
668
        struct protosw *pr = so->so_proto;
669
        struct mbuf *nextrecord;
670
        int moff, type = 0;
671
        int orig_resid = uio->uio_resid;
672
 
673
        mp = mp0;
674
        if (psa)
675
                *psa = 0;
676
        if (controlp)
677
                *controlp = 0;
678
        if (flagsp)
679
                flags = *flagsp &~ MSG_EOR;
680
        else
681
                flags = 0;
682
        if (flags & MSG_OOB) {
683
                m = m_get(M_WAIT, MT_DATA);
684
                if (m == NULL) {
685
                        return (ENOBUFS);
686
                }
687
                error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
688
                if (error)
689
                        goto bad;
690
                do {
691
                        error = uiomove(mtod(m, caddr_t),
692
                            (int) min(uio->uio_resid, m->m_len), uio);
693
                        m = m_free(m);
694
                } while (uio->uio_resid && error == 0 && m);
695
bad:
696
                if (m)
697
                        m_freem(m);
698
                return (error);
699
        }
700
        if (mp)
701
                *mp = (struct mbuf *)0;
702
        if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
703
                (*pr->pr_usrreqs->pru_rcvd)(so, 0);
704
 
705
restart:
706
        error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
707
        if (error)
708
                return (error);
709
        s = splnet();
710
 
711
        m = so->so_rcv.sb_mb;
712
        /*
713
         * If we have less data than requested, block awaiting more
714
         * (subject to any timeout) if:
715
         *   1. the current count is less than the low water mark, or
716
         *   2. MSG_WAITALL is set, and it is possible to do the entire
717
         *      receive operation at once if we block (resid <= hiwat).
718
         *   3. MSG_DONTWAIT is not set
719
         * If MSG_WAITALL is set but resid is larger than the receive buffer,
720
         * we have to do the receive in sections, and thus risk returning
721
         * a short count if a timeout or signal occurs after we start.
722
         */
723
        if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
724
            so->so_rcv.sb_cc < uio->uio_resid) &&
725
            (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
726
            ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
727
            m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
728
                if (so->so_error) {
729
                        if (m)
730
                                goto dontblock;
731
                        error = so->so_error;
732
                        if ((flags & MSG_PEEK) == 0)
733
                                so->so_error = 0;
734
                        goto release;
735
                }
736
                if (so->so_state & SS_CANTRCVMORE) {
737
                        if (m)
738
                                goto dontblock;
739
                        else
740
                                goto release;
741
                }
742
                for (; m; m = m->m_next)
743
                        if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
744
                                m = so->so_rcv.sb_mb;
745
                                goto dontblock;
746
                        }
747
                if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
748
                    (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
749
                        error = ENOTCONN;
750
                        goto release;
751
                }
752
                if (uio->uio_resid == 0)
753
                        goto release;
754
                if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
755
                        error = EWOULDBLOCK;
756
                        goto release;
757
                }
758
                sbunlock(&so->so_rcv);
759
                error = sbwait(&so->so_rcv);
760
                splx(s);
761
                if (error)
762
                        return (error);
763
                goto restart;
764
        }
765
dontblock:
766
        nextrecord = m->m_nextpkt;
767
        if (pr->pr_flags & PR_ADDR) {
768
                orig_resid = 0;
769
                if (psa)
770
                        *psa = dup_sockaddr(mtod(m, struct sockaddr *),
771
                                            mp0 == 0);
772
                if (flags & MSG_PEEK) {
773
                        m = m->m_next;
774
                } else {
775
                        sbfree(&so->so_rcv, m);
776
                        MFREE(m, so->so_rcv.sb_mb);
777
                        m = so->so_rcv.sb_mb;
778
                }
779
        }
780
        while (m && m->m_type == MT_CONTROL && error == 0) {
781
                if (flags & MSG_PEEK) {
782
                        if (controlp)
783
                                *controlp = m_copy(m, 0, m->m_len);
784
                        m = m->m_next;
785
                } else {
786
                        sbfree(&so->so_rcv, m);
787
                        if (controlp) {
788
                                if (pr->pr_domain->dom_externalize &&
789
                                    mtod(m, struct cmsghdr *)->cmsg_type ==
790
                                    SCM_RIGHTS)
791
                                   error = (*pr->pr_domain->dom_externalize)(m);
792
                                *controlp = m;
793
                                so->so_rcv.sb_mb = m->m_next;
794
                                m->m_next = 0;
795
                                m = so->so_rcv.sb_mb;
796
                        } else {
797
                                MFREE(m, so->so_rcv.sb_mb);
798
                                m = so->so_rcv.sb_mb;
799
                        }
800
                }
801
                if (controlp) {
802
                        orig_resid = 0;
803
                        controlp = &(*controlp)->m_next;
804
                }
805
        }
806
        if (m) {
807
                if ((flags & MSG_PEEK) == 0)
808
                        m->m_nextpkt = nextrecord;
809
                type = m->m_type;
810
                if (type == MT_OOBDATA)
811
                        flags |= MSG_OOB;
812
        }
813
        moff = 0;
814
        offset = 0;
815
        while (m && uio->uio_resid > 0 && error == 0) {
816
                if (m->m_type == MT_OOBDATA) {
817
                        if (type != MT_OOBDATA)
818
                                break;
819
                } else if (type == MT_OOBDATA)
820
                        break;
821
                so->so_state &= ~SS_RCVATMARK;
822
                len = uio->uio_resid;
823
                if (so->so_oobmark && len > so->so_oobmark - offset)
824
                        len = so->so_oobmark - offset;
825
                if (len > m->m_len - moff)
826
                        len = m->m_len - moff;
827
                /*
828
                 * If mp is set, just pass back the mbufs.
829
                 * Otherwise copy them out via the uio, then free.
830
                 * Sockbuf must be consistent here (points to current mbuf,
831
                 * it points to next record) when we drop priority;
832
                 * we must note any additions to the sockbuf when we
833
                 * block interrupts again.
834
                 */
835
                if (mp == 0) {
836
                        splx(s);
837
                        error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
838
                        s = splnet();
839
                        if (error)
840
                                goto release;
841
                } else
842
                        uio->uio_resid -= len;
843
                if (len == m->m_len - moff) {
844
                        if (m->m_flags & M_EOR)
845
                                flags |= MSG_EOR;
846
                        if (flags & MSG_PEEK) {
847
                                m = m->m_next;
848
                                moff = 0;
849
                        } else {
850
                                nextrecord = m->m_nextpkt;
851
                                sbfree(&so->so_rcv, m);
852
                                if (mp) {
853
                                        *mp = m;
854
                                        mp = &m->m_next;
855
                                        so->so_rcv.sb_mb = m = m->m_next;
856
                                        *mp = (struct mbuf *)0;
857
                                } else {
858
                                        MFREE(m, so->so_rcv.sb_mb);
859
                                        m = so->so_rcv.sb_mb;
860
                                }
861
                                if (m)
862
                                        m->m_nextpkt = nextrecord;
863
                        }
864
                } else {
865
                        if (flags & MSG_PEEK)
866
                                moff += len;
867
                        else {
868
                                if (mp)
869
                                        *mp = m_copym(m, 0, len, M_WAIT);
870
                                m->m_data += len;
871
                                m->m_len -= len;
872
                                so->so_rcv.sb_cc -= len;
873
                        }
874
                }
875
                if (so->so_oobmark) {
876
                        if ((flags & MSG_PEEK) == 0) {
877
                                so->so_oobmark -= len;
878
                                if (so->so_oobmark == 0) {
879
                                        so->so_state |= SS_RCVATMARK;
880
                                        break;
881
                                }
882
                        } else {
883
                                offset += len;
884
                                if (offset == so->so_oobmark)
885
                                        break;
886
                        }
887
                }
888
                if (flags & MSG_EOR)
889
                        break;
890
                /*
891
                 * If the MSG_WAITALL flag is set (for non-atomic socket),
892
                 * we must not quit until "uio->uio_resid == 0" or an error
893
                 * termination.  If a signal/timeout occurs, return
894
                 * with a short count but without error.
895
                 * Keep sockbuf locked against other readers.
896
                 */
897
                while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
898
                    !sosendallatonce(so) && !nextrecord) {
899
                        if (so->so_error || so->so_state & SS_CANTRCVMORE)
900
                                break;
901
                        error = sbwait(&so->so_rcv);
902
                        if (error) {
903
                                sbunlock(&so->so_rcv);
904
                                splx(s);
905
                                return (0);
906
                        }
907
                        m = so->so_rcv.sb_mb;
908
                        if (m)
909
                                nextrecord = m->m_nextpkt;
910
                }
911
        }
912
 
913
        if (m && pr->pr_flags & PR_ATOMIC) {
914
                flags |= MSG_TRUNC;
915
                if ((flags & MSG_PEEK) == 0)
916
                        (void) sbdroprecord(&so->so_rcv);
917
        }
918
        if ((flags & MSG_PEEK) == 0) {
919
                if (m == 0)
920
                        so->so_rcv.sb_mb = nextrecord;
921
                if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
922
                        (*pr->pr_usrreqs->pru_rcvd)(so, flags);
923
        }
924
        if (orig_resid == uio->uio_resid && orig_resid &&
925
            (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
926
                sbunlock(&so->so_rcv);
927
                splx(s);
928
                goto restart;
929
        }
930
 
931
        if (flagsp)
932
                *flagsp |= flags;
933
release:
934
        sbunlock(&so->so_rcv);
935
        splx(s);
936
        return (error);
937
}
938
 
939
int
940
soshutdown(so, how)
941
        register struct socket *so;
942
        register int how;
943
{
944
        register struct protosw *pr = so->so_proto;
945
 
946
        if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
947
                return (EINVAL);
948
 
949
        if (how != SHUT_WR)
950
                sorflush(so);
951
        if (how != SHUT_RD)
952
                return ((*pr->pr_usrreqs->pru_shutdown)(so));
953
        return (0);
954
}
955
 
956
void
957
sorflush(so)
958
        register struct socket *so;
959
{
960
        register struct sockbuf *sb = &so->so_rcv;
961
        register struct protosw *pr = so->so_proto;
962
        register int s;
963
        struct sockbuf asb;
964
 
965
        sb->sb_flags |= SB_NOINTR;
966
        (void) sblock(sb, M_WAITOK);
967
        s = splimp();
968
        socantrcvmore(so);
969
        sbunlock(sb);
970
        asb = *sb;
971
        bzero((caddr_t)sb, sizeof (*sb));
972
        splx(s);
973
        if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
974
                (*pr->pr_domain->dom_dispose)(asb.sb_mb);
975
        sbrelease(&asb, so);
976
}
977
 
978
#ifdef INET
979
static int
980
do_setopt_accept_filter(so, sopt)
981
        struct  socket *so;
982
        struct  sockopt *sopt;
983
{
984
        struct accept_filter_arg        *afap = NULL;
985
        struct accept_filter    *afp;
986
        struct so_accf  *af = so->so_accf;
987
        int     error = 0;
988
 
989
        /* do not set/remove accept filters on non listen sockets */
990
        if ((so->so_options & SO_ACCEPTCONN) == 0) {
991
                error = EINVAL;
992
                goto out;
993
        }
994
 
995
        /* removing the filter */
996
        if (sopt == NULL) {
997
                if (af != NULL) {
998
                        if (af->so_accept_filter != NULL &&
999
                                af->so_accept_filter->accf_destroy != NULL) {
1000
                                af->so_accept_filter->accf_destroy(so);
1001
                        }
1002
                        if (af->so_accept_filter_str != NULL) {
1003
                                FREE(af->so_accept_filter_str, M_ACCF);
1004
                        }
1005
                        FREE(af, M_ACCF);
1006
                        so->so_accf = NULL;
1007
                }
1008
                so->so_options &= ~SO_ACCEPTFILTER;
1009
                return (0);
1010
        }
1011
        /* adding a filter */
1012
        /* must remove previous filter first */
1013
        if (af != NULL) {
1014
                error = EINVAL;
1015
                goto out;
1016
        }
1017
        /* don't put large objects on the kernel stack */
1018
        MALLOC(afap, struct accept_filter_arg *, sizeof(*afap), M_TEMP, M_WAITOK);
1019
        error = sooptcopyin(sopt, afap, sizeof *afap, sizeof *afap);
1020
        afap->af_name[sizeof(afap->af_name)-1] = '\0';
1021
        afap->af_arg[sizeof(afap->af_arg)-1] = '\0';
1022
        if (error)
1023
                goto out;
1024
        afp = accept_filt_get(afap->af_name);
1025
        if (afp == NULL) {
1026
                error = ENOENT;
1027
                goto out;
1028
        }
1029
        MALLOC(af, struct so_accf *, sizeof(*af), M_ACCF, M_WAITOK);
1030
        bzero(af, sizeof(*af));
1031
        if (afp->accf_create != NULL) {
1032
                if (afap->af_name[0] != '\0') {
1033
                        int len = strlen(afap->af_name) + 1;
1034
 
1035
                        MALLOC(af->so_accept_filter_str, char *, len, M_ACCF, M_WAITOK);
1036
                        strcpy(af->so_accept_filter_str, afap->af_name);
1037
                }
1038
                af->so_accept_filter_arg = afp->accf_create(so, afap->af_arg);
1039
                if (af->so_accept_filter_arg == NULL) {
1040
                        FREE(af->so_accept_filter_str, M_ACCF);
1041
                        FREE(af, M_ACCF);
1042
                        so->so_accf = NULL;
1043
                        error = EINVAL;
1044
                        goto out;
1045
                }
1046
        }
1047
        af->so_accept_filter = afp;
1048
        so->so_accf = af;
1049
        so->so_options |= SO_ACCEPTFILTER;
1050
out:
1051
        if (afap != NULL)
1052
                FREE(afap, M_TEMP);
1053
        return (error);
1054
}
1055
#endif /* INET */
1056
 
1057
/*
1058
 * Perhaps this routine, and sooptcopyout(), below, ought to come in
1059
 * an additional variant to handle the case where the option value needs
1060
 * to be some kind of integer, but not a specific size.
1061
 * In addition to their use here, these functions are also called by the
1062
 * protocol-level pr_ctloutput() routines.
1063
 */
1064
int
1065
sooptcopyin(sopt, buf, len, minlen)
1066
        struct  sockopt *sopt;
1067
        void    *buf;
1068
        size_t  len;
1069
        size_t  minlen;
1070
{
1071
        size_t  valsize;
1072
 
1073
        /*
1074
         * If the user gives us more than we wanted, we ignore it,
1075
         * but if we don't get the minimum length the caller
1076
         * wants, we return EINVAL.  On success, sopt->sopt_valsize
1077
         * is set to however much we actually retrieved.
1078
         */
1079
        if ((valsize = sopt->sopt_valsize) < minlen)
1080
                return EINVAL;
1081
        if (valsize > len)
1082
                sopt->sopt_valsize = valsize = len;
1083
 
1084
        if (sopt->sopt_p != 0)
1085
                return (copyin(sopt->sopt_val, buf, valsize));
1086
 
1087
        bcopy(sopt->sopt_val, buf, valsize);
1088
        return 0;
1089
}
1090
 
1091
int
1092
sosetopt(so, sopt)
1093
        struct socket *so;
1094
        struct sockopt *sopt;
1095
{
1096
        int     error, optval;
1097
        struct  linger l;
1098
        struct  timeval tv;
1099
        u_long  val;
1100
 
1101
        error = 0;
1102
        if (sopt->sopt_level != SOL_SOCKET) {
1103
                if (so->so_proto && so->so_proto->pr_ctloutput)
1104
                        return ((*so->so_proto->pr_ctloutput)
1105
                                  (so, sopt));
1106
                error = ENOPROTOOPT;
1107
        } else {
1108
                switch (sopt->sopt_name) {
1109
#ifdef INET
1110
                case SO_ACCEPTFILTER:
1111
                        error = do_setopt_accept_filter(so, sopt);
1112
                        if (error)
1113
                                goto bad;
1114
                        break;
1115
#endif /* INET */
1116
                case SO_LINGER:
1117
                        error = sooptcopyin(sopt, &l, sizeof l, sizeof l);
1118
                        if (error)
1119
                                goto bad;
1120
 
1121
                        so->so_linger = l.l_linger;
1122
                        if (l.l_onoff)
1123
                                so->so_options |= SO_LINGER;
1124
                        else
1125
                                so->so_options &= ~SO_LINGER;
1126
                        break;
1127
 
1128
                case SO_DEBUG:
1129
                case SO_KEEPALIVE:
1130
                case SO_DONTROUTE:
1131
                case SO_USELOOPBACK:
1132
                case SO_BROADCAST:
1133
                case SO_REUSEADDR:
1134
                case SO_REUSEPORT:
1135
                case SO_OOBINLINE:
1136
                case SO_TIMESTAMP:
1137
                        error = sooptcopyin(sopt, &optval, sizeof optval,
1138
                                            sizeof optval);
1139
                        if (error)
1140
                                goto bad;
1141
                        if (optval)
1142
                                so->so_options |= sopt->sopt_name;
1143
                        else
1144
                                so->so_options &= ~sopt->sopt_name;
1145
                        break;
1146
 
1147
                case SO_SNDBUF:
1148
                case SO_RCVBUF:
1149
                case SO_SNDLOWAT:
1150
                case SO_RCVLOWAT:
1151
                        error = sooptcopyin(sopt, &optval, sizeof optval,
1152
                                            sizeof optval);
1153
                        if (error)
1154
                                goto bad;
1155
 
1156
                        /*
1157
                         * Values < 1 make no sense for any of these
1158
                         * options, so disallow them.
1159
                         */
1160
                        if (optval < 1) {
1161
                                error = EINVAL;
1162
                                goto bad;
1163
                        }
1164
 
1165
                        switch (sopt->sopt_name) {
1166
                        case SO_SNDBUF:
1167
                        case SO_RCVBUF:
1168
                                if (sbreserve(sopt->sopt_name == SO_SNDBUF ?
1169
                                    &so->so_snd : &so->so_rcv, (u_long)optval,
1170
                                    so, curproc) == 0) {
1171
                                        error = ENOBUFS;
1172
                                        goto bad;
1173
                                }
1174
                                break;
1175
 
1176
                        /*
1177
                         * Make sure the low-water is never greater than
1178
                         * the high-water.
1179
                         */
1180
                        case SO_SNDLOWAT:
1181
                                so->so_snd.sb_lowat =
1182
                                    (optval > so->so_snd.sb_hiwat) ?
1183
                                    so->so_snd.sb_hiwat : optval;
1184
                                break;
1185
                        case SO_RCVLOWAT:
1186
                                so->so_rcv.sb_lowat =
1187
                                    (optval > so->so_rcv.sb_hiwat) ?
1188
                                    so->so_rcv.sb_hiwat : optval;
1189
                                break;
1190
                        }
1191
                        break;
1192
 
1193
                case SO_SNDTIMEO:
1194
                case SO_RCVTIMEO:
1195
                        error = sooptcopyin(sopt, &tv, sizeof tv,
1196
                                            sizeof tv);
1197
                        if (error)
1198
                                goto bad;
1199
 
1200
                        /* assert(hz > 0); */
1201
                        if (tv.tv_sec < 0 || tv.tv_sec > SHRT_MAX / hz ||
1202
                            tv.tv_usec < 0 || tv.tv_usec >= 1000000) {
1203
                                error = EDOM;
1204
                                goto bad;
1205
                        }
1206
                        /* assert(tick > 0); */
1207
                        /* assert(ULONG_MAX - SHRT_MAX >= 1000000); */
1208
                        val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick;
1209
                        if (val > SHRT_MAX) {
1210
                                error = EDOM;
1211
                                goto bad;
1212
                        }
1213
 
1214
                        switch (sopt->sopt_name) {
1215
                        case SO_SNDTIMEO:
1216
                                so->so_snd.sb_timeo = val;
1217
                                break;
1218
                        case SO_RCVTIMEO:
1219
                                so->so_rcv.sb_timeo = val;
1220
                                break;
1221
                        }
1222
                        break;
1223
                default:
1224
                        error = ENOPROTOOPT;
1225
                        break;
1226
                }
1227
                if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
1228
                        (void) ((*so->so_proto->pr_ctloutput)
1229
                                  (so, sopt));
1230
                }
1231
        }
1232
bad:
1233
        return (error);
1234
}
1235
 
1236
/* Helper routine for getsockopt */
1237
int
1238
sooptcopyout(sopt, buf, len)
1239
        struct  sockopt *sopt;
1240
        void    *buf;
1241
        size_t  len;
1242
{
1243
        int     error;
1244
        size_t  valsize;
1245
 
1246
        error = 0;
1247
 
1248
        /*
1249
         * Documented get behavior is that we always return a value,
1250
         * possibly truncated to fit in the user's buffer.
1251
         * Traditional behavior is that we always tell the user
1252
         * precisely how much we copied, rather than something useful
1253
         * like the total amount we had available for her.
1254
         * Note that this interface is not idempotent; the entire answer must
1255
         * generated ahead of time.
1256
         */
1257
        valsize = min(len, sopt->sopt_valsize);
1258
        sopt->sopt_valsize = valsize;
1259
        if (sopt->sopt_val != 0) {
1260
                if (sopt->sopt_p != 0)
1261
                        error = copyout(buf, sopt->sopt_val, valsize);
1262
                else
1263
                        bcopy(buf, sopt->sopt_val, valsize);
1264
        }
1265
        return error;
1266
}
1267
 
1268
int
1269
sogetopt(so, sopt)
1270
        struct socket *so;
1271
        struct sockopt *sopt;
1272
{
1273
        int     error, optval;
1274
        struct  linger l;
1275
        struct  timeval tv;
1276
        struct accept_filter_arg *afap;
1277
 
1278
        error = 0;
1279
        if (sopt->sopt_level != SOL_SOCKET) {
1280
                if (so->so_proto && so->so_proto->pr_ctloutput) {
1281
                        return ((*so->so_proto->pr_ctloutput)
1282
                                  (so, sopt));
1283
                } else
1284
                        return (ENOPROTOOPT);
1285
        } else {
1286
                switch (sopt->sopt_name) {
1287
#ifdef INET
1288
                case SO_ACCEPTFILTER:
1289
                        if ((so->so_options & SO_ACCEPTCONN) == 0)
1290
                                return (EINVAL);
1291
                        MALLOC(afap, struct accept_filter_arg *, sizeof(*afap),
1292
                                M_TEMP, M_WAITOK);
1293
                        bzero(afap, sizeof(*afap));
1294
                        if ((so->so_options & SO_ACCEPTFILTER) != 0) {
1295
                                strcpy(afap->af_name, so->so_accf->so_accept_filter->accf_name);
1296
                                if (so->so_accf->so_accept_filter_str != NULL)
1297
                                        strcpy(afap->af_arg, so->so_accf->so_accept_filter_str);
1298
                        }
1299
                        error = sooptcopyout(sopt, afap, sizeof(*afap));
1300
                        FREE(afap, M_TEMP);
1301
                        break;
1302
#endif /* INET */
1303
 
1304
                case SO_LINGER:
1305
                        l.l_onoff = so->so_options & SO_LINGER;
1306
                        l.l_linger = so->so_linger;
1307
                        error = sooptcopyout(sopt, &l, sizeof l);
1308
                        break;
1309
 
1310
                case SO_USELOOPBACK:
1311
                case SO_DONTROUTE:
1312
                case SO_DEBUG:
1313
                case SO_KEEPALIVE:
1314
                case SO_REUSEADDR:
1315
                case SO_REUSEPORT:
1316
                case SO_BROADCAST:
1317
                case SO_OOBINLINE:
1318
                case SO_TIMESTAMP:
1319
                        optval = so->so_options & sopt->sopt_name;
1320
integer:
1321
                        error = sooptcopyout(sopt, &optval, sizeof optval);
1322
                        break;
1323
 
1324
                case SO_TYPE:
1325
                        optval = so->so_type;
1326
                        goto integer;
1327
 
1328
                case SO_ERROR:
1329
                        optval = so->so_error;
1330
                        so->so_error = 0;
1331
                        goto integer;
1332
 
1333
                case SO_SNDBUF:
1334
                        optval = so->so_snd.sb_hiwat;
1335
                        goto integer;
1336
 
1337
                case SO_RCVBUF:
1338
                        optval = so->so_rcv.sb_hiwat;
1339
                        goto integer;
1340
 
1341
                case SO_SNDLOWAT:
1342
                        optval = so->so_snd.sb_lowat;
1343
                        goto integer;
1344
 
1345
                case SO_RCVLOWAT:
1346
                        optval = so->so_rcv.sb_lowat;
1347
                        goto integer;
1348
 
1349
                case SO_SNDTIMEO:
1350
                case SO_RCVTIMEO:
1351
                        optval = (sopt->sopt_name == SO_SNDTIMEO ?
1352
                                  so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
1353
 
1354
                        tv.tv_sec = optval / hz;
1355
                        tv.tv_usec = (optval % hz) * tick;
1356
                        error = sooptcopyout(sopt, &tv, sizeof tv);
1357
                        break;
1358
 
1359
                default:
1360
                        error = ENOPROTOOPT;
1361
                        break;
1362
                }
1363
                return (error);
1364
        }
1365
}
1366
 
1367
/* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */
1368
int
1369
soopt_getm(struct sockopt *sopt, struct mbuf **mp)
1370
{
1371
        struct mbuf *m, *m_prev;
1372
        int sopt_size = sopt->sopt_valsize;
1373
 
1374
        MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_DATA);
1375
        if (m == 0) {
1376
                return ENOBUFS;
1377
        }
1378
        if (sopt_size > MLEN) {
1379
                MCLGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT);
1380
                if ((m->m_flags & M_EXT) == 0) {
1381
                        m_free(m);
1382
                        return ENOBUFS;
1383
                }
1384
                m->m_len = min(MCLBYTES, sopt_size);
1385
        } else {
1386
                m->m_len = min(MLEN, sopt_size);
1387
        }
1388
        sopt_size -= m->m_len;
1389
        *mp = m;
1390
        m_prev = m;
1391
 
1392
        while (sopt_size) {
1393
                MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_DATA);
1394
                if (m == 0) {
1395
                        m_freem(*mp);
1396
                        return ENOBUFS;
1397
                }
1398
                if (sopt_size > MLEN) {
1399
                        MCLGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT);
1400
                        if ((m->m_flags & M_EXT) == 0) {
1401
                                m_freem(*mp);
1402
                                return ENOBUFS;
1403
                        }
1404
                        m->m_len = min(MCLBYTES, sopt_size);
1405
                } else {
1406
                        m->m_len = min(MLEN, sopt_size);
1407
                }
1408
                sopt_size -= m->m_len;
1409
                m_prev->m_next = m;
1410
                m_prev = m;
1411
        }
1412
        return 0;
1413
}
1414
 
1415
/* XXX; copyin sopt data into mbuf chain for (__FreeBSD__ < 3) routines. */
1416
int
1417
soopt_mcopyin(struct sockopt *sopt, struct mbuf *m)
1418
{
1419
        struct mbuf *m0 = m;
1420
 
1421
        if (sopt->sopt_val == NULL)
1422
                return 0;
1423
        while (m != NULL && sopt->sopt_valsize >= m->m_len) {
1424
                if (sopt->sopt_p != NULL) {
1425
                        int error;
1426
 
1427
                        error = copyin(sopt->sopt_val, mtod(m, char *),
1428
                                       m->m_len);
1429
                        if (error != 0) {
1430
                                m_freem(m0);
1431
                                return(error);
1432
                        }
1433
                } else
1434
                        bcopy(sopt->sopt_val, mtod(m, char *), m->m_len);
1435
                sopt->sopt_valsize -= m->m_len;
1436
                sopt->sopt_val = (char *)sopt->sopt_val + m->m_len;
1437
                m = m->m_next;
1438
        }
1439
        if (m != NULL) /* should be allocated enoughly at ip6_sooptmcopyin() */
1440
                panic("ip6_sooptmcopyin");
1441
        return 0;
1442
}
1443
 
1444
/* XXX; copyout mbuf chain data into soopt for (__FreeBSD__ < 3) routines. */
1445
int
1446
soopt_mcopyout(struct sockopt *sopt, struct mbuf *m)
1447
{
1448
        struct mbuf *m0 = m;
1449
        size_t valsize = 0;
1450
 
1451
        if (sopt->sopt_val == NULL)
1452
                return 0;
1453
        while (m != NULL && sopt->sopt_valsize >= m->m_len) {
1454
                if (sopt->sopt_p != NULL) {
1455
                        int error;
1456
 
1457
                        error = copyout(mtod(m, char *), sopt->sopt_val,
1458
                                       m->m_len);
1459
                        if (error != 0) {
1460
                                m_freem(m0);
1461
                                return(error);
1462
                        }
1463
                } else
1464
                        bcopy(mtod(m, char *), sopt->sopt_val, m->m_len);
1465
               sopt->sopt_valsize -= m->m_len;
1466
               sopt->sopt_val = (char *)sopt->sopt_val + m->m_len;
1467
               valsize += m->m_len;
1468
               m = m->m_next;
1469
        }
1470
        if (m != NULL) {
1471
                /* enough soopt buffer should be given from user-land */
1472
                m_freem(m0);
1473
                return(EINVAL);
1474
        }
1475
        sopt->sopt_valsize = valsize;
1476
        return 0;
1477
}
1478
 
1479
void
1480
sohasoutofband(so)
1481
        register struct socket *so;
1482
{
1483
        selwakeup(&so->so_rcv.sb_sel);
1484
}
1485
 
1486
int
1487
sopoll(struct socket *so, int events, struct ucred *cred, struct proc *p)
1488
{
1489
    panic("%s\n", __FUNCTION__);
1490
    return 0;
1491
#if 0 // POLL
1492
        int revents = 0;
1493
        int s = splnet();
1494
 
1495
        if (events & (POLLIN | POLLRDNORM))
1496
                if (soreadable(so))
1497
                        revents |= events & (POLLIN | POLLRDNORM);
1498
 
1499
        if (events & (POLLOUT | POLLWRNORM))
1500
                if (sowriteable(so))
1501
                        revents |= events & (POLLOUT | POLLWRNORM);
1502
 
1503
        if (events & (POLLPRI | POLLRDBAND))
1504
                if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
1505
                        revents |= events & (POLLPRI | POLLRDBAND);
1506
 
1507
        if (revents == 0) {
1508
                if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
1509
                        selrecord(p, &so->so_rcv.sb_sel);
1510
                        so->so_rcv.sb_flags |= SB_SEL;
1511
                }
1512
 
1513
                if (events & (POLLOUT | POLLWRNORM)) {
1514
                        selrecord(p, &so->so_snd.sb_sel);
1515
                        so->so_snd.sb_flags |= SB_SEL;
1516
                }
1517
        }
1518
 
1519
        splx(s);
1520
        return (revents);
1521
#endif // POLL
1522
}
1523
 

powered by: WebSVN 2.1.0

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