1 /* uipc_socket.c 4.50 82/10/03 */ 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) 258 register struct socket *so; 259 struct mbuf *nam; 260 struct uio *uio; 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 #ifdef notdef 270 /* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING */ 271 if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 272 return (EWOULDBLOCK); 273 #endif 274 restart: 275 sblock(&so->so_snd); 276 #define snderr(errno) { error = errno; splx(s); goto release; } 277 278 u.u_ru.ru_msgsnd++; 279 again: 280 s = splnet(); 281 if (so->so_state & SS_CANTSENDMORE) { 282 psignal(u.u_procp, SIGPIPE); 283 snderr(EPIPE); 284 } 285 if (so->so_error) { 286 error = so->so_error; 287 so->so_error = 0; /* ??? */ 288 splx(s); 289 goto release; 290 } 291 if ((so->so_state & SS_ISCONNECTED) == 0) { 292 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 293 snderr(ENOTCONN); 294 if (nam == 0) 295 snderr(EDESTADDRREQ); 296 } 297 if (top) { 298 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, 299 top, (caddr_t)nam, (struct socketopt *)0); 300 top = 0; 301 if (error) { 302 splx(s); 303 goto release; 304 } 305 mp = ⊤ 306 } 307 if (uio->uio_resid == 0) { 308 splx(s); 309 goto release; 310 } 311 space = sbspace(&so->so_snd); 312 if (space <= 0 || 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 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 m->m_off = MMINOFF; 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 space = sbspace(&so->so_snd); 353 } 354 goto again; 355 356 release: 357 sbunlock(&so->so_snd); 358 if (top) 359 m_freem(top); 360 return (error); 361 } 362 363 soreceive(so, aname, uio) 364 register struct socket *so; 365 struct mbuf **aname; 366 struct uio *uio; 367 { 368 register struct iovec *iov; 369 register struct mbuf *m, *n; 370 u_int len; 371 int eor, s, error = 0; 372 373 restart: 374 sblock(&so->so_rcv); 375 s = splnet(); 376 377 #define rcverr(errno) { error = errno; splx(s); goto release; } 378 if (so->so_rcv.sb_cc == 0) { 379 if (so->so_error) { 380 error = so->so_error; 381 so->so_error = 0; 382 splx(s); 383 goto release; 384 } 385 if (so->so_state & SS_CANTRCVMORE) { 386 splx(s); 387 goto release; 388 } 389 if ((so->so_state & SS_ISCONNECTED) == 0 && 390 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 391 rcverr(ENOTCONN); 392 if (so->so_state & SS_NBIO) 393 rcverr(EWOULDBLOCK); 394 sbunlock(&so->so_rcv); 395 sbwait(&so->so_rcv); 396 splx(s); 397 goto restart; 398 } 399 u.u_ru.ru_msgrcv++; 400 m = so->so_rcv.sb_mb; 401 if (m == 0) 402 panic("receive"); 403 if (so->so_proto->pr_flags & PR_ADDR) { 404 so->so_rcv.sb_cc -= m->m_len; 405 so->so_rcv.sb_mbcnt -= MSIZE; 406 if (aname) { 407 *aname = m; 408 m = m->m_next; 409 (*aname)->m_next = 0; 410 } else 411 m = m_free(m); 412 if (m == 0) 413 panic("receive 2"); 414 so->so_rcv.sb_mb = m; 415 } 416 eor = 0; 417 do { 418 if (uio->uio_resid <= 0) 419 break; 420 len = uio->uio_resid; 421 so->so_state &= ~SS_RCVATMARK; 422 if (so->so_oobmark && len > so->so_oobmark) 423 len = so->so_oobmark; 424 if (len > m->m_len) 425 len = m->m_len; 426 splx(s); 427 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 428 s = splnet(); 429 if (len == m->m_len) { 430 eor = (int)m->m_act; 431 sbfree(&so->so_rcv, m); 432 so->so_rcv.sb_mb = m->m_next; 433 MFREE(m, n); 434 } else { 435 m->m_off += len; 436 m->m_len -= len; 437 so->so_rcv.sb_cc -= len; 438 } 439 if (so->so_oobmark) { 440 so->so_oobmark -= len; 441 if (so->so_oobmark == 0) { 442 so->so_state |= SS_RCVATMARK; 443 break; 444 } 445 } 446 } while ((m = so->so_rcv.sb_mb) && !eor); 447 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 448 do { 449 if (m == 0) 450 panic("receive 3"); 451 sbfree(&so->so_rcv, m); 452 eor = (int)m->m_act; 453 so->so_rcv.sb_mb = m->m_next; 454 MFREE(m, n); 455 m = n; 456 } while (eor == 0); 457 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 458 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 459 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 460 release: 461 sbunlock(&so->so_rcv); 462 splx(s); 463 return (error); 464 } 465 466 sohasoutofband(so) 467 struct socket *so; 468 { 469 470 if (so->so_pgrp == 0) 471 return; 472 if (so->so_pgrp > 0) 473 gsignal(so->so_pgrp, SIGURG); 474 else { 475 struct proc *p = pfind(-so->so_pgrp); 476 477 if (p) 478 psignal(p, SIGURG); 479 } 480 } 481 482 /*ARGSUSED*/ 483 soioctl(so, cmd, data) 484 register struct socket *so; 485 int cmd; 486 register char *data; 487 { 488 489 switch (cmd) { 490 491 case FIONBIO: 492 if (*(int *)data) 493 so->so_state |= SS_NBIO; 494 else 495 so->so_state &= ~SS_NBIO; 496 return; 497 498 case FIOASYNC: 499 if (*(int *)data) 500 so->so_state |= SS_ASYNC; 501 else 502 so->so_state &= ~SS_ASYNC; 503 return; 504 505 case SIOCSKEEP: 506 if (*(int *)data) 507 so->so_options &= ~SO_KEEPALIVE; 508 else 509 so->so_options |= SO_KEEPALIVE; 510 return; 511 512 case SIOCGKEEP: 513 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 514 return; 515 516 case SIOCSLINGER: 517 so->so_linger = *(int *)data; 518 if (so->so_linger) 519 so->so_options &= ~SO_DONTLINGER; 520 else 521 so->so_options |= SO_DONTLINGER; 522 return; 523 524 case SIOCGLINGER: 525 *(int *)data = so->so_linger; 526 return; 527 528 case SIOCSPGRP: 529 so->so_pgrp = *(int *)data; 530 return; 531 532 case SIOCGPGRP: 533 *(int *)data = so->so_pgrp; 534 return; 535 536 case SIOCDONE: { 537 int flags = *(int *)data; 538 539 flags++; 540 if (flags & FREAD) { 541 int s = splimp(); 542 socantrcvmore(so); 543 sbflush(&so->so_rcv); 544 splx(s); 545 } 546 if (flags & FWRITE) 547 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 548 (struct mbuf *)0, (struct mbuf *)0, 549 (struct socketopt *)0); 550 return; 551 } 552 553 case SIOCSENDOOB: { 554 char oob = *(char *)data; 555 struct mbuf *m; 556 557 m = m_get(M_DONTWAIT); 558 if (m == 0) { 559 u.u_error = ENOBUFS; 560 return; 561 } 562 m->m_off = MMINOFF; 563 m->m_len = sizeof (char); 564 *mtod(m, char *) = oob; 565 (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 566 m, (struct mbuf *)0, (struct socketopt *)0); 567 return; 568 } 569 570 case SIOCRCVOOB: { 571 struct mbuf *m = m_get(M_DONTWAIT); 572 573 if (m == 0) { 574 u.u_error = ENOBUFS; 575 return; 576 } 577 m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 578 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 579 m, (struct mbuf *)0, (struct socketopt *)0); 580 *(char *)data = *mtod(m, char *); 581 (void) m_free(m); 582 return; 583 } 584 585 case SIOCATMARK: 586 *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 587 return; 588 589 /* routing table update calls */ 590 case SIOCADDRT: 591 case SIOCDELRT: 592 if (!suser()) 593 return; 594 u.u_error = rtrequest(cmd, (struct rtentry *)data); 595 return; 596 597 /* type/protocol specific ioctls */ 598 } 599 u.u_error = EOPNOTSUPP; 600 } 601