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