1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)uipc_syscalls.c 7.10 (Berkeley) 05/09/89 18 */ 19 20 #include "param.h" 21 #include "user.h" 22 #include "proc.h" 23 #include "file.h" 24 #include "buf.h" 25 #include "malloc.h" 26 #include "mbuf.h" 27 #include "protosw.h" 28 #include "socket.h" 29 #include "socketvar.h" 30 31 /* 32 * System call interface to the socket abstraction. 33 */ 34 35 struct file *getsock(); 36 extern struct fileops socketops; 37 38 socket() 39 { 40 register struct a { 41 int domain; 42 int type; 43 int protocol; 44 } *uap = (struct a *)u.u_ap; 45 struct socket *so; 46 struct file *fp; 47 int fd; 48 49 if (u.u_error = falloc(&fp, &fd)) 50 return; 51 fp->f_flag = FREAD|FWRITE; 52 fp->f_type = DTYPE_SOCKET; 53 fp->f_ops = &socketops; 54 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol); 55 if (u.u_error) 56 goto bad; 57 fp->f_data = (caddr_t)so; 58 u.u_r.r_val1 = fd; 59 return; 60 bad: 61 u.u_ofile[fd] = 0; 62 crfree(fp->f_cred); 63 fp->f_count = 0; 64 } 65 66 bind() 67 { 68 register struct a { 69 int s; 70 caddr_t name; 71 int namelen; 72 } *uap = (struct a *)u.u_ap; 73 register struct file *fp; 74 struct mbuf *nam; 75 76 fp = getsock(uap->s); 77 if (fp == 0) 78 return; 79 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); 80 if (u.u_error) 81 return; 82 u.u_error = sobind((struct socket *)fp->f_data, nam); 83 m_freem(nam); 84 } 85 86 listen() 87 { 88 register struct a { 89 int s; 90 int backlog; 91 } *uap = (struct a *)u.u_ap; 92 register struct file *fp; 93 94 fp = getsock(uap->s); 95 if (fp == 0) 96 return; 97 u.u_error = solisten((struct socket *)fp->f_data, uap->backlog); 98 } 99 100 #ifdef COMPAT_43 101 accept() 102 { 103 accept1(0); 104 } 105 106 oaccept() 107 { 108 accept1(1); 109 } 110 111 accept1(compat_43) 112 #else 113 accept() 114 #endif 115 { 116 register struct a { 117 int s; 118 caddr_t name; 119 int *anamelen; 120 } *uap = (struct a *)u.u_ap; 121 struct file *fp; 122 struct mbuf *nam; 123 int namelen; 124 int s; 125 register struct socket *so; 126 127 if (uap->name == 0) 128 goto noname; 129 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 130 sizeof (namelen)); 131 if (u.u_error) 132 return; 133 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { 134 u.u_error = EFAULT; 135 return; 136 } 137 noname: 138 fp = getsock(uap->s); 139 if (fp == 0) 140 return; 141 s = splnet(); 142 so = (struct socket *)fp->f_data; 143 if ((so->so_options & SO_ACCEPTCONN) == 0) { 144 u.u_error = EINVAL; 145 splx(s); 146 return; 147 } 148 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 149 u.u_error = EWOULDBLOCK; 150 splx(s); 151 return; 152 } 153 while (so->so_qlen == 0 && so->so_error == 0) { 154 if (so->so_state & SS_CANTRCVMORE) { 155 so->so_error = ECONNABORTED; 156 break; 157 } 158 sleep((caddr_t)&so->so_timeo, PZERO+1); 159 } 160 if (so->so_error) { 161 u.u_error = so->so_error; 162 so->so_error = 0; 163 splx(s); 164 return; 165 } 166 if (u.u_error = falloc(&fp, &u.u_r.r_val1)) { 167 splx(s); 168 return; 169 } 170 { struct socket *aso = so->so_q; 171 if (soqremque(aso, 1) == 0) 172 panic("accept"); 173 so = aso; 174 } 175 fp->f_type = DTYPE_SOCKET; 176 fp->f_flag = FREAD|FWRITE; 177 fp->f_ops = &socketops; 178 fp->f_data = (caddr_t)so; 179 nam = m_get(M_WAIT, MT_SONAME); 180 (void) soaccept(so, nam); 181 if (uap->name) { 182 #ifdef COMPAT_43 183 if (compat_43) 184 mtod(nam, struct osockaddr *)->sa_family = 185 mtod(nam, struct sockaddr *)->sa_family; 186 #endif 187 if (namelen > nam->m_len) 188 namelen = nam->m_len; 189 /* SHOULD COPY OUT A CHAIN HERE */ 190 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, 191 (u_int)namelen); 192 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, 193 sizeof (*uap->anamelen)); 194 } 195 m_freem(nam); 196 splx(s); 197 } 198 199 connect() 200 { 201 register struct a { 202 int s; 203 caddr_t name; 204 int namelen; 205 } *uap = (struct a *)u.u_ap; 206 register struct file *fp; 207 register struct socket *so; 208 struct mbuf *nam; 209 int s; 210 211 fp = getsock(uap->s); 212 if (fp == 0) 213 return; 214 so = (struct socket *)fp->f_data; 215 if ((so->so_state & SS_NBIO) && 216 (so->so_state & SS_ISCONNECTING)) { 217 u.u_error = EALREADY; 218 return; 219 } 220 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); 221 if (u.u_error) 222 return; 223 u.u_error = soconnect(so, nam); 224 if (u.u_error) 225 goto bad; 226 if ((so->so_state & SS_NBIO) && 227 (so->so_state & SS_ISCONNECTING)) { 228 u.u_error = EINPROGRESS; 229 m_freem(nam); 230 return; 231 } 232 s = splnet(); 233 if (setjmp(&u.u_qsave)) { 234 if (u.u_error == 0) 235 u.u_error = EINTR; 236 goto bad2; 237 } 238 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 239 sleep((caddr_t)&so->so_timeo, PZERO+1); 240 u.u_error = so->so_error; 241 so->so_error = 0; 242 bad2: 243 splx(s); 244 bad: 245 so->so_state &= ~SS_ISCONNECTING; 246 m_freem(nam); 247 } 248 249 socketpair() 250 { 251 register struct a { 252 int domain; 253 int type; 254 int protocol; 255 int *rsv; 256 } *uap = (struct a *)u.u_ap; 257 struct file *fp1, *fp2; 258 struct socket *so1, *so2; 259 int fd, sv[2]; 260 261 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) { 262 u.u_error = EFAULT; 263 return; 264 } 265 u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol); 266 if (u.u_error) 267 return; 268 u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol); 269 if (u.u_error) 270 goto free1; 271 if (u.u_error = falloc(&fp1, &fd)) 272 goto free2; 273 sv[0] = fd; 274 fp1->f_flag = FREAD|FWRITE; 275 fp1->f_type = DTYPE_SOCKET; 276 fp1->f_ops = &socketops; 277 fp1->f_data = (caddr_t)so1; 278 if (u.u_error = falloc(&fp2, &fd)) 279 goto free3; 280 fp2->f_flag = FREAD|FWRITE; 281 fp2->f_type = DTYPE_SOCKET; 282 fp2->f_ops = &socketops; 283 fp2->f_data = (caddr_t)so2; 284 sv[1] = fd; 285 u.u_error = soconnect2(so1, so2); 286 if (u.u_error) 287 goto free4; 288 if (uap->type == SOCK_DGRAM) { 289 /* 290 * Datagram socket connection is asymmetric. 291 */ 292 u.u_error = soconnect2(so2, so1); 293 if (u.u_error) 294 goto free4; 295 } 296 (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 297 u.u_r.r_val1 = sv[0]; 298 u.u_r.r_val2 = sv[1]; 299 return; 300 free4: 301 crfree(fp2->f_cred); 302 fp2->f_count = 0; 303 u.u_ofile[sv[1]] = 0; 304 free3: 305 crfree(fp1->f_cred); 306 fp1->f_count = 0; 307 u.u_ofile[sv[0]] = 0; 308 free2: 309 (void)soclose(so2); 310 free1: 311 (void)soclose(so1); 312 } 313 314 sendto() 315 { 316 register struct a { 317 int s; 318 caddr_t buf; 319 int len; 320 int flags; 321 caddr_t to; 322 int tolen; 323 } *uap = (struct a *)u.u_ap; 324 struct msghdr msg; 325 struct iovec aiov; 326 327 msg.msg_name = uap->to; 328 msg.msg_namelen = uap->tolen; 329 msg.msg_iov = &aiov; 330 msg.msg_iovlen = 1; 331 aiov.iov_base = uap->buf; 332 aiov.iov_len = uap->len; 333 msg.msg_accrights = 0; 334 msg.msg_control = 0; 335 sendit(uap->s, &msg, uap->flags); 336 } 337 338 #ifdef COMPAT_43 339 340 osend() 341 { 342 register struct a { 343 int s; 344 caddr_t buf; 345 int len; 346 int flags; 347 } *uap = (struct a *)u.u_ap; 348 struct msghdr msg; 349 struct iovec aiov; 350 351 msg.msg_name = 0; 352 msg.msg_namelen = 0; 353 msg.msg_iov = &aiov; 354 msg.msg_iovlen = 1; 355 aiov.iov_base = uap->buf; 356 aiov.iov_len = uap->len; 357 msg.msg_accrights = 0; 358 msg.msg_control = 0; 359 sendit(uap->s, &msg, uap->flags); 360 } 361 362 osendmsg() 363 { 364 register struct a { 365 int s; 366 caddr_t msg; 367 int flags; 368 } *uap = (struct a *)u.u_ap; 369 struct msghdr msg; 370 struct iovec aiov[MSG_MAXIOVLEN]; 371 372 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)); 373 if (u.u_error) 374 return; 375 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 376 u.u_error = EMSGSIZE; 377 return; 378 } 379 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 380 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 381 if (u.u_error) 382 return; 383 msg.msg_control = 0; 384 msg.msg_controllen = 0; 385 sendit(uap->s, &msg, uap->flags); 386 } 387 #endif 388 389 sendmsg() 390 { 391 register struct a { 392 int s; 393 caddr_t msg; 394 int flags; 395 } *uap = (struct a *)u.u_ap; 396 struct msghdr msg; 397 struct iovec aiov[MSG_MAXIOVLEN]; 398 399 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 400 if (u.u_error) 401 return; 402 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 403 u.u_error = EMSGSIZE; 404 return; 405 } 406 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 407 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 408 if (u.u_error) 409 return; 410 msg.msg_iov = aiov; 411 sendit(uap->s, &msg, uap->flags); 412 } 413 414 sendit(s, mp, flags) 415 int s; 416 register struct msghdr *mp; 417 int flags; 418 { 419 register struct file *fp; 420 struct uio auio; 421 register struct iovec *iov; 422 register int i; 423 struct mbuf *to, *rights, *control; 424 int len; 425 426 fp = getsock(s); 427 if (fp == 0) 428 return; 429 auio.uio_iov = mp->msg_iov; 430 auio.uio_iovcnt = mp->msg_iovlen; 431 auio.uio_segflg = UIO_USERSPACE; 432 auio.uio_rw = UIO_WRITE; 433 auio.uio_offset = 0; /* XXX */ 434 auio.uio_resid = 0; 435 iov = mp->msg_iov; 436 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 437 if (iov->iov_len < 0) { 438 u.u_error = EINVAL; 439 return; 440 } 441 if (iov->iov_len == 0) 442 continue; 443 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) { 444 u.u_error = EFAULT; 445 return; 446 } 447 auio.uio_resid += iov->iov_len; 448 } 449 if (mp->msg_name) { 450 u.u_error = 451 sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME); 452 if (u.u_error) 453 return; 454 } else 455 to = 0; 456 if (mp->msg_accrights) { 457 u.u_error = 458 sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen, 459 MT_RIGHTS); 460 if (u.u_error) 461 goto bad; 462 } else 463 rights = 0; 464 if (mp->msg_control) { 465 u.u_error = 466 sockargs(&control, mp->msg_control, mp->msg_controllen, 467 MT_CONTROL); 468 if (u.u_error) 469 goto bad; 470 } else 471 control = 0; 472 len = auio.uio_resid; 473 if (setjmp(&u.u_qsave)) { /* XXX */ 474 if (auio.uio_resid == len) { 475 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 476 u.u_error = EINTR; 477 else 478 u.u_eosys = RESTARTSYS; 479 } 480 } else 481 u.u_error = sosend((struct socket *)fp->f_data, to, &auio, 482 flags, rights, control); 483 u.u_r.r_val1 = len - auio.uio_resid; 484 bad: 485 if (rights) 486 m_freem(rights); 487 if (to) 488 m_freem(to); 489 if (control) 490 m_freem(control); 491 } 492 493 #ifdef COMPAT_43 494 recvfrom() 495 { 496 recvfrom1(0); 497 } 498 499 orecvfrom() 500 { 501 recvfrom1(1); 502 } 503 504 recvfrom1(compat_43) 505 { /* vi will want an extra } to be happy! */ 506 #else 507 recvfrom() 508 { 509 int compat_43 = 0; 510 #endif 511 register struct a { 512 int s; 513 caddr_t buf; 514 int len; 515 int flags; 516 caddr_t from; 517 int *fromlenaddr; 518 } *uap = (struct a *)u.u_ap; 519 struct msghdr msg; 520 struct iovec aiov; 521 int len; 522 523 if (uap->fromlenaddr) { 524 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, 525 sizeof (len)); 526 if (u.u_error) 527 return; 528 } else 529 len = 0; 530 msg.msg_name = uap->from; 531 msg.msg_namelen = len; 532 msg.msg_iov = &aiov; 533 msg.msg_iovlen = 1; 534 aiov.iov_base = uap->buf; 535 aiov.iov_len = uap->len; 536 msg.msg_accrights = 0; 537 msg.msg_control = 0; 538 msg.msg_flags = uap->flags; 539 recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, compat_43); 540 } 541 #ifdef COMPAT_43 542 orecv() 543 { 544 register struct a { 545 int s; 546 caddr_t buf; 547 int len; 548 int flags; 549 } *uap = (struct a *)u.u_ap; 550 struct msghdr msg; 551 struct iovec aiov; 552 553 msg.msg_name = 0; 554 msg.msg_namelen = 0; 555 msg.msg_iov = &aiov; 556 msg.msg_iovlen = 1; 557 aiov.iov_base = uap->buf; 558 aiov.iov_len = uap->len; 559 msg.msg_accrights = 0; 560 msg.msg_control = 0; 561 msg.msg_flags = uap->flags; 562 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0); 563 } 564 565 orecvmsg() 566 { 567 register struct a { 568 int s; 569 struct omsghdr *msg; 570 int flags; 571 } *uap = (struct a *)u.u_ap; 572 struct msghdr msg; 573 struct iovec aiov[MSG_MAXIOVLEN]; 574 575 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 576 sizeof (struct omsghdr)); 577 if (u.u_error) 578 return; 579 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 580 u.u_error = EMSGSIZE; 581 return; 582 } 583 msg.msg_control = 0; 584 msg.msg_flags = uap->flags; 585 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 586 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 587 if (u.u_error) 588 return; 589 msg.msg_iov = aiov; 590 if (msg.msg_accrights) 591 if (useracc((caddr_t)msg.msg_accrights, 592 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { 593 u.u_error = EFAULT; 594 return; 595 } 596 597 recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, 598 (caddr_t)&uap->msg->msg_accrightslen, /* compat_43 */1); 599 } 600 #endif 601 602 recvmsg() 603 { 604 register struct a { 605 int s; 606 struct msghdr *msg; 607 int flags; 608 } *uap = (struct a *)u.u_ap; 609 struct msghdr msg; 610 struct iovec aiov[MSG_MAXIOVLEN], *uiov; 611 612 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 613 if (u.u_error) 614 return; 615 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 616 u.u_error = EMSGSIZE; 617 return; 618 } 619 msg.msg_flags = uap->flags; 620 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 621 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 622 if (u.u_error) 623 return; 624 uiov = msg.msg_iov; 625 msg.msg_iov = aiov; 626 if (msg.msg_accrights) 627 if (useracc((caddr_t)msg.msg_accrights, 628 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { 629 u.u_error = EFAULT; 630 return; 631 } 632 if (msg.msg_control) 633 if (useracc((caddr_t)msg.msg_control, 634 (unsigned)msg.msg_controllen, B_WRITE) == 0) { 635 u.u_error = EFAULT; 636 return; 637 } 638 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0); 639 msg.msg_iov = uiov; 640 u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 641 } 642 643 /* ARGSUSED */ 644 recvit(s, mp, namelenp, rightslenp, compat_43) 645 int s, compat_43; 646 register struct msghdr *mp; 647 caddr_t namelenp, rightslenp; 648 { 649 register struct file *fp; 650 struct uio auio; 651 register struct iovec *iov; 652 register int i; 653 int len; 654 struct mbuf *from = 0, *rights = 0, *control = 0; 655 656 fp = getsock(s); 657 if (fp == 0) 658 return; 659 auio.uio_iov = mp->msg_iov; 660 auio.uio_iovcnt = mp->msg_iovlen; 661 auio.uio_segflg = UIO_USERSPACE; 662 auio.uio_rw = UIO_READ; 663 auio.uio_offset = 0; /* XXX */ 664 auio.uio_resid = 0; 665 iov = mp->msg_iov; 666 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 667 if (iov->iov_len < 0) { 668 u.u_error = EINVAL; 669 return; 670 } 671 if (iov->iov_len == 0) 672 continue; 673 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) { 674 u.u_error = EFAULT; 675 return; 676 } 677 auio.uio_resid += iov->iov_len; 678 } 679 len = auio.uio_resid; 680 if (setjmp(&u.u_qsave)) { /* XXX */ 681 if (auio.uio_resid == len) { 682 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 683 u.u_error = EINTR; 684 else 685 u.u_eosys = RESTARTSYS; 686 } 687 } else 688 u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio, 689 &mp->msg_flags, &rights, &control); 690 u.u_r.r_val1 = len - auio.uio_resid; 691 if (mp->msg_name) { 692 len = mp->msg_namelen; 693 if (len <= 0 || from == 0) 694 len = 0; 695 else { 696 #ifdef COMPAT_43 697 if (compat_43) 698 mtod(from, struct osockaddr *)->sa_family = 699 mtod(from, struct sockaddr *)->sa_family; 700 #endif 701 if (len > from->m_len) /* ??? */ 702 len = from->m_len; 703 (void) copyout(mtod(from, caddr_t), 704 (caddr_t)mp->msg_name, (unsigned)len); 705 } 706 mp->msg_namelen = len; 707 if (namelenp) 708 (void) copyout((caddr_t)&len, namelenp, sizeof (int)); 709 } 710 if (mp->msg_accrights) { 711 len = mp->msg_accrightslen; 712 if (len <= 0 || rights == 0) 713 len = 0; 714 else { 715 if (len > rights->m_len) 716 len = rights->m_len; 717 (void) copyout((caddr_t)mtod(rights, caddr_t), 718 (caddr_t)mp->msg_accrights, (unsigned)len); 719 } 720 mp->msg_accrightslen = len; 721 if (rightslenp) 722 (void) copyout((caddr_t)&len, rightslenp, sizeof (int)); 723 } 724 if (mp->msg_control) { 725 len = mp->msg_controllen; 726 if (len <= 0 || control == 0) 727 len = 0; 728 else { 729 if (len >= control->m_len) 730 len = control->m_len; 731 else 732 mp->msg_flags |= MSG_CTRUNC; 733 (void) copyout((caddr_t)mtod(control, caddr_t), 734 (caddr_t)mp->msg_control, (unsigned)len); 735 } 736 mp->msg_controllen = len; 737 } 738 if (rights) 739 m_freem(rights); 740 if (from) 741 m_freem(from); 742 if (control) 743 m_freem(control); 744 } 745 746 shutdown() 747 { 748 struct a { 749 int s; 750 int how; 751 } *uap = (struct a *)u.u_ap; 752 struct file *fp; 753 754 fp = getsock(uap->s); 755 if (fp == 0) 756 return; 757 u.u_error = soshutdown((struct socket *)fp->f_data, uap->how); 758 } 759 760 setsockopt() 761 { 762 struct a { 763 int s; 764 int level; 765 int name; 766 caddr_t val; 767 int valsize; 768 } *uap = (struct a *)u.u_ap; 769 struct file *fp; 770 struct mbuf *m = NULL; 771 772 fp = getsock(uap->s); 773 if (fp == 0) 774 return; 775 if (uap->valsize > MLEN) { 776 u.u_error = EINVAL; 777 return; 778 } 779 if (uap->val) { 780 m = m_get(M_WAIT, MT_SOOPTS); 781 if (m == NULL) { 782 u.u_error = ENOBUFS; 783 return; 784 } 785 u.u_error = 786 copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 787 if (u.u_error) { 788 (void) m_free(m); 789 return; 790 } 791 m->m_len = uap->valsize; 792 } 793 u.u_error = 794 sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m); 795 } 796 797 getsockopt() 798 { 799 struct a { 800 int s; 801 int level; 802 int name; 803 caddr_t val; 804 int *avalsize; 805 } *uap = (struct a *)u.u_ap; 806 struct file *fp; 807 struct mbuf *m = NULL; 808 int valsize; 809 810 fp = getsock(uap->s); 811 if (fp == 0) 812 return; 813 if (uap->val) { 814 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 815 sizeof (valsize)); 816 if (u.u_error) 817 return; 818 } else 819 valsize = 0; 820 u.u_error = 821 sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m); 822 if (u.u_error) 823 goto bad; 824 if (uap->val && valsize && m != NULL) { 825 if (valsize > m->m_len) 826 valsize = m->m_len; 827 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 828 if (u.u_error) 829 goto bad; 830 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, 831 sizeof (valsize)); 832 } 833 bad: 834 if (m != NULL) 835 (void) m_free(m); 836 } 837 838 pipe() 839 { 840 struct file *rf, *wf; 841 struct socket *rso, *wso; 842 int fd, r; 843 844 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0); 845 if (u.u_error) 846 return; 847 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0); 848 if (u.u_error) 849 goto free1; 850 if (u.u_error = falloc(&rf, &fd)) 851 goto free2; 852 u.u_r.r_val1 = fd; 853 rf->f_flag = FREAD; 854 rf->f_type = DTYPE_SOCKET; 855 rf->f_ops = &socketops; 856 rf->f_data = (caddr_t)rso; 857 if (u.u_error = falloc(&wf, &fd)) 858 goto free3; 859 wf->f_flag = FWRITE; 860 wf->f_type = DTYPE_SOCKET; 861 wf->f_ops = &socketops; 862 wf->f_data = (caddr_t)wso; 863 u.u_r.r_val2 = fd; 864 if (u.u_error = unp_connect2(wso, rso)) 865 goto free4; 866 wso->so_state |= SS_CANTRCVMORE; 867 rso->so_state |= SS_CANTSENDMORE; 868 return; 869 free4: 870 wf->f_count = 0; 871 u.u_ofile[u.u_r.r_val2] = 0; 872 free3: 873 rf->f_count = 0; 874 u.u_ofile[u.u_r.r_val1] = 0; 875 free2: 876 (void)soclose(wso); 877 free1: 878 (void)soclose(rso); 879 } 880 881 /* 882 * Get socket name. 883 */ 884 #ifdef COMPAT_43 885 getsockname() 886 { 887 getsockname1(0); 888 } 889 890 ogetsockname() 891 { 892 getsockname1(1); 893 } 894 895 getsockname1(compat_43) 896 #else 897 getsockname() 898 #endif 899 { 900 register struct a { 901 int fdes; 902 caddr_t asa; 903 int *alen; 904 } *uap = (struct a *)u.u_ap; 905 register struct file *fp; 906 register struct socket *so; 907 struct mbuf *m; 908 int len; 909 910 fp = getsock(uap->fdes); 911 if (fp == 0) 912 return; 913 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 914 if (u.u_error) 915 return; 916 so = (struct socket *)fp->f_data; 917 m = m_getclr(M_WAIT, MT_SONAME); 918 if (m == NULL) { 919 u.u_error = ENOBUFS; 920 return; 921 } 922 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 923 if (u.u_error) 924 goto bad; 925 if (len > m->m_len) 926 len = m->m_len; 927 #ifdef COMPAT_43 928 if (compat_43) 929 mtod(m, struct osockaddr *)->sa_family = 930 mtod(m, struct sockaddr *)->sa_family; 931 #endif 932 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 933 if (u.u_error == 0) 934 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, 935 sizeof (len)); 936 bad: 937 m_freem(m); 938 } 939 940 /* 941 * Get name of peer for connected socket. 942 */ 943 #ifdef COMPAT_43 944 getpeername() 945 { 946 getpeername1(0); 947 } 948 949 ogetpeername() 950 { 951 getpeername1(1); 952 } 953 954 getpeername1(compat_43) 955 #else 956 getpeername() 957 #endif 958 { 959 register struct a { 960 int fdes; 961 caddr_t asa; 962 int *alen; 963 } *uap = (struct a *)u.u_ap; 964 register struct file *fp; 965 register struct socket *so; 966 struct mbuf *m; 967 int len; 968 969 fp = getsock(uap->fdes); 970 if (fp == 0) 971 return; 972 so = (struct socket *)fp->f_data; 973 if ((so->so_state & SS_ISCONNECTED) == 0) { 974 u.u_error = ENOTCONN; 975 return; 976 } 977 m = m_getclr(M_WAIT, MT_SONAME); 978 if (m == NULL) { 979 u.u_error = ENOBUFS; 980 return; 981 } 982 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 983 if (u.u_error) 984 return; 985 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); 986 if (u.u_error) 987 goto bad; 988 if (len > m->m_len) 989 len = m->m_len; 990 #ifdef COMPAT_43 991 if (compat_43) 992 mtod(m, struct osockaddr *)->sa_family = 993 mtod(m, struct sockaddr *)->sa_family; 994 #endif 995 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 996 if (u.u_error) 997 goto bad; 998 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 999 bad: 1000 m_freem(m); 1001 } 1002 1003 sockargs(aname, name, namelen, type) 1004 struct mbuf **aname; 1005 caddr_t name; 1006 int namelen, type; 1007 { 1008 register struct mbuf *m; 1009 int error; 1010 1011 if ((u_int)namelen > MLEN) 1012 return (EINVAL); 1013 m = m_get(M_WAIT, type); 1014 if (m == NULL) 1015 return (ENOBUFS); 1016 m->m_len = namelen; 1017 error = copyin(name, mtod(m, caddr_t), (u_int)namelen); 1018 if (error) 1019 (void) m_free(m); 1020 else 1021 *aname = m; 1022 if (type == MT_SONAME) { 1023 register struct sockaddr *sa = mtod(m, struct sockaddr *); 1024 #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN 1025 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1026 sa->sa_family = sa->sa_len; 1027 #endif 1028 sa->sa_len = namelen; 1029 } 1030 return (error); 1031 } 1032 1033 struct file * 1034 getsock(fdes) 1035 int fdes; 1036 { 1037 register struct file *fp; 1038 1039 if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { 1040 u.u_error = EBADF; 1041 return (0); 1042 } 1043 if (fp->f_type != DTYPE_SOCKET) { 1044 u.u_error = ENOTSOCK; 1045 return (0); 1046 } 1047 return (fp); 1048 } 1049