1*4917Swnj /* uipc_socket2.c 4.2 81/11/16 */ 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/protocol.h" 134903Swnj #include "../h/protosw.h" 144903Swnj #include "../h/socket.h" 154903Swnj #include "../h/socketvar.h" 164903Swnj #include "../h/inaddr.h" 174903Swnj #include "../net/inet.h" 184903Swnj #include "../net/inet_systm.h" 194903Swnj 204903Swnj /* 214903Swnj * Primitive routines for operating on sockets and socket buffers 224903Swnj */ 234903Swnj 244903Swnj /* 254903Swnj * Procedures to manipulate state flags of socket 264903Swnj * and do appropriate wakeups. 274903Swnj */ 284903Swnj soisconnecting(so) 294903Swnj struct socket *so; 304903Swnj { 314903Swnj 324903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 334903Swnj so->so_state |= SS_ISCONNECTING; 344903Swnj wakeup((caddr_t)&so->so_timeo); 354903Swnj } 364903Swnj 374903Swnj soisconnected(so) 384903Swnj struct socket *so; 394903Swnj { 404903Swnj 414903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 424903Swnj so->so_state |= SS_ISCONNECTED; 434903Swnj wakeup((caddr_t)&so->so_timeo); 444903Swnj } 454903Swnj 464903Swnj soisdisconnecting(so) 474903Swnj struct socket *so; 484903Swnj { 494903Swnj 504903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISCONNECTING); 514903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 524903Swnj wakeup((caddr_t)&so->so_timeo); 534903Swnj } 544903Swnj 554903Swnj soisdisconnected(so) 564903Swnj struct socket *so; 574903Swnj { 584903Swnj 594903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 604903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 614903Swnj wakeup((caddr_t)&so->so_timeo); 624903Swnj sowwakeup(so); 634903Swnj sorwakeup(so); 644903Swnj } 654903Swnj 66*4917Swnj socantsendmore(so) 67*4917Swnj struct socket *so; 68*4917Swnj { 69*4917Swnj 70*4917Swnj so->so_state |= SS_CANTSENDMORE; 71*4917Swnj sowwakeup(so); 72*4917Swnj } 73*4917Swnj 74*4917Swnj socantrcvmore(so) 75*4917Swnj struct socket *so; 76*4917Swnj { 77*4917Swnj 78*4917Swnj so->so_state |= SS_CANTRCVMORE; 79*4917Swnj sorwakeup(so); 80*4917Swnj } 81*4917Swnj 824903Swnj /* 834903Swnj * Select a socket. 844903Swnj */ 854903Swnj soselect(so, flag) 864903Swnj register struct socket *so; 874903Swnj int flag; 884903Swnj { 894903Swnj 904903Swnj if (flag & FREAD) { 914903Swnj if (soreadable(so)) 924903Swnj return (1); 934903Swnj sbselqueue(&so->so_rcv); 944903Swnj } 954903Swnj if (flag & FWRITE) { 964903Swnj if (sowriteable(so)) 974903Swnj return (1); 984903Swnj sbselqueue(&so->so_snd); 994903Swnj } 1004903Swnj return (0); 1014903Swnj } 1024903Swnj 1034903Swnj /* 1044903Swnj * Queue a process for a select on a socket buffer. 1054903Swnj */ 1064903Swnj sbselqueue(sb) 1074903Swnj struct sockbuf *sb; 1084903Swnj { 1094903Swnj register struct proc *p; 1104903Swnj 111*4917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 1124903Swnj sb->sb_flags |= SB_COLL; 1134903Swnj else 1144903Swnj sb->sb_sel = u.u_procp; 1154903Swnj } 1164903Swnj 1174903Swnj /* 118*4917Swnj * Wait for data to arrive at/drain from a socket buffer. 119*4917Swnj */ 120*4917Swnj sbwait(sb) 121*4917Swnj struct sockbuf *sb; 122*4917Swnj { 123*4917Swnj 124*4917Swnj sb->sb_flags |= SB_WAIT; 125*4917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 126*4917Swnj } 127*4917Swnj 128*4917Swnj /* 1294903Swnj * Wakeup processes waiting on a socket buffer. 1304903Swnj */ 1314903Swnj sbwakeup(sb) 1324903Swnj struct sockbuf *sb; 1334903Swnj { 1344903Swnj 1354903Swnj if (sb->sb_sel) { 1364903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 1374903Swnj sb->sb_sel = 0; 1384903Swnj sb->sb_flags &= ~SB_COLL; 1394903Swnj } 1404903Swnj if (sb->sb_flags & SB_WAIT) { 1414903Swnj sb->sb_flags &= ~SB_WAIT; 1424903Swnj wakeup((caddr_t)sb->sb_cc); 1434903Swnj } 1444903Swnj } 1454903Swnj 1464903Swnj /* 1474903Swnj * Allot mbufs to a sockbuf. 1484903Swnj */ 1494903Swnj sbreserve(sb, cc) 1504903Swnj struct sockbuf *sb; 1514903Swnj { 1524903Swnj 1534903Swnj if (m_reserve(cc) == 0) 1544903Swnj return (0); 1554903Swnj sb->sb_cc = cc; 1564903Swnj sb->sb_mbcnt = (cc*2)/MSIZE; 157*4917Swnj return (1); 1584903Swnj } 1594903Swnj 1604903Swnj /* 1614903Swnj * Free mbufs held by a socket, and reserved mbuf space. 1624903Swnj */ 1634903Swnj sbrelease(sb) 1644903Swnj struct sockbuf *sb; 1654903Swnj { 1664903Swnj 1674903Swnj sbflush(sb); 1684903Swnj m_release(sb->sb_cc); 1694903Swnj sb->sb_cc = sb->sb_mbcnt = 0; 1704903Swnj } 1714903Swnj 1724903Swnj /* 1734903Swnj * Routines to add (at the end) and remove (from the beginning) 1744903Swnj * data from a mbuf queue. 1754903Swnj */ 1764903Swnj 1774903Swnj /* 1784903Swnj * Append mbuf queue m to sockbuf sb. 1794903Swnj */ 1804903Swnj sbappend(sb, m) 1814903Swnj register struct mbuf *m; 1824903Swnj register struct sockbuf *sb; 1834903Swnj { 1844903Swnj register struct mbuf **np, *n; 1854903Swnj 1864903Swnj np = &sb->sb_mb; 1874903Swnj while ((n = *np) && n->m_next) 1884903Swnj np = &n->m_next; 1894903Swnj while (m) { 1904903Swnj if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 1914903Swnj (int)n->m_act == 0 && (int)m->m_act == 0 && 1924903Swnj (n->m_off + n->m_len + m->m_off) <= MMAXOFF) { 193*4917Swnj bcopy(mtod(m, caddr_t), mtod(n, caddr_t), 194*4917Swnj (unsigned)m->m_len); 1954903Swnj n->m_len += m->m_len; 1964903Swnj sb->sb_cc += m->m_len; 1974903Swnj m = m_free(m); 1984903Swnj continue; 1994903Swnj } 2004903Swnj sballoc(sb, m); 2014903Swnj *np = m; 2024903Swnj n = m; 2034903Swnj np = &n->m_next; 2044903Swnj m = m->m_next; 2054903Swnj } 2064903Swnj } 2074903Swnj 2084903Swnj /* 2094903Swnj * Free all mbufs on a sockbuf mbuf chain. 2104903Swnj * Check that resource allocations return to 0. 2114903Swnj */ 2124903Swnj sbflush(sb) 2134903Swnj struct sockbuf *sb; 2144903Swnj { 2154903Swnj 2164903Swnj if (sb->sb_flags & SB_LOCK) 2174903Swnj panic("sbflush"); 2184903Swnj sbdrop(sb, sb->sb_cc); 2194903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 2204903Swnj panic("sbflush 2"); 2214903Swnj } 2224903Swnj 2234903Swnj /* 2244903Swnj * Drop data from (the front of) a sockbuf chain. 2254903Swnj */ 2264903Swnj sbdrop(sb, len) 2274903Swnj register struct sockbuf *sb; 2284903Swnj register int len; 2294903Swnj { 2304903Swnj register struct mbuf *m = sb->sb_mb, *mn; 2314903Swnj 2324903Swnj while (len > 0) { 2334903Swnj if (m == 0) 2344903Swnj panic("sbdrop"); 2354903Swnj if (m->m_len <= len) { 2364903Swnj len -= m->m_len; 2374903Swnj sbfree(sb, m); 2384903Swnj MFREE(m, mn); 2394903Swnj m = mn; 2404903Swnj } else { 2414903Swnj m->m_len -= len; 2424903Swnj m->m_off += len; 2434903Swnj sb->sb_cc -= len; 2444903Swnj break; 2454903Swnj } 2464903Swnj } 2474903Swnj sb->sb_mb = m; 2484903Swnj } 2494903Swnj 2504903Swnj struct mbuf * 251*4917Swnj sbcopy(sb, off, len) 2524903Swnj struct sockbuf *sb; 2534903Swnj int off; 2544903Swnj register int len; 2554903Swnj { 2564903Swnj register struct mbuf *m, *n, **np; 2574903Swnj struct mbuf *top, *p; 2584903Swnj COUNT(SB_COPY); 2594903Swnj 2604903Swnj if (len == 0) 2614903Swnj return (0); 2624903Swnj if (off < 0 || len < 0) 2634903Swnj panic("sb_copy"); 2644903Swnj m = sb->sb_mb; 2654903Swnj while (off > 0) { 2664903Swnj if (m == 0) 2674903Swnj panic("sb_copy"); 2684903Swnj if (off < m->m_len) 2694903Swnj break; 2704903Swnj off -= m->m_len; 2714903Swnj m = m->m_next; 2724903Swnj } 2734903Swnj np = ⊤ 2744903Swnj top = 0; 2754903Swnj while (len > 0) { 2764903Swnj MGET(n, 1); 2774903Swnj *np = n; 2784903Swnj if (n == 0) 2794903Swnj goto nospace; 2804903Swnj if (m == 0) 2814903Swnj panic("sb_copy"); 2824903Swnj n->m_len = MIN(len, m->m_len - off); 2834903Swnj if (m->m_off > MMAXOFF) { 2844903Swnj p = mtod(m, struct mbuf *); 2854903Swnj n->m_off = ((int)p - (int)n) + off; 2864903Swnj mprefcnt[mtopf(p)]++; 2874903Swnj } else { 2884903Swnj n->m_off = MMINOFF; 2894903Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 290*4917Swnj (unsigned)n->m_len); 2914903Swnj } 2924903Swnj len -= n->m_len; 2934903Swnj off = 0; 2944903Swnj m = m->m_next; 2954903Swnj np = &n->m_next; 2964903Swnj } 2974903Swnj return (top); 2984903Swnj nospace: 2994903Swnj printf("snd_copy: no space\n"); 3004903Swnj m_freem(top); 3014903Swnj return (0); 3024903Swnj } 303