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