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