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