1 /* uipc_socket.c 6.2 83/09/29 */ 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/un.h" 13 #include "../h/protosw.h" 14 #include "../h/socket.h" 15 #include "../h/socketvar.h" 16 #include "../h/stat.h" 17 #include "../h/ioctl.h" 18 #include "../h/uio.h" 19 #include "../net/route.h" 20 #include "../netinet/in.h" 21 #include "../net/if.h" 22 23 /* 24 * Socket operation routines. 25 * These routines are called by the routines in 26 * sys_socket.c or from a system process, and 27 * implement the semantics of socket operations by 28 * switching out to the protocol specific routines. 29 * 30 * TODO: 31 * sostat 32 * test socketpair 33 * PR_RIGHTS 34 * clean up select, async 35 * out-of-band is a kludge 36 */ 37 /*ARGSUSED*/ 38 socreate(dom, aso, type, proto) 39 struct socket **aso; 40 register int type; 41 int proto; 42 { 43 register struct protosw *prp; 44 register struct socket *so; 45 register struct mbuf *m; 46 register int error; 47 48 if (proto) 49 prp = pffindproto(dom, proto); 50 else 51 prp = pffindtype(dom, type); 52 if (prp == 0) 53 return (EPROTONOSUPPORT); 54 if (prp->pr_type != type) 55 return (EPROTOTYPE); 56 m = m_getclr(M_WAIT, MT_SOCKET); 57 if (m == 0) 58 return (ENOBUFS); 59 so = mtod(m, struct socket *); 60 so->so_options = 0; 61 so->so_state = 0; 62 so->so_type = type; 63 if (u.u_uid == 0) 64 so->so_state = SS_PRIV; 65 so->so_proto = prp; 66 error = 67 (*prp->pr_usrreq)(so, PRU_ATTACH, 68 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 69 if (error) { 70 so->so_state |= SS_NOFDREF; 71 sofree(so); 72 return (error); 73 } 74 *aso = so; 75 return (0); 76 } 77 78 sobind(so, nam) 79 struct socket *so; 80 struct mbuf *nam; 81 { 82 int s = splnet(); 83 int error; 84 85 error = 86 (*so->so_proto->pr_usrreq)(so, PRU_BIND, 87 (struct mbuf *)0, nam, (struct mbuf *)0); 88 splx(s); 89 return (error); 90 } 91 92 solisten(so, backlog) 93 register struct socket *so; 94 int backlog; 95 { 96 int s = splnet(), error; 97 98 error = 99 (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 100 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 101 if (error) { 102 splx(s); 103 return (error); 104 } 105 if (so->so_q == 0) { 106 so->so_q = so; 107 so->so_q0 = so; 108 so->so_options |= SO_ACCEPTCONN; 109 } 110 if (backlog < 0) 111 backlog = 0; 112 so->so_qlimit = MIN(backlog, SOMAXCONN); 113 splx(s); 114 return (0); 115 } 116 117 sofree(so) 118 register struct socket *so; 119 { 120 121 if (so->so_head) { 122 if (!soqremque(so, 0) && !soqremque(so, 1)) 123 panic("sofree dq"); 124 so->so_head = 0; 125 } 126 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 127 return; 128 sbrelease(&so->so_snd); 129 sorflush(so); 130 (void) m_free(dtom(so)); 131 } 132 133 /* 134 * Close a socket on last file table reference removal. 135 * Initiate disconnect if connected. 136 * Free socket when disconnect complete. 137 */ 138 soclose(so) 139 register struct socket *so; 140 { 141 int s = splnet(); /* conservative */ 142 int error; 143 144 if (so->so_options & SO_ACCEPTCONN) { 145 while (so->so_q0 != so) 146 (void) soabort(so->so_q0); 147 while (so->so_q != so) 148 (void) soabort(so->so_q); 149 } 150 if (so->so_pcb == 0) 151 goto discard; 152 if (so->so_state & SS_ISCONNECTED) { 153 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 154 error = sodisconnect(so, (struct mbuf *)0); 155 if (error) 156 goto drop; 157 } 158 if (so->so_options & SO_LINGER) { 159 if ((so->so_state & SS_ISDISCONNECTING) && 160 (so->so_state & SS_NBIO)) 161 goto drop; 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 int error2 = 169 (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 170 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 171 if (error == 0) 172 error = error2; 173 } 174 discard: 175 if (so->so_state & SS_NOFDREF) 176 panic("soclose: NOFDREF"); 177 so->so_state |= SS_NOFDREF; 178 sofree(so); 179 splx(s); 180 return (error); 181 } 182 183 /* 184 * Must be called at splnet... 185 */ 186 soabort(so) 187 struct socket *so; 188 { 189 190 return ( 191 (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 192 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 193 } 194 195 soaccept(so, nam) 196 register struct socket *so; 197 struct mbuf *nam; 198 { 199 int s = splnet(); 200 int error; 201 202 if ((so->so_state & SS_NOFDREF) == 0) 203 panic("soaccept: !NOFDREF"); 204 so->so_state &= ~SS_NOFDREF; 205 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 206 (struct mbuf *)0, nam, (struct mbuf *)0); 207 splx(s); 208 return (error); 209 } 210 211 soconnect(so, nam) 212 register struct socket *so; 213 struct mbuf *nam; 214 { 215 int s = splnet(); 216 int error; 217 218 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 219 error = EISCONN; 220 goto bad; 221 } 222 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 223 (struct mbuf *)0, nam, (struct mbuf *)0); 224 bad: 225 splx(s); 226 return (error); 227 } 228 229 soconnect2(so1, so2) 230 register struct socket *so1; 231 struct socket *so2; 232 { 233 int s = splnet(); 234 int error; 235 236 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 237 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 238 splx(s); 239 return (error); 240 } 241 242 sodisconnect(so, nam) 243 register struct socket *so; 244 struct mbuf *nam; 245 { 246 int s = splnet(); 247 int error; 248 249 if ((so->so_state & SS_ISCONNECTED) == 0) { 250 error = ENOTCONN; 251 goto bad; 252 } 253 if (so->so_state & SS_ISDISCONNECTING) { 254 error = EALREADY; 255 goto bad; 256 } 257 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 258 (struct mbuf *)0, nam, (struct mbuf *)0); 259 bad: 260 splx(s); 261 return (error); 262 } 263 264 /* 265 * Send on a socket. 266 * If send must go all at once and message is larger than 267 * send buffering, then hard error. 268 * Lock against other senders. 269 * If must go all at once and not enough room now, then 270 * inform user that this would block and do nothing. 271 */ 272 sosend(so, nam, uio, flags, rights) 273 register struct socket *so; 274 struct mbuf *nam; 275 register struct uio *uio; 276 int flags; 277 struct mbuf *rights; 278 { 279 struct mbuf *top = 0; 280 register struct mbuf *m, **mp = ⊤ 281 register int space; 282 int len, error = 0, s, dontroute; 283 struct sockbuf sendtempbuf; 284 285 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 286 return (EMSGSIZE); 287 dontroute = 288 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 289 (so->so_proto->pr_flags & PR_ATOMIC); 290 restart: 291 sblock(&so->so_snd); 292 #define snderr(errno) { error = errno; splx(s); goto release; } 293 294 u.u_ru.ru_msgsnd++; 295 again: 296 s = splnet(); 297 if (so->so_state & SS_CANTSENDMORE) { 298 psignal(u.u_procp, SIGPIPE); 299 snderr(EPIPE); 300 } 301 if (so->so_error) { 302 error = so->so_error; 303 so->so_error = 0; /* ??? */ 304 splx(s); 305 goto release; 306 } 307 if ((so->so_state & SS_ISCONNECTED) == 0) { 308 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 309 snderr(ENOTCONN); 310 if (nam == 0) 311 snderr(EDESTADDRREQ); 312 } 313 if (top) { 314 if (dontroute) 315 so->so_options |= SO_DONTROUTE; 316 error = (*so->so_proto->pr_usrreq)(so, 317 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 318 top, (caddr_t)nam, rights); 319 if (dontroute) 320 so->so_options &= ~SO_DONTROUTE; 321 top = 0; 322 if (error) { 323 splx(s); 324 goto release; 325 } 326 mp = ⊤ 327 } 328 if (uio->uio_resid == 0) { 329 splx(s); 330 goto release; 331 } 332 if (flags & MSG_OOB) 333 space = 1024; 334 else { 335 space = sbspace(&so->so_snd); 336 if (space <= 0 || 337 sosendallatonce(so) && space < uio->uio_resid) { 338 if (so->so_state & SS_NBIO) 339 snderr(EWOULDBLOCK); 340 sbunlock(&so->so_snd); 341 sbwait(&so->so_snd); 342 splx(s); 343 goto restart; 344 } 345 } 346 splx(s); 347 /* 348 * Temporary kludge-- don't want to update so_snd in this loop 349 * (will be done when sent), but need to recalculate 350 * space on each iteration. For now, copy so_snd into a tmp. 351 */ 352 sendtempbuf = so->so_snd; 353 while (uio->uio_resid > 0 && space > 0) { 354 register struct iovec *iov = uio->uio_iov; 355 356 if (iov->iov_len == 0) { 357 uio->uio_iov++; 358 uio->uio_iovcnt--; 359 if (uio->uio_iovcnt < 0) 360 panic("sosend"); 361 continue; 362 } 363 MGET(m, M_WAIT, MT_DATA); 364 if (m == NULL) { 365 error = ENOBUFS; /* SIGPIPE? */ 366 goto release; 367 } 368 if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 369 register struct mbuf *p; 370 MCLGET(p, 1); 371 if (p == 0) 372 goto nopages; 373 m->m_off = (int)p - (int)m; 374 len = CLBYTES; 375 } else { 376 nopages: 377 len = MIN(MLEN, iov->iov_len); 378 } 379 error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 380 m->m_len = len; 381 *mp = m; 382 if (error) 383 goto release; 384 mp = &m->m_next; 385 if (flags & MSG_OOB) 386 space -= len; 387 else { 388 sballoc(&sendtempbuf, m); 389 space = sbspace(&sendtempbuf); 390 } 391 } 392 goto again; 393 394 release: 395 sbunlock(&so->so_snd); 396 if (top) 397 m_freem(top); 398 return (error); 399 } 400 401 soreceive(so, aname, uio, flags, rightsp) 402 register struct socket *so; 403 struct mbuf **aname; 404 register struct uio *uio; 405 int flags; 406 struct mbuf **rightsp; 407 { 408 register struct mbuf *m, *n; 409 register int len, error = 0, s, eor, tomark; 410 struct protosw *pr = so->so_proto; 411 int moff; 412 413 if (rightsp) 414 *rightsp = 0; 415 if (aname) 416 *aname = 0; 417 if (flags & MSG_OOB) { 418 m = m_get(M_WAIT, MT_DATA); 419 if (m == 0) 420 return (ENOBUFS); 421 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 422 m, (struct mbuf *)0, (struct mbuf *)0); 423 if (error) 424 goto bad; 425 do { 426 len = uio->uio_resid; 427 if (len > m->m_len) 428 len = m->m_len; 429 error = 430 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 431 m = m_free(m); 432 } while (uio->uio_resid && error == 0 && m); 433 bad: 434 if (m) 435 m_freem(m); 436 return (error); 437 } 438 439 restart: 440 sblock(&so->so_rcv); 441 s = splnet(); 442 443 #define rcverr(errno) { error = errno; splx(s); goto release; } 444 if (so->so_rcv.sb_cc == 0) { 445 if (so->so_error) { 446 error = so->so_error; 447 so->so_error = 0; 448 splx(s); 449 goto release; 450 } 451 if (so->so_state & SS_CANTRCVMORE) { 452 splx(s); 453 goto release; 454 } 455 if ((so->so_state & SS_ISCONNECTED) == 0 && 456 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 457 rcverr(ENOTCONN); 458 if (so->so_state & SS_NBIO) 459 rcverr(EWOULDBLOCK); 460 sbunlock(&so->so_rcv); 461 sbwait(&so->so_rcv); 462 splx(s); 463 goto restart; 464 } 465 u.u_ru.ru_msgrcv++; 466 m = so->so_rcv.sb_mb; 467 if (m == 0) 468 panic("receive"); 469 if (pr->pr_flags & PR_ADDR) { 470 if ((flags & MSG_PEEK) == 0) { 471 so->so_rcv.sb_cc -= m->m_len; 472 so->so_rcv.sb_mbcnt -= MSIZE; 473 } 474 if (aname) { 475 if (flags & MSG_PEEK) { 476 *aname = m_copy(m, 0, m->m_len); 477 if (*aname == NULL) 478 panic("receive 2"); 479 } else 480 *aname = m; 481 m = m->m_next; 482 (*aname)->m_next = 0; 483 } else 484 if (flags & MSG_PEEK) 485 m = m->m_next; 486 else 487 m = m_free(m); 488 if (m == 0) 489 panic("receive 2a"); 490 if (rightsp) { 491 if (m->m_len) 492 *rightsp = m_copy(m, 0, m->m_len); 493 else { 494 *rightsp = m_get(M_DONTWAIT, MT_SONAME); 495 if (*rightsp) 496 (*rightsp)->m_len = 0; 497 } 498 #ifdef notdef 499 if (*rightsp == NULL) 500 panic("receive 2b"); 501 #endif 502 } 503 if (flags & MSG_PEEK) 504 m = m->m_next; 505 else { 506 so->so_rcv.sb_cc -= m->m_len; 507 so->so_rcv.sb_mbcnt -= MSIZE; 508 m = m_free(m); 509 } 510 if (m == 0) 511 panic("receive 3"); 512 if ((flags & MSG_PEEK) == 0) 513 so->so_rcv.sb_mb = m; 514 } 515 eor = 0; 516 moff = 0; 517 tomark = so->so_oobmark; 518 do { 519 if (uio->uio_resid <= 0) 520 break; 521 len = uio->uio_resid; 522 so->so_state &= ~SS_RCVATMARK; 523 if (tomark && len > tomark) 524 len = tomark; 525 if (moff+len > m->m_len - moff) 526 len = m->m_len - moff; 527 splx(s); 528 error = 529 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 530 s = splnet(); 531 if (len == m->m_len) { 532 eor = (int)m->m_act; 533 if (flags & MSG_PEEK) 534 m = m->m_next; 535 else { 536 sbfree(&so->so_rcv, m); 537 MFREE(m, n); 538 m = n; 539 so->so_rcv.sb_mb = m; 540 } 541 moff = 0; 542 } else { 543 if (flags & MSG_PEEK) 544 moff += len; 545 else { 546 m->m_off += len; 547 m->m_len -= len; 548 so->so_rcv.sb_cc -= len; 549 } 550 } 551 if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 552 so->so_oobmark -= len; 553 if (so->so_oobmark == 0) { 554 so->so_state |= SS_RCVATMARK; 555 break; 556 } 557 } 558 if (tomark) { 559 tomark -= len; 560 if (tomark == 0) 561 break; 562 } 563 } while (m && error == 0 && !eor); 564 if (flags & MSG_PEEK) 565 goto release; 566 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 567 do { 568 if (m == 0) 569 panic("receive 4"); 570 sbfree(&so->so_rcv, m); 571 eor = (int)m->m_act; 572 so->so_rcv.sb_mb = m->m_next; 573 MFREE(m, n); 574 m = n; 575 } while (eor == 0); 576 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 577 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 578 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 579 release: 580 sbunlock(&so->so_rcv); 581 if (error == 0 && rightsp && 582 *rightsp && so->so_proto->pr_family == AF_UNIX) 583 error = unp_externalize(*rightsp); 584 splx(s); 585 return (error); 586 } 587 588 soshutdown(so, how) 589 register struct socket *so; 590 register int how; 591 { 592 register struct protosw *pr = so->so_proto; 593 594 how++; 595 if (how & FREAD) 596 sorflush(so); 597 if (how & FWRITE) 598 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 599 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 600 return (0); 601 } 602 603 sorflush(so) 604 register struct socket *so; 605 { 606 register struct sockbuf *sb = &so->so_rcv; 607 register struct protosw *pr = so->so_proto; 608 register int s; 609 struct sockbuf asb; 610 611 sblock(sb); 612 s = splimp(); 613 socantrcvmore(so); 614 sbunlock(sb); 615 asb = *sb; 616 bzero((caddr_t)sb, sizeof (*sb)); 617 splx(s); 618 if (pr->pr_family == AF_UNIX && (pr->pr_flags & PR_RIGHTS)) 619 unp_scan(asb.sb_mb, unp_discard); 620 sbrelease(&asb); 621 } 622 623 sosetopt(so, level, optname, m) 624 register struct socket *so; 625 int level, optname; 626 register struct mbuf *m; 627 { 628 629 if (level != SOL_SOCKET) 630 return (EINVAL); /* XXX */ 631 switch (optname) { 632 633 case SO_DEBUG: 634 case SO_KEEPALIVE: 635 case SO_DONTROUTE: 636 case SO_USELOOPBACK: 637 case SO_REUSEADDR: 638 so->so_options |= optname; 639 break; 640 641 case SO_LINGER: 642 if (m == NULL || m->m_len != sizeof (int)) 643 return (EINVAL); 644 so->so_options |= SO_LINGER; 645 so->so_linger = *mtod(m, int *); 646 break; 647 648 case SO_DONTLINGER: 649 so->so_options &= ~SO_LINGER; 650 so->so_linger = 0; 651 break; 652 653 default: 654 return (EINVAL); 655 } 656 return (0); 657 } 658 659 sogetopt(so, level, optname, m) 660 register struct socket *so; 661 int level, optname; 662 register struct mbuf *m; 663 { 664 665 if (level != SOL_SOCKET) 666 return (EINVAL); /* XXX */ 667 switch (optname) { 668 669 case SO_USELOOPBACK: 670 case SO_DONTROUTE: 671 case SO_DEBUG: 672 case SO_KEEPALIVE: 673 case SO_LINGER: 674 case SO_REUSEADDR: 675 if ((so->so_options & optname) == 0) 676 return (ENOPROTOOPT); 677 if (optname == SO_LINGER && m != NULL) { 678 *mtod(m, int *) = so->so_linger; 679 m->m_len = sizeof (so->so_linger); 680 } 681 break; 682 683 default: 684 return (EINVAL); 685 } 686 return (0); 687 } 688 689 sohasoutofband(so) 690 register struct socket *so; 691 { 692 693 if (so->so_pgrp == 0) 694 return; 695 if (so->so_pgrp > 0) 696 gsignal(so->so_pgrp, SIGURG); 697 else { 698 struct proc *p = pfind(-so->so_pgrp); 699 700 if (p) 701 psignal(p, SIGURG); 702 } 703 } 704