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