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.8 (Berkeley) 04/22/89 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 #ifdef COMPAT_43 99 accept() 100 { 101 accept1(0); 102 } 103 104 oaccept() 105 { 106 accept1(1); 107 } 108 109 accept1(compat_43) 110 #else 111 accept() 112 #endif 113 { 114 register struct a { 115 int s; 116 caddr_t name; 117 int *anamelen; 118 } *uap = (struct a *)u.u_ap; 119 register struct file *fp; 120 struct mbuf *nam; 121 int namelen; 122 int s; 123 register struct socket *so; 124 125 if (uap->name == 0) 126 goto noname; 127 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 128 sizeof (namelen)); 129 if (u.u_error) 130 return; 131 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { 132 u.u_error = EFAULT; 133 return; 134 } 135 noname: 136 fp = getsock(uap->s); 137 if (fp == 0) 138 return; 139 s = splnet(); 140 so = (struct socket *)fp->f_data; 141 if ((so->so_options & SO_ACCEPTCONN) == 0) { 142 u.u_error = EINVAL; 143 splx(s); 144 return; 145 } 146 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 147 u.u_error = EWOULDBLOCK; 148 splx(s); 149 return; 150 } 151 while (so->so_qlen == 0 && so->so_error == 0) { 152 if (so->so_state & SS_CANTRCVMORE) { 153 so->so_error = ECONNABORTED; 154 break; 155 } 156 sleep((caddr_t)&so->so_timeo, PZERO+1); 157 } 158 if (so->so_error) { 159 u.u_error = so->so_error; 160 so->so_error = 0; 161 splx(s); 162 return; 163 } 164 if (ufalloc(0) < 0) { 165 splx(s); 166 return; 167 } 168 fp = falloc(); 169 if (fp == 0) { 170 u.u_ofile[u.u_r.r_val1] = 0; 171 splx(s); 172 return; 173 } 174 { struct socket *aso = so->so_q; 175 if (soqremque(aso, 1) == 0) 176 panic("accept"); 177 so = aso; 178 } 179 fp->f_type = DTYPE_SOCKET; 180 fp->f_flag = FREAD|FWRITE; 181 fp->f_ops = &socketops; 182 fp->f_data = (caddr_t)so; 183 nam = m_get(M_WAIT, MT_SONAME); 184 (void) soaccept(so, nam); 185 if (uap->name) { 186 #ifdef COMPAT_43 187 if (compat_43) 188 mtod(nam, struct osockaddr *)->sa_family = 189 mtod(nam, struct sockaddr *)->sa_family; 190 #endif 191 if (namelen > nam->m_len) 192 namelen = nam->m_len; 193 /* SHOULD COPY OUT A CHAIN HERE */ 194 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, 195 (u_int)namelen); 196 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, 197 sizeof (*uap->anamelen)); 198 } 199 m_freem(nam); 200 splx(s); 201 } 202 203 connect() 204 { 205 register struct a { 206 int s; 207 caddr_t name; 208 int namelen; 209 } *uap = (struct a *)u.u_ap; 210 register struct file *fp; 211 register struct socket *so; 212 struct mbuf *nam; 213 int s; 214 215 fp = getsock(uap->s); 216 if (fp == 0) 217 return; 218 so = (struct socket *)fp->f_data; 219 if ((so->so_state & SS_NBIO) && 220 (so->so_state & SS_ISCONNECTING)) { 221 u.u_error = EALREADY; 222 return; 223 } 224 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); 225 if (u.u_error) 226 return; 227 u.u_error = soconnect(so, nam); 228 if (u.u_error) 229 goto bad; 230 if ((so->so_state & SS_NBIO) && 231 (so->so_state & SS_ISCONNECTING)) { 232 u.u_error = EINPROGRESS; 233 m_freem(nam); 234 return; 235 } 236 s = splnet(); 237 if (setjmp(&u.u_qsave)) { 238 if (u.u_error == 0) 239 u.u_error = EINTR; 240 goto bad2; 241 } 242 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 243 sleep((caddr_t)&so->so_timeo, PZERO+1); 244 u.u_error = so->so_error; 245 so->so_error = 0; 246 bad2: 247 splx(s); 248 bad: 249 so->so_state &= ~SS_ISCONNECTING; 250 m_freem(nam); 251 } 252 253 socketpair() 254 { 255 register struct a { 256 int domain; 257 int type; 258 int protocol; 259 int *rsv; 260 } *uap = (struct a *)u.u_ap; 261 register struct file *fp1, *fp2; 262 struct socket *so1, *so2; 263 int sv[2]; 264 265 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) { 266 u.u_error = EFAULT; 267 return; 268 } 269 u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol); 270 if (u.u_error) 271 return; 272 u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol); 273 if (u.u_error) 274 goto freeit; 275 fp1 = falloc(); 276 if (fp1 == NULL) 277 goto free2; 278 sv[0] = u.u_r.r_val1; 279 fp1->f_flag = FREAD|FWRITE; 280 fp1->f_type = DTYPE_SOCKET; 281 fp1->f_ops = &socketops; 282 fp1->f_data = (caddr_t)so1; 283 fp2 = falloc(); 284 if (fp2 == NULL) 285 goto free3; 286 fp2->f_flag = FREAD|FWRITE; 287 fp2->f_type = DTYPE_SOCKET; 288 fp2->f_ops = &socketops; 289 fp2->f_data = (caddr_t)so2; 290 sv[1] = u.u_r.r_val1; 291 u.u_error = soconnect2(so1, so2); 292 if (u.u_error) 293 goto free4; 294 if (uap->type == SOCK_DGRAM) { 295 /* 296 * Datagram socket connection is asymmetric. 297 */ 298 u.u_error = soconnect2(so2, so1); 299 if (u.u_error) 300 goto free4; 301 } 302 u.u_r.r_val1 = 0; 303 (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 304 return; 305 free4: 306 fp2->f_count = 0; 307 u.u_ofile[sv[1]] = 0; 308 free3: 309 fp1->f_count = 0; 310 u.u_ofile[sv[0]] = 0; 311 free2: 312 (void)soclose(so2); 313 freeit: 314 (void)soclose(so1); 315 } 316 317 sendto() 318 { 319 register struct a { 320 int s; 321 caddr_t buf; 322 int len; 323 int flags; 324 caddr_t to; 325 int tolen; 326 } *uap = (struct a *)u.u_ap; 327 struct msghdr msg; 328 struct iovec aiov; 329 330 msg.msg_name = uap->to; 331 msg.msg_namelen = uap->tolen; 332 msg.msg_iov = &aiov; 333 msg.msg_iovlen = 1; 334 aiov.iov_base = uap->buf; 335 aiov.iov_len = uap->len; 336 msg.msg_accrights = 0; 337 msg.msg_control = 0; 338 sendit(uap->s, &msg, uap->flags); 339 } 340 341 #ifdef COMPAT_43 342 343 osend() 344 { 345 register struct a { 346 int s; 347 caddr_t buf; 348 int len; 349 int flags; 350 } *uap = (struct a *)u.u_ap; 351 struct msghdr msg; 352 struct iovec aiov; 353 354 msg.msg_name = 0; 355 msg.msg_namelen = 0; 356 msg.msg_iov = &aiov; 357 msg.msg_iovlen = 1; 358 aiov.iov_base = uap->buf; 359 aiov.iov_len = uap->len; 360 msg.msg_accrights = 0; 361 msg.msg_control = 0; 362 sendit(uap->s, &msg, uap->flags); 363 } 364 365 osendmsg() 366 { 367 register struct a { 368 int s; 369 caddr_t msg; 370 int flags; 371 } *uap = (struct a *)u.u_ap; 372 struct msghdr msg; 373 struct iovec aiov[MSG_MAXIOVLEN]; 374 375 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)); 376 if (u.u_error) 377 return; 378 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 379 u.u_error = EMSGSIZE; 380 return; 381 } 382 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 383 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 384 if (u.u_error) 385 return; 386 msg.msg_control = 0; 387 msg.msg_controllen = 0; 388 sendit(uap->s, &msg, uap->flags); 389 } 390 #endif 391 392 sendmsg() 393 { 394 register struct a { 395 int s; 396 caddr_t msg; 397 int flags; 398 } *uap = (struct a *)u.u_ap; 399 struct msghdr msg; 400 struct iovec aiov[MSG_MAXIOVLEN]; 401 402 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 403 if (u.u_error) 404 return; 405 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 406 u.u_error = EMSGSIZE; 407 return; 408 } 409 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 410 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 411 if (u.u_error) 412 return; 413 msg.msg_iov = aiov; 414 sendit(uap->s, &msg, uap->flags); 415 } 416 417 sendit(s, mp, flags) 418 int s; 419 register struct msghdr *mp; 420 int flags; 421 { 422 register struct file *fp; 423 struct uio auio; 424 register struct iovec *iov; 425 register int i; 426 struct mbuf *to, *rights, *control; 427 int len; 428 429 fp = getsock(s); 430 if (fp == 0) 431 return; 432 auio.uio_iov = mp->msg_iov; 433 auio.uio_iovcnt = mp->msg_iovlen; 434 auio.uio_segflg = UIO_USERSPACE; 435 auio.uio_offset = 0; /* XXX */ 436 auio.uio_resid = 0; 437 iov = mp->msg_iov; 438 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 439 if (iov->iov_len < 0) { 440 u.u_error = EINVAL; 441 return; 442 } 443 if (iov->iov_len == 0) 444 continue; 445 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) { 446 u.u_error = EFAULT; 447 return; 448 } 449 auio.uio_resid += iov->iov_len; 450 } 451 if (mp->msg_name) { 452 u.u_error = 453 sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME); 454 if (u.u_error) 455 return; 456 } else 457 to = 0; 458 if (mp->msg_accrights) { 459 u.u_error = 460 sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen, 461 MT_RIGHTS); 462 if (u.u_error) 463 goto bad; 464 } else 465 rights = 0; 466 if (mp->msg_control) { 467 u.u_error = 468 sockargs(&control, mp->msg_control, mp->msg_controllen, 469 MT_CONTROL); 470 if (u.u_error) 471 goto bad; 472 } else 473 control = 0; 474 len = auio.uio_resid; 475 if (setjmp(&u.u_qsave)) { /* XXX */ 476 if (auio.uio_resid == len) { 477 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 478 u.u_error = EINTR; 479 else 480 u.u_eosys = RESTARTSYS; 481 } 482 } else 483 u.u_error = sosend((struct socket *)fp->f_data, to, &auio, 484 flags, rights, control); 485 u.u_r.r_val1 = len - auio.uio_resid; 486 bad: 487 if (rights) 488 m_freem(rights); 489 if (to) 490 m_freem(to); 491 if (control) 492 m_freem(control); 493 } 494 495 #ifdef COMPAT_43 496 recvfrom() 497 { 498 recvfrom1(0); 499 } 500 501 orecvfrom() 502 { 503 recvfrom1(1); 504 } 505 506 recvfrom1(compat_43) 507 { /* vi will want an extra } to be happy! */ 508 #else 509 recvfrom() 510 { 511 int compat_43 = 0; 512 #endif 513 register struct a { 514 int s; 515 caddr_t buf; 516 int len; 517 int flags; 518 caddr_t from; 519 int *fromlenaddr; 520 } *uap = (struct a *)u.u_ap; 521 struct msghdr msg; 522 struct iovec aiov; 523 int len; 524 525 if (uap->fromlenaddr) { 526 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, 527 sizeof (len)); 528 if (u.u_error) 529 return; 530 } else 531 len = 0; 532 msg.msg_name = uap->from; 533 msg.msg_namelen = len; 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)uap->fromlenaddr, (caddr_t)0, compat_43); 542 } 543 #ifdef COMPAT_43 544 orecv() 545 { 546 register struct a { 547 int s; 548 caddr_t buf; 549 int len; 550 int flags; 551 } *uap = (struct a *)u.u_ap; 552 struct msghdr msg; 553 struct iovec aiov; 554 555 msg.msg_name = 0; 556 msg.msg_namelen = 0; 557 msg.msg_iov = &aiov; 558 msg.msg_iovlen = 1; 559 aiov.iov_base = uap->buf; 560 aiov.iov_len = uap->len; 561 msg.msg_accrights = 0; 562 msg.msg_control = 0; 563 msg.msg_flags = uap->flags; 564 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0); 565 } 566 567 orecvmsg() 568 { 569 register struct a { 570 int s; 571 struct omsghdr *msg; 572 int flags; 573 } *uap = (struct a *)u.u_ap; 574 struct msghdr msg; 575 struct iovec aiov[MSG_MAXIOVLEN]; 576 577 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 578 sizeof (struct omsghdr)); 579 if (u.u_error) 580 return; 581 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 582 u.u_error = EMSGSIZE; 583 return; 584 } 585 msg.msg_control = 0; 586 msg.msg_flags = uap->flags; 587 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 588 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 589 if (u.u_error) 590 return; 591 msg.msg_iov = aiov; 592 if (msg.msg_accrights) 593 if (useracc((caddr_t)msg.msg_accrights, 594 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { 595 u.u_error = EFAULT; 596 return; 597 } 598 599 recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, 600 (caddr_t)&uap->msg->msg_accrightslen, /* compat_43 */1); 601 } 602 #endif 603 604 recvmsg() 605 { 606 register struct a { 607 int s; 608 struct msghdr *msg; 609 int flags; 610 } *uap = (struct a *)u.u_ap; 611 struct msghdr msg; 612 struct iovec aiov[MSG_MAXIOVLEN], *uiov; 613 614 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 615 if (u.u_error) 616 return; 617 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 618 u.u_error = EMSGSIZE; 619 return; 620 } 621 msg.msg_flags = uap->flags; 622 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 623 (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 624 if (u.u_error) 625 return; 626 uiov = msg.msg_iov; 627 msg.msg_iov = aiov; 628 if (msg.msg_accrights) 629 if (useracc((caddr_t)msg.msg_accrights, 630 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { 631 u.u_error = EFAULT; 632 return; 633 } 634 if (msg.msg_control) 635 if (useracc((caddr_t)msg.msg_control, 636 (unsigned)msg.msg_controllen, B_WRITE) == 0) { 637 u.u_error = EFAULT; 638 return; 639 } 640 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0); 641 msg.msg_iov = uiov; 642 u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 643 } 644 645 recvit(s, mp, namelenp, rightslenp, compat_43) 646 int s, compat_43; 647 register struct msghdr *mp; 648 caddr_t namelenp, rightslenp; 649 { 650 register struct file *fp; 651 struct uio auio; 652 register struct iovec *iov; 653 register int i; 654 int len; 655 struct mbuf *from = 0, *rights = 0, *control = 0; 656 657 fp = getsock(s); 658 if (fp == 0) 659 return; 660 auio.uio_iov = mp->msg_iov; 661 auio.uio_iovcnt = mp->msg_iovlen; 662 auio.uio_segflg = UIO_USERSPACE; 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 register struct file *rf, *wf; 841 struct socket *rso, *wso; 842 int 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 freeit; 850 rf = falloc(); 851 if (rf == NULL) 852 goto free2; 853 r = u.u_r.r_val1; 854 rf->f_flag = FREAD; 855 rf->f_type = DTYPE_SOCKET; 856 rf->f_ops = &socketops; 857 rf->f_data = (caddr_t)rso; 858 wf = falloc(); 859 if (wf == NULL) 860 goto free3; 861 wf->f_flag = FWRITE; 862 wf->f_type = DTYPE_SOCKET; 863 wf->f_ops = &socketops; 864 wf->f_data = (caddr_t)wso; 865 u.u_r.r_val2 = u.u_r.r_val1; 866 u.u_r.r_val1 = r; 867 if (u.u_error = unp_connect2(wso, rso)) 868 goto free4; 869 wso->so_state |= SS_CANTRCVMORE; 870 rso->so_state |= SS_CANTSENDMORE; 871 return; 872 free4: 873 wf->f_count = 0; 874 u.u_ofile[u.u_r.r_val2] = 0; 875 free3: 876 rf->f_count = 0; 877 u.u_ofile[r] = 0; 878 free2: 879 (void)soclose(wso); 880 freeit: 881 (void)soclose(rso); 882 } 883 884 /* 885 * Get socket name. 886 */ 887 #ifdef COMPAT_43 888 getsockname() 889 { 890 getsockname1(0); 891 } 892 893 ogetsockname() 894 { 895 getsockname1(1); 896 } 897 898 getsockname1(compat_43) 899 #else 900 getsockname() 901 #endif 902 { 903 register struct a { 904 int fdes; 905 caddr_t asa; 906 int *alen; 907 } *uap = (struct a *)u.u_ap; 908 register struct file *fp; 909 register struct socket *so; 910 struct mbuf *m; 911 int len; 912 913 fp = getsock(uap->fdes); 914 if (fp == 0) 915 return; 916 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 917 if (u.u_error) 918 return; 919 so = (struct socket *)fp->f_data; 920 m = m_getclr(M_WAIT, MT_SONAME); 921 if (m == NULL) { 922 u.u_error = ENOBUFS; 923 return; 924 } 925 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 926 if (u.u_error) 927 goto bad; 928 if (len > m->m_len) 929 len = m->m_len; 930 #ifdef COMPAT_43 931 if (compat_43) 932 mtod(m, struct osockaddr *)->sa_family = 933 mtod(m, struct sockaddr *)->sa_family; 934 #endif 935 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 936 if (u.u_error == 0) 937 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, 938 sizeof (len)); 939 bad: 940 m_freem(m); 941 } 942 943 /* 944 * Get name of peer for connected socket. 945 */ 946 #ifdef COMPAT_43 947 getpeername() 948 { 949 getpeername1(0); 950 } 951 952 ogetpeername() 953 { 954 getpeername1(1); 955 } 956 957 getpeername1(compat_43) 958 #else 959 getpeername() 960 #endif 961 { 962 register struct a { 963 int fdes; 964 caddr_t asa; 965 int *alen; 966 } *uap = (struct a *)u.u_ap; 967 register struct file *fp; 968 register struct socket *so; 969 struct mbuf *m; 970 int len; 971 972 fp = getsock(uap->fdes); 973 if (fp == 0) 974 return; 975 so = (struct socket *)fp->f_data; 976 if ((so->so_state & SS_ISCONNECTED) == 0) { 977 u.u_error = ENOTCONN; 978 return; 979 } 980 m = m_getclr(M_WAIT, MT_SONAME); 981 if (m == NULL) { 982 u.u_error = ENOBUFS; 983 return; 984 } 985 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 986 if (u.u_error) 987 return; 988 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); 989 if (u.u_error) 990 goto bad; 991 if (len > m->m_len) 992 len = m->m_len; 993 #ifdef COMPAT_43 994 if (compat_43) 995 mtod(m, struct osockaddr *)->sa_family = 996 mtod(m, struct sockaddr *)->sa_family; 997 #endif 998 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 999 if (u.u_error) 1000 goto bad; 1001 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 1002 bad: 1003 m_freem(m); 1004 } 1005 1006 sockargs(aname, name, namelen, type) 1007 struct mbuf **aname; 1008 caddr_t name; 1009 int namelen, type; 1010 { 1011 register struct mbuf *m; 1012 int error; 1013 1014 if ((u_int)namelen > MLEN) 1015 return (EINVAL); 1016 m = m_get(M_WAIT, type); 1017 if (m == NULL) 1018 return (ENOBUFS); 1019 m->m_len = namelen; 1020 error = copyin(name, mtod(m, caddr_t), (u_int)namelen); 1021 if (error) 1022 (void) m_free(m); 1023 else 1024 *aname = m; 1025 if (type == MT_SONAME) { 1026 register struct sockaddr *sa = mtod(m, struct sockaddr *); 1027 #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN 1028 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1029 sa->sa_family = sa->sa_len; 1030 #endif 1031 sa->sa_len = namelen; 1032 } 1033 return (error); 1034 } 1035 1036 struct file * 1037 getsock(fdes) 1038 int fdes; 1039 { 1040 register struct file *fp; 1041 1042 fp = getf(fdes); 1043 if (fp == NULL) 1044 return (0); 1045 if (fp->f_type != DTYPE_SOCKET) { 1046 u.u_error = ENOTSOCK; 1047 return (0); 1048 } 1049 return (fp); 1050 } 1051