123431Smckusick /* 223431Smckusick * Copyright (c) 1982 Regents of the University of California. 323431Smckusick * All rights reserved. The Berkeley software License Agreement 423431Smckusick * specifies the terms and conditions for redistribution. 523431Smckusick * 6*26105Skarels * @(#)uipc_socket2.c 6.14 (Berkeley) 02/07/86 723431Smckusick */ 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 */ 3145169Swnj 3159027Sroot soreserve(so, sndcc, rcvcc) 31612758Ssam register struct socket *so; 3179027Sroot int sndcc, rcvcc; 3189027Sroot { 3199027Sroot 3209027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3219027Sroot goto bad; 3229027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3239027Sroot goto bad2; 3249027Sroot return (0); 3259027Sroot bad2: 3269027Sroot sbrelease(&so->so_snd); 3279027Sroot bad: 3289027Sroot return (ENOBUFS); 3299027Sroot } 3309027Sroot 3315169Swnj /* 3324903Swnj * Allot mbufs to a sockbuf. 3334903Swnj */ 3344903Swnj sbreserve(sb, cc) 3354903Swnj struct sockbuf *sb; 3364903Swnj { 3374903Swnj 33817355Skarels if ((unsigned) cc > SB_MAX) 33917355Skarels return (0); 3407181Swnj /* someday maybe this routine will fail... */ 3414980Swnj sb->sb_hiwat = cc; 34212758Ssam /* * 2 implies names can be no more than 1 mbuf each */ 34317417Skarels sb->sb_mbmax = MIN(cc * 2, SB_MAX); 3444917Swnj return (1); 3454903Swnj } 3464903Swnj 3474903Swnj /* 3484903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3494903Swnj */ 3504903Swnj sbrelease(sb) 3514903Swnj struct sockbuf *sb; 3524903Swnj { 3534903Swnj 3544903Swnj sbflush(sb); 3554980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3564903Swnj } 3574903Swnj 3584903Swnj /* 35916994Skarels * Routines to add and remove 36016994Skarels * data from an mbuf queue. 36125630Skarels * 36225630Skarels * The routines sbappend() or sbappendrecord() are normally called to 36325630Skarels * append new mbufs to a socket buffer, after checking that adequate 36425630Skarels * space is available, comparing the function sbspace() with the amount 36525630Skarels * of data to be added. sbappendrecord() differs from sbappend() in 36625630Skarels * that data supplied is treated as the beginning of a new record. 36725630Skarels * To place a sender's address, optional access rights, and data in a 36825630Skarels * socket receive buffer, sbappendaddr() should be used. To place 36925630Skarels * access rights and data in a socket receive buffer, sbappendrights() 37025630Skarels * should be used. In either case, the new data begins a new record. 37125630Skarels * Note that unlike sbappend() and sbappendrecord(), these routines check 37225630Skarels * for the caller that there will be enough space to store the data. 37325630Skarels * Each fails if there is not enough space, or if it cannot find mbufs 37425630Skarels * to store additional information in. 37525630Skarels * 37625630Skarels * Reliable protocols may use the socket send buffer to hold data 37725630Skarels * awaiting acknowledgement. Data is normally copied from a socket 37825630Skarels * send buffer in a protocol with m_copy for output to a peer, 37925630Skarels * and then removing the data from the socket buffer with sbdrop() 38025630Skarels * or sbdroprecord() when the data is acknowledged by the peer. 3814903Swnj */ 3824903Swnj 3834903Swnj /* 38416994Skarels * Append mbuf chain m to the last record in the 38516994Skarels * socket buffer sb. The additional space associated 38616994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 38716994Skarels * discarded and mbufs are compacted where possible. 3884903Swnj */ 3894903Swnj sbappend(sb, m) 39016994Skarels struct sockbuf *sb; 39116994Skarels struct mbuf *m; 3924903Swnj { 3936092Sroot register struct mbuf *n; 3944903Swnj 39516994Skarels if (m == 0) 39616994Skarels return; 39716994Skarels if (n = sb->sb_mb) { 39816994Skarels while (n->m_act) 39916994Skarels n = n->m_act; 4006092Sroot while (n->m_next) 4016092Sroot n = n->m_next; 4024903Swnj } 40316994Skarels sbcompress(sb, m, n); 4044903Swnj } 4054903Swnj 4065169Swnj /* 40716994Skarels * As above, except the mbuf chain 40816994Skarels * begins a new record. 4095169Swnj */ 41016994Skarels sbappendrecord(sb, m0) 41116994Skarels register struct sockbuf *sb; 41216994Skarels register struct mbuf *m0; 4134928Swnj { 4144928Swnj register struct mbuf *m; 4154928Swnj 41616994Skarels if (m0 == 0) 41716994Skarels return; 41816994Skarels if (m = sb->sb_mb) 41916994Skarels while (m->m_act) 42016994Skarels m = m->m_act; 42116994Skarels /* 42216994Skarels * Put the first mbuf on the queue. 42316994Skarels * Note this permits zero length records. 42416994Skarels */ 42516994Skarels sballoc(sb, m0); 42616994Skarels if (m) 42716994Skarels m->m_act = m0; 42816994Skarels else 42916994Skarels sb->sb_mb = m0; 43016994Skarels m = m0->m_next; 43116994Skarels m0->m_next = 0; 43216994Skarels sbcompress(sb, m, m0); 43316994Skarels } 43416994Skarels 43516994Skarels /* 43616994Skarels * Append address and data, and optionally, rights 43716994Skarels * to the receive queue of a socket. Return 0 if 43816994Skarels * no space in sockbuf or insufficient mbufs. 43916994Skarels */ 44025630Skarels sbappendaddr(sb, asa, m0, rights0) 44116994Skarels register struct sockbuf *sb; 44216994Skarels struct sockaddr *asa; 44316994Skarels struct mbuf *rights0, *m0; 44416994Skarels { 44516994Skarels register struct mbuf *m, *n; 44616994Skarels int space = sizeof (*asa); 44716994Skarels 44825630Skarels for (m = m0; m; m = m->m_next) 44916994Skarels space += m->m_len; 45016994Skarels if (rights0) 45116994Skarels space += rights0->m_len; 45216994Skarels if (space > sbspace(sb)) 4534928Swnj return (0); 45425630Skarels MGET(m, M_DONTWAIT, MT_SONAME); 45516994Skarels if (m == 0) 4564928Swnj return (0); 45712758Ssam *mtod(m, struct sockaddr *) = *asa; 45816994Skarels m->m_len = sizeof (*asa); 45925921Skarels if (rights0 && rights0->m_len) { 46025630Skarels m->m_next = m_copy(rights0, 0, rights0->m_len); 46125630Skarels if (m->m_next == 0) { 46216994Skarels m_freem(m); 46316994Skarels return (0); 46416994Skarels } 46525630Skarels sballoc(sb, m->m_next); 46621765Skarels } 46725938Skarels sballoc(sb, m); 46816994Skarels if (n = sb->sb_mb) { 46916994Skarels while (n->m_act) 47016994Skarels n = n->m_act; 47116994Skarels n->m_act = m; 47216994Skarels } else 47316994Skarels sb->sb_mb = m; 47425630Skarels if (m->m_next) 47525630Skarels m = m->m_next; 47625630Skarels if (m0) 47725630Skarels sbcompress(sb, m0, m); 47816994Skarels return (1); 47916994Skarels } 48016994Skarels 48125630Skarels sbappendrights(sb, m0, rights) 48216994Skarels struct sockbuf *sb; 48325630Skarels struct mbuf *rights, *m0; 48416994Skarels { 48516994Skarels register struct mbuf *m, *n; 48616994Skarels int space = 0; 48716994Skarels 48825630Skarels if (rights == 0) 48916994Skarels panic("sbappendrights"); 49025630Skarels for (m = m0; m; m = m->m_next) 49116994Skarels space += m->m_len; 49216994Skarels space += rights->m_len; 49316994Skarels if (space > sbspace(sb)) 49412758Ssam return (0); 49516994Skarels m = m_copy(rights, 0, rights->m_len); 49616994Skarels if (m == 0) 49716994Skarels return (0); 49816994Skarels sballoc(sb, m); 49916994Skarels if (n = sb->sb_mb) { 50016994Skarels while (n->m_act) 50116994Skarels n = n->m_act; 50216994Skarels n->m_act = m; 50316994Skarels } else 50425630Skarels sb->sb_mb = m; 50525630Skarels if (m0) 50625630Skarels sbcompress(sb, m0, m); 5074928Swnj return (1); 5084928Swnj } 5094928Swnj 5104903Swnj /* 51116994Skarels * Compress mbuf chain m into the socket 51216994Skarels * buffer sb following mbuf n. If n 51316994Skarels * is null, the buffer is presumed empty. 5144903Swnj */ 51516994Skarels sbcompress(sb, m, n) 51616994Skarels register struct sockbuf *sb; 51716994Skarels register struct mbuf *m, *n; 51816994Skarels { 51916994Skarels 52016994Skarels while (m) { 52116994Skarels if (m->m_len == 0) { 52216994Skarels m = m_free(m); 52316994Skarels continue; 52416994Skarels } 52516994Skarels if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 52625630Skarels (n->m_off + n->m_len + m->m_len) <= MMAXOFF && 52725630Skarels n->m_type == m->m_type) { 52816994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 52916994Skarels (unsigned)m->m_len); 53016994Skarels n->m_len += m->m_len; 53116994Skarels sb->sb_cc += m->m_len; 53216994Skarels m = m_free(m); 53316994Skarels continue; 53416994Skarels } 53516994Skarels sballoc(sb, m); 53616994Skarels if (n) 53716994Skarels n->m_next = m; 53816994Skarels else 53916994Skarels sb->sb_mb = m; 54016994Skarels n = m; 54116994Skarels m = m->m_next; 54216994Skarels n->m_next = 0; 54316994Skarels } 54416994Skarels } 54516994Skarels 54616994Skarels /* 54716994Skarels * Free all mbufs in a sockbuf. 54816994Skarels * Check that all resources are reclaimed. 54916994Skarels */ 5504903Swnj sbflush(sb) 55112758Ssam register struct sockbuf *sb; 5524903Swnj { 5534903Swnj 5544903Swnj if (sb->sb_flags & SB_LOCK) 5554903Swnj panic("sbflush"); 556*26105Skarels while (sb->sb_mbcnt) 5575266Swnj sbdrop(sb, sb->sb_cc); 5584903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 5594903Swnj panic("sbflush 2"); 5604903Swnj } 5614903Swnj 5624903Swnj /* 56316994Skarels * Drop data from (the front of) a sockbuf. 5644903Swnj */ 56516994Skarels struct mbuf * 5664903Swnj sbdrop(sb, len) 5674903Swnj register struct sockbuf *sb; 5684903Swnj register int len; 5694903Swnj { 57016994Skarels register struct mbuf *m, *mn; 57116994Skarels struct mbuf *next; 5724903Swnj 57316994Skarels next = (m = sb->sb_mb) ? m->m_act : 0; 5744903Swnj while (len > 0) { 57516994Skarels if (m == 0) { 57616994Skarels if (next == 0) 57716994Skarels panic("sbdrop"); 57816994Skarels m = next; 57916994Skarels next = m->m_act; 58016994Skarels continue; 58116994Skarels } 5825064Swnj if (m->m_len > len) { 5834903Swnj m->m_len -= len; 5844903Swnj m->m_off += len; 5854903Swnj sb->sb_cc -= len; 5864903Swnj break; 5874903Swnj } 5885064Swnj len -= m->m_len; 5895064Swnj sbfree(sb, m); 5905064Swnj MFREE(m, mn); 5915064Swnj m = mn; 5924903Swnj } 59317331Skarels while (m && m->m_len == 0) { 59417417Skarels sbfree(sb, m); 59517331Skarels MFREE(m, mn); 59617331Skarels m = mn; 59717331Skarels } 59816994Skarels if (m) { 59916994Skarels sb->sb_mb = m; 60016994Skarels m->m_act = next; 60116994Skarels } else 60216994Skarels sb->sb_mb = next; 60316994Skarels return (sb->sb_mb); 6044903Swnj } 60516994Skarels 60616994Skarels /* 60716994Skarels * Drop a record off the front of a sockbuf 60816994Skarels * and move the next record to the front. 60916994Skarels */ 61016994Skarels struct mbuf * 61116994Skarels sbdroprecord(sb) 61216994Skarels register struct sockbuf *sb; 61316994Skarels { 61416994Skarels register struct mbuf *m, *mn; 61516994Skarels 61616994Skarels m = sb->sb_mb; 61716994Skarels if (m) { 61816994Skarels sb->sb_mb = m->m_act; 61916994Skarels do { 62016994Skarels sbfree(sb, m); 62116994Skarels MFREE(m, mn); 62216994Skarels } while (m = mn); 62316994Skarels } 62416994Skarels return (sb->sb_mb); 62516994Skarels } 626