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