1 /* uipc_socket.c 4.75 83/05/27 */ 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 #ifdef notdef 230 soconnect2(so1, so2) 231 register struct socket *so1; 232 struct socket *so2; 233 { 234 int s = splnet(); 235 int error; 236 237 error = 238 (*so1->so_proto->pr_usrreq)(so, PRU_CONNECT2, 239 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 240 splx(s); 241 return (error); 242 } 243 #endif 244 245 sodisconnect(so, nam) 246 register struct socket *so; 247 struct mbuf *nam; 248 { 249 int s = splnet(); 250 int error; 251 252 if ((so->so_state & SS_ISCONNECTED) == 0) { 253 error = ENOTCONN; 254 goto bad; 255 } 256 if (so->so_state & SS_ISDISCONNECTING) { 257 error = EALREADY; 258 goto bad; 259 } 260 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 261 (struct mbuf *)0, nam, (struct mbuf *)0); 262 bad: 263 splx(s); 264 return (error); 265 } 266 267 /* 268 * Send on a socket. 269 * If send must go all at once and message is larger than 270 * send buffering, then hard error. 271 * Lock against other senders. 272 * If must go all at once and not enough room now, then 273 * inform user that this would block and do nothing. 274 */ 275 sosend(so, nam, uio, flags, rights) 276 register struct socket *so; 277 struct mbuf *nam; 278 register struct uio *uio; 279 int flags; 280 struct mbuf *rights; 281 { 282 struct mbuf *top = 0; 283 register struct mbuf *m, **mp = ⊤ 284 register int space; 285 int len, error = 0, s, dontroute; 286 287 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 288 return (EMSGSIZE); 289 dontroute = 290 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 291 (so->so_proto->pr_flags & PR_ATOMIC); 292 restart: 293 sblock(&so->so_snd); 294 #define snderr(errno) { error = errno; splx(s); goto release; } 295 296 u.u_ru.ru_msgsnd++; 297 again: 298 s = splnet(); 299 if (so->so_state & SS_CANTSENDMORE) { 300 psignal(u.u_procp, SIGPIPE); 301 snderr(EPIPE); 302 } 303 if (so->so_error) { 304 error = so->so_error; 305 so->so_error = 0; /* ??? */ 306 splx(s); 307 goto release; 308 } 309 if ((so->so_state & SS_ISCONNECTED) == 0) { 310 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 311 snderr(ENOTCONN); 312 if (nam == 0) 313 snderr(EDESTADDRREQ); 314 } 315 if (top) { 316 if (dontroute) 317 so->so_options |= SO_DONTROUTE; 318 error = (*so->so_proto->pr_usrreq)(so, 319 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 320 top, (caddr_t)nam, rights); 321 if (dontroute) 322 so->so_options &= ~SO_DONTROUTE; 323 top = 0; 324 if (error) { 325 splx(s); 326 goto release; 327 } 328 mp = ⊤ 329 } 330 if (uio->uio_resid == 0) { 331 splx(s); 332 goto release; 333 } 334 if (flags & MSG_OOB) 335 space = 1024; 336 else { 337 space = sbspace(&so->so_snd); 338 if (space <= 0 || 339 sosendallatonce(so) && space < uio->uio_resid) { 340 if (so->so_state & SS_NBIO) 341 snderr(EWOULDBLOCK); 342 sbunlock(&so->so_snd); 343 sbwait(&so->so_snd); 344 splx(s); 345 goto restart; 346 } 347 } 348 splx(s); 349 while (uio->uio_resid > 0 && space > 0) { 350 register struct iovec *iov = uio->uio_iov; 351 352 if (iov->iov_len == 0) { 353 uio->uio_iov++; 354 uio->uio_iovcnt--; 355 if (uio->uio_iovcnt < 0) 356 panic("sosend"); 357 continue; 358 } 359 MGET(m, M_WAIT, MT_DATA); 360 if (m == NULL) { 361 error = ENOBUFS; /* SIGPIPE? */ 362 goto release; 363 } 364 if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 365 register struct mbuf *p; 366 MCLGET(p, 1); 367 if (p == 0) 368 goto nopages; 369 m->m_off = (int)p - (int)m; 370 len = CLBYTES; 371 } else { 372 nopages: 373 len = MIN(MLEN, iov->iov_len); 374 } 375 (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 376 m->m_len = len; 377 *mp = m; 378 mp = &m->m_next; 379 if (flags & MSG_OOB) 380 space -= len; 381 else 382 space = sbspace(&so->so_snd); 383 } 384 goto again; 385 386 release: 387 sbunlock(&so->so_snd); 388 if (top) 389 m_freem(top); 390 return (error); 391 } 392 393 soreceive(so, aname, uio, flags, rightsp) 394 register struct socket *so; 395 struct mbuf **aname; 396 register struct uio *uio; 397 int flags; 398 struct mbuf **rightsp; 399 { 400 register struct mbuf *m, *n; 401 register int len, error = 0, s, eor, tomark; 402 struct protosw *pr = so->so_proto; 403 int moff; 404 405 if (rightsp) 406 *rightsp = 0; 407 if (aname) 408 *aname = 0; 409 if (flags & MSG_OOB) { 410 m = m_get(M_WAIT, MT_DATA); 411 if (m == 0) 412 return (ENOBUFS); 413 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 414 m, (struct mbuf *)0, (struct mbuf *)0); 415 if (error) 416 goto bad; 417 do { 418 len = uio->uio_resid; 419 if (len > m->m_len) 420 len = m->m_len; 421 error = 422 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 423 m = m_free(m); 424 } while (uio->uio_resid && error == 0 && m); 425 bad: 426 if (m) 427 m_freem(m); 428 return (error); 429 } 430 431 restart: 432 sblock(&so->so_rcv); 433 s = splnet(); 434 435 #define rcverr(errno) { error = errno; splx(s); goto release; } 436 if (so->so_rcv.sb_cc == 0) { 437 if (so->so_error) { 438 error = so->so_error; 439 so->so_error = 0; 440 splx(s); 441 goto release; 442 } 443 if (so->so_state & SS_CANTRCVMORE) { 444 splx(s); 445 goto release; 446 } 447 if ((so->so_state & SS_ISCONNECTED) == 0 && 448 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 449 rcverr(ENOTCONN); 450 if (so->so_state & SS_NBIO) 451 rcverr(EWOULDBLOCK); 452 sbunlock(&so->so_rcv); 453 sbwait(&so->so_rcv); 454 splx(s); 455 goto restart; 456 } 457 u.u_ru.ru_msgrcv++; 458 m = so->so_rcv.sb_mb; 459 if (m == 0) 460 panic("receive"); 461 if (pr->pr_flags & PR_ADDR) { 462 if ((flags & MSG_PEEK) == 0) { 463 so->so_rcv.sb_cc -= m->m_len; 464 so->so_rcv.sb_mbcnt -= MSIZE; 465 } 466 if (aname) { 467 if (flags & MSG_PEEK) { 468 *aname = m_copy(m, 0, m->m_len); 469 if (*aname == NULL) 470 panic("receive 2"); 471 } else 472 *aname = m; 473 m = m->m_next; 474 (*aname)->m_next = 0; 475 } else 476 if (flags & MSG_PEEK) 477 m = m->m_next; 478 else 479 m = m_free(m); 480 if (m == 0) 481 panic("receive 2a"); 482 if (rightsp) { 483 if (m->m_len) 484 *rightsp = m_copy(m, 0, m->m_len); 485 else { 486 *rightsp = m_get(M_DONTWAIT, MT_SONAME); 487 if (*rightsp) 488 (*rightsp)->m_len = 0; 489 } 490 if (*rightsp == NULL) 491 panic("receive 2b"); 492 } 493 if (flags & MSG_PEEK) 494 m = m->m_next; 495 else { 496 so->so_rcv.sb_cc -= m->m_len; 497 so->so_rcv.sb_mbcnt -= MSIZE; 498 m = m_free(m); 499 } 500 if (m == 0) 501 panic("receive 3"); 502 if ((flags & MSG_PEEK) == 0) 503 so->so_rcv.sb_mb = m; 504 } 505 eor = 0; 506 moff = 0; 507 tomark = so->so_oobmark; 508 do { 509 if (uio->uio_resid <= 0) 510 break; 511 len = uio->uio_resid; 512 so->so_state &= ~SS_RCVATMARK; 513 if (tomark && len > tomark) 514 len = tomark; 515 if (moff+len > m->m_len - moff) 516 len = m->m_len - moff; 517 splx(s); 518 error = 519 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 520 s = splnet(); 521 if (len == m->m_len) { 522 eor = (int)m->m_act; 523 if (flags & MSG_PEEK) 524 m = m->m_next; 525 else { 526 sbfree(&so->so_rcv, m); 527 MFREE(m, n); 528 m = n; 529 so->so_rcv.sb_mb = m; 530 } 531 moff = 0; 532 } else { 533 if (flags & MSG_PEEK) 534 moff += len; 535 else { 536 m->m_off += len; 537 m->m_len -= len; 538 so->so_rcv.sb_cc -= len; 539 } 540 } 541 if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { 542 so->so_oobmark -= len; 543 if (so->so_oobmark == 0) { 544 so->so_state |= SS_RCVATMARK; 545 break; 546 } 547 } 548 if (tomark) { 549 tomark -= len; 550 if (tomark == 0) 551 break; 552 } 553 } while (m && error == 0 && !eor); 554 if (flags & MSG_PEEK) 555 goto release; 556 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 557 do { 558 if (m == 0) 559 panic("receive 4"); 560 sbfree(&so->so_rcv, m); 561 eor = (int)m->m_act; 562 so->so_rcv.sb_mb = m->m_next; 563 MFREE(m, n); 564 m = n; 565 } while (eor == 0); 566 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 567 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 568 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 569 release: 570 sbunlock(&so->so_rcv); 571 if (error == 0 && rightsp && 572 *rightsp && so->so_proto->pr_family == AF_UNIX) 573 error = unp_externalize(*rightsp); 574 splx(s); 575 return (error); 576 } 577 578 soshutdown(so, how) 579 register struct socket *so; 580 register int how; 581 { 582 register struct protosw *pr = so->so_proto; 583 584 how++; 585 if (how & FREAD) 586 sorflush(so); 587 if (how & FWRITE) 588 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 589 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 590 return (0); 591 } 592 593 sorflush(so) 594 register struct socket *so; 595 { 596 register struct sockbuf *sb = &so->so_rcv; 597 register struct protosw *pr = so->so_proto; 598 register int s; 599 struct sockbuf asb; 600 601 sblock(sb); 602 s = splimp(); 603 socantrcvmore(so); 604 sbunlock(sb); 605 asb = *sb; 606 bzero((caddr_t)sb, sizeof (*sb)); 607 splx(s); 608 if (pr->pr_family == AF_UNIX && (pr->pr_flags & PR_RIGHTS)) 609 unp_scan(asb.sb_mb, unp_discard); 610 sbrelease(&asb); 611 } 612 613 sosetopt(so, level, optname, m) 614 register struct socket *so; 615 int level, optname; 616 register struct mbuf *m; 617 { 618 619 if (level != SOL_SOCKET) 620 return (EINVAL); /* XXX */ 621 switch (optname) { 622 623 case SO_DEBUG: 624 case SO_KEEPALIVE: 625 case SO_DONTROUTE: 626 case SO_USELOOPBACK: 627 case SO_REUSEADDR: 628 so->so_options |= optname; 629 break; 630 631 case SO_LINGER: 632 if (m == NULL || m->m_len != sizeof (int)) 633 return (EINVAL); 634 so->so_options |= SO_LINGER; 635 so->so_linger = *mtod(m, int *); 636 break; 637 638 case SO_DONTLINGER: 639 so->so_options &= ~SO_LINGER; 640 so->so_linger = 0; 641 break; 642 643 default: 644 return (EINVAL); 645 } 646 return (0); 647 } 648 649 sogetopt(so, level, optname, m) 650 register struct socket *so; 651 int level, optname; 652 register struct mbuf *m; 653 { 654 655 if (level != SOL_SOCKET) 656 return (EINVAL); /* XXX */ 657 switch (optname) { 658 659 case SO_USELOOPBACK: 660 case SO_DONTROUTE: 661 case SO_DEBUG: 662 case SO_KEEPALIVE: 663 case SO_LINGER: 664 case SO_REUSEADDR: 665 if ((so->so_options & optname) == 0) 666 return (ENOPROTOOPT); 667 if (optname == SO_LINGER && m != NULL) { 668 *mtod(m, int *) = so->so_linger; 669 m->m_len = sizeof (so->so_linger); 670 } 671 break; 672 673 default: 674 return (EINVAL); 675 } 676 return (0); 677 } 678 679 sohasoutofband(so) 680 register struct socket *so; 681 { 682 683 if (so->so_pgrp == 0) 684 return; 685 if (so->so_pgrp > 0) 686 gsignal(so->so_pgrp, SIGURG); 687 else { 688 struct proc *p = pfind(-so->so_pgrp); 689 690 if (p) 691 psignal(p, SIGURG); 692 } 693 } 694