|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)uipc_socket2.c 7.17 (Berkeley) 5/4/91
1.1.1.2 ! root 34: *
! 35: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
! 36: * -------------------- ----- ----------------------
! 37: * CURRENT PATCH LEVEL: 1 00061
! 38: * -------------------- ----- ----------------------
! 39: *
! 40: * 11 Dec 92 Williams Jolitz Fixed tty handling
1.1 root 41: */
42:
43: #include "param.h"
44: #include "systm.h"
45: #include "proc.h"
46: #include "file.h"
47: #include "buf.h"
48: #include "malloc.h"
49: #include "mbuf.h"
50: #include "protosw.h"
51: #include "socket.h"
52: #include "socketvar.h"
53:
54: /*
55: * Primitive routines for operating on sockets and socket buffers
56: */
57:
58: /* strings for sleep message: */
59: char netio[] = "netio";
60: char netcon[] = "netcon";
61: char netcls[] = "netcls";
62:
63: u_long sb_max = SB_MAX; /* patchable */
64:
65: /*
66: * Procedures to manipulate state flags of socket
67: * and do appropriate wakeups. Normal sequence from the
68: * active (originating) side is that soisconnecting() is
69: * called during processing of connect() call,
70: * resulting in an eventual call to soisconnected() if/when the
71: * connection is established. When the connection is torn down
72: * soisdisconnecting() is called during processing of disconnect() call,
73: * and soisdisconnected() is called when the connection to the peer
74: * is totally severed. The semantics of these routines are such that
75: * connectionless protocols can call soisconnected() and soisdisconnected()
76: * only, bypassing the in-progress calls when setting up a ``connection''
77: * takes no time.
78: *
79: * From the passive side, a socket is created with
80: * two queues of sockets: so_q0 for connections in progress
81: * and so_q for connections already made and awaiting user acceptance.
82: * As a protocol is preparing incoming connections, it creates a socket
83: * structure queued on so_q0 by calling sonewconn(). When the connection
84: * is established, soisconnected() is called, and transfers the
85: * socket structure to so_q, making it available to accept().
86: *
87: * If a socket is closed with sockets on either
88: * so_q0 or so_q, these sockets are dropped.
89: *
90: * If higher level protocols are implemented in
91: * the kernel, the wakeups done here will sometimes
92: * cause software-interrupt process scheduling.
93: */
94:
95: soisconnecting(so)
96: register struct socket *so;
97: {
98:
99: so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
100: so->so_state |= SS_ISCONNECTING;
101: }
102:
103: soisconnected(so)
104: register struct socket *so;
105: {
106: register struct socket *head = so->so_head;
107:
108: so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
109: so->so_state |= SS_ISCONNECTED;
110: if (head && soqremque(so, 0)) {
111: soqinsque(head, so, 1);
112: sorwakeup(head);
113: wakeup((caddr_t)&head->so_timeo);
114: } else {
115: wakeup((caddr_t)&so->so_timeo);
116: sorwakeup(so);
117: sowwakeup(so);
118: }
119: }
120:
121: soisdisconnecting(so)
122: register struct socket *so;
123: {
124:
125: so->so_state &= ~SS_ISCONNECTING;
126: so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
127: wakeup((caddr_t)&so->so_timeo);
128: sowwakeup(so);
129: sorwakeup(so);
130: }
131:
132: soisdisconnected(so)
133: register struct socket *so;
134: {
135:
136: so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
137: so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
138: wakeup((caddr_t)&so->so_timeo);
139: sowwakeup(so);
140: sorwakeup(so);
141: }
142:
143: /*
144: * When an attempt at a new connection is noted on a socket
145: * which accepts connections, sonewconn is called. If the
146: * connection is possible (subject to space constraints, etc.)
147: * then we allocate a new structure, propoerly linked into the
148: * data structure of the original socket, and return this.
149: * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
150: *
151: * Currently, sonewconn() is defined as sonewconn1() in socketvar.h
152: * to catch calls that are missing the (new) second parameter.
153: */
154: struct socket *
155: sonewconn1(head, connstatus)
156: register struct socket *head;
157: int connstatus;
158: {
159: register struct socket *so;
160: int soqueue = connstatus ? 1 : 0;
161:
162: if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
163: return ((struct socket *)0);
164: MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT);
165: if (so == NULL)
166: return ((struct socket *)0);
167: bzero((caddr_t)so, sizeof(*so));
168: so->so_type = head->so_type;
169: so->so_options = head->so_options &~ SO_ACCEPTCONN;
170: so->so_linger = head->so_linger;
171: so->so_state = head->so_state | SS_NOFDREF;
172: so->so_proto = head->so_proto;
173: so->so_timeo = head->so_timeo;
174: so->so_pgid = head->so_pgid;
175: (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
176: soqinsque(head, so, soqueue);
177: if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
178: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
179: (void) soqremque(so, soqueue);
180: (void) free((caddr_t)so, M_SOCKET);
181: return ((struct socket *)0);
182: }
183: if (connstatus) {
184: sorwakeup(head);
185: wakeup((caddr_t)&head->so_timeo);
186: so->so_state |= connstatus;
187: }
188: return (so);
189: }
190:
191: soqinsque(head, so, q)
192: register struct socket *head, *so;
193: int q;
194: {
195:
196: register struct socket **prev;
197: so->so_head = head;
198: if (q == 0) {
199: head->so_q0len++;
200: so->so_q0 = 0;
201: for (prev = &(head->so_q0); *prev; )
202: prev = &((*prev)->so_q0);
203: } else {
204: head->so_qlen++;
205: so->so_q = 0;
206: for (prev = &(head->so_q); *prev; )
207: prev = &((*prev)->so_q);
208: }
209: *prev = so;
210: }
211:
212: soqremque(so, q)
213: register struct socket *so;
214: int q;
215: {
216: register struct socket *head, *prev, *next;
217:
218: head = so->so_head;
219: prev = head;
220: for (;;) {
221: next = q ? prev->so_q : prev->so_q0;
222: if (next == so)
223: break;
224: if (next == 0)
225: return (0);
226: prev = next;
227: }
228: if (q == 0) {
229: prev->so_q0 = next->so_q0;
230: head->so_q0len--;
231: } else {
232: prev->so_q = next->so_q;
233: head->so_qlen--;
234: }
235: next->so_q0 = next->so_q = 0;
236: next->so_head = 0;
237: return (1);
238: }
239:
240: /*
241: * Socantsendmore indicates that no more data will be sent on the
242: * socket; it would normally be applied to a socket when the user
243: * informs the system that no more data is to be sent, by the protocol
244: * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data
245: * will be received, and will normally be applied to the socket by a
246: * protocol when it detects that the peer will send no more data.
247: * Data queued for reading in the socket may yet be read.
248: */
249:
250: socantsendmore(so)
251: struct socket *so;
252: {
253:
254: so->so_state |= SS_CANTSENDMORE;
255: sowwakeup(so);
256: }
257:
258: socantrcvmore(so)
259: struct socket *so;
260: {
261:
262: so->so_state |= SS_CANTRCVMORE;
263: sorwakeup(so);
264: }
265:
266: /*
267: * Socket select/wakeup routines.
268: */
269:
270: /*
271: * Queue a process for a select on a socket buffer.
272: */
273: sbselqueue(sb, cp)
274: struct sockbuf *sb;
275: struct proc *cp;
276: {
277: struct proc *p;
278:
1.1.1.2 ! root 279: if (sb->sb_sel && (p = pfind(sb->sb_sel)) && p->p_wchan == (caddr_t)&selwait)
1.1 root 280: sb->sb_flags |= SB_COLL;
281: else {
1.1.1.2 ! root 282: sb->sb_sel = cp->p_pid;
1.1 root 283: sb->sb_flags |= SB_SEL;
284: }
285: }
286:
287: /*
288: * Wait for data to arrive at/drain from a socket buffer.
289: */
290: sbwait(sb)
291: struct sockbuf *sb;
292: {
293:
294: sb->sb_flags |= SB_WAIT;
295: return (tsleep((caddr_t)&sb->sb_cc,
296: (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio,
297: sb->sb_timeo));
298: }
299:
300: /*
301: * Lock a sockbuf already known to be locked;
302: * return any error returned from sleep (EINTR).
303: */
304: sb_lock(sb)
305: register struct sockbuf *sb;
306: {
307: int error;
308:
309: while (sb->sb_flags & SB_LOCK) {
310: sb->sb_flags |= SB_WANT;
311: if (error = tsleep((caddr_t)&sb->sb_flags,
312: (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH,
313: netio, 0))
314: return (error);
315: }
316: sb->sb_flags |= SB_LOCK;
317: return (0);
318: }
319:
320: /*
321: * Wakeup processes waiting on a socket buffer.
322: * Do asynchronous notification via SIGIO
323: * if the socket has the SS_ASYNC flag set.
324: */
325: sowakeup(so, sb)
326: register struct socket *so;
327: register struct sockbuf *sb;
328: {
329: struct proc *p;
330:
331: if (sb->sb_sel) {
332: selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
333: sb->sb_sel = 0;
334: sb->sb_flags &= ~(SB_SEL|SB_COLL);
335: }
336: if (sb->sb_flags & SB_WAIT) {
337: sb->sb_flags &= ~SB_WAIT;
338: wakeup((caddr_t)&sb->sb_cc);
339: }
340: if (so->so_state & SS_ASYNC) {
341: if (so->so_pgid < 0)
342: gsignal(-so->so_pgid, SIGIO);
343: else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
344: psignal(p, SIGIO);
345: }
346: }
347:
348: /*
349: * Socket buffer (struct sockbuf) utility routines.
350: *
351: * Each socket contains two socket buffers: one for sending data and
352: * one for receiving data. Each buffer contains a queue of mbufs,
353: * information about the number of mbufs and amount of data in the
354: * queue, and other fields allowing select() statements and notification
355: * on data availability to be implemented.
356: *
357: * Data stored in a socket buffer is maintained as a list of records.
358: * Each record is a list of mbufs chained together with the m_next
359: * field. Records are chained together with the m_nextpkt field. The upper
360: * level routine soreceive() expects the following conventions to be
361: * observed when placing information in the receive buffer:
362: *
363: * 1. If the protocol requires each message be preceded by the sender's
364: * name, then a record containing that name must be present before
365: * any associated data (mbuf's must be of type MT_SONAME).
366: * 2. If the protocol supports the exchange of ``access rights'' (really
367: * just additional data associated with the message), and there are
368: * ``rights'' to be received, then a record containing this data
369: * should be present (mbuf's must be of type MT_RIGHTS).
370: * 3. If a name or rights record exists, then it must be followed by
371: * a data record, perhaps of zero length.
372: *
373: * Before using a new socket structure it is first necessary to reserve
374: * buffer space to the socket, by calling sbreserve(). This should commit
375: * some of the available buffer space in the system buffer pool for the
376: * socket (currently, it does nothing but enforce limits). The space
377: * should be released by calling sbrelease() when the socket is destroyed.
378: */
379:
380: soreserve(so, sndcc, rcvcc)
381: register struct socket *so;
382: u_long sndcc, rcvcc;
383: {
384:
385: if (sbreserve(&so->so_snd, sndcc) == 0)
386: goto bad;
387: if (sbreserve(&so->so_rcv, rcvcc) == 0)
388: goto bad2;
389: if (so->so_rcv.sb_lowat == 0)
390: so->so_rcv.sb_lowat = 1;
391: if (so->so_snd.sb_lowat == 0)
392: so->so_snd.sb_lowat = MCLBYTES;
393: if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
394: so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
395: return (0);
396: bad2:
397: sbrelease(&so->so_snd);
398: bad:
399: return (ENOBUFS);
400: }
401:
402: /*
403: * Allot mbufs to a sockbuf.
404: * Attempt to scale mbmax so that mbcnt doesn't become limiting
405: * if buffering efficiency is near the normal case.
406: */
407: sbreserve(sb, cc)
408: struct sockbuf *sb;
409: u_long cc;
410: {
411:
412: if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES))
413: return (0);
414: sb->sb_hiwat = cc;
415: sb->sb_mbmax = min(cc * 2, sb_max);
416: if (sb->sb_lowat > sb->sb_hiwat)
417: sb->sb_lowat = sb->sb_hiwat;
418: return (1);
419: }
420:
421: /*
422: * Free mbufs held by a socket, and reserved mbuf space.
423: */
424: sbrelease(sb)
425: struct sockbuf *sb;
426: {
427:
428: sbflush(sb);
429: sb->sb_hiwat = sb->sb_mbmax = 0;
430: }
431:
432: /*
433: * Routines to add and remove
434: * data from an mbuf queue.
435: *
436: * The routines sbappend() or sbappendrecord() are normally called to
437: * append new mbufs to a socket buffer, after checking that adequate
438: * space is available, comparing the function sbspace() with the amount
439: * of data to be added. sbappendrecord() differs from sbappend() in
440: * that data supplied is treated as the beginning of a new record.
441: * To place a sender's address, optional access rights, and data in a
442: * socket receive buffer, sbappendaddr() should be used. To place
443: * access rights and data in a socket receive buffer, sbappendrights()
444: * should be used. In either case, the new data begins a new record.
445: * Note that unlike sbappend() and sbappendrecord(), these routines check
446: * for the caller that there will be enough space to store the data.
447: * Each fails if there is not enough space, or if it cannot find mbufs
448: * to store additional information in.
449: *
450: * Reliable protocols may use the socket send buffer to hold data
451: * awaiting acknowledgement. Data is normally copied from a socket
452: * send buffer in a protocol with m_copy for output to a peer,
453: * and then removing the data from the socket buffer with sbdrop()
454: * or sbdroprecord() when the data is acknowledged by the peer.
455: */
456:
457: /*
458: * Append mbuf chain m to the last record in the
459: * socket buffer sb. The additional space associated
460: * the mbuf chain is recorded in sb. Empty mbufs are
461: * discarded and mbufs are compacted where possible.
462: */
463: sbappend(sb, m)
464: struct sockbuf *sb;
465: struct mbuf *m;
466: {
467: register struct mbuf *n;
468:
469: if (m == 0)
470: return;
471: if (n = sb->sb_mb) {
472: while (n->m_nextpkt)
473: n = n->m_nextpkt;
474: do {
475: if (n->m_flags & M_EOR) {
476: sbappendrecord(sb, m); /* XXXXXX!!!! */
477: return;
478: }
479: } while (n->m_next && (n = n->m_next));
480: }
481: sbcompress(sb, m, n);
482: }
483:
484: #ifdef SOCKBUF_DEBUG
485: sbcheck(sb)
486: register struct sockbuf *sb;
487: {
488: register struct mbuf *m;
489: register int len = 0, mbcnt = 0;
490:
491: for (m = sb->sb_mb; m; m = m->m_next) {
492: len += m->m_len;
493: mbcnt += MSIZE;
494: if (m->m_flags & M_EXT)
495: mbcnt += m->m_ext.ext_size;
496: if (m->m_nextpkt)
497: panic("sbcheck nextpkt");
498: }
499: if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
500: printf("cc %d != %d || mbcnt %d != %d\n", len, sb->sb_cc,
501: mbcnt, sb->sb_mbcnt);
502: panic("sbcheck");
503: }
504: }
505: #endif
506:
507: /*
508: * As above, except the mbuf chain
509: * begins a new record.
510: */
511: sbappendrecord(sb, m0)
512: register struct sockbuf *sb;
513: register struct mbuf *m0;
514: {
515: register struct mbuf *m;
516:
517: if (m0 == 0)
518: return;
519: if (m = sb->sb_mb)
520: while (m->m_nextpkt)
521: m = m->m_nextpkt;
522: /*
523: * Put the first mbuf on the queue.
524: * Note this permits zero length records.
525: */
526: sballoc(sb, m0);
527: if (m)
528: m->m_nextpkt = m0;
529: else
530: sb->sb_mb = m0;
531: m = m0->m_next;
532: m0->m_next = 0;
533: if (m && (m0->m_flags & M_EOR)) {
534: m0->m_flags &= ~M_EOR;
535: m->m_flags |= M_EOR;
536: }
537: sbcompress(sb, m, m0);
538: }
539:
540: /*
541: * As above except that OOB data
542: * is inserted at the beginning of the sockbuf,
543: * but after any other OOB data.
544: */
545: sbinsertoob(sb, m0)
546: register struct sockbuf *sb;
547: register struct mbuf *m0;
548: {
549: register struct mbuf *m;
550: register struct mbuf **mp;
551:
552: if (m0 == 0)
553: return;
554: for (mp = &sb->sb_mb; m = *mp; mp = &((*mp)->m_nextpkt)) {
555: again:
556: switch (m->m_type) {
557:
558: case MT_OOBDATA:
559: continue; /* WANT next train */
560:
561: case MT_CONTROL:
562: if (m = m->m_next)
563: goto again; /* inspect THIS train further */
564: }
565: break;
566: }
567: /*
568: * Put the first mbuf on the queue.
569: * Note this permits zero length records.
570: */
571: sballoc(sb, m0);
572: m0->m_nextpkt = *mp;
573: *mp = m0;
574: m = m0->m_next;
575: m0->m_next = 0;
576: if (m && (m0->m_flags & M_EOR)) {
577: m0->m_flags &= ~M_EOR;
578: m->m_flags |= M_EOR;
579: }
580: sbcompress(sb, m, m0);
581: }
582:
583: /*
584: * Append address and data, and optionally, control (ancillary) data
585: * to the receive queue of a socket. If present,
586: * m0 must include a packet header with total length.
587: * Returns 0 if no space in sockbuf or insufficient mbufs.
588: */
589: sbappendaddr(sb, asa, m0, control)
590: register struct sockbuf *sb;
591: struct sockaddr *asa;
592: struct mbuf *m0, *control;
593: {
594: register struct mbuf *m, *n;
595: int space = asa->sa_len;
596:
597: if (m0 && (m0->m_flags & M_PKTHDR) == 0)
598: panic("sbappendaddr");
599: if (m0)
600: space += m0->m_pkthdr.len;
601: for (n = control; n; n = n->m_next) {
602: space += n->m_len;
603: if (n->m_next == 0) /* keep pointer to last control buf */
604: break;
605: }
606: if (space > sbspace(sb))
607: return (0);
608: if (asa->sa_len > MLEN)
609: return (0);
610: MGET(m, M_DONTWAIT, MT_SONAME);
611: if (m == 0)
612: return (0);
613: m->m_len = asa->sa_len;
614: bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
615: if (n)
616: n->m_next = m0; /* concatenate data to control */
617: else
618: control = m0;
619: m->m_next = control;
620: for (n = m; n; n = n->m_next)
621: sballoc(sb, n);
622: if (n = sb->sb_mb) {
623: while (n->m_nextpkt)
624: n = n->m_nextpkt;
625: n->m_nextpkt = m;
626: } else
627: sb->sb_mb = m;
628: return (1);
629: }
630:
631: sbappendcontrol(sb, m0, control)
632: struct sockbuf *sb;
633: struct mbuf *control, *m0;
634: {
635: register struct mbuf *m, *n;
636: int space = 0;
637:
638: if (control == 0)
639: panic("sbappendcontrol");
640: for (m = control; ; m = m->m_next) {
641: space += m->m_len;
642: if (m->m_next == 0)
643: break;
644: }
645: n = m; /* save pointer to last control buffer */
646: for (m = m0; m; m = m->m_next)
647: space += m->m_len;
648: if (space > sbspace(sb))
649: return (0);
650: n->m_next = m0; /* concatenate data to control */
651: for (m = control; m; m = m->m_next)
652: sballoc(sb, m);
653: if (n = sb->sb_mb) {
654: while (n->m_nextpkt)
655: n = n->m_nextpkt;
656: n->m_nextpkt = control;
657: } else
658: sb->sb_mb = control;
659: return (1);
660: }
661:
662: /*
663: * Compress mbuf chain m into the socket
664: * buffer sb following mbuf n. If n
665: * is null, the buffer is presumed empty.
666: */
667: sbcompress(sb, m, n)
668: register struct sockbuf *sb;
669: register struct mbuf *m, *n;
670: {
671: register int eor = 0;
672: register struct mbuf *o;
673:
674: while (m) {
675: eor |= m->m_flags & M_EOR;
676: if (m->m_len == 0 &&
677: (eor == 0 ||
678: (((o = m->m_next) || (o = n)) &&
679: o->m_type == m->m_type))) {
680: m = m_free(m);
681: continue;
682: }
683: if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 &&
684: (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] &&
685: n->m_type == m->m_type) {
686: bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
687: (unsigned)m->m_len);
688: n->m_len += m->m_len;
689: sb->sb_cc += m->m_len;
690: m = m_free(m);
691: continue;
692: }
693: if (n)
694: n->m_next = m;
695: else
696: sb->sb_mb = m;
697: sballoc(sb, m);
698: n = m;
699: m->m_flags &= ~M_EOR;
700: m = m->m_next;
701: n->m_next = 0;
702: }
703: if (eor) {
704: if (n)
705: n->m_flags |= eor;
706: else
707: printf("semi-panic: sbcompress\n");
708: }
709: }
710:
711: /*
712: * Free all mbufs in a sockbuf.
713: * Check that all resources are reclaimed.
714: */
715: sbflush(sb)
716: register struct sockbuf *sb;
717: {
718:
719: if (sb->sb_flags & SB_LOCK)
720: panic("sbflush");
721: while (sb->sb_mbcnt)
722: sbdrop(sb, (int)sb->sb_cc);
723: if (sb->sb_cc || sb->sb_mb)
724: panic("sbflush 2");
725: }
726:
727: /*
728: * Drop data from (the front of) a sockbuf.
729: */
730: sbdrop(sb, len)
731: register struct sockbuf *sb;
732: register int len;
733: {
734: register struct mbuf *m, *mn;
735: struct mbuf *next;
736:
737: next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
738: while (len > 0) {
739: if (m == 0) {
740: if (next == 0)
741: panic("sbdrop");
742: m = next;
743: next = m->m_nextpkt;
744: continue;
745: }
746: if (m->m_len > len) {
747: m->m_len -= len;
748: m->m_data += len;
749: sb->sb_cc -= len;
750: break;
751: }
752: len -= m->m_len;
753: sbfree(sb, m);
754: MFREE(m, mn);
755: m = mn;
756: }
757: while (m && m->m_len == 0) {
758: sbfree(sb, m);
759: MFREE(m, mn);
760: m = mn;
761: }
762: if (m) {
763: sb->sb_mb = m;
764: m->m_nextpkt = next;
765: } else
766: sb->sb_mb = next;
767: }
768:
769: /*
770: * Drop a record off the front of a sockbuf
771: * and move the next record to the front.
772: */
773: sbdroprecord(sb)
774: register struct sockbuf *sb;
775: {
776: register struct mbuf *m, *mn;
777:
778: m = sb->sb_mb;
779: if (m) {
780: sb->sb_mb = m->m_nextpkt;
781: do {
782: sbfree(sb, m);
783: MFREE(m, mn);
784: } while (m = mn);
785: }
786: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.