123431Smckusick /* 2*35385Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 333187Sbostic * All rights reserved. 423431Smckusick * 533187Sbostic * Redistribution and use in source and binary forms are permitted 634858Sbostic * provided that the above copyright notice and this paragraph are 734858Sbostic * duplicated in all such forms and that any documentation, 834858Sbostic * advertising materials, and other materials related to such 934858Sbostic * distribution and use acknowledge that the software was developed 1034858Sbostic * by the University of California, Berkeley. The name of the 1134858Sbostic * University may not be used to endorse or promote products derived 1234858Sbostic * from this software without specific prior written permission. 1334858Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434858Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534858Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633187Sbostic * 17*35385Skarels * @(#)uipc_socket2.c 7.6 (Berkeley) 08/21/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" 28*35385Skarels #include "malloc.h" 2917103Sbloom #include "mbuf.h" 3017103Sbloom #include "protosw.h" 3117103Sbloom #include "socket.h" 3217103Sbloom #include "socketvar.h" 334903Swnj 344903Swnj /* 354903Swnj * Primitive routines for operating on sockets and socket buffers 364903Swnj */ 374903Swnj 384903Swnj /* 394903Swnj * Procedures to manipulate state flags of socket 407509Sroot * and do appropriate wakeups. Normal sequence from the 417509Sroot * active (originating) side is that soisconnecting() is 427509Sroot * called during processing of connect() call, 435169Swnj * resulting in an eventual call to soisconnected() if/when the 445169Swnj * connection is established. When the connection is torn down 455169Swnj * soisdisconnecting() is called during processing of disconnect() call, 465169Swnj * and soisdisconnected() is called when the connection to the peer 475169Swnj * is totally severed. The semantics of these routines are such that 485169Swnj * connectionless protocols can call soisconnected() and soisdisconnected() 495169Swnj * only, bypassing the in-progress calls when setting up a ``connection'' 505169Swnj * takes no time. 515169Swnj * 5212758Ssam * From the passive side, a socket is created with 5312758Ssam * two queues of sockets: so_q0 for connections in progress 547509Sroot * and so_q for connections already made and awaiting user acceptance. 557509Sroot * As a protocol is preparing incoming connections, it creates a socket 567509Sroot * structure queued on so_q0 by calling sonewconn(). When the connection 577509Sroot * is established, soisconnected() is called, and transfers the 587509Sroot * socket structure to so_q, making it available to accept(). 597509Sroot * 6012758Ssam * If a socket is closed with sockets on either 617509Sroot * so_q0 or so_q, these sockets are dropped. 627509Sroot * 6312758Ssam * If higher level protocols are implemented in 645169Swnj * the kernel, the wakeups done here will sometimes 6512758Ssam * cause software-interrupt process scheduling. 664903Swnj */ 675169Swnj 684903Swnj soisconnecting(so) 6912758Ssam register struct socket *so; 704903Swnj { 714903Swnj 724903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 734903Swnj so->so_state |= SS_ISCONNECTING; 744903Swnj wakeup((caddr_t)&so->so_timeo); 754903Swnj } 764903Swnj 774903Swnj soisconnected(so) 7812758Ssam register struct socket *so; 794903Swnj { 807509Sroot register struct socket *head = so->so_head; 814903Swnj 827509Sroot if (head) { 837509Sroot if (soqremque(so, 0) == 0) 847509Sroot panic("soisconnected"); 857509Sroot soqinsque(head, so, 1); 8612758Ssam sorwakeup(head); 877509Sroot wakeup((caddr_t)&head->so_timeo); 887509Sroot } 894903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 904903Swnj so->so_state |= SS_ISCONNECTED; 914903Swnj wakeup((caddr_t)&so->so_timeo); 925578Swnj sorwakeup(so); 935578Swnj sowwakeup(so); 944903Swnj } 954903Swnj 964903Swnj soisdisconnecting(so) 9712758Ssam register struct socket *so; 984903Swnj { 994903Swnj 1005248Sroot so->so_state &= ~SS_ISCONNECTING; 1014903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 1024903Swnj wakeup((caddr_t)&so->so_timeo); 1035170Swnj sowwakeup(so); 1045169Swnj sorwakeup(so); 1054903Swnj } 1064903Swnj 1074903Swnj soisdisconnected(so) 10812758Ssam register struct socket *so; 1094903Swnj { 1104903Swnj 1114903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 1124903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 1134903Swnj wakeup((caddr_t)&so->so_timeo); 1144903Swnj sowwakeup(so); 1154903Swnj sorwakeup(so); 1164903Swnj } 1174903Swnj 1185169Swnj /* 1197509Sroot * When an attempt at a new connection is noted on a socket 1207509Sroot * which accepts connections, sonewconn is called. If the 1217509Sroot * connection is possible (subject to space constraints, etc.) 1227509Sroot * then we allocate a new structure, propoerly linked into the 1237509Sroot * data structure of the original socket, and return this. 1247509Sroot */ 1257509Sroot struct socket * 1267509Sroot sonewconn(head) 1277509Sroot register struct socket *head; 1287509Sroot { 1297509Sroot register struct socket *so; 13012758Ssam register struct mbuf *m; 1317509Sroot 1327509Sroot if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) 1337509Sroot goto bad; 1349636Ssam m = m_getclr(M_DONTWAIT, MT_SOCKET); 13510138Ssam if (m == NULL) 1367509Sroot goto bad; 1377509Sroot so = mtod(m, struct socket *); 1387509Sroot so->so_type = head->so_type; 1397509Sroot so->so_options = head->so_options &~ SO_ACCEPTCONN; 1407509Sroot so->so_linger = head->so_linger; 14110204Ssam so->so_state = head->so_state | SS_NOFDREF; 1427509Sroot so->so_proto = head->so_proto; 1437509Sroot so->so_timeo = head->so_timeo; 1447509Sroot so->so_pgrp = head->so_pgrp; 145*35385Skarels (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); 1467509Sroot soqinsque(head, so, 0); 14712758Ssam if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, 14812758Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { 1497509Sroot (void) soqremque(so, 0); 1508818Sroot (void) m_free(m); 1517509Sroot goto bad; 1527509Sroot } 1537509Sroot return (so); 1547509Sroot bad: 1557509Sroot return ((struct socket *)0); 1567509Sroot } 1577509Sroot 1587509Sroot soqinsque(head, so, q) 1597509Sroot register struct socket *head, *so; 1607509Sroot int q; 1617509Sroot { 1627509Sroot 1637509Sroot so->so_head = head; 1647509Sroot if (q == 0) { 1657509Sroot head->so_q0len++; 1667509Sroot so->so_q0 = head->so_q0; 1677509Sroot head->so_q0 = so; 1687509Sroot } else { 1697509Sroot head->so_qlen++; 1707509Sroot so->so_q = head->so_q; 1717509Sroot head->so_q = so; 1727509Sroot } 1737509Sroot } 1747509Sroot 1757509Sroot soqremque(so, q) 1767509Sroot register struct socket *so; 1777509Sroot int q; 1787509Sroot { 1797509Sroot register struct socket *head, *prev, *next; 1807509Sroot 1817509Sroot head = so->so_head; 1827509Sroot prev = head; 1837509Sroot for (;;) { 1847509Sroot next = q ? prev->so_q : prev->so_q0; 1857509Sroot if (next == so) 1867509Sroot break; 1877509Sroot if (next == head) 1887509Sroot return (0); 1897509Sroot prev = next; 1907509Sroot } 1917509Sroot if (q == 0) { 1927509Sroot prev->so_q0 = next->so_q0; 1937509Sroot head->so_q0len--; 1947509Sroot } else { 1957509Sroot prev->so_q = next->so_q; 1967509Sroot head->so_qlen--; 1977509Sroot } 1987509Sroot next->so_q0 = next->so_q = 0; 1997509Sroot next->so_head = 0; 2007509Sroot return (1); 2017509Sroot } 2027509Sroot 2037509Sroot /* 2045169Swnj * Socantsendmore indicates that no more data will be sent on the 2055169Swnj * socket; it would normally be applied to a socket when the user 2065169Swnj * informs the system that no more data is to be sent, by the protocol 2075169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 2085169Swnj * will be received, and will normally be applied to the socket by a 2095169Swnj * protocol when it detects that the peer will send no more data. 2105169Swnj * Data queued for reading in the socket may yet be read. 2115169Swnj */ 2125169Swnj 2134917Swnj socantsendmore(so) 2144917Swnj struct socket *so; 2154917Swnj { 2164917Swnj 2174917Swnj so->so_state |= SS_CANTSENDMORE; 2184917Swnj sowwakeup(so); 2194917Swnj } 2204917Swnj 2214917Swnj socantrcvmore(so) 2224917Swnj struct socket *so; 2234917Swnj { 2244917Swnj 2254917Swnj so->so_state |= SS_CANTRCVMORE; 2264917Swnj sorwakeup(so); 2274917Swnj } 2284917Swnj 2294903Swnj /* 2305169Swnj * Socket select/wakeup routines. 2314903Swnj */ 2325169Swnj 2335169Swnj /* 2344903Swnj * Queue a process for a select on a socket buffer. 2354903Swnj */ 2364903Swnj sbselqueue(sb) 2374903Swnj struct sockbuf *sb; 2384903Swnj { 239*35385Skarels struct proc *p; 2404903Swnj 2414917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 2424903Swnj sb->sb_flags |= SB_COLL; 2434903Swnj else 2444903Swnj sb->sb_sel = u.u_procp; 2454903Swnj } 2464903Swnj 2474903Swnj /* 2484917Swnj * Wait for data to arrive at/drain from a socket buffer. 2494917Swnj */ 2504917Swnj sbwait(sb) 2514917Swnj struct sockbuf *sb; 2524917Swnj { 2534917Swnj 2544917Swnj sb->sb_flags |= SB_WAIT; 2554917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 2564917Swnj } 2574917Swnj 2584917Swnj /* 2594903Swnj * Wakeup processes waiting on a socket buffer. 260*35385Skarels * Do asynchronous notification via SIGIO 261*35385Skarels * if the socket has the SS_ASYNC flag set. 2624903Swnj */ 263*35385Skarels sowakeup(so, sb) 264*35385Skarels register struct socket *so; 26512758Ssam register struct sockbuf *sb; 2664903Swnj { 267*35385Skarels register struct proc *p; 2684903Swnj 2694903Swnj if (sb->sb_sel) { 2704903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 2714903Swnj sb->sb_sel = 0; 2724903Swnj sb->sb_flags &= ~SB_COLL; 2734903Swnj } 2744903Swnj if (sb->sb_flags & SB_WAIT) { 2754903Swnj sb->sb_flags &= ~SB_WAIT; 2765013Swnj wakeup((caddr_t)&sb->sb_cc); 2774903Swnj } 27815829Scooper if (so->so_state & SS_ASYNC) { 27923239Skarels if (so->so_pgrp < 0) 28023239Skarels gsignal(-so->so_pgrp, SIGIO); 28123239Skarels else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 28215829Scooper psignal(p, SIGIO); 28315829Scooper } 28415829Scooper } 28515829Scooper 28615829Scooper /* 2875169Swnj * Socket buffer (struct sockbuf) utility routines. 2885169Swnj * 2895169Swnj * Each socket contains two socket buffers: one for sending data and 2905169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 2915169Swnj * information about the number of mbufs and amount of data in the 2925169Swnj * queue, and other fields allowing select() statements and notification 2935169Swnj * on data availability to be implemented. 2945169Swnj * 29516994Skarels * Data stored in a socket buffer is maintained as a list of records. 29616994Skarels * Each record is a list of mbufs chained together with the m_next 297*35385Skarels * field. Records are chained together with the m_nextpkt field. The upper 29816994Skarels * level routine soreceive() expects the following conventions to be 29916994Skarels * observed when placing information in the receive buffer: 30016994Skarels * 30116994Skarels * 1. If the protocol requires each message be preceded by the sender's 30216994Skarels * name, then a record containing that name must be present before 30316994Skarels * any associated data (mbuf's must be of type MT_SONAME). 30416994Skarels * 2. If the protocol supports the exchange of ``access rights'' (really 30516994Skarels * just additional data associated with the message), and there are 30616994Skarels * ``rights'' to be received, then a record containing this data 30716994Skarels * should be present (mbuf's must be of type MT_RIGHTS). 30816994Skarels * 3. If a name or rights record exists, then it must be followed by 30916994Skarels * a data record, perhaps of zero length. 31016994Skarels * 3115169Swnj * Before using a new socket structure it is first necessary to reserve 31233406Skarels * buffer space to the socket, by calling sbreserve(). This should commit 3135169Swnj * some of the available buffer space in the system buffer pool for the 31433406Skarels * socket (currently, it does nothing but enforce limits). The space 31533406Skarels * should be released by calling sbrelease() when the socket is destroyed. 3165169Swnj */ 3175169Swnj 3189027Sroot soreserve(so, sndcc, rcvcc) 31912758Ssam register struct socket *so; 32033406Skarels u_long sndcc, rcvcc; 3219027Sroot { 3229027Sroot 3239027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3249027Sroot goto bad; 3259027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3269027Sroot goto bad2; 3279027Sroot return (0); 3289027Sroot bad2: 3299027Sroot sbrelease(&so->so_snd); 3309027Sroot bad: 3319027Sroot return (ENOBUFS); 3329027Sroot } 3339027Sroot 3345169Swnj /* 3354903Swnj * Allot mbufs to a sockbuf. 33626830Skarels * Attempt to scale cc so that mbcnt doesn't become limiting 33726830Skarels * if buffering efficiency is near the normal case. 3384903Swnj */ 3394903Swnj sbreserve(sb, cc) 3404903Swnj struct sockbuf *sb; 34133406Skarels u_long cc; 3424903Swnj { 3434903Swnj 344*35385Skarels if (cc > (u_long)SB_MAX * MCLBYTES / (2 * MSIZE + MCLBYTES)) 34517355Skarels return (0); 3464980Swnj sb->sb_hiwat = cc; 34717417Skarels sb->sb_mbmax = MIN(cc * 2, SB_MAX); 3484917Swnj return (1); 3494903Swnj } 3504903Swnj 3514903Swnj /* 3524903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3534903Swnj */ 3544903Swnj sbrelease(sb) 3554903Swnj struct sockbuf *sb; 3564903Swnj { 3574903Swnj 3584903Swnj sbflush(sb); 3594980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3604903Swnj } 3614903Swnj 3624903Swnj /* 36316994Skarels * Routines to add and remove 36416994Skarels * data from an mbuf queue. 36525630Skarels * 36625630Skarels * The routines sbappend() or sbappendrecord() are normally called to 36725630Skarels * append new mbufs to a socket buffer, after checking that adequate 36825630Skarels * space is available, comparing the function sbspace() with the amount 36925630Skarels * of data to be added. sbappendrecord() differs from sbappend() in 37025630Skarels * that data supplied is treated as the beginning of a new record. 37125630Skarels * To place a sender's address, optional access rights, and data in a 37225630Skarels * socket receive buffer, sbappendaddr() should be used. To place 37325630Skarels * access rights and data in a socket receive buffer, sbappendrights() 37425630Skarels * should be used. In either case, the new data begins a new record. 37525630Skarels * Note that unlike sbappend() and sbappendrecord(), these routines check 37625630Skarels * for the caller that there will be enough space to store the data. 37725630Skarels * Each fails if there is not enough space, or if it cannot find mbufs 37825630Skarels * to store additional information in. 37925630Skarels * 38025630Skarels * Reliable protocols may use the socket send buffer to hold data 38125630Skarels * awaiting acknowledgement. Data is normally copied from a socket 38225630Skarels * send buffer in a protocol with m_copy for output to a peer, 38325630Skarels * and then removing the data from the socket buffer with sbdrop() 38425630Skarels * or sbdroprecord() when the data is acknowledged by the peer. 3854903Swnj */ 3864903Swnj 3874903Swnj /* 38816994Skarels * Append mbuf chain m to the last record in the 38916994Skarels * socket buffer sb. The additional space associated 39016994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 39116994Skarels * discarded and mbufs are compacted where possible. 3924903Swnj */ 3934903Swnj sbappend(sb, m) 39416994Skarels struct sockbuf *sb; 39516994Skarels struct mbuf *m; 3964903Swnj { 3976092Sroot register struct mbuf *n; 3984903Swnj 39916994Skarels if (m == 0) 40016994Skarels return; 40116994Skarels if (n = sb->sb_mb) { 402*35385Skarels while (n->m_nextpkt) 403*35385Skarels n = n->m_nextpkt; 4046092Sroot while (n->m_next) 4056092Sroot n = n->m_next; 4064903Swnj } 40716994Skarels sbcompress(sb, m, n); 4084903Swnj } 4094903Swnj 4105169Swnj /* 41116994Skarels * As above, except the mbuf chain 41216994Skarels * begins a new record. 4135169Swnj */ 41416994Skarels sbappendrecord(sb, m0) 41516994Skarels register struct sockbuf *sb; 41616994Skarels register struct mbuf *m0; 4174928Swnj { 4184928Swnj register struct mbuf *m; 4194928Swnj 42016994Skarels if (m0 == 0) 42116994Skarels return; 42216994Skarels if (m = sb->sb_mb) 423*35385Skarels while (m->m_nextpkt) 424*35385Skarels m = m->m_nextpkt; 42516994Skarels /* 42616994Skarels * Put the first mbuf on the queue. 42716994Skarels * Note this permits zero length records. 42816994Skarels */ 42916994Skarels sballoc(sb, m0); 43016994Skarels if (m) 431*35385Skarels m->m_nextpkt = m0; 43216994Skarels else 43316994Skarels sb->sb_mb = m0; 43416994Skarels m = m0->m_next; 43516994Skarels m0->m_next = 0; 43616994Skarels sbcompress(sb, m, m0); 43716994Skarels } 43816994Skarels 43916994Skarels /* 44016994Skarels * Append address and data, and optionally, rights 441*35385Skarels * to the receive queue of a socket. If present, 442*35385Skarels * m0 Return 0 if 44316994Skarels * no space in sockbuf or insufficient mbufs. 44416994Skarels */ 44525630Skarels sbappendaddr(sb, asa, m0, rights0) 44616994Skarels register struct sockbuf *sb; 44716994Skarels struct sockaddr *asa; 448*35385Skarels struct mbuf *m0, *rights0; 44916994Skarels { 45016994Skarels register struct mbuf *m, *n; 45116994Skarels int space = sizeof (*asa); 45216994Skarels 453*35385Skarels if (m0 && (m0->m_flags & M_PKTHDR) == 0) 454*35385Skarels panic("sbappendaddr"); 455*35385Skarels if (m0) 456*35385Skarels space += m0->m_pkthdr.len; 45716994Skarels if (rights0) 45816994Skarels space += rights0->m_len; 45916994Skarels if (space > sbspace(sb)) 4604928Swnj return (0); 46125630Skarels MGET(m, M_DONTWAIT, MT_SONAME); 46216994Skarels if (m == 0) 4634928Swnj return (0); 46412758Ssam *mtod(m, struct sockaddr *) = *asa; 46516994Skarels m->m_len = sizeof (*asa); 46625921Skarels if (rights0 && rights0->m_len) { 46725630Skarels m->m_next = m_copy(rights0, 0, rights0->m_len); 46825630Skarels if (m->m_next == 0) { 46916994Skarels m_freem(m); 47016994Skarels return (0); 47116994Skarels } 47225630Skarels sballoc(sb, m->m_next); 47321765Skarels } 47425938Skarels sballoc(sb, m); 47516994Skarels if (n = sb->sb_mb) { 476*35385Skarels while (n->m_nextpkt) 477*35385Skarels n = n->m_nextpkt; 478*35385Skarels n->m_nextpkt = m; 47916994Skarels } else 48016994Skarels sb->sb_mb = m; 48125630Skarels if (m->m_next) 48225630Skarels m = m->m_next; 48325630Skarels if (m0) 48425630Skarels sbcompress(sb, m0, m); 48516994Skarels return (1); 48616994Skarels } 48716994Skarels 48825630Skarels sbappendrights(sb, m0, rights) 48916994Skarels struct sockbuf *sb; 49025630Skarels struct mbuf *rights, *m0; 49116994Skarels { 49216994Skarels register struct mbuf *m, *n; 49316994Skarels int space = 0; 49416994Skarels 49525630Skarels if (rights == 0) 49616994Skarels panic("sbappendrights"); 49725630Skarels for (m = m0; m; m = m->m_next) 49816994Skarels space += m->m_len; 49916994Skarels space += rights->m_len; 50016994Skarels if (space > sbspace(sb)) 50112758Ssam return (0); 50216994Skarels m = m_copy(rights, 0, rights->m_len); 50316994Skarels if (m == 0) 50416994Skarels return (0); 50516994Skarels sballoc(sb, m); 50616994Skarels if (n = sb->sb_mb) { 507*35385Skarels while (n->m_nextpkt) 508*35385Skarels n = n->m_nextpkt; 509*35385Skarels n->m_nextpkt = m; 51016994Skarels } else 51125630Skarels sb->sb_mb = m; 51225630Skarels if (m0) 51325630Skarels sbcompress(sb, m0, m); 5144928Swnj return (1); 5154928Swnj } 5164928Swnj 5174903Swnj /* 51816994Skarels * Compress mbuf chain m into the socket 51916994Skarels * buffer sb following mbuf n. If n 52016994Skarels * is null, the buffer is presumed empty. 5214903Swnj */ 52216994Skarels sbcompress(sb, m, n) 52316994Skarels register struct sockbuf *sb; 52416994Skarels register struct mbuf *m, *n; 52516994Skarels { 52616994Skarels 52716994Skarels while (m) { 52816994Skarels if (m->m_len == 0) { 52916994Skarels m = m_free(m); 53016994Skarels continue; 53116994Skarels } 532*35385Skarels if (n && (n->m_flags & M_EXT) == 0 && 533*35385Skarels (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] && 53425630Skarels n->m_type == m->m_type) { 53516994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 53616994Skarels (unsigned)m->m_len); 53716994Skarels n->m_len += m->m_len; 53816994Skarels sb->sb_cc += m->m_len; 53916994Skarels m = m_free(m); 54016994Skarels continue; 54116994Skarels } 54216994Skarels sballoc(sb, m); 54316994Skarels if (n) 54416994Skarels n->m_next = m; 54516994Skarels else 54616994Skarels sb->sb_mb = m; 54716994Skarels n = m; 54816994Skarels m = m->m_next; 54916994Skarels n->m_next = 0; 55016994Skarels } 55116994Skarels } 55216994Skarels 55316994Skarels /* 55416994Skarels * Free all mbufs in a sockbuf. 55516994Skarels * Check that all resources are reclaimed. 55616994Skarels */ 5574903Swnj sbflush(sb) 55812758Ssam register struct sockbuf *sb; 5594903Swnj { 5604903Swnj 5614903Swnj if (sb->sb_flags & SB_LOCK) 5624903Swnj panic("sbflush"); 56326105Skarels while (sb->sb_mbcnt) 56426363Skarels sbdrop(sb, (int)sb->sb_cc); 5654903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 5664903Swnj panic("sbflush 2"); 5674903Swnj } 5684903Swnj 5694903Swnj /* 57016994Skarels * Drop data from (the front of) a sockbuf. 5714903Swnj */ 5724903Swnj sbdrop(sb, len) 5734903Swnj register struct sockbuf *sb; 5744903Swnj register int len; 5754903Swnj { 57616994Skarels register struct mbuf *m, *mn; 57716994Skarels struct mbuf *next; 5784903Swnj 579*35385Skarels next = (m = sb->sb_mb) ? m->m_nextpkt : 0; 5804903Swnj while (len > 0) { 58116994Skarels if (m == 0) { 58216994Skarels if (next == 0) 58316994Skarels panic("sbdrop"); 58416994Skarels m = next; 585*35385Skarels next = m->m_nextpkt; 58616994Skarels continue; 58716994Skarels } 5885064Swnj if (m->m_len > len) { 5894903Swnj m->m_len -= len; 590*35385Skarels m->m_data += len; 5914903Swnj sb->sb_cc -= len; 5924903Swnj break; 5934903Swnj } 5945064Swnj len -= m->m_len; 5955064Swnj sbfree(sb, m); 5965064Swnj MFREE(m, mn); 5975064Swnj m = mn; 5984903Swnj } 59917331Skarels while (m && m->m_len == 0) { 60017417Skarels sbfree(sb, m); 60117331Skarels MFREE(m, mn); 60217331Skarels m = mn; 60317331Skarels } 60416994Skarels if (m) { 60516994Skarels sb->sb_mb = m; 606*35385Skarels m->m_nextpkt = next; 60716994Skarels } else 60816994Skarels sb->sb_mb = next; 6094903Swnj } 61016994Skarels 61116994Skarels /* 61216994Skarels * Drop a record off the front of a sockbuf 61316994Skarels * and move the next record to the front. 61416994Skarels */ 61516994Skarels sbdroprecord(sb) 61616994Skarels register struct sockbuf *sb; 61716994Skarels { 61816994Skarels register struct mbuf *m, *mn; 61916994Skarels 62016994Skarels m = sb->sb_mb; 62116994Skarels if (m) { 622*35385Skarels sb->sb_mb = m->m_nextpkt; 62316994Skarels do { 62416994Skarels sbfree(sb, m); 62516994Skarels MFREE(m, mn); 62616994Skarels } while (m = mn); 62716994Skarels } 62816994Skarels } 629