123431Smckusick /* 2*63180Sbostic * Copyright (c) 1982, 1986, 1988, 1990, 1993 3*63180Sbostic * The Regents of the University of California. All rights reserved. 423431Smckusick * 544451Sbostic * %sccs.include.redist.c% 633187Sbostic * 7*63180Sbostic * @(#)uipc_socket2.c 8.1 (Berkeley) 06/10/93 823431Smckusick */ 94903Swnj 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/systm.h> 1256517Sbostic #include <sys/proc.h> 1356517Sbostic #include <sys/file.h> 1456517Sbostic #include <sys/buf.h> 1556517Sbostic #include <sys/malloc.h> 1656517Sbostic #include <sys/mbuf.h> 1756517Sbostic #include <sys/protosw.h> 1856517Sbostic #include <sys/socket.h> 1956517Sbostic #include <sys/socketvar.h> 204903Swnj 214903Swnj /* 224903Swnj * Primitive routines for operating on sockets and socket buffers 234903Swnj */ 244903Swnj 2540706Skarels /* strings for sleep message: */ 2640706Skarels char netio[] = "netio"; 2740706Skarels char netcon[] = "netcon"; 2840706Skarels char netcls[] = "netcls"; 2940706Skarels 3040706Skarels u_long sb_max = SB_MAX; /* patchable */ 3140706Skarels 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 } 694903Swnj 704903Swnj soisconnected(so) 7112758Ssam register struct socket *so; 724903Swnj { 737509Sroot register struct socket *head = so->so_head; 744903Swnj 7540633Skarels so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); 7640633Skarels so->so_state |= SS_ISCONNECTED; 7740633Skarels if (head && soqremque(so, 0)) { 787509Sroot soqinsque(head, so, 1); 7912758Ssam sorwakeup(head); 807509Sroot wakeup((caddr_t)&head->so_timeo); 8140633Skarels } else { 8240633Skarels wakeup((caddr_t)&so->so_timeo); 8340633Skarels sorwakeup(so); 8440633Skarels sowwakeup(so); 857509Sroot } 864903Swnj } 874903Swnj 884903Swnj soisdisconnecting(so) 8912758Ssam register struct socket *so; 904903Swnj { 914903Swnj 925248Sroot so->so_state &= ~SS_ISCONNECTING; 934903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 944903Swnj wakeup((caddr_t)&so->so_timeo); 955170Swnj sowwakeup(so); 965169Swnj sorwakeup(so); 974903Swnj } 984903Swnj 994903Swnj soisdisconnected(so) 10012758Ssam register struct socket *so; 1014903Swnj { 1024903Swnj 1034903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 1044903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 1054903Swnj wakeup((caddr_t)&so->so_timeo); 1064903Swnj sowwakeup(so); 1074903Swnj sorwakeup(so); 1084903Swnj } 1094903Swnj 1105169Swnj /* 1117509Sroot * When an attempt at a new connection is noted on a socket 1127509Sroot * which accepts connections, sonewconn is called. If the 1137509Sroot * connection is possible (subject to space constraints, etc.) 1147509Sroot * then we allocate a new structure, propoerly linked into the 1157509Sroot * data structure of the original socket, and return this. 11640633Skarels * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED. 11740706Skarels * 11840706Skarels * Currently, sonewconn() is defined as sonewconn1() in socketvar.h 11940706Skarels * to catch calls that are missing the (new) second parameter. 1207509Sroot */ 1217509Sroot struct socket * 12240706Skarels sonewconn1(head, connstatus) 1237509Sroot register struct socket *head; 12440633Skarels int connstatus; 1257509Sroot { 1267509Sroot register struct socket *so; 12740633Skarels int soqueue = connstatus ? 1 : 0; 1287509Sroot 1297509Sroot if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) 13037329Skarels return ((struct socket *)0); 13137329Skarels MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT); 13237329Skarels if (so == NULL) 13337329Skarels return ((struct socket *)0); 13437329Skarels bzero((caddr_t)so, sizeof(*so)); 1357509Sroot so->so_type = head->so_type; 1367509Sroot so->so_options = head->so_options &~ SO_ACCEPTCONN; 1377509Sroot so->so_linger = head->so_linger; 13810204Ssam so->so_state = head->so_state | SS_NOFDREF; 1397509Sroot so->so_proto = head->so_proto; 1407509Sroot so->so_timeo = head->so_timeo; 14135804Smarc so->so_pgid = head->so_pgid; 14235385Skarels (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); 14340633Skarels soqinsque(head, so, soqueue); 14412758Ssam if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, 14512758Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { 14640633Skarels (void) soqremque(so, soqueue); 14737329Skarels (void) free((caddr_t)so, M_SOCKET); 14837329Skarels return ((struct socket *)0); 1497509Sroot } 15040633Skarels if (connstatus) { 15140633Skarels sorwakeup(head); 15240633Skarels wakeup((caddr_t)&head->so_timeo); 15340633Skarels so->so_state |= connstatus; 15440633Skarels } 1557509Sroot return (so); 1567509Sroot } 1577509Sroot 1587509Sroot soqinsque(head, so, q) 1597509Sroot register struct socket *head, *so; 1607509Sroot int q; 1617509Sroot { 16240706Skarels 16340633Skarels register struct socket **prev; 1647509Sroot so->so_head = head; 1657509Sroot if (q == 0) { 1667509Sroot head->so_q0len++; 16740633Skarels so->so_q0 = 0; 16840633Skarels for (prev = &(head->so_q0); *prev; ) 16940633Skarels prev = &((*prev)->so_q0); 1707509Sroot } else { 1717509Sroot head->so_qlen++; 17240633Skarels so->so_q = 0; 17340633Skarels for (prev = &(head->so_q); *prev; ) 17440633Skarels prev = &((*prev)->so_q); 1757509Sroot } 17640633Skarels *prev = so; 1777509Sroot } 1787509Sroot 1797509Sroot soqremque(so, q) 1807509Sroot register struct socket *so; 1817509Sroot int q; 1827509Sroot { 1837509Sroot register struct socket *head, *prev, *next; 1847509Sroot 1857509Sroot head = so->so_head; 1867509Sroot prev = head; 1877509Sroot for (;;) { 1887509Sroot next = q ? prev->so_q : prev->so_q0; 1897509Sroot if (next == so) 1907509Sroot break; 19140633Skarels if (next == 0) 1927509Sroot return (0); 1937509Sroot prev = next; 1947509Sroot } 1957509Sroot if (q == 0) { 1967509Sroot prev->so_q0 = next->so_q0; 1977509Sroot head->so_q0len--; 1987509Sroot } else { 1997509Sroot prev->so_q = next->so_q; 2007509Sroot head->so_qlen--; 2017509Sroot } 2027509Sroot next->so_q0 = next->so_q = 0; 2037509Sroot next->so_head = 0; 2047509Sroot return (1); 2057509Sroot } 2067509Sroot 2077509Sroot /* 2085169Swnj * Socantsendmore indicates that no more data will be sent on the 2095169Swnj * socket; it would normally be applied to a socket when the user 2105169Swnj * informs the system that no more data is to be sent, by the protocol 2115169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 2125169Swnj * will be received, and will normally be applied to the socket by a 2135169Swnj * protocol when it detects that the peer will send no more data. 2145169Swnj * Data queued for reading in the socket may yet be read. 2155169Swnj */ 2165169Swnj 2174917Swnj socantsendmore(so) 2184917Swnj struct socket *so; 2194917Swnj { 2204917Swnj 2214917Swnj so->so_state |= SS_CANTSENDMORE; 2224917Swnj sowwakeup(so); 2234917Swnj } 2244917Swnj 2254917Swnj socantrcvmore(so) 2264917Swnj struct socket *so; 2274917Swnj { 2284917Swnj 2294917Swnj so->so_state |= SS_CANTRCVMORE; 2304917Swnj sorwakeup(so); 2314917Swnj } 2324917Swnj 2334903Swnj /* 2344917Swnj * Wait for data to arrive at/drain from a socket buffer. 2354917Swnj */ 2364917Swnj sbwait(sb) 2374917Swnj struct sockbuf *sb; 2384917Swnj { 2394917Swnj 2404917Swnj sb->sb_flags |= SB_WAIT; 24140706Skarels return (tsleep((caddr_t)&sb->sb_cc, 24240706Skarels (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio, 24340706Skarels sb->sb_timeo)); 2444917Swnj } 2454917Swnj 24640706Skarels /* 24740706Skarels * Lock a sockbuf already known to be locked; 24840706Skarels * return any error returned from sleep (EINTR). 24940706Skarels */ 25040706Skarels sb_lock(sb) 25140706Skarels register struct sockbuf *sb; 25240706Skarels { 25340706Skarels int error; 25440706Skarels 25540706Skarels while (sb->sb_flags & SB_LOCK) { 25640706Skarels sb->sb_flags |= SB_WANT; 25740706Skarels if (error = tsleep((caddr_t)&sb->sb_flags, 25840706Skarels (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH, 25940706Skarels netio, 0)) 26040706Skarels return (error); 26140706Skarels } 26240706Skarels sb->sb_flags |= SB_LOCK; 26340706Skarels return (0); 26440706Skarels } 26540706Skarels 2664917Swnj /* 2674903Swnj * Wakeup processes waiting on a socket buffer. 26835385Skarels * Do asynchronous notification via SIGIO 26935385Skarels * if the socket has the SS_ASYNC flag set. 2704903Swnj */ 27135385Skarels sowakeup(so, sb) 27235385Skarels register struct socket *so; 27312758Ssam register struct sockbuf *sb; 2744903Swnj { 27537329Skarels struct proc *p; 2764903Swnj 27752527Smckusick selwakeup(&sb->sb_sel); 27852527Smckusick sb->sb_flags &= ~SB_SEL; 2794903Swnj if (sb->sb_flags & SB_WAIT) { 2804903Swnj sb->sb_flags &= ~SB_WAIT; 2815013Swnj wakeup((caddr_t)&sb->sb_cc); 2824903Swnj } 28315829Scooper if (so->so_state & SS_ASYNC) { 28435804Smarc if (so->so_pgid < 0) 28535804Smarc gsignal(-so->so_pgid, SIGIO); 28635804Smarc else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) 28715829Scooper psignal(p, SIGIO); 28815829Scooper } 28915829Scooper } 29015829Scooper 29115829Scooper /* 2925169Swnj * Socket buffer (struct sockbuf) utility routines. 2935169Swnj * 2945169Swnj * Each socket contains two socket buffers: one for sending data and 2955169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 2965169Swnj * information about the number of mbufs and amount of data in the 2975169Swnj * queue, and other fields allowing select() statements and notification 2985169Swnj * on data availability to be implemented. 2995169Swnj * 30016994Skarels * Data stored in a socket buffer is maintained as a list of records. 30116994Skarels * Each record is a list of mbufs chained together with the m_next 30235385Skarels * field. Records are chained together with the m_nextpkt field. The upper 30316994Skarels * level routine soreceive() expects the following conventions to be 30416994Skarels * observed when placing information in the receive buffer: 30516994Skarels * 30616994Skarels * 1. If the protocol requires each message be preceded by the sender's 30716994Skarels * name, then a record containing that name must be present before 30816994Skarels * any associated data (mbuf's must be of type MT_SONAME). 30916994Skarels * 2. If the protocol supports the exchange of ``access rights'' (really 31016994Skarels * just additional data associated with the message), and there are 31116994Skarels * ``rights'' to be received, then a record containing this data 31216994Skarels * should be present (mbuf's must be of type MT_RIGHTS). 31316994Skarels * 3. If a name or rights record exists, then it must be followed by 31416994Skarels * a data record, perhaps of zero length. 31516994Skarels * 3165169Swnj * Before using a new socket structure it is first necessary to reserve 31733406Skarels * buffer space to the socket, by calling sbreserve(). This should commit 3185169Swnj * some of the available buffer space in the system buffer pool for the 31933406Skarels * socket (currently, it does nothing but enforce limits). The space 32033406Skarels * should be released by calling sbrelease() when the socket is destroyed. 3215169Swnj */ 3225169Swnj 3239027Sroot soreserve(so, sndcc, rcvcc) 32412758Ssam register struct socket *so; 32533406Skarels u_long sndcc, rcvcc; 3269027Sroot { 3279027Sroot 3289027Sroot if (sbreserve(&so->so_snd, sndcc) == 0) 3299027Sroot goto bad; 3309027Sroot if (sbreserve(&so->so_rcv, rcvcc) == 0) 3319027Sroot goto bad2; 33240706Skarels if (so->so_rcv.sb_lowat == 0) 33340706Skarels so->so_rcv.sb_lowat = 1; 33440706Skarels if (so->so_snd.sb_lowat == 0) 33540706Skarels so->so_snd.sb_lowat = MCLBYTES; 33640706Skarels if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) 33740706Skarels so->so_snd.sb_lowat = so->so_snd.sb_hiwat; 3389027Sroot return (0); 3399027Sroot bad2: 3409027Sroot sbrelease(&so->so_snd); 3419027Sroot bad: 3429027Sroot return (ENOBUFS); 3439027Sroot } 3449027Sroot 3455169Swnj /* 3464903Swnj * Allot mbufs to a sockbuf. 34740706Skarels * Attempt to scale mbmax so that mbcnt doesn't become limiting 34826830Skarels * if buffering efficiency is near the normal case. 3494903Swnj */ 3504903Swnj sbreserve(sb, cc) 3514903Swnj struct sockbuf *sb; 35233406Skarels u_long cc; 3534903Swnj { 3544903Swnj 35540706Skarels if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES)) 35617355Skarels return (0); 3574980Swnj sb->sb_hiwat = cc; 35840706Skarels sb->sb_mbmax = min(cc * 2, sb_max); 35940706Skarels if (sb->sb_lowat > sb->sb_hiwat) 36040706Skarels sb->sb_lowat = sb->sb_hiwat; 3614917Swnj return (1); 3624903Swnj } 3634903Swnj 3644903Swnj /* 3654903Swnj * Free mbufs held by a socket, and reserved mbuf space. 3664903Swnj */ 3674903Swnj sbrelease(sb) 3684903Swnj struct sockbuf *sb; 3694903Swnj { 3704903Swnj 3714903Swnj sbflush(sb); 3724980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 3734903Swnj } 3744903Swnj 3754903Swnj /* 37616994Skarels * Routines to add and remove 37716994Skarels * data from an mbuf queue. 37825630Skarels * 37925630Skarels * The routines sbappend() or sbappendrecord() are normally called to 38025630Skarels * append new mbufs to a socket buffer, after checking that adequate 38125630Skarels * space is available, comparing the function sbspace() with the amount 38225630Skarels * of data to be added. sbappendrecord() differs from sbappend() in 38325630Skarels * that data supplied is treated as the beginning of a new record. 38425630Skarels * To place a sender's address, optional access rights, and data in a 38525630Skarels * socket receive buffer, sbappendaddr() should be used. To place 38625630Skarels * access rights and data in a socket receive buffer, sbappendrights() 38725630Skarels * should be used. In either case, the new data begins a new record. 38825630Skarels * Note that unlike sbappend() and sbappendrecord(), these routines check 38925630Skarels * for the caller that there will be enough space to store the data. 39025630Skarels * Each fails if there is not enough space, or if it cannot find mbufs 39125630Skarels * to store additional information in. 39225630Skarels * 39325630Skarels * Reliable protocols may use the socket send buffer to hold data 39425630Skarels * awaiting acknowledgement. Data is normally copied from a socket 39525630Skarels * send buffer in a protocol with m_copy for output to a peer, 39625630Skarels * and then removing the data from the socket buffer with sbdrop() 39725630Skarels * or sbdroprecord() when the data is acknowledged by the peer. 3984903Swnj */ 3994903Swnj 4004903Swnj /* 40116994Skarels * Append mbuf chain m to the last record in the 40216994Skarels * socket buffer sb. The additional space associated 40316994Skarels * the mbuf chain is recorded in sb. Empty mbufs are 40416994Skarels * discarded and mbufs are compacted where possible. 4054903Swnj */ 4064903Swnj sbappend(sb, m) 40716994Skarels struct sockbuf *sb; 40816994Skarels struct mbuf *m; 4094903Swnj { 41052527Smckusick register struct mbuf *n; 4114903Swnj 41216994Skarels if (m == 0) 41316994Skarels return; 41416994Skarels if (n = sb->sb_mb) { 41535385Skarels while (n->m_nextpkt) 41635385Skarels n = n->m_nextpkt; 41752527Smckusick do { 41852527Smckusick if (n->m_flags & M_EOR) { 41952527Smckusick sbappendrecord(sb, m); /* XXXXXX!!!! */ 42052527Smckusick return; 42152527Smckusick } 42252527Smckusick } while (n->m_next && (n = n->m_next)); 4234903Swnj } 42416994Skarels sbcompress(sb, m, n); 4254903Swnj } 4264903Swnj 42744384Skarels #ifdef SOCKBUF_DEBUG 42844384Skarels sbcheck(sb) 42944384Skarels register struct sockbuf *sb; 43044384Skarels { 43144384Skarels register struct mbuf *m; 43244384Skarels register int len = 0, mbcnt = 0; 43344384Skarels 43444384Skarels for (m = sb->sb_mb; m; m = m->m_next) { 43544384Skarels len += m->m_len; 43644384Skarels mbcnt += MSIZE; 43744384Skarels if (m->m_flags & M_EXT) 43844384Skarels mbcnt += m->m_ext.ext_size; 43944384Skarels if (m->m_nextpkt) 44044384Skarels panic("sbcheck nextpkt"); 44144384Skarels } 44244384Skarels if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) { 44344384Skarels printf("cc %d != %d || mbcnt %d != %d\n", len, sb->sb_cc, 44444384Skarels mbcnt, sb->sb_mbcnt); 44544384Skarels panic("sbcheck"); 44644384Skarels } 44744384Skarels } 44844384Skarels #endif 44944384Skarels 4505169Swnj /* 45116994Skarels * As above, except the mbuf chain 45216994Skarels * begins a new record. 4535169Swnj */ 45416994Skarels sbappendrecord(sb, m0) 45516994Skarels register struct sockbuf *sb; 45616994Skarels register struct mbuf *m0; 4574928Swnj { 4584928Swnj register struct mbuf *m; 4594928Swnj 46016994Skarels if (m0 == 0) 46116994Skarels return; 46216994Skarels if (m = sb->sb_mb) 46335385Skarels while (m->m_nextpkt) 46435385Skarels m = m->m_nextpkt; 46516994Skarels /* 46616994Skarels * Put the first mbuf on the queue. 46716994Skarels * Note this permits zero length records. 46816994Skarels */ 46916994Skarels sballoc(sb, m0); 47016994Skarels if (m) 47135385Skarels m->m_nextpkt = m0; 47216994Skarels else 47316994Skarels sb->sb_mb = m0; 47416994Skarels m = m0->m_next; 47516994Skarels m0->m_next = 0; 47652527Smckusick if (m && (m0->m_flags & M_EOR)) { 47752527Smckusick m0->m_flags &= ~M_EOR; 47852527Smckusick m->m_flags |= M_EOR; 47952527Smckusick } 48016994Skarels sbcompress(sb, m, m0); 48116994Skarels } 48216994Skarels 48316994Skarels /* 48437329Skarels * As above except that OOB data 48537329Skarels * is inserted at the beginning of the sockbuf, 48637329Skarels * but after any other OOB data. 48737329Skarels */ 48837329Skarels sbinsertoob(sb, m0) 48937329Skarels register struct sockbuf *sb; 49037329Skarels register struct mbuf *m0; 49137329Skarels { 49237329Skarels register struct mbuf *m; 49337329Skarels register struct mbuf **mp; 49437329Skarels 49537329Skarels if (m0 == 0) 49637329Skarels return; 49737329Skarels for (mp = &sb->sb_mb; m = *mp; mp = &((*mp)->m_nextpkt)) { 49837329Skarels again: 49937329Skarels switch (m->m_type) { 50037329Skarels 50137329Skarels case MT_OOBDATA: 50237329Skarels continue; /* WANT next train */ 50337329Skarels 50437329Skarels case MT_CONTROL: 50537329Skarels if (m = m->m_next) 50637329Skarels goto again; /* inspect THIS train further */ 50737329Skarels } 50837329Skarels break; 50937329Skarels } 51037329Skarels /* 51137329Skarels * Put the first mbuf on the queue. 51237329Skarels * Note this permits zero length records. 51337329Skarels */ 51452527Smckusick sballoc(sb, m0); 51537329Skarels m0->m_nextpkt = *mp; 51637329Skarels *mp = m0; 51752527Smckusick m = m0->m_next; 51852527Smckusick m0->m_next = 0; 51952527Smckusick if (m && (m0->m_flags & M_EOR)) { 52052527Smckusick m0->m_flags &= ~M_EOR; 52152527Smckusick m->m_flags |= M_EOR; 52252527Smckusick } 52352527Smckusick sbcompress(sb, m, m0); 52437329Skarels } 52537329Skarels 52637329Skarels /* 52742259Skarels * Append address and data, and optionally, control (ancillary) data 52835385Skarels * to the receive queue of a socket. If present, 52942259Skarels * m0 must include a packet header with total length. 53042259Skarels * Returns 0 if no space in sockbuf or insufficient mbufs. 53116994Skarels */ 53242259Skarels sbappendaddr(sb, asa, m0, control) 53316994Skarels register struct sockbuf *sb; 53416994Skarels struct sockaddr *asa; 53542259Skarels struct mbuf *m0, *control; 53616994Skarels { 53716994Skarels register struct mbuf *m, *n; 53852527Smckusick int space = asa->sa_len; 53916994Skarels 54035385Skarels if (m0 && (m0->m_flags & M_PKTHDR) == 0) 54135385Skarels panic("sbappendaddr"); 54235385Skarels if (m0) 54335385Skarels space += m0->m_pkthdr.len; 54442259Skarels for (n = control; n; n = n->m_next) { 54542259Skarels space += n->m_len; 54642259Skarels if (n->m_next == 0) /* keep pointer to last control buf */ 54742259Skarels break; 54842259Skarels } 54916994Skarels if (space > sbspace(sb)) 5504928Swnj return (0); 55142259Skarels if (asa->sa_len > MLEN) 55242259Skarels return (0); 55325630Skarels MGET(m, M_DONTWAIT, MT_SONAME); 55416994Skarels if (m == 0) 5554928Swnj return (0); 55637329Skarels m->m_len = asa->sa_len; 55737329Skarels bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len); 55842259Skarels if (n) 55942259Skarels n->m_next = m0; /* concatenate data to control */ 56042259Skarels else 56142259Skarels control = m0; 56242259Skarels m->m_next = control; 56352527Smckusick for (n = m; n; n = n->m_next) 56442259Skarels sballoc(sb, n); 56516994Skarels if (n = sb->sb_mb) { 56635385Skarels while (n->m_nextpkt) 56735385Skarels n = n->m_nextpkt; 56835385Skarels n->m_nextpkt = m; 56916994Skarels } else 57016994Skarels sb->sb_mb = m; 57116994Skarels return (1); 57216994Skarels } 57316994Skarels 57442259Skarels sbappendcontrol(sb, m0, control) 57516994Skarels struct sockbuf *sb; 57642259Skarels struct mbuf *control, *m0; 57716994Skarels { 57816994Skarels register struct mbuf *m, *n; 57952527Smckusick int space = 0; 58016994Skarels 58142259Skarels if (control == 0) 58242259Skarels panic("sbappendcontrol"); 58342259Skarels for (m = control; ; m = m->m_next) { 58442259Skarels space += m->m_len; 58542259Skarels if (m->m_next == 0) 58642259Skarels break; 58742259Skarels } 58842259Skarels n = m; /* save pointer to last control buffer */ 58925630Skarels for (m = m0; m; m = m->m_next) 59016994Skarels space += m->m_len; 59116994Skarels if (space > sbspace(sb)) 59212758Ssam return (0); 59342259Skarels n->m_next = m0; /* concatenate data to control */ 59452527Smckusick for (m = control; m; m = m->m_next) 59542259Skarels sballoc(sb, m); 59616994Skarels if (n = sb->sb_mb) { 59735385Skarels while (n->m_nextpkt) 59835385Skarels n = n->m_nextpkt; 59942259Skarels n->m_nextpkt = control; 60016994Skarels } else 60142259Skarels sb->sb_mb = control; 6024928Swnj return (1); 6034928Swnj } 6044928Swnj 6054903Swnj /* 60616994Skarels * Compress mbuf chain m into the socket 60716994Skarels * buffer sb following mbuf n. If n 60816994Skarels * is null, the buffer is presumed empty. 6094903Swnj */ 61052527Smckusick sbcompress(sb, m, n) 61116994Skarels register struct sockbuf *sb; 61252527Smckusick register struct mbuf *m, *n; 61316994Skarels { 61442259Skarels register int eor = 0; 61552527Smckusick register struct mbuf *o; 61616994Skarels 61716994Skarels while (m) { 61837329Skarels eor |= m->m_flags & M_EOR; 61952527Smckusick if (m->m_len == 0 && 62052527Smckusick (eor == 0 || 62152527Smckusick (((o = m->m_next) || (o = n)) && 62252527Smckusick o->m_type == m->m_type))) { 62352527Smckusick m = m_free(m); 62452527Smckusick continue; 62516994Skarels } 62652527Smckusick if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 && 62735385Skarels (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] && 62825630Skarels n->m_type == m->m_type) { 62916994Skarels bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 63016994Skarels (unsigned)m->m_len); 63116994Skarels n->m_len += m->m_len; 63216994Skarels sb->sb_cc += m->m_len; 63316994Skarels m = m_free(m); 63416994Skarels continue; 63516994Skarels } 63652527Smckusick if (n) 63716994Skarels n->m_next = m; 63852527Smckusick else 63952527Smckusick sb->sb_mb = m; 64037329Skarels sballoc(sb, m); 64116994Skarels n = m; 64252527Smckusick m->m_flags &= ~M_EOR; 64316994Skarels m = m->m_next; 64416994Skarels n->m_next = 0; 64516994Skarels } 64646480Ssklower if (eor) { 64752527Smckusick if (n) 64852527Smckusick n->m_flags |= eor; 64946480Ssklower else 65052527Smckusick printf("semi-panic: sbcompress\n"); 65146480Ssklower } 65216994Skarels } 65316994Skarels 65416994Skarels /* 65516994Skarels * Free all mbufs in a sockbuf. 65616994Skarels * Check that all resources are reclaimed. 65716994Skarels */ 6584903Swnj sbflush(sb) 65912758Ssam register struct sockbuf *sb; 6604903Swnj { 6614903Swnj 6624903Swnj if (sb->sb_flags & SB_LOCK) 6634903Swnj panic("sbflush"); 66426105Skarels while (sb->sb_mbcnt) 66526363Skarels sbdrop(sb, (int)sb->sb_cc); 66642259Skarels if (sb->sb_cc || sb->sb_mb) 6674903Swnj panic("sbflush 2"); 6684903Swnj } 6694903Swnj 6704903Swnj /* 67116994Skarels * Drop data from (the front of) a sockbuf. 6724903Swnj */ 6734903Swnj sbdrop(sb, len) 6744903Swnj register struct sockbuf *sb; 6754903Swnj register int len; 6764903Swnj { 67716994Skarels register struct mbuf *m, *mn; 67816994Skarels struct mbuf *next; 6794903Swnj 68035385Skarels next = (m = sb->sb_mb) ? m->m_nextpkt : 0; 6814903Swnj while (len > 0) { 68216994Skarels if (m == 0) { 68316994Skarels if (next == 0) 68416994Skarels panic("sbdrop"); 68516994Skarels m = next; 68635385Skarels next = m->m_nextpkt; 68716994Skarels continue; 68816994Skarels } 6895064Swnj if (m->m_len > len) { 6904903Swnj m->m_len -= len; 69135385Skarels m->m_data += len; 6924903Swnj sb->sb_cc -= len; 6934903Swnj break; 6944903Swnj } 6955064Swnj len -= m->m_len; 6965064Swnj sbfree(sb, m); 6975064Swnj MFREE(m, mn); 6985064Swnj m = mn; 6994903Swnj } 70017331Skarels while (m && m->m_len == 0) { 70117417Skarels sbfree(sb, m); 70217331Skarels MFREE(m, mn); 70317331Skarels m = mn; 70417331Skarels } 70516994Skarels if (m) { 70616994Skarels sb->sb_mb = m; 70735385Skarels m->m_nextpkt = next; 70816994Skarels } else 70916994Skarels sb->sb_mb = next; 7104903Swnj } 71116994Skarels 71216994Skarels /* 71316994Skarels * Drop a record off the front of a sockbuf 71416994Skarels * and move the next record to the front. 71516994Skarels */ 71616994Skarels sbdroprecord(sb) 71716994Skarels register struct sockbuf *sb; 71816994Skarels { 71916994Skarels register struct mbuf *m, *mn; 72016994Skarels 72116994Skarels m = sb->sb_mb; 72216994Skarels if (m) { 72335385Skarels sb->sb_mb = m->m_nextpkt; 72416994Skarels do { 72516994Skarels sbfree(sb, m); 72616994Skarels MFREE(m, mn); 72716994Skarels } while (m = mn); 72816994Skarels } 72916994Skarels } 730