1*5013Swnj /* uipc_socket2.c 4.5 81/11/21 */ 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" 154903Swnj #include "../net/inet.h" 164903Swnj #include "../net/inet_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 244903Swnj * and do appropriate wakeups. 254903Swnj */ 264903Swnj soisconnecting(so) 274903Swnj struct socket *so; 284903Swnj { 294903Swnj 304903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 314903Swnj so->so_state |= SS_ISCONNECTING; 324903Swnj wakeup((caddr_t)&so->so_timeo); 334903Swnj } 344903Swnj 354903Swnj soisconnected(so) 364903Swnj struct socket *so; 374903Swnj { 384903Swnj 394903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 404903Swnj so->so_state |= SS_ISCONNECTED; 414903Swnj wakeup((caddr_t)&so->so_timeo); 424903Swnj } 434903Swnj 444903Swnj soisdisconnecting(so) 454903Swnj struct socket *so; 464903Swnj { 474903Swnj 484903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISCONNECTING); 494903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 504903Swnj wakeup((caddr_t)&so->so_timeo); 514903Swnj } 524903Swnj 534903Swnj soisdisconnected(so) 544903Swnj struct socket *so; 554903Swnj { 564903Swnj 574903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 584903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 594903Swnj wakeup((caddr_t)&so->so_timeo); 604903Swnj sowwakeup(so); 614903Swnj sorwakeup(so); 624903Swnj } 634903Swnj 644917Swnj socantsendmore(so) 654917Swnj struct socket *so; 664917Swnj { 674917Swnj 684917Swnj so->so_state |= SS_CANTSENDMORE; 694917Swnj sowwakeup(so); 704917Swnj } 714917Swnj 724917Swnj socantrcvmore(so) 734917Swnj struct socket *so; 744917Swnj { 754917Swnj 764917Swnj so->so_state |= SS_CANTRCVMORE; 774917Swnj sorwakeup(so); 784917Swnj } 794917Swnj 804903Swnj /* 814903Swnj * Select a socket. 824903Swnj */ 834903Swnj soselect(so, flag) 844903Swnj register struct socket *so; 854903Swnj int flag; 864903Swnj { 874903Swnj 884903Swnj if (flag & FREAD) { 894903Swnj if (soreadable(so)) 904903Swnj return (1); 914903Swnj sbselqueue(&so->so_rcv); 924903Swnj } 934903Swnj if (flag & FWRITE) { 944903Swnj if (sowriteable(so)) 954903Swnj return (1); 964903Swnj sbselqueue(&so->so_snd); 974903Swnj } 984903Swnj return (0); 994903Swnj } 1004903Swnj 1014903Swnj /* 1024903Swnj * Queue a process for a select on a socket buffer. 1034903Swnj */ 1044903Swnj sbselqueue(sb) 1054903Swnj struct sockbuf *sb; 1064903Swnj { 1074903Swnj register struct proc *p; 1084903Swnj 1094917Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 1104903Swnj sb->sb_flags |= SB_COLL; 1114903Swnj else 1124903Swnj sb->sb_sel = u.u_procp; 1134903Swnj } 1144903Swnj 1154903Swnj /* 1164917Swnj * Wait for data to arrive at/drain from a socket buffer. 1174917Swnj */ 1184917Swnj sbwait(sb) 1194917Swnj struct sockbuf *sb; 1204917Swnj { 1214917Swnj 1224917Swnj sb->sb_flags |= SB_WAIT; 1234917Swnj sleep((caddr_t)&sb->sb_cc, PZERO+1); 1244917Swnj } 1254917Swnj 1264917Swnj /* 1274903Swnj * Wakeup processes waiting on a socket buffer. 1284903Swnj */ 1294903Swnj sbwakeup(sb) 1304903Swnj struct sockbuf *sb; 1314903Swnj { 1324903Swnj 1334903Swnj if (sb->sb_sel) { 1344903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 1354903Swnj sb->sb_sel = 0; 1364903Swnj sb->sb_flags &= ~SB_COLL; 1374903Swnj } 1384903Swnj if (sb->sb_flags & SB_WAIT) { 1394903Swnj sb->sb_flags &= ~SB_WAIT; 140*5013Swnj wakeup((caddr_t)&sb->sb_cc); 1414903Swnj } 1424903Swnj } 1434903Swnj 1444903Swnj /* 1454903Swnj * Allot mbufs to a sockbuf. 1464903Swnj */ 1474903Swnj sbreserve(sb, cc) 1484903Swnj struct sockbuf *sb; 1494903Swnj { 1504903Swnj 1514903Swnj if (m_reserve(cc) == 0) 1524903Swnj return (0); 1534980Swnj sb->sb_hiwat = cc; 1544980Swnj sb->sb_mbmax = (cc*2)/MSIZE; 1554917Swnj return (1); 1564903Swnj } 1574903Swnj 1584903Swnj /* 1594903Swnj * Free mbufs held by a socket, and reserved mbuf space. 1604903Swnj */ 1614903Swnj sbrelease(sb) 1624903Swnj struct sockbuf *sb; 1634903Swnj { 1644903Swnj 1654903Swnj sbflush(sb); 1664980Swnj m_release(sb->sb_hiwat); 1674980Swnj sb->sb_hiwat = sb->sb_mbmax = 0; 1684903Swnj } 1694903Swnj 1704903Swnj /* 1714903Swnj * Routines to add (at the end) and remove (from the beginning) 1724903Swnj * data from a mbuf queue. 1734903Swnj */ 1744903Swnj 1754903Swnj /* 1764903Swnj * Append mbuf queue m to sockbuf sb. 1774903Swnj */ 1784903Swnj sbappend(sb, m) 1794903Swnj register struct mbuf *m; 1804903Swnj register struct sockbuf *sb; 1814903Swnj { 1824903Swnj register struct mbuf **np, *n; 1834903Swnj 1844903Swnj np = &sb->sb_mb; 185*5013Swnj n = 0; 186*5013Swnj while (*np) { 187*5013Swnj n = *np; 1884903Swnj np = &n->m_next; 189*5013Swnj } 1904903Swnj while (m) { 1914903Swnj if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 1924903Swnj (int)n->m_act == 0 && (int)m->m_act == 0 && 1934903Swnj (n->m_off + n->m_len + m->m_off) <= MMAXOFF) { 1944917Swnj bcopy(mtod(m, caddr_t), mtod(n, caddr_t), 1954917Swnj (unsigned)m->m_len); 1964903Swnj n->m_len += m->m_len; 1974903Swnj sb->sb_cc += m->m_len; 1984903Swnj m = m_free(m); 1994903Swnj continue; 2004903Swnj } 2014903Swnj sballoc(sb, m); 2024903Swnj *np = m; 2034903Swnj n = m; 2044903Swnj np = &n->m_next; 2054903Swnj m = m->m_next; 2064903Swnj } 2074903Swnj } 2084903Swnj 2094928Swnj sbappendaddr(sb, asa, m0) 2104928Swnj struct sockbuf *sb; 2114928Swnj struct sockaddr *asa; 2124928Swnj struct mbuf *m0; 2134928Swnj { 2144928Swnj struct sockaddr *msa; 2154928Swnj register struct mbuf *m; 2164928Swnj register int len = sizeof (struct sockaddr); 2174928Swnj 2184928Swnj for (m = m0; m; m = m->m_next) 2194928Swnj len += m->m_len; 2204928Swnj if (len > sbspace(sb)) 2214928Swnj return (0); 2224928Swnj m = m_get(0); 2234928Swnj if (m == 0) 2244928Swnj return (0); 2254928Swnj m->m_off = MMINOFF; 2264928Swnj m->m_len = sizeof (struct sockaddr); 2274928Swnj msa = mtod(m, struct sockaddr *); 2284928Swnj *msa = *asa; 2294928Swnj m->m_act = (struct mbuf *)1; 2304928Swnj sbappend(sb, m); 2314928Swnj m0->m_act = (struct mbuf *)1; 2324928Swnj sbappend(sb, m0); 2334928Swnj return (1); 2344928Swnj } 2354928Swnj 2364903Swnj /* 2374903Swnj * Free all mbufs on a sockbuf mbuf chain. 2384903Swnj * Check that resource allocations return to 0. 2394903Swnj */ 2404903Swnj sbflush(sb) 2414903Swnj struct sockbuf *sb; 2424903Swnj { 2434903Swnj 2444903Swnj if (sb->sb_flags & SB_LOCK) 2454903Swnj panic("sbflush"); 2464903Swnj sbdrop(sb, sb->sb_cc); 2474903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 2484903Swnj panic("sbflush 2"); 2494903Swnj } 2504903Swnj 2514903Swnj /* 2524903Swnj * Drop data from (the front of) a sockbuf chain. 2534903Swnj */ 2544903Swnj sbdrop(sb, len) 2554903Swnj register struct sockbuf *sb; 2564903Swnj register int len; 2574903Swnj { 2584903Swnj register struct mbuf *m = sb->sb_mb, *mn; 2594903Swnj 2604903Swnj while (len > 0) { 2614903Swnj if (m == 0) 2624903Swnj panic("sbdrop"); 2634903Swnj if (m->m_len <= len) { 2644903Swnj len -= m->m_len; 2654903Swnj sbfree(sb, m); 2664903Swnj MFREE(m, mn); 2674903Swnj m = mn; 2684903Swnj } else { 2694903Swnj m->m_len -= len; 2704903Swnj m->m_off += len; 2714903Swnj sb->sb_cc -= len; 2724903Swnj break; 2734903Swnj } 2744903Swnj } 2754903Swnj sb->sb_mb = m; 2764903Swnj } 277