1 /* uipc_socket.c 4.49 82/09/04 */ 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 u.u_ru.ru_msgsnd++; 276 again: 277 s = splnet(); 278 if (so->so_state & SS_CANTSENDMORE) { 279 psignal(u.u_procp, SIGPIPE); 280 snderr(EPIPE); 281 } 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 top = 0; 297 if (error) { 298 splx(s); 299 goto release; 300 } 301 mp = ⊤ 302 } 303 if (uio->uio_resid == 0) { 304 splx(s); 305 goto release; 306 } 307 space = sbspace(&so->so_snd); 308 if (space <= 0 || sosendallatonce(so) && space < uio->uio_resid) { 309 if (so->so_state & SS_NBIO) 310 snderr(EWOULDBLOCK); 311 sbunlock(&so->so_snd); 312 sbwait(&so->so_snd); 313 splx(s); 314 goto restart; 315 } 316 splx(s); 317 while (uio->uio_resid > 0 && space > 0) { 318 register struct iovec *iov = uio->uio_iov; 319 320 if (iov->iov_len == 0) { 321 uio->uio_iov++; 322 uio->uio_iovcnt--; 323 if (uio->uio_iovcnt < 0) 324 panic("sosend"); 325 continue; 326 } 327 MGET(m, 1); 328 if (m == NULL) { 329 error = ENOBUFS; /* SIGPIPE? */ 330 goto release; 331 } 332 if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 333 register struct mbuf *p; 334 MCLGET(p, 1); 335 if (p == 0) 336 goto nopages; 337 m->m_off = (int)p - (int)m; 338 len = CLBYTES; 339 } else { 340 nopages: 341 m->m_off = MMINOFF; 342 len = MIN(MLEN, iov->iov_len); 343 } 344 uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 345 m->m_len = len; 346 *mp = m; 347 mp = &m->m_next; 348 space = sbspace(&so->so_snd); 349 } 350 goto again; 351 352 release: 353 sbunlock(&so->so_snd); 354 if (top) 355 m_freem(top); 356 return (error); 357 } 358 359 soreceive(so, asa, uio) 360 register struct socket *so; 361 struct sockaddr *asa; 362 struct uio *uio; 363 { 364 register struct iovec *iov; 365 register struct mbuf *m, *n; 366 u_int len; 367 int eor, s, error = 0; 368 369 restart: 370 sblock(&so->so_rcv); 371 s = splnet(); 372 373 #define rcverr(errno) { error = errno; splx(s); goto release; } 374 if (so->so_rcv.sb_cc == 0) { 375 if (so->so_error) { 376 error = so->so_error; 377 so->so_error = 0; 378 splx(s); 379 goto release; 380 } 381 if (so->so_state & SS_CANTRCVMORE) { 382 splx(s); 383 goto release; 384 } 385 if ((so->so_state & SS_ISCONNECTED) == 0 && 386 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 387 rcverr(ENOTCONN); 388 if (so->so_state & SS_NBIO) 389 rcverr(EWOULDBLOCK); 390 sbunlock(&so->so_rcv); 391 sbwait(&so->so_rcv); 392 splx(s); 393 goto restart; 394 } 395 u.u_ru.ru_msgrcv++; 396 m = so->so_rcv.sb_mb; 397 if (m == 0) 398 panic("receive"); 399 if (so->so_proto->pr_flags & PR_ADDR) { 400 if (m->m_len != sizeof (struct sockaddr)) 401 panic("soreceive addr"); 402 if (asa) 403 bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); 404 so->so_rcv.sb_cc -= m->m_len; 405 so->so_rcv.sb_mbcnt -= MSIZE; 406 m = m_free(m); 407 if (m == 0) 408 panic("receive 2"); 409 so->so_rcv.sb_mb = m; 410 } 411 eor = 0; 412 do { 413 if (uio->uio_resid <= 0) 414 break; 415 len = uio->uio_resid; 416 so->so_state &= ~SS_RCVATMARK; 417 if (so->so_oobmark && len > so->so_oobmark) 418 len = so->so_oobmark; 419 if (len > m->m_len) 420 len = m->m_len; 421 splx(s); 422 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 423 s = splnet(); 424 if (len == m->m_len) { 425 eor = (int)m->m_act; 426 sbfree(&so->so_rcv, m); 427 so->so_rcv.sb_mb = m->m_next; 428 MFREE(m, n); 429 } else { 430 m->m_off += len; 431 m->m_len -= len; 432 so->so_rcv.sb_cc -= len; 433 } 434 if (so->so_oobmark) { 435 so->so_oobmark -= len; 436 if (so->so_oobmark == 0) { 437 so->so_state |= SS_RCVATMARK; 438 break; 439 } 440 } 441 } while ((m = so->so_rcv.sb_mb) && !eor); 442 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 443 do { 444 if (m == 0) 445 panic("receive 3"); 446 sbfree(&so->so_rcv, m); 447 eor = (int)m->m_act; 448 so->so_rcv.sb_mb = m->m_next; 449 MFREE(m, n); 450 m = n; 451 } while (eor == 0); 452 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 453 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 454 release: 455 sbunlock(&so->so_rcv); 456 splx(s); 457 return (error); 458 } 459 460 sohasoutofband(so) 461 struct socket *so; 462 { 463 464 if (so->so_pgrp == 0) 465 return; 466 if (so->so_pgrp > 0) 467 gsignal(so->so_pgrp, SIGURG); 468 else { 469 struct proc *p = pfind(-so->so_pgrp); 470 471 if (p) 472 psignal(p, SIGURG); 473 } 474 } 475 476 /*ARGSUSED*/ 477 soioctl(so, cmd, data) 478 register struct socket *so; 479 int cmd; 480 register char *data; 481 { 482 483 switch (cmd) { 484 485 case FIONBIO: 486 if (*(int *)data) 487 so->so_state |= SS_NBIO; 488 else 489 so->so_state &= ~SS_NBIO; 490 return; 491 492 case FIOASYNC: 493 if (*(int *)data) 494 so->so_state |= SS_ASYNC; 495 else 496 so->so_state &= ~SS_ASYNC; 497 return; 498 499 case SIOCSKEEP: 500 if (*(int *)data) 501 so->so_options &= ~SO_KEEPALIVE; 502 else 503 so->so_options |= SO_KEEPALIVE; 504 return; 505 506 case SIOCGKEEP: 507 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 508 return; 509 510 case SIOCSLINGER: 511 so->so_linger = *(int *)data; 512 if (so->so_linger) 513 so->so_options &= ~SO_DONTLINGER; 514 else 515 so->so_options |= SO_DONTLINGER; 516 return; 517 518 case SIOCGLINGER: 519 *(int *)data = so->so_linger; 520 return; 521 522 case SIOCSPGRP: 523 so->so_pgrp = *(int *)data; 524 return; 525 526 case SIOCGPGRP: 527 *(int *)data = so->so_pgrp; 528 return; 529 530 case SIOCDONE: { 531 int flags = *(int *)data; 532 533 flags++; 534 if (flags & FREAD) { 535 int s = splimp(); 536 socantrcvmore(so); 537 sbflush(&so->so_rcv); 538 splx(s); 539 } 540 if (flags & FWRITE) 541 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); 542 return; 543 } 544 545 case SIOCSENDOOB: { 546 char oob = *(char *)data; 547 struct mbuf *m; 548 549 m = m_get(M_DONTWAIT); 550 if (m == 0) { 551 u.u_error = ENOBUFS; 552 return; 553 } 554 m->m_off = MMINOFF; 555 m->m_len = sizeof (char); 556 *mtod(m, char *) = oob; 557 (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); 558 return; 559 } 560 561 case SIOCRCVOOB: { 562 struct mbuf *m = m_get(M_DONTWAIT); 563 564 if (m == 0) { 565 u.u_error = ENOBUFS; 566 return; 567 } 568 m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; 569 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); 570 *(char *)data = *mtod(m, char *); 571 (void) m_free(m); 572 return; 573 } 574 575 case SIOCATMARK: 576 *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 577 return; 578 579 /* routing table update calls */ 580 case SIOCADDRT: 581 case SIOCDELRT: 582 if (!suser()) 583 return; 584 u.u_error = rtrequest(cmd, (struct rtentry *)data); 585 return; 586 587 /* type/protocol specific ioctls */ 588 } 589 u.u_error = EOPNOTSUPP; 590 } 591