1 /* uipc_socket2.c 4.14 81/12/12 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/proc.h" 8 #include "../h/file.h" 9 #include "../h/inode.h" 10 #include "../h/buf.h" 11 #include "../h/mbuf.h" 12 #include "../h/protosw.h" 13 #include "../h/socket.h" 14 #include "../h/socketvar.h" 15 #include "../net/in.h" 16 #include "../net/in_systm.h" 17 18 /* 19 * Primitive routines for operating on sockets and socket buffers 20 */ 21 22 /* 23 * Procedures to manipulate state flags of socket 24 * and do appropriate wakeups. Normal sequence is that 25 * soisconnecting() is called during processing of connect() call, 26 * resulting in an eventual call to soisconnected() if/when the 27 * connection is established. When the connection is torn down 28 * soisdisconnecting() is called during processing of disconnect() call, 29 * and soisdisconnected() is called when the connection to the peer 30 * is totally severed. The semantics of these routines are such that 31 * connectionless protocols can call soisconnected() and soisdisconnected() 32 * only, bypassing the in-progress calls when setting up a ``connection'' 33 * takes no time. 34 * 35 * When higher level protocols are implemented in 36 * the kernel, the wakeups done here will sometimes 37 * be implemented as software-interrupt process scheduling. 38 */ 39 40 soisconnecting(so) 41 struct socket *so; 42 { 43 44 printf("soisconnecting %x\n", so); 45 so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 46 so->so_state |= SS_ISCONNECTING; 47 wakeup((caddr_t)&so->so_timeo); 48 } 49 50 soisconnected(so) 51 struct socket *so; 52 { 53 54 printf("soisconnected %x\n", so); 55 so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 56 so->so_state |= SS_ISCONNECTED; 57 wakeup((caddr_t)&so->so_timeo); 58 } 59 60 soisdisconnecting(so) 61 struct socket *so; 62 { 63 64 printf("soisdisconnecting %x\n", so); 65 so->so_state &= ~SS_ISCONNECTING; 66 so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); 67 wakeup((caddr_t)&so->so_timeo); 68 sowwakeup(so); 69 sorwakeup(so); 70 } 71 72 soisdisconnected(so) 73 struct socket *so; 74 { 75 76 printf("soisdisconnected %x\n", so); 77 so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 78 so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 79 wakeup((caddr_t)&so->so_timeo); 80 sowwakeup(so); 81 sorwakeup(so); 82 } 83 84 /* 85 * Socantsendmore indicates that no more data will be sent on the 86 * socket; it would normally be applied to a socket when the user 87 * informs the system that no more data is to be sent, by the protocol 88 * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data 89 * will be received, and will normally be applied to the socket by a 90 * protocol when it detects that the peer will send no more data. 91 * Data queued for reading in the socket may yet be read. 92 */ 93 94 socantsendmore(so) 95 struct socket *so; 96 { 97 98 so->so_state |= SS_CANTSENDMORE; 99 sowwakeup(so); 100 } 101 102 socantrcvmore(so) 103 struct socket *so; 104 { 105 106 so->so_state |= SS_CANTRCVMORE; 107 sorwakeup(so); 108 } 109 110 /* 111 * Socket select/wakeup routines. 112 */ 113 114 /* 115 * Interface routine to select() system 116 * call for sockets. 117 */ 118 soselect(so, flag) 119 register struct socket *so; 120 int flag; 121 { 122 123 if (flag & FREAD) { 124 if (soreadable(so)) 125 return (1); 126 sbselqueue(&so->so_rcv); 127 } 128 if (flag & FWRITE) { 129 if (sowriteable(so)) 130 return (1); 131 sbselqueue(&so->so_snd); 132 } 133 return (0); 134 } 135 136 /* 137 * Queue a process for a select on a socket buffer. 138 */ 139 sbselqueue(sb) 140 struct sockbuf *sb; 141 { 142 register struct proc *p; 143 144 if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) 145 sb->sb_flags |= SB_COLL; 146 else 147 sb->sb_sel = u.u_procp; 148 } 149 150 /* 151 * Wait for data to arrive at/drain from a socket buffer. 152 */ 153 sbwait(sb) 154 struct sockbuf *sb; 155 { 156 157 sb->sb_flags |= SB_WAIT; 158 sleep((caddr_t)&sb->sb_cc, PZERO+1); 159 } 160 161 /* 162 * Wakeup processes waiting on a socket buffer. 163 */ 164 sbwakeup(sb) 165 struct sockbuf *sb; 166 { 167 168 if (sb->sb_sel) { 169 selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 170 sb->sb_sel = 0; 171 sb->sb_flags &= ~SB_COLL; 172 } 173 if (sb->sb_flags & SB_WAIT) { 174 sb->sb_flags &= ~SB_WAIT; 175 wakeup((caddr_t)&sb->sb_cc); 176 } 177 } 178 179 /* 180 * Socket buffer (struct sockbuf) utility routines. 181 * 182 * Each socket contains two socket buffers: one for sending data and 183 * one for receiving data. Each buffer contains a queue of mbufs, 184 * information about the number of mbufs and amount of data in the 185 * queue, and other fields allowing select() statements and notification 186 * on data availability to be implemented. 187 * 188 * Before using a new socket structure it is first necessary to reserve 189 * buffer space to the socket, by calling sbreserve. This commits 190 * some of the available buffer space in the system buffer pool for the 191 * socket. The space should be released by calling sbrelease when the 192 * socket is destroyed. 193 * 194 * The routine sbappend() is normally called to append new mbufs 195 * to a socket buffer, after checking that adequate space is available 196 * comparing the function spspace() with the amount of data to be added. 197 * Data is normally removed from a socket buffer in a protocol by 198 * first calling m_copy on the socket buffer mbuf chain and sending this 199 * to a peer, and then removing the data from the socket buffer with 200 * sbdrop when the data is acknowledged by the peer (or immediately 201 * in the case of unreliable protocols.) 202 * 203 * Protocols which do not require connections place both source address 204 * and data information in socket buffer queues. The source addresses 205 * are stored in single mbufs after each data item, and are easily found 206 * as the data items are all marked with end of record markers. The 207 * sbappendaddr() routine stores a datum and associated address in 208 * a socket buffer. Note that, unlike sbappend(), this routine checks 209 * for the caller that there will be enough space to store the data. 210 * It fails if there is not enough space, or if it cannot find 211 * a mbuf to store the address in. 212 * 213 * The higher-level routines sosend and soreceive (in socket.c) 214 * also add data to, and remove data from socket buffers repectively. 215 */ 216 217 /* 218 * Allot mbufs to a sockbuf. 219 */ 220 sbreserve(sb, cc) 221 struct sockbuf *sb; 222 { 223 224 if (m_reserve((cc*2)/MSIZE) == 0) 225 return (0); 226 sb->sb_hiwat = cc; 227 sb->sb_mbmax = cc*2; 228 return (1); 229 } 230 231 /* 232 * Free mbufs held by a socket, and reserved mbuf space. 233 */ 234 sbrelease(sb) 235 struct sockbuf *sb; 236 { 237 238 sbflush(sb); 239 m_release(sb->sb_mbmax/MSIZE); 240 sb->sb_hiwat = sb->sb_mbmax = 0; 241 } 242 243 /* 244 * Routines to add (at the end) and remove (from the beginning) 245 * data from a mbuf queue. 246 */ 247 248 /* 249 * Append mbuf queue m to sockbuf sb. 250 */ 251 sbappend(sb, m) 252 register struct mbuf *m; 253 register struct sockbuf *sb; 254 { 255 register struct mbuf **np, *n; 256 257 np = &sb->sb_mb; 258 n = 0; 259 while (*np) { 260 n = *np; 261 np = &n->m_next; 262 } 263 while (m) { 264 if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 265 (int)n->m_act == 0 && (int)m->m_act == 0 && 266 (n->m_off + n->m_len + m->m_len) <= MMAXOFF) { 267 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 268 (unsigned)m->m_len); 269 n->m_len += m->m_len; 270 sb->sb_cc += m->m_len; 271 m = m_free(m); 272 continue; 273 } 274 sballoc(sb, m); 275 *np = m; 276 n = m; 277 np = &n->m_next; 278 m = m->m_next; 279 } 280 } 281 282 /* 283 * Append data and address. 284 * Return 0 if no space in sockbuf or if 285 * can't get mbuf to stuff address in. 286 */ 287 sbappendaddr(sb, asa, m0) 288 struct sockbuf *sb; 289 struct sockaddr *asa; 290 struct mbuf *m0; 291 { 292 struct sockaddr *msa; 293 register struct mbuf *m; 294 register int len = sizeof (struct sockaddr); 295 296 m = m0; 297 if (m == 0) 298 panic("sbappendaddr"); 299 for (;;) { 300 len += m->m_len; 301 if (m->m_next == 0) { 302 m->m_act = (struct mbuf *)1; 303 break; 304 } 305 m = m->m_next; 306 } 307 if (len > sbspace(sb)) 308 return (0); 309 m = m_get(0); 310 if (m == 0) 311 return (0); 312 m->m_off = MMINOFF; 313 m->m_len = sizeof (struct sockaddr); 314 msa = mtod(m, struct sockaddr *); 315 *msa = *asa; 316 m->m_act = (struct mbuf *)1; 317 sbappend(sb, m); 318 sbappend(sb, m0); 319 return (1); 320 } 321 322 /* 323 * Free all mbufs on a sockbuf mbuf chain. 324 * Check that resource allocations return to 0. 325 */ 326 sbflush(sb) 327 struct sockbuf *sb; 328 { 329 330 if (sb->sb_flags & SB_LOCK) 331 panic("sbflush"); 332 sbdrop(sb, sb->sb_cc); 333 if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 334 panic("sbflush 2"); 335 } 336 337 /* 338 * Drop data from (the front of) a sockbuf chain. 339 */ 340 sbdrop(sb, len) 341 register struct sockbuf *sb; 342 register int len; 343 { 344 register struct mbuf *m = sb->sb_mb, *mn; 345 346 while (len > 0) { 347 if (m == 0) 348 panic("sbdrop"); 349 if (m->m_len > len) { 350 m->m_len -= len; 351 m->m_off += len; 352 sb->sb_cc -= len; 353 break; 354 } 355 len -= m->m_len; 356 sbfree(sb, m); 357 MFREE(m, mn); 358 m = mn; 359 } 360 sb->sb_mb = m; 361 } 362