1 /* uipc_syscalls.c 4.47 83/06/14 */ 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/uio.h" 16 17 /* 18 * System call interface to the socket abstraction. 19 */ 20 21 struct file *getsock(); 22 extern struct fileops socketops; 23 24 socket() 25 { 26 register struct a { 27 int domain; 28 int type; 29 int protocol; 30 } *uap = (struct a *)u.u_ap; 31 struct socket *so; 32 register struct file *fp; 33 34 if ((fp = falloc()) == NULL) 35 return; 36 fp->f_flag = FREAD|FWRITE; 37 fp->f_type = DTYPE_SOCKET; 38 fp->f_ops = &socketops; 39 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol); 40 if (u.u_error) 41 goto bad; 42 fp->f_data = (caddr_t)so; 43 return; 44 bad: 45 u.u_ofile[u.u_r.r_val1] = 0; 46 fp->f_count = 0; 47 } 48 49 bind() 50 { 51 register struct a { 52 int s; 53 caddr_t name; 54 int namelen; 55 } *uap = (struct a *)u.u_ap; 56 register struct file *fp; 57 struct mbuf *nam; 58 59 fp = getsock(uap->s); 60 if (fp == 0) 61 return; 62 u.u_error = sockargs(&nam, uap->name, uap->namelen); 63 if (u.u_error) 64 return; 65 u.u_error = sobind((struct socket *)fp->f_data, nam); 66 m_freem(nam); 67 } 68 69 listen() 70 { 71 register struct a { 72 int s; 73 int backlog; 74 } *uap = (struct a *)u.u_ap; 75 register struct file *fp; 76 77 fp = getsock(uap->s); 78 if (fp == 0) 79 return; 80 u.u_error = solisten((struct socket *)fp->f_data, uap->backlog); 81 } 82 83 accept() 84 { 85 register struct a { 86 int s; 87 caddr_t name; 88 int *anamelen; 89 } *uap = (struct a *)u.u_ap; 90 register struct file *fp; 91 struct mbuf *nam; 92 int namelen; 93 int s; 94 register struct socket *so; 95 96 if (uap->name == 0) 97 goto noname; 98 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 99 sizeof (namelen)); 100 if (u.u_error) 101 return; 102 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { 103 u.u_error = EFAULT; 104 return; 105 } 106 noname: 107 fp = getsock(uap->s); 108 if (fp == 0) 109 return; 110 s = splnet(); 111 so = (struct socket *)fp->f_data; 112 if ((so->so_options & SO_ACCEPTCONN) == 0) { 113 u.u_error = EINVAL; 114 splx(s); 115 return; 116 } 117 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 118 u.u_error = EWOULDBLOCK; 119 splx(s); 120 return; 121 } 122 while (so->so_qlen == 0 && so->so_error == 0) { 123 if (so->so_state & SS_CANTRCVMORE) { 124 so->so_error = ECONNABORTED; 125 break; 126 } 127 sleep((caddr_t)&so->so_timeo, PZERO+1); 128 } 129 if (so->so_error) { 130 u.u_error = so->so_error; 131 splx(s); 132 return; 133 } 134 if (ufalloc(0) < 0) { 135 splx(s); 136 return; 137 } 138 fp = falloc(); 139 if (fp == 0) { 140 u.u_ofile[u.u_r.r_val1] = 0; 141 splx(s); 142 return; 143 } 144 { struct socket *aso = so->so_q; 145 if (soqremque(aso, 1) == 0) 146 panic("accept"); 147 so = aso; 148 } 149 fp->f_type = DTYPE_SOCKET; 150 fp->f_flag = FREAD|FWRITE; 151 fp->f_ops = &socketops; 152 fp->f_data = (caddr_t)so; 153 nam = m_get(M_WAIT, MT_SONAME); 154 (void) soaccept(so, nam); 155 if (uap->name) { 156 if (namelen > nam->m_len) 157 namelen = nam->m_len; 158 /* SHOULD COPY OUT A CHAIN HERE */ 159 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, 160 (u_int)namelen); 161 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, 162 sizeof (*uap->anamelen)); 163 } 164 m_freem(nam); 165 splx(s); 166 } 167 168 connect() 169 { 170 register struct a { 171 int s; 172 caddr_t name; 173 int namelen; 174 } *uap = (struct a *)u.u_ap; 175 register struct file *fp; 176 register struct socket *so; 177 struct mbuf *nam; 178 int s; 179 180 fp = getsock(uap->s); 181 if (fp == 0) 182 return; 183 so = (struct socket *)fp->f_data; 184 u.u_error = sockargs(&nam, uap->name, uap->namelen); 185 if (u.u_error) 186 return; 187 u.u_error = soconnect(so, nam); 188 if (u.u_error) 189 goto bad; 190 s = splnet(); 191 if ((so->so_state & SS_NBIO) && 192 (so->so_state & SS_ISCONNECTING)) { 193 u.u_error = EINPROGRESS; 194 goto bad2; 195 } 196 if (setjmp(&u.u_qsave)) { 197 if (u.u_error == 0) 198 u.u_error = EINTR; 199 goto bad2; 200 } 201 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 202 sleep((caddr_t)&so->so_timeo, PZERO+1); 203 u.u_error = so->so_error; 204 so->so_error = 0; 205 bad2: 206 splx(s); 207 bad: 208 m_freem(nam); 209 } 210 211 socketpair() 212 { 213 register struct a { 214 int domain; 215 int type; 216 int protocol; 217 int *rsv; 218 } *uap = (struct a *)u.u_ap; 219 register struct file *fp1, *fp2; 220 struct socket *so1, *so2; 221 int sv[2]; 222 223 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) { 224 u.u_error = EFAULT; 225 return; 226 } 227 u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol); 228 if (u.u_error) 229 return; 230 u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol); 231 if (u.u_error) 232 goto free; 233 fp1 = falloc(); 234 if (fp1 == NULL) 235 goto free2; 236 sv[0] = u.u_r.r_val1; 237 fp1->f_flag = FREAD|FWRITE; 238 fp1->f_type = DTYPE_SOCKET; 239 fp1->f_ops = &socketops; 240 fp1->f_data = (caddr_t)so1; 241 fp2 = falloc(); 242 if (fp2 == NULL) 243 goto free3; 244 fp2->f_flag = FREAD|FWRITE; 245 fp2->f_type = DTYPE_SOCKET; 246 fp2->f_ops = &socketops; 247 fp2->f_data = (caddr_t)so2; 248 sv[1] = u.u_r.r_val1; 249 u.u_error = soconnect2(so1, so2); 250 if (u.u_error) 251 goto free4; 252 (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 253 return; 254 free4: 255 fp2->f_count = 0; 256 u.u_ofile[sv[1]] = 0; 257 free3: 258 fp1->f_count = 0; 259 u.u_ofile[sv[0]] = 0; 260 free2: 261 so2->so_state |= SS_NOFDREF; 262 sofree(so2); 263 free: 264 so1->so_state |= SS_NOFDREF; 265 sofree(so1); 266 } 267 268 sendto() 269 { 270 register struct a { 271 int s; 272 caddr_t buf; 273 int len; 274 int flags; 275 caddr_t to; 276 int tolen; 277 } *uap = (struct a *)u.u_ap; 278 struct msghdr msg; 279 struct iovec aiov; 280 281 msg.msg_name = uap->to; 282 msg.msg_namelen = uap->tolen; 283 msg.msg_iov = &aiov; 284 msg.msg_iovlen = 1; 285 aiov.iov_base = uap->buf; 286 aiov.iov_len = uap->len; 287 msg.msg_accrights = 0; 288 msg.msg_accrightslen = 0; 289 sendit(uap->s, &msg, uap->flags); 290 } 291 292 send() 293 { 294 register struct a { 295 int s; 296 caddr_t buf; 297 int len; 298 int flags; 299 } *uap = (struct a *)u.u_ap; 300 struct msghdr msg; 301 struct iovec aiov; 302 303 msg.msg_name = 0; 304 msg.msg_namelen = 0; 305 msg.msg_iov = &aiov; 306 msg.msg_iovlen = 1; 307 aiov.iov_base = uap->buf; 308 aiov.iov_len = uap->len; 309 msg.msg_accrights = 0; 310 msg.msg_accrightslen = 0; 311 sendit(uap->s, &msg, uap->flags); 312 } 313 314 sendmsg() 315 { 316 register struct a { 317 int s; 318 caddr_t msg; 319 int flags; 320 } *uap = (struct a *)u.u_ap; 321 struct msghdr msg; 322 struct iovec aiov[MSG_MAXIOVLEN]; 323 324 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 325 if (u.u_error) 326 return; 327 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 328 u.u_error = EMSGSIZE; 329 return; 330 } 331 u.u_error = 332 copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 333 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 334 if (u.u_error) 335 return; 336 msg.msg_iov = aiov; 337 #ifdef notdef 338 printf("sendmsg name %x namelen %d iov %x iovlen %d accrights %x &len %d\n", 339 msg.msg_name, msg.msg_namelen, msg.msg_iov, msg.msg_iovlen, 340 msg.msg_accrights, msg.msg_accrightslen); 341 #endif 342 sendit(uap->s, &msg, uap->flags); 343 } 344 345 sendit(s, mp, flags) 346 int s; 347 register struct msghdr *mp; 348 int flags; 349 { 350 register struct file *fp; 351 struct uio auio; 352 register struct iovec *iov; 353 register int i; 354 struct mbuf *to, *rights; 355 int len; 356 357 fp = getsock(s); 358 if (fp == 0) 359 return; 360 auio.uio_iov = mp->msg_iov; 361 auio.uio_iovcnt = mp->msg_iovlen; 362 auio.uio_segflg = 0; 363 auio.uio_offset = 0; /* XXX */ 364 auio.uio_resid = 0; 365 iov = mp->msg_iov; 366 for (i = 0; i < mp->msg_iovlen; i++) { 367 if (iov->iov_len < 0) { 368 u.u_error = EINVAL; 369 return; 370 } 371 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) { 372 u.u_error = EFAULT; 373 return; 374 } 375 auio.uio_resid += iov->iov_len; 376 iov++; 377 } 378 if (mp->msg_name) { 379 u.u_error = 380 sockargs(&to, mp->msg_name, mp->msg_namelen); 381 if (u.u_error) 382 return; 383 } else 384 to = 0; 385 if (mp->msg_accrights) { 386 u.u_error = 387 sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen); 388 if (u.u_error) 389 goto bad; 390 } else 391 rights = 0; 392 len = auio.uio_resid; 393 u.u_error = 394 sosend((struct socket *)fp->f_data, to, &auio, flags, rights); 395 u.u_r.r_val1 = len - auio.uio_resid; 396 if (rights) 397 m_freem(rights); 398 bad: 399 if (to) 400 m_freem(to); 401 } 402 403 recvfrom() 404 { 405 register struct a { 406 int s; 407 caddr_t buf; 408 int len; 409 int flags; 410 caddr_t from; 411 int *fromlenaddr; 412 } *uap = (struct a *)u.u_ap; 413 struct msghdr msg; 414 struct iovec aiov; 415 int len; 416 417 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, 418 sizeof (len)); 419 if (u.u_error) 420 return; 421 msg.msg_name = uap->from; 422 msg.msg_namelen = len; 423 msg.msg_iov = &aiov; 424 msg.msg_iovlen = 1; 425 aiov.iov_base = uap->buf; 426 aiov.iov_len = uap->len; 427 msg.msg_accrights = 0; 428 msg.msg_accrightslen = 0; 429 recvit(uap->s, &msg, uap->flags, (caddr_t)uap->fromlenaddr, (caddr_t)0); 430 } 431 432 recv() 433 { 434 register struct a { 435 int s; 436 caddr_t buf; 437 int len; 438 int flags; 439 } *uap = (struct a *)u.u_ap; 440 struct msghdr msg; 441 struct iovec aiov; 442 443 msg.msg_name = 0; 444 msg.msg_namelen = 0; 445 msg.msg_iov = &aiov; 446 msg.msg_iovlen = 1; 447 aiov.iov_base = uap->buf; 448 aiov.iov_len = uap->len; 449 msg.msg_accrights = 0; 450 msg.msg_accrightslen = 0; 451 recvit(uap->s, &msg, uap->flags, (caddr_t)0, (caddr_t)0); 452 } 453 454 recvmsg() 455 { 456 register struct a { 457 int s; 458 struct msghdr *msg; 459 int flags; 460 } *uap = (struct a *)u.u_ap; 461 struct msghdr msg; 462 struct iovec aiov[MSG_MAXIOVLEN]; 463 464 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 465 if (u.u_error) 466 return; 467 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 468 u.u_error = EMSGSIZE; 469 return; 470 } 471 u.u_error = 472 copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 473 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 474 if (u.u_error) 475 return; 476 msg.msg_iov = aiov; 477 if (msg.msg_accrights) 478 if (useracc((caddr_t)msg.msg_accrights, 479 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { 480 u.u_error = EFAULT; 481 return; 482 } 483 recvit(uap->s, &msg, uap->flags, 484 (caddr_t)&uap->msg->msg_namelen, 485 (caddr_t)&uap->msg->msg_accrightslen); 486 } 487 488 recvit(s, mp, flags, namelenp, rightslenp) 489 int s; 490 register struct msghdr *mp; 491 int flags; 492 caddr_t namelenp, rightslenp; 493 { 494 register struct file *fp; 495 struct uio auio; 496 register struct iovec *iov; 497 register int i; 498 struct mbuf *from, *rights; 499 int len; 500 501 fp = getsock(s); 502 if (fp == 0) 503 return; 504 auio.uio_iov = mp->msg_iov; 505 auio.uio_iovcnt = mp->msg_iovlen; 506 auio.uio_segflg = 0; 507 auio.uio_offset = 0; /* XXX */ 508 auio.uio_resid = 0; 509 iov = mp->msg_iov; 510 for (i = 0; i < mp->msg_iovlen; i++) { 511 if (iov->iov_len < 0) { 512 u.u_error = EINVAL; 513 return; 514 } 515 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) { 516 u.u_error = EFAULT; 517 return; 518 } 519 auio.uio_resid += iov->iov_len; 520 iov++; 521 } 522 len = auio.uio_resid; 523 u.u_error = 524 soreceive((struct socket *)fp->f_data, &from, &auio, 525 flags, &rights); 526 u.u_r.r_val1 = len - auio.uio_resid; 527 if (mp->msg_name) { 528 len = mp->msg_namelen; 529 if (len <= 0 || from == 0) 530 len = 0; 531 else { 532 if (len > from->m_len) 533 len = from->m_len; 534 (void) copyout((caddr_t)mtod(from, caddr_t), 535 (caddr_t)mp->msg_name, (unsigned)len); 536 } 537 (void) copyout((caddr_t)&len, namelenp, sizeof (int)); 538 } 539 if (mp->msg_accrights) { 540 len = mp->msg_accrightslen; 541 if (len <= 0 || rights == 0) 542 len = 0; 543 else { 544 if (len > rights->m_len) 545 len = rights->m_len; 546 (void) copyout((caddr_t)mtod(rights, caddr_t), 547 (caddr_t)mp->msg_accrights, (unsigned)len); 548 } 549 (void) copyout((caddr_t)&len, rightslenp, sizeof (int)); 550 } 551 if (rights) 552 m_freem(rights); 553 if (from) 554 m_freem(from); 555 } 556 557 shutdown() 558 { 559 struct a { 560 int s; 561 int how; 562 } *uap = (struct a *)u.u_ap; 563 struct file *fp; 564 565 fp = getsock(uap->s); 566 if (fp == 0) 567 return; 568 u.u_error = soshutdown((struct socket *)fp->f_data, uap->how); 569 } 570 571 setsockopt() 572 { 573 struct a { 574 int s; 575 int level; 576 int name; 577 caddr_t val; 578 int valsize; 579 } *uap = (struct a *)u.u_ap; 580 struct file *fp; 581 struct mbuf *m = NULL; 582 583 fp = getsock(uap->s); 584 if (fp == 0) 585 return; 586 if (uap->valsize > MLEN) { 587 u.u_error = EINVAL; 588 return; 589 } 590 if (uap->val) { 591 m = m_get(M_WAIT, MT_SOOPTS); 592 if (m == NULL) { 593 u.u_error = ENOBUFS; 594 return; 595 } 596 u.u_error = 597 copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 598 if (u.u_error) 599 goto bad; 600 m->m_len = uap->valsize; 601 } 602 u.u_error = 603 sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m); 604 bad: 605 if (m != NULL) 606 (void) m_free(m); 607 } 608 609 getsockopt() 610 { 611 struct a { 612 int s; 613 int level; 614 int name; 615 caddr_t val; 616 int *avalsize; 617 } *uap = (struct a *)u.u_ap; 618 struct file *fp; 619 struct mbuf *m = NULL; 620 int valsize; 621 622 fp = getsock(uap->s); 623 if (fp == 0) 624 return; 625 if (uap->val) { 626 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 627 sizeof (valsize)); 628 if (u.u_error) 629 return; 630 m = m_get(M_WAIT, MT_SOOPTS); 631 if (m == NULL) { 632 u.u_error = ENOBUFS; 633 return; 634 } 635 } 636 u.u_error = 637 sogetopt((struct socket *)fp->f_data, uap->level, uap->name, m); 638 if (u.u_error) 639 goto bad; 640 if (uap->val) { 641 if (valsize > m->m_len) 642 valsize = m->m_len; 643 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 644 if (u.u_error) 645 goto bad; 646 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, 647 sizeof (valsize)); 648 } 649 bad: 650 if (m != NULL) 651 (void) m_free(m); 652 } 653 654 pipe() 655 { 656 register struct file *rf, *wf; 657 struct socket *rso, *wso; 658 int r; 659 660 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0); 661 if (u.u_error) 662 return; 663 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0); 664 if (u.u_error) 665 goto free; 666 rf = falloc(); 667 if (rf == NULL) 668 goto free2; 669 r = u.u_r.r_val1; 670 rf->f_flag = FREAD; 671 rf->f_type = DTYPE_SOCKET; 672 rf->f_ops = &socketops; 673 rf->f_data = (caddr_t)rso; 674 wf = falloc(); 675 if (wf == NULL) 676 goto free3; 677 wf->f_flag = FWRITE; 678 wf->f_type = DTYPE_SOCKET; 679 wf->f_ops = &socketops; 680 wf->f_data = (caddr_t)wso; 681 u.u_r.r_val2 = u.u_r.r_val1; 682 u.u_r.r_val1 = r; 683 if (piconnect(wso, rso) == 0) 684 goto free4; 685 return; 686 free4: 687 wf->f_count = 0; 688 u.u_ofile[u.u_r.r_val2] = 0; 689 free3: 690 rf->f_count = 0; 691 u.u_ofile[r] = 0; 692 free2: 693 wso->so_state |= SS_NOFDREF; 694 sofree(wso); 695 free: 696 rso->so_state |= SS_NOFDREF; 697 sofree(rso); 698 } 699 700 /* 701 * Get socket name. 702 */ 703 getsockname() 704 { 705 register struct a { 706 int fdes; 707 caddr_t asa; 708 int *alen; 709 } *uap = (struct a *)u.u_ap; 710 register struct file *fp; 711 register struct socket *so; 712 struct mbuf *m; 713 int len; 714 715 fp = getsock(uap->fdes); 716 if (fp == 0) 717 return; 718 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 719 if (u.u_error) 720 return; 721 so = (struct socket *)fp->f_data; 722 m = m_getclr(M_WAIT, MT_SONAME); 723 if (m == NULL) { 724 u.u_error = ENOBUFS; 725 return; 726 } 727 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 728 if (u.u_error) 729 goto bad; 730 if (len > m->m_len) 731 len = m->m_len; 732 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 733 if (u.u_error) 734 goto bad; 735 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 736 bad: 737 m_freem(m); 738 } 739 740 sockargs(aname, name, namelen) 741 struct mbuf **aname; 742 caddr_t name; 743 int namelen; 744 { 745 register struct mbuf *m; 746 int error; 747 748 if (namelen > MLEN) 749 return (EINVAL); 750 m = m_get(M_WAIT, MT_SONAME); 751 if (m == NULL) 752 return (ENOBUFS); 753 m->m_len = namelen; 754 error = copyin(name, mtod(m, caddr_t), (u_int)namelen); 755 if (error) 756 (void) m_free(m); 757 else 758 *aname = m; 759 return (error); 760 } 761 762 struct file * 763 getsock(fdes) 764 int fdes; 765 { 766 register struct file *fp; 767 768 fp = getf(fdes); 769 if (fp == NULL) 770 return (0); 771 if (fp->f_type != DTYPE_SOCKET) { 772 u.u_error = ENOTSOCK; 773 return (0); 774 } 775 return (fp); 776 } 777