1 /* uipc_socket.c 4.60 82/10/21 */ 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 "../h/uio.h" 18 #include "../net/route.h" 19 20 /* 21 * Socket operation routines. 22 * These routines are called by the routines in 23 * sys_socket.c or from a system process, and 24 * implement the semantics of socket operations by 25 * switching out to the protocol specific routines. 26 */ 27 28 /*ARGSUSED*/ 29 socreate(dom, aso, type, proto, opt) 30 struct socket **aso; 31 int type, proto; 32 struct socketopt *opt; 33 { 34 register struct protosw *prp; 35 register struct socket *so; 36 struct mbuf *m; 37 int pf, error; 38 39 pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ 40 if (proto) 41 prp = pffindproto(pf, proto); 42 else 43 prp = pffindtype(pf, type); 44 if (prp == 0) 45 return (EPROTONOSUPPORT); 46 if (prp->pr_type != type) 47 return (EPROTOTYPE); 48 m = m_getclr(M_WAIT); 49 if (m == 0) 50 return (ENOBUFS); 51 so = mtod(m, struct socket *); 52 so->so_options = 0; 53 so->so_state = 0; 54 if (u.u_uid == 0) 55 so->so_state = SS_PRIV; 56 so->so_proto = prp; 57 error = (*prp->pr_usrreq)(so, PRU_ATTACH, 58 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 59 if (error) { 60 so->so_state |= SS_NOFDREF; 61 sofree(so); 62 return (error); 63 } 64 *aso = so; 65 return (0); 66 } 67 68 sobind(so, nam, opt) 69 struct socket *so; 70 struct mbuf *nam; 71 struct socketopt *opt; 72 { 73 int s = splnet(); 74 int error; 75 76 error = 77 (*so->so_proto->pr_usrreq)(so, PRU_BIND, 78 (struct mbuf *)0, nam, opt); 79 splx(s); 80 return (error); 81 } 82 83 solisten(so, backlog) 84 struct socket *so; 85 int backlog; 86 { 87 int s = splnet(); 88 int error; 89 90 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 91 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 92 if (error) { 93 splx(s); 94 return (error); 95 } 96 if (so->so_q == 0) { 97 so->so_q = so; 98 so->so_q0 = so; 99 so->so_options |= SO_ACCEPTCONN; 100 } 101 if (backlog < 0) 102 backlog = 0; 103 so->so_qlimit = backlog < 5 ? backlog : 5; 104 so->so_options |= SO_NEWFDONCONN; 105 return (0); 106 } 107 108 sofree(so) 109 struct socket *so; 110 { 111 112 if (so->so_head) { 113 if (!soqremque(so, 0) && !soqremque(so, 1)) 114 panic("sofree dq"); 115 so->so_head = 0; 116 } 117 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 118 return; 119 sbrelease(&so->so_snd); 120 sbrelease(&so->so_rcv); 121 (void) m_free(dtom(so)); 122 } 123 124 /* 125 * Close a socket on last file table reference removal. 126 * Initiate disconnect if connected. 127 * Free socket when disconnect complete. 128 */ 129 soclose(so, exiting) 130 register struct socket *so; 131 int exiting; 132 { 133 int s = splnet(); /* conservative */ 134 int error; 135 136 if (so->so_options & SO_ACCEPTCONN) { 137 while (so->so_q0 != so) 138 (void) soclose(so->so_q0, 1); 139 while (so->so_q != so) 140 (void) soclose(so->so_q, 1); 141 } 142 if (so->so_pcb == 0) 143 goto discard; 144 if (exiting) 145 so->so_options |= SO_KEEPALIVE; 146 if (so->so_state & SS_ISCONNECTED) { 147 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 148 error = sodisconnect(so, (struct mbuf *)0); 149 if (error) { 150 if (exiting) 151 goto drop; 152 splx(s); 153 return (error); 154 } 155 } 156 if ((so->so_options & SO_DONTLINGER) == 0) { 157 if ((so->so_state & SS_ISDISCONNECTING) && 158 (so->so_state & SS_NBIO) && 159 exiting == 0) 160 return (EINPROGRESS); 161 /* should use tsleep here, for at most linger */ 162 while (so->so_state & SS_ISCONNECTED) 163 sleep((caddr_t)&so->so_timeo, PZERO+1); 164 } 165 } 166 drop: 167 if (so->so_pcb) { 168 error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 169 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 170 if (exiting == 0 && error) { 171 splx(s); 172 return (error); 173 } 174 } 175 discard: 176 so->so_state |= SS_NOFDREF; 177 sofree(so); 178 splx(s); 179 return (0); 180 } 181 182 /*ARGSUSED*/ 183 sostat(so, sb) 184 struct socket *so; 185 struct stat *sb; 186 { 187 188 bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 189 return (0); /* XXX */ 190 } 191 192 soaccept(so, nam, opt) 193 struct socket *so; 194 struct mbuf *nam; 195 struct socketopt *opt; 196 { 197 int s = splnet(); 198 int error; 199 200 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 201 (struct mbuf *)0, nam, opt); 202 splx(s); 203 return (error); 204 } 205 206 soconnect(so, nam, opt) 207 struct socket *so; 208 struct mbuf *nam; 209 struct socketopt *opt; 210 { 211 int s = splnet(); 212 int error; 213 214 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 215 error = EISCONN; 216 goto bad; 217 } 218 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 219 (struct mbuf *)0, nam, opt); 220 bad: 221 splx(s); 222 return (error); 223 } 224 225 sodisconnect(so, nam) 226 struct socket *so; 227 struct mbuf *nam; 228 { 229 int s = splnet(); 230 int error; 231 232 if ((so->so_state & SS_ISCONNECTED) == 0) { 233 error = ENOTCONN; 234 goto bad; 235 } 236 if (so->so_state & SS_ISDISCONNECTING) { 237 error = EALREADY; 238 goto bad; 239 } 240 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 241 (struct mbuf *)0, nam, (struct socketopt *)0); 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, nam, uio, flags) 256 register struct socket *so; 257 struct mbuf *nam; 258 struct uio *uio; 259 int flags; 260 { 261 struct mbuf *top = 0; 262 register struct mbuf *m, **mp = ⊤ 263 register int len; 264 int error = 0, space, s; 265 266 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 267 return (EMSGSIZE); 268 restart: 269 sblock(&so->so_snd); 270 #define snderr(errno) { error = errno; splx(s); goto release; } 271 272 u.u_ru.ru_msgsnd++; 273 again: 274 s = splnet(); 275 if (so->so_state & SS_CANTSENDMORE) { 276 psignal(u.u_procp, SIGPIPE); 277 snderr(EPIPE); 278 } 279 if (so->so_error) { 280 error = so->so_error; 281 so->so_error = 0; /* ??? */ 282 splx(s); 283 goto release; 284 } 285 if ((so->so_state & SS_ISCONNECTED) == 0) { 286 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 287 snderr(ENOTCONN); 288 if (nam == 0) 289 snderr(EDESTADDRREQ); 290 } 291 if (top) { 292 error = (*so->so_proto->pr_usrreq)(so, 293 (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 294 top, (caddr_t)nam, (struct socketopt *)0); 295 top = 0; 296 if (error) { 297 splx(s); 298 goto release; 299 } 300 mp = ⊤ 301 } 302 if (uio->uio_resid == 0) { 303 splx(s); 304 goto release; 305 } 306 if (flags & SOF_OOB) 307 space = 1024; 308 else { 309 space = sbspace(&so->so_snd); 310 if (space <= 0 || 311 sosendallatonce(so) && space < uio->uio_resid) { 312 if (so->so_state & SS_NBIO) 313 snderr(EWOULDBLOCK); 314 sbunlock(&so->so_snd); 315 sbwait(&so->so_snd); 316 splx(s); 317 goto restart; 318 } 319 } 320 splx(s); 321 while (uio->uio_resid > 0 && space > 0) { 322 register struct iovec *iov = uio->uio_iov; 323 324 if (iov->iov_len == 0) { 325 uio->uio_iov++; 326 uio->uio_iovcnt--; 327 if (uio->uio_iovcnt < 0) 328 panic("sosend"); 329 continue; 330 } 331 MGET(m, 1); 332 if (m == NULL) { 333 error = ENOBUFS; /* SIGPIPE? */ 334 goto release; 335 } 336 if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 337 register struct mbuf *p; 338 MCLGET(p, 1); 339 if (p == 0) 340 goto nopages; 341 m->m_off = (int)p - (int)m; 342 len = CLBYTES; 343 } else { 344 nopages: 345 len = MIN(MLEN, iov->iov_len); 346 } 347 (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 348 m->m_len = len; 349 *mp = m; 350 mp = &m->m_next; 351 if (flags & SOF_OOB) 352 space -= len; 353 else 354 space = sbspace(&so->so_snd); 355 } 356 goto again; 357 358 release: 359 sbunlock(&so->so_snd); 360 if (top) 361 m_freem(top); 362 return (error); 363 } 364 365 soreceive(so, aname, uio, flags) 366 register struct socket *so; 367 struct mbuf **aname; 368 struct uio *uio; 369 int flags; 370 { 371 register struct mbuf *m, *n; 372 int len; 373 int eor, s, error = 0, moff, tomark; 374 375 if (flags & SOF_OOB) { 376 m = m_get(M_WAIT); 377 error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 378 m, (struct mbuf *)0, (struct socketopt *)0); 379 if (error) 380 return (error); 381 len = uio->uio_resid; 382 do { 383 if (len > m->m_len) 384 len = m->m_len; 385 error = 386 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 387 m = m_free(m); 388 } while (uio->uio_resid && error == 0 && m); 389 if (m) 390 m_freem(m); 391 return (error); 392 } 393 394 restart: 395 sblock(&so->so_rcv); 396 SBCHECK(&so->so_rcv, "soreceive restart"); 397 s = splnet(); 398 399 #define rcverr(errno) { error = errno; splx(s); goto release; } 400 if (so->so_rcv.sb_cc == 0) { 401 if (so->so_error) { 402 error = so->so_error; 403 so->so_error = 0; 404 splx(s); 405 goto release; 406 } 407 if (so->so_state & SS_CANTRCVMORE) { 408 splx(s); 409 goto release; 410 } 411 if ((so->so_state & SS_ISCONNECTED) == 0 && 412 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 413 rcverr(ENOTCONN); 414 if (so->so_state & SS_NBIO) 415 rcverr(EWOULDBLOCK); 416 sbunlock(&so->so_rcv); 417 sbwait(&so->so_rcv); 418 splx(s); 419 goto restart; 420 } 421 u.u_ru.ru_msgrcv++; 422 m = so->so_rcv.sb_mb; 423 if (m == 0) 424 panic("receive"); 425 SBCHECK(&so->so_snd, "soreceive havecc"); 426 if (so->so_proto->pr_flags & PR_ADDR) { 427 if ((flags & SOF_PREVIEW) == 0) { 428 so->so_rcv.sb_cc -= m->m_len; 429 so->so_rcv.sb_mbcnt -= MSIZE; 430 } 431 if (aname) { 432 if (flags & SOF_PREVIEW) 433 *aname = m_copy(m, 0, m->m_len); 434 else 435 *aname = m; 436 m = m->m_next; 437 (*aname)->m_next = 0; 438 } else 439 if (flags & SOF_PREVIEW) 440 m = m->m_next; 441 else 442 m = m_free(m); 443 if (m == 0) 444 panic("receive 2"); 445 if ((flags & SOF_PREVIEW) == 0) 446 so->so_rcv.sb_mb = m; 447 SBCHECK(&so->so_snd, "soreceive afteraddr"); 448 } 449 eor = 0; 450 moff = 0; 451 tomark = so->so_oobmark; 452 do { 453 if (uio->uio_resid <= 0) 454 break; 455 len = uio->uio_resid; 456 so->so_state &= ~SS_RCVATMARK; 457 if (tomark && len > tomark) 458 len = tomark; 459 if (moff+len > m->m_len - moff) 460 len = m->m_len - moff; 461 splx(s); 462 error = 463 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 464 s = splnet(); 465 if (len == m->m_len) { 466 eor = (int)m->m_act; 467 if (flags & SOF_PREVIEW) 468 m = m->m_next; 469 else { 470 sbfree(&so->so_rcv, m); 471 MFREE(m, n); 472 m = n; 473 so->so_rcv.sb_mb = m; 474 } 475 moff = 0; 476 } else { 477 if (flags & SOF_PREVIEW) 478 moff += len; 479 else { 480 m->m_off += len; 481 m->m_len -= len; 482 so->so_rcv.sb_cc -= len; 483 } 484 } 485 if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 486 so->so_oobmark -= len; 487 if (so->so_oobmark == 0) { 488 so->so_state |= SS_RCVATMARK; 489 break; 490 } 491 } 492 if (tomark) { 493 tomark -= len; 494 if (tomark == 0) 495 break; 496 } 497 SBCHECK(&so->so_snd, "soreceive rcvloop"); 498 } while (m && error == 0 && !eor); 499 if (flags & SOF_PREVIEW) 500 goto release; 501 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 502 do { 503 if (m == 0) 504 panic("receive 3"); 505 sbfree(&so->so_rcv, m); 506 eor = (int)m->m_act; 507 so->so_rcv.sb_mb = m->m_next; 508 MFREE(m, n); 509 m = n; 510 SBCHECK(&so->so_snd, "soreceive atomicloop"); 511 } while (eor == 0); 512 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 513 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 514 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 515 release: 516 sbunlock(&so->so_rcv); 517 splx(s); 518 return (error); 519 } 520 521 sohasoutofband(so) 522 struct socket *so; 523 { 524 525 if (so->so_pgrp == 0) 526 return; 527 if (so->so_pgrp > 0) 528 gsignal(so->so_pgrp, SIGURG); 529 else { 530 struct proc *p = pfind(-so->so_pgrp); 531 532 if (p) 533 psignal(p, SIGURG); 534 } 535 } 536 537 /*ARGSUSED*/ 538 soioctl(so, cmd, data) 539 register struct socket *so; 540 int cmd; 541 register char *data; 542 { 543 544 switch (cmd) { 545 546 case FIONBIO: 547 if (*(int *)data) 548 so->so_state |= SS_NBIO; 549 else 550 so->so_state &= ~SS_NBIO; 551 break; 552 553 case FIOASYNC: 554 if (*(int *)data) 555 so->so_state |= SS_ASYNC; 556 else 557 so->so_state &= ~SS_ASYNC; 558 break; 559 560 case SIOCSKEEP: 561 if (*(int *)data) 562 so->so_options &= ~SO_KEEPALIVE; 563 else 564 so->so_options |= SO_KEEPALIVE; 565 break; 566 567 case SIOCGKEEP: 568 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 569 break; 570 571 case SIOCSLINGER: 572 so->so_linger = *(int *)data; 573 if (so->so_linger) 574 so->so_options &= ~SO_DONTLINGER; 575 else 576 so->so_options |= SO_DONTLINGER; 577 break; 578 579 case SIOCGLINGER: 580 *(int *)data = so->so_linger; 581 break; 582 583 case SIOCSPGRP: 584 so->so_pgrp = *(int *)data; 585 break; 586 587 case SIOCGPGRP: 588 *(int *)data = so->so_pgrp; 589 break; 590 591 case SIOCDONE: { 592 int flags = *(int *)data; 593 594 flags++; 595 if (flags & FREAD) { 596 int s = splimp(); 597 socantrcvmore(so); 598 sbflush(&so->so_rcv); 599 splx(s); 600 } 601 if (flags & FWRITE) 602 return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 603 (struct mbuf *)0, (struct mbuf *)0, 604 (struct socketopt *)0)); 605 break; 606 } 607 608 case SIOCSENDOOB: { 609 char oob = *(char *)data; 610 struct mbuf *m = m_get(M_DONTWAIT); 611 612 if (m == 0) 613 return (ENOBUFS); 614 m->m_len = 1; 615 *mtod(m, char *) = oob; 616 return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 617 m, (struct mbuf *)0, (struct socketopt *)0)); 618 } 619 620 case SIOCRCVOOB: { 621 struct mbuf *m = m_get(M_WAIT); 622 623 if (m == 0) 624 return (ENOBUFS); 625 *mtod(m, caddr_t) = 0; 626 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 627 m, (struct mbuf *)0, (struct socketopt *)0); 628 *(char *)data = *mtod(m, char *); 629 (void) m_free(m); 630 break; 631 } 632 633 case SIOCATMARK: 634 *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 635 break; 636 637 /* routing table update calls */ 638 case SIOCADDRT: 639 case SIOCDELRT: 640 if (!suser()) 641 return (u.u_error); /* XXX */ 642 return (rtrequest(cmd, (struct rtentry *)data)); 643 644 /* type/protocol specific ioctls */ 645 default: 646 return (ENOTTY); 647 } 648 return (0); 649 } 650