1 /* uipc_socket.c 4.35 82/03/19 */ 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 20 /* 21 * Socket support routines. 22 * 23 * DEAL WITH INTERRUPT NOTIFICATION. 24 */ 25 26 /* 27 * Create a socket. 28 */ 29 socreate(aso, type, asp, asa, options) 30 struct socket **aso; 31 int type; 32 struct sockproto *asp; 33 struct sockaddr *asa; 34 int options; 35 { 36 register struct protosw *prp; 37 register struct socket *so; 38 struct mbuf *m; 39 int pf, proto, error; 40 COUNT(SOCREATE); 41 42 /* 43 * Use process standard protocol/protocol family if none 44 * specified by address argument. 45 */ 46 if (asp == 0) { 47 pf = PF_INET; /* should be u.u_protof */ 48 proto = 0; 49 } else { 50 pf = asp->sp_family; 51 proto = asp->sp_protocol; 52 } 53 54 /* 55 * If protocol specified, look for it, otherwise 56 * for a protocol of the correct type in the right family. 57 */ 58 if (proto) 59 prp = pffindproto(pf, proto); 60 else 61 prp = pffindtype(pf, type); 62 if (prp == 0) 63 return (EPROTONOSUPPORT); 64 65 /* 66 * Get a socket structure. 67 */ 68 m = m_getclr(M_WAIT); 69 if (m == 0) 70 return (ENOBUFS); 71 so = mtod(m, struct socket *); 72 so->so_options = options; 73 so->so_state = 0; 74 if (u.u_uid == 0) 75 so->so_state = SS_PRIV; 76 77 /* 78 * Attach protocol to socket, initializing 79 * and reserving resources. 80 */ 81 so->so_proto = prp; 82 error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); 83 if (error) { 84 (void) m_free(dtom(so)); 85 return (error); 86 } 87 *aso = so; 88 return (0); 89 } 90 91 sofree(so) 92 struct socket *so; 93 { 94 95 COUNT(SOFREE); 96 if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) 97 return; 98 sbrelease(&so->so_snd); 99 sbrelease(&so->so_rcv); 100 (void) m_free(dtom(so)); 101 } 102 103 /* 104 * Close a socket on last file table reference removal. 105 * Initiate disconnect if connected. 106 * Free socket when disconnect complete. 107 * 108 * THIS IS REALLY A UNIX INTERFACE ROUTINE 109 */ 110 soclose(so, exiting) 111 register struct socket *so; 112 int exiting; 113 { 114 int s = splnet(); /* conservative */ 115 116 COUNT(SOCLOSE); 117 if (so->so_pcb == 0) 118 goto discard; 119 if (exiting) 120 so->so_options |= SO_KEEPALIVE; 121 if (so->so_state & SS_ISCONNECTED) { 122 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 123 u.u_error = sodisconnect(so, (struct sockaddr *)0); 124 if (u.u_error) { 125 if (exiting) 126 goto drop; 127 splx(s); 128 return; 129 } 130 } 131 if ((so->so_options & SO_DONTLINGER) == 0) { 132 if ((so->so_state & SS_ISDISCONNECTING) && 133 (so->so_state & SS_NBIO) && 134 exiting == 0) { 135 u.u_error = EINPROGRESS; 136 splx(s); 137 return; 138 } 139 /* should use tsleep here, for at most linger */ 140 while (so->so_state & SS_ISCONNECTED) 141 sleep((caddr_t)&so->so_timeo, PZERO+1); 142 } 143 } 144 drop: 145 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 146 discard: 147 so->so_state |= SS_USERGONE; 148 sofree(so); 149 splx(s); 150 } 151 152 sosplice(pso, so) 153 struct socket *pso, *so; 154 { 155 156 COUNT(SOSPLICE); 157 if (pso->so_proto->pr_family != PF_UNIX) { 158 struct socket *tso; 159 tso = pso; pso = so; so = tso; 160 } 161 if (pso->so_proto->pr_family != PF_UNIX) 162 return (EOPNOTSUPP); 163 /* check types and buffer space */ 164 /* merge buffers */ 165 return (0); 166 } 167 168 /*ARGSUSED*/ 169 sostat(so, sb) 170 struct socket *so; 171 struct stat *sb; 172 { 173 174 COUNT(SOSTAT); 175 bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 176 return (0); /* XXX */ 177 } 178 179 /* 180 * Accept connection on a socket. 181 */ 182 soaccept(so, asa) 183 struct socket *so; 184 struct sockaddr *asa; 185 { 186 int s = splnet(); 187 int error; 188 189 COUNT(SOACCEPT); 190 if ((so->so_options & SO_ACCEPTCONN) == 0) { 191 error = EINVAL; /* XXX */ 192 goto bad; 193 } 194 if ((so->so_state & SS_CONNAWAITING) == 0) { 195 error = ENOTCONN; 196 goto bad; 197 } 198 so->so_state &= ~SS_CONNAWAITING; 199 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); 200 bad: 201 splx(s); 202 return (error); 203 } 204 205 /* 206 * Connect socket to a specified address. 207 * If already connected or connecting, then avoid 208 * the protocol entry, to keep its job simpler. 209 */ 210 soconnect(so, asa) 211 struct socket *so; 212 struct sockaddr *asa; 213 { 214 int s = splnet(); 215 int error; 216 217 COUNT(SOCONNECT); 218 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 219 error = EISCONN; 220 goto bad; 221 } 222 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); 223 bad: 224 splx(s); 225 return (error); 226 } 227 228 /* 229 * Disconnect from a socket. 230 * Address parameter is from system call for later multicast 231 * protocols. Check to make sure that connected and no disconnect 232 * in progress (for protocol's sake), and then invoke protocol. 233 */ 234 sodisconnect(so, asa) 235 struct socket *so; 236 struct sockaddr *asa; 237 { 238 int s = splnet(); 239 int error; 240 241 COUNT(SODISCONNECT); 242 if ((so->so_state & SS_ISCONNECTED) == 0) { 243 error = ENOTCONN; 244 goto bad; 245 } 246 if (so->so_state & SS_ISDISCONNECTING) { 247 error = EALREADY; 248 goto bad; 249 } 250 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); 251 bad: 252 splx(s); 253 return (error); 254 } 255 256 /* 257 * Send on a socket. 258 * If send must go all at once and message is larger than 259 * send buffering, then hard error. 260 * Lock against other senders. 261 * If must go all at once and not enough room now, then 262 * inform user that this would block and do nothing. 263 */ 264 sosend(so, asa) 265 register struct socket *so; 266 struct sockaddr *asa; 267 { 268 struct mbuf *top = 0; 269 register struct mbuf *m, **mp = ⊤ 270 register u_int len; 271 int error = 0, space, s; 272 273 COUNT(SOSEND); 274 if (so->so_state & SS_CANTSENDMORE) { 275 psignal(u.u_procp, SIGPIPE); 276 return (EPIPE); 277 } 278 if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 279 return (EMSGSIZE); 280 if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_state & SS_NBIO)) 281 return (EWOULDBLOCK); 282 sblock(&so->so_snd); 283 #define snderr(errno) { error = errno; splx(s); goto release; } 284 285 s = splnet(); 286 again: 287 if (so->so_error) { 288 error = so->so_error; 289 so->so_error = 0; 290 splx(s); 291 goto release; 292 } 293 if ((so->so_state & SS_ISCONNECTED) == 0) { 294 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 295 snderr(ENOTCONN); 296 if (asa == 0) 297 snderr(EDESTADDRREQ); 298 } 299 if (top) { 300 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); 301 if (error) { 302 splx(s); 303 goto release; 304 } 305 top = 0; 306 mp = ⊤ 307 } 308 if (u.u_count == 0) { 309 splx(s); 310 goto release; 311 } 312 space = sbspace(&so->so_snd); 313 if (space <= 0 || sosendallatonce(so) && space < u.u_count) { 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 again; 320 } 321 splx(s); 322 while (u.u_count && space > 0) { 323 MGET(m, 1); 324 if (m == NULL) { 325 error = ENOBUFS; 326 m_freem(top); 327 goto release; 328 } 329 if (u.u_count >= CLBYTES && space >= CLBYTES) { 330 register struct mbuf *p; 331 MCLGET(p, 1); 332 if (p == 0) 333 goto nopages; 334 m->m_off = (int)p - (int)m; 335 len = CLBYTES; 336 } else { 337 nopages: 338 m->m_off = MMINOFF; 339 len = MIN(MLEN, u.u_count); 340 } 341 iomove(mtod(m, caddr_t), len, B_WRITE); 342 m->m_len = len; 343 *mp = m; 344 mp = &m->m_next; 345 space = sbspace(&so->so_snd); 346 } 347 s = splnet(); 348 goto again; 349 350 release: 351 sbunlock(&so->so_snd); 352 return (error); 353 } 354 355 soreceive(so, asa) 356 register struct socket *so; 357 struct sockaddr *asa; 358 { 359 register struct mbuf *m, *n; 360 u_int len; 361 int eor, s, error = 0, cnt = u.u_count; 362 caddr_t base = u.u_base; 363 364 COUNT(SORECEIVE); 365 restart: 366 sblock(&so->so_rcv); 367 s = splnet(); 368 369 #define rcverr(errno) { error = errno; splx(s); goto release; } 370 if (so->so_rcv.sb_cc == 0) { 371 if (so->so_error) { 372 error = so->so_error; 373 so->so_error = 0; 374 splx(s); 375 goto release; 376 } 377 if (so->so_state & SS_CANTRCVMORE) { 378 splx(s); 379 goto release; 380 } 381 if ((so->so_state & SS_ISCONNECTED) == 0 && 382 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 383 rcverr(ENOTCONN); 384 if (so->so_state & SS_NBIO) 385 rcverr(EWOULDBLOCK); 386 sbunlock(&so->so_rcv); 387 sbwait(&so->so_rcv); 388 splx(s); 389 goto restart; 390 } 391 m = so->so_rcv.sb_mb; 392 if (m == 0) 393 panic("receive"); 394 if (so->so_proto->pr_flags & PR_ADDR) { 395 if (m->m_len != sizeof (struct sockaddr)) 396 panic("soreceive addr"); 397 if (asa) 398 bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 399 so->so_rcv.sb_cc -= m->m_len; 400 so->so_rcv.sb_mbcnt -= MSIZE; 401 m = m_free(m); 402 if (m == 0) 403 panic("receive 2"); 404 so->so_rcv.sb_mb = m; 405 } 406 so->so_state &= ~SS_RCVATMARK; 407 if (so->so_oobmark && cnt > so->so_oobmark) 408 cnt = so->so_oobmark; 409 eor = 0; 410 do { 411 len = MIN(m->m_len, cnt); 412 splx(s); 413 iomove(mtod(m, caddr_t), len, B_READ); 414 cnt -= len; 415 s = splnet(); 416 if (len == m->m_len) { 417 eor = (int)m->m_act; 418 sbfree(&so->so_rcv, m); 419 so->so_rcv.sb_mb = m->m_next; 420 MFREE(m, n); 421 } else { 422 m->m_off += len; 423 m->m_len -= len; 424 so->so_rcv.sb_cc -= len; 425 } 426 } while ((m = so->so_rcv.sb_mb) && cnt && !eor); 427 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 428 do { 429 if (m == 0) 430 panic("receive 3"); 431 sbfree(&so->so_rcv, m); 432 eor = (int)m->m_act; 433 so->so_rcv.sb_mb = m->m_next; 434 MFREE(m, n); 435 m = n; 436 } while (eor == 0); 437 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 438 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 439 if (so->so_oobmark) { 440 so->so_oobmark -= u.u_base - base; 441 if (so->so_oobmark == 0) 442 so->so_state |= SS_RCVATMARK; 443 } 444 release: 445 sbunlock(&so->so_rcv); 446 splx(s); 447 return (error); 448 } 449 450 sohasoutofband(so) 451 struct socket *so; 452 { 453 454 if (so->so_pgrp == 0) 455 return; 456 if (so->so_pgrp > 0) 457 gsignal(so->so_pgrp, SIGURG); 458 else { 459 struct proc *p = pfind(-so->so_pgrp); 460 461 if (p) 462 psignal(p, SIGURG); 463 } 464 } 465 466 /*ARGSUSED*/ 467 soioctl(so, cmd, cmdp) 468 register struct socket *so; 469 int cmd; 470 register caddr_t cmdp; 471 { 472 473 COUNT(SOIOCTL); 474 switch (cmd) { 475 476 case FIONBIO: { 477 int nbio; 478 if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { 479 u.u_error = EFAULT; 480 return; 481 } 482 if (nbio) 483 so->so_state |= SS_NBIO; 484 else 485 so->so_state &= ~SS_NBIO; 486 return; 487 } 488 489 case FIOASYNC: { 490 int async; 491 if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { 492 u.u_error = EFAULT; 493 return; 494 } 495 if (async) 496 so->so_state |= SS_ASYNC; 497 else 498 so->so_state &= ~SS_ASYNC; 499 return; 500 } 501 502 case SIOCSKEEP: { 503 int keep; 504 if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { 505 u.u_error = EFAULT; 506 return; 507 } 508 if (keep) 509 so->so_options &= ~SO_KEEPALIVE; 510 else 511 so->so_options |= SO_KEEPALIVE; 512 return; 513 } 514 515 case SIOCGKEEP: { 516 int keep = (so->so_options & SO_KEEPALIVE) != 0; 517 if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) 518 u.u_error = EFAULT; 519 return; 520 } 521 522 case SIOCSLINGER: { 523 int linger; 524 if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { 525 u.u_error = EFAULT; 526 return; 527 } 528 so->so_linger = linger; 529 if (so->so_linger) 530 so->so_options &= ~SO_DONTLINGER; 531 else 532 so->so_options |= SO_DONTLINGER; 533 return; 534 } 535 536 case SIOCGLINGER: { 537 int linger = so->so_linger; 538 if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { 539 u.u_error = EFAULT; 540 return; 541 } 542 } 543 case SIOCSPGRP: { 544 int pgrp; 545 if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { 546 u.u_error = EFAULT; 547 return; 548 } 549 so->so_pgrp = pgrp; 550 return; 551 } 552 553 case SIOCGPGRP: { 554 int pgrp = so->so_pgrp; 555 if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { 556 u.u_error = EFAULT; 557 return; 558 } 559 } 560 561 case SIOCDONE: { 562 int flags; 563 if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { 564 u.u_error = EFAULT; 565 return; 566 } 567 flags++; 568 if (flags & FREAD) { 569 int s = splimp(); 570 socantrcvmore(so); 571 sbflush(&so->so_rcv); 572 splx(s); 573 } 574 if (flags & FWRITE) 575 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 576 return; 577 } 578 579 case SIOCSENDOOB: { 580 char oob; 581 struct mbuf *m; 582 if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { 583 u.u_error = EFAULT; 584 return; 585 } 586 m = m_get(M_DONTWAIT); 587 if (m == 0) { 588 u.u_error = ENOBUFS; 589 return; 590 } 591 m->m_off = MMINOFF; 592 m->m_len = 1; 593 *mtod(m, caddr_t) = oob; 594 (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 595 return; 596 } 597 598 case SIOCRCVOOB: { 599 struct mbuf *m = m_get(M_DONTWAIT); 600 if (m == 0) { 601 u.u_error = ENOBUFS; 602 return; 603 } 604 m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 605 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 606 if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { 607 u.u_error = EFAULT; 608 return; 609 } 610 m_free(m); 611 return; 612 } 613 614 case SIOCATMARK: { 615 int atmark = (so->so_state&SS_RCVATMARK) != 0; 616 if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { 617 u.u_error = EFAULT; 618 return; 619 } 620 return; 621 } 622 /* type/protocol specific ioctls */ 623 } 624 u.u_error = EOPNOTSUPP; 625 } 626