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