369} 370 371void 372bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 373{ 374 375 printf("%s flags %x, addr ", 376 ifp->if_xname, ifp->if_flags); 377 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 378 printf(", broadcast "); 379 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 380 printf(", netmask "); 381 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 382 printf("\n"); 383} 384 385void 386bootpboot_p_iflist(void) 387{ 388 INIT_VNET_NET(curvnet); 389 struct ifnet *ifp; 390 struct ifaddr *ifa; 391 392 printf("Interface list:\n"); 393 IFNET_RLOCK(); /* could sleep, but okay for debugging XXX */ 394 for (ifp = TAILQ_FIRST(&V_ifnet); 395 ifp != NULL; 396 ifp = TAILQ_NEXT(ifp, if_link)) { 397 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 398 ifa != NULL; 399 ifa = TAILQ_NEXT(ifa, ifa_link)) 400 if (ifa->ifa_addr->sa_family == AF_INET) 401 bootpboot_p_if(ifp, ifa); 402 } 403 IFNET_RUNLOCK(); 404} 405#endif /* defined(BOOTP_DEBUG) */ 406 407static void 408clear_sinaddr(struct sockaddr_in *sin) 409{ 410 411 bzero(sin, sizeof(*sin)); 412 sin->sin_len = sizeof(*sin); 413 sin->sin_family = AF_INET; 414 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 415 sin->sin_port = 0; 416} 417 418static void 419allocifctx(struct bootpc_globalcontext *gctx) 420{ 421 struct bootpc_ifcontext *ifctx; 422 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), 423 M_TEMP, M_WAITOK | M_ZERO); 424 if (ifctx == NULL) 425 panic("Failed to allocate bootp interface context structure"); 426 427 ifctx->xid = gctx->xid; 428#ifdef BOOTP_NO_DHCP 429 ifctx->state = IF_BOOTP_UNRESOLVED; 430#else 431 ifctx->state = IF_DHCP_UNRESOLVED; 432#endif 433 gctx->xid += 0x100; 434 if (gctx->interfaces != NULL) 435 gctx->lastinterface->next = ifctx; 436 else 437 gctx->interfaces = ifctx; 438 gctx->lastinterface = ifctx; 439} 440 441static __inline int 442bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 443{ 444 445 if (ifctx->state == IF_BOOTP_RESOLVED || 446 ifctx->state == IF_DHCP_RESOLVED) 447 return 1; 448 return 0; 449} 450 451static __inline int 452bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 453{ 454 455 if (ifctx->state == IF_BOOTP_UNRESOLVED || 456 ifctx->state == IF_DHCP_UNRESOLVED) 457 return 1; 458 return 0; 459} 460 461static __inline int 462bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 463{ 464 465 if (ifctx->state == IF_BOOTP_FAILED || 466 ifctx->state == IF_DHCP_FAILED) 467 return 1; 468 return 0; 469} 470 471static int 472bootpc_received(struct bootpc_globalcontext *gctx, 473 struct bootpc_ifcontext *ifctx) 474{ 475 unsigned char dhcpreplytype; 476 char *p; 477 478 /* 479 * Need timeout for fallback to less 480 * desirable alternative. 481 */ 482 483 /* This call used for the side effect (badopt flag) */ 484 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 485 gctx->replylen, 486 TAG_END); 487 488 /* If packet is invalid, ignore it */ 489 if (gctx->tmptag.badopt != 0) 490 return 0; 491 492 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 493 gctx->replylen, TAG_DHCP_MSGTYPE); 494 if (p != NULL) 495 dhcpreplytype = *p; 496 else 497 dhcpreplytype = DHCP_NOMSG; 498 499 switch (ifctx->dhcpquerytype) { 500 case DHCP_DISCOVER: 501 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 502#ifndef BOOTP_FORCE_DHCP 503 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 504#endif 505 ) 506 return 0; 507 break; 508 case DHCP_REQUEST: 509 if (dhcpreplytype != DHCP_ACK) 510 return 0; 511 case DHCP_NOMSG: 512 break; 513 } 514 515 /* Ignore packet unless it gives us a root tag we didn't have */ 516 517 if ((ifctx->state == IF_BOOTP_RESOLVED || 518 (ifctx->dhcpquerytype == DHCP_DISCOVER && 519 (ifctx->state == IF_DHCP_OFFERED || 520 ifctx->state == IF_DHCP_RESOLVED))) && 521 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 522 ifctx->replylen, 523 TAG_ROOT) != NULL || 524 bootpc_tag(&gctx->tmptag, &gctx->reply, 525 gctx->replylen, 526 TAG_ROOT) == NULL)) 527 return 0; 528 529 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); 530 ifctx->replylen = gctx->replylen; 531 532 /* XXX: Only reset if 'perfect' response */ 533 if (ifctx->state == IF_BOOTP_UNRESOLVED) 534 ifctx->state = IF_BOOTP_RESOLVED; 535 else if (ifctx->state == IF_DHCP_UNRESOLVED && 536 ifctx->dhcpquerytype == DHCP_DISCOVER) { 537 if (dhcpreplytype == DHCP_OFFER) 538 ifctx->state = IF_DHCP_OFFERED; 539 else 540 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 541 } else if (ifctx->state == IF_DHCP_OFFERED && 542 ifctx->dhcpquerytype == DHCP_REQUEST) 543 ifctx->state = IF_DHCP_RESOLVED; 544 545 546 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 547 ifctx->state != IF_BOOTP_RESOLVED) { 548 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 549 ifctx->replylen, TAG_DHCP_SERVERID); 550 if (p != NULL && gctx->tmptag.taglen == 4) { 551 memcpy(&ifctx->dhcpserver, p, 4); 552 ifctx->gotdhcpserver = 1; 553 } else 554 ifctx->gotdhcpserver = 0; 555 return 1; 556 } 557 558 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 559 ifctx->replylen, 560 TAG_ROOT) != NULL); 561 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 562 ifctx->replylen, 563 TAG_ROUTERS) != NULL); 564 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 565 ifctx->replylen, 566 TAG_SUBNETMASK) != NULL); 567 return 1; 568} 569 570static int 571bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) 572{ 573 struct socket *so; 574 struct sockaddr_in *sin, dst; 575 struct uio auio; 576 struct sockopt sopt; 577 struct iovec aio; 578 int error, on, rcvflg, timo, len; 579 time_t atimo; 580 time_t rtimo; 581 struct timeval tv; 582 struct bootpc_ifcontext *ifctx; 583 int outstanding; 584 int gotrootpath; 585 int retry; 586 const char *s; 587 588 /* 589 * Create socket and set its recieve timeout. 590 */ 591 error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td); 592 if (error != 0) 593 goto out0; 594 595 tv.tv_sec = 1; 596 tv.tv_usec = 0; 597 bzero(&sopt, sizeof(sopt)); 598 sopt.sopt_dir = SOPT_SET; 599 sopt.sopt_level = SOL_SOCKET; 600 sopt.sopt_name = SO_RCVTIMEO; 601 sopt.sopt_val = &tv; 602 sopt.sopt_valsize = sizeof tv; 603 604 error = sosetopt(so, &sopt); 605 if (error != 0) 606 goto out; 607 608 /* 609 * Enable broadcast. 610 */ 611 on = 1; 612 sopt.sopt_name = SO_BROADCAST; 613 sopt.sopt_val = &on; 614 sopt.sopt_valsize = sizeof on; 615 616 error = sosetopt(so, &sopt); 617 if (error != 0) 618 goto out; 619 620 /* 621 * Disable routing. 622 */ 623 624 on = 1; 625 sopt.sopt_name = SO_DONTROUTE; 626 sopt.sopt_val = &on; 627 sopt.sopt_valsize = sizeof on; 628 629 error = sosetopt(so, &sopt); 630 if (error != 0) 631 goto out; 632 633 /* 634 * Bind the local endpoint to a bootp client port. 635 */ 636 sin = &dst; 637 clear_sinaddr(sin); 638 sin->sin_port = htons(IPPORT_BOOTPC); 639 error = sobind(so, (struct sockaddr *)sin, td); 640 if (error != 0) { 641 printf("bind failed\n"); 642 goto out; 643 } 644 645 /* 646 * Setup socket address for the server. 647 */ 648 sin = &dst; 649 clear_sinaddr(sin); 650 sin->sin_addr.s_addr = INADDR_BROADCAST; 651 sin->sin_port = htons(IPPORT_BOOTPS); 652 653 /* 654 * Send it, repeatedly, until a reply is received, 655 * but delay each re-send by an increasing amount. 656 * If the delay hits the maximum, start complaining. 657 */ 658 timo = 0; 659 rtimo = 0; 660 for (;;) { 661 662 outstanding = 0; 663 gotrootpath = 0; 664 665 for (ifctx = gctx->interfaces; 666 ifctx != NULL; 667 ifctx = ifctx->next) { 668 if (bootpc_ifctx_isresolved(ifctx) != 0 && 669 bootpc_tag(&gctx->tmptag, &ifctx->reply, 670 ifctx->replylen, 671 TAG_ROOT) != NULL) 672 gotrootpath = 1; 673 } 674 675 for (ifctx = gctx->interfaces; 676 ifctx != NULL; 677 ifctx = ifctx->next) { 678 ifctx->outstanding = 0; 679 if (bootpc_ifctx_isresolved(ifctx) != 0 && 680 gotrootpath != 0) { 681 continue; 682 } 683 if (bootpc_ifctx_isfailed(ifctx) != 0) 684 continue; 685 686 outstanding++; 687 ifctx->outstanding = 1; 688 689 /* Proceed to next step in DHCP negotiation */ 690 if ((ifctx->state == IF_DHCP_OFFERED && 691 ifctx->dhcpquerytype != DHCP_REQUEST) || 692 (ifctx->state == IF_DHCP_UNRESOLVED && 693 ifctx->dhcpquerytype != DHCP_DISCOVER) || 694 (ifctx->state == IF_BOOTP_UNRESOLVED && 695 ifctx->dhcpquerytype != DHCP_NOMSG)) { 696 ifctx->sentmsg = 0; 697 bootpc_compose_query(ifctx, gctx, td); 698 } 699 700 /* Send BOOTP request (or re-send). */ 701 702 if (ifctx->sentmsg == 0) { 703 switch(ifctx->dhcpquerytype) { 704 case DHCP_DISCOVER: 705 s = "DHCP Discover"; 706 break; 707 case DHCP_REQUEST: 708 s = "DHCP Request"; 709 break; 710 case DHCP_NOMSG: 711 default: 712 s = "BOOTP Query"; 713 break; 714 } 715 printf("Sending %s packet from " 716 "interface %s (%*D)\n", 717 s, 718 ifctx->ireq.ifr_name, 719 ifctx->sdl->sdl_alen, 720 (unsigned char *) LLADDR(ifctx->sdl), 721 ":"); 722 ifctx->sentmsg = 1; 723 } 724 725 aio.iov_base = (caddr_t) &ifctx->call; 726 aio.iov_len = sizeof(ifctx->call); 727 728 auio.uio_iov = &aio; 729 auio.uio_iovcnt = 1; 730 auio.uio_segflg = UIO_SYSSPACE; 731 auio.uio_rw = UIO_WRITE; 732 auio.uio_offset = 0; 733 auio.uio_resid = sizeof(ifctx->call); 734 auio.uio_td = td; 735 736 /* Set netmask to 0.0.0.0 */ 737 738 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 739 clear_sinaddr(sin); 740 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 741 (caddr_t) &ifctx->ireq, td); 742 if (error != 0) 743 panic("bootpc_call:" 744 "set if netmask, error=%d", 745 error); 746 747 error = sosend(so, (struct sockaddr *) &dst, 748 &auio, NULL, NULL, 0, td); 749 if (error != 0) { 750 printf("bootpc_call: sosend: %d state %08x\n", 751 error, (int) so->so_state); 752 } 753 754 /* XXX: Is this needed ? */ 755 pause("bootpw", hz/10); 756 757 /* Set netmask to 255.0.0.0 */ 758 759 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 760 clear_sinaddr(sin); 761 sin->sin_addr.s_addr = htonl(0xff000000u); 762 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 763 (caddr_t) &ifctx->ireq, td); 764 if (error != 0) 765 panic("bootpc_call:" 766 "set if netmask, error=%d", 767 error); 768 769 } 770 771 if (outstanding == 0 && 772 (rtimo == 0 || time_second >= rtimo)) { 773 error = 0; 774 goto gotreply; 775 } 776 777 /* Determine new timeout. */ 778 if (timo < MAX_RESEND_DELAY) 779 timo++; 780 else { 781 printf("DHCP/BOOTP timeout for server "); 782 print_sin_addr(&dst); 783 printf("\n"); 784 } 785 786 /* 787 * Wait for up to timo seconds for a reply. 788 * The socket receive timeout was set to 1 second. 789 */ 790 atimo = timo + time_second; 791 while (time_second < atimo) { 792 aio.iov_base = (caddr_t) &gctx->reply; 793 aio.iov_len = sizeof(gctx->reply); 794 795 auio.uio_iov = &aio; 796 auio.uio_iovcnt = 1; 797 auio.uio_segflg = UIO_SYSSPACE; 798 auio.uio_rw = UIO_READ; 799 auio.uio_offset = 0; 800 auio.uio_resid = sizeof(gctx->reply); 801 auio.uio_td = td; 802 803 rcvflg = 0; 804 error = soreceive(so, NULL, &auio, 805 NULL, NULL, &rcvflg); 806 gctx->secs = time_second - gctx->starttime; 807 for (ifctx = gctx->interfaces; 808 ifctx != NULL; 809 ifctx = ifctx->next) { 810 if (bootpc_ifctx_isresolved(ifctx) != 0 || 811 bootpc_ifctx_isfailed(ifctx) != 0) 812 continue; 813 814 ifctx->call.secs = htons(gctx->secs); 815 } 816 if (error == EWOULDBLOCK) 817 continue; 818 if (error != 0) 819 goto out; 820 len = sizeof(gctx->reply) - auio.uio_resid; 821 822 /* Do we have the required number of bytes ? */ 823 if (len < BOOTP_MIN_LEN) 824 continue; 825 gctx->replylen = len; 826 827 /* Is it a reply? */ 828 if (gctx->reply.op != BOOTP_REPLY) 829 continue; 830 831 /* Is this an answer to our query */ 832 for (ifctx = gctx->interfaces; 833 ifctx != NULL; 834 ifctx = ifctx->next) { 835 if (gctx->reply.xid != ifctx->call.xid) 836 continue; 837 838 /* Same HW address size ? */ 839 if (gctx->reply.hlen != ifctx->call.hlen) 840 continue; 841 842 /* Correct HW address ? */ 843 if (bcmp(gctx->reply.chaddr, 844 ifctx->call.chaddr, 845 ifctx->call.hlen) != 0) 846 continue; 847 848 break; 849 } 850 851 if (ifctx != NULL) { 852 s = bootpc_tag(&gctx->tmptag, 853 &gctx->reply, 854 gctx->replylen, 855 TAG_DHCP_MSGTYPE); 856 if (s != NULL) { 857 switch (*s) { 858 case DHCP_OFFER: 859 s = "DHCP Offer"; 860 break; 861 case DHCP_ACK: 862 s = "DHCP Ack"; 863 break; 864 default: 865 s = "DHCP (unexpected)"; 866 break; 867 } 868 } else 869 s = "BOOTP Reply"; 870 871 printf("Received %s packet" 872 " on %s from ", 873 s, 874 ifctx->ireq.ifr_name); 875 print_in_addr(gctx->reply.siaddr); 876 if (gctx->reply.giaddr.s_addr != 877 htonl(INADDR_ANY)) { 878 printf(" via "); 879 print_in_addr(gctx->reply.giaddr); 880 } 881 if (bootpc_received(gctx, ifctx) != 0) { 882 printf(" (accepted)"); 883 if (ifctx->outstanding) { 884 ifctx->outstanding = 0; 885 outstanding--; 886 } 887 /* Network settle delay */ 888 if (outstanding == 0) 889 atimo = time_second + 890 BOOTP_SETTLE_DELAY; 891 } else 892 printf(" (ignored)"); 893 if (ifctx->gotrootpath) { 894 gotrootpath = 1; 895 rtimo = time_second + 896 BOOTP_SETTLE_DELAY; 897 printf(" (got root path)"); 898 } else 899 printf(" (no root path)"); 900 printf("\n"); 901 } 902 } /* while secs */ 903#ifdef BOOTP_TIMEOUT 904 if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0) 905 break; 906#endif 907 /* Force a retry if halfway in DHCP negotiation */ 908 retry = 0; 909 for (ifctx = gctx->interfaces; ifctx != NULL; 910 ifctx = ifctx->next) { 911 if (ifctx->state == IF_DHCP_OFFERED) { 912 if (ifctx->dhcpquerytype == DHCP_DISCOVER) 913 retry = 1; 914 else 915 ifctx->state = IF_DHCP_UNRESOLVED; 916 } 917 } 918 919 if (retry != 0) 920 continue; 921 922 if (gotrootpath != 0) { 923 gctx->gotrootpath = gotrootpath; 924 if (rtimo != 0 && time_second >= rtimo) 925 break; 926 } 927 } /* forever send/receive */ 928 929 /* 930 * XXX: These are errors of varying seriousness being silently 931 * ignored 932 */ 933 934 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 935 if (bootpc_ifctx_isresolved(ifctx) == 0) { 936 printf("%s timeout for interface %s\n", 937 ifctx->dhcpquerytype != DHCP_NOMSG ? 938 "DHCP" : "BOOTP", 939 ifctx->ireq.ifr_name); 940 } 941 } 942 if (gctx->gotrootpath != 0) { 943#if 0 944 printf("Got a root path, ignoring remaining timeout\n"); 945#endif 946 error = 0; 947 goto out; 948 } 949#ifndef BOOTP_NFSROOT 950 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 951 if (bootpc_ifctx_isresolved(ifctx) != 0) { 952 error = 0; 953 goto out; 954 } 955 } 956#endif 957 error = ETIMEDOUT; 958 goto out; 959 960gotreply: 961out: 962 soclose(so); 963out0: 964 return error; 965} 966 967static int 968bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 969 struct bootpc_globalcontext *gctx, struct thread *td) 970{ 971 struct sockaddr_in *sin; 972 int error; 973 struct ifreq *ireq; 974 struct socket *so; 975 struct ifaddr *ifa; 976 struct sockaddr_dl *sdl; 977 978 error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td); 979 if (error != 0) 980 panic("nfs_boot: socreate, error=%d", error); 981 982 ireq = &ifctx->ireq; 983 so = ifctx->so; 984 985 /* 986 * Bring up the interface. 987 * 988 * Get the old interface flags and or IFF_UP into them; if 989 * IFF_UP set blindly, interface selection can be clobbered. 990 */ 991 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 992 if (error != 0) 993 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 994 ireq->ifr_flags |= IFF_UP; 995 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 996 if (error != 0) 997 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); 998 999 /* 1000 * Do enough of ifconfig(8) so that the chosen interface 1001 * can talk to the servers. (just set the address) 1002 */ 1003 1004 /* addr is 0.0.0.0 */ 1005 1006 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1007 clear_sinaddr(sin); 1008 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1009 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1010 panic("bootpc_fakeup_interface: " 1011 "set if addr, error=%d", error); 1012 1013 /* netmask is 255.0.0.0 */ 1014 1015 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1016 clear_sinaddr(sin); 1017 sin->sin_addr.s_addr = htonl(0xff000000u); 1018 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); 1019 if (error != 0) 1020 panic("bootpc_fakeup_interface: set if netmask, error=%d", 1021 error); 1022 1023 /* Broadcast is 255.255.255.255 */ 1024 1025 sin = (struct sockaddr_in *)&ireq->ifr_addr; 1026 clear_sinaddr(sin); 1027 clear_sinaddr(&ifctx->broadcast); 1028 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 1029 ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; 1030 1031 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); 1032 if (error != 0) 1033 panic("bootpc_fakeup_interface: " 1034 "set if broadcast addr, error=%d", 1035 error); 1036 1037 /* Get HW address */ 1038 1039 sdl = NULL; 1040 TAILQ_FOREACH(ifa, &ifctx->ifp->if_addrhead, ifa_link) 1041 if (ifa->ifa_addr->sa_family == AF_LINK) { 1042 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 1043 if (sdl->sdl_type == IFT_ETHER) 1044 break; 1045 } 1046 1047 if (sdl == NULL) 1048 panic("bootpc: Unable to find HW address for %s", 1049 ifctx->ireq.ifr_name); 1050 ifctx->sdl = sdl; 1051 1052 return error; 1053} 1054 1055 1056static int 1057bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 1058 struct bootpc_globalcontext *gctx, struct thread *td) 1059{ 1060 int error; 1061 struct sockaddr_in defdst; 1062 struct sockaddr_in defmask; 1063 struct sockaddr_in *sin; 1064 struct ifreq *ireq; 1065 struct socket *so; 1066 struct sockaddr_in *myaddr; 1067 struct sockaddr_in *netmask; 1068 struct sockaddr_in *gw; 1069 1070 ireq = &ifctx->ireq; 1071 so = ifctx->so; 1072 myaddr = &ifctx->myaddr; 1073 netmask = &ifctx->netmask; 1074 gw = &ifctx->gw; 1075 1076 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1077 1078 /* Shutdown interfaces where BOOTP failed */ 1079 1080 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 1081 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1082 if (error != 0) 1083 panic("bootpc_adjust_interface: " 1084 "SIOCGIFFLAGS, error=%d", error); 1085 ireq->ifr_flags &= ~IFF_UP; 1086 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1087 if (error != 0) 1088 panic("bootpc_adjust_interface: " 1089 "SIOCSIFFLAGS, error=%d", error); 1090 1091 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1092 clear_sinaddr(sin); 1093 error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); 1094 if (error != 0 && (error != EEXIST || 1095 ifctx == gctx->interfaces)) 1096 panic("bootpc_adjust_interface: " 1097 "SIOCDIFADDR, error=%d", error); 1098 1099 return 0; 1100 } 1101 1102 printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); 1103 /* 1104 * Do enough of ifconfig(8) so that the chosen interface 1105 * can talk to the servers. (just set the address) 1106 */ 1107 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); 1108 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); 1109 if (error != 0) 1110 panic("bootpc_adjust_interface: " 1111 "set if netmask, error=%d", error); 1112 1113 /* Broadcast is with host part of IP address all 1's */ 1114 1115 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1116 clear_sinaddr(sin); 1117 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | 1118 ~ netmask->sin_addr.s_addr; 1119 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); 1120 if (error != 0) 1121 panic("bootpc_adjust_interface: " 1122 "set if broadcast addr, error=%d", error); 1123 1124 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); 1125 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1126 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1127 panic("bootpc_adjust_interface: " 1128 "set if addr, error=%d", error); 1129 1130 /* Add new default route */ 1131 1132 if (ifctx->gotgw != 0 || gctx->gotgw == 0) { 1133 clear_sinaddr(&defdst); 1134 clear_sinaddr(&defmask); 1135 /* XXX MRT just table 0 */ 1136 error = rtrequest_fib(RTM_ADD, 1137 (struct sockaddr *) &defdst, 1138 (struct sockaddr *) gw, 1139 (struct sockaddr *) &defmask, 1140 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0); 1141 if (error != 0) { 1142 printf("bootpc_adjust_interface: " 1143 "add net route, error=%d\n", error); 1144 return error; 1145 } 1146 } 1147 1148 return 0; 1149} 1150 1151static int 1152setfs(struct sockaddr_in *addr, char *path, char *p, 1153 const struct in_addr *siaddr) 1154{ 1155 1156 if (getip(&p, &addr->sin_addr) == 0) { 1157 if (siaddr != NULL && *p == '/') 1158 bcopy(siaddr, &addr->sin_addr, sizeof(struct in_addr)); 1159 else 1160 return 0; 1161 } else { 1162 if (*p != ':') 1163 return 0; 1164 p++; 1165 } 1166 1167 addr->sin_len = sizeof(struct sockaddr_in); 1168 addr->sin_family = AF_INET; 1169 1170 strlcpy(path, p, MNAMELEN); 1171 return 1; 1172} 1173 1174static int 1175getip(char **ptr, struct in_addr *addr) 1176{ 1177 char *p; 1178 unsigned int ip; 1179 int val; 1180 1181 p = *ptr; 1182 ip = 0; 1183 if (((val = getdec(&p)) < 0) || (val > 255)) 1184 return 0; 1185 ip = val << 24; 1186 if (*p != '.') 1187 return 0; 1188 p++; 1189 if (((val = getdec(&p)) < 0) || (val > 255)) 1190 return 0; 1191 ip |= (val << 16); 1192 if (*p != '.') 1193 return 0; 1194 p++; 1195 if (((val = getdec(&p)) < 0) || (val > 255)) 1196 return 0; 1197 ip |= (val << 8); 1198 if (*p != '.') 1199 return 0; 1200 p++; 1201 if (((val = getdec(&p)) < 0) || (val > 255)) 1202 return 0; 1203 ip |= val; 1204 1205 addr->s_addr = htonl(ip); 1206 *ptr = p; 1207 return 1; 1208} 1209 1210static int 1211getdec(char **ptr) 1212{ 1213 char *p; 1214 int ret; 1215 1216 p = *ptr; 1217 ret = 0; 1218 if ((*p < '0') || (*p > '9')) 1219 return -1; 1220 while ((*p >= '0') && (*p <= '9')) { 1221 ret = ret * 10 + (*p - '0'); 1222 p++; 1223 } 1224 *ptr = p; 1225 return ret; 1226} 1227 1228static void 1229mountopts(struct nfs_args *args, char *p) 1230{ 1231 args->version = NFS_ARGSVERSION; 1232 args->rsize = BOOTP_BLOCKSIZE; 1233 args->wsize = BOOTP_BLOCKSIZE; 1234 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1235 args->sotype = SOCK_DGRAM; 1236 if (p != NULL) 1237 nfs_parse_options(p, args); 1238} 1239 1240static int 1241xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1242{ 1243 struct mbuf *m; 1244 int alignedlen; 1245 1246 m = *mptr; 1247 alignedlen = ( len + 3 ) & ~3; 1248 1249 if (m->m_len < alignedlen) { 1250 m = m_pullup(m, alignedlen); 1251 if (m == NULL) { 1252 *mptr = NULL; 1253 return EBADRPC; 1254 } 1255 } 1256 bcopy(mtod(m, u_char *), buf, len); 1257 m_adj(m, alignedlen); 1258 *mptr = m; 1259 return 0; 1260} 1261 1262static int 1263xdr_int_decode(struct mbuf **mptr, int *iptr) 1264{ 1265 u_int32_t i; 1266 1267 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1268 return EBADRPC; 1269 *iptr = fxdr_unsigned(u_int32_t, i); 1270 return 0; 1271} 1272 1273static void 1274print_sin_addr(struct sockaddr_in *sin) 1275{ 1276 1277 print_in_addr(sin->sin_addr); 1278} 1279 1280static void 1281print_in_addr(struct in_addr addr) 1282{ 1283 unsigned int ip; 1284 1285 ip = ntohl(addr.s_addr); 1286 printf("%d.%d.%d.%d", 1287 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1288} 1289 1290static void 1291bootpc_compose_query(struct bootpc_ifcontext *ifctx, 1292 struct bootpc_globalcontext *gctx, struct thread *td) 1293{ 1294 unsigned char *vendp; 1295 unsigned char vendor_client[64]; 1296 uint32_t leasetime; 1297 uint8_t vendor_client_len; 1298 1299 ifctx->gotrootpath = 0; 1300 1301 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); 1302 1303 /* bootpc part */ 1304 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1305 ifctx->call.htype = 1; /* 10mb ethernet */ 1306 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1307 ifctx->call.hops = 0; 1308 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1309 ifctx->xid++; 1310 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1311 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); 1312 1313 vendp = ifctx->call.vend; 1314 *vendp++ = 99; /* RFC1048 cookie */ 1315 *vendp++ = 130; 1316 *vendp++ = 83; 1317 *vendp++ = 99; 1318 *vendp++ = TAG_MAXMSGSIZE; 1319 *vendp++ = 2; 1320 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1321 *vendp++ = sizeof(struct bootp_packet) & 255; 1322 1323 snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s", 1324 ostype, MACHINE, osrelease); 1325 vendor_client_len = strlen(vendor_client); 1326 *vendp++ = TAG_VENDOR_INDENTIFIER; 1327 *vendp++ = vendor_client_len; 1328 memcpy(vendp, vendor_client, vendor_client_len); 1329 vendp += vendor_client_len;; 1330 ifctx->dhcpquerytype = DHCP_NOMSG; 1331 switch (ifctx->state) { 1332 case IF_DHCP_UNRESOLVED: 1333 *vendp++ = TAG_DHCP_MSGTYPE; 1334 *vendp++ = 1; 1335 *vendp++ = DHCP_DISCOVER; 1336 ifctx->dhcpquerytype = DHCP_DISCOVER; 1337 ifctx->gotdhcpserver = 0; 1338 break; 1339 case IF_DHCP_OFFERED: 1340 *vendp++ = TAG_DHCP_MSGTYPE; 1341 *vendp++ = 1; 1342 *vendp++ = DHCP_REQUEST; 1343 ifctx->dhcpquerytype = DHCP_REQUEST; 1344 *vendp++ = TAG_DHCP_REQ_ADDR; 1345 *vendp++ = 4; 1346 memcpy(vendp, &ifctx->reply.yiaddr, 4); 1347 vendp += 4; 1348 if (ifctx->gotdhcpserver != 0) { 1349 *vendp++ = TAG_DHCP_SERVERID; 1350 *vendp++ = 4; 1351 memcpy(vendp, &ifctx->dhcpserver, 4); 1352 vendp += 4; 1353 } 1354 *vendp++ = TAG_DHCP_LEASETIME; 1355 *vendp++ = 4; 1356 leasetime = htonl(300); 1357 memcpy(vendp, &leasetime, 4); 1358 vendp += 4; 1359 break; 1360 default: 1361 break; 1362 } 1363 *vendp = TAG_END; 1364 1365 ifctx->call.secs = 0; 1366 ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */ 1367} 1368 1369static int 1370bootpc_hascookie(struct bootp_packet *bp) 1371{ 1372 1373 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1374 bp->vend[2] == 83 && bp->vend[3] == 99); 1375} 1376 1377static void 1378bootpc_tag_helper(struct bootpc_tagcontext *tctx, 1379 unsigned char *start, int len, int tag) 1380{ 1381 unsigned char *j; 1382 unsigned char *ej; 1383 unsigned char code; 1384 1385 if (tctx->badtag != 0 || tctx->badopt != 0) 1386 return; 1387 1388 j = start; 1389 ej = j + len; 1390 1391 while (j < ej) { 1392 code = *j++; 1393 if (code == TAG_PAD) 1394 continue; 1395 if (code == TAG_END) 1396 return; 1397 if (j >= ej || j + *j + 1 > ej) { 1398 tctx->badopt = 1; 1399 return; 1400 } 1401 len = *j++; 1402 if (code == tag) { 1403 if (tctx->taglen + len > TAG_MAXLEN) { 1404 tctx->badtag = 1; 1405 return; 1406 } 1407 tctx->foundopt = 1; 1408 if (len > 0) 1409 memcpy(tctx->buf + tctx->taglen, 1410 j, len); 1411 tctx->taglen += len; 1412 } 1413 if (code == TAG_OVERLOAD) 1414 tctx->overload = *j; 1415 1416 j += len; 1417 } 1418} 1419 1420static unsigned char * 1421bootpc_tag(struct bootpc_tagcontext *tctx, 1422 struct bootp_packet *bp, int len, int tag) 1423{ 1424 tctx->overload = 0; 1425 tctx->badopt = 0; 1426 tctx->badtag = 0; 1427 tctx->foundopt = 0; 1428 tctx->taglen = 0; 1429 1430 if (bootpc_hascookie(bp) == 0) 1431 return NULL; 1432 1433 bootpc_tag_helper(tctx, &bp->vend[4], 1434 (unsigned char *) bp + len - &bp->vend[4], tag); 1435 1436 if ((tctx->overload & OVERLOAD_FILE) != 0) 1437 bootpc_tag_helper(tctx, 1438 (unsigned char *) bp->file, 1439 sizeof(bp->file), 1440 tag); 1441 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1442 bootpc_tag_helper(tctx, 1443 (unsigned char *) bp->sname, 1444 sizeof(bp->sname), 1445 tag); 1446 1447 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1448 return NULL; 1449 tctx->buf[tctx->taglen] = '\0'; 1450 return tctx->buf; 1451} 1452 1453static void 1454bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, 1455 struct bootpc_globalcontext *gctx) 1456{ 1457 char *p; 1458 unsigned int ip; 1459 1460 ifctx->gotgw = 0; 1461 ifctx->gotnetmask = 0; 1462 1463 clear_sinaddr(&ifctx->myaddr); 1464 clear_sinaddr(&ifctx->netmask); 1465 clear_sinaddr(&ifctx->gw); 1466 1467 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; 1468 1469 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); 1470 1471 printf("%s at ", ifctx->ireq.ifr_name); 1472 print_sin_addr(&ifctx->myaddr); 1473 printf(" server "); 1474 print_in_addr(ifctx->reply.siaddr); 1475 1476 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1477 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1478 printf(" via gateway "); 1479 print_in_addr(ifctx->reply.giaddr); 1480 } 1481 1482 /* This call used for the side effect (overload flag) */ 1483 (void) bootpc_tag(&gctx->tmptag, 1484 &ifctx->reply, ifctx->replylen, TAG_END); 1485 1486 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1487 if (ifctx->reply.sname[0] != '\0') 1488 printf(" server name %s", ifctx->reply.sname); 1489 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1490 if (ifctx->reply.file[0] != '\0') 1491 printf(" boot file %s", ifctx->reply.file); 1492 1493 printf("\n"); 1494 1495 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1496 TAG_SUBNETMASK); 1497 if (p != NULL) { 1498 if (gctx->tag.taglen != 4) 1499 panic("bootpc: subnet mask len is %d", 1500 gctx->tag.taglen); 1501 bcopy(p, &ifctx->netmask.sin_addr, 4); 1502 ifctx->gotnetmask = 1; 1503 printf("subnet mask "); 1504 print_sin_addr(&ifctx->netmask); 1505 printf(" "); 1506 } 1507 1508 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1509 TAG_ROUTERS); 1510 if (p != NULL) { 1511 /* Routers */ 1512 if (gctx->tag.taglen % 4) 1513 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1514 if (gctx->tag.taglen > 0) { 1515 bcopy(p, &ifctx->gw.sin_addr, 4); 1516 printf("router "); 1517 print_sin_addr(&ifctx->gw); 1518 printf(" "); 1519 ifctx->gotgw = 1; 1520 gctx->gotgw = 1; 1521 } 1522 } 1523 1524 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1525 TAG_ROOT); 1526 if (p != NULL) { 1527 if (gctx->setrootfs != NULL) { 1528 printf("rootfs %s (ignored) ", p); 1529 } else if (setfs(&nd->root_saddr, 1530 nd->root_hostnam, p, &ifctx->reply.siaddr)) { 1531 if (*p == '/') { 1532 printf("root_server "); 1533 print_sin_addr(&nd->root_saddr); 1534 printf(" "); 1535 } 1536 printf("rootfs %s ", p); 1537 gctx->gotrootpath = 1; 1538 ifctx->gotrootpath = 1; 1539 gctx->setrootfs = ifctx; 1540 1541 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1542 ifctx->replylen, 1543 TAG_ROOTOPTS); 1544 if (p != NULL) { 1545 mountopts(&nd->root_args, p); 1546 printf("rootopts %s ", p); 1547 } 1548 } else 1549 panic("Failed to set rootfs to %s", p); 1550 } 1551 1552 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1553 TAG_HOSTNAME); 1554 if (p != NULL) { 1555 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1556 panic("bootpc: hostname >= %d bytes", 1557 MAXHOSTNAMELEN); 1558 if (gctx->sethostname != NULL) { 1559 printf("hostname %s (ignored) ", p); 1560 } else { 1561 strcpy(nd->my_hostnam, p); 1562 mtx_lock(&prison0.pr_mtx); 1563 strcpy(prison0.pr_host, p); 1564 mtx_unlock(&prison0.pr_mtx); 1565 printf("hostname %s ", p); 1566 gctx->sethostname = ifctx; 1567 } 1568 } 1569 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1570 TAG_COOKIE); 1571 if (p != NULL) { /* store in a sysctl variable */ 1572 int i, l = sizeof(bootp_cookie) - 1; 1573 for (i = 0; i < l && p[i] != '\0'; i++) 1574 bootp_cookie[i] = p[i]; 1575 p[i] = '\0'; 1576 } 1577 1578 1579 printf("\n"); 1580 1581 if (ifctx->gotnetmask == 0) { 1582 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1583 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1584 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1585 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1586 else 1587 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1588 } 1589 if (ifctx->gotgw == 0) { 1590 /* Use proxyarp */ 1591 ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr; 1592 } 1593} 1594 1595void 1596bootpc_init(void) 1597{ 1598 INIT_VNET_NET(curvnet); 1599 struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ 1600 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1601 struct ifnet *ifp; 1602 int error; 1603#ifndef BOOTP_WIRED_TO 1604 int ifcnt; 1605#endif 1606 struct nfsv3_diskless *nd; 1607 struct thread *td; 1608 1609 nd = &nfsv3_diskless; 1610 td = curthread; 1611 1612 /* 1613 * If already filled in, don't touch it here 1614 */ 1615 if (nfs_diskless_valid != 0) 1616 return; 1617 1618 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO); 1619 if (gctx == NULL) 1620 panic("Failed to allocate bootp global context structure"); 1621 1622 gctx->xid = ~0xFFFF; 1623 gctx->starttime = time_second; 1624 1625 /* 1626 * Find a network interface. 1627 */ 1628#ifdef BOOTP_WIRED_TO 1629 printf("bootpc_init: wired to interface '%s'\n", 1630 __XSTRING(BOOTP_WIRED_TO)); 1631 allocifctx(gctx); 1632#else 1633 /* 1634 * Preallocate interface context storage, if another interface 1635 * attaches and wins the race, it won't be eligible for bootp. 1636 */ 1637 IFNET_RLOCK(); 1638 for (ifp = TAILQ_FIRST(&V_ifnet), ifcnt = 0; 1639 ifp != NULL; 1640 ifp = TAILQ_NEXT(ifp, if_link)) { 1641 if ((ifp->if_flags & 1642 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1643 IFF_BROADCAST) 1644 continue; 1645 ifcnt++; 1646 } 1647 IFNET_RUNLOCK(); 1648 if (ifcnt == 0) 1649 panic("bootpc_init: no eligible interfaces"); 1650 for (; ifcnt > 0; ifcnt--) 1651 allocifctx(gctx); 1652#endif 1653 1654 IFNET_RLOCK(); 1655 for (ifp = TAILQ_FIRST(&V_ifnet), ifctx = gctx->interfaces; 1656 ifp != NULL && ifctx != NULL; 1657 ifp = TAILQ_NEXT(ifp, if_link)) { 1658 strlcpy(ifctx->ireq.ifr_name, ifp->if_xname, 1659 sizeof(ifctx->ireq.ifr_name)); 1660#ifdef BOOTP_WIRED_TO 1661 if (strcmp(ifctx->ireq.ifr_name, 1662 __XSTRING(BOOTP_WIRED_TO)) != 0) 1663 continue; 1664#else 1665 if ((ifp->if_flags & 1666 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1667 IFF_BROADCAST) 1668 continue; 1669#endif 1670 ifctx->ifp = ifp; 1671 ifctx = ifctx->next; 1672 } 1673 IFNET_RUNLOCK(); 1674 1675 if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) { 1676#ifdef BOOTP_WIRED_TO 1677 panic("bootpc_init: Could not find interface specified " 1678 "by BOOTP_WIRED_TO: " 1679 __XSTRING(BOOTP_WIRED_TO)); 1680#else 1681 panic("bootpc_init: no suitable interface"); 1682#endif 1683 } 1684 1685 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1686 bootpc_fakeup_interface(ifctx, gctx, td); 1687 1688 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1689 bootpc_compose_query(ifctx, gctx, td); 1690 1691 error = bootpc_call(gctx, td); 1692 1693 if (error != 0) { 1694#ifdef BOOTP_NFSROOT 1695 panic("BOOTP call failed"); 1696#else 1697 printf("BOOTP call failed\n"); 1698#endif 1699 } 1700 1701 rootdevnames[0] = "nfs:"; 1702 mountopts(&nd->root_args, NULL); 1703 1704 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1705 if (bootpc_ifctx_isresolved(ifctx) != 0) 1706 bootpc_decode_reply(nd, ifctx, gctx); 1707 1708#ifdef BOOTP_NFSROOT 1709 if (gctx->gotrootpath == 0) 1710 panic("bootpc: No root path offered"); 1711#endif 1712 1713 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 1714 bootpc_adjust_interface(ifctx, gctx, td); 1715 1716 soclose(ifctx->so); 1717 } 1718 1719 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1720 if (ifctx->gotrootpath != 0) 1721 break; 1722 if (ifctx == NULL) { 1723 for (ifctx = gctx->interfaces; 1724 ifctx != NULL; 1725 ifctx = ifctx->next) 1726 if (bootpc_ifctx_isresolved(ifctx) != 0) 1727 break; 1728 } 1729 if (ifctx == NULL) 1730 goto out; 1731 1732 if (gctx->gotrootpath != 0) { 1733 1734 setenv("boot.netif.name", ifctx->ifp->if_xname); 1735 1736 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1737 nd->root_fh, &nd->root_fhsize, 1738 &nd->root_args, td); 1739 if (error != 0) 1740 panic("nfs_boot: mountd root, error=%d", error); 1741 1742 nfs_diskless_valid = 3; 1743 } 1744 1745 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1746 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1747 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1748 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1749 ifctx->myaddr.sin_addr.s_addr | 1750 ~ ifctx->netmask.sin_addr.s_addr; 1751 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); 1752 1753out: 1754 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { 1755 nctx = ifctx->next; 1756 free(ifctx, M_TEMP); 1757 } 1758 free(gctx, M_TEMP); 1759} 1760 1761/* 1762 * RPC: mountd/mount 1763 * Given a server pathname, get an NFS file handle. 1764 * Also, sets sin->sin_port to the NFS service port. 1765 */ 1766static int 1767md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1768 struct nfs_args *args, struct thread *td) 1769{ 1770 struct mbuf *m; 1771 int error; 1772 int authunixok; 1773 int authcount; 1774 int authver; 1775 1776 /* XXX honor v2/v3 flags in args->flags? */ 1777#ifdef BOOTP_NFSV3 1778 /* First try NFS v3 */ 1779 /* Get port number for MOUNTD. */ 1780 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1781 &mdsin->sin_port, td); 1782 if (error == 0) { 1783 m = xdr_string_encode(path, strlen(path)); 1784 1785 /* Do RPC to mountd. */ 1786 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1787 RPCMNT_MOUNT, &m, NULL, td); 1788 } 1789 if (error == 0) { 1790 args->flags |= NFSMNT_NFSV3; 1791 } else { 1792#endif 1793 /* Fallback to NFS v2 */ 1794 1795 /* Get port number for MOUNTD. */ 1796 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1797 &mdsin->sin_port, td); 1798 if (error != 0) 1799 return error; 1800 1801 m = xdr_string_encode(path, strlen(path)); 1802 1803 /* Do RPC to mountd. */ 1804 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1805 RPCMNT_MOUNT, &m, NULL, td); 1806 if (error != 0) 1807 return error; /* message already freed */ 1808 1809#ifdef BOOTP_NFSV3 1810 } 1811#endif 1812 1813 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1814 goto bad; 1815 1816 if ((args->flags & NFSMNT_NFSV3) != 0) { 1817 if (xdr_int_decode(&m, fhsizep) != 0 || 1818 *fhsizep > NFSX_V3FHMAX || 1819 *fhsizep <= 0) 1820 goto bad; 1821 } else 1822 *fhsizep = NFSX_V2FH; 1823 1824 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1825 goto bad; 1826 1827 if (args->flags & NFSMNT_NFSV3) { 1828 if (xdr_int_decode(&m, &authcount) != 0) 1829 goto bad; 1830 authunixok = 0; 1831 if (authcount < 0 || authcount > 100) 1832 goto bad; 1833 while (authcount > 0) { 1834 if (xdr_int_decode(&m, &authver) != 0) 1835 goto bad; 1836 if (authver == RPCAUTH_UNIX) 1837 authunixok = 1; 1838 authcount--; 1839 } 1840 if (authunixok == 0) 1841 goto bad; 1842 } 1843 1844 /* Set port number for NFS use. */ 1845 error = krpc_portmap(mdsin, NFS_PROG, 1846 (args->flags & 1847 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1848 &mdsin->sin_port, td); 1849 1850 goto out; 1851 1852bad: 1853 error = EBADRPC; 1854 1855out: 1856 m_freem(m); 1857 return error; 1858} 1859 1860SYSINIT(bootp_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, bootpc_init, NULL);
| 373} 374 375void 376bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 377{ 378 379 printf("%s flags %x, addr ", 380 ifp->if_xname, ifp->if_flags); 381 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 382 printf(", broadcast "); 383 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 384 printf(", netmask "); 385 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 386 printf("\n"); 387} 388 389void 390bootpboot_p_iflist(void) 391{ 392 INIT_VNET_NET(curvnet); 393 struct ifnet *ifp; 394 struct ifaddr *ifa; 395 396 printf("Interface list:\n"); 397 IFNET_RLOCK(); /* could sleep, but okay for debugging XXX */ 398 for (ifp = TAILQ_FIRST(&V_ifnet); 399 ifp != NULL; 400 ifp = TAILQ_NEXT(ifp, if_link)) { 401 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 402 ifa != NULL; 403 ifa = TAILQ_NEXT(ifa, ifa_link)) 404 if (ifa->ifa_addr->sa_family == AF_INET) 405 bootpboot_p_if(ifp, ifa); 406 } 407 IFNET_RUNLOCK(); 408} 409#endif /* defined(BOOTP_DEBUG) */ 410 411static void 412clear_sinaddr(struct sockaddr_in *sin) 413{ 414 415 bzero(sin, sizeof(*sin)); 416 sin->sin_len = sizeof(*sin); 417 sin->sin_family = AF_INET; 418 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 419 sin->sin_port = 0; 420} 421 422static void 423allocifctx(struct bootpc_globalcontext *gctx) 424{ 425 struct bootpc_ifcontext *ifctx; 426 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), 427 M_TEMP, M_WAITOK | M_ZERO); 428 if (ifctx == NULL) 429 panic("Failed to allocate bootp interface context structure"); 430 431 ifctx->xid = gctx->xid; 432#ifdef BOOTP_NO_DHCP 433 ifctx->state = IF_BOOTP_UNRESOLVED; 434#else 435 ifctx->state = IF_DHCP_UNRESOLVED; 436#endif 437 gctx->xid += 0x100; 438 if (gctx->interfaces != NULL) 439 gctx->lastinterface->next = ifctx; 440 else 441 gctx->interfaces = ifctx; 442 gctx->lastinterface = ifctx; 443} 444 445static __inline int 446bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 447{ 448 449 if (ifctx->state == IF_BOOTP_RESOLVED || 450 ifctx->state == IF_DHCP_RESOLVED) 451 return 1; 452 return 0; 453} 454 455static __inline int 456bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 457{ 458 459 if (ifctx->state == IF_BOOTP_UNRESOLVED || 460 ifctx->state == IF_DHCP_UNRESOLVED) 461 return 1; 462 return 0; 463} 464 465static __inline int 466bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 467{ 468 469 if (ifctx->state == IF_BOOTP_FAILED || 470 ifctx->state == IF_DHCP_FAILED) 471 return 1; 472 return 0; 473} 474 475static int 476bootpc_received(struct bootpc_globalcontext *gctx, 477 struct bootpc_ifcontext *ifctx) 478{ 479 unsigned char dhcpreplytype; 480 char *p; 481 482 /* 483 * Need timeout for fallback to less 484 * desirable alternative. 485 */ 486 487 /* This call used for the side effect (badopt flag) */ 488 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 489 gctx->replylen, 490 TAG_END); 491 492 /* If packet is invalid, ignore it */ 493 if (gctx->tmptag.badopt != 0) 494 return 0; 495 496 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 497 gctx->replylen, TAG_DHCP_MSGTYPE); 498 if (p != NULL) 499 dhcpreplytype = *p; 500 else 501 dhcpreplytype = DHCP_NOMSG; 502 503 switch (ifctx->dhcpquerytype) { 504 case DHCP_DISCOVER: 505 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 506#ifndef BOOTP_FORCE_DHCP 507 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 508#endif 509 ) 510 return 0; 511 break; 512 case DHCP_REQUEST: 513 if (dhcpreplytype != DHCP_ACK) 514 return 0; 515 case DHCP_NOMSG: 516 break; 517 } 518 519 /* Ignore packet unless it gives us a root tag we didn't have */ 520 521 if ((ifctx->state == IF_BOOTP_RESOLVED || 522 (ifctx->dhcpquerytype == DHCP_DISCOVER && 523 (ifctx->state == IF_DHCP_OFFERED || 524 ifctx->state == IF_DHCP_RESOLVED))) && 525 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 526 ifctx->replylen, 527 TAG_ROOT) != NULL || 528 bootpc_tag(&gctx->tmptag, &gctx->reply, 529 gctx->replylen, 530 TAG_ROOT) == NULL)) 531 return 0; 532 533 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); 534 ifctx->replylen = gctx->replylen; 535 536 /* XXX: Only reset if 'perfect' response */ 537 if (ifctx->state == IF_BOOTP_UNRESOLVED) 538 ifctx->state = IF_BOOTP_RESOLVED; 539 else if (ifctx->state == IF_DHCP_UNRESOLVED && 540 ifctx->dhcpquerytype == DHCP_DISCOVER) { 541 if (dhcpreplytype == DHCP_OFFER) 542 ifctx->state = IF_DHCP_OFFERED; 543 else 544 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 545 } else if (ifctx->state == IF_DHCP_OFFERED && 546 ifctx->dhcpquerytype == DHCP_REQUEST) 547 ifctx->state = IF_DHCP_RESOLVED; 548 549 550 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 551 ifctx->state != IF_BOOTP_RESOLVED) { 552 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 553 ifctx->replylen, TAG_DHCP_SERVERID); 554 if (p != NULL && gctx->tmptag.taglen == 4) { 555 memcpy(&ifctx->dhcpserver, p, 4); 556 ifctx->gotdhcpserver = 1; 557 } else 558 ifctx->gotdhcpserver = 0; 559 return 1; 560 } 561 562 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 563 ifctx->replylen, 564 TAG_ROOT) != NULL); 565 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 566 ifctx->replylen, 567 TAG_ROUTERS) != NULL); 568 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 569 ifctx->replylen, 570 TAG_SUBNETMASK) != NULL); 571 return 1; 572} 573 574static int 575bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) 576{ 577 struct socket *so; 578 struct sockaddr_in *sin, dst; 579 struct uio auio; 580 struct sockopt sopt; 581 struct iovec aio; 582 int error, on, rcvflg, timo, len; 583 time_t atimo; 584 time_t rtimo; 585 struct timeval tv; 586 struct bootpc_ifcontext *ifctx; 587 int outstanding; 588 int gotrootpath; 589 int retry; 590 const char *s; 591 592 /* 593 * Create socket and set its recieve timeout. 594 */ 595 error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td); 596 if (error != 0) 597 goto out0; 598 599 tv.tv_sec = 1; 600 tv.tv_usec = 0; 601 bzero(&sopt, sizeof(sopt)); 602 sopt.sopt_dir = SOPT_SET; 603 sopt.sopt_level = SOL_SOCKET; 604 sopt.sopt_name = SO_RCVTIMEO; 605 sopt.sopt_val = &tv; 606 sopt.sopt_valsize = sizeof tv; 607 608 error = sosetopt(so, &sopt); 609 if (error != 0) 610 goto out; 611 612 /* 613 * Enable broadcast. 614 */ 615 on = 1; 616 sopt.sopt_name = SO_BROADCAST; 617 sopt.sopt_val = &on; 618 sopt.sopt_valsize = sizeof on; 619 620 error = sosetopt(so, &sopt); 621 if (error != 0) 622 goto out; 623 624 /* 625 * Disable routing. 626 */ 627 628 on = 1; 629 sopt.sopt_name = SO_DONTROUTE; 630 sopt.sopt_val = &on; 631 sopt.sopt_valsize = sizeof on; 632 633 error = sosetopt(so, &sopt); 634 if (error != 0) 635 goto out; 636 637 /* 638 * Bind the local endpoint to a bootp client port. 639 */ 640 sin = &dst; 641 clear_sinaddr(sin); 642 sin->sin_port = htons(IPPORT_BOOTPC); 643 error = sobind(so, (struct sockaddr *)sin, td); 644 if (error != 0) { 645 printf("bind failed\n"); 646 goto out; 647 } 648 649 /* 650 * Setup socket address for the server. 651 */ 652 sin = &dst; 653 clear_sinaddr(sin); 654 sin->sin_addr.s_addr = INADDR_BROADCAST; 655 sin->sin_port = htons(IPPORT_BOOTPS); 656 657 /* 658 * Send it, repeatedly, until a reply is received, 659 * but delay each re-send by an increasing amount. 660 * If the delay hits the maximum, start complaining. 661 */ 662 timo = 0; 663 rtimo = 0; 664 for (;;) { 665 666 outstanding = 0; 667 gotrootpath = 0; 668 669 for (ifctx = gctx->interfaces; 670 ifctx != NULL; 671 ifctx = ifctx->next) { 672 if (bootpc_ifctx_isresolved(ifctx) != 0 && 673 bootpc_tag(&gctx->tmptag, &ifctx->reply, 674 ifctx->replylen, 675 TAG_ROOT) != NULL) 676 gotrootpath = 1; 677 } 678 679 for (ifctx = gctx->interfaces; 680 ifctx != NULL; 681 ifctx = ifctx->next) { 682 ifctx->outstanding = 0; 683 if (bootpc_ifctx_isresolved(ifctx) != 0 && 684 gotrootpath != 0) { 685 continue; 686 } 687 if (bootpc_ifctx_isfailed(ifctx) != 0) 688 continue; 689 690 outstanding++; 691 ifctx->outstanding = 1; 692 693 /* Proceed to next step in DHCP negotiation */ 694 if ((ifctx->state == IF_DHCP_OFFERED && 695 ifctx->dhcpquerytype != DHCP_REQUEST) || 696 (ifctx->state == IF_DHCP_UNRESOLVED && 697 ifctx->dhcpquerytype != DHCP_DISCOVER) || 698 (ifctx->state == IF_BOOTP_UNRESOLVED && 699 ifctx->dhcpquerytype != DHCP_NOMSG)) { 700 ifctx->sentmsg = 0; 701 bootpc_compose_query(ifctx, gctx, td); 702 } 703 704 /* Send BOOTP request (or re-send). */ 705 706 if (ifctx->sentmsg == 0) { 707 switch(ifctx->dhcpquerytype) { 708 case DHCP_DISCOVER: 709 s = "DHCP Discover"; 710 break; 711 case DHCP_REQUEST: 712 s = "DHCP Request"; 713 break; 714 case DHCP_NOMSG: 715 default: 716 s = "BOOTP Query"; 717 break; 718 } 719 printf("Sending %s packet from " 720 "interface %s (%*D)\n", 721 s, 722 ifctx->ireq.ifr_name, 723 ifctx->sdl->sdl_alen, 724 (unsigned char *) LLADDR(ifctx->sdl), 725 ":"); 726 ifctx->sentmsg = 1; 727 } 728 729 aio.iov_base = (caddr_t) &ifctx->call; 730 aio.iov_len = sizeof(ifctx->call); 731 732 auio.uio_iov = &aio; 733 auio.uio_iovcnt = 1; 734 auio.uio_segflg = UIO_SYSSPACE; 735 auio.uio_rw = UIO_WRITE; 736 auio.uio_offset = 0; 737 auio.uio_resid = sizeof(ifctx->call); 738 auio.uio_td = td; 739 740 /* Set netmask to 0.0.0.0 */ 741 742 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 743 clear_sinaddr(sin); 744 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 745 (caddr_t) &ifctx->ireq, td); 746 if (error != 0) 747 panic("bootpc_call:" 748 "set if netmask, error=%d", 749 error); 750 751 error = sosend(so, (struct sockaddr *) &dst, 752 &auio, NULL, NULL, 0, td); 753 if (error != 0) { 754 printf("bootpc_call: sosend: %d state %08x\n", 755 error, (int) so->so_state); 756 } 757 758 /* XXX: Is this needed ? */ 759 pause("bootpw", hz/10); 760 761 /* Set netmask to 255.0.0.0 */ 762 763 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 764 clear_sinaddr(sin); 765 sin->sin_addr.s_addr = htonl(0xff000000u); 766 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 767 (caddr_t) &ifctx->ireq, td); 768 if (error != 0) 769 panic("bootpc_call:" 770 "set if netmask, error=%d", 771 error); 772 773 } 774 775 if (outstanding == 0 && 776 (rtimo == 0 || time_second >= rtimo)) { 777 error = 0; 778 goto gotreply; 779 } 780 781 /* Determine new timeout. */ 782 if (timo < MAX_RESEND_DELAY) 783 timo++; 784 else { 785 printf("DHCP/BOOTP timeout for server "); 786 print_sin_addr(&dst); 787 printf("\n"); 788 } 789 790 /* 791 * Wait for up to timo seconds for a reply. 792 * The socket receive timeout was set to 1 second. 793 */ 794 atimo = timo + time_second; 795 while (time_second < atimo) { 796 aio.iov_base = (caddr_t) &gctx->reply; 797 aio.iov_len = sizeof(gctx->reply); 798 799 auio.uio_iov = &aio; 800 auio.uio_iovcnt = 1; 801 auio.uio_segflg = UIO_SYSSPACE; 802 auio.uio_rw = UIO_READ; 803 auio.uio_offset = 0; 804 auio.uio_resid = sizeof(gctx->reply); 805 auio.uio_td = td; 806 807 rcvflg = 0; 808 error = soreceive(so, NULL, &auio, 809 NULL, NULL, &rcvflg); 810 gctx->secs = time_second - gctx->starttime; 811 for (ifctx = gctx->interfaces; 812 ifctx != NULL; 813 ifctx = ifctx->next) { 814 if (bootpc_ifctx_isresolved(ifctx) != 0 || 815 bootpc_ifctx_isfailed(ifctx) != 0) 816 continue; 817 818 ifctx->call.secs = htons(gctx->secs); 819 } 820 if (error == EWOULDBLOCK) 821 continue; 822 if (error != 0) 823 goto out; 824 len = sizeof(gctx->reply) - auio.uio_resid; 825 826 /* Do we have the required number of bytes ? */ 827 if (len < BOOTP_MIN_LEN) 828 continue; 829 gctx->replylen = len; 830 831 /* Is it a reply? */ 832 if (gctx->reply.op != BOOTP_REPLY) 833 continue; 834 835 /* Is this an answer to our query */ 836 for (ifctx = gctx->interfaces; 837 ifctx != NULL; 838 ifctx = ifctx->next) { 839 if (gctx->reply.xid != ifctx->call.xid) 840 continue; 841 842 /* Same HW address size ? */ 843 if (gctx->reply.hlen != ifctx->call.hlen) 844 continue; 845 846 /* Correct HW address ? */ 847 if (bcmp(gctx->reply.chaddr, 848 ifctx->call.chaddr, 849 ifctx->call.hlen) != 0) 850 continue; 851 852 break; 853 } 854 855 if (ifctx != NULL) { 856 s = bootpc_tag(&gctx->tmptag, 857 &gctx->reply, 858 gctx->replylen, 859 TAG_DHCP_MSGTYPE); 860 if (s != NULL) { 861 switch (*s) { 862 case DHCP_OFFER: 863 s = "DHCP Offer"; 864 break; 865 case DHCP_ACK: 866 s = "DHCP Ack"; 867 break; 868 default: 869 s = "DHCP (unexpected)"; 870 break; 871 } 872 } else 873 s = "BOOTP Reply"; 874 875 printf("Received %s packet" 876 " on %s from ", 877 s, 878 ifctx->ireq.ifr_name); 879 print_in_addr(gctx->reply.siaddr); 880 if (gctx->reply.giaddr.s_addr != 881 htonl(INADDR_ANY)) { 882 printf(" via "); 883 print_in_addr(gctx->reply.giaddr); 884 } 885 if (bootpc_received(gctx, ifctx) != 0) { 886 printf(" (accepted)"); 887 if (ifctx->outstanding) { 888 ifctx->outstanding = 0; 889 outstanding--; 890 } 891 /* Network settle delay */ 892 if (outstanding == 0) 893 atimo = time_second + 894 BOOTP_SETTLE_DELAY; 895 } else 896 printf(" (ignored)"); 897 if (ifctx->gotrootpath) { 898 gotrootpath = 1; 899 rtimo = time_second + 900 BOOTP_SETTLE_DELAY; 901 printf(" (got root path)"); 902 } else 903 printf(" (no root path)"); 904 printf("\n"); 905 } 906 } /* while secs */ 907#ifdef BOOTP_TIMEOUT 908 if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0) 909 break; 910#endif 911 /* Force a retry if halfway in DHCP negotiation */ 912 retry = 0; 913 for (ifctx = gctx->interfaces; ifctx != NULL; 914 ifctx = ifctx->next) { 915 if (ifctx->state == IF_DHCP_OFFERED) { 916 if (ifctx->dhcpquerytype == DHCP_DISCOVER) 917 retry = 1; 918 else 919 ifctx->state = IF_DHCP_UNRESOLVED; 920 } 921 } 922 923 if (retry != 0) 924 continue; 925 926 if (gotrootpath != 0) { 927 gctx->gotrootpath = gotrootpath; 928 if (rtimo != 0 && time_second >= rtimo) 929 break; 930 } 931 } /* forever send/receive */ 932 933 /* 934 * XXX: These are errors of varying seriousness being silently 935 * ignored 936 */ 937 938 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 939 if (bootpc_ifctx_isresolved(ifctx) == 0) { 940 printf("%s timeout for interface %s\n", 941 ifctx->dhcpquerytype != DHCP_NOMSG ? 942 "DHCP" : "BOOTP", 943 ifctx->ireq.ifr_name); 944 } 945 } 946 if (gctx->gotrootpath != 0) { 947#if 0 948 printf("Got a root path, ignoring remaining timeout\n"); 949#endif 950 error = 0; 951 goto out; 952 } 953#ifndef BOOTP_NFSROOT 954 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 955 if (bootpc_ifctx_isresolved(ifctx) != 0) { 956 error = 0; 957 goto out; 958 } 959 } 960#endif 961 error = ETIMEDOUT; 962 goto out; 963 964gotreply: 965out: 966 soclose(so); 967out0: 968 return error; 969} 970 971static int 972bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 973 struct bootpc_globalcontext *gctx, struct thread *td) 974{ 975 struct sockaddr_in *sin; 976 int error; 977 struct ifreq *ireq; 978 struct socket *so; 979 struct ifaddr *ifa; 980 struct sockaddr_dl *sdl; 981 982 error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td); 983 if (error != 0) 984 panic("nfs_boot: socreate, error=%d", error); 985 986 ireq = &ifctx->ireq; 987 so = ifctx->so; 988 989 /* 990 * Bring up the interface. 991 * 992 * Get the old interface flags and or IFF_UP into them; if 993 * IFF_UP set blindly, interface selection can be clobbered. 994 */ 995 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 996 if (error != 0) 997 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 998 ireq->ifr_flags |= IFF_UP; 999 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1000 if (error != 0) 1001 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); 1002 1003 /* 1004 * Do enough of ifconfig(8) so that the chosen interface 1005 * can talk to the servers. (just set the address) 1006 */ 1007 1008 /* addr is 0.0.0.0 */ 1009 1010 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1011 clear_sinaddr(sin); 1012 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1013 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1014 panic("bootpc_fakeup_interface: " 1015 "set if addr, error=%d", error); 1016 1017 /* netmask is 255.0.0.0 */ 1018 1019 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1020 clear_sinaddr(sin); 1021 sin->sin_addr.s_addr = htonl(0xff000000u); 1022 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); 1023 if (error != 0) 1024 panic("bootpc_fakeup_interface: set if netmask, error=%d", 1025 error); 1026 1027 /* Broadcast is 255.255.255.255 */ 1028 1029 sin = (struct sockaddr_in *)&ireq->ifr_addr; 1030 clear_sinaddr(sin); 1031 clear_sinaddr(&ifctx->broadcast); 1032 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 1033 ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; 1034 1035 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); 1036 if (error != 0) 1037 panic("bootpc_fakeup_interface: " 1038 "set if broadcast addr, error=%d", 1039 error); 1040 1041 /* Get HW address */ 1042 1043 sdl = NULL; 1044 TAILQ_FOREACH(ifa, &ifctx->ifp->if_addrhead, ifa_link) 1045 if (ifa->ifa_addr->sa_family == AF_LINK) { 1046 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 1047 if (sdl->sdl_type == IFT_ETHER) 1048 break; 1049 } 1050 1051 if (sdl == NULL) 1052 panic("bootpc: Unable to find HW address for %s", 1053 ifctx->ireq.ifr_name); 1054 ifctx->sdl = sdl; 1055 1056 return error; 1057} 1058 1059 1060static int 1061bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 1062 struct bootpc_globalcontext *gctx, struct thread *td) 1063{ 1064 int error; 1065 struct sockaddr_in defdst; 1066 struct sockaddr_in defmask; 1067 struct sockaddr_in *sin; 1068 struct ifreq *ireq; 1069 struct socket *so; 1070 struct sockaddr_in *myaddr; 1071 struct sockaddr_in *netmask; 1072 struct sockaddr_in *gw; 1073 1074 ireq = &ifctx->ireq; 1075 so = ifctx->so; 1076 myaddr = &ifctx->myaddr; 1077 netmask = &ifctx->netmask; 1078 gw = &ifctx->gw; 1079 1080 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1081 1082 /* Shutdown interfaces where BOOTP failed */ 1083 1084 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 1085 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1086 if (error != 0) 1087 panic("bootpc_adjust_interface: " 1088 "SIOCGIFFLAGS, error=%d", error); 1089 ireq->ifr_flags &= ~IFF_UP; 1090 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1091 if (error != 0) 1092 panic("bootpc_adjust_interface: " 1093 "SIOCSIFFLAGS, error=%d", error); 1094 1095 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1096 clear_sinaddr(sin); 1097 error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); 1098 if (error != 0 && (error != EEXIST || 1099 ifctx == gctx->interfaces)) 1100 panic("bootpc_adjust_interface: " 1101 "SIOCDIFADDR, error=%d", error); 1102 1103 return 0; 1104 } 1105 1106 printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); 1107 /* 1108 * Do enough of ifconfig(8) so that the chosen interface 1109 * can talk to the servers. (just set the address) 1110 */ 1111 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); 1112 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); 1113 if (error != 0) 1114 panic("bootpc_adjust_interface: " 1115 "set if netmask, error=%d", error); 1116 1117 /* Broadcast is with host part of IP address all 1's */ 1118 1119 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1120 clear_sinaddr(sin); 1121 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | 1122 ~ netmask->sin_addr.s_addr; 1123 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); 1124 if (error != 0) 1125 panic("bootpc_adjust_interface: " 1126 "set if broadcast addr, error=%d", error); 1127 1128 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); 1129 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1130 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1131 panic("bootpc_adjust_interface: " 1132 "set if addr, error=%d", error); 1133 1134 /* Add new default route */ 1135 1136 if (ifctx->gotgw != 0 || gctx->gotgw == 0) { 1137 clear_sinaddr(&defdst); 1138 clear_sinaddr(&defmask); 1139 /* XXX MRT just table 0 */ 1140 error = rtrequest_fib(RTM_ADD, 1141 (struct sockaddr *) &defdst, 1142 (struct sockaddr *) gw, 1143 (struct sockaddr *) &defmask, 1144 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0); 1145 if (error != 0) { 1146 printf("bootpc_adjust_interface: " 1147 "add net route, error=%d\n", error); 1148 return error; 1149 } 1150 } 1151 1152 return 0; 1153} 1154 1155static int 1156setfs(struct sockaddr_in *addr, char *path, char *p, 1157 const struct in_addr *siaddr) 1158{ 1159 1160 if (getip(&p, &addr->sin_addr) == 0) { 1161 if (siaddr != NULL && *p == '/') 1162 bcopy(siaddr, &addr->sin_addr, sizeof(struct in_addr)); 1163 else 1164 return 0; 1165 } else { 1166 if (*p != ':') 1167 return 0; 1168 p++; 1169 } 1170 1171 addr->sin_len = sizeof(struct sockaddr_in); 1172 addr->sin_family = AF_INET; 1173 1174 strlcpy(path, p, MNAMELEN); 1175 return 1; 1176} 1177 1178static int 1179getip(char **ptr, struct in_addr *addr) 1180{ 1181 char *p; 1182 unsigned int ip; 1183 int val; 1184 1185 p = *ptr; 1186 ip = 0; 1187 if (((val = getdec(&p)) < 0) || (val > 255)) 1188 return 0; 1189 ip = val << 24; 1190 if (*p != '.') 1191 return 0; 1192 p++; 1193 if (((val = getdec(&p)) < 0) || (val > 255)) 1194 return 0; 1195 ip |= (val << 16); 1196 if (*p != '.') 1197 return 0; 1198 p++; 1199 if (((val = getdec(&p)) < 0) || (val > 255)) 1200 return 0; 1201 ip |= (val << 8); 1202 if (*p != '.') 1203 return 0; 1204 p++; 1205 if (((val = getdec(&p)) < 0) || (val > 255)) 1206 return 0; 1207 ip |= val; 1208 1209 addr->s_addr = htonl(ip); 1210 *ptr = p; 1211 return 1; 1212} 1213 1214static int 1215getdec(char **ptr) 1216{ 1217 char *p; 1218 int ret; 1219 1220 p = *ptr; 1221 ret = 0; 1222 if ((*p < '0') || (*p > '9')) 1223 return -1; 1224 while ((*p >= '0') && (*p <= '9')) { 1225 ret = ret * 10 + (*p - '0'); 1226 p++; 1227 } 1228 *ptr = p; 1229 return ret; 1230} 1231 1232static void 1233mountopts(struct nfs_args *args, char *p) 1234{ 1235 args->version = NFS_ARGSVERSION; 1236 args->rsize = BOOTP_BLOCKSIZE; 1237 args->wsize = BOOTP_BLOCKSIZE; 1238 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1239 args->sotype = SOCK_DGRAM; 1240 if (p != NULL) 1241 nfs_parse_options(p, args); 1242} 1243 1244static int 1245xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1246{ 1247 struct mbuf *m; 1248 int alignedlen; 1249 1250 m = *mptr; 1251 alignedlen = ( len + 3 ) & ~3; 1252 1253 if (m->m_len < alignedlen) { 1254 m = m_pullup(m, alignedlen); 1255 if (m == NULL) { 1256 *mptr = NULL; 1257 return EBADRPC; 1258 } 1259 } 1260 bcopy(mtod(m, u_char *), buf, len); 1261 m_adj(m, alignedlen); 1262 *mptr = m; 1263 return 0; 1264} 1265 1266static int 1267xdr_int_decode(struct mbuf **mptr, int *iptr) 1268{ 1269 u_int32_t i; 1270 1271 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1272 return EBADRPC; 1273 *iptr = fxdr_unsigned(u_int32_t, i); 1274 return 0; 1275} 1276 1277static void 1278print_sin_addr(struct sockaddr_in *sin) 1279{ 1280 1281 print_in_addr(sin->sin_addr); 1282} 1283 1284static void 1285print_in_addr(struct in_addr addr) 1286{ 1287 unsigned int ip; 1288 1289 ip = ntohl(addr.s_addr); 1290 printf("%d.%d.%d.%d", 1291 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1292} 1293 1294static void 1295bootpc_compose_query(struct bootpc_ifcontext *ifctx, 1296 struct bootpc_globalcontext *gctx, struct thread *td) 1297{ 1298 unsigned char *vendp; 1299 unsigned char vendor_client[64]; 1300 uint32_t leasetime; 1301 uint8_t vendor_client_len; 1302 1303 ifctx->gotrootpath = 0; 1304 1305 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); 1306 1307 /* bootpc part */ 1308 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1309 ifctx->call.htype = 1; /* 10mb ethernet */ 1310 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1311 ifctx->call.hops = 0; 1312 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1313 ifctx->xid++; 1314 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1315 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); 1316 1317 vendp = ifctx->call.vend; 1318 *vendp++ = 99; /* RFC1048 cookie */ 1319 *vendp++ = 130; 1320 *vendp++ = 83; 1321 *vendp++ = 99; 1322 *vendp++ = TAG_MAXMSGSIZE; 1323 *vendp++ = 2; 1324 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1325 *vendp++ = sizeof(struct bootp_packet) & 255; 1326 1327 snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s", 1328 ostype, MACHINE, osrelease); 1329 vendor_client_len = strlen(vendor_client); 1330 *vendp++ = TAG_VENDOR_INDENTIFIER; 1331 *vendp++ = vendor_client_len; 1332 memcpy(vendp, vendor_client, vendor_client_len); 1333 vendp += vendor_client_len;; 1334 ifctx->dhcpquerytype = DHCP_NOMSG; 1335 switch (ifctx->state) { 1336 case IF_DHCP_UNRESOLVED: 1337 *vendp++ = TAG_DHCP_MSGTYPE; 1338 *vendp++ = 1; 1339 *vendp++ = DHCP_DISCOVER; 1340 ifctx->dhcpquerytype = DHCP_DISCOVER; 1341 ifctx->gotdhcpserver = 0; 1342 break; 1343 case IF_DHCP_OFFERED: 1344 *vendp++ = TAG_DHCP_MSGTYPE; 1345 *vendp++ = 1; 1346 *vendp++ = DHCP_REQUEST; 1347 ifctx->dhcpquerytype = DHCP_REQUEST; 1348 *vendp++ = TAG_DHCP_REQ_ADDR; 1349 *vendp++ = 4; 1350 memcpy(vendp, &ifctx->reply.yiaddr, 4); 1351 vendp += 4; 1352 if (ifctx->gotdhcpserver != 0) { 1353 *vendp++ = TAG_DHCP_SERVERID; 1354 *vendp++ = 4; 1355 memcpy(vendp, &ifctx->dhcpserver, 4); 1356 vendp += 4; 1357 } 1358 *vendp++ = TAG_DHCP_LEASETIME; 1359 *vendp++ = 4; 1360 leasetime = htonl(300); 1361 memcpy(vendp, &leasetime, 4); 1362 vendp += 4; 1363 break; 1364 default: 1365 break; 1366 } 1367 *vendp = TAG_END; 1368 1369 ifctx->call.secs = 0; 1370 ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */ 1371} 1372 1373static int 1374bootpc_hascookie(struct bootp_packet *bp) 1375{ 1376 1377 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1378 bp->vend[2] == 83 && bp->vend[3] == 99); 1379} 1380 1381static void 1382bootpc_tag_helper(struct bootpc_tagcontext *tctx, 1383 unsigned char *start, int len, int tag) 1384{ 1385 unsigned char *j; 1386 unsigned char *ej; 1387 unsigned char code; 1388 1389 if (tctx->badtag != 0 || tctx->badopt != 0) 1390 return; 1391 1392 j = start; 1393 ej = j + len; 1394 1395 while (j < ej) { 1396 code = *j++; 1397 if (code == TAG_PAD) 1398 continue; 1399 if (code == TAG_END) 1400 return; 1401 if (j >= ej || j + *j + 1 > ej) { 1402 tctx->badopt = 1; 1403 return; 1404 } 1405 len = *j++; 1406 if (code == tag) { 1407 if (tctx->taglen + len > TAG_MAXLEN) { 1408 tctx->badtag = 1; 1409 return; 1410 } 1411 tctx->foundopt = 1; 1412 if (len > 0) 1413 memcpy(tctx->buf + tctx->taglen, 1414 j, len); 1415 tctx->taglen += len; 1416 } 1417 if (code == TAG_OVERLOAD) 1418 tctx->overload = *j; 1419 1420 j += len; 1421 } 1422} 1423 1424static unsigned char * 1425bootpc_tag(struct bootpc_tagcontext *tctx, 1426 struct bootp_packet *bp, int len, int tag) 1427{ 1428 tctx->overload = 0; 1429 tctx->badopt = 0; 1430 tctx->badtag = 0; 1431 tctx->foundopt = 0; 1432 tctx->taglen = 0; 1433 1434 if (bootpc_hascookie(bp) == 0) 1435 return NULL; 1436 1437 bootpc_tag_helper(tctx, &bp->vend[4], 1438 (unsigned char *) bp + len - &bp->vend[4], tag); 1439 1440 if ((tctx->overload & OVERLOAD_FILE) != 0) 1441 bootpc_tag_helper(tctx, 1442 (unsigned char *) bp->file, 1443 sizeof(bp->file), 1444 tag); 1445 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1446 bootpc_tag_helper(tctx, 1447 (unsigned char *) bp->sname, 1448 sizeof(bp->sname), 1449 tag); 1450 1451 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1452 return NULL; 1453 tctx->buf[tctx->taglen] = '\0'; 1454 return tctx->buf; 1455} 1456 1457static void 1458bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, 1459 struct bootpc_globalcontext *gctx) 1460{ 1461 char *p; 1462 unsigned int ip; 1463 1464 ifctx->gotgw = 0; 1465 ifctx->gotnetmask = 0; 1466 1467 clear_sinaddr(&ifctx->myaddr); 1468 clear_sinaddr(&ifctx->netmask); 1469 clear_sinaddr(&ifctx->gw); 1470 1471 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; 1472 1473 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); 1474 1475 printf("%s at ", ifctx->ireq.ifr_name); 1476 print_sin_addr(&ifctx->myaddr); 1477 printf(" server "); 1478 print_in_addr(ifctx->reply.siaddr); 1479 1480 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1481 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1482 printf(" via gateway "); 1483 print_in_addr(ifctx->reply.giaddr); 1484 } 1485 1486 /* This call used for the side effect (overload flag) */ 1487 (void) bootpc_tag(&gctx->tmptag, 1488 &ifctx->reply, ifctx->replylen, TAG_END); 1489 1490 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1491 if (ifctx->reply.sname[0] != '\0') 1492 printf(" server name %s", ifctx->reply.sname); 1493 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1494 if (ifctx->reply.file[0] != '\0') 1495 printf(" boot file %s", ifctx->reply.file); 1496 1497 printf("\n"); 1498 1499 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1500 TAG_SUBNETMASK); 1501 if (p != NULL) { 1502 if (gctx->tag.taglen != 4) 1503 panic("bootpc: subnet mask len is %d", 1504 gctx->tag.taglen); 1505 bcopy(p, &ifctx->netmask.sin_addr, 4); 1506 ifctx->gotnetmask = 1; 1507 printf("subnet mask "); 1508 print_sin_addr(&ifctx->netmask); 1509 printf(" "); 1510 } 1511 1512 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1513 TAG_ROUTERS); 1514 if (p != NULL) { 1515 /* Routers */ 1516 if (gctx->tag.taglen % 4) 1517 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1518 if (gctx->tag.taglen > 0) { 1519 bcopy(p, &ifctx->gw.sin_addr, 4); 1520 printf("router "); 1521 print_sin_addr(&ifctx->gw); 1522 printf(" "); 1523 ifctx->gotgw = 1; 1524 gctx->gotgw = 1; 1525 } 1526 } 1527 1528 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1529 TAG_ROOT); 1530 if (p != NULL) { 1531 if (gctx->setrootfs != NULL) { 1532 printf("rootfs %s (ignored) ", p); 1533 } else if (setfs(&nd->root_saddr, 1534 nd->root_hostnam, p, &ifctx->reply.siaddr)) { 1535 if (*p == '/') { 1536 printf("root_server "); 1537 print_sin_addr(&nd->root_saddr); 1538 printf(" "); 1539 } 1540 printf("rootfs %s ", p); 1541 gctx->gotrootpath = 1; 1542 ifctx->gotrootpath = 1; 1543 gctx->setrootfs = ifctx; 1544 1545 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1546 ifctx->replylen, 1547 TAG_ROOTOPTS); 1548 if (p != NULL) { 1549 mountopts(&nd->root_args, p); 1550 printf("rootopts %s ", p); 1551 } 1552 } else 1553 panic("Failed to set rootfs to %s", p); 1554 } 1555 1556 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1557 TAG_HOSTNAME); 1558 if (p != NULL) { 1559 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1560 panic("bootpc: hostname >= %d bytes", 1561 MAXHOSTNAMELEN); 1562 if (gctx->sethostname != NULL) { 1563 printf("hostname %s (ignored) ", p); 1564 } else { 1565 strcpy(nd->my_hostnam, p); 1566 mtx_lock(&prison0.pr_mtx); 1567 strcpy(prison0.pr_host, p); 1568 mtx_unlock(&prison0.pr_mtx); 1569 printf("hostname %s ", p); 1570 gctx->sethostname = ifctx; 1571 } 1572 } 1573 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1574 TAG_COOKIE); 1575 if (p != NULL) { /* store in a sysctl variable */ 1576 int i, l = sizeof(bootp_cookie) - 1; 1577 for (i = 0; i < l && p[i] != '\0'; i++) 1578 bootp_cookie[i] = p[i]; 1579 p[i] = '\0'; 1580 } 1581 1582 1583 printf("\n"); 1584 1585 if (ifctx->gotnetmask == 0) { 1586 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1587 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1588 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1589 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1590 else 1591 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1592 } 1593 if (ifctx->gotgw == 0) { 1594 /* Use proxyarp */ 1595 ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr; 1596 } 1597} 1598 1599void 1600bootpc_init(void) 1601{ 1602 INIT_VNET_NET(curvnet); 1603 struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ 1604 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1605 struct ifnet *ifp; 1606 int error; 1607#ifndef BOOTP_WIRED_TO 1608 int ifcnt; 1609#endif 1610 struct nfsv3_diskless *nd; 1611 struct thread *td; 1612 1613 nd = &nfsv3_diskless; 1614 td = curthread; 1615 1616 /* 1617 * If already filled in, don't touch it here 1618 */ 1619 if (nfs_diskless_valid != 0) 1620 return; 1621 1622 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO); 1623 if (gctx == NULL) 1624 panic("Failed to allocate bootp global context structure"); 1625 1626 gctx->xid = ~0xFFFF; 1627 gctx->starttime = time_second; 1628 1629 /* 1630 * Find a network interface. 1631 */ 1632#ifdef BOOTP_WIRED_TO 1633 printf("bootpc_init: wired to interface '%s'\n", 1634 __XSTRING(BOOTP_WIRED_TO)); 1635 allocifctx(gctx); 1636#else 1637 /* 1638 * Preallocate interface context storage, if another interface 1639 * attaches and wins the race, it won't be eligible for bootp. 1640 */ 1641 IFNET_RLOCK(); 1642 for (ifp = TAILQ_FIRST(&V_ifnet), ifcnt = 0; 1643 ifp != NULL; 1644 ifp = TAILQ_NEXT(ifp, if_link)) { 1645 if ((ifp->if_flags & 1646 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1647 IFF_BROADCAST) 1648 continue; 1649 ifcnt++; 1650 } 1651 IFNET_RUNLOCK(); 1652 if (ifcnt == 0) 1653 panic("bootpc_init: no eligible interfaces"); 1654 for (; ifcnt > 0; ifcnt--) 1655 allocifctx(gctx); 1656#endif 1657 1658 IFNET_RLOCK(); 1659 for (ifp = TAILQ_FIRST(&V_ifnet), ifctx = gctx->interfaces; 1660 ifp != NULL && ifctx != NULL; 1661 ifp = TAILQ_NEXT(ifp, if_link)) { 1662 strlcpy(ifctx->ireq.ifr_name, ifp->if_xname, 1663 sizeof(ifctx->ireq.ifr_name)); 1664#ifdef BOOTP_WIRED_TO 1665 if (strcmp(ifctx->ireq.ifr_name, 1666 __XSTRING(BOOTP_WIRED_TO)) != 0) 1667 continue; 1668#else 1669 if ((ifp->if_flags & 1670 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1671 IFF_BROADCAST) 1672 continue; 1673#endif 1674 ifctx->ifp = ifp; 1675 ifctx = ifctx->next; 1676 } 1677 IFNET_RUNLOCK(); 1678 1679 if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) { 1680#ifdef BOOTP_WIRED_TO 1681 panic("bootpc_init: Could not find interface specified " 1682 "by BOOTP_WIRED_TO: " 1683 __XSTRING(BOOTP_WIRED_TO)); 1684#else 1685 panic("bootpc_init: no suitable interface"); 1686#endif 1687 } 1688 1689 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1690 bootpc_fakeup_interface(ifctx, gctx, td); 1691 1692 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1693 bootpc_compose_query(ifctx, gctx, td); 1694 1695 error = bootpc_call(gctx, td); 1696 1697 if (error != 0) { 1698#ifdef BOOTP_NFSROOT 1699 panic("BOOTP call failed"); 1700#else 1701 printf("BOOTP call failed\n"); 1702#endif 1703 } 1704 1705 rootdevnames[0] = "nfs:"; 1706 mountopts(&nd->root_args, NULL); 1707 1708 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1709 if (bootpc_ifctx_isresolved(ifctx) != 0) 1710 bootpc_decode_reply(nd, ifctx, gctx); 1711 1712#ifdef BOOTP_NFSROOT 1713 if (gctx->gotrootpath == 0) 1714 panic("bootpc: No root path offered"); 1715#endif 1716 1717 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 1718 bootpc_adjust_interface(ifctx, gctx, td); 1719 1720 soclose(ifctx->so); 1721 } 1722 1723 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1724 if (ifctx->gotrootpath != 0) 1725 break; 1726 if (ifctx == NULL) { 1727 for (ifctx = gctx->interfaces; 1728 ifctx != NULL; 1729 ifctx = ifctx->next) 1730 if (bootpc_ifctx_isresolved(ifctx) != 0) 1731 break; 1732 } 1733 if (ifctx == NULL) 1734 goto out; 1735 1736 if (gctx->gotrootpath != 0) { 1737 1738 setenv("boot.netif.name", ifctx->ifp->if_xname); 1739 1740 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1741 nd->root_fh, &nd->root_fhsize, 1742 &nd->root_args, td); 1743 if (error != 0) 1744 panic("nfs_boot: mountd root, error=%d", error); 1745 1746 nfs_diskless_valid = 3; 1747 } 1748 1749 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1750 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1751 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1752 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1753 ifctx->myaddr.sin_addr.s_addr | 1754 ~ ifctx->netmask.sin_addr.s_addr; 1755 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); 1756 1757out: 1758 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { 1759 nctx = ifctx->next; 1760 free(ifctx, M_TEMP); 1761 } 1762 free(gctx, M_TEMP); 1763} 1764 1765/* 1766 * RPC: mountd/mount 1767 * Given a server pathname, get an NFS file handle. 1768 * Also, sets sin->sin_port to the NFS service port. 1769 */ 1770static int 1771md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1772 struct nfs_args *args, struct thread *td) 1773{ 1774 struct mbuf *m; 1775 int error; 1776 int authunixok; 1777 int authcount; 1778 int authver; 1779 1780 /* XXX honor v2/v3 flags in args->flags? */ 1781#ifdef BOOTP_NFSV3 1782 /* First try NFS v3 */ 1783 /* Get port number for MOUNTD. */ 1784 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1785 &mdsin->sin_port, td); 1786 if (error == 0) { 1787 m = xdr_string_encode(path, strlen(path)); 1788 1789 /* Do RPC to mountd. */ 1790 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1791 RPCMNT_MOUNT, &m, NULL, td); 1792 } 1793 if (error == 0) { 1794 args->flags |= NFSMNT_NFSV3; 1795 } else { 1796#endif 1797 /* Fallback to NFS v2 */ 1798 1799 /* Get port number for MOUNTD. */ 1800 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1801 &mdsin->sin_port, td); 1802 if (error != 0) 1803 return error; 1804 1805 m = xdr_string_encode(path, strlen(path)); 1806 1807 /* Do RPC to mountd. */ 1808 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1809 RPCMNT_MOUNT, &m, NULL, td); 1810 if (error != 0) 1811 return error; /* message already freed */ 1812 1813#ifdef BOOTP_NFSV3 1814 } 1815#endif 1816 1817 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1818 goto bad; 1819 1820 if ((args->flags & NFSMNT_NFSV3) != 0) { 1821 if (xdr_int_decode(&m, fhsizep) != 0 || 1822 *fhsizep > NFSX_V3FHMAX || 1823 *fhsizep <= 0) 1824 goto bad; 1825 } else 1826 *fhsizep = NFSX_V2FH; 1827 1828 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1829 goto bad; 1830 1831 if (args->flags & NFSMNT_NFSV3) { 1832 if (xdr_int_decode(&m, &authcount) != 0) 1833 goto bad; 1834 authunixok = 0; 1835 if (authcount < 0 || authcount > 100) 1836 goto bad; 1837 while (authcount > 0) { 1838 if (xdr_int_decode(&m, &authver) != 0) 1839 goto bad; 1840 if (authver == RPCAUTH_UNIX) 1841 authunixok = 1; 1842 authcount--; 1843 } 1844 if (authunixok == 0) 1845 goto bad; 1846 } 1847 1848 /* Set port number for NFS use. */ 1849 error = krpc_portmap(mdsin, NFS_PROG, 1850 (args->flags & 1851 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1852 &mdsin->sin_port, td); 1853 1854 goto out; 1855 1856bad: 1857 error = EBADRPC; 1858 1859out: 1860 m_freem(m); 1861 return error; 1862} 1863 1864SYSINIT(bootp_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, bootpc_init, NULL);
|