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