1*5578Swnj /* uipc_socket2.c 4.19 82/01/19 */ 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); 56*5578Swnj sorwakeup(so); 57*5578Swnj sowwakeup(so); 584903Swnj } 594903Swnj 604903Swnj soisdisconnecting(so) 614903Swnj struct socket *so; 624903Swnj { 634903Swnj 645248Sroot so->so_state &= ~SS_ISCONNECTING; 654903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 664903Swnj wakeup((caddr_t)&so->so_timeo); 675170Swnj sowwakeup(so); 685169Swnj sorwakeup(so); 694903Swnj } 704903Swnj 714903Swnj soisdisconnected(so) 724903Swnj struct socket *so; 734903Swnj { 744903Swnj 754903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 764903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 774903Swnj wakeup((caddr_t)&so->so_timeo); 784903Swnj sowwakeup(so); 794903Swnj sorwakeup(so); 804903Swnj } 814903Swnj 825169Swnj /* 835169Swnj * Socantsendmore indicates that no more data will be sent on the 845169Swnj * socket; it would normally be applied to a socket when the user 855169Swnj * informs the system that no more data is to be sent, by the protocol 865169Swnj * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 875169Swnj * will be received, and will normally be applied to the socket by a 885169Swnj * protocol when it detects that the peer will send no more data. 895169Swnj * Data queued for reading in the socket may yet be read. 905169Swnj */ 915169Swnj 924917Swnj socantsendmore(so) 934917Swnj struct socket *so; 944917Swnj { 954917Swnj 964917Swnj so->so_state |= SS_CANTSENDMORE; 974917Swnj sowwakeup(so); 984917Swnj } 994917Swnj 1004917Swnj socantrcvmore(so) 1014917Swnj struct socket *so; 1024917Swnj { 1034917Swnj 1044917Swnj so->so_state |= SS_CANTRCVMORE; 1054917Swnj sorwakeup(so); 1064917Swnj } 1074917Swnj 1084903Swnj /* 1095169Swnj * Socket select/wakeup routines. 1104903Swnj */ 1115169Swnj 1125169Swnj /* 1135169Swnj * Interface routine to select() system 1145169Swnj * call for sockets. 1155169Swnj */ 1165577Swnj soselect(so, rw) 1174903Swnj register struct socket *so; 1185577Swnj int rw; 1194903Swnj { 120*5578Swnj int s = splnet(); 1214903Swnj 1225577Swnj switch (rw) { 1235577Swnj 1245577Swnj case FREAD: 125*5578Swnj if (soreadable(so)) { 126*5578Swnj splx(s); 1274903Swnj return (1); 128*5578Swnj } 1294903Swnj sbselqueue(&so->so_rcv); 1305577Swnj break; 1315577Swnj 1325577Swnj case FWRITE: 133*5578Swnj if (sowriteable(so)) { 134*5578Swnj splx(s); 1354903Swnj return (1); 136*5578Swnj } 1374903Swnj sbselqueue(&so->so_snd); 1385577Swnj break; 1394903Swnj } 140*5578Swnj splx(s); 1414903Swnj return (0); 1424903Swnj } 1434903Swnj 1444903Swnj /* 1454903Swnj * Queue a process for a select on a socket buffer. 1464903Swnj */ 1474903Swnj sbselqueue(sb) 1484903Swnj struct sockbuf *sb; 1494903Swnj { 1504903Swnj register struct proc *p; 1514903Swnj 1524917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 1534903Swnj sb->sb_flags |= SB_COLL; 1544903Swnj else 1554903Swnj sb->sb_sel = u.u_procp; 1564903Swnj } 1574903Swnj 1584903Swnj /* 1594917Swnj * Wait for data to arrive at/drain from a socket buffer. 1604917Swnj */ 1614917Swnj sbwait(sb) 1624917Swnj struct sockbuf *sb; 1634917Swnj { 1644917Swnj 1654917Swnj sb->sb_flags |= SB_WAIT; 1664917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 1674917Swnj } 1684917Swnj 1694917Swnj /* 1704903Swnj * Wakeup processes waiting on a socket buffer. 1714903Swnj */ 1724903Swnj sbwakeup(sb) 1734903Swnj struct sockbuf *sb; 1744903Swnj { 1754903Swnj 1764903Swnj if (sb->sb_sel) { 1774903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 1784903Swnj sb->sb_sel = 0; 1794903Swnj sb->sb_flags &= ~SB_COLL; 1804903Swnj } 1814903Swnj if (sb->sb_flags & SB_WAIT) { 1824903Swnj sb->sb_flags &= ~SB_WAIT; 1835013Swnj wakeup((caddr_t)&sb->sb_cc); 1844903Swnj } 1854903Swnj } 1864903Swnj 1874903Swnj /* 1885169Swnj * Socket buffer (struct sockbuf) utility routines. 1895169Swnj * 1905169Swnj * Each socket contains two socket buffers: one for sending data and 1915169Swnj * one for receiving data. Each buffer contains a queue of mbufs, 1925169Swnj * information about the number of mbufs and amount of data in the 1935169Swnj * queue, and other fields allowing select() statements and notification 1945169Swnj * on data availability to be implemented. 1955169Swnj * 1965169Swnj * Before using a new socket structure it is first necessary to reserve 1975169Swnj * buffer space to the socket, by calling sbreserve. This commits 1985169Swnj * some of the available buffer space in the system buffer pool for the 1995169Swnj * socket. The space should be released by calling sbrelease when the 2005169Swnj * socket is destroyed. 2015169Swnj * 2025169Swnj * The routine sbappend() is normally called to append new mbufs 2035169Swnj * to a socket buffer, after checking that adequate space is available 2045169Swnj * comparing the function spspace() with the amount of data to be added. 2055169Swnj * Data is normally removed from a socket buffer in a protocol by 2065169Swnj * first calling m_copy on the socket buffer mbuf chain and sending this 2075169Swnj * to a peer, and then removing the data from the socket buffer with 2085169Swnj * sbdrop when the data is acknowledged by the peer (or immediately 2095170Swnj * in the case of unreliable protocols.) 2105169Swnj * 2115169Swnj * Protocols which do not require connections place both source address 2125169Swnj * and data information in socket buffer queues. The source addresses 2135169Swnj * are stored in single mbufs after each data item, and are easily found 2145169Swnj * as the data items are all marked with end of record markers. The 2155169Swnj * sbappendaddr() routine stores a datum and associated address in 2165169Swnj * a socket buffer. Note that, unlike sbappend(), this routine checks 2175169Swnj * for the caller that there will be enough space to store the data. 2185169Swnj * It fails if there is not enough space, or if it cannot find 2195169Swnj * a mbuf to store the address in. 2205169Swnj * 2215169Swnj * The higher-level routines sosend and soreceive (in socket.c) 2225170Swnj * also add data to, and remove data from socket buffers repectively. 2235169Swnj */ 2245169Swnj 2255169Swnj /* 2264903Swnj * Allot mbufs to a sockbuf. 2274903Swnj */ 2284903Swnj sbreserve(sb, cc) 2294903Swnj struct sockbuf *sb; 2304903Swnj { 2314903Swnj 2325015Sroot if (m_reserve((cc*2)/MSIZE) == 0) 2334903Swnj return (0); 2344980Swnj sb->sb_hiwat = cc; 2355042Swnj sb->sb_mbmax = cc*2; 2364917Swnj return (1); 2374903Swnj } 2384903Swnj 2394903Swnj /* 2404903Swnj * Free mbufs held by a socket, and reserved mbuf space. 2414903Swnj */ 2424903Swnj sbrelease(sb) 2434903Swnj struct sockbuf *sb; 2444903Swnj { 2454903Swnj 2464903Swnj sbflush(sb); 2475019Swnj m_release(sb->sb_mbmax/MSIZE); 2484980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 2494903Swnj } 2504903Swnj 2514903Swnj /* 2524903Swnj * Routines to add (at the end) and remove (from the beginning) 2534903Swnj * data from a mbuf queue. 2544903Swnj */ 2554903Swnj 2564903Swnj /* 2574903Swnj * Append mbuf queue m to sockbuf sb. 2584903Swnj */ 2594903Swnj sbappend(sb, m) 2604903Swnj register struct mbuf *m; 2614903Swnj register struct sockbuf *sb; 2624903Swnj { 2634903Swnj register struct mbuf **np, *n; 2644903Swnj 2654903Swnj np = &sb->sb_mb; 2665013Swnj n = 0; 2675013Swnj while (*np) { 2685013Swnj n = *np; 2694903Swnj np = &n->m_next; 2705013Swnj } 2714903Swnj while (m) { 2725266Swnj if (m->m_len == 0 && (int)m->m_act == 0) { 2735304Sroot m = m_free(m); 2745266Swnj continue; 2755266Swnj } 2764903Swnj if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 2774903Swnj (int)n->m_act == 0 && (int)m->m_act == 0 && 2785042Swnj (n->m_off + n->m_len + m->m_len) <= MMAXOFF) { 2795042Swnj bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 2804917Swnj (unsigned)m->m_len); 2814903Swnj n->m_len += m->m_len; 2824903Swnj sb->sb_cc += m->m_len; 2834903Swnj m = m_free(m); 2844903Swnj continue; 2854903Swnj } 2864903Swnj sballoc(sb, m); 2874903Swnj *np = m; 2884903Swnj n = m; 2894903Swnj np = &n->m_next; 2904903Swnj m = m->m_next; 2914903Swnj } 2924903Swnj } 2934903Swnj 2945169Swnj /* 2955169Swnj * Append data and address. 2965169Swnj * Return 0 if no space in sockbuf or if 2975169Swnj * can't get mbuf to stuff address in. 2985169Swnj */ 2994928Swnj sbappendaddr(sb, asa, m0) 3004928Swnj struct sockbuf *sb; 3014928Swnj struct sockaddr *asa; 3024928Swnj struct mbuf *m0; 3034928Swnj { 3044928Swnj struct sockaddr *msa; 3054928Swnj register struct mbuf *m; 3064928Swnj register int len = sizeof (struct sockaddr); 3074928Swnj 3085042Swnj m = m0; 3095042Swnj if (m == 0) 3105042Swnj panic("sbappendaddr"); 3115042Swnj for (;;) { 3124928Swnj len += m->m_len; 3135042Swnj if (m->m_next == 0) { 3145042Swnj m->m_act = (struct mbuf *)1; 3155042Swnj break; 3165042Swnj } 3175042Swnj m = m->m_next; 3185042Swnj } 3195043Swnj if (len > sbspace(sb)) 3204928Swnj return (0); 3214928Swnj m = m_get(0); 3225043Swnj if (m == 0) 3234928Swnj return (0); 3244928Swnj m->m_off = MMINOFF; 3254928Swnj m->m_len = sizeof (struct sockaddr); 3264928Swnj msa = mtod(m, struct sockaddr *); 3274928Swnj *msa = *asa; 3284928Swnj m->m_act = (struct mbuf *)1; 3294928Swnj sbappend(sb, m); 3304928Swnj sbappend(sb, m0); 3314928Swnj return (1); 3324928Swnj } 3334928Swnj 3344903Swnj /* 3354903Swnj * Free all mbufs on a sockbuf mbuf chain. 3364903Swnj * Check that resource allocations return to 0. 3374903Swnj */ 3384903Swnj sbflush(sb) 3394903Swnj struct sockbuf *sb; 3404903Swnj { 3414903Swnj 3424903Swnj if (sb->sb_flags & SB_LOCK) 3434903Swnj panic("sbflush"); 3445266Swnj if (sb->sb_cc) 3455266Swnj sbdrop(sb, sb->sb_cc); 3464903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 3474903Swnj panic("sbflush 2"); 3484903Swnj } 3494903Swnj 3504903Swnj /* 3514903Swnj * Drop data from (the front of) a sockbuf chain. 3524903Swnj */ 3534903Swnj sbdrop(sb, len) 3544903Swnj register struct sockbuf *sb; 3554903Swnj register int len; 3564903Swnj { 3574903Swnj register struct mbuf *m = sb->sb_mb, *mn; 3584903Swnj 3594903Swnj while (len > 0) { 3604903Swnj if (m == 0) 3614903Swnj panic("sbdrop"); 3625064Swnj if (m->m_len > len) { 3634903Swnj m->m_len -= len; 3644903Swnj m->m_off += len; 3654903Swnj sb->sb_cc -= len; 3664903Swnj break; 3674903Swnj } 3685064Swnj len -= m->m_len; 3695064Swnj sbfree(sb, m); 3705064Swnj MFREE(m, mn); 3715064Swnj m = mn; 3724903Swnj } 3734903Swnj sb->sb_mb = m; 3744903Swnj } 3755266Swnj 3765266Swnj /* 3775266Swnj printm(m) 3785266Swnj struct mbuf *m; 3795266Swnj { 3805266Swnj 3815266Swnj printf("<"); 3825266Swnj while (m) { 3835266Swnj printf("%d,", m->m_len); 3845266Swnj m = m->m_next; 3855266Swnj } 3865266Swnj printf(">"); 3875266Swnj printf("\n"); 3885266Swnj } 3895266Swnj */ 390