1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * socket.c, Code implementing a simple socket interface. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/types.h> 32 #include "socket_impl.h" 33 #include <sys/isa_defs.h> 34 #include <sys/sysmacros.h> 35 #include <sys/bootconf.h> 36 #include <sys/socket.h> 37 #include <netinet/in.h> 38 #include <netinet/ip.h> 39 #include <netinet/tcp.h> 40 #include <sys/uio.h> 41 #include <sys/salib.h> 42 #include "socket_inet.h" 43 #include "ipv4.h" 44 #include "ipv4_impl.h" 45 #include "udp_inet.h" 46 #include "tcp_inet.h" 47 #include "mac.h" 48 #include "mac_impl.h" 49 #include <sys/promif.h> 50 51 struct inetboot_socket sockets[MAXSOCKET] = { 0 }; 52 53 /* Default send and receive socket buffer size */ 54 #define SO_DEF_SNDBUF 48*1024 55 #define SO_DEF_RCVBUF 48*1024 56 57 /* Default max socket buffer size */ 58 #define SO_MAX_BUF 4*1024*1024 59 60 static ssize_t dgram_sendto(int, const void *, size_t, int, 61 const struct sockaddr *, int); 62 static ssize_t stream_sendto(int, const void *, size_t, int); 63 static int bind_check(int, const struct sockaddr *); 64 static int quickbind(int); 65 66 /* Check the validity of a fd and return the socket index of that fd. */ 67 int 68 so_check_fd(int fd, int *errno) 69 { 70 int i; 71 72 i = FD_TO_SOCKET(fd); 73 if (i < 0 || i >= MAXSOCKET) { 74 *errno = ENOTSOCK; 75 return (-1); 76 } 77 if (sockets[i].type == INETBOOT_UNUSED) { 78 *errno = ENOTSOCK; 79 return (-1); 80 } 81 return (i); 82 } 83 84 /* 85 * Create an endpoint for network communication. Returns a descriptor. 86 * 87 * Notes: 88 * Only PF_INET communication domains are supported. Within 89 * this domain, only SOCK_RAW, SOCK_DGRAM and SOCK_STREAM types are 90 * supported. 91 */ 92 int 93 socket(int domain, int type, int protocol) 94 { 95 static int sock_initialized; 96 int i; 97 98 errno = 0; 99 100 if (!sock_initialized) { 101 for (i = 0; i < MAXSOCKET; i++) 102 sockets[i].type = INETBOOT_UNUSED; 103 sock_initialized = B_TRUE; 104 } 105 if (domain != AF_INET) { 106 errno = EPROTONOSUPPORT; 107 return (-1); 108 } 109 110 /* Find available socket */ 111 for (i = 0; i < MAXSOCKET; i++) { 112 if (sockets[i].type == INETBOOT_UNUSED) 113 break; 114 } 115 if (i >= MAXSOCKET) { 116 errno = EMFILE; /* No slots left. */ 117 return (-1); 118 } 119 120 /* Some socket initialization... */ 121 sockets[i].so_rcvbuf = SO_DEF_RCVBUF; 122 sockets[i].so_sndbuf = SO_DEF_SNDBUF; 123 124 /* 125 * Note that we ignore the protocol field for SOCK_DGRAM and 126 * SOCK_STREAM. When we support different protocols in future, 127 * this needs to be changed. 128 */ 129 switch (type) { 130 case SOCK_RAW: 131 ipv4_raw_socket(&sockets[i], (uint8_t)protocol); 132 break; 133 case SOCK_DGRAM: 134 udp_socket_init(&sockets[i]); 135 break; 136 case SOCK_STREAM: 137 tcp_socket_init(&sockets[i]); 138 break; 139 default: 140 errno = EPROTOTYPE; 141 break; 142 } 143 144 if (errno != 0) 145 return (-1); 146 147 /* IPv4 generic initialization. */ 148 ipv4_socket_init(&sockets[i]); 149 150 /* MAC generic initialization. */ 151 mac_socket_init(&sockets[i]); 152 153 return (i + SOCKETTYPE); 154 } 155 156 int 157 getsockname(int s, struct sockaddr *name, socklen_t *namelen) 158 { 159 int i; 160 161 errno = 0; 162 if ((i = so_check_fd(s, &errno)) == -1) 163 return (-1); 164 165 if (*namelen < sizeof (struct sockaddr_in)) { 166 errno = ENOMEM; 167 return (-1); 168 } 169 170 /* Structure assignment... */ 171 *((struct sockaddr_in *)name) = sockets[i].bind; 172 *namelen = sizeof (struct sockaddr_in); 173 return (0); 174 } 175 176 /* 177 * The socket options we support are: 178 * SO_RCVTIMEO - Value is in msecs, and is of uint32_t. 179 * SO_DONTROUTE - Value is an int, and is a boolean (nonzero if set). 180 * SO_REUSEADDR - Value is an int boolean. 181 * SO_RCVBUF - Value is an int. 182 * SO_SNDBUF - Value is an int. 183 */ 184 int 185 getsockopt(int s, int level, int option, void *optval, socklen_t *optlen) 186 { 187 int i; 188 189 errno = 0; 190 if ((i = so_check_fd(s, &errno)) == -1) 191 return (-1); 192 193 switch (level) { 194 case SOL_SOCKET: { 195 switch (option) { 196 case SO_RCVTIMEO: 197 if (*optlen == sizeof (uint32_t)) { 198 *(uint32_t *)optval = sockets[i].in_timeout; 199 } else { 200 *optlen = 0; 201 errno = EINVAL; 202 } 203 break; 204 case SO_DONTROUTE: 205 if (*optlen == sizeof (int)) { 206 *(int *)optval = 207 (sockets[i].out_flags & SO_DONTROUTE); 208 } else { 209 *optlen = 0; 210 errno = EINVAL; 211 } 212 break; 213 case SO_REUSEADDR: 214 if (*optlen == sizeof (int)) { 215 *(int *)optval = 216 (sockets[i].so_opt & SO_REUSEADDR); 217 } else { 218 *optlen = 0; 219 errno = EINVAL; 220 } 221 break; 222 case SO_RCVBUF: 223 if (*optlen == sizeof (int)) { 224 *(int *)optval = sockets[i].so_rcvbuf; 225 } else { 226 *optlen = 0; 227 errno = EINVAL; 228 } 229 break; 230 case SO_SNDBUF: 231 if (*optlen == sizeof (int)) { 232 *(int *)optval = sockets[i].so_sndbuf; 233 } else { 234 *optlen = 0; 235 errno = EINVAL; 236 } 237 break; 238 case SO_LINGER: 239 if (*optlen == sizeof (struct linger)) { 240 /* struct copy */ 241 *(struct linger *)optval = sockets[i].so_linger; 242 } else { 243 *optlen = 0; 244 errno = EINVAL; 245 } 246 default: 247 errno = ENOPROTOOPT; 248 break; 249 } 250 break; 251 } /* case SOL_SOCKET */ 252 case IPPROTO_TCP: 253 case IPPROTO_IP: { 254 switch (option) { 255 default: 256 *optlen = 0; 257 errno = ENOPROTOOPT; 258 break; 259 } 260 break; 261 } /* case IPPROTO_IP or IPPROTO_TCP */ 262 default: 263 errno = ENOPROTOOPT; 264 break; 265 } /* switch (level) */ 266 267 if (errno != 0) 268 return (-1); 269 else 270 return (0); 271 } 272 273 /* 274 * Generate a network-order source port from the privileged range if 275 * "reserved" is true, dynamic/private range otherwise. We consider the 276 * range of 512-1023 privileged ports as ports we can use. This mirrors 277 * historical rpc client practice for privileged port selection. 278 */ 279 in_port_t 280 get_source_port(boolean_t reserved) 281 { 282 static in_port_t dynamic = IPPORT_DYNAMIC_START - 1, 283 rsvdport = (IPPORT_RESERVED / 2) - 1; 284 in_port_t p; 285 286 if (reserved) { 287 if (++rsvdport >= IPPORT_RESERVED) 288 p = rsvdport = IPPORT_RESERVED / 2; 289 else 290 p = rsvdport; 291 } else 292 p = ++dynamic; 293 294 return (htons(p)); 295 } 296 297 /* 298 * The socket options we support are: 299 * SO_RECVTIMEO - Value is uint32_t msecs. 300 * SO_DONTROUTE - Value is int boolean (nonzero == TRUE, zero == FALSE). 301 * SO_REUSEADDR - value is int boolean. 302 * SO_RCVBUF - Value is int. 303 * SO_SNDBUF - Value is int. 304 */ 305 int 306 setsockopt(int s, int level, int option, const void *optval, socklen_t optlen) 307 { 308 int i; 309 310 errno = 0; 311 if ((i = so_check_fd(s, &errno)) == -1) 312 return (-1); 313 314 switch (level) { 315 case SOL_SOCKET: { 316 switch (option) { 317 case SO_RCVTIMEO: 318 if (optlen == sizeof (uint32_t)) 319 sockets[i].in_timeout = *(uint32_t *)optval; 320 else { 321 errno = EINVAL; 322 } 323 break; 324 case SO_DONTROUTE: 325 if (optlen == sizeof (int)) { 326 if (*(int *)optval) 327 sockets[i].out_flags |= SO_DONTROUTE; 328 else 329 sockets[i].out_flags &= ~SO_DONTROUTE; 330 } else { 331 errno = EINVAL; 332 } 333 break; 334 case SO_REUSEADDR: 335 if (optlen == sizeof (int)) { 336 if (*(int *)optval) 337 sockets[i].so_opt |= SO_REUSEADDR; 338 else 339 sockets[i].so_opt &= ~SO_REUSEADDR; 340 } else { 341 errno = EINVAL; 342 } 343 break; 344 case SO_RCVBUF: 345 if (optlen == sizeof (int)) { 346 sockets[i].so_rcvbuf = *(int *)optval; 347 if (sockets[i].so_rcvbuf > SO_MAX_BUF) 348 sockets[i].so_rcvbuf = SO_MAX_BUF; 349 (void) tcp_opt_set(sockets[i].pcb, 350 level, option, optval, optlen); 351 } else { 352 errno = EINVAL; 353 } 354 break; 355 case SO_SNDBUF: 356 if (optlen == sizeof (int)) { 357 sockets[i].so_sndbuf = *(int *)optval; 358 if (sockets[i].so_sndbuf > SO_MAX_BUF) 359 sockets[i].so_sndbuf = SO_MAX_BUF; 360 (void) tcp_opt_set(sockets[i].pcb, 361 level, option, optval, optlen); 362 } else { 363 errno = EINVAL; 364 } 365 break; 366 case SO_LINGER: 367 if (optlen == sizeof (struct linger)) { 368 /* struct copy */ 369 sockets[i].so_linger = *(struct linger *)optval; 370 (void) tcp_opt_set(sockets[i].pcb, 371 level, option, optval, optlen); 372 } else { 373 errno = EINVAL; 374 } 375 break; 376 default: 377 errno = ENOPROTOOPT; 378 break; 379 } 380 break; 381 } /* case SOL_SOCKET */ 382 case IPPROTO_TCP: 383 case IPPROTO_IP: { 384 switch (option) { 385 default: 386 errno = ENOPROTOOPT; 387 break; 388 } 389 break; 390 } /* case IPPROTO_IP or IPPROTO_TCP */ 391 default: 392 errno = ENOPROTOOPT; 393 break; 394 } /* switch (level) */ 395 396 if (errno != 0) 397 return (-1); 398 else 399 return (0); 400 } 401 402 /* 403 * Shut down part of a full-duplex connection. 404 * 405 * Only supported for TCP sockets 406 */ 407 int 408 shutdown(int s, int how) 409 { 410 int sock_id; 411 int i; 412 413 errno = 0; 414 if ((sock_id = so_check_fd(s, &errno)) == -1) 415 return (-1); 416 417 /* shutdown only supported for TCP sockets */ 418 if (sockets[sock_id].type != INETBOOT_STREAM) { 419 errno = EOPNOTSUPP; 420 return (-1); 421 } 422 423 if (!(sockets[sock_id].so_state & SS_ISCONNECTED)) { 424 errno = ENOTCONN; 425 return (-1); 426 } 427 428 switch (how) { 429 case 0: 430 sockets[sock_id].so_state |= SS_CANTRCVMORE; 431 break; 432 case 1: 433 sockets[sock_id].so_state |= SS_CANTSENDMORE; 434 break; 435 case 2: 436 sockets[sock_id].so_state |= (SS_CANTRCVMORE | SS_CANTSENDMORE); 437 break; 438 default: 439 errno = EINVAL; 440 return (-1); 441 } 442 443 switch (sockets[sock_id].so_state & 444 (SS_CANTRCVMORE | SS_CANTSENDMORE)) { 445 case (SS_CANTRCVMORE | SS_CANTSENDMORE): 446 /* Call lower level protocol close routine. */ 447 for (i = TRANSPORT_LVL; i >= MEDIA_LVL; i--) { 448 if (sockets[sock_id].close[i] != NULL) { 449 (void) sockets[sock_id].close[i](sock_id); 450 } 451 } 452 nuke_grams(&sockets[sock_id].inq); 453 break; 454 case SS_CANTRCVMORE: 455 nuke_grams(&sockets[sock_id].inq); 456 break; 457 case SS_CANTSENDMORE: 458 /* Call lower level protocol close routine. */ 459 if (tcp_shutdown(sock_id) < 0) 460 return (-1); 461 break; 462 default: 463 errno = EINVAL; 464 return (-1); 465 } 466 467 return (0); 468 } 469 470 /* 471 * "close" a socket. 472 */ 473 int 474 socket_close(int s) 475 { 476 int sock_id, i; 477 478 errno = 0; 479 if ((sock_id = so_check_fd(s, &errno)) == -1) 480 return (-1); 481 482 /* Call lower level protocol close routine. */ 483 for (i = TRANSPORT_LVL; i >= MEDIA_LVL; i--) { 484 if (sockets[sock_id].close[i] != NULL) { 485 /* 486 * Note that the close() routine of other 487 * layers can return an error. But right 488 * now, the only mechanism to report that 489 * back is for the close() routine to set 490 * the errno and socket_close() will return 491 * an error. But the close operation will 492 * not be stopped. 493 */ 494 (void) sockets[sock_id].close[i](sock_id); 495 } 496 } 497 498 /* 499 * Clear the input queue. This has to be done 500 * after the lower level protocol close routines have been 501 * called as they may want to do something about the queue. 502 */ 503 nuke_grams(&sockets[sock_id].inq); 504 505 bzero((caddr_t)&sockets[sock_id], sizeof (struct inetboot_socket)); 506 sockets[sock_id].type = INETBOOT_UNUSED; 507 508 return (0); 509 } 510 511 /* 512 * Read up to `nbyte' of data from socket `s' into `buf'; if non-zero, 513 * then give up after `read_timeout' seconds. Returns the number of 514 * bytes read, or -1 on failure. 515 */ 516 int 517 socket_read(int s, void *buf, size_t nbyte, int read_timeout) 518 { 519 ssize_t n; 520 uint_t start, diff; 521 struct sockaddr from; 522 uint_t fromlen = sizeof (from); 523 524 /* 525 * keep calling non-blocking recvfrom until something received 526 * or an error occurs 527 */ 528 start = prom_gettime(); 529 while ((n = recvfrom(s, buf, nbyte, 0, &from, &fromlen)) == 0) { 530 diff = (uint_t)((prom_gettime() - start) + 500) / 1000; 531 if (read_timeout != 0 && diff > read_timeout) { 532 errno = EINTR; 533 return (-1); 534 } 535 } 536 return (n); 537 } 538 539 /* 540 * Write up to `nbyte' bytes of data from `buf' to the address pointed to 541 * `addr' using socket `s'. Returns the number of bytes writte on success, 542 * or -1 on failure. 543 */ 544 int 545 socket_write(int s, const void *buf, size_t nbyte, struct sockaddr_in *addr) 546 { 547 return (sendto(s, buf, nbyte, 0, (struct sockaddr *)addr, 548 sizeof (*addr))); 549 } 550 551 static int 552 bind_check(int sock_id, const struct sockaddr *addr) 553 { 554 int k; 555 struct sockaddr_in *in_addr = (struct sockaddr_in *)addr; 556 557 /* Do not check for duplicate bind() if SO_REUSEADDR option is set. */ 558 if (! (sockets[sock_id].so_opt & SO_REUSEADDR)) { 559 for (k = 0; k < MAXSOCKET; k++) { 560 if (sockets[k].type != INETBOOT_UNUSED && 561 sockets[k].proto == sockets[sock_id].proto && 562 sockets[k].bound) { 563 if ((sockets[k].bind.sin_addr.s_addr == 564 in_addr->sin_addr.s_addr) && 565 (sockets[k].bind.sin_port == 566 in_addr->sin_port)) { 567 errno = EADDRINUSE; 568 return (-1); 569 } 570 } 571 } 572 } 573 return (0); 574 } 575 576 /* Assign a name to an unnamed socket. */ 577 int 578 bind(int s, const struct sockaddr *name, socklen_t namelen) 579 { 580 int i; 581 582 errno = 0; 583 584 if ((i = so_check_fd(s, &errno)) == -1) 585 return (-1); 586 587 if (name == NULL) { 588 /* unbind */ 589 if (sockets[i].bound) { 590 bzero((caddr_t)&sockets[i].bind, 591 sizeof (struct sockaddr_in)); 592 sockets[i].bound = B_FALSE; 593 } 594 return (0); 595 } 596 if (namelen != sizeof (struct sockaddr_in) || name == NULL) { 597 errno = EINVAL; 598 return (-1); 599 } 600 if (name->sa_family != AF_INET) { 601 errno = EAFNOSUPPORT; 602 return (-1); 603 } 604 if (sockets[i].bound) { 605 if (bcmp((caddr_t)&sockets[i].bind, (caddr_t)name, 606 namelen) == 0) { 607 /* attempt to bind to same address ok... */ 608 return (0); 609 } 610 errno = EINVAL; /* already bound */ 611 return (-1); 612 } 613 614 if (errno != 0) { 615 return (-1); 616 } 617 618 /* Check for duplicate bind(). */ 619 if (bind_check(i, name) < 0) 620 return (-1); 621 622 bcopy((caddr_t)name, (caddr_t)&sockets[i].bind, namelen); 623 if (sockets[i].type == INETBOOT_STREAM) { 624 if (tcp_bind(i) < 0) { 625 return (-1); 626 } 627 } 628 sockets[i].bound = B_TRUE; 629 630 return (0); 631 } 632 633 static int 634 quickbind(int sock_id) 635 { 636 int i; 637 struct sockaddr_in addr; 638 639 /* 640 * XXX This needs more work. Right now, if ipv4_setipaddr() 641 * have not been called, this will be wrong. But we need 642 * something better. Need to be revisited. 643 */ 644 ipv4_getipaddr(&addr.sin_addr); 645 addr.sin_family = AF_INET; 646 647 for (i = SMALLEST_ANON_PORT; i <= LARGEST_ANON_PORT; i++) { 648 addr.sin_port = htons(i); 649 if (bind_check(sock_id, (struct sockaddr *)&addr) == 0) 650 break; 651 } 652 /* Need to clear errno as it is probably set by bind_check(). */ 653 errno = 0; 654 655 if (i <= LARGEST_ANON_PORT) { 656 bcopy((caddr_t)&addr, (caddr_t)&sockets[sock_id].bind, 657 sizeof (struct sockaddr_in)); 658 sockets[sock_id].bound = B_TRUE; 659 #ifdef DEBUG 660 printf("quick bind done addr %s port %d\n", 661 inet_ntoa(sockets[sock_id].bind.sin_addr), 662 ntohs(sockets[sock_id].bind.sin_port)); 663 #endif 664 return (0); 665 } else { 666 return (-1); 667 } 668 } 669 670 int 671 listen(int fd, int backlog) 672 { 673 int sock_id; 674 675 errno = 0; 676 if ((sock_id = so_check_fd(fd, &errno)) == -1) 677 return (-1); 678 679 if (sockets[sock_id].type != INETBOOT_STREAM) { 680 errno = EOPNOTSUPP; 681 return (-1); 682 } 683 if (sockets[sock_id].so_error != 0) { 684 errno = sockets[sock_id].so_error; 685 return (-1); 686 } 687 return (tcp_listen(sock_id, backlog)); 688 } 689 690 int 691 accept(int fd, struct sockaddr *addr, socklen_t *addr_len) 692 { 693 int sock_id; 694 int new_sd; 695 696 errno = 0; 697 if ((sock_id = so_check_fd(fd, &errno)) == -1) 698 return (-1); 699 700 if (sockets[sock_id].type != INETBOOT_STREAM) { 701 errno = EOPNOTSUPP; 702 return (-1); 703 } 704 if (sockets[sock_id].so_error != 0) { 705 errno = sockets[sock_id].so_error; 706 return (-1); 707 } 708 if ((new_sd = tcp_accept(sock_id, addr, addr_len)) == -1) 709 return (-1); 710 sock_id = so_check_fd(new_sd, &errno); 711 sockets[sock_id].so_state |= SS_ISCONNECTED; 712 return (new_sd); 713 } 714 715 int 716 connect(int fd, const struct sockaddr *addr, socklen_t addr_len) 717 { 718 int sock_id; 719 int so_type; 720 721 errno = 0; 722 if ((sock_id = so_check_fd(fd, &errno)) == -1) 723 return (-1); 724 725 so_type = sockets[sock_id].type; 726 727 if (addr == NULL || addr_len == 0) { 728 errno = EINVAL; 729 return (-1); 730 } 731 /* Don't allow connect for raw socket. */ 732 if (so_type == INETBOOT_RAW) { 733 errno = EPROTONOSUPPORT; 734 return (-1); 735 } 736 737 if (sockets[sock_id].so_state & SS_ISCONNECTED) { 738 errno = EINVAL; 739 return (-1); 740 } 741 742 if (sockets[sock_id].so_error != 0) { 743 errno = sockets[sock_id].so_error; 744 return (-1); 745 } 746 747 /* If the socket is not bound, we need to do a quick bind. */ 748 if (!sockets[sock_id].bound) { 749 /* For TCP socket, just call tcp_bind(). */ 750 if (so_type == INETBOOT_STREAM) { 751 if (tcp_bind(sock_id) < 0) 752 return (-1); 753 } else { 754 if (quickbind(sock_id) < 0) { 755 errno = EADDRNOTAVAIL; 756 return (-1); 757 } 758 } 759 } 760 /* Should do some sanity check for addr .... */ 761 bcopy((caddr_t)addr, &sockets[sock_id].remote, 762 sizeof (struct sockaddr_in)); 763 764 if (sockets[sock_id].type == INETBOOT_STREAM) { 765 /* Call TCP connect routine. */ 766 if (tcp_connect(sock_id) == 0) 767 sockets[sock_id].so_state |= SS_ISCONNECTED; 768 else { 769 if (sockets[sock_id].so_error != 0) 770 errno = sockets[sock_id].so_error; 771 return (-1); 772 } 773 } else { 774 sockets[sock_id].so_state |= SS_ISCONNECTED; 775 } 776 return (0); 777 } 778 779 /* Just a wrapper around recvfrom(). */ 780 ssize_t 781 recv(int s, void *buf, size_t len, int flags) 782 { 783 return (recvfrom(s, buf, len, flags, NULL, NULL)); 784 } 785 786 /* 787 * Receive messages from a connectionless socket. Legal flags are 0 and 788 * MSG_DONTWAIT. MSG_WAITALL is not currently supported. 789 * 790 * Returns length of message for success, -1 if error occurred. 791 */ 792 ssize_t 793 recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, 794 socklen_t *fromlen) 795 { 796 int sock_id, i; 797 ssize_t datalen, bytes = 0; 798 struct inetgram *icp; 799 enum SockType so_type; 800 char *tmp_buf; 801 mblk_t *mp; 802 803 errno = 0; 804 805 if ((sock_id = so_check_fd(s, &errno)) == -1) { 806 errno = EINVAL; 807 return (-1); 808 } 809 810 if (sockets[sock_id].type == INETBOOT_STREAM && 811 !(sockets[sock_id].so_state & SS_ISCONNECTED)) { 812 errno = ENOTCONN; 813 return (-1); 814 } 815 816 if (buf == NULL || len == 0) { 817 errno = EINVAL; 818 return (-1); 819 } 820 /* Yup - MSG_WAITALL not implemented */ 821 if ((flags & ~MSG_DONTWAIT) != 0) { 822 errno = EINVAL; 823 return (-1); 824 } 825 826 retry: 827 if (sockets[sock_id].inq == NULL) { 828 /* Go out and check the wire */ 829 for (i = MEDIA_LVL; i < APP_LVL; i++) { 830 if (sockets[sock_id].input[i] != NULL) { 831 if (sockets[sock_id].input[i](sock_id) < 0) { 832 if (sockets[sock_id].so_error != 0) { 833 errno = 834 sockets[sock_id].so_error; 835 } 836 return (-1); 837 } 838 } 839 } 840 } 841 842 so_type = sockets[sock_id].type; 843 844 /* Remove unknown inetgrams from the head of inq. Can this happen? */ 845 while ((icp = sockets[sock_id].inq) != NULL) { 846 if ((so_type == INETBOOT_DGRAM || 847 so_type == INETBOOT_STREAM) && 848 icp->igm_level != APP_LVL) { 849 #ifdef DEBUG 850 printf("recvfrom: unexpected level %d frame found\n", 851 icp->igm_level); 852 #endif /* DEBUG */ 853 del_gram(&sockets[sock_id].inq, icp, B_TRUE); 854 continue; 855 } else { 856 break; 857 } 858 } 859 860 861 if (icp == NULL) { 862 /* 863 * Checking for error should be done everytime a lower layer 864 * input routing is called. For example, if TCP gets a RST, 865 * this should be reported asap. 866 */ 867 if (sockets[sock_id].so_state & SS_CANTRCVMORE) { 868 if (sockets[sock_id].so_error != 0) { 869 errno = sockets[sock_id].so_error; 870 return (-1); 871 } else { 872 return (0); 873 } 874 } 875 876 if ((flags & MSG_DONTWAIT) == 0) 877 goto retry; /* wait forever */ 878 879 /* no data */ 880 errno = EWOULDBLOCK; 881 return (-1); 882 } 883 884 if (from != NULL && fromlen != NULL) { 885 switch (so_type) { 886 case INETBOOT_STREAM: 887 /* Need to copy from the socket's remote address. */ 888 bcopy(&(sockets[sock_id].remote), from, MIN(*fromlen, 889 sizeof (struct sockaddr_in))); 890 break; 891 case INETBOOT_RAW: 892 case INETBOOT_DGRAM: 893 default: 894 if (*fromlen > sizeof (icp->igm_saddr)) 895 *fromlen = sizeof (icp->igm_saddr); 896 bcopy((caddr_t)&(icp->igm_saddr), (caddr_t)from, 897 MIN(*fromlen, sizeof (struct sockaddr_in))); 898 break; 899 } 900 } 901 902 mp = icp->igm_mp; 903 switch (so_type) { 904 case INETBOOT_STREAM: 905 /* 906 * If the message has igm_id == TCP_CALLB_MAGIC_ID, we need 907 * to drain the data held by tcp and try again. 908 */ 909 if (icp->igm_id == TCP_CALLB_MAGIC_ID) { 910 del_gram(&sockets[sock_id].inq, icp, B_TRUE); 911 tcp_rcv_drain_sock(sock_id); 912 goto retry; 913 } 914 915 /* TCP should put only user data in the inetgram. */ 916 tmp_buf = (char *)buf; 917 while (len > 0 && icp != NULL) { 918 datalen = mp->b_wptr - mp->b_rptr; 919 if (len < datalen) { 920 bcopy(mp->b_rptr, tmp_buf, len); 921 bytes += len; 922 mp->b_rptr += len; 923 break; 924 } else { 925 bcopy(mp->b_rptr, tmp_buf, datalen); 926 len -= datalen; 927 bytes += datalen; 928 tmp_buf += datalen; 929 del_gram(&sockets[sock_id].inq, icp, B_TRUE); 930 931 /* 932 * If we have any embedded magic messages just 933 * drop them. 934 */ 935 while ((icp = sockets[sock_id].inq) != NULL) { 936 if (icp->igm_id != TCP_CALLB_MAGIC_ID) 937 break; 938 del_gram(&sockets[sock_id].inq, icp, 939 B_TRUE); 940 } 941 942 if (icp == NULL) 943 break; 944 mp = icp->igm_mp; 945 } 946 } 947 sockets[sock_id].so_rcvbuf += (int32_t)bytes; 948 break; 949 case INETBOOT_DGRAM: 950 datalen = mp->b_wptr - mp->b_rptr; 951 if (len < datalen) 952 bytes = len; 953 else 954 bytes = datalen; 955 bcopy(mp->b_rptr, buf, bytes); 956 del_gram(&sockets[sock_id].inq, icp, B_TRUE); 957 break; 958 case INETBOOT_RAW: 959 default: 960 datalen = mp->b_wptr - mp->b_rptr; 961 if (len < datalen) 962 bytes = len; 963 else 964 bytes = datalen; 965 bcopy(mp->b_rptr, buf, bytes); 966 del_gram(&sockets[sock_id].inq, icp, B_TRUE); 967 break; 968 } 969 970 #ifdef DEBUG 971 printf("recvfrom(%d): data: (0x%x,%d)\n", sock_id, 972 (icp != NULL) ? icp->igm_mp : 0, bytes); 973 #endif /* DEBUG */ 974 return (bytes); 975 } 976 977 978 /* Just a wrapper around sendto(). */ 979 ssize_t 980 send(int s, const void *msg, size_t len, int flags) 981 { 982 return (sendto(s, msg, len, flags, NULL, 0)); 983 } 984 985 /* 986 * Transmit a message through a socket. 987 * 988 * Supported flags: MSG_DONTROUTE or 0. 989 */ 990 ssize_t 991 sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, 992 socklen_t tolen) 993 { 994 enum SockType so_type; 995 int sock_id; 996 ssize_t bytes; 997 998 errno = 0; 999 1000 if ((sock_id = so_check_fd(s, &errno)) == -1) { 1001 return (-1); 1002 } 1003 if (msg == NULL) { 1004 errno = EINVAL; 1005 return (-1); 1006 } 1007 so_type = sockets[sock_id].type; 1008 if ((flags & ~MSG_DONTROUTE) != 0) { 1009 errno = EINVAL; 1010 return (-1); 1011 } 1012 if (sockets[sock_id].so_error != 0) { 1013 errno = sockets[sock_id].so_error; 1014 return (-1); 1015 } 1016 if (to != NULL && to->sa_family != AF_INET) { 1017 errno = EAFNOSUPPORT; 1018 return (-1); 1019 } 1020 1021 switch (so_type) { 1022 case INETBOOT_RAW: 1023 case INETBOOT_DGRAM: 1024 if (!(sockets[sock_id].so_state & SS_ISCONNECTED) && 1025 (to == NULL || tolen != sizeof (struct sockaddr_in))) { 1026 errno = EINVAL; 1027 return (-1); 1028 } 1029 bytes = dgram_sendto(sock_id, msg, len, flags, to, tolen); 1030 break; 1031 case INETBOOT_STREAM: 1032 if (!((sockets[sock_id].so_state & SS_ISCONNECTED) || 1033 (sockets[sock_id].so_state & SS_ISCONNECTING))) { 1034 errno = EINVAL; 1035 return (-1); 1036 } 1037 if (sockets[sock_id].so_state & SS_CANTSENDMORE) { 1038 errno = EPIPE; 1039 return (-1); 1040 } 1041 bytes = stream_sendto(sock_id, msg, len, flags); 1042 break; 1043 default: 1044 /* Should not happen... */ 1045 errno = EPROTOTYPE; 1046 return (-1); 1047 } 1048 return (bytes); 1049 } 1050 1051 static ssize_t 1052 dgram_sendto(int i, const void *msg, size_t len, int flags, 1053 const struct sockaddr *to, int tolen) 1054 { 1055 struct inetgram oc; 1056 int l, offset; 1057 size_t tlen; 1058 mblk_t *mp; 1059 1060 #ifdef DEBUG 1061 { 1062 struct sockaddr_in *sin = (struct sockaddr_in *)to; 1063 printf("sendto(%d): msg of length: %d sent to port %d and host: %s\n", 1064 i, len, ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)); 1065 } 1066 #endif /* DEBUG */ 1067 1068 nuke_grams(&sockets[i].inq); /* flush the input queue */ 1069 1070 /* calculate offset for data */ 1071 offset = sockets[i].headerlen[MEDIA_LVL](NULL) + 1072 (sockets[i].headerlen[NETWORK_LVL])(NULL); 1073 1074 bzero((caddr_t)&oc, sizeof (oc)); 1075 if (sockets[i].type != INETBOOT_RAW) { 1076 offset += (sockets[i].headerlen[TRANSPORT_LVL])(NULL); 1077 oc.igm_level = TRANSPORT_LVL; 1078 } else 1079 oc.igm_level = NETWORK_LVL; 1080 oc.igm_oflags = flags; 1081 1082 if (to != NULL) { 1083 bcopy((caddr_t)to, (caddr_t)&oc.igm_saddr, tolen); 1084 } else { 1085 bcopy((caddr_t)&sockets[i].remote, (caddr_t)&oc.igm_saddr, 1086 sizeof (struct sockaddr_in)); 1087 } 1088 1089 /* Get a legal source port if the socket isn't bound. */ 1090 if (sockets[i].bound == B_FALSE && 1091 ntohs(oc.igm_saddr.sin_port == 0)) { 1092 ((struct sockaddr_in *)&oc.igm_saddr)->sin_port = 1093 get_source_port(B_FALSE); 1094 } 1095 1096 /* Round up to 16bit value for checksum purposes */ 1097 if (sockets[i].type == INETBOOT_DGRAM) { 1098 tlen = ((len + sizeof (uint16_t) - 1) & 1099 ~(sizeof (uint16_t) - 1)); 1100 } else 1101 tlen = len; 1102 1103 if ((oc.igm_mp = allocb(tlen + offset, 0)) == NULL) { 1104 errno = ENOMEM; 1105 return (-1); 1106 } 1107 mp = oc.igm_mp; 1108 mp->b_rptr = mp->b_wptr += offset; 1109 bcopy((caddr_t)msg, mp->b_wptr, len); 1110 mp->b_wptr += len; 1111 for (l = TRANSPORT_LVL; l >= MEDIA_LVL; l--) { 1112 if (sockets[i].output[l] != NULL) { 1113 if (sockets[i].output[l](i, &oc) < 0) { 1114 freeb(mp); 1115 if (errno == 0) 1116 errno = EIO; 1117 return (-1); 1118 } 1119 } 1120 } 1121 freeb(mp); 1122 return (len); 1123 } 1124 1125 /* ARGSUSED */ 1126 static ssize_t 1127 stream_sendto(int i, const void *msg, size_t len, int flags) 1128 { 1129 int cnt; 1130 1131 assert(sockets[i].pcb != NULL); 1132 1133 /* 1134 * Call directly TCP's send routine. We do this because TCP 1135 * needs to decide whether to send out the data. 1136 * 1137 * Note also that currently, TCP ignores all flags passed in for 1138 * TCP socket. 1139 */ 1140 if ((cnt = tcp_send(i, sockets[i].pcb, msg, len)) < 0) { 1141 if (sockets[i].so_error != 0) 1142 errno = sockets[i].so_error; 1143 return (-1); 1144 } else { 1145 return (cnt); 1146 } 1147 } 1148 1149 /* 1150 * Returns ptr to the last inetgram in the list, or null if list is null 1151 */ 1152 struct inetgram * 1153 last_gram(struct inetgram *igp) 1154 { 1155 struct inetgram *wp; 1156 for (wp = igp; wp != NULL; wp = wp->igm_next) { 1157 if (wp->igm_next == NULL) 1158 return (wp); 1159 } 1160 return (NULL); 1161 } 1162 1163 /* 1164 * Adds an inetgram or list of inetgrams to the end of the list. 1165 */ 1166 void 1167 add_grams(struct inetgram **igpp, struct inetgram *newgp) 1168 { 1169 struct inetgram *wp; 1170 1171 if (newgp == NULL) 1172 return; 1173 1174 if (*igpp == NULL) 1175 *igpp = newgp; 1176 else { 1177 wp = last_gram(*igpp); 1178 wp->igm_next = newgp; 1179 } 1180 } 1181 1182 /* 1183 * Nuke a whole list of grams. 1184 */ 1185 void 1186 nuke_grams(struct inetgram **lgpp) 1187 { 1188 while (*lgpp != NULL) 1189 del_gram(lgpp, *lgpp, B_TRUE); 1190 } 1191 1192 /* 1193 * Remove the referenced inetgram. List is altered accordingly. Destroy the 1194 * referenced inetgram if freeit is B_TRUE. 1195 */ 1196 void 1197 del_gram(struct inetgram **lgpp, struct inetgram *igp, int freeit) 1198 { 1199 struct inetgram *wp, *pp = NULL; 1200 1201 if (lgpp == NULL || igp == NULL) 1202 return; 1203 1204 wp = *lgpp; 1205 while (wp != NULL) { 1206 if (wp == igp) { 1207 /* detach wp from the list */ 1208 if (*lgpp == wp) 1209 *lgpp = (*lgpp)->igm_next; 1210 else 1211 pp->igm_next = wp->igm_next; 1212 igp->igm_next = NULL; 1213 1214 if (freeit) { 1215 if (igp->igm_mp != NULL) 1216 freeb(igp->igm_mp); 1217 bkmem_free((caddr_t)igp, 1218 sizeof (struct inetgram)); 1219 } 1220 break; 1221 } 1222 pp = wp; 1223 wp = wp->igm_next; 1224 } 1225 } 1226 1227 struct nct_t nct[] = { 1228 "bootp", NCT_BOOTP_DHCP, 1229 "dhcp", NCT_BOOTP_DHCP, 1230 "rarp", NCT_RARP_BOOTPARAMS, 1231 "manual", NCT_MANUAL 1232 }; 1233 int nct_entries = sizeof (nct) / sizeof (nct[0]); 1234 1235 /* 1236 * Figure out from the bootpath what kind of network configuration strategy 1237 * we should use. Returns the network config strategy. 1238 */ 1239 int 1240 get_netconfig_strategy(void) 1241 { 1242 int i; 1243 #if !defined(__i386) 1244 /* sparc */ 1245 #define ISSPACE(c) (c == ' ' || c == '\t' || c == '\n' || c == '\0') 1246 char lbootpath[OBP_MAXPATHLEN]; 1247 char net_options[NCT_BUFSIZE]; 1248 char *op, *nop, *sp; 1249 dnode_t cn; 1250 int proplen; 1251 1252 /* If the PROM DHCP cache exists, we're done */ 1253 if (prom_cached_reply(B_TRUE)) 1254 return (NCT_BOOTP_DHCP); 1255 1256 /* 1257 * Newer (version 4) PROMs will put the name in the 1258 * "net-config-strategy" property. 1259 */ 1260 cn = prom_finddevice("/chosen"); 1261 if ((proplen = prom_getproplen(cn, "net-config-strategy")) < 1262 sizeof (net_options)) { 1263 (void) prom_getprop(cn, "net-config-strategy", net_options); 1264 net_options[proplen] = '\0'; 1265 } else { 1266 1267 /* 1268 * We're reduced to sacanning bootpath for the prototol to use. 1269 * Since there was no "net-config-strategy" property, this is 1270 * an old PROM, so we need to excise any extraneous key/value 1271 * initializations from bootpath[]. 1272 */ 1273 for (op = prom_bootpath(), sp = lbootpath; op != NULL && 1274 !ISSPACE(*op); sp++, op++) 1275 *sp = *op; 1276 *sp = '\0'; 1277 /* find the last '/' (in the device path) */ 1278 if ((op = strrchr(lbootpath, '/')) == NULL) /* last '/' */ 1279 op = lbootpath; 1280 else 1281 op++; 1282 /* then look for the ':' separating it from the protocol */ 1283 while (*op != ':' && *op != '\0') 1284 op++; 1285 1286 if (*op == ':') { 1287 for (nop = net_options, op++; 1288 *op != '\0' && *op != '/' && !ISSPACE(*op) && 1289 nop < &net_options[NCT_BUFSIZE]; nop++, op++) 1290 *nop = *op; 1291 *nop = '\0'; 1292 } else 1293 net_options[0] = '\0'; 1294 } 1295 1296 #undef ISSPACE 1297 #else 1298 /* i86 */ 1299 extern struct bootops bootops; 1300 extern int bgetprop(struct bootops *, char *, caddr_t, int, phandle_t); 1301 char net_options[MAXNAMELEN]; 1302 1303 /* 1304 * Look at net-config-strategy boot property to determine what protocol 1305 * will be used. 1306 */ 1307 (void) bgetprop(&bootops, "net-config-strategy", net_options, 1308 sizeof (net_options), 0); 1309 1310 #endif /* __i386 */ 1311 1312 for (i = 0; i < nct_entries; i++) 1313 if (strcmp(net_options, nct[i].p_name) == 0) 1314 return (nct[i].p_id); 1315 1316 return (NCT_DEFAULT); 1317 } 1318 1319 /* Modified STREAM routines for ease of porting core TCP code. */ 1320 1321 /*ARGSUSED*/ 1322 mblk_t * 1323 allocb(size_t size, uint_t pri) 1324 { 1325 unsigned char *base; 1326 mblk_t *mp; 1327 1328 if ((mp = (mblk_t *)bkmem_zalloc(sizeof (mblk_t))) == NULL) 1329 return (NULL); 1330 if ((base = (unsigned char *)bkmem_zalloc(size)) == NULL) 1331 return (NULL); 1332 1333 mp->b_next = mp->b_prev = mp->b_cont = NULL; 1334 mp->b_rptr = mp->b_wptr = mp->b_datap = (unsigned char *)base; 1335 mp->b_size = size; 1336 1337 return (mp); 1338 } 1339 1340 void 1341 freeb(mblk_t *mp) 1342 { 1343 #ifdef DEBUG 1344 printf("freeb datap %x\n", mp->b_datap); 1345 #endif 1346 bkmem_free((caddr_t)(mp->b_datap), mp->b_size); 1347 #ifdef DEBUG 1348 printf("freeb mp %x\n", mp); 1349 #endif 1350 bkmem_free((caddr_t)mp, sizeof (mblk_t)); 1351 } 1352 1353 void 1354 freemsg(mblk_t *mp) 1355 { 1356 while (mp) { 1357 mblk_t *mp_cont = mp->b_cont; 1358 1359 freeb(mp); 1360 mp = mp_cont; 1361 } 1362 } 1363 1364 mblk_t * 1365 copyb(mblk_t *bp) 1366 { 1367 mblk_t *nbp; 1368 unsigned char *ndp; 1369 1370 assert((uintptr_t)(bp->b_wptr - bp->b_rptr) >= 0); 1371 1372 if (!(nbp = allocb(bp->b_size, 0))) 1373 return (NULL); 1374 nbp->b_cont = NULL; 1375 ndp = nbp->b_datap; 1376 1377 nbp->b_rptr = ndp + (bp->b_rptr - bp->b_datap); 1378 nbp->b_wptr = nbp->b_rptr + (bp->b_wptr - bp->b_rptr); 1379 bcopy(bp->b_datap, nbp->b_datap, bp->b_size); 1380 return (nbp); 1381 } 1382 1383 /* To simplify things, dupb() is implemented as copyb(). */ 1384 mblk_t * 1385 dupb(mblk_t *mp) 1386 { 1387 return (copyb(mp)); 1388 } 1389 1390 /* 1391 * get number of data bytes in message 1392 */ 1393 size_t 1394 msgdsize(mblk_t *bp) 1395 { 1396 size_t count = 0; 1397 1398 for (; bp != NULL; bp = bp->b_cont) { 1399 assert(bp->b_wptr >= bp->b_rptr); 1400 count += bp->b_wptr - bp->b_rptr; 1401 } 1402 return (count); 1403 } 1404