1 /* uipc_socket.c 4.47 82/08/14 */ 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 "../h/ioctl.h" 17 #include "../net/in.h" 18 #include "../net/in_systm.h" 19 #include "../net/route.h" 20 #include "../h/uio.h" 21 22 /* 23 * Socket support routines. 24 * 25 * DEAL WITH INTERRUPT NOTIFICATION. 26 */ 27 28 /* 29 * Create a socket. 30 */ 31 socreate(aso, type, asp, asa, options) 32 struct socket **aso; 33 int type; 34 struct sockproto *asp; 35 struct sockaddr *asa; 36 int options; 37 { 38 register struct protosw *prp; 39 register struct socket *so; 40 struct mbuf *m; 41 int pf, proto, error; 42 43 /* 44 * Use process standard protocol/protocol family if none 45 * specified by address argument. 46 */ 47 if (asp == 0) { 48 pf = PF_INET; /* should be u.u_protof */ 49 proto = 0; 50 } else { 51 pf = asp->sp_family; 52 proto = asp->sp_protocol; 53 } 54 55 /* 56 * If protocol specified, look for it, otherwise 57 * for a protocol of the correct type in the right family. 58 */ 59 if (proto) 60 prp = pffindproto(pf, proto); 61 else 62 prp = pffindtype(pf, type); 63 if (prp == 0) 64 return (EPROTONOSUPPORT); 65 66 /* 67 * Get a socket structure. 68 */ 69 m = m_getclr(M_WAIT); 70 if (m == 0) 71 return (ENOBUFS); 72 so = mtod(m, struct socket *); 73 so->so_options = options; 74 if (options & SO_ACCEPTCONN) { 75 so->so_q = so; 76 so->so_q0 = so; 77 so->so_qlimit = (so->so_options & SO_NEWFDONCONN) ? 5 : 1; 78 } 79 so->so_state = 0; 80 if (u.u_uid == 0) 81 so->so_state = SS_PRIV; 82 83 /* 84 * Attach protocol to socket, initializing 85 * and reserving resources. 86 */ 87 so->so_proto = prp; 88 error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 89 if (error) { 90 so->so_state |= SS_NOFDREF; 91 sofree(so); 92 return (error); 93 } 94 *aso = so; 95 return (0); 96 } 97 98 sofree(so) 99 struct socket *so; 100 { 101 102 if (so->so_head) { 103 if (!soqremque(so, 0) && !soqremque(so, 1)) 104 panic("sofree dq"); 105 so->so_head = 0; 106 } 107 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 108 return; 109 sbrelease(&so->so_snd); 110 sbrelease(&so->so_rcv); 111 (void) m_free(dtom(so)); 112 } 113 114 /* 115 * Close a socket on last file table reference removal. 116 * Initiate disconnect if connected. 117 * Free socket when disconnect complete. 118 */ 119 soclose(so, exiting) 120 register struct socket *so; 121 int exiting; 122 { 123 int s = splnet(); /* conservative */ 124 register struct socket *so2; 125 126 if (so->so_options & SO_ACCEPTCONN) { 127 while (so->so_q0 != so) 128 soclose(so->so_q0, 1); 129 while (so->so_q != so) 130 soclose(so->so_q, 1); 131 } 132 if (so->so_pcb == 0) 133 goto discard; 134 if (exiting) 135 so->so_options |= SO_KEEPALIVE; 136 if (so->so_state & SS_ISCONNECTED) { 137 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 138 u.u_error = sodisconnect(so, (struct sockaddr *)0); 139 if (u.u_error) { 140 if (exiting) 141 goto drop; 142 splx(s); 143 return; 144 } 145 } 146 if ((so->so_options & SO_DONTLINGER) == 0) { 147 if ((so->so_state & SS_ISDISCONNECTING) && 148 (so->so_state & SS_NBIO) && 149 exiting == 0) { 150 u.u_error = EINPROGRESS; 151 splx(s); 152 return; 153 } 154 /* should use tsleep here, for at most linger */ 155 while (so->so_state & SS_ISCONNECTED) 156 sleep((caddr_t)&so->so_timeo, PZERO+1); 157 } 158 } 159 drop: 160 if (so->so_pcb) { 161 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 162 if (exiting == 0 && u.u_error) { 163 splx(s); 164 return; 165 } 166 } 167 discard: 168 so->so_state |= SS_NOFDREF; 169 sofree(so); 170 splx(s); 171 } 172 173 /*ARGSUSED*/ 174 sostat(so, sb) 175 struct socket *so; 176 struct stat *sb; 177 { 178 179 bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 180 return (0); /* XXX */ 181 } 182 183 /* 184 * Accept connection on a socket. 185 */ 186 soaccept(so, asa) 187 struct socket *so; 188 struct sockaddr *asa; 189 { 190 int s = splnet(); 191 int error; 192 193 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 194 splx(s); 195 return (error); 196 } 197 198 /* 199 * Connect socket to a specified address. 200 * If already connected or connecting, then avoid 201 * the protocol entry, to keep its job simpler. 202 */ 203 soconnect(so, asa) 204 struct socket *so; 205 struct sockaddr *asa; 206 { 207 int s = splnet(); 208 int error; 209 210 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 211 error = EISCONN; 212 goto bad; 213 } 214 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 215 bad: 216 splx(s); 217 return (error); 218 } 219 220 /* 221 * Disconnect from a socket. 222 * Address parameter is from system call for later multicast 223 * protocols. Check to make sure that connected and no disconnect 224 * in progress (for protocol's sake), and then invoke protocol. 225 */ 226 sodisconnect(so, asa) 227 struct socket *so; 228 struct sockaddr *asa; 229 { 230 int s = splnet(); 231 int error; 232 233 if ((so->so_state & SS_ISCONNECTED) == 0) { 234 error = ENOTCONN; 235 goto bad; 236 } 237 if (so->so_state & SS_ISDISCONNECTING) { 238 error = EALREADY; 239 goto bad; 240 } 241 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 242 bad: 243 splx(s); 244 return (error); 245 } 246 247 /* 248 * Send on a socket. 249 * If send must go all at once and message is larger than 250 * send buffering, then hard error. 251 * Lock against other senders. 252 * If must go all at once and not enough room now, then 253 * inform user that this would block and do nothing. 254 */ 255 sosend(so, asa) 256 register struct socket *so; 257 struct sockaddr *asa; 258 { 259 struct mbuf *top = 0; 260 register struct mbuf *m, **mp = ⊤ 261 register u_int len; 262 int error = 0, space, s; 263 264 if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 265 return (EMSGSIZE); 266 #ifdef notdef 267 /* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING */ 268 if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 269 return (EWOULDBLOCK); 270 #endif 271 restart: 272 sblock(&so->so_snd); 273 #define snderr(errno) { error = errno; splx(s); goto release; } 274 275 again: 276 s = splnet(); 277 if (so->so_state & SS_CANTSENDMORE) { 278 psignal(u.u_procp, SIGPIPE); 279 snderr(EPIPE); 280 } 281 if (so->so_error) { 282 error = so->so_error; 283 so->so_error = 0; /* ??? */ 284 splx(s); 285 goto release; 286 } 287 if ((so->so_state & SS_ISCONNECTED) == 0) { 288 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 289 snderr(ENOTCONN); 290 if (asa == 0) 291 snderr(EDESTADDRREQ); 292 } 293 if (top) { 294 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 295 top = 0; 296 if (error) { 297 splx(s); 298 goto release; 299 } 300 mp = ⊤ 301 } 302 if (u.u_count == 0) { 303 splx(s); 304 goto release; 305 } 306 space = sbspace(&so->so_snd); 307 if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 308 if (so->so_state & SS_NBIO) 309 snderr(EWOULDBLOCK); 310 sbunlock(&so->so_snd); 311 sbwait(&so->so_snd); 312 splx(s); 313 goto restart; 314 } 315 splx(s); 316 while (u.u_count && space > 0) { 317 MGET(m, 1); 318 if (m == NULL) { 319 error = ENOBUFS; /* SIGPIPE? */ 320 goto release; 321 } 322 if (u.u_count >= CLBYTES && space >= CLBYTES) { 323 register struct mbuf *p; 324 MCLGET(p, 1); 325 if (p == 0) 326 goto nopages; 327 m->m_off = (int)p - (int)m; 328 len = CLBYTES; 329 } else { 330 nopages: 331 m->m_off = MMINOFF; 332 len = MIN(MLEN, u.u_count); 333 } 334 iomove(mtod(m, caddr_t), len, B_WRITE); 335 m->m_len = len; 336 *mp = m; 337 mp = &m->m_next; 338 space = sbspace(&so->so_snd); 339 } 340 goto again; 341 342 release: 343 sbunlock(&so->so_snd); 344 if (top) 345 m_freem(top); 346 return (error); 347 } 348 349 soreceive(so, asa, uio) 350 register struct socket *so; 351 struct sockaddr *asa; 352 struct uio *uio; 353 { 354 register struct iovec *iov; 355 register struct mbuf *m, *n; 356 u_int len; 357 int eor, s, error = 0, resid = uio->uio_resid; 358 int cnt; 359 360 restart: 361 sblock(&so->so_rcv); 362 s = splnet(); 363 364 #define rcverr(errno) { error = errno; splx(s); goto release; } 365 if (so->so_rcv.sb_cc == 0) { 366 if (so->so_error) { 367 error = so->so_error; 368 so->so_error = 0; 369 splx(s); 370 goto release; 371 } 372 if (so->so_state & SS_CANTRCVMORE) { 373 splx(s); 374 goto release; 375 } 376 if ((so->so_state & SS_ISCONNECTED) == 0 && 377 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 378 rcverr(ENOTCONN); 379 if (so->so_state & SS_NBIO) 380 rcverr(EWOULDBLOCK); 381 sbunlock(&so->so_rcv); 382 sbwait(&so->so_rcv); 383 splx(s); 384 goto restart; 385 } 386 m = so->so_rcv.sb_mb; 387 if (m == 0) 388 panic("receive"); 389 if (so->so_proto->pr_flags & PR_ADDR) { 390 if (m->m_len != sizeof (struct sockaddr)) 391 panic("soreceive addr"); 392 if (asa) 393 bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 394 so->so_rcv.sb_cc -= m->m_len; 395 so->so_rcv.sb_mbcnt -= MSIZE; 396 m = m_free(m); 397 if (m == 0) 398 panic("receive 2"); 399 so->so_rcv.sb_mb = m; 400 } 401 eor = 0; 402 do { 403 if (uio->uio_iovcnt == 0) 404 break; 405 iov = uio->uio_iov; 406 len = iov->iov_len; 407 so->so_state &= ~SS_RCVATMARK; 408 if (so->so_oobmark && len > so->so_oobmark) 409 len = so->so_oobmark; 410 if (len > m->m_len) 411 len = m->m_len; 412 splx(s); 413 uiomove(mtod(m, caddr_t), len, UIO_WRITETO, uio); 414 s = splnet(); 415 if (len == m->m_len) { 416 eor = (int)m->m_act; 417 sbfree(&so->so_rcv, m); 418 so->so_rcv.sb_mb = m->m_next; 419 MFREE(m, n); 420 } else { 421 m->m_off += len; 422 m->m_len -= len; 423 so->so_rcv.sb_cc -= len; 424 } 425 if (so->so_oobmark) { 426 so->so_oobmark -= len; 427 if (so->so_oobmark == 0) { 428 so->so_state |= SS_RCVATMARK; 429 break; 430 } 431 } 432 } while ((m = so->so_rcv.sb_mb) && !eor); 433 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 434 do { 435 if (m == 0) 436 panic("receive 3"); 437 sbfree(&so->so_rcv, m); 438 eor = (int)m->m_act; 439 so->so_rcv.sb_mb = m->m_next; 440 MFREE(m, n); 441 m = n; 442 } while (eor == 0); 443 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 444 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 445 release: 446 sbunlock(&so->so_rcv); 447 splx(s); 448 return (error); 449 } 450 451 sohasoutofband(so) 452 struct socket *so; 453 { 454 455 if (so->so_pgrp == 0) 456 return; 457 if (so->so_pgrp > 0) 458 gsignal(so->so_pgrp, SIGURG); 459 else { 460 struct proc *p = pfind(-so->so_pgrp); 461 462 if (p) 463 psignal(p, SIGURG); 464 } 465 } 466 467 /*ARGSUSED*/ 468 soioctl(so, cmd, data) 469 register struct socket *so; 470 int cmd; 471 register char *data; 472 { 473 474 switch (cmd) { 475 476 case FIONBIO: 477 if (*(int *)data) 478 so->so_state |= SS_NBIO; 479 else 480 so->so_state &= ~SS_NBIO; 481 return; 482 483 case FIOASYNC: 484 if (*(int *)data) 485 so->so_state |= SS_ASYNC; 486 else 487 so->so_state &= ~SS_ASYNC; 488 return; 489 490 case SIOCSKEEP: 491 if (*(int *)data) 492 so->so_options &= ~SO_KEEPALIVE; 493 else 494 so->so_options |= SO_KEEPALIVE; 495 return; 496 497 case SIOCGKEEP: 498 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 499 return; 500 501 case SIOCSLINGER: 502 so->so_linger = *(int *)data; 503 if (so->so_linger) 504 so->so_options &= ~SO_DONTLINGER; 505 else 506 so->so_options |= SO_DONTLINGER; 507 return; 508 509 case SIOCGLINGER: 510 *(int *)data = so->so_linger; 511 return; 512 513 case SIOCSPGRP: 514 so->so_pgrp = *(int *)data; 515 return; 516 517 case SIOCGPGRP: 518 *(int *)data = so->so_pgrp; 519 return; 520 521 case SIOCDONE: { 522 int flags = *(int *)data; 523 524 flags++; 525 if (flags & FREAD) { 526 int s = splimp(); 527 socantrcvmore(so); 528 sbflush(&so->so_rcv); 529 splx(s); 530 } 531 if (flags & FWRITE) 532 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 533 return; 534 } 535 536 case SIOCSENDOOB: { 537 char oob = *(char *)data; 538 struct mbuf *m; 539 540 m = m_get(M_DONTWAIT); 541 if (m == 0) { 542 u.u_error = ENOBUFS; 543 return; 544 } 545 m->m_off = MMINOFF; 546 m->m_len = sizeof (char); 547 *mtod(m, char *) = oob; 548 (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 549 return; 550 } 551 552 case SIOCRCVOOB: { 553 struct mbuf *m = m_get(M_DONTWAIT); 554 555 if (m == 0) { 556 u.u_error = ENOBUFS; 557 return; 558 } 559 m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 560 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 561 *(char *)data = *mtod(m, char *); 562 (void) m_free(m); 563 return; 564 } 565 566 case SIOCATMARK: 567 *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 568 return; 569 570 /* routing table update calls */ 571 case SIOCADDRT: 572 case SIOCDELRT: 573 if (!suser()) 574 return; 575 u.u_error = rtrequest(cmd, (struct rtentry *)data); 576 return; 577 578 /* type/protocol specific ioctls */ 579 } 580 u.u_error = EOPNOTSUPP; 581 } 582