1 /* uipc_socket.c 4.72 83/03/15 */ 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 return (0); 105 } 106 107 sofree(so) 108 struct socket *so; 109 { 110 111 if (so->so_head) { 112 if (!soqremque(so, 0) && !soqremque(so, 1)) 113 panic("sofree dq"); 114 so->so_head = 0; 115 } 116 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 117 return; 118 sbrelease(&so->so_snd); 119 sbrelease(&so->so_rcv); 120 (void) m_free(dtom(so)); 121 } 122 123 /* 124 * Close a socket on last file table reference removal. 125 * Initiate disconnect if connected. 126 * Free socket when disconnect complete. 127 */ 128 soclose(so, exiting) 129 register struct socket *so; 130 int exiting; 131 { 132 int s = splnet(); /* conservative */ 133 int error; 134 135 if (so->so_options & SO_ACCEPTCONN) { 136 while (so->so_q0 != so) 137 (void) soabort(so->so_q0); 138 while (so->so_q != so) 139 (void) soabort(so->so_q); 140 } 141 if (so->so_pcb == 0) 142 goto discard; 143 if (exiting) 144 so->so_options |= SO_KEEPALIVE; 145 if (so->so_state & SS_ISCONNECTED) { 146 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 147 error = sodisconnect(so, (struct mbuf *)0); 148 if (error) { 149 if (exiting) 150 goto drop; 151 splx(s); 152 return (error); 153 } 154 } 155 if (so->so_options & SO_LINGER) { 156 if ((so->so_state & SS_ISDISCONNECTING) && 157 (so->so_state & SS_NBIO) && 158 exiting == 0) 159 return (EINPROGRESS); 160 /* should use tsleep here, for at most linger */ 161 while (so->so_state & SS_ISCONNECTED) 162 sleep((caddr_t)&so->so_timeo, PZERO+1); 163 } 164 } 165 drop: 166 if (so->so_pcb) { 167 error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 168 (struct mbuf *)0, (struct mbuf *)0); 169 if (exiting == 0 && error) { 170 splx(s); 171 return (error); 172 } 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 (0); 181 } 182 183 /* 184 * Must be called at splnet... 185 */ 186 soabort(so) 187 struct socket *so; 188 { 189 int error; 190 191 error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 192 (struct mbuf *)0, (struct mbuf *)0); 193 return (error); 194 } 195 196 /*ARGSUSED*/ 197 sostat(so, ub) 198 struct socket *so; 199 struct stat *ub; 200 { 201 struct stat sb; 202 203 bzero((caddr_t)&sb, sizeof (sb)); /* XXX */ 204 (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */ 205 return (0); /* XXX */ 206 } 207 208 soaccept(so, nam) 209 struct socket *so; 210 struct mbuf *nam; 211 { 212 int s = splnet(); 213 int error; 214 215 if ((so->so_state & SS_NOFDREF) == 0) 216 panic("soaccept: !NOFDREF"); 217 so->so_state &= ~SS_NOFDREF; 218 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 219 (struct mbuf *)0, nam); 220 splx(s); 221 return (error); 222 } 223 224 soconnect(so, nam) 225 struct socket *so; 226 struct mbuf *nam; 227 { 228 int s = splnet(); 229 int error; 230 231 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 232 error = EISCONN; 233 goto bad; 234 } 235 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 236 (struct mbuf *)0, nam); 237 bad: 238 splx(s); 239 return (error); 240 } 241 242 sodisconnect(so, nam) 243 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); 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) 273 register struct socket *so; 274 struct mbuf *nam; 275 struct uio *uio; 276 int flags; 277 { 278 struct mbuf *top = 0; 279 register struct mbuf *m, **mp = ⊤ 280 register int len; 281 int error = 0, space, s, dontroute; 282 283 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 284 return (EMSGSIZE); 285 dontroute = (flags & SOF_DONTROUTE) && 286 (so->so_options & SO_DONTROUTE) == 0 && 287 (so->so_proto->pr_flags & PR_ATOMIC); 288 restart: 289 sblock(&so->so_snd); 290 #define snderr(errno) { error = errno; splx(s); goto release; } 291 292 u.u_ru.ru_msgsnd++; 293 again: 294 s = splnet(); 295 if (so->so_state & SS_CANTSENDMORE) { 296 psignal(u.u_procp, SIGPIPE); 297 snderr(EPIPE); 298 } 299 if (so->so_error) { 300 error = so->so_error; 301 so->so_error = 0; /* ??? */ 302 splx(s); 303 goto release; 304 } 305 if ((so->so_state & SS_ISCONNECTED) == 0) { 306 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 307 snderr(ENOTCONN); 308 if (nam == 0) 309 snderr(EDESTADDRREQ); 310 } 311 if (top) { 312 if (dontroute) 313 so->so_options |= SO_DONTROUTE; 314 error = (*so->so_proto->pr_usrreq)(so, 315 (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 316 top, (caddr_t)nam); 317 if (dontroute) 318 so->so_options &= ~SO_DONTROUTE; 319 top = 0; 320 if (error) { 321 splx(s); 322 goto release; 323 } 324 mp = ⊤ 325 } 326 if (uio->uio_resid == 0) { 327 splx(s); 328 goto release; 329 } 330 if (flags & SOF_OOB) 331 space = 1024; 332 else { 333 space = sbspace(&so->so_snd); 334 if (space <= 0 || 335 sosendallatonce(so) && space < uio->uio_resid) { 336 if (so->so_state & SS_NBIO) 337 snderr(EWOULDBLOCK); 338 sbunlock(&so->so_snd); 339 sbwait(&so->so_snd); 340 splx(s); 341 goto restart; 342 } 343 } 344 splx(s); 345 while (uio->uio_resid > 0 && space > 0) { 346 register struct iovec *iov = uio->uio_iov; 347 348 if (iov->iov_len == 0) { 349 uio->uio_iov++; 350 uio->uio_iovcnt--; 351 if (uio->uio_iovcnt < 0) 352 panic("sosend"); 353 continue; 354 } 355 MGET(m, M_WAIT, MT_DATA); 356 if (m == NULL) { 357 error = ENOBUFS; /* SIGPIPE? */ 358 goto release; 359 } 360 if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 361 register struct mbuf *p; 362 MCLGET(p, 1); 363 if (p == 0) 364 goto nopages; 365 m->m_off = (int)p - (int)m; 366 len = CLBYTES; 367 } else { 368 nopages: 369 len = MIN(MLEN, iov->iov_len); 370 } 371 (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 372 m->m_len = len; 373 *mp = m; 374 mp = &m->m_next; 375 if (flags & SOF_OOB) 376 space -= len; 377 else 378 space = sbspace(&so->so_snd); 379 } 380 goto again; 381 382 release: 383 sbunlock(&so->so_snd); 384 if (top) 385 m_freem(top); 386 return (error); 387 } 388 389 soreceive(so, aname, uio, flags) 390 register struct socket *so; 391 struct mbuf **aname; 392 struct uio *uio; 393 int flags; 394 { 395 register struct mbuf *m, *n; 396 int len; 397 int eor, s, error = 0, moff, tomark; 398 399 if (flags & SOF_OOB) { 400 m = m_get(M_WAIT, MT_DATA); 401 if (m == NULL) 402 return (ENOBUFS); 403 error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 404 m, (struct mbuf *)0); 405 if (error) 406 goto bad; 407 do { 408 len = uio->uio_resid; 409 if (len > m->m_len) 410 len = m->m_len; 411 error = 412 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 413 m = m_free(m); 414 } while (uio->uio_resid && error == 0 && m); 415 bad: 416 if (m) 417 m_freem(m); 418 return (error); 419 } 420 421 restart: 422 sblock(&so->so_rcv); 423 s = splnet(); 424 425 #define rcverr(errno) { error = errno; splx(s); goto release; } 426 if (so->so_rcv.sb_cc == 0) { 427 if (so->so_error) { 428 error = so->so_error; 429 so->so_error = 0; 430 splx(s); 431 goto release; 432 } 433 if (so->so_state & SS_CANTRCVMORE) { 434 splx(s); 435 goto release; 436 } 437 if ((so->so_state & SS_ISCONNECTED) == 0 && 438 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 439 rcverr(ENOTCONN); 440 if (so->so_state & SS_NBIO) 441 rcverr(EWOULDBLOCK); 442 sbunlock(&so->so_rcv); 443 sbwait(&so->so_rcv); 444 splx(s); 445 goto restart; 446 } 447 u.u_ru.ru_msgrcv++; 448 m = so->so_rcv.sb_mb; 449 if (m == 0) 450 panic("receive"); 451 if (so->so_proto->pr_flags & PR_ADDR) { 452 if ((flags & SOF_PREVIEW) == 0) { 453 so->so_rcv.sb_cc -= m->m_len; 454 so->so_rcv.sb_mbcnt -= MSIZE; 455 } 456 if (aname) { 457 if (flags & SOF_PREVIEW) { 458 *aname = m_copy(m, 0, m->m_len); 459 if (*aname == NULL) 460 panic("receive 2"); 461 } else 462 *aname = m; 463 m = m->m_next; 464 (*aname)->m_next = 0; 465 } else 466 if (flags & SOF_PREVIEW) 467 m = m->m_next; 468 else 469 m = m_free(m); 470 if (m == 0) 471 panic("receive 3"); 472 if ((flags & SOF_PREVIEW) == 0) 473 so->so_rcv.sb_mb = m; 474 } 475 eor = 0; 476 moff = 0; 477 tomark = so->so_oobmark; 478 do { 479 if (uio->uio_resid <= 0) 480 break; 481 len = uio->uio_resid; 482 so->so_state &= ~SS_RCVATMARK; 483 if (tomark && len > tomark) 484 len = tomark; 485 if (moff+len > m->m_len - moff) 486 len = m->m_len - moff; 487 splx(s); 488 error = 489 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 490 s = splnet(); 491 if (len == m->m_len) { 492 eor = (int)m->m_act; 493 if (flags & SOF_PREVIEW) 494 m = m->m_next; 495 else { 496 sbfree(&so->so_rcv, m); 497 MFREE(m, n); 498 m = n; 499 so->so_rcv.sb_mb = m; 500 } 501 moff = 0; 502 } else { 503 if (flags & SOF_PREVIEW) 504 moff += len; 505 else { 506 m->m_off += len; 507 m->m_len -= len; 508 so->so_rcv.sb_cc -= len; 509 } 510 } 511 if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 512 so->so_oobmark -= len; 513 if (so->so_oobmark == 0) { 514 so->so_state |= SS_RCVATMARK; 515 break; 516 } 517 } 518 if (tomark) { 519 tomark -= len; 520 if (tomark == 0) 521 break; 522 } 523 } while (m && error == 0 && !eor); 524 if (flags & SOF_PREVIEW) 525 goto release; 526 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 527 do { 528 if (m == 0) 529 panic("receive 4"); 530 sbfree(&so->so_rcv, m); 531 eor = (int)m->m_act; 532 so->so_rcv.sb_mb = m->m_next; 533 MFREE(m, n); 534 m = n; 535 } while (eor == 0); 536 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 537 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 538 (struct mbuf *)0, (struct mbuf *)0); 539 release: 540 sbunlock(&so->so_rcv); 541 splx(s); 542 return (error); 543 } 544 545 soshutdown(so, how) 546 struct socket *so; 547 int how; 548 { 549 550 how++; 551 if (how & FREAD) { 552 int s = splimp(); 553 socantrcvmore(so); 554 sbflush(&so->so_rcv); 555 splx(s); 556 } 557 if (how & FWRITE) 558 return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 559 (struct mbuf *)0, (struct mbuf *)0)); 560 return (0); 561 } 562 563 sosetopt(so, level, optname, m) 564 struct socket *so; 565 int level, optname; 566 struct mbuf *m; 567 { 568 569 if (level != SOL_SOCKET) 570 return (EINVAL); /* XXX */ 571 switch (optname) { 572 573 case SO_DEBUG: 574 case SO_KEEPALIVE: 575 case SO_DONTROUTE: 576 case SO_USELOOPBACK: 577 case SO_REUSEADDR: 578 so->so_options |= optname; 579 break; 580 581 case SO_LINGER: 582 if (m == NULL || m->m_len != sizeof (int)) 583 return (EINVAL); 584 so->so_options |= SO_LINGER; 585 so->so_linger = *mtod(m, int *); 586 break; 587 588 case SO_DONTLINGER: 589 so->so_options &= ~SO_LINGER; 590 so->so_linger = 0; 591 break; 592 593 default: 594 return (EINVAL); 595 } 596 return (0); 597 } 598 599 sogetopt(so, level, optname, m) 600 struct socket *so; 601 int level, optname; 602 struct mbuf *m; 603 { 604 605 if (level != SOL_SOCKET) 606 return (EINVAL); /* XXX */ 607 switch (optname) { 608 609 case SO_USELOOPBACK: 610 case SO_DONTROUTE: 611 case SO_DEBUG: 612 case SO_KEEPALIVE: 613 case SO_LINGER: 614 case SO_REUSEADDR: 615 if ((so->so_options & optname) == 0) 616 return (ENOPROTOOPT); 617 if (optname == SO_LINGER && m != NULL) { 618 *mtod(m, int *) = so->so_linger; 619 m->m_len = sizeof (so->so_linger); 620 } 621 break; 622 623 default: 624 return (EINVAL); 625 } 626 return (0); 627 } 628 629 sohasoutofband(so) 630 struct socket *so; 631 { 632 633 if (so->so_pgrp == 0) 634 return; 635 if (so->so_pgrp > 0) 636 gsignal(so->so_pgrp, SIGURG); 637 else { 638 struct proc *p = pfind(-so->so_pgrp); 639 640 if (p) 641 psignal(p, SIGURG); 642 } 643 } 644 645 /*ARGSUSED*/ 646 soioctl(so, cmd, data) 647 register struct socket *so; 648 int cmd; 649 register char *data; 650 { 651 652 switch (cmd) { 653 654 case FIONBIO: 655 if (*(int *)data) 656 so->so_state |= SS_NBIO; 657 else 658 so->so_state &= ~SS_NBIO; 659 break; 660 661 case FIOASYNC: 662 if (*(int *)data) 663 so->so_state |= SS_ASYNC; 664 else 665 so->so_state &= ~SS_ASYNC; 666 break; 667 668 case SIOCSPGRP: 669 so->so_pgrp = *(int *)data; 670 break; 671 672 case SIOCGPGRP: 673 *(int *)data = so->so_pgrp; 674 break; 675 676 case SIOCATMARK: 677 *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 678 break; 679 680 /* routing table update calls */ 681 case SIOCADDRT: 682 case SIOCDELRT: 683 if (!suser()) 684 return (u.u_error); 685 return (rtrequest(cmd, (struct rtentry *)data)); 686 687 /* interface parameter requests */ 688 case SIOCSIFADDR: 689 case SIOCSIFFLAGS: 690 if (!suser()) 691 return (u.u_error); 692 return (ifrequest(cmd, data)); 693 694 case SIOCGIFADDR: 695 case SIOCGIFFLAGS: 696 return (ifrequest(cmd, data)); 697 698 case SIOCGIFCONF: 699 return (ifconf(cmd, data)); 700 701 /* type/protocol specific ioctls */ 702 default: 703 return (ENOTTY); /* XXX */ 704 } 705 return (0); 706 } 707