123431Smckusick /* 229127Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 333187Sbostic * All rights reserved. 423431Smckusick * 533187Sbostic * Redistribution and use in source and binary forms are permitted 6*34858Sbostic * provided that the above copyright notice and this paragraph are 7*34858Sbostic * duplicated in all such forms and that any documentation, 8*34858Sbostic * advertising materials, and other materials related to such 9*34858Sbostic * distribution and use acknowledge that the software was developed 10*34858Sbostic * by the University of California, Berkeley. The name of the 11*34858Sbostic * University may not be used to endorse or promote products derived 12*34858Sbostic * from this software without specific prior written permission. 13*34858Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34858Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34858Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633187Sbostic * 17*34858Sbostic * @(#)uipc_socket2.c 7.5 (Berkeley) 06/29/88 1823431Smckusick */ 194903Swnj 2017103Sbloom #include "param.h" 2117103Sbloom #include "systm.h" 2217103Sbloom #include "dir.h" 2317103Sbloom #include "user.h" 2417103Sbloom #include "proc.h" 2517103Sbloom #include "file.h" 2617103Sbloom #include "inode.h" 2717103Sbloom #include "buf.h" 2817103Sbloom #include "mbuf.h" 2917103Sbloom #include "protosw.h" 3017103Sbloom #include "socket.h" 3117103Sbloom #include "socketvar.h" 324903Swnj 334903Swnj /* 344903Swnj * Primitive routines for operating on sockets and socket buffers 354903Swnj */ 364903Swnj 374903Swnj /* 384903Swnj * Procedures to manipulate state flags of socket 397509Sroot * and do appropriate wakeups. Normal sequence from the 407509Sroot * active (originating) side is that soisconnecting() is 417509Sroot * called during processing of connect() call, 425169Swnj * resulting in an eventual call to soisconnected() if/when the 435169Swnj * connection is established. When the connection is torn down 445169Swnj * soisdisconnecting() is called during processing of disconnect() call, 455169Swnj * and soisdisconnected() is called when the connection to the peer 465169Swnj * is totally severed. The semantics of these routines are such that 475169Swnj * connectionless protocols can call soisconnected() and soisdisconnected() 485169Swnj * only, bypassing the in-progress calls when setting up a ``connection'' 495169Swnj * takes no time. 505169Swnj * 5112758Ssam * From the passive side, a socket is created with 5212758Ssam * two queues of sockets: so_q0 for connections in progress 537509Sroot * and so_q for connections already made and awaiting user acceptance. 547509Sroot * As a protocol is preparing incoming connections, it creates a socket 557509Sroot * structure queued on so_q0 by calling sonewconn(). When the connection 567509Sroot * is established, soisconnected() is called, and transfers the 577509Sroot * socket structure to so_q, making it available to accept(). 587509Sroot * 5912758Ssam * If a socket is closed with sockets on either 607509Sroot * so_q0 or so_q, these sockets are dropped. 617509Sroot * 6212758Ssam * If higher level protocols are implemented in 635169Swnj * the kernel, the wakeups done here will sometimes 6412758Ssam * cause software-interrupt process scheduling. 654903Swnj */ 665169Swnj 674903Swnj soisconnecting(so) 6812758Ssam register struct socket *so; 694903Swnj { 704903Swnj 714903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 724903Swnj so->so_state |= SS_ISCONNECTING; 734903Swnj wakeup((caddr_t)&so->so_timeo); 744903Swnj } 754903Swnj 764903Swnj soisconnected(so) 7712758Ssam register struct socket *so; 784903Swnj { 797509Sroot register struct socket *head = so->so_head; 804903Swnj 817509Sroot if (head) { 827509Sroot if (soqremque(so, 0) == 0) 837509Sroot panic("soisconnected"); 847509Sroot soqinsque(head, so, 1); 8512758Ssam sorwakeup(head); 867509Sroot wakeup((caddr_t)&head->so_timeo); 877509Sroot } 884903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 894903Swnj so->so_state |= SS_ISCONNECTED; 904903Swnj wakeup((caddr_t)&so->so_timeo); 915578Swnj sorwakeup(so); 925578Swnj sowwakeup(so); 934903Swnj } 944903Swnj 954903Swnj soisdisconnecting(so) 9612758Ssam register struct socket *so; 974903Swnj { 984903Swnj 995248Sroot so->so_state &= ~SS_ISCONNECTING; 1004903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 1014903Swnj wakeup((caddr_t)&so->so_timeo); 1025170Swnj sowwakeup(so); 1035169Swnj sorwakeup(so); 1044903Swnj } 1054903Swnj 1064903Swnj soisdisconnected(so) 10712758Ssam register struct socket *so; 1084903Swnj { 1094903Swnj 1104903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 1114903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 1124903Swnj wakeup((caddr_t)&so->so_timeo); 1134903Swnj sowwakeup(so); 1144903Swnj sorwakeup(so); 1154903Swnj } 1164903Swnj 1175169Swnj /* 1187509Sroot * When an attempt at a new connection is noted on a socket 1197509Sroot * which accepts connections, sonewconn is called. If the 1207509Sroot * connection is possible (subject to space constraints, etc.) 1217509Sroot * then we allocate a new structure, propoerly linked into the 1227509Sroot * data structure of the original socket, and return this. 1237509Sroot */ 1247509Sroot struct socket * 1257509Sroot sonewconn(head) 1267509Sroot register struct socket *head; 1277509Sroot { 1287509Sroot register struct socket *so; 12912758Ssam register struct mbuf *m; 1307509Sroot 1317509Sroot if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) 1327509Sroot goto bad; 1339636Ssam m = m_getclr(M_DONTWAIT, MT_SOCKET); 13410138Ssam if (m == NULL) 1357509Sroot goto bad; 1367509Sroot so = mtod(m, struct socket *); 1377509Sroot so->so_type = head->so_type; 1387509Sroot so->so_options = head->so_options &~ SO_ACCEPTCONN; 1397509Sroot so->so_linger = head->so_linger; 14010204Ssam so->so_state = head->so_state | SS_NOFDREF; 1417509Sroot so->so_proto = head->so_proto; 1427509Sroot so->so_timeo = head->so_timeo; 1437509Sroot so->so_pgrp = head->so_pgrp; 14434491Skarels (void) soreserve(so, head->so_snd.sb_hiwat, head->so_snd.sb_hiwat); 1457509Sroot soqinsque(head, so, 0); 14612758Ssam if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, 14712758Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { 1487509Sroot (void) soqremque(so, 0); 1498818Sroot (void) m_free(m); 1507509Sroot goto bad; 1517509Sroot } 1527509Sroot return (so); 1537509Sroot bad: 1547509Sroot return ((struct socket *)0); 1557509Sroot } 1567509Sroot 1577509Sroot soqinsque(head, so, q) 1587509Sroot register struct socket *head, *so; 1597509Sroot int q; 1607509Sroot { 1617509Sroot 1627509Sroot so->so_head = head; 1637509Sroot if (q == 0) { 1647509Sroot head->so_q0len++; 1657509Sroot so->so_q0 = head->so_q0; 1667509Sroot head->so_q0 = so; 1677509Sroot } else { 1687509Sroot head->so_qlen++; 1697509Sroot so->so_q = head->so_q; 1707509Sroot head->so_q = so; 1717509Sroot } 1727509Sroot } 1737509Sroot 1747509Sroot soqremque(so, q) 1757509Sroot register struct socket *so; 1767509Sroot int q; 1777509Sroot { 1787509Sroot register struct socket *head, *prev, *next; 1797509Sroot 1807509Sroot head = so->so_head; 1817509Sroot prev = head; 1827509Sroot for (;;) { 1837509Sroot next = q ? prev->so_q : prev->so_q0; 1847509Sroot if (next == so) 1857509Sroot break; 1867509Sroot if (next == head) 1877509Sroot return (0); 1887509Sroot prev = next; 1897509Sroot } 1907509Sroot if (q == 0) { 1917509Sroot prev->so_q0 = next->so_q0; 1927509Sroot head->so_q0len--; 1937509Sroot } else { 1947509Sroot prev->so_q = next->so_q; 1957509Sroot head->so_qlen--; 1967509Sroot } 1977509Sroot next->so_q0 = next->so_q = 0; 1987509Sroot next->so_head = 0; 1997509Sroot return (1); 2007509Sroot } 2017509Sroot 2027509Sroot /* 2035169Swnj * Socantsendmore indicates that no more data will be sent on the 2045169Swnj * socket; it would normally be applied to a socket when the user 2055169Swnj * informs the system that no more data is to be sent, by the protocol 2065169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 2075169Swnj * will be received, and will normally be applied to the socket by a 2085169Swnj * protocol when it detects that the peer will send no more data. 2095169Swnj * Data queued for reading in the socket may yet be read. 2105169Swnj */ 2115169Swnj 2124917Swnj socantsendmore(so) 2134917Swnj struct socket *so; 2144917Swnj { 2154917Swnj 2164917Swnj so->so_state |= SS_CANTSENDMORE; 2174917Swnj sowwakeup(so); 2184917Swnj } 2194917Swnj 2204917Swnj socantrcvmore(so) 2214917Swnj struct socket *so; 2224917Swnj { 2234917Swnj 2244917Swnj so->so_state |= SS_CANTRCVMORE; 2254917Swnj sorwakeup(so); 2264917Swnj } 2274917Swnj 2284903Swnj /* 2295169Swnj * Socket select/wakeup routines. 2304903Swnj */ 2315169Swnj 2325169Swnj /* 2334903Swnj * Queue a process for a select on a socket buffer. 2344903Swnj */ 2354903Swnj sbselqueue(sb) 2364903Swnj struct sockbuf *sb; 2374903Swnj { 2384903Swnj register struct proc *p; 2394903Swnj 2404917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 2414903Swnj sb->sb_flags |= SB_COLL; 2424903Swnj else 2434903Swnj sb->sb_sel = u.u_procp; 2444903Swnj } 2454903Swnj 2464903Swnj /* 2474917Swnj * Wait for data to arrive at/drain from a socket buffer. 2484917Swnj */ 2494917Swnj sbwait(sb) 2504917Swnj struct sockbuf *sb; 2514917Swnj { 2524917Swnj 2534917Swnj sb->sb_flags |= SB_WAIT; 2544917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 2554917Swnj } 2564917Swnj 2574917Swnj /* 2584903Swnj * Wakeup processes waiting on a socket buffer. 2594903Swnj */ 2604903Swnj sbwakeup(sb) 26112758Ssam register struct sockbuf *sb; 2624903Swnj { 2634903Swnj 2644903Swnj if (sb->sb_sel) { 2654903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 2664903Swnj sb->sb_sel = 0; 2674903Swnj sb->sb_flags &= ~SB_COLL; 2684903Swnj } 2694903Swnj if (sb->sb_flags & SB_WAIT) { 2704903Swnj sb->sb_flags &= ~SB_WAIT; 2715013Swnj wakeup((caddr_t)&sb->sb_cc); 2724903Swnj } 2734903Swnj } 2744903Swnj 2754903Swnj /* 27615829Scooper * Wakeup socket readers and writers. 27715829Scooper * Do asynchronous notification via SIGIO 27815829Scooper * if the socket has the SS_ASYNC flag set. 27915829Scooper */ 28015829Scooper sowakeup(so, sb) 28115829Scooper register struct socket *so; 28215829Scooper struct sockbuf *sb; 28315829Scooper { 28415829Scooper register struct proc *p; 28515829Scooper 28615829Scooper sbwakeup(sb); 28715829Scooper if (so->so_state & SS_ASYNC) { 28823239Skarels if (so->so_pgrp < 0) 28923239Skarels gsignal(-so->so_pgrp, SIGIO); 29023239Skarels else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 29115829Scooper psignal(p, SIGIO); 29215829Scooper } 29315829Scooper } 29415829Scooper 29515829Scooper /* 2965169Swnj * Socket buffer (struct sockbuf) utility routines. 2975169Swnj * 2985169Swnj * Each socket contains two socket buffers: one for sending data and 2995169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 3005169Swnj * information about the number of mbufs and amount of data in the 3015169Swnj * queue, and other fields allowing select() statements and notification 3025169Swnj * on data availability to be implemented. 3035169Swnj * 30416994Skarels * Data stored in a socket buffer is maintained as a list of records. 30516994Skarels * Each record is a list of mbufs chained together with the m_next 30616994Skarels * field. Records are chained together with the m_act field. The upper 30716994Skarels * level routine soreceive() expects the following conventions to be 30816994Skarels * observed when placing information in the receive buffer: 30916994Skarels * 31016994Skarels * 1. If the protocol requires each message be preceded by the sender's 31116994Skarels * name, then a record containing that name must be present before 31216994Skarels * any associated data (mbuf's must be of type MT_SONAME). 31316994Skarels * 2. If the protocol supports the exchange of ``access rights'' (really 31416994Skarels * just additional data associated with the message), and there are 31516994Skarels * ``rights'' to be received, then a record containing this data 31616994Skarels * should be present (mbuf's must be of type MT_RIGHTS). 31716994Skarels * 3. If a name or rights record exists, then it must be followed by 31816994Skarels * a data record, perhaps of zero length. 31916994Skarels * 3205169Swnj * Before using a new socket structure it is first necessary to reserve 32133406Skarels * buffer space to the socket, by calling sbreserve(). This should commit 3225169Swnj * some of the available buffer space in the system buffer pool for the 32333406Skarels * socket (currently, it does nothing but enforce limits). The space 32433406Skarels * should be released by calling sbrelease() when the socket is destroyed. 3255169Swnj */ 3265169Swnj 3279027Sroot soreserve(so, sndcc, rcvcc) 32812758Ssam register struct socket *so; 32933406Skarels u_long sndcc, rcvcc; 3309027Sroot { 3319027Sroot 3329027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3339027Sroot goto bad; 3349027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3359027Sroot goto bad2; 3369027Sroot return (0); 3379027Sroot bad2: 3389027Sroot sbrelease(&so->so_snd); 3399027Sroot bad: 3409027Sroot return (ENOBUFS); 3419027Sroot } 3429027Sroot 3435169Swnj /* 3444903Swnj * Allot mbufs to a sockbuf. 34526830Skarels * Attempt to scale cc so that mbcnt doesn't become limiting 34626830Skarels * if buffering efficiency is near the normal case. 3474903Swnj */ 3484903Swnj sbreserve(sb, cc) 3494903Swnj struct sockbuf *sb; 35033406Skarels u_long cc; 3514903Swnj { 3524903Swnj 35333406Skarels if (cc > (u_long)SB_MAX * CLBYTES / (2 * MSIZE + CLBYTES)) 35417355Skarels return (0); 3554980Swnj sb->sb_hiwat = cc; 35617417Skarels sb->sb_mbmax = MIN(cc * 2, SB_MAX); 3574917Swnj return (1); 3584903Swnj } 3594903Swnj 3604903Swnj /* 3614903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3624903Swnj */ 3634903Swnj sbrelease(sb) 3644903Swnj struct sockbuf *sb; 3654903Swnj { 3664903Swnj 3674903Swnj sbflush(sb); 3684980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3694903Swnj } 3704903Swnj 3714903Swnj /* 37216994Skarels * Routines to add and remove 37316994Skarels * data from an mbuf queue. 37425630Skarels * 37525630Skarels * The routines sbappend() or sbappendrecord() are normally called to 37625630Skarels * append new mbufs to a socket buffer, after checking that adequate 37725630Skarels * space is available, comparing the function sbspace() with the amount 37825630Skarels * of data to be added. sbappendrecord() differs from sbappend() in 37925630Skarels * that data supplied is treated as the beginning of a new record. 38025630Skarels * To place a sender's address, optional access rights, and data in a 38125630Skarels * socket receive buffer, sbappendaddr() should be used. To place 38225630Skarels * access rights and data in a socket receive buffer, sbappendrights() 38325630Skarels * should be used. In either case, the new data begins a new record. 38425630Skarels * Note that unlike sbappend() and sbappendrecord(), these routines check 38525630Skarels * for the caller that there will be enough space to store the data. 38625630Skarels * Each fails if there is not enough space, or if it cannot find mbufs 38725630Skarels * to store additional information in. 38825630Skarels * 38925630Skarels * Reliable protocols may use the socket send buffer to hold data 39025630Skarels * awaiting acknowledgement. Data is normally copied from a socket 39125630Skarels * send buffer in a protocol with m_copy for output to a peer, 39225630Skarels * and then removing the data from the socket buffer with sbdrop() 39325630Skarels * or sbdroprecord() when the data is acknowledged by the peer. 3944903Swnj */ 3954903Swnj 3964903Swnj /* 39716994Skarels * Append mbuf chain m to the last record in the 39816994Skarels * socket buffer sb. The additional space associated 39916994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 40016994Skarels * discarded and mbufs are compacted where possible. 4014903Swnj */ 4024903Swnj sbappend(sb, m) 40316994Skarels struct sockbuf *sb; 40416994Skarels struct mbuf *m; 4054903Swnj { 4066092Sroot register struct mbuf *n; 4074903Swnj 40816994Skarels if (m == 0) 40916994Skarels return; 41016994Skarels if (n = sb->sb_mb) { 41116994Skarels while (n->m_act) 41216994Skarels n = n->m_act; 4136092Sroot while (n->m_next) 4146092Sroot n = n->m_next; 4154903Swnj } 41616994Skarels sbcompress(sb, m, n); 4174903Swnj } 4184903Swnj 4195169Swnj /* 42016994Skarels * As above, except the mbuf chain 42116994Skarels * begins a new record. 4225169Swnj */ 42316994Skarels sbappendrecord(sb, m0) 42416994Skarels register struct sockbuf *sb; 42516994Skarels register struct mbuf *m0; 4264928Swnj { 4274928Swnj register struct mbuf *m; 4284928Swnj 42916994Skarels if (m0 == 0) 43016994Skarels return; 43116994Skarels if (m = sb->sb_mb) 43216994Skarels while (m->m_act) 43316994Skarels m = m->m_act; 43416994Skarels /* 43516994Skarels * Put the first mbuf on the queue. 43616994Skarels * Note this permits zero length records. 43716994Skarels */ 43816994Skarels sballoc(sb, m0); 43916994Skarels if (m) 44016994Skarels m->m_act = m0; 44116994Skarels else 44216994Skarels sb->sb_mb = m0; 44316994Skarels m = m0->m_next; 44416994Skarels m0->m_next = 0; 44516994Skarels sbcompress(sb, m, m0); 44616994Skarels } 44716994Skarels 44816994Skarels /* 44916994Skarels * Append address and data, and optionally, rights 45016994Skarels * to the receive queue of a socket. Return 0 if 45116994Skarels * no space in sockbuf or insufficient mbufs. 45216994Skarels */ 45325630Skarels sbappendaddr(sb, asa, m0, rights0) 45416994Skarels register struct sockbuf *sb; 45516994Skarels struct sockaddr *asa; 45616994Skarels struct mbuf *rights0, *m0; 45716994Skarels { 45816994Skarels register struct mbuf *m, *n; 45916994Skarels int space = sizeof (*asa); 46016994Skarels 46125630Skarels for (m = m0; m; m = m->m_next) 46216994Skarels space += m->m_len; 46316994Skarels if (rights0) 46416994Skarels space += rights0->m_len; 46516994Skarels if (space > sbspace(sb)) 4664928Swnj return (0); 46725630Skarels MGET(m, M_DONTWAIT, MT_SONAME); 46816994Skarels if (m == 0) 4694928Swnj return (0); 47012758Ssam *mtod(m, struct sockaddr *) = *asa; 47116994Skarels m->m_len = sizeof (*asa); 47225921Skarels if (rights0 && rights0->m_len) { 47325630Skarels m->m_next = m_copy(rights0, 0, rights0->m_len); 47425630Skarels if (m->m_next == 0) { 47516994Skarels m_freem(m); 47616994Skarels return (0); 47716994Skarels } 47825630Skarels sballoc(sb, m->m_next); 47921765Skarels } 48025938Skarels sballoc(sb, m); 48116994Skarels if (n = sb->sb_mb) { 48216994Skarels while (n->m_act) 48316994Skarels n = n->m_act; 48416994Skarels n->m_act = m; 48516994Skarels } else 48616994Skarels sb->sb_mb = m; 48725630Skarels if (m->m_next) 48825630Skarels m = m->m_next; 48925630Skarels if (m0) 49025630Skarels sbcompress(sb, m0, m); 49116994Skarels return (1); 49216994Skarels } 49316994Skarels 49425630Skarels sbappendrights(sb, m0, rights) 49516994Skarels struct sockbuf *sb; 49625630Skarels struct mbuf *rights, *m0; 49716994Skarels { 49816994Skarels register struct mbuf *m, *n; 49916994Skarels int space = 0; 50016994Skarels 50125630Skarels if (rights == 0) 50216994Skarels panic("sbappendrights"); 50325630Skarels for (m = m0; m; m = m->m_next) 50416994Skarels space += m->m_len; 50516994Skarels space += rights->m_len; 50616994Skarels if (space > sbspace(sb)) 50712758Ssam return (0); 50816994Skarels m = m_copy(rights, 0, rights->m_len); 50916994Skarels if (m == 0) 51016994Skarels return (0); 51116994Skarels sballoc(sb, m); 51216994Skarels if (n = sb->sb_mb) { 51316994Skarels while (n->m_act) 51416994Skarels n = n->m_act; 51516994Skarels n->m_act = m; 51616994Skarels } else 51725630Skarels sb->sb_mb = m; 51825630Skarels if (m0) 51925630Skarels sbcompress(sb, m0, m); 5204928Swnj return (1); 5214928Swnj } 5224928Swnj 5234903Swnj /* 52416994Skarels * Compress mbuf chain m into the socket 52516994Skarels * buffer sb following mbuf n. If n 52616994Skarels * is null, the buffer is presumed empty. 5274903Swnj */ 52816994Skarels sbcompress(sb, m, n) 52916994Skarels register struct sockbuf *sb; 53016994Skarels register struct mbuf *m, *n; 53116994Skarels { 53216994Skarels 53316994Skarels while (m) { 53416994Skarels if (m->m_len == 0) { 53516994Skarels m = m_free(m); 53616994Skarels continue; 53716994Skarels } 53816994Skarels if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 53925630Skarels (n->m_off + n->m_len + m->m_len) <= MMAXOFF && 54025630Skarels n->m_type == m->m_type) { 54116994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 54216994Skarels (unsigned)m->m_len); 54316994Skarels n->m_len += m->m_len; 54416994Skarels sb->sb_cc += m->m_len; 54516994Skarels m = m_free(m); 54616994Skarels continue; 54716994Skarels } 54816994Skarels sballoc(sb, m); 54916994Skarels if (n) 55016994Skarels n->m_next = m; 55116994Skarels else 55216994Skarels sb->sb_mb = m; 55316994Skarels n = m; 55416994Skarels m = m->m_next; 55516994Skarels n->m_next = 0; 55616994Skarels } 55716994Skarels } 55816994Skarels 55916994Skarels /* 56016994Skarels * Free all mbufs in a sockbuf. 56116994Skarels * Check that all resources are reclaimed. 56216994Skarels */ 5634903Swnj sbflush(sb) 56412758Ssam register struct sockbuf *sb; 5654903Swnj { 5664903Swnj 5674903Swnj if (sb->sb_flags & SB_LOCK) 5684903Swnj panic("sbflush"); 56926105Skarels while (sb->sb_mbcnt) 57026363Skarels sbdrop(sb, (int)sb->sb_cc); 5714903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 5724903Swnj panic("sbflush 2"); 5734903Swnj } 5744903Swnj 5754903Swnj /* 57616994Skarels * Drop data from (the front of) a sockbuf. 5774903Swnj */ 5784903Swnj sbdrop(sb, len) 5794903Swnj register struct sockbuf *sb; 5804903Swnj register int len; 5814903Swnj { 58216994Skarels register struct mbuf *m, *mn; 58316994Skarels struct mbuf *next; 5844903Swnj 58516994Skarels next = (m = sb->sb_mb) ? m->m_act : 0; 5864903Swnj while (len > 0) { 58716994Skarels if (m == 0) { 58816994Skarels if (next == 0) 58916994Skarels panic("sbdrop"); 59016994Skarels m = next; 59116994Skarels next = m->m_act; 59216994Skarels continue; 59316994Skarels } 5945064Swnj if (m->m_len > len) { 5954903Swnj m->m_len -= len; 5964903Swnj m->m_off += len; 5974903Swnj sb->sb_cc -= len; 5984903Swnj break; 5994903Swnj } 6005064Swnj len -= m->m_len; 6015064Swnj sbfree(sb, m); 6025064Swnj MFREE(m, mn); 6035064Swnj m = mn; 6044903Swnj } 60517331Skarels while (m && m->m_len == 0) { 60617417Skarels sbfree(sb, m); 60717331Skarels MFREE(m, mn); 60817331Skarels m = mn; 60917331Skarels } 61016994Skarels if (m) { 61116994Skarels sb->sb_mb = m; 61216994Skarels m->m_act = next; 61316994Skarels } else 61416994Skarels sb->sb_mb = next; 6154903Swnj } 61616994Skarels 61716994Skarels /* 61816994Skarels * Drop a record off the front of a sockbuf 61916994Skarels * and move the next record to the front. 62016994Skarels */ 62116994Skarels sbdroprecord(sb) 62216994Skarels register struct sockbuf *sb; 62316994Skarels { 62416994Skarels register struct mbuf *m, *mn; 62516994Skarels 62616994Skarels m = sb->sb_mb; 62716994Skarels if (m) { 62816994Skarels sb->sb_mb = m->m_act; 62916994Skarels do { 63016994Skarels sbfree(sb, m); 63116994Skarels MFREE(m, mn); 63216994Skarels } while (m = mn); 63316994Skarels } 63416994Skarels } 635