1*4903Swnj /* uipc_socket2.c 4.1 81/11/15 */ 2*4903Swnj 3*4903Swnj #include "../h/param.h" 4*4903Swnj #include "../h/systm.h" 5*4903Swnj #include "../h/dir.h" 6*4903Swnj #include "../h/user.h" 7*4903Swnj #include "../h/proc.h" 8*4903Swnj #include "../h/file.h" 9*4903Swnj #include "../h/inode.h" 10*4903Swnj #include "../h/buf.h" 11*4903Swnj #include "../h/mbuf.h" 12*4903Swnj #include "../h/protocol.h" 13*4903Swnj #include "../h/protosw.h" 14*4903Swnj #include "../h/socket.h" 15*4903Swnj #include "../h/socketvar.h" 16*4903Swnj #include "../h/inaddr.h" 17*4903Swnj #include "../net/inet.h" 18*4903Swnj #include "../net/inet_systm.h" 19*4903Swnj 20*4903Swnj /* 21*4903Swnj * Primitive routines for operating on sockets and socket buffers 22*4903Swnj */ 23*4903Swnj 24*4903Swnj /* 25*4903Swnj * Procedures to manipulate state flags of socket 26*4903Swnj * and do appropriate wakeups. 27*4903Swnj */ 28*4903Swnj soisconnecting(so) 29*4903Swnj struct socket *so; 30*4903Swnj { 31*4903Swnj 32*4903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 33*4903Swnj so->so_state |= SS_ISCONNECTING; 34*4903Swnj wakeup((caddr_t)&so->so_timeo); 35*4903Swnj } 36*4903Swnj 37*4903Swnj soisconnected(so) 38*4903Swnj struct socket *so; 39*4903Swnj { 40*4903Swnj 41*4903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 42*4903Swnj so->so_state |= SS_ISCONNECTED; 43*4903Swnj wakeup((caddr_t)&so->so_timeo); 44*4903Swnj } 45*4903Swnj 46*4903Swnj soisdisconnecting(so) 47*4903Swnj struct socket *so; 48*4903Swnj { 49*4903Swnj 50*4903Swnj so->so_state &= ~(SS_ISCONNECTED|SS_ISCONNECTING); 51*4903Swnj so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 52*4903Swnj wakeup((caddr_t)&so->so_timeo); 53*4903Swnj } 54*4903Swnj 55*4903Swnj soisdisconnected(so) 56*4903Swnj struct socket *so; 57*4903Swnj { 58*4903Swnj 59*4903Swnj so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 60*4903Swnj so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 61*4903Swnj wakeup((caddr_t)&so->so_timeo); 62*4903Swnj sowwakeup(so); 63*4903Swnj sorwakeup(so); 64*4903Swnj } 65*4903Swnj 66*4903Swnj /* 67*4903Swnj * Select a socket. 68*4903Swnj */ 69*4903Swnj soselect(so, flag) 70*4903Swnj register struct socket *so; 71*4903Swnj int flag; 72*4903Swnj { 73*4903Swnj 74*4903Swnj if (flag & FREAD) { 75*4903Swnj if (soreadable(so)) 76*4903Swnj return (1); 77*4903Swnj sbselqueue(&so->so_rcv); 78*4903Swnj } 79*4903Swnj if (flag & FWRITE) { 80*4903Swnj if (sowriteable(so)) 81*4903Swnj return (1); 82*4903Swnj sbselqueue(&so->so_snd); 83*4903Swnj } 84*4903Swnj return (0); 85*4903Swnj } 86*4903Swnj 87*4903Swnj /* 88*4903Swnj * Queue a process for a select on a socket buffer. 89*4903Swnj */ 90*4903Swnj sbselqueue(sb) 91*4903Swnj struct sockbuf *sb; 92*4903Swnj { 93*4903Swnj register struct proc *p; 94*4903Swnj 95*4903Swnj if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)select) 96*4903Swnj sb->sb_flags |= SB_COLL; 97*4903Swnj else 98*4903Swnj sb->sb_sel = u.u_procp; 99*4903Swnj } 100*4903Swnj 101*4903Swnj /* 102*4903Swnj * Wakeup processes waiting on a socket buffer. 103*4903Swnj */ 104*4903Swnj sbwakeup(sb) 105*4903Swnj struct sockbuf *sb; 106*4903Swnj { 107*4903Swnj 108*4903Swnj if (sb->sb_sel) { 109*4903Swnj selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 110*4903Swnj sb->sb_sel = 0; 111*4903Swnj sb->sb_flags &= ~SB_COLL; 112*4903Swnj } 113*4903Swnj if (sb->sb_flags & SB_WAIT) { 114*4903Swnj sb->sb_flags &= ~SB_WAIT; 115*4903Swnj wakeup((caddr_t)sb->sb_cc); 116*4903Swnj } 117*4903Swnj } 118*4903Swnj 119*4903Swnj /* 120*4903Swnj * Allot mbufs to a sockbuf. 121*4903Swnj */ 122*4903Swnj sbreserve(sb, cc) 123*4903Swnj struct sockbuf *sb; 124*4903Swnj { 125*4903Swnj 126*4903Swnj if (m_reserve(cc) == 0) 127*4903Swnj return (0); 128*4903Swnj sb->sb_cc = cc; 129*4903Swnj sb->sb_mbcnt = (cc*2)/MSIZE; 130*4903Swnj } 131*4903Swnj 132*4903Swnj /* 133*4903Swnj * Free mbufs held by a socket, and reserved mbuf space. 134*4903Swnj */ 135*4903Swnj sbrelease(sb) 136*4903Swnj struct sockbuf *sb; 137*4903Swnj { 138*4903Swnj 139*4903Swnj sbflush(sb); 140*4903Swnj m_release(sb->sb_cc); 141*4903Swnj sb->sb_cc = sb->sb_mbcnt = 0; 142*4903Swnj } 143*4903Swnj 144*4903Swnj /* 145*4903Swnj * Routines to add (at the end) and remove (from the beginning) 146*4903Swnj * data from a mbuf queue. 147*4903Swnj */ 148*4903Swnj 149*4903Swnj /* 150*4903Swnj * Append mbuf queue m to sockbuf sb. 151*4903Swnj */ 152*4903Swnj sbappend(sb, m) 153*4903Swnj register struct mbuf *m; 154*4903Swnj register struct sockbuf *sb; 155*4903Swnj { 156*4903Swnj register struct mbuf **np, *n; 157*4903Swnj 158*4903Swnj np = &sb->sb_mb; 159*4903Swnj while ((n = *np) && n->m_next) 160*4903Swnj np = &n->m_next; 161*4903Swnj while (m) { 162*4903Swnj if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 163*4903Swnj (int)n->m_act == 0 && (int)m->m_act == 0 && 164*4903Swnj (n->m_off + n->m_len + m->m_off) <= MMAXOFF) { 165*4903Swnj bcopy(mtod(m, caddr_t), mtod(n, caddr_t), m->m_len); 166*4903Swnj n->m_len += m->m_len; 167*4903Swnj sb->sb_cc += m->m_len; 168*4903Swnj m = m_free(m); 169*4903Swnj continue; 170*4903Swnj } 171*4903Swnj sballoc(sb, m); 172*4903Swnj *np = m; 173*4903Swnj n = m; 174*4903Swnj np = &n->m_next; 175*4903Swnj m = m->m_next; 176*4903Swnj } 177*4903Swnj } 178*4903Swnj 179*4903Swnj /* 180*4903Swnj * Free all mbufs on a sockbuf mbuf chain. 181*4903Swnj * Check that resource allocations return to 0. 182*4903Swnj */ 183*4903Swnj sbflush(sb) 184*4903Swnj struct sockbuf *sb; 185*4903Swnj { 186*4903Swnj 187*4903Swnj if (sb->sb_flags & SB_LOCK) 188*4903Swnj panic("sbflush"); 189*4903Swnj sbdrop(sb, sb->sb_cc); 190*4903Swnj if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 191*4903Swnj panic("sbflush 2"); 192*4903Swnj } 193*4903Swnj 194*4903Swnj /* 195*4903Swnj * Drop data from (the front of) a sockbuf chain. 196*4903Swnj */ 197*4903Swnj sbdrop(sb, len) 198*4903Swnj register struct sockbuf *sb; 199*4903Swnj register int len; 200*4903Swnj { 201*4903Swnj register struct mbuf *m = sb->sb_mb, *mn; 202*4903Swnj 203*4903Swnj while (len > 0) { 204*4903Swnj if (m == 0) 205*4903Swnj panic("sbdrop"); 206*4903Swnj if (m->m_len <= len) { 207*4903Swnj len -= m->m_len; 208*4903Swnj sbfree(sb, m); 209*4903Swnj MFREE(m, mn); 210*4903Swnj m = mn; 211*4903Swnj } else { 212*4903Swnj m->m_len -= len; 213*4903Swnj m->m_off += len; 214*4903Swnj sb->sb_cc -= len; 215*4903Swnj break; 216*4903Swnj } 217*4903Swnj } 218*4903Swnj sb->sb_mb = m; 219*4903Swnj } 220*4903Swnj 221*4903Swnj struct mbuf * 222*4903Swnj sb_copy(sb, off, len) 223*4903Swnj struct sockbuf *sb; 224*4903Swnj int off; 225*4903Swnj register int len; 226*4903Swnj { 227*4903Swnj register struct mbuf *m, *n, **np; 228*4903Swnj struct mbuf *top, *p; 229*4903Swnj COUNT(SB_COPY); 230*4903Swnj 231*4903Swnj if (len == 0) 232*4903Swnj return (0); 233*4903Swnj if (off < 0 || len < 0) 234*4903Swnj panic("sb_copy"); 235*4903Swnj m = sb->sb_mb; 236*4903Swnj while (off > 0) { 237*4903Swnj if (m == 0) 238*4903Swnj panic("sb_copy"); 239*4903Swnj if (off < m->m_len) 240*4903Swnj break; 241*4903Swnj off -= m->m_len; 242*4903Swnj m = m->m_next; 243*4903Swnj } 244*4903Swnj np = ⊤ 245*4903Swnj top = 0; 246*4903Swnj while (len > 0) { 247*4903Swnj MGET(n, 1); 248*4903Swnj *np = n; 249*4903Swnj if (n == 0) 250*4903Swnj goto nospace; 251*4903Swnj if (m == 0) 252*4903Swnj panic("sb_copy"); 253*4903Swnj n->m_len = MIN(len, m->m_len - off); 254*4903Swnj if (m->m_off > MMAXOFF) { 255*4903Swnj p = mtod(m, struct mbuf *); 256*4903Swnj n->m_off = ((int)p - (int)n) + off; 257*4903Swnj mprefcnt[mtopf(p)]++; 258*4903Swnj } else { 259*4903Swnj n->m_off = MMINOFF; 260*4903Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 261*4903Swnj n->m_len); 262*4903Swnj } 263*4903Swnj len -= n->m_len; 264*4903Swnj off = 0; 265*4903Swnj m = m->m_next; 266*4903Swnj np = &n->m_next; 267*4903Swnj } 268*4903Swnj return (top); 269*4903Swnj nospace: 270*4903Swnj printf("snd_copy: no space\n"); 271*4903Swnj m_freem(top); 272*4903Swnj return (0); 273*4903Swnj } 274