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