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

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

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

powered by: WebSVN 2.1.0

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