1*5170Swnj /* uipc_socket2.c 4.13 81/12/03 */ 24903Swnj 34903Swnj #include "../h/param.h" 44903Swnj #include "../h/systm.h" 54903Swnj #include "../h/dir.h" 64903Swnj #include "../h/user.h" 74903Swnj #include "../h/proc.h" 84903Swnj #include "../h/file.h" 94903Swnj #include "../h/inode.h" 104903Swnj #include "../h/buf.h" 114903Swnj #include "../h/mbuf.h" 124903Swnj #include "../h/protosw.h" 134903Swnj #include "../h/socket.h" 144903Swnj #include "../h/socketvar.h" 155096Swnj #include "../net/in.h" 165096Swnj #include "../net/in_systm.h" 174903Swnj 184903Swnj /* 194903Swnj * Primitive routines for operating on sockets and socket buffers 204903Swnj */ 214903Swnj 224903Swnj /* 234903Swnj * Procedures to manipulate state flags of socket 245169Swnj * and do appropriate wakeups. Normal sequence is that 255169Swnj * soisconnecting() is called during processing of connect() call, 265169Swnj * resulting in an eventual call to soisconnected() if/when the 275169Swnj * connection is established. When the connection is torn down 285169Swnj * soisdisconnecting() is called during processing of disconnect() call, 295169Swnj * and soisdisconnected() is called when the connection to the peer 305169Swnj * is totally severed. The semantics of these routines are such that 315169Swnj * connectionless protocols can call soisconnected() and soisdisconnected() 325169Swnj * only, bypassing the in-progress calls when setting up a ``connection'' 335169Swnj * takes no time. 345169Swnj * 355169Swnj * When higher level protocols are implemented in 365169Swnj * the kernel, the wakeups done here will sometimes 375169Swnj * be implemented as software-interrupt process scheduling. 384903Swnj */ 395169Swnj 404903Swnj soisconnecting(so) 414903Swnj struct socket *so; 424903Swnj { 434903Swnj 444903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 454903Swnj so->so_state |= SS_ISCONNECTING; 464903Swnj wakeup((caddr_t)&so->so_timeo); 474903Swnj } 484903Swnj 494903Swnj soisconnected(so) 504903Swnj struct socket *so; 514903Swnj { 524903Swnj 534903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 544903Swnj so->so_state |= SS_ISCONNECTED; 554903Swnj wakeup((caddr_t)&so->so_timeo); 564903Swnj } 574903Swnj 584903Swnj soisdisconnecting(so) 594903Swnj struct socket *so; 604903Swnj { 614903Swnj 624903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISCONNECTING); 634903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 644903Swnj wakeup((caddr_t)&so->so_timeo); 65*5170Swnj sowwakeup(so); 665169Swnj sorwakeup(so); 674903Swnj } 684903Swnj 694903Swnj soisdisconnected(so) 704903Swnj struct socket *so; 714903Swnj { 724903Swnj 734903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 744903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 754903Swnj wakeup((caddr_t)&so->so_timeo); 764903Swnj sowwakeup(so); 774903Swnj sorwakeup(so); 784903Swnj } 794903Swnj 805169Swnj /* 815169Swnj * Socantsendmore indicates that no more data will be sent on the 825169Swnj * socket; it would normally be applied to a socket when the user 835169Swnj * informs the system that no more data is to be sent, by the protocol 845169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 855169Swnj * will be received, and will normally be applied to the socket by a 865169Swnj * protocol when it detects that the peer will send no more data. 875169Swnj * Data queued for reading in the socket may yet be read. 885169Swnj */ 895169Swnj 904917Swnj socantsendmore(so) 914917Swnj struct socket *so; 924917Swnj { 934917Swnj 944917Swnj so->so_state |= SS_CANTSENDMORE; 954917Swnj sowwakeup(so); 964917Swnj } 974917Swnj 984917Swnj socantrcvmore(so) 994917Swnj struct socket *so; 1004917Swnj { 1014917Swnj 1024917Swnj so->so_state |= SS_CANTRCVMORE; 1034917Swnj sorwakeup(so); 1044917Swnj } 1054917Swnj 1064903Swnj /* 1075169Swnj * Socket select/wakeup routines. 1084903Swnj */ 1095169Swnj 1105169Swnj /* 1115169Swnj * Interface routine to select() system 1125169Swnj * call for sockets. 1135169Swnj */ 1144903Swnj soselect(so, flag) 1154903Swnj register struct socket *so; 1164903Swnj int flag; 1174903Swnj { 1184903Swnj 1194903Swnj if (flag & FREAD) { 1204903Swnj if (soreadable(so)) 1214903Swnj return (1); 1224903Swnj sbselqueue(&so->so_rcv); 1234903Swnj } 1244903Swnj if (flag & FWRITE) { 1254903Swnj if (sowriteable(so)) 1264903Swnj return (1); 1274903Swnj sbselqueue(&so->so_snd); 1284903Swnj } 1294903Swnj return (0); 1304903Swnj } 1314903Swnj 1324903Swnj /* 1334903Swnj * Queue a process for a select on a socket buffer. 1344903Swnj */ 1354903Swnj sbselqueue(sb) 1364903Swnj struct sockbuf *sb; 1374903Swnj { 1384903Swnj register struct proc *p; 1394903Swnj 1404917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 1414903Swnj sb->sb_flags |= SB_COLL; 1424903Swnj else 1434903Swnj sb->sb_sel = u.u_procp; 1444903Swnj } 1454903Swnj 1464903Swnj /* 1474917Swnj * Wait for data to arrive at/drain from a socket buffer. 1484917Swnj */ 1494917Swnj sbwait(sb) 1504917Swnj struct sockbuf *sb; 1514917Swnj { 1524917Swnj 1534917Swnj sb->sb_flags |= SB_WAIT; 1544917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 1554917Swnj } 1564917Swnj 1574917Swnj /* 1584903Swnj * Wakeup processes waiting on a socket buffer. 1594903Swnj */ 1604903Swnj sbwakeup(sb) 1614903Swnj struct sockbuf *sb; 1624903Swnj { 1634903Swnj 1644903Swnj if (sb->sb_sel) { 1654903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 1664903Swnj sb->sb_sel = 0; 1674903Swnj sb->sb_flags &= ~SB_COLL; 1684903Swnj } 1694903Swnj if (sb->sb_flags & SB_WAIT) { 1704903Swnj sb->sb_flags &= ~SB_WAIT; 1715013Swnj wakeup((caddr_t)&sb->sb_cc); 1724903Swnj } 1734903Swnj } 1744903Swnj 1754903Swnj /* 1765169Swnj * Socket buffer (struct sockbuf) utility routines. 1775169Swnj * 1785169Swnj * Each socket contains two socket buffers: one for sending data and 1795169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 1805169Swnj * information about the number of mbufs and amount of data in the 1815169Swnj * queue, and other fields allowing select() statements and notification 1825169Swnj * on data availability to be implemented. 1835169Swnj * 1845169Swnj * Before using a new socket structure it is first necessary to reserve 1855169Swnj * buffer space to the socket, by calling sbreserve. This commits 1865169Swnj * some of the available buffer space in the system buffer pool for the 1875169Swnj * socket. The space should be released by calling sbrelease when the 1885169Swnj * socket is destroyed. 1895169Swnj * 1905169Swnj * The routine sbappend() is normally called to append new mbufs 1915169Swnj * to a socket buffer, after checking that adequate space is available 1925169Swnj * comparing the function spspace() with the amount of data to be added. 1935169Swnj * Data is normally removed from a socket buffer in a protocol by 1945169Swnj * first calling m_copy on the socket buffer mbuf chain and sending this 1955169Swnj * to a peer, and then removing the data from the socket buffer with 1965169Swnj * sbdrop when the data is acknowledged by the peer (or immediately 197*5170Swnj * in the case of unreliable protocols.) 1985169Swnj * 1995169Swnj * Protocols which do not require connections place both source address 2005169Swnj * and data information in socket buffer queues. The source addresses 2015169Swnj * are stored in single mbufs after each data item, and are easily found 2025169Swnj * as the data items are all marked with end of record markers. The 2035169Swnj * sbappendaddr() routine stores a datum and associated address in 2045169Swnj * a socket buffer. Note that, unlike sbappend(), this routine checks 2055169Swnj * for the caller that there will be enough space to store the data. 2065169Swnj * It fails if there is not enough space, or if it cannot find 2075169Swnj * a mbuf to store the address in. 2085169Swnj * 2095169Swnj * The higher-level routines sosend and soreceive (in socket.c) 210*5170Swnj * also add data to, and remove data from socket buffers repectively. 2115169Swnj */ 2125169Swnj 2135169Swnj /* 2144903Swnj * Allot mbufs to a sockbuf. 2154903Swnj */ 2164903Swnj sbreserve(sb, cc) 2174903Swnj struct sockbuf *sb; 2184903Swnj { 2194903Swnj 2205015Sroot if (m_reserve((cc*2)/MSIZE) == 0) 2214903Swnj return (0); 2224980Swnj sb->sb_hiwat = cc; 2235042Swnj sb->sb_mbmax = cc*2; 2244917Swnj return (1); 2254903Swnj } 2264903Swnj 2274903Swnj /* 2284903Swnj * Free mbufs held by a socket, and reserved mbuf space. 2294903Swnj */ 2304903Swnj sbrelease(sb) 2314903Swnj struct sockbuf *sb; 2324903Swnj { 2334903Swnj 2344903Swnj sbflush(sb); 2355019Swnj m_release(sb->sb_mbmax/MSIZE); 2364980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 2374903Swnj } 2384903Swnj 2394903Swnj /* 2404903Swnj * Routines to add (at the end) and remove (from the beginning) 2414903Swnj * data from a mbuf queue. 2424903Swnj */ 2434903Swnj 2444903Swnj /* 2454903Swnj * Append mbuf queue m to sockbuf sb. 2464903Swnj */ 2474903Swnj sbappend(sb, m) 2484903Swnj register struct mbuf *m; 2494903Swnj register struct sockbuf *sb; 2504903Swnj { 2514903Swnj register struct mbuf **np, *n; 2524903Swnj 2534903Swnj np = &sb->sb_mb; 2545013Swnj n = 0; 2555013Swnj while (*np) { 2565013Swnj n = *np; 2574903Swnj np = &n->m_next; 2585013Swnj } 2594903Swnj while (m) { 2604903Swnj if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 2614903Swnj (int)n->m_act == 0 && (int)m->m_act == 0 && 2625042Swnj (n->m_off + n->m_len + m->m_len) <= MMAXOFF) { 2635042Swnj bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 2644917Swnj (unsigned)m->m_len); 2654903Swnj n->m_len += m->m_len; 2664903Swnj sb->sb_cc += m->m_len; 2674903Swnj m = m_free(m); 2684903Swnj continue; 2694903Swnj } 2704903Swnj sballoc(sb, m); 2714903Swnj *np = m; 2724903Swnj n = m; 2734903Swnj np = &n->m_next; 2744903Swnj m = m->m_next; 2754903Swnj } 2764903Swnj } 2774903Swnj 2785169Swnj /* 2795169Swnj * Append data and address. 2805169Swnj * Return 0 if no space in sockbuf or if 2815169Swnj * can't get mbuf to stuff address in. 2825169Swnj */ 2834928Swnj sbappendaddr(sb, asa, m0) 2844928Swnj struct sockbuf *sb; 2854928Swnj struct sockaddr *asa; 2864928Swnj struct mbuf *m0; 2874928Swnj { 2884928Swnj struct sockaddr *msa; 2894928Swnj register struct mbuf *m; 2904928Swnj register int len = sizeof (struct sockaddr); 2914928Swnj 2925042Swnj m = m0; 2935042Swnj if (m == 0) 2945042Swnj panic("sbappendaddr"); 2955042Swnj for (;;) { 2964928Swnj len += m->m_len; 2975042Swnj if (m->m_next == 0) { 2985042Swnj m->m_act = (struct mbuf *)1; 2995042Swnj break; 3005042Swnj } 3015042Swnj m = m->m_next; 3025042Swnj } 3035043Swnj if (len > sbspace(sb)) 3044928Swnj return (0); 3054928Swnj m = m_get(0); 3065043Swnj if (m == 0) 3074928Swnj return (0); 3084928Swnj m->m_off = MMINOFF; 3094928Swnj m->m_len = sizeof (struct sockaddr); 3104928Swnj msa = mtod(m, struct sockaddr *); 3114928Swnj *msa = *asa; 3124928Swnj m->m_act = (struct mbuf *)1; 3134928Swnj sbappend(sb, m); 3144928Swnj sbappend(sb, m0); 3154928Swnj return (1); 3164928Swnj } 3174928Swnj 3184903Swnj /* 3194903Swnj * Free all mbufs on a sockbuf mbuf chain. 3204903Swnj * Check that resource allocations return to 0. 3214903Swnj */ 3224903Swnj sbflush(sb) 3234903Swnj struct sockbuf *sb; 3244903Swnj { 3254903Swnj 3264903Swnj if (sb->sb_flags & SB_LOCK) 3274903Swnj panic("sbflush"); 3284903Swnj sbdrop(sb, sb->sb_cc); 3294903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 3304903Swnj panic("sbflush 2"); 3314903Swnj } 3324903Swnj 3334903Swnj /* 3344903Swnj * Drop data from (the front of) a sockbuf chain. 3354903Swnj */ 3364903Swnj sbdrop(sb, len) 3374903Swnj register struct sockbuf *sb; 3384903Swnj register int len; 3394903Swnj { 3404903Swnj register struct mbuf *m = sb->sb_mb, *mn; 3414903Swnj 3424903Swnj while (len > 0) { 3434903Swnj if (m == 0) 3444903Swnj panic("sbdrop"); 3455064Swnj if (m->m_len > len) { 3464903Swnj m->m_len -= len; 3474903Swnj m->m_off += len; 3484903Swnj sb->sb_cc -= len; 3494903Swnj break; 3504903Swnj } 3515064Swnj len -= m->m_len; 3525064Swnj sbfree(sb, m); 3535064Swnj MFREE(m, mn); 3545064Swnj m = mn; 3554903Swnj } 3564903Swnj sb->sb_mb = m; 3574903Swnj } 358