123431Smckusick /* 229127Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 3*33187Sbostic * All rights reserved. 423431Smckusick * 5*33187Sbostic * Redistribution and use in source and binary forms are permitted 6*33187Sbostic * provided that this notice is preserved and that due credit is given 7*33187Sbostic * to the University of California at Berkeley. The name of the University 8*33187Sbostic * may not be used to endorse or promote products derived from this 9*33187Sbostic * software without specific prior written permission. This software 10*33187Sbostic * is provided ``as is'' without express or implied warranty. 11*33187Sbostic * 12*33187Sbostic * @(#)uipc_socket2.c 7.2 (Berkeley) 12/30/87 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; 1397509Sroot soqinsque(head, so, 0); 14012758Ssam if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, 14112758Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { 1427509Sroot (void) soqremque(so, 0); 1438818Sroot (void) m_free(m); 1447509Sroot goto bad; 1457509Sroot } 1467509Sroot return (so); 1477509Sroot bad: 1487509Sroot return ((struct socket *)0); 1497509Sroot } 1507509Sroot 1517509Sroot soqinsque(head, so, q) 1527509Sroot register struct socket *head, *so; 1537509Sroot int q; 1547509Sroot { 1557509Sroot 1567509Sroot so->so_head = head; 1577509Sroot if (q == 0) { 1587509Sroot head->so_q0len++; 1597509Sroot so->so_q0 = head->so_q0; 1607509Sroot head->so_q0 = so; 1617509Sroot } else { 1627509Sroot head->so_qlen++; 1637509Sroot so->so_q = head->so_q; 1647509Sroot head->so_q = so; 1657509Sroot } 1667509Sroot } 1677509Sroot 1687509Sroot soqremque(so, q) 1697509Sroot register struct socket *so; 1707509Sroot int q; 1717509Sroot { 1727509Sroot register struct socket *head, *prev, *next; 1737509Sroot 1747509Sroot head = so->so_head; 1757509Sroot prev = head; 1767509Sroot for (;;) { 1777509Sroot next = q ? prev->so_q : prev->so_q0; 1787509Sroot if (next == so) 1797509Sroot break; 1807509Sroot if (next == head) 1817509Sroot return (0); 1827509Sroot prev = next; 1837509Sroot } 1847509Sroot if (q == 0) { 1857509Sroot prev->so_q0 = next->so_q0; 1867509Sroot head->so_q0len--; 1877509Sroot } else { 1887509Sroot prev->so_q = next->so_q; 1897509Sroot head->so_qlen--; 1907509Sroot } 1917509Sroot next->so_q0 = next->so_q = 0; 1927509Sroot next->so_head = 0; 1937509Sroot return (1); 1947509Sroot } 1957509Sroot 1967509Sroot /* 1975169Swnj * Socantsendmore indicates that no more data will be sent on the 1985169Swnj * socket; it would normally be applied to a socket when the user 1995169Swnj * informs the system that no more data is to be sent, by the protocol 2005169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 2015169Swnj * will be received, and will normally be applied to the socket by a 2025169Swnj * protocol when it detects that the peer will send no more data. 2035169Swnj * Data queued for reading in the socket may yet be read. 2045169Swnj */ 2055169Swnj 2064917Swnj socantsendmore(so) 2074917Swnj struct socket *so; 2084917Swnj { 2094917Swnj 2104917Swnj so->so_state |= SS_CANTSENDMORE; 2114917Swnj sowwakeup(so); 2124917Swnj } 2134917Swnj 2144917Swnj socantrcvmore(so) 2154917Swnj struct socket *so; 2164917Swnj { 2174917Swnj 2184917Swnj so->so_state |= SS_CANTRCVMORE; 2194917Swnj sorwakeup(so); 2204917Swnj } 2214917Swnj 2224903Swnj /* 2235169Swnj * Socket select/wakeup routines. 2244903Swnj */ 2255169Swnj 2265169Swnj /* 2274903Swnj * Queue a process for a select on a socket buffer. 2284903Swnj */ 2294903Swnj sbselqueue(sb) 2304903Swnj struct sockbuf *sb; 2314903Swnj { 2324903Swnj register struct proc *p; 2334903Swnj 2344917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 2354903Swnj sb->sb_flags |= SB_COLL; 2364903Swnj else 2374903Swnj sb->sb_sel = u.u_procp; 2384903Swnj } 2394903Swnj 2404903Swnj /* 2414917Swnj * Wait for data to arrive at/drain from a socket buffer. 2424917Swnj */ 2434917Swnj sbwait(sb) 2444917Swnj struct sockbuf *sb; 2454917Swnj { 2464917Swnj 2474917Swnj sb->sb_flags |= SB_WAIT; 2484917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 2494917Swnj } 2504917Swnj 2514917Swnj /* 2524903Swnj * Wakeup processes waiting on a socket buffer. 2534903Swnj */ 2544903Swnj sbwakeup(sb) 25512758Ssam register struct sockbuf *sb; 2564903Swnj { 2574903Swnj 2584903Swnj if (sb->sb_sel) { 2594903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 2604903Swnj sb->sb_sel = 0; 2614903Swnj sb->sb_flags &= ~SB_COLL; 2624903Swnj } 2634903Swnj if (sb->sb_flags & SB_WAIT) { 2644903Swnj sb->sb_flags &= ~SB_WAIT; 2655013Swnj wakeup((caddr_t)&sb->sb_cc); 2664903Swnj } 2674903Swnj } 2684903Swnj 2694903Swnj /* 27015829Scooper * Wakeup socket readers and writers. 27115829Scooper * Do asynchronous notification via SIGIO 27215829Scooper * if the socket has the SS_ASYNC flag set. 27315829Scooper */ 27415829Scooper sowakeup(so, sb) 27515829Scooper register struct socket *so; 27615829Scooper struct sockbuf *sb; 27715829Scooper { 27815829Scooper register struct proc *p; 27915829Scooper 28015829Scooper sbwakeup(sb); 28115829Scooper if (so->so_state & SS_ASYNC) { 28223239Skarels if (so->so_pgrp < 0) 28323239Skarels gsignal(-so->so_pgrp, SIGIO); 28423239Skarels else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 28515829Scooper psignal(p, SIGIO); 28615829Scooper } 28715829Scooper } 28815829Scooper 28915829Scooper /* 2905169Swnj * Socket buffer (struct sockbuf) utility routines. 2915169Swnj * 2925169Swnj * Each socket contains two socket buffers: one for sending data and 2935169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 2945169Swnj * information about the number of mbufs and amount of data in the 2955169Swnj * queue, and other fields allowing select() statements and notification 2965169Swnj * on data availability to be implemented. 2975169Swnj * 29816994Skarels * Data stored in a socket buffer is maintained as a list of records. 29916994Skarels * Each record is a list of mbufs chained together with the m_next 30016994Skarels * field. Records are chained together with the m_act field. The upper 30116994Skarels * level routine soreceive() expects the following conventions to be 30216994Skarels * observed when placing information in the receive buffer: 30316994Skarels * 30416994Skarels * 1. If the protocol requires each message be preceded by the sender's 30516994Skarels * name, then a record containing that name must be present before 30616994Skarels * any associated data (mbuf's must be of type MT_SONAME). 30716994Skarels * 2. If the protocol supports the exchange of ``access rights'' (really 30816994Skarels * just additional data associated with the message), and there are 30916994Skarels * ``rights'' to be received, then a record containing this data 31016994Skarels * should be present (mbuf's must be of type MT_RIGHTS). 31116994Skarels * 3. If a name or rights record exists, then it must be followed by 31216994Skarels * a data record, perhaps of zero length. 31316994Skarels * 3145169Swnj * Before using a new socket structure it is first necessary to reserve 31516994Skarels * buffer space to the socket, by calling sbreserve(). This commits 3165169Swnj * some of the available buffer space in the system buffer pool for the 31716994Skarels * socket. The space should be released by calling sbrelease() when the 3185169Swnj * socket is destroyed. 3195169Swnj */ 3205169Swnj 3219027Sroot soreserve(so, sndcc, rcvcc) 32212758Ssam register struct socket *so; 3239027Sroot int sndcc, rcvcc; 3249027Sroot { 3259027Sroot 3269027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3279027Sroot goto bad; 3289027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3299027Sroot goto bad2; 3309027Sroot return (0); 3319027Sroot bad2: 3329027Sroot sbrelease(&so->so_snd); 3339027Sroot bad: 3349027Sroot return (ENOBUFS); 3359027Sroot } 3369027Sroot 3375169Swnj /* 3384903Swnj * Allot mbufs to a sockbuf. 33926830Skarels * Attempt to scale cc so that mbcnt doesn't become limiting 34026830Skarels * if buffering efficiency is near the normal case. 3414903Swnj */ 3424903Swnj sbreserve(sb, cc) 3434903Swnj struct sockbuf *sb; 3444903Swnj { 3454903Swnj 34626830Skarels if ((unsigned) cc > (unsigned)SB_MAX * CLBYTES / (2 * MSIZE + CLBYTES)) 34717355Skarels return (0); 3484980Swnj sb->sb_hiwat = cc; 34917417Skarels sb->sb_mbmax = MIN(cc * 2, SB_MAX); 3504917Swnj return (1); 3514903Swnj } 3524903Swnj 3534903Swnj /* 3544903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3554903Swnj */ 3564903Swnj sbrelease(sb) 3574903Swnj struct sockbuf *sb; 3584903Swnj { 3594903Swnj 3604903Swnj sbflush(sb); 3614980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3624903Swnj } 3634903Swnj 3644903Swnj /* 36516994Skarels * Routines to add and remove 36616994Skarels * data from an mbuf queue. 36725630Skarels * 36825630Skarels * The routines sbappend() or sbappendrecord() are normally called to 36925630Skarels * append new mbufs to a socket buffer, after checking that adequate 37025630Skarels * space is available, comparing the function sbspace() with the amount 37125630Skarels * of data to be added. sbappendrecord() differs from sbappend() in 37225630Skarels * that data supplied is treated as the beginning of a new record. 37325630Skarels * To place a sender's address, optional access rights, and data in a 37425630Skarels * socket receive buffer, sbappendaddr() should be used. To place 37525630Skarels * access rights and data in a socket receive buffer, sbappendrights() 37625630Skarels * should be used. In either case, the new data begins a new record. 37725630Skarels * Note that unlike sbappend() and sbappendrecord(), these routines check 37825630Skarels * for the caller that there will be enough space to store the data. 37925630Skarels * Each fails if there is not enough space, or if it cannot find mbufs 38025630Skarels * to store additional information in. 38125630Skarels * 38225630Skarels * Reliable protocols may use the socket send buffer to hold data 38325630Skarels * awaiting acknowledgement. Data is normally copied from a socket 38425630Skarels * send buffer in a protocol with m_copy for output to a peer, 38525630Skarels * and then removing the data from the socket buffer with sbdrop() 38625630Skarels * or sbdroprecord() when the data is acknowledged by the peer. 3874903Swnj */ 3884903Swnj 3894903Swnj /* 39016994Skarels * Append mbuf chain m to the last record in the 39116994Skarels * socket buffer sb. The additional space associated 39216994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 39316994Skarels * discarded and mbufs are compacted where possible. 3944903Swnj */ 3954903Swnj sbappend(sb, m) 39616994Skarels struct sockbuf *sb; 39716994Skarels struct mbuf *m; 3984903Swnj { 3996092Sroot register struct mbuf *n; 4004903Swnj 40116994Skarels if (m == 0) 40216994Skarels return; 40316994Skarels if (n = sb->sb_mb) { 40416994Skarels while (n->m_act) 40516994Skarels n = n->m_act; 4066092Sroot while (n->m_next) 4076092Sroot n = n->m_next; 4084903Swnj } 40916994Skarels sbcompress(sb, m, n); 4104903Swnj } 4114903Swnj 4125169Swnj /* 41316994Skarels * As above, except the mbuf chain 41416994Skarels * begins a new record. 4155169Swnj */ 41616994Skarels sbappendrecord(sb, m0) 41716994Skarels register struct sockbuf *sb; 41816994Skarels register struct mbuf *m0; 4194928Swnj { 4204928Swnj register struct mbuf *m; 4214928Swnj 42216994Skarels if (m0 == 0) 42316994Skarels return; 42416994Skarels if (m = sb->sb_mb) 42516994Skarels while (m->m_act) 42616994Skarels m = m->m_act; 42716994Skarels /* 42816994Skarels * Put the first mbuf on the queue. 42916994Skarels * Note this permits zero length records. 43016994Skarels */ 43116994Skarels sballoc(sb, m0); 43216994Skarels if (m) 43316994Skarels m->m_act = m0; 43416994Skarels else 43516994Skarels sb->sb_mb = m0; 43616994Skarels m = m0->m_next; 43716994Skarels m0->m_next = 0; 43816994Skarels sbcompress(sb, m, m0); 43916994Skarels } 44016994Skarels 44116994Skarels /* 44216994Skarels * Append address and data, and optionally, rights 44316994Skarels * to the receive queue of a socket. Return 0 if 44416994Skarels * no space in sockbuf or insufficient mbufs. 44516994Skarels */ 44625630Skarels sbappendaddr(sb, asa, m0, rights0) 44716994Skarels register struct sockbuf *sb; 44816994Skarels struct sockaddr *asa; 44916994Skarels struct mbuf *rights0, *m0; 45016994Skarels { 45116994Skarels register struct mbuf *m, *n; 45216994Skarels int space = sizeof (*asa); 45316994Skarels 45425630Skarels for (m = m0; m; m = m->m_next) 45516994Skarels space += m->m_len; 45616994Skarels if (rights0) 45716994Skarels space += rights0->m_len; 45816994Skarels if (space > sbspace(sb)) 4594928Swnj return (0); 46025630Skarels MGET(m, M_DONTWAIT, MT_SONAME); 46116994Skarels if (m == 0) 4624928Swnj return (0); 46312758Ssam *mtod(m, struct sockaddr *) = *asa; 46416994Skarels m->m_len = sizeof (*asa); 46525921Skarels if (rights0 && rights0->m_len) { 46625630Skarels m->m_next = m_copy(rights0, 0, rights0->m_len); 46725630Skarels if (m->m_next == 0) { 46816994Skarels m_freem(m); 46916994Skarels return (0); 47016994Skarels } 47125630Skarels sballoc(sb, m->m_next); 47221765Skarels } 47325938Skarels sballoc(sb, m); 47416994Skarels if (n = sb->sb_mb) { 47516994Skarels while (n->m_act) 47616994Skarels n = n->m_act; 47716994Skarels n->m_act = m; 47816994Skarels } else 47916994Skarels sb->sb_mb = m; 48025630Skarels if (m->m_next) 48125630Skarels m = m->m_next; 48225630Skarels if (m0) 48325630Skarels sbcompress(sb, m0, m); 48416994Skarels return (1); 48516994Skarels } 48616994Skarels 48725630Skarels sbappendrights(sb, m0, rights) 48816994Skarels struct sockbuf *sb; 48925630Skarels struct mbuf *rights, *m0; 49016994Skarels { 49116994Skarels register struct mbuf *m, *n; 49216994Skarels int space = 0; 49316994Skarels 49425630Skarels if (rights == 0) 49516994Skarels panic("sbappendrights"); 49625630Skarels for (m = m0; m; m = m->m_next) 49716994Skarels space += m->m_len; 49816994Skarels space += rights->m_len; 49916994Skarels if (space > sbspace(sb)) 50012758Ssam return (0); 50116994Skarels m = m_copy(rights, 0, rights->m_len); 50216994Skarels if (m == 0) 50316994Skarels return (0); 50416994Skarels sballoc(sb, m); 50516994Skarels if (n = sb->sb_mb) { 50616994Skarels while (n->m_act) 50716994Skarels n = n->m_act; 50816994Skarels n->m_act = m; 50916994Skarels } else 51025630Skarels sb->sb_mb = m; 51125630Skarels if (m0) 51225630Skarels sbcompress(sb, m0, m); 5134928Swnj return (1); 5144928Swnj } 5154928Swnj 5164903Swnj /* 51716994Skarels * Compress mbuf chain m into the socket 51816994Skarels * buffer sb following mbuf n. If n 51916994Skarels * is null, the buffer is presumed empty. 5204903Swnj */ 52116994Skarels sbcompress(sb, m, n) 52216994Skarels register struct sockbuf *sb; 52316994Skarels register struct mbuf *m, *n; 52416994Skarels { 52516994Skarels 52616994Skarels while (m) { 52716994Skarels if (m->m_len == 0) { 52816994Skarels m = m_free(m); 52916994Skarels continue; 53016994Skarels } 53116994Skarels if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 53225630Skarels (n->m_off + n->m_len + m->m_len) <= MMAXOFF && 53325630Skarels n->m_type == m->m_type) { 53416994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 53516994Skarels (unsigned)m->m_len); 53616994Skarels n->m_len += m->m_len; 53716994Skarels sb->sb_cc += m->m_len; 53816994Skarels m = m_free(m); 53916994Skarels continue; 54016994Skarels } 54116994Skarels sballoc(sb, m); 54216994Skarels if (n) 54316994Skarels n->m_next = m; 54416994Skarels else 54516994Skarels sb->sb_mb = m; 54616994Skarels n = m; 54716994Skarels m = m->m_next; 54816994Skarels n->m_next = 0; 54916994Skarels } 55016994Skarels } 55116994Skarels 55216994Skarels /* 55316994Skarels * Free all mbufs in a sockbuf. 55416994Skarels * Check that all resources are reclaimed. 55516994Skarels */ 5564903Swnj sbflush(sb) 55712758Ssam register struct sockbuf *sb; 5584903Swnj { 5594903Swnj 5604903Swnj if (sb->sb_flags & SB_LOCK) 5614903Swnj panic("sbflush"); 56226105Skarels while (sb->sb_mbcnt) 56326363Skarels sbdrop(sb, (int)sb->sb_cc); 5644903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 5654903Swnj panic("sbflush 2"); 5664903Swnj } 5674903Swnj 5684903Swnj /* 56916994Skarels * Drop data from (the front of) a sockbuf. 5704903Swnj */ 5714903Swnj sbdrop(sb, len) 5724903Swnj register struct sockbuf *sb; 5734903Swnj register int len; 5744903Swnj { 57516994Skarels register struct mbuf *m, *mn; 57616994Skarels struct mbuf *next; 5774903Swnj 57816994Skarels next = (m = sb->sb_mb) ? m->m_act : 0; 5794903Swnj while (len > 0) { 58016994Skarels if (m == 0) { 58116994Skarels if (next == 0) 58216994Skarels panic("sbdrop"); 58316994Skarels m = next; 58416994Skarels next = m->m_act; 58516994Skarels continue; 58616994Skarels } 5875064Swnj if (m->m_len > len) { 5884903Swnj m->m_len -= len; 5894903Swnj m->m_off += len; 5904903Swnj sb->sb_cc -= len; 5914903Swnj break; 5924903Swnj } 5935064Swnj len -= m->m_len; 5945064Swnj sbfree(sb, m); 5955064Swnj MFREE(m, mn); 5965064Swnj m = mn; 5974903Swnj } 59817331Skarels while (m && m->m_len == 0) { 59917417Skarels sbfree(sb, m); 60017331Skarels MFREE(m, mn); 60117331Skarels m = mn; 60217331Skarels } 60316994Skarels if (m) { 60416994Skarels sb->sb_mb = m; 60516994Skarels m->m_act = next; 60616994Skarels } else 60716994Skarels sb->sb_mb = next; 6084903Swnj } 60916994Skarels 61016994Skarels /* 61116994Skarels * Drop a record off the front of a sockbuf 61216994Skarels * and move the next record to the front. 61316994Skarels */ 61416994Skarels sbdroprecord(sb) 61516994Skarels register struct sockbuf *sb; 61616994Skarels { 61716994Skarels register struct mbuf *m, *mn; 61816994Skarels 61916994Skarels m = sb->sb_mb; 62016994Skarels if (m) { 62116994Skarels sb->sb_mb = m->m_act; 62216994Skarels do { 62316994Skarels sbfree(sb, m); 62416994Skarels MFREE(m, mn); 62516994Skarels } while (m = mn); 62616994Skarels } 62716994Skarels } 628