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