1*23431Smckusick /* 2*23431Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23431Smckusick * All rights reserved. The Berkeley software License Agreement 4*23431Smckusick * specifies the terms and conditions for redistribution. 5*23431Smckusick * 6*23431Smckusick * @(#)uipc_socket2.c 6.10 (Berkeley) 06/08/85 7*23431Smckusick */ 84903Swnj 917103Sbloom #include "param.h" 1017103Sbloom #include "systm.h" 1117103Sbloom #include "dir.h" 1217103Sbloom #include "user.h" 1317103Sbloom #include "proc.h" 1417103Sbloom #include "file.h" 1517103Sbloom #include "inode.h" 1617103Sbloom #include "buf.h" 1717103Sbloom #include "mbuf.h" 1817103Sbloom #include "protosw.h" 1917103Sbloom #include "socket.h" 2017103Sbloom #include "socketvar.h" 214903Swnj 224903Swnj /* 234903Swnj * Primitive routines for operating on sockets and socket buffers 244903Swnj */ 254903Swnj 264903Swnj /* 274903Swnj * Procedures to manipulate state flags of socket 287509Sroot * and do appropriate wakeups. Normal sequence from the 297509Sroot * active (originating) side is that soisconnecting() is 307509Sroot * called during processing of connect() call, 315169Swnj * resulting in an eventual call to soisconnected() if/when the 325169Swnj * connection is established. When the connection is torn down 335169Swnj * soisdisconnecting() is called during processing of disconnect() call, 345169Swnj * and soisdisconnected() is called when the connection to the peer 355169Swnj * is totally severed. The semantics of these routines are such that 365169Swnj * connectionless protocols can call soisconnected() and soisdisconnected() 375169Swnj * only, bypassing the in-progress calls when setting up a ``connection'' 385169Swnj * takes no time. 395169Swnj * 4012758Ssam * From the passive side, a socket is created with 4112758Ssam * two queues of sockets: so_q0 for connections in progress 427509Sroot * and so_q for connections already made and awaiting user acceptance. 437509Sroot * As a protocol is preparing incoming connections, it creates a socket 447509Sroot * structure queued on so_q0 by calling sonewconn(). When the connection 457509Sroot * is established, soisconnected() is called, and transfers the 467509Sroot * socket structure to so_q, making it available to accept(). 477509Sroot * 4812758Ssam * If a socket is closed with sockets on either 497509Sroot * so_q0 or so_q, these sockets are dropped. 507509Sroot * 5112758Ssam * If higher level protocols are implemented in 525169Swnj * the kernel, the wakeups done here will sometimes 5312758Ssam * cause software-interrupt process scheduling. 544903Swnj */ 555169Swnj 564903Swnj soisconnecting(so) 5712758Ssam register struct socket *so; 584903Swnj { 594903Swnj 604903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 614903Swnj so->so_state |= SS_ISCONNECTING; 624903Swnj wakeup((caddr_t)&so->so_timeo); 634903Swnj } 644903Swnj 654903Swnj soisconnected(so) 6612758Ssam register struct socket *so; 674903Swnj { 687509Sroot register struct socket *head = so->so_head; 694903Swnj 707509Sroot if (head) { 717509Sroot if (soqremque(so, 0) == 0) 727509Sroot panic("soisconnected"); 737509Sroot soqinsque(head, so, 1); 7412758Ssam sorwakeup(head); 757509Sroot wakeup((caddr_t)&head->so_timeo); 767509Sroot } 774903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 784903Swnj so->so_state |= SS_ISCONNECTED; 794903Swnj wakeup((caddr_t)&so->so_timeo); 805578Swnj sorwakeup(so); 815578Swnj sowwakeup(so); 824903Swnj } 834903Swnj 844903Swnj soisdisconnecting(so) 8512758Ssam register struct socket *so; 864903Swnj { 874903Swnj 885248Sroot so->so_state &= ~SS_ISCONNECTING; 894903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 904903Swnj wakeup((caddr_t)&so->so_timeo); 915170Swnj sowwakeup(so); 925169Swnj sorwakeup(so); 934903Swnj } 944903Swnj 954903Swnj soisdisconnected(so) 9612758Ssam register struct socket *so; 974903Swnj { 984903Swnj 994903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 1004903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 1014903Swnj wakeup((caddr_t)&so->so_timeo); 1024903Swnj sowwakeup(so); 1034903Swnj sorwakeup(so); 1044903Swnj } 1054903Swnj 1065169Swnj /* 1077509Sroot * When an attempt at a new connection is noted on a socket 1087509Sroot * which accepts connections, sonewconn is called. If the 1097509Sroot * connection is possible (subject to space constraints, etc.) 1107509Sroot * then we allocate a new structure, propoerly linked into the 1117509Sroot * data structure of the original socket, and return this. 1127509Sroot */ 1137509Sroot struct socket * 1147509Sroot sonewconn(head) 1157509Sroot register struct socket *head; 1167509Sroot { 1177509Sroot register struct socket *so; 11812758Ssam register struct mbuf *m; 1197509Sroot 1207509Sroot if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) 1217509Sroot goto bad; 1229636Ssam m = m_getclr(M_DONTWAIT, MT_SOCKET); 12310138Ssam if (m == NULL) 1247509Sroot goto bad; 1257509Sroot so = mtod(m, struct socket *); 1267509Sroot so->so_type = head->so_type; 1277509Sroot so->so_options = head->so_options &~ SO_ACCEPTCONN; 1287509Sroot so->so_linger = head->so_linger; 12910204Ssam so->so_state = head->so_state | SS_NOFDREF; 1307509Sroot so->so_proto = head->so_proto; 1317509Sroot so->so_timeo = head->so_timeo; 1327509Sroot so->so_pgrp = head->so_pgrp; 1337509Sroot soqinsque(head, so, 0); 13412758Ssam if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, 13512758Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { 1367509Sroot (void) soqremque(so, 0); 1378818Sroot (void) m_free(m); 1387509Sroot goto bad; 1397509Sroot } 1407509Sroot return (so); 1417509Sroot bad: 1427509Sroot return ((struct socket *)0); 1437509Sroot } 1447509Sroot 1457509Sroot soqinsque(head, so, q) 1467509Sroot register struct socket *head, *so; 1477509Sroot int q; 1487509Sroot { 1497509Sroot 1507509Sroot so->so_head = head; 1517509Sroot if (q == 0) { 1527509Sroot head->so_q0len++; 1537509Sroot so->so_q0 = head->so_q0; 1547509Sroot head->so_q0 = so; 1557509Sroot } else { 1567509Sroot head->so_qlen++; 1577509Sroot so->so_q = head->so_q; 1587509Sroot head->so_q = so; 1597509Sroot } 1607509Sroot } 1617509Sroot 1627509Sroot soqremque(so, q) 1637509Sroot register struct socket *so; 1647509Sroot int q; 1657509Sroot { 1667509Sroot register struct socket *head, *prev, *next; 1677509Sroot 1687509Sroot head = so->so_head; 1697509Sroot prev = head; 1707509Sroot for (;;) { 1717509Sroot next = q ? prev->so_q : prev->so_q0; 1727509Sroot if (next == so) 1737509Sroot break; 1747509Sroot if (next == head) 1757509Sroot return (0); 1767509Sroot prev = next; 1777509Sroot } 1787509Sroot if (q == 0) { 1797509Sroot prev->so_q0 = next->so_q0; 1807509Sroot head->so_q0len--; 1817509Sroot } else { 1827509Sroot prev->so_q = next->so_q; 1837509Sroot head->so_qlen--; 1847509Sroot } 1857509Sroot next->so_q0 = next->so_q = 0; 1867509Sroot next->so_head = 0; 1877509Sroot return (1); 1887509Sroot } 1897509Sroot 1907509Sroot /* 1915169Swnj * Socantsendmore indicates that no more data will be sent on the 1925169Swnj * socket; it would normally be applied to a socket when the user 1935169Swnj * informs the system that no more data is to be sent, by the protocol 1945169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 1955169Swnj * will be received, and will normally be applied to the socket by a 1965169Swnj * protocol when it detects that the peer will send no more data. 1975169Swnj * Data queued for reading in the socket may yet be read. 1985169Swnj */ 1995169Swnj 2004917Swnj socantsendmore(so) 2014917Swnj struct socket *so; 2024917Swnj { 2034917Swnj 2044917Swnj so->so_state |= SS_CANTSENDMORE; 2054917Swnj sowwakeup(so); 2064917Swnj } 2074917Swnj 2084917Swnj socantrcvmore(so) 2094917Swnj struct socket *so; 2104917Swnj { 2114917Swnj 2124917Swnj so->so_state |= SS_CANTRCVMORE; 2134917Swnj sorwakeup(so); 2144917Swnj } 2154917Swnj 2164903Swnj /* 2175169Swnj * Socket select/wakeup routines. 2184903Swnj */ 2195169Swnj 2205169Swnj /* 2214903Swnj * Queue a process for a select on a socket buffer. 2224903Swnj */ 2234903Swnj sbselqueue(sb) 2244903Swnj struct sockbuf *sb; 2254903Swnj { 2264903Swnj register struct proc *p; 2274903Swnj 2284917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 2294903Swnj sb->sb_flags |= SB_COLL; 2304903Swnj else 2314903Swnj sb->sb_sel = u.u_procp; 2324903Swnj } 2334903Swnj 2344903Swnj /* 2354917Swnj * Wait for data to arrive at/drain from a socket buffer. 2364917Swnj */ 2374917Swnj sbwait(sb) 2384917Swnj struct sockbuf *sb; 2394917Swnj { 2404917Swnj 2414917Swnj sb->sb_flags |= SB_WAIT; 2424917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 2434917Swnj } 2444917Swnj 2454917Swnj /* 2464903Swnj * Wakeup processes waiting on a socket buffer. 2474903Swnj */ 2484903Swnj sbwakeup(sb) 24912758Ssam register struct sockbuf *sb; 2504903Swnj { 2514903Swnj 2524903Swnj if (sb->sb_sel) { 2534903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 2544903Swnj sb->sb_sel = 0; 2554903Swnj sb->sb_flags &= ~SB_COLL; 2564903Swnj } 2574903Swnj if (sb->sb_flags & SB_WAIT) { 2584903Swnj sb->sb_flags &= ~SB_WAIT; 2595013Swnj wakeup((caddr_t)&sb->sb_cc); 2604903Swnj } 2614903Swnj } 2624903Swnj 2634903Swnj /* 26415829Scooper * Wakeup socket readers and writers. 26515829Scooper * Do asynchronous notification via SIGIO 26615829Scooper * if the socket has the SS_ASYNC flag set. 26715829Scooper */ 26815829Scooper sowakeup(so, sb) 26915829Scooper register struct socket *so; 27015829Scooper struct sockbuf *sb; 27115829Scooper { 27215829Scooper register struct proc *p; 27315829Scooper 27415829Scooper sbwakeup(sb); 27515829Scooper if (so->so_state & SS_ASYNC) { 27623239Skarels if (so->so_pgrp < 0) 27723239Skarels gsignal(-so->so_pgrp, SIGIO); 27823239Skarels else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0) 27915829Scooper psignal(p, SIGIO); 28015829Scooper } 28115829Scooper } 28215829Scooper 28315829Scooper /* 2845169Swnj * Socket buffer (struct sockbuf) utility routines. 2855169Swnj * 2865169Swnj * Each socket contains two socket buffers: one for sending data and 2875169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 2885169Swnj * information about the number of mbufs and amount of data in the 2895169Swnj * queue, and other fields allowing select() statements and notification 2905169Swnj * on data availability to be implemented. 2915169Swnj * 29216994Skarels * Data stored in a socket buffer is maintained as a list of records. 29316994Skarels * Each record is a list of mbufs chained together with the m_next 29416994Skarels * field. Records are chained together with the m_act field. The upper 29516994Skarels * level routine soreceive() expects the following conventions to be 29616994Skarels * observed when placing information in the receive buffer: 29716994Skarels * 29816994Skarels * 1. If the protocol requires each message be preceded by the sender's 29916994Skarels * name, then a record containing that name must be present before 30016994Skarels * any associated data (mbuf's must be of type MT_SONAME). 30116994Skarels * 2. If the protocol supports the exchange of ``access rights'' (really 30216994Skarels * just additional data associated with the message), and there are 30316994Skarels * ``rights'' to be received, then a record containing this data 30416994Skarels * should be present (mbuf's must be of type MT_RIGHTS). 30516994Skarels * 3. If a name or rights record exists, then it must be followed by 30616994Skarels * a data record, perhaps of zero length. 30716994Skarels * 3085169Swnj * Before using a new socket structure it is first necessary to reserve 30916994Skarels * buffer space to the socket, by calling sbreserve(). This commits 3105169Swnj * some of the available buffer space in the system buffer pool for the 31116994Skarels * socket. The space should be released by calling sbrelease() when the 3125169Swnj * socket is destroyed. 3135169Swnj * 31416994Skarels * The routines sbappend() or sbappendrecord() are normally called to 31516994Skarels * append new mbufs to a socket buffer, after checking that adequate 31616994Skarels * space is available, comparing the function sbspace() with the amount 31716994Skarels * of data to be added. sbappendrecord() differs from sbappend() in 31816994Skarels * that data supplied is treated as the beginning of a new record. 3195169Swnj * Data is normally removed from a socket buffer in a protocol by 3205169Swnj * first calling m_copy on the socket buffer mbuf chain and sending this 3215169Swnj * to a peer, and then removing the data from the socket buffer with 32216994Skarels * sbdrop() or sbdroprecord() when the data is acknowledged by the peer 32316994Skarels * (or immediately in the case of unreliable protocols.) 3245169Swnj * 32516994Skarels * To place a sender's name, optionally, access rights, and data in a 32616994Skarels * socket buffer sbappendaddr() should be used. To place access rights 32716994Skarels * and data in a socket buffer sbappendrights() should be used. Note 32816994Skarels * that unlike sbappend() and sbappendrecord(), these routines check 3295169Swnj * for the caller that there will be enough space to store the data. 33016994Skarels * Each fails if there is not enough space, or if it cannot find mbufs 33116994Skarels * to store additional information in. 3325169Swnj */ 3335169Swnj 3349027Sroot soreserve(so, sndcc, rcvcc) 33512758Ssam register struct socket *so; 3369027Sroot int sndcc, rcvcc; 3379027Sroot { 3389027Sroot 3399027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3409027Sroot goto bad; 3419027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3429027Sroot goto bad2; 3439027Sroot return (0); 3449027Sroot bad2: 3459027Sroot sbrelease(&so->so_snd); 3469027Sroot bad: 3479027Sroot return (ENOBUFS); 3489027Sroot } 3499027Sroot 3505169Swnj /* 3514903Swnj * Allot mbufs to a sockbuf. 3524903Swnj */ 3534903Swnj sbreserve(sb, cc) 3544903Swnj struct sockbuf *sb; 3554903Swnj { 3564903Swnj 35717355Skarels if ((unsigned) cc > SB_MAX) 35817355Skarels return (0); 3597181Swnj /* someday maybe this routine will fail... */ 3604980Swnj sb->sb_hiwat = cc; 36112758Ssam /* * 2 implies names can be no more than 1 mbuf each */ 36217417Skarels sb->sb_mbmax = MIN(cc * 2, SB_MAX); 3634917Swnj return (1); 3644903Swnj } 3654903Swnj 3664903Swnj /* 3674903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3684903Swnj */ 3694903Swnj sbrelease(sb) 3704903Swnj struct sockbuf *sb; 3714903Swnj { 3724903Swnj 3734903Swnj sbflush(sb); 3744980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3754903Swnj } 3764903Swnj 3774903Swnj /* 37816994Skarels * Routines to add and remove 37916994Skarels * data from an mbuf queue. 3804903Swnj */ 3814903Swnj 3824903Swnj /* 38316994Skarels * Append mbuf chain m to the last record in the 38416994Skarels * socket buffer sb. The additional space associated 38516994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 38616994Skarels * discarded and mbufs are compacted where possible. 3874903Swnj */ 3884903Swnj sbappend(sb, m) 38916994Skarels struct sockbuf *sb; 39016994Skarels struct mbuf *m; 3914903Swnj { 3926092Sroot register struct mbuf *n; 3934903Swnj 39416994Skarels if (m == 0) 39516994Skarels return; 39616994Skarels if (n = sb->sb_mb) { 39716994Skarels while (n->m_act) 39816994Skarels n = n->m_act; 3996092Sroot while (n->m_next) 4006092Sroot n = n->m_next; 4014903Swnj } 40216994Skarels sbcompress(sb, m, n); 4034903Swnj } 4044903Swnj 4055169Swnj /* 40616994Skarels * As above, except the mbuf chain 40716994Skarels * begins a new record. 4085169Swnj */ 40916994Skarels sbappendrecord(sb, m0) 41016994Skarels register struct sockbuf *sb; 41116994Skarels register struct mbuf *m0; 4124928Swnj { 4134928Swnj register struct mbuf *m; 4144928Swnj 41516994Skarels if (m0 == 0) 41616994Skarels return; 41716994Skarels if (m = sb->sb_mb) 41816994Skarels while (m->m_act) 41916994Skarels m = m->m_act; 42016994Skarels /* 42116994Skarels * Put the first mbuf on the queue. 42216994Skarels * Note this permits zero length records. 42316994Skarels */ 42416994Skarels sballoc(sb, m0); 42516994Skarels if (m) 42616994Skarels m->m_act = m0; 42716994Skarels else 42816994Skarels sb->sb_mb = m0; 42916994Skarels m = m0->m_next; 43016994Skarels m0->m_next = 0; 43116994Skarels sbcompress(sb, m, m0); 43216994Skarels } 43316994Skarels 43416994Skarels /* 43516994Skarels * Append address and data, and optionally, rights 43616994Skarels * to the receive queue of a socket. Return 0 if 43716994Skarels * no space in sockbuf or insufficient mbufs. 43816994Skarels */ 43916994Skarels sbappendaddr(sb, asa, m0, rights0) /* XXX */ 44016994Skarels register struct sockbuf *sb; 44116994Skarels struct sockaddr *asa; 44216994Skarels struct mbuf *rights0, *m0; 44316994Skarels { 44416994Skarels register struct mbuf *m, *n; 44516994Skarels int space = sizeof (*asa); 44616994Skarels 4475042Swnj m = m0; 4485042Swnj if (m == 0) 4495042Swnj panic("sbappendaddr"); 45016994Skarels do { 45116994Skarels space += m->m_len; 4525042Swnj m = m->m_next; 45316994Skarels } while (m); 45416994Skarels if (rights0) 45516994Skarels space += rights0->m_len; 45616994Skarels if (space > sbspace(sb)) 4574928Swnj return (0); 4589636Ssam m = m_get(M_DONTWAIT, MT_SONAME); 45916994Skarels if (m == 0) 4604928Swnj return (0); 46112758Ssam *mtod(m, struct sockaddr *) = *asa; 46216994Skarels m->m_len = sizeof (*asa); 46316994Skarels if (rights0) { 46416994Skarels m->m_act = m_copy(rights0, 0, rights0->m_len); 46516994Skarels if (m->m_act == 0) { 46616994Skarels m_freem(m); 46716994Skarels return (0); 46816994Skarels } 46916994Skarels sballoc(sb, m->m_act); 47021765Skarels } 47121765Skarels sballoc(sb, m); 47216994Skarels if (n = sb->sb_mb) { 47316994Skarels while (n->m_act) 47416994Skarels n = n->m_act; 47516994Skarels n->m_act = m; 47616994Skarels } else 47716994Skarels sb->sb_mb = m; 47816994Skarels if (m->m_act) 47916994Skarels m = m->m_act; 48016994Skarels sballoc(sb, m0); 48116994Skarels m->m_act = m0; 48216994Skarels m = m0->m_next; 48316994Skarels m0->m_next = 0; 48421765Skarels if (m) 48521765Skarels sbcompress(sb, m, m0); 48616994Skarels return (1); 48716994Skarels } 48816994Skarels 48916994Skarels #ifdef notdef 49016994Skarels sbappendrights(sb, rights, m0) 49116994Skarels struct sockbuf *sb; 49216994Skarels struct mbuf *rights, *m; 49316994Skarels { 49416994Skarels register struct mbuf *m, *n; 49516994Skarels int space = 0; 49616994Skarels 49716994Skarels m = m0; 49816994Skarels if (m == 0 || rights == 0) 49916994Skarels panic("sbappendrights"); 50016994Skarels do { 50116994Skarels space += m->m_len; 50216994Skarels m = m->m_next; 50316994Skarels } while (m); 50416994Skarels space += rights->m_len; 50516994Skarels if (space > sbspace(sb)) 50612758Ssam return (0); 50716994Skarels m = m_copy(rights, 0, rights->m_len); 50816994Skarels if (m == 0) 50916994Skarels return (0); 51016994Skarels sballoc(sb, m); 51116994Skarels if (n = sb->sb_mb) { 51216994Skarels while (n->m_act) 51316994Skarels n = n->m_act; 51416994Skarels n->m_act = m; 51516994Skarels } else 51616994Skarels n->m_act = m; 51716994Skarels sballoc(sb, m0); 51816994Skarels m->m_act = m0; 51916994Skarels m = m0->m_next; 52016994Skarels m0->m_next = 0; 52121765Skarels if (m) 52221765Skarels sbcompress(sb, m, m0); 5234928Swnj return (1); 5244928Swnj } 52516994Skarels #endif 5264928Swnj 5274903Swnj /* 52816994Skarels * Compress mbuf chain m into the socket 52916994Skarels * buffer sb following mbuf n. If n 53016994Skarels * is null, the buffer is presumed empty. 5314903Swnj */ 53216994Skarels sbcompress(sb, m, n) 53316994Skarels register struct sockbuf *sb; 53416994Skarels register struct mbuf *m, *n; 53516994Skarels { 53616994Skarels 53716994Skarels while (m) { 53816994Skarels if (m->m_len == 0) { 53916994Skarels m = m_free(m); 54016994Skarels continue; 54116994Skarels } 54216994Skarels if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 54316994Skarels (n->m_off + n->m_len + m->m_len) <= MMAXOFF) { 54416994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 54516994Skarels (unsigned)m->m_len); 54616994Skarels n->m_len += m->m_len; 54716994Skarels sb->sb_cc += m->m_len; 54816994Skarels m = m_free(m); 54916994Skarels continue; 55016994Skarels } 55116994Skarels sballoc(sb, m); 55216994Skarels if (n) 55316994Skarels n->m_next = m; 55416994Skarels else 55516994Skarels sb->sb_mb = m; 55616994Skarels n = m; 55716994Skarels m = m->m_next; 55816994Skarels n->m_next = 0; 55916994Skarels } 56016994Skarels } 56116994Skarels 56216994Skarels /* 56316994Skarels * Free all mbufs in a sockbuf. 56416994Skarels * Check that all resources are reclaimed. 56516994Skarels */ 5664903Swnj sbflush(sb) 56712758Ssam register struct sockbuf *sb; 5684903Swnj { 5694903Swnj 5704903Swnj if (sb->sb_flags & SB_LOCK) 5714903Swnj panic("sbflush"); 5725266Swnj if (sb->sb_cc) 5735266Swnj sbdrop(sb, sb->sb_cc); 5744903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 5754903Swnj panic("sbflush 2"); 5764903Swnj } 5774903Swnj 5784903Swnj /* 57916994Skarels * Drop data from (the front of) a sockbuf. 5804903Swnj */ 58116994Skarels struct mbuf * 5824903Swnj sbdrop(sb, len) 5834903Swnj register struct sockbuf *sb; 5844903Swnj register int len; 5854903Swnj { 58616994Skarels register struct mbuf *m, *mn; 58716994Skarels struct mbuf *next; 5884903Swnj 58916994Skarels next = (m = sb->sb_mb) ? m->m_act : 0; 5904903Swnj while (len > 0) { 59116994Skarels if (m == 0) { 59216994Skarels if (next == 0) 59316994Skarels panic("sbdrop"); 59416994Skarels m = next; 59516994Skarels next = m->m_act; 59616994Skarels continue; 59716994Skarels } 5985064Swnj if (m->m_len > len) { 5994903Swnj m->m_len -= len; 6004903Swnj m->m_off += len; 6014903Swnj sb->sb_cc -= len; 6024903Swnj break; 6034903Swnj } 6045064Swnj len -= m->m_len; 6055064Swnj sbfree(sb, m); 6065064Swnj MFREE(m, mn); 6075064Swnj m = mn; 6084903Swnj } 60917331Skarels while (m && m->m_len == 0) { 61017417Skarels sbfree(sb, m); 61117331Skarels MFREE(m, mn); 61217331Skarels m = mn; 61317331Skarels } 61416994Skarels if (m) { 61516994Skarels sb->sb_mb = m; 61616994Skarels m->m_act = next; 61716994Skarels } else 61816994Skarels sb->sb_mb = next; 61916994Skarels return (sb->sb_mb); 6204903Swnj } 62116994Skarels 62216994Skarels /* 62316994Skarels * Drop a record off the front of a sockbuf 62416994Skarels * and move the next record to the front. 62516994Skarels */ 62616994Skarels struct mbuf * 62716994Skarels sbdroprecord(sb) 62816994Skarels register struct sockbuf *sb; 62916994Skarels { 63016994Skarels register struct mbuf *m, *mn; 63116994Skarels 63216994Skarels m = sb->sb_mb; 63316994Skarels if (m) { 63416994Skarels sb->sb_mb = m->m_act; 63516994Skarels do { 63616994Skarels sbfree(sb, m); 63716994Skarels MFREE(m, mn); 63816994Skarels } while (m = mn); 63916994Skarels } 64016994Skarels return (sb->sb_mb); 64116994Skarels } 642