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 633187Sbostic * provided that this notice is preserved and that due credit is given 733187Sbostic * to the University of California at Berkeley. The name of the University 833187Sbostic * may not be used to endorse or promote products derived from this 933187Sbostic * software without specific prior written permission. This software 1033187Sbostic * is provided ``as is'' without express or implied warranty. 1133187Sbostic * 12*34491Skarels * @(#)uipc_socket2.c 7.4 (Berkeley) 05/26/88 1323431Smckusick */ 144903Swnj 1517103Sbloom #include "param.h" 1617103Sbloom #include "systm.h" 1717103Sbloom #include "dir.h" 1817103Sbloom #include "user.h" 1917103Sbloom #include "proc.h" 2017103Sbloom #include "file.h" 2117103Sbloom #include "inode.h" 2217103Sbloom #include "buf.h" 2317103Sbloom #include "mbuf.h" 2417103Sbloom #include "protosw.h" 2517103Sbloom #include "socket.h" 2617103Sbloom #include "socketvar.h" 274903Swnj 284903Swnj /* 294903Swnj * Primitive routines for operating on sockets and socket buffers 304903Swnj */ 314903Swnj 324903Swnj /* 334903Swnj * Procedures to manipulate state flags of socket 347509Sroot * and do appropriate wakeups. Normal sequence from the 357509Sroot * active (originating) side is that soisconnecting() is 367509Sroot * called during processing of connect() call, 375169Swnj * resulting in an eventual call to soisconnected() if/when the 385169Swnj * connection is established. When the connection is torn down 395169Swnj * soisdisconnecting() is called during processing of disconnect() call, 405169Swnj * and soisdisconnected() is called when the connection to the peer 415169Swnj * is totally severed. The semantics of these routines are such that 425169Swnj * connectionless protocols can call soisconnected() and soisdisconnected() 435169Swnj * only, bypassing the in-progress calls when setting up a ``connection'' 445169Swnj * takes no time. 455169Swnj * 4612758Ssam * From the passive side, a socket is created with 4712758Ssam * two queues of sockets: so_q0 for connections in progress 487509Sroot * and so_q for connections already made and awaiting user acceptance. 497509Sroot * As a protocol is preparing incoming connections, it creates a socket 507509Sroot * structure queued on so_q0 by calling sonewconn(). When the connection 517509Sroot * is established, soisconnected() is called, and transfers the 527509Sroot * socket structure to so_q, making it available to accept(). 537509Sroot * 5412758Ssam * If a socket is closed with sockets on either 557509Sroot * so_q0 or so_q, these sockets are dropped. 567509Sroot * 5712758Ssam * If higher level protocols are implemented in 585169Swnj * the kernel, the wakeups done here will sometimes 5912758Ssam * cause software-interrupt process scheduling. 604903Swnj */ 615169Swnj 624903Swnj soisconnecting(so) 6312758Ssam register struct socket *so; 644903Swnj { 654903Swnj 664903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 674903Swnj so->so_state |= SS_ISCONNECTING; 684903Swnj wakeup((caddr_t)&so->so_timeo); 694903Swnj } 704903Swnj 714903Swnj soisconnected(so) 7212758Ssam register struct socket *so; 734903Swnj { 747509Sroot register struct socket *head = so->so_head; 754903Swnj 767509Sroot if (head) { 777509Sroot if (soqremque(so, 0) == 0) 787509Sroot panic("soisconnected"); 797509Sroot soqinsque(head, so, 1); 8012758Ssam sorwakeup(head); 817509Sroot wakeup((caddr_t)&head->so_timeo); 827509Sroot } 834903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 844903Swnj so->so_state |= SS_ISCONNECTED; 854903Swnj wakeup((caddr_t)&so->so_timeo); 865578Swnj sorwakeup(so); 875578Swnj sowwakeup(so); 884903Swnj } 894903Swnj 904903Swnj soisdisconnecting(so) 9112758Ssam register struct socket *so; 924903Swnj { 934903Swnj 945248Sroot so->so_state &= ~SS_ISCONNECTING; 954903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 964903Swnj wakeup((caddr_t)&so->so_timeo); 975170Swnj sowwakeup(so); 985169Swnj sorwakeup(so); 994903Swnj } 1004903Swnj 1014903Swnj soisdisconnected(so) 10212758Ssam register struct socket *so; 1034903Swnj { 1044903Swnj 1054903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 1064903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 1074903Swnj wakeup((caddr_t)&so->so_timeo); 1084903Swnj sowwakeup(so); 1094903Swnj sorwakeup(so); 1104903Swnj } 1114903Swnj 1125169Swnj /* 1137509Sroot * When an attempt at a new connection is noted on a socket 1147509Sroot * which accepts connections, sonewconn is called. If the 1157509Sroot * connection is possible (subject to space constraints, etc.) 1167509Sroot * then we allocate a new structure, propoerly linked into the 1177509Sroot * data structure of the original socket, and return this. 1187509Sroot */ 1197509Sroot struct socket * 1207509Sroot sonewconn(head) 1217509Sroot register struct socket *head; 1227509Sroot { 1237509Sroot register struct socket *so; 12412758Ssam register struct mbuf *m; 1257509Sroot 1267509Sroot if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) 1277509Sroot goto bad; 1289636Ssam m = m_getclr(M_DONTWAIT, MT_SOCKET); 12910138Ssam if (m == NULL) 1307509Sroot goto bad; 1317509Sroot so = mtod(m, struct socket *); 1327509Sroot so->so_type = head->so_type; 1337509Sroot so->so_options = head->so_options &~ SO_ACCEPTCONN; 1347509Sroot so->so_linger = head->so_linger; 13510204Ssam so->so_state = head->so_state | SS_NOFDREF; 1367509Sroot so->so_proto = head->so_proto; 1377509Sroot so->so_timeo = head->so_timeo; 1387509Sroot so->so_pgrp = head->so_pgrp; 139*34491Skarels (void) soreserve(so, head->so_snd.sb_hiwat, head->so_snd.sb_hiwat); 1407509Sroot soqinsque(head, so, 0); 14112758Ssam if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, 14212758Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { 1437509Sroot (void) soqremque(so, 0); 1448818Sroot (void) m_free(m); 1457509Sroot goto bad; 1467509Sroot } 1477509Sroot return (so); 1487509Sroot bad: 1497509Sroot return ((struct socket *)0); 1507509Sroot } 1517509Sroot 1527509Sroot soqinsque(head, so, q) 1537509Sroot register struct socket *head, *so; 1547509Sroot int q; 1557509Sroot { 1567509Sroot 1577509Sroot so->so_head = head; 1587509Sroot if (q == 0) { 1597509Sroot head->so_q0len++; 1607509Sroot so->so_q0 = head->so_q0; 1617509Sroot head->so_q0 = so; 1627509Sroot } else { 1637509Sroot head->so_qlen++; 1647509Sroot so->so_q = head->so_q; 1657509Sroot head->so_q = so; 1667509Sroot } 1677509Sroot } 1687509Sroot 1697509Sroot soqremque(so, q) 1707509Sroot register struct socket *so; 1717509Sroot int q; 1727509Sroot { 1737509Sroot register struct socket *head, *prev, *next; 1747509Sroot 1757509Sroot head = so->so_head; 1767509Sroot prev = head; 1777509Sroot for (;;) { 1787509Sroot next = q ? prev->so_q : prev->so_q0; 1797509Sroot if (next == so) 1807509Sroot break; 1817509Sroot if (next == head) 1827509Sroot return (0); 1837509Sroot prev = next; 1847509Sroot } 1857509Sroot if (q == 0) { 1867509Sroot prev->so_q0 = next->so_q0; 1877509Sroot head->so_q0len--; 1887509Sroot } else { 1897509Sroot prev->so_q = next->so_q; 1907509Sroot head->so_qlen--; 1917509Sroot } 1927509Sroot next->so_q0 = next->so_q = 0; 1937509Sroot next->so_head = 0; 1947509Sroot return (1); 1957509Sroot } 1967509Sroot 1977509Sroot /* 1985169Swnj * Socantsendmore indicates that no more data will be sent on the 1995169Swnj * socket; it would normally be applied to a socket when the user 2005169Swnj * informs the system that no more data is to be sent, by the protocol 2015169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 2025169Swnj * will be received, and will normally be applied to the socket by a 2035169Swnj * protocol when it detects that the peer will send no more data. 2045169Swnj * Data queued for reading in the socket may yet be read. 2055169Swnj */ 2065169Swnj 2074917Swnj socantsendmore(so) 2084917Swnj struct socket *so; 2094917Swnj { 2104917Swnj 2114917Swnj so->so_state |= SS_CANTSENDMORE; 2124917Swnj sowwakeup(so); 2134917Swnj } 2144917Swnj 2154917Swnj socantrcvmore(so) 2164917Swnj struct socket *so; 2174917Swnj { 2184917Swnj 2194917Swnj so->so_state |= SS_CANTRCVMORE; 2204917Swnj sorwakeup(so); 2214917Swnj } 2224917Swnj 2234903Swnj /* 2245169Swnj * Socket select/wakeup routines. 2254903Swnj */ 2265169Swnj 2275169Swnj /* 2284903Swnj * Queue a process for a select on a socket buffer. 2294903Swnj */ 2304903Swnj sbselqueue(sb) 2314903Swnj struct sockbuf *sb; 2324903Swnj { 2334903Swnj register struct proc *p; 2344903Swnj 2354917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 2364903Swnj sb->sb_flags |= SB_COLL; 2374903Swnj else 2384903Swnj sb->sb_sel = u.u_procp; 2394903Swnj } 2404903Swnj 2414903Swnj /* 2424917Swnj * Wait for data to arrive at/drain from a socket buffer. 2434917Swnj */ 2444917Swnj sbwait(sb) 2454917Swnj struct sockbuf *sb; 2464917Swnj { 2474917Swnj 2484917Swnj sb->sb_flags |= SB_WAIT; 2494917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 2504917Swnj } 2514917Swnj 2524917Swnj /* 2534903Swnj * Wakeup processes waiting on a socket buffer. 2544903Swnj */ 2554903Swnj sbwakeup(sb) 25612758Ssam register struct sockbuf *sb; 2574903Swnj { 2584903Swnj 2594903Swnj if (sb->sb_sel) { 2604903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 2614903Swnj sb->sb_sel = 0; 2624903Swnj sb->sb_flags &= ~SB_COLL; 2634903Swnj } 2644903Swnj if (sb->sb_flags & SB_WAIT) { 2654903Swnj sb->sb_flags &= ~SB_WAIT; 2665013Swnj wakeup((caddr_t)&sb->sb_cc); 2674903Swnj } 2684903Swnj } 2694903Swnj 2704903Swnj /* 27115829Scooper * Wakeup socket readers and writers. 27215829Scooper * Do asynchronous notification via SIGIO 27315829Scooper * if the socket has the SS_ASYNC flag set. 27415829Scooper */ 27515829Scooper sowakeup(so, sb) 27615829Scooper register struct socket *so; 27715829Scooper struct sockbuf *sb; 27815829Scooper { 27915829Scooper register struct proc *p; 28015829Scooper 28115829Scooper sbwakeup(sb); 28215829Scooper if (so->so_state & SS_ASYNC) { 28323239Skarels if (so->so_pgrp < 0) 28423239Skarels gsignal(-so->so_pgrp, SIGIO); 28523239Skarels else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 28615829Scooper psignal(p, SIGIO); 28715829Scooper } 28815829Scooper } 28915829Scooper 29015829Scooper /* 2915169Swnj * Socket buffer (struct sockbuf) utility routines. 2925169Swnj * 2935169Swnj * Each socket contains two socket buffers: one for sending data and 2945169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 2955169Swnj * information about the number of mbufs and amount of data in the 2965169Swnj * queue, and other fields allowing select() statements and notification 2975169Swnj * on data availability to be implemented. 2985169Swnj * 29916994Skarels * Data stored in a socket buffer is maintained as a list of records. 30016994Skarels * Each record is a list of mbufs chained together with the m_next 30116994Skarels * field. Records are chained together with the m_act field. The upper 30216994Skarels * level routine soreceive() expects the following conventions to be 30316994Skarels * observed when placing information in the receive buffer: 30416994Skarels * 30516994Skarels * 1. If the protocol requires each message be preceded by the sender's 30616994Skarels * name, then a record containing that name must be present before 30716994Skarels * any associated data (mbuf's must be of type MT_SONAME). 30816994Skarels * 2. If the protocol supports the exchange of ``access rights'' (really 30916994Skarels * just additional data associated with the message), and there are 31016994Skarels * ``rights'' to be received, then a record containing this data 31116994Skarels * should be present (mbuf's must be of type MT_RIGHTS). 31216994Skarels * 3. If a name or rights record exists, then it must be followed by 31316994Skarels * a data record, perhaps of zero length. 31416994Skarels * 3155169Swnj * Before using a new socket structure it is first necessary to reserve 31633406Skarels * buffer space to the socket, by calling sbreserve(). This should commit 3175169Swnj * some of the available buffer space in the system buffer pool for the 31833406Skarels * socket (currently, it does nothing but enforce limits). The space 31933406Skarels * should be released by calling sbrelease() when the socket is destroyed. 3205169Swnj */ 3215169Swnj 3229027Sroot soreserve(so, sndcc, rcvcc) 32312758Ssam register struct socket *so; 32433406Skarels u_long sndcc, rcvcc; 3259027Sroot { 3269027Sroot 3279027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3289027Sroot goto bad; 3299027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3309027Sroot goto bad2; 3319027Sroot return (0); 3329027Sroot bad2: 3339027Sroot sbrelease(&so->so_snd); 3349027Sroot bad: 3359027Sroot return (ENOBUFS); 3369027Sroot } 3379027Sroot 3385169Swnj /* 3394903Swnj * Allot mbufs to a sockbuf. 34026830Skarels * Attempt to scale cc so that mbcnt doesn't become limiting 34126830Skarels * if buffering efficiency is near the normal case. 3424903Swnj */ 3434903Swnj sbreserve(sb, cc) 3444903Swnj struct sockbuf *sb; 34533406Skarels u_long cc; 3464903Swnj { 3474903Swnj 34833406Skarels if (cc > (u_long)SB_MAX * CLBYTES / (2 * MSIZE + CLBYTES)) 34917355Skarels return (0); 3504980Swnj sb->sb_hiwat = cc; 35117417Skarels sb->sb_mbmax = MIN(cc * 2, SB_MAX); 3524917Swnj return (1); 3534903Swnj } 3544903Swnj 3554903Swnj /* 3564903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3574903Swnj */ 3584903Swnj sbrelease(sb) 3594903Swnj struct sockbuf *sb; 3604903Swnj { 3614903Swnj 3624903Swnj sbflush(sb); 3634980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3644903Swnj } 3654903Swnj 3664903Swnj /* 36716994Skarels * Routines to add and remove 36816994Skarels * data from an mbuf queue. 36925630Skarels * 37025630Skarels * The routines sbappend() or sbappendrecord() are normally called to 37125630Skarels * append new mbufs to a socket buffer, after checking that adequate 37225630Skarels * space is available, comparing the function sbspace() with the amount 37325630Skarels * of data to be added. sbappendrecord() differs from sbappend() in 37425630Skarels * that data supplied is treated as the beginning of a new record. 37525630Skarels * To place a sender's address, optional access rights, and data in a 37625630Skarels * socket receive buffer, sbappendaddr() should be used. To place 37725630Skarels * access rights and data in a socket receive buffer, sbappendrights() 37825630Skarels * should be used. In either case, the new data begins a new record. 37925630Skarels * Note that unlike sbappend() and sbappendrecord(), these routines check 38025630Skarels * for the caller that there will be enough space to store the data. 38125630Skarels * Each fails if there is not enough space, or if it cannot find mbufs 38225630Skarels * to store additional information in. 38325630Skarels * 38425630Skarels * Reliable protocols may use the socket send buffer to hold data 38525630Skarels * awaiting acknowledgement. Data is normally copied from a socket 38625630Skarels * send buffer in a protocol with m_copy for output to a peer, 38725630Skarels * and then removing the data from the socket buffer with sbdrop() 38825630Skarels * or sbdroprecord() when the data is acknowledged by the peer. 3894903Swnj */ 3904903Swnj 3914903Swnj /* 39216994Skarels * Append mbuf chain m to the last record in the 39316994Skarels * socket buffer sb. The additional space associated 39416994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 39516994Skarels * discarded and mbufs are compacted where possible. 3964903Swnj */ 3974903Swnj sbappend(sb, m) 39816994Skarels struct sockbuf *sb; 39916994Skarels struct mbuf *m; 4004903Swnj { 4016092Sroot register struct mbuf *n; 4024903Swnj 40316994Skarels if (m == 0) 40416994Skarels return; 40516994Skarels if (n = sb->sb_mb) { 40616994Skarels while (n->m_act) 40716994Skarels n = n->m_act; 4086092Sroot while (n->m_next) 4096092Sroot n = n->m_next; 4104903Swnj } 41116994Skarels sbcompress(sb, m, n); 4124903Swnj } 4134903Swnj 4145169Swnj /* 41516994Skarels * As above, except the mbuf chain 41616994Skarels * begins a new record. 4175169Swnj */ 41816994Skarels sbappendrecord(sb, m0) 41916994Skarels register struct sockbuf *sb; 42016994Skarels register struct mbuf *m0; 4214928Swnj { 4224928Swnj register struct mbuf *m; 4234928Swnj 42416994Skarels if (m0 == 0) 42516994Skarels return; 42616994Skarels if (m = sb->sb_mb) 42716994Skarels while (m->m_act) 42816994Skarels m = m->m_act; 42916994Skarels /* 43016994Skarels * Put the first mbuf on the queue. 43116994Skarels * Note this permits zero length records. 43216994Skarels */ 43316994Skarels sballoc(sb, m0); 43416994Skarels if (m) 43516994Skarels m->m_act = m0; 43616994Skarels else 43716994Skarels sb->sb_mb = m0; 43816994Skarels m = m0->m_next; 43916994Skarels m0->m_next = 0; 44016994Skarels sbcompress(sb, m, m0); 44116994Skarels } 44216994Skarels 44316994Skarels /* 44416994Skarels * Append address and data, and optionally, rights 44516994Skarels * to the receive queue of a socket. Return 0 if 44616994Skarels * no space in sockbuf or insufficient mbufs. 44716994Skarels */ 44825630Skarels sbappendaddr(sb, asa, m0, rights0) 44916994Skarels register struct sockbuf *sb; 45016994Skarels struct sockaddr *asa; 45116994Skarels struct mbuf *rights0, *m0; 45216994Skarels { 45316994Skarels register struct mbuf *m, *n; 45416994Skarels int space = sizeof (*asa); 45516994Skarels 45625630Skarels for (m = m0; m; m = m->m_next) 45716994Skarels space += m->m_len; 45816994Skarels if (rights0) 45916994Skarels space += rights0->m_len; 46016994Skarels if (space > sbspace(sb)) 4614928Swnj return (0); 46225630Skarels MGET(m, M_DONTWAIT, MT_SONAME); 46316994Skarels if (m == 0) 4644928Swnj return (0); 46512758Ssam *mtod(m, struct sockaddr *) = *asa; 46616994Skarels m->m_len = sizeof (*asa); 46725921Skarels if (rights0 && rights0->m_len) { 46825630Skarels m->m_next = m_copy(rights0, 0, rights0->m_len); 46925630Skarels if (m->m_next == 0) { 47016994Skarels m_freem(m); 47116994Skarels return (0); 47216994Skarels } 47325630Skarels sballoc(sb, m->m_next); 47421765Skarels } 47525938Skarels sballoc(sb, m); 47616994Skarels if (n = sb->sb_mb) { 47716994Skarels while (n->m_act) 47816994Skarels n = n->m_act; 47916994Skarels n->m_act = m; 48016994Skarels } else 48116994Skarels sb->sb_mb = m; 48225630Skarels if (m->m_next) 48325630Skarels m = m->m_next; 48425630Skarels if (m0) 48525630Skarels sbcompress(sb, m0, m); 48616994Skarels return (1); 48716994Skarels } 48816994Skarels 48925630Skarels sbappendrights(sb, m0, rights) 49016994Skarels struct sockbuf *sb; 49125630Skarels struct mbuf *rights, *m0; 49216994Skarels { 49316994Skarels register struct mbuf *m, *n; 49416994Skarels int space = 0; 49516994Skarels 49625630Skarels if (rights == 0) 49716994Skarels panic("sbappendrights"); 49825630Skarels for (m = m0; m; m = m->m_next) 49916994Skarels space += m->m_len; 50016994Skarels space += rights->m_len; 50116994Skarels if (space > sbspace(sb)) 50212758Ssam return (0); 50316994Skarels m = m_copy(rights, 0, rights->m_len); 50416994Skarels if (m == 0) 50516994Skarels return (0); 50616994Skarels sballoc(sb, m); 50716994Skarels if (n = sb->sb_mb) { 50816994Skarels while (n->m_act) 50916994Skarels n = n->m_act; 51016994Skarels n->m_act = m; 51116994Skarels } else 51225630Skarels sb->sb_mb = m; 51325630Skarels if (m0) 51425630Skarels sbcompress(sb, m0, m); 5154928Swnj return (1); 5164928Swnj } 5174928Swnj 5184903Swnj /* 51916994Skarels * Compress mbuf chain m into the socket 52016994Skarels * buffer sb following mbuf n. If n 52116994Skarels * is null, the buffer is presumed empty. 5224903Swnj */ 52316994Skarels sbcompress(sb, m, n) 52416994Skarels register struct sockbuf *sb; 52516994Skarels register struct mbuf *m, *n; 52616994Skarels { 52716994Skarels 52816994Skarels while (m) { 52916994Skarels if (m->m_len == 0) { 53016994Skarels m = m_free(m); 53116994Skarels continue; 53216994Skarels } 53316994Skarels if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 53425630Skarels (n->m_off + n->m_len + m->m_len) <= MMAXOFF && 53525630Skarels n->m_type == m->m_type) { 53616994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 53716994Skarels (unsigned)m->m_len); 53816994Skarels n->m_len += m->m_len; 53916994Skarels sb->sb_cc += m->m_len; 54016994Skarels m = m_free(m); 54116994Skarels continue; 54216994Skarels } 54316994Skarels sballoc(sb, m); 54416994Skarels if (n) 54516994Skarels n->m_next = m; 54616994Skarels else 54716994Skarels sb->sb_mb = m; 54816994Skarels n = m; 54916994Skarels m = m->m_next; 55016994Skarels n->m_next = 0; 55116994Skarels } 55216994Skarels } 55316994Skarels 55416994Skarels /* 55516994Skarels * Free all mbufs in a sockbuf. 55616994Skarels * Check that all resources are reclaimed. 55716994Skarels */ 5584903Swnj sbflush(sb) 55912758Ssam register struct sockbuf *sb; 5604903Swnj { 5614903Swnj 5624903Swnj if (sb->sb_flags & SB_LOCK) 5634903Swnj panic("sbflush"); 56426105Skarels while (sb->sb_mbcnt) 56526363Skarels sbdrop(sb, (int)sb->sb_cc); 5664903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 5674903Swnj panic("sbflush 2"); 5684903Swnj } 5694903Swnj 5704903Swnj /* 57116994Skarels * Drop data from (the front of) a sockbuf. 5724903Swnj */ 5734903Swnj sbdrop(sb, len) 5744903Swnj register struct sockbuf *sb; 5754903Swnj register int len; 5764903Swnj { 57716994Skarels register struct mbuf *m, *mn; 57816994Skarels struct mbuf *next; 5794903Swnj 58016994Skarels next = (m = sb->sb_mb) ? m->m_act : 0; 5814903Swnj while (len > 0) { 58216994Skarels if (m == 0) { 58316994Skarels if (next == 0) 58416994Skarels panic("sbdrop"); 58516994Skarels m = next; 58616994Skarels next = m->m_act; 58716994Skarels continue; 58816994Skarels } 5895064Swnj if (m->m_len > len) { 5904903Swnj m->m_len -= len; 5914903Swnj m->m_off += len; 5924903Swnj sb->sb_cc -= len; 5934903Swnj break; 5944903Swnj } 5955064Swnj len -= m->m_len; 5965064Swnj sbfree(sb, m); 5975064Swnj MFREE(m, mn); 5985064Swnj m = mn; 5994903Swnj } 60017331Skarels while (m && m->m_len == 0) { 60117417Skarels sbfree(sb, m); 60217331Skarels MFREE(m, mn); 60317331Skarels m = mn; 60417331Skarels } 60516994Skarels if (m) { 60616994Skarels sb->sb_mb = m; 60716994Skarels m->m_act = next; 60816994Skarels } else 60916994Skarels sb->sb_mb = next; 6104903Swnj } 61116994Skarels 61216994Skarels /* 61316994Skarels * Drop a record off the front of a sockbuf 61416994Skarels * and move the next record to the front. 61516994Skarels */ 61616994Skarels sbdroprecord(sb) 61716994Skarels register struct sockbuf *sb; 61816994Skarels { 61916994Skarels register struct mbuf *m, *mn; 62016994Skarels 62116994Skarels m = sb->sb_mb; 62216994Skarels if (m) { 62316994Skarels sb->sb_mb = m->m_act; 62416994Skarels do { 62516994Skarels sbfree(sb, m); 62616994Skarels MFREE(m, mn); 62716994Skarels } while (m = mn); 62816994Skarels } 62916994Skarels } 630