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