1 /* uipc_socket.c 4.17 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 "../h/stat.h" 16 #include "../net/in.h" 17 #include "../net/in_systm.h" 18 19 /* 20 * Socket support routines. 21 * 22 * DEAL WITH INTERRUPT NOTIFICATION. 23 */ 24 25 /* 26 * Create a socket. 27 */ 28 socreate(aso, type, asp, asa, options) 29 struct socket **aso; 30 int type; 31 struct sockproto *asp; 32 struct sockaddr *asa; 33 int options; 34 { 35 register struct protosw *prp; 36 register struct socket *so; 37 struct mbuf *m; 38 int pf, proto, error; 39 COUNT(SOCREATE); 40 41 /* 42 * Use process standard protocol/protocol family if none 43 * specified by address argument. 44 */ 45 if (asp == 0) { 46 pf = PF_INET; /* should be u.u_protof */ 47 proto = 0; 48 } else { 49 pf = asp->sp_family; 50 proto = asp->sp_protocol; 51 } 52 53 /* 54 * If protocol specified, look for it, otherwise 55 * for a protocol of the correct type in the right family. 56 */ 57 if (proto) 58 prp = pffindproto(pf, proto); 59 else 60 prp = pffindtype(pf, type); 61 if (prp == 0) 62 return (EPROTONOSUPPORT); 63 64 /* 65 * Get a socket structure. 66 */ 67 m = m_getclr(M_WAIT); 68 if (m == 0) 69 return (ENOBUFS); 70 so = mtod(m, struct socket *); 71 so->so_options = options; 72 73 /* 74 * Attach protocol to socket, initializing 75 * and reserving resources. 76 */ 77 so->so_proto = prp; 78 error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 79 if (error) { 80 (void) m_free(dtom(so)); 81 return (error); 82 } 83 *aso = so; 84 return (0); 85 } 86 87 sofree(so) 88 struct socket *so; 89 { 90 91 COUNT(SOFREE); 92 if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) 93 return; 94 sbrelease(&so->so_snd); 95 sbrelease(&so->so_rcv); 96 (void) m_free(dtom(so)); 97 } 98 99 /* 100 * Close a socket on last file table reference removal. 101 * Initiate disconnect if connected. 102 * Free socket when disconnect complete. 103 */ 104 soclose(so) 105 register struct socket *so; 106 { 107 int s = splnet(); /* conservative */ 108 109 COUNT(SOCLOSE); 110 if (so->so_pcb == 0) 111 goto discard; 112 printf("soclose %x state %x\n", so, so->so_state); 113 if (so->so_state & SS_ISCONNECTED) { 114 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 115 u.u_error = sodisconnect(so, (struct sockaddr *)0); 116 if (u.u_error) { 117 printf("soclose disconnect error %d\n", u.u_error); 118 splx(s); 119 return; 120 } 121 } 122 if ((so->so_state & SS_ISDISCONNECTING) && 123 (so->so_options & SO_NBIO)) { 124 u.u_error = EINPROGRESS; 125 splx(s); 126 return; 127 } 128 while (so->so_state & SS_ISCONNECTED) { 129 printf("sleeping until not connected\n"); 130 sleep((caddr_t)&so->so_timeo, PZERO+1); 131 } 132 } 133 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 134 discard: 135 so->so_state |= SS_USERGONE; 136 sofree(so); 137 splx(s); 138 } 139 140 sosplice(pso, so) 141 struct socket *pso, *so; 142 { 143 144 COUNT(SOSPLICE); 145 if (pso->so_proto->pr_family != PF_UNIX) { 146 struct socket *tso; 147 tso = pso; pso = so; so = tso; 148 } 149 if (pso->so_proto->pr_family != PF_UNIX) 150 return (EOPNOTSUPP); 151 /* check types and buffer space */ 152 /* merge buffers */ 153 return (0); 154 } 155 156 /*ARGSUSED*/ 157 sostat(so, sb) 158 struct socket *so; 159 struct stat *sb; 160 { 161 162 COUNT(SOSTAT); 163 return (EOPNOTSUPP); 164 } 165 166 /* 167 * Accept connection on a socket. 168 */ 169 soaccept(so, asa) 170 struct socket *so; 171 struct sockaddr *asa; 172 { 173 int s = splnet(); 174 int error; 175 176 COUNT(SOACCEPT); 177 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 178 error = EISCONN; 179 goto bad; 180 } 181 if ((so->so_options & SO_ACCEPTCONN) == 0) { 182 error = EINVAL; /* XXX */ 183 goto bad; 184 } 185 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 186 printf("PRU_ACCEPT returns error %d\n", error); 187 bad: 188 splx(s); 189 return (error); 190 } 191 192 /* 193 * Connect socket to a specified address. 194 * If already connected or connecting, then avoid 195 * the protocol entry, to keep its job simpler. 196 */ 197 soconnect(so, asa) 198 struct socket *so; 199 struct sockaddr *asa; 200 { 201 int s = splnet(); 202 int error; 203 204 COUNT(SOCONNECT); 205 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 206 error = EISCONN; 207 goto bad; 208 } 209 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 210 bad: 211 splx(s); 212 return (error); 213 } 214 215 /* 216 * Disconnect from a socket. 217 * Address parameter is from system call for later multicast 218 * protocols. Check to make sure that connected and no disconnect 219 * in progress (for protocol's sake), and then invoke protocol. 220 */ 221 sodisconnect(so, asa) 222 struct socket *so; 223 struct sockaddr *asa; 224 { 225 int s = splnet(); 226 int error; 227 228 COUNT(SODISCONNECT); 229 if ((so->so_state & SS_ISCONNECTED) == 0) { 230 error = ENOTCONN; 231 goto bad; 232 } 233 if (so->so_state & SS_ISDISCONNECTING) { 234 error = EALREADY; 235 goto bad; 236 } 237 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 238 bad: 239 splx(s); 240 return (error); 241 } 242 243 /* 244 * Send on a socket. 245 * If send must go all at once and message is larger than 246 * send buffering, then hard error. 247 * Lock against other senders. 248 * If must go all at once and not enough room now, then 249 * inform user that this would block and do nothing. 250 */ 251 sosend(so, asa) 252 register struct socket *so; 253 struct sockaddr *asa; 254 { 255 struct mbuf *top = 0; 256 register struct mbuf *m, **mp = ⊤ 257 register u_int len; 258 int error = 0, space, s; 259 260 COUNT(SOSEND); 261 if (so->so_state & SS_CANTSENDMORE) 262 return (EPIPE); 263 if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 264 return (EMSGSIZE); 265 if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_options & SO_NBIO)) 266 return (EWOULDBLOCK); 267 sblock(&so->so_snd); 268 #define snderr(errno) { error = errno; splx(s); goto release; } 269 270 s = splnet(); 271 again: 272 if (so->so_error) { 273 error = so->so_error; 274 so->so_error = 0; 275 splx(s); 276 goto release; 277 } 278 if ((so->so_state & SS_ISCONNECTED) == 0) { 279 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 280 snderr(ENOTCONN); 281 if (asa == 0) 282 snderr(EDESTADDRREQ); 283 } 284 if (top) { 285 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 286 if (error) { 287 splx(s); 288 goto release; 289 } 290 top = 0; 291 mp = ⊤ 292 } 293 if (u.u_count == 0) { 294 splx(s); 295 goto release; 296 } 297 space = sbspace(&so->so_snd); 298 if (space == 0 || sosendallatonce(so) && space < u.u_count) { 299 if (so->so_options & SO_NBIO) 300 snderr(EWOULDBLOCK); 301 sbunlock(&so->so_snd); 302 sbwait(&so->so_snd); 303 splx(s); 304 goto again; 305 } 306 splx(s); 307 while (u.u_count && space > 0) { 308 MGET(m, 1); 309 if (m == NULL) { 310 error = ENOBUFS; 311 m_freem(top); 312 goto release; 313 } 314 if (u.u_count >= CLBYTES && space >= CLBYTES) { 315 register struct mbuf *p; 316 MCLGET(p, 1); 317 if (p == 0) 318 goto nopages; 319 m->m_off = (int)p - (int)m; 320 len = CLBYTES; 321 } else { 322 nopages: 323 m->m_off = MMINOFF; 324 len = MIN(MLEN, u.u_count); 325 } 326 iomove(mtod(m, caddr_t), len, B_WRITE); 327 m->m_len = len; 328 *mp = m; 329 mp = &m->m_next; 330 space = sbspace(&so->so_snd); 331 } 332 s = splnet(); 333 goto again; 334 335 release: 336 sbunlock(&so->so_snd); 337 return (error); 338 } 339 340 soreceive(so, asa) 341 register struct socket *so; 342 struct sockaddr *asa; 343 { 344 register struct mbuf *m, *n; 345 u_int len; 346 int eor, s, error = 0; 347 348 COUNT(SORECEIVE); 349 restart: 350 sblock(&so->so_rcv); 351 s = splnet(); 352 353 #define rcverr(errno) { error = errno; splx(s); goto release; } 354 if (so->so_rcv.sb_cc == 0) { 355 if (so->so_error) { 356 error = so->so_error; 357 so->so_error = 0; 358 splx(s); 359 goto release; 360 } 361 if (so->so_state & SS_CANTRCVMORE) { 362 splx(s); 363 goto release; 364 } 365 if ((so->so_state & SS_ISCONNECTED) == 0 && 366 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 367 rcverr(ENOTCONN); 368 if (so->so_options & SO_NBIO) 369 rcverr(EWOULDBLOCK); 370 sbunlock(&so->so_rcv); 371 sbwait(&so->so_rcv); 372 splx(s); 373 goto restart; 374 } 375 m = so->so_rcv.sb_mb; 376 if (m == 0) 377 panic("receive"); 378 if (so->so_proto->pr_flags & PR_ADDR) { 379 if (m->m_len != sizeof (struct sockaddr)) 380 panic("soreceive addr"); 381 if (asa) 382 bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 383 so->so_rcv.sb_cc -= m->m_len; 384 so->so_rcv.sb_mbcnt -= MSIZE; 385 m = m_free(m); 386 if (m == 0) 387 panic("receive 2"); 388 so->so_rcv.sb_mb = m; 389 } 390 eor = 0; 391 do { 392 len = MIN(m->m_len, u.u_count); 393 if (len == m->m_len) { 394 eor = (int)m->m_act; 395 sbfree(&so->so_rcv, m); 396 } 397 splx(s); 398 iomove(mtod(m, caddr_t), len, B_READ); 399 s = splnet(); 400 if (len == m->m_len) { 401 MFREE(m, n); 402 so->so_rcv.sb_mb = n; 403 } else { 404 m->m_off += len; 405 m->m_len -= len; 406 so->so_rcv.sb_cc -= len; 407 } 408 } while ((m = so->so_rcv.sb_mb) && u.u_count && !eor); 409 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 410 do { 411 if (m == 0) 412 panic("receive 3"); 413 sbfree(&so->so_rcv, m); 414 eor = (int)m->m_act; 415 so->so_rcv.sb_mb = m->m_next; 416 MFREE(m, n); 417 m = n; 418 } while (eor == 0); 419 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 420 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 421 release: 422 sbunlock(&so->so_rcv); 423 splx(s); 424 return (error); 425 } 426 427 /*ARGSUSED*/ 428 soioctl(so, cmd, cmdp) 429 register struct socket *so; 430 int cmd; 431 register caddr_t cmdp; 432 { 433 434 COUNT(SOIOCTL); 435 switch (cmdp) { 436 437 } 438 switch (so->so_type) { 439 440 case SOCK_STREAM: 441 break; 442 443 case SOCK_DGRAM: 444 break; 445 446 case SOCK_RDM: 447 break; 448 449 case SOCK_RAW: 450 break; 451 452 } 453 } 454