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