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