1 /* uipc_socket.c 4.51 82/10/05 */ 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 "../net/in.h" 18 #include "../net/in_systm.h" 19 #include "../net/route.h" 20 #include "../h/uio.h" 21 22 /* 23 * Socket operation routines. 24 * These routines are called by the routines in 25 * sys_socket.c or from a system process, and 26 * implement the semantics of socket operations by 27 * switching out to the protocol specific routines. 28 */ 29 30 socreate(dom, aso, type, proto, opt) 31 struct socket **aso; 32 int type, proto; 33 struct socketopt *opt; 34 { 35 register struct protosw *prp; 36 register struct socket *so; 37 struct mbuf *m; 38 int pf, error; 39 40 pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ 41 if (proto) 42 prp = pffindproto(pf, proto); 43 else 44 prp = pffindtype(pf, type); 45 if (prp == 0) 46 return (EPROTONOSUPPORT); 47 if (prp->pr_type != type) 48 return (EPROTOTYPE); 49 m = m_getclr(M_WAIT); 50 if (m == 0) 51 return (ENOBUFS); 52 so = mtod(m, struct socket *); 53 so->so_options = 0; 54 so->so_state = 0; 55 if (u.u_uid == 0) 56 so->so_state = SS_PRIV; 57 so->so_proto = prp; 58 error = (*prp->pr_usrreq)(so, PRU_ATTACH, 59 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 60 if (error) { 61 so->so_state |= SS_NOFDREF; 62 sofree(so); 63 return (error); 64 } 65 *aso = so; 66 return (0); 67 } 68 69 sobind(so, nam, opt) 70 struct socket *so; 71 struct mbuf *nam; 72 struct socketopt *opt; 73 { 74 int s = splnet(); 75 int error; 76 77 error = 78 (*so->so_proto->pr_usrreq)(so, PRU_BIND, 79 (struct mbuf *)0, nam, opt); 80 splx(s); 81 return (error); 82 } 83 84 solisten(so, backlog) 85 struct socket *so; 86 int backlog; 87 { 88 int s = splnet(); 89 int error; 90 91 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 92 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 93 if (error) { 94 splx(s); 95 return (error); 96 } 97 if (so->so_q == 0) { 98 so->so_q = so; 99 so->so_q0 = so; 100 so->so_options |= SO_ACCEPTCONN; 101 } 102 if (backlog < 0) 103 backlog = 0; 104 so->so_qlimit = backlog < 5 ? backlog : 5; 105 so->so_options |= SO_NEWFDONCONN; 106 return (0); 107 } 108 109 sofree(so) 110 struct socket *so; 111 { 112 113 if (so->so_head) { 114 if (!soqremque(so, 0) && !soqremque(so, 1)) 115 panic("sofree dq"); 116 so->so_head = 0; 117 } 118 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 119 return; 120 sbrelease(&so->so_snd); 121 sbrelease(&so->so_rcv); 122 (void) m_free(dtom(so)); 123 } 124 125 /* 126 * Close a socket on last file table reference removal. 127 * Initiate disconnect if connected. 128 * Free socket when disconnect complete. 129 */ 130 soclose(so, exiting) 131 register struct socket *so; 132 int exiting; 133 { 134 int s = splnet(); /* conservative */ 135 136 if (so->so_options & SO_ACCEPTCONN) { 137 while (so->so_q0 != so) 138 soclose(so->so_q0, 1); 139 while (so->so_q != so) 140 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 u.u_error = sodisconnect(so, (struct sockaddr *)0); 149 if (u.u_error) { 150 if (exiting) 151 goto drop; 152 splx(s); 153 return; 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 u.u_error = EINPROGRESS; 161 splx(s); 162 return; 163 } 164 /* should use tsleep here, for at most linger */ 165 while (so->so_state & SS_ISCONNECTED) 166 sleep((caddr_t)&so->so_timeo, PZERO+1); 167 } 168 } 169 drop: 170 if (so->so_pcb) { 171 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 172 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 173 if (exiting == 0 && u.u_error) { 174 splx(s); 175 return; 176 } 177 } 178 discard: 179 so->so_state |= SS_NOFDREF; 180 sofree(so); 181 splx(s); 182 } 183 184 /*ARGSUSED*/ 185 sostat(so, sb) 186 struct socket *so; 187 struct stat *sb; 188 { 189 190 bzero((caddr_t)sb, 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 u_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 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 iovec *iov; 374 register struct mbuf *m, *n; 375 u_int len; 376 int eor, s, error = 0, moff, tomark; 377 378 if (flags & SOF_OOB) { 379 struct mbuf *m = m_get(M_WAIT); 380 381 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 382 m, (struct mbuf *)0, (struct socketopt *)0); 383 len = uio->uio_resid; 384 do { 385 if (len > m->m_len) 386 len = m->m_len; 387 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 388 m = m_free(m); 389 } while (uio->uio_resid && u.u_error == 0 && m); 390 if (m) 391 (void) m_freem(m); 392 return; 393 } 394 395 restart: 396 sblock(&so->so_rcv); 397 s = splnet(); 398 399 #define rcverr(errno) { error = errno; splx(s); goto release; } 400 if (so->so_rcv.sb_cc == 0) { 401 if (so->so_error) { 402 error = so->so_error; 403 so->so_error = 0; 404 splx(s); 405 goto release; 406 } 407 if (so->so_state & SS_CANTRCVMORE) { 408 splx(s); 409 goto release; 410 } 411 if ((so->so_state & SS_ISCONNECTED) == 0 && 412 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 413 rcverr(ENOTCONN); 414 if (so->so_state & SS_NBIO) 415 rcverr(EWOULDBLOCK); 416 sbunlock(&so->so_rcv); 417 sbwait(&so->so_rcv); 418 splx(s); 419 goto restart; 420 } 421 u.u_ru.ru_msgrcv++; 422 m = so->so_rcv.sb_mb; 423 if (m == 0) 424 panic("receive"); 425 if (so->so_proto->pr_flags & PR_ADDR) { 426 if ((flags & SOF_PREVIEW) == 0) { 427 so->so_rcv.sb_cc -= m->m_len; 428 so->so_rcv.sb_mbcnt -= MSIZE; 429 } 430 if (aname) { 431 if (flags & SOF_PREVIEW) 432 *aname = m_copy(m, 0, m->m_len); 433 else 434 *aname = m; 435 m = m->m_next; 436 (*aname)->m_next = 0; 437 } else 438 if (flags & SOF_PREVIEW) 439 m = m->m_next; 440 else 441 m = m_free(m); 442 if (m == 0) 443 panic("receive 2"); 444 } 445 eor = 0; 446 moff = 0; 447 tomark = so->so_oobmark; 448 do { 449 if (uio->uio_resid <= 0) 450 break; 451 len = uio->uio_resid; 452 so->so_state &= ~SS_RCVATMARK; 453 if (tomark && len > tomark) 454 len = tomark; 455 if (len > m->m_len - moff) 456 len = m->m_len - moff; 457 splx(s); 458 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 459 s = splnet(); 460 if (len == m->m_len) { 461 eor = (int)m->m_act; 462 if (flags & SOF_PREVIEW) 463 m = m->m_next; 464 else { 465 sbfree(&so->so_rcv, m); 466 MFREE(m, n); 467 m = n; 468 } 469 moff = 0; 470 } else { 471 if (flags & SOF_PREVIEW) 472 moff += len; 473 else { 474 m->m_off += len; 475 m->m_len -= len; 476 so->so_rcv.sb_cc -= len; 477 } 478 } 479 if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 480 so->so_oobmark -= len; 481 if (so->so_oobmark == 0) { 482 so->so_state |= SS_RCVATMARK; 483 break; 484 } 485 } 486 if (tomark) { 487 tomark -= len; 488 if (tomark == 0) 489 break; 490 } 491 } while (m && !eor); 492 if (flags & SOF_PREVIEW) 493 goto release; 494 so->so_rcv.sb_mb = m; 495 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 496 do { 497 if (m == 0) 498 panic("receive 3"); 499 sbfree(&so->so_rcv, m); 500 eor = (int)m->m_act; 501 so->so_rcv.sb_mb = m->m_next; 502 MFREE(m, n); 503 m = n; 504 } while (eor == 0); 505 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 506 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 507 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 508 release: 509 sbunlock(&so->so_rcv); 510 splx(s); 511 return (error); 512 } 513 514 sohasoutofband(so) 515 struct socket *so; 516 { 517 518 if (so->so_pgrp == 0) 519 return; 520 if (so->so_pgrp > 0) 521 gsignal(so->so_pgrp, SIGURG); 522 else { 523 struct proc *p = pfind(-so->so_pgrp); 524 525 if (p) 526 psignal(p, SIGURG); 527 } 528 } 529 530 /*ARGSUSED*/ 531 soioctl(so, cmd, data) 532 register struct socket *so; 533 int cmd; 534 register char *data; 535 { 536 537 switch (cmd) { 538 539 case FIONBIO: 540 if (*(int *)data) 541 so->so_state |= SS_NBIO; 542 else 543 so->so_state &= ~SS_NBIO; 544 return; 545 546 case FIOASYNC: 547 if (*(int *)data) 548 so->so_state |= SS_ASYNC; 549 else 550 so->so_state &= ~SS_ASYNC; 551 return; 552 553 case SIOCSKEEP: 554 if (*(int *)data) 555 so->so_options &= ~SO_KEEPALIVE; 556 else 557 so->so_options |= SO_KEEPALIVE; 558 return; 559 560 case SIOCGKEEP: 561 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 562 return; 563 564 case SIOCSLINGER: 565 so->so_linger = *(int *)data; 566 if (so->so_linger) 567 so->so_options &= ~SO_DONTLINGER; 568 else 569 so->so_options |= SO_DONTLINGER; 570 return; 571 572 case SIOCGLINGER: 573 *(int *)data = so->so_linger; 574 return; 575 576 case SIOCSPGRP: 577 so->so_pgrp = *(int *)data; 578 return; 579 580 case SIOCGPGRP: 581 *(int *)data = so->so_pgrp; 582 return; 583 584 case SIOCDONE: { 585 int flags = *(int *)data; 586 587 flags++; 588 if (flags & FREAD) { 589 int s = splimp(); 590 socantrcvmore(so); 591 sbflush(&so->so_rcv); 592 splx(s); 593 } 594 if (flags & FWRITE) 595 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 596 (struct mbuf *)0, (struct mbuf *)0, 597 (struct socketopt *)0); 598 return; 599 } 600 601 case SIOCSENDOOB: { 602 char oob = *(char *)data; 603 struct mbuf *m = m_get(M_DONTWAIT); 604 605 if (m == 0) { 606 u.u_error = ENOBUFS; 607 return; 608 } 609 m->m_len = 1; 610 *mtod(m, char *) = oob; 611 (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 612 m, (struct mbuf *)0, (struct socketopt *)0); 613 return; 614 } 615 616 case SIOCRCVOOB: { 617 struct mbuf *m = m_get(M_WAIT); 618 619 if (m == 0) { 620 u.u_error = ENOBUFS; 621 return; 622 } 623 *mtod(m, caddr_t) = 0; 624 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 625 m, (struct mbuf *)0, (struct socketopt *)0); 626 *(char *)data = *mtod(m, char *); 627 (void) m_free(m); 628 return; 629 } 630 631 case SIOCATMARK: 632 *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 633 return; 634 635 /* routing table update calls */ 636 case SIOCADDRT: 637 case SIOCDELRT: 638 if (!suser()) 639 return; 640 u.u_error = rtrequest(cmd, (struct rtentry *)data); 641 return; 642 643 /* type/protocol specific ioctls */ 644 } 645 u.u_error = EOPNOTSUPP; 646 } 647