Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/networking/udhcp/dhcpc.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/networking/udhcp/dhcpc.c
r3306 r3621 26 26 #include "dhcpc.h" 27 27 28 #include <asm/types.h> 29 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) 30 # include <netpacket/packet.h> 31 # include <net/ethernet.h> 32 #else 33 # include <linux/if_packet.h> 34 # include <linux/if_ether.h> 28 #include <netinet/if_ether.h> 29 #include <linux/filter.h> 30 #include <linux/if_packet.h> 31 32 #ifndef PACKET_AUXDATA 33 # define PACKET_AUXDATA 8 34 struct tpacket_auxdata { 35 uint32_t tp_status; 36 uint32_t tp_len; 37 uint32_t tp_snaplen; 38 uint16_t tp_mac; 39 uint16_t tp_net; 40 uint16_t tp_vlan_tci; 41 uint16_t tp_padding; 42 }; 35 43 #endif 36 #include <linux/filter.h> 44 37 45 38 46 /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ … … 61 69 "background\0" No_argument "b" 62 70 "broadcast\0" No_argument "B" 63 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument"a")71 IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") 64 72 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") 65 73 ; … … 102 110 103 111 /* get a rough idea of how long an option will be (rounding up...) */ 104 static const uint8_t len_of_option_as_string[] = {112 static const uint8_t len_of_option_as_string[] ALIGN1 = { 105 113 [OPTION_IP ] = sizeof("255.255.255.255 "), 106 114 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 107 115 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 108 [OPTION_6RD ] = sizeof(" 32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),116 [OPTION_6RD ] = sizeof("132 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "), 109 117 [OPTION_STRING ] = 1, 110 118 [OPTION_STRING_HOST ] = 1, … … 143 151 } 144 152 153 #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT 145 154 /* Check if a given label represents a valid DNS label 146 155 * Return pointer to the first character after the label upon success, … … 162 171 ch = *label; 163 172 if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { 164 if (pos == 0) {165 /* label must begin with letter */166 return NULL;167 }168 173 if (ch < '0' || ch > '9') { 169 174 if (ch == '\0' || ch == '.') … … 197 202 //return ((name - start) < 1025); /* NS_MAXDNAME */ 198 203 name++; 199 } 200 } 204 if (*name == '\0') 205 return 1; // We allow trailing dot too 206 } 207 } 208 #else 209 # define good_hostname(name) 1 210 #endif 201 211 202 212 /* Create "opt_name=opt_value" string */ … … 213 223 optlen = dhcp_option_lengths[type]; 214 224 upper_length = len_of_option_as_string[type] 215 * ((unsigned)(len + optlen - 1) / (unsigned)optlen);225 * ((unsigned)(len + optlen) / (unsigned)optlen); 216 226 217 227 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); … … 552 562 553 563 /* call script */ 554 log1(" Executing %s %s", client_config.script, name);564 log1("executing %s %s", client_config.script, name); 555 565 argv[0] = (char*) client_config.script; 556 566 argv[1] = (char*) name; … … 666 676 */ 667 677 668 static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet )678 static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip) 669 679 { 670 680 return udhcp_send_raw_packet(packet, 671 /*src*/ INADDR_ANY, CLIENT_PORT,681 /*src*/ src_nip, CLIENT_PORT, 672 682 /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, 673 683 client_config.ifindex); 684 } 685 686 static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) 687 { 688 if (server) 689 return udhcp_send_kernel_packet(packet, 690 ciaddr, CLIENT_PORT, 691 server, SERVER_PORT); 692 return raw_bcast_from_client_config_ifindex(packet, ciaddr); 674 693 } 675 694 … … 696 715 add_client_options(&packet); 697 716 698 bb_ info_msg("Sending discover...");699 return raw_bcast_from_client_config_ifindex(&packet );717 bb_error_msg("sending %s", "discover"); 718 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); 700 719 } 701 720 … … 740 759 741 760 addr.s_addr = requested; 742 bb_ info_msg("Sending select for %s...", inet_ntoa(addr));743 return raw_bcast_from_client_config_ifindex(&packet );761 bb_error_msg("sending select for %s", inet_ntoa(addr)); 762 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); 744 763 } 745 764 … … 779 798 add_client_options(&packet); 780 799 781 bb_info_msg("Sending renew..."); 782 if (server) 783 return udhcp_send_kernel_packet(&packet, 784 ciaddr, CLIENT_PORT, 785 server, SERVER_PORT); 786 return raw_bcast_from_client_config_ifindex(&packet); 800 bb_error_msg("sending %s", "renew"); 801 return bcast_or_ucast(&packet, ciaddr, server); 787 802 } 788 803 … … 812 827 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 813 828 814 bb_ info_msg("Sending decline...");815 return raw_bcast_from_client_config_ifindex(&packet );829 bb_error_msg("sending %s", "decline"); 830 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); 816 831 } 817 832 #endif … … 832 847 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 833 848 834 bb_info_msg("Sending release..."); 835 return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); 849 bb_error_msg("sending %s", "release"); 850 /* Note: normally we unicast here since "server" is not zero. 851 * However, there _are_ people who run "address-less" DHCP servers, 852 * and reportedly ISC dhcp client and Windows allow that. 853 */ 854 return bcast_or_ucast(&packet, ciaddr, server); 836 855 } 837 856 … … 843 862 struct ip_udp_dhcp_packet packet; 844 863 uint16_t check; 845 #ifdef PACKET_AUXDATA846 864 unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; 847 struct cmsghdr *cmsg;848 #endif849 865 struct iovec iov; 850 866 struct msghdr msg; 851 852 #ifdef PACKET_AUXDATA 867 struct cmsghdr *cmsg; 868 853 869 /* used to use just safe_read(fd, &packet, sizeof(packet)) 854 870 * but we need to check for TP_STATUS_CSUMNOTREADY :( … … 866 882 if (errno == EINTR) 867 883 continue; 868 log1(" Packet read error, ignoring");884 log1("packet read error, ignoring"); 869 885 /* NB: possible down interface, etc. Caller should pause. */ 870 886 return bytes; /* returns -1 */ … … 872 888 break; 873 889 } 874 #else875 memset(&packet, 0, sizeof(packet));876 bytes = safe_read(fd, &packet, sizeof(packet));877 if (bytes < 0) {878 log1("Packet read error, ignoring");879 /* NB: possible down interface, etc. Caller should pause. */880 return bytes; /* returns -1 */881 }882 #endif883 890 884 891 if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { 885 log1(" Packet is too short, ignoring");892 log1("packet is too short, ignoring"); 886 893 return -2; 887 894 } … … 889 896 if (bytes < ntohs(packet.ip.tot_len)) { 890 897 /* packet is bigger than sizeof(packet), we did partial read */ 891 log1(" Oversized packet, ignoring");898 log1("oversized packet, ignoring"); 892 899 return -2; 893 900 } … … 904 911 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) 905 912 ) { 906 log1(" Unrelated/bogus packet, ignoring");913 log1("unrelated/bogus packet, ignoring"); 907 914 return -2; 908 915 } … … 912 919 packet.ip.check = 0; 913 920 if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { 914 log1(" Bad IP header checksum, ignoring");921 log1("bad IP header checksum, ignoring"); 915 922 return -2; 916 923 } 917 924 918 #ifdef PACKET_AUXDATA919 925 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 920 926 if (cmsg->cmsg_level == SOL_PACKET … … 930 936 } 931 937 } 932 #endif933 938 934 939 /* verify UDP checksum. IP header has to be modified for this */ … … 939 944 packet.udp.check = 0; 940 945 if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { 941 log1(" Packet with bad UDP checksum received, ignoring");946 log1("packet with bad UDP checksum received, ignoring"); 942 947 return -2; 943 948 } 944 #ifdef PACKET_AUXDATA945 949 skip_udp_sum_check: 946 #endif947 950 948 951 if (packet.data.cookie != htonl(DHCP_MAGIC)) { 949 bb_ info_msg("Packet with bad magic, ignoring");952 bb_error_msg("packet with bad magic, ignoring"); 950 953 return -2; 951 954 } 952 955 953 log1(" Receiveda packet");956 log1("received %s", "a packet"); 954 957 udhcp_dump_packet(&packet.data); 955 958 … … 990 993 struct sockaddr_ll sock; 991 994 992 /* 993 * Comment: 994 * 995 * I've selected not to see LL header, so BPF doesn't see it, too. 996 * The filter may also pass non-IP and non-ARP packets, but we do 997 * a more complete check when receiving the message in userspace. 998 * 999 * and filter shamelessly stolen from: 1000 * 1001 * http://www.flamewarmaster.de/software/dhcpclient/ 1002 * 1003 * There are a few other interesting ideas on that page (look under 1004 * "Motivation"). Use of netlink events is most interesting. Think 1005 * of various network servers listening for events and reconfiguring. 1006 * That would obsolete sending HUP signals and/or make use of restarts. 1007 * 1008 * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>. 1009 * License: GPL v2. 1010 * 1011 * TODO: make conditional? 995 log1("opening raw socket on ifindex %d", ifindex); //log2? 996 997 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 998 /* ^^^^^ 999 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) 1000 * ETH_P_IP: want to receive only packets with IPv4 eth type 1012 1001 */ 1013 static const struct sock_filter filter_instr[] = { 1014 /* load 9th byte (protocol) */ 1015 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9), 1016 /* jump to L1 if it is IPPROTO_UDP, else to L4 */ 1017 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6), 1018 /* L1: load halfword from offset 6 (flags and frag offset) */ 1019 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6), 1020 /* jump to L4 if any bits in frag offset field are set, else to L2 */ 1021 BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0), 1022 /* L2: skip IP header (load index reg with header len) */ 1023 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), 1024 /* load udp destination port from halfword[header_len + 2] */ 1025 BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2), 1026 /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */ 1027 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1), 1028 /* L3: accept packet */ 1029 BPF_STMT(BPF_RET|BPF_K, 0xffffffff), 1030 /* L4: discard packet */ 1031 BPF_STMT(BPF_RET|BPF_K, 0), 1032 }; 1033 static const struct sock_fprog filter_prog = { 1034 .len = sizeof(filter_instr) / sizeof(filter_instr[0]), 1035 /* casting const away: */ 1036 .filter = (struct sock_filter *) filter_instr, 1037 }; 1038 1039 log1("Opening raw socket on ifindex %d", ifindex); //log2? 1040 1041 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 1042 log1("Got raw socket fd"); //log2? 1002 log1("got raw socket fd"); //log2? 1043 1003 1044 1004 sock.sll_family = AF_PACKET; … … 1047 1007 xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); 1048 1008 1009 #if 0 /* Several users reported breakage when BPF filter is used */ 1049 1010 if (CLIENT_PORT == 68) { 1050 1011 /* Use only if standard port is in use */ 1012 /* 1013 * I've selected not to see LL header, so BPF doesn't see it, too. 1014 * The filter may also pass non-IP and non-ARP packets, but we do 1015 * a more complete check when receiving the message in userspace. 1016 * 1017 * and filter shamelessly stolen from: 1018 * 1019 * http://www.flamewarmaster.de/software/dhcpclient/ 1020 * 1021 * There are a few other interesting ideas on that page (look under 1022 * "Motivation"). Use of netlink events is most interesting. Think 1023 * of various network servers listening for events and reconfiguring. 1024 * That would obsolete sending HUP signals and/or make use of restarts. 1025 * 1026 * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>. 1027 * License: GPL v2. 1028 */ 1029 static const struct sock_filter filter_instr[] = { 1030 /* load 9th byte (protocol) */ 1031 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9), 1032 /* jump to L1 if it is IPPROTO_UDP, else to L4 */ 1033 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6), 1034 /* L1: load halfword from offset 6 (flags and frag offset) */ 1035 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6), 1036 /* jump to L4 if any bits in frag offset field are set, else to L2 */ 1037 BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0), 1038 /* L2: skip IP header (load index reg with header len) */ 1039 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), 1040 /* load udp destination port from halfword[header_len + 2] */ 1041 BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2), 1042 /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */ 1043 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1), 1044 /* L3: accept packet ("accept 0x7fffffff bytes") */ 1045 /* Accepting 0xffffffff works too but kernel 2.6.19 is buggy */ 1046 BPF_STMT(BPF_RET|BPF_K, 0x7fffffff), 1047 /* L4: discard packet ("accept zero bytes") */ 1048 BPF_STMT(BPF_RET|BPF_K, 0), 1049 }; 1050 static const struct sock_fprog filter_prog = { 1051 .len = sizeof(filter_instr) / sizeof(filter_instr[0]), 1052 /* casting const away: */ 1053 .filter = (struct sock_filter *) filter_instr, 1054 }; 1051 1055 /* Ignoring error (kernel may lack support for this) */ 1052 1056 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, 1053 1057 sizeof(filter_prog)) >= 0) 1054 log1("Attached filter to raw socket fd"); // log? 1055 } 1056 1057 #ifdef PACKET_AUXDATA 1058 if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, 1059 &const_int_1, sizeof(int)) < 0 1060 ) { 1058 log1("attached filter to raw socket fd"); // log? 1059 } 1060 #endif 1061 1062 if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) { 1061 1063 if (errno != ENOPROTOOPT) 1062 log1("Can't set PACKET_AUXDATA on raw socket"); 1063 } 1064 #else 1065 sock.sll_family = AF_PACKET; 1066 sock.sll_protocol = htons(ETH_P_IP); 1067 sock.sll_ifindex = ifindex; 1068 xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); 1069 #endif 1070 1071 log1("Created raw socket"); 1064 log1("can't set PACKET_AUXDATA on raw socket"); 1065 } 1066 1067 log1("created raw socket"); 1072 1068 1073 1069 return fd; … … 1076 1072 static void change_listen_mode(int new_mode) 1077 1073 { 1078 log1(" Entering listen mode: %s",1074 log1("entering listen mode: %s", 1079 1075 new_mode != LISTEN_NONE 1080 1076 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw") … … 1097 1093 static void perform_renew(void) 1098 1094 { 1099 bb_ info_msg("Performing aDHCP renew");1095 bb_error_msg("performing DHCP renew"); 1100 1096 switch (state) { 1101 1097 case BOUND: … … 1127 1123 strcpy(buffer, inet_ntoa(temp_addr)); 1128 1124 temp_addr.s_addr = requested_ip; 1129 bb_ info_msg("Unicasting a release of %s to %s",1125 bb_error_msg("unicasting a release of %s to %s", 1130 1126 inet_ntoa(temp_addr), buffer); 1131 1127 send_release(server_addr, requested_ip); /* unicast */ 1132 1128 udhcp_run_script(NULL, "deconfig"); 1133 1129 } 1134 bb_ info_msg("Entering released state");1130 bb_error_msg("entering released state"); 1135 1131 1136 1132 change_listen_mode(LISTEN_NONE); … … 1165 1161 //usage:#endif 1166 1162 //usage:#define udhcpc_trivial_usage 1167 //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" 1168 //usage: " [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") 1163 //usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n" 1164 //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" 1165 //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." 1169 1166 //usage:#define udhcpc_full_usage "\n" 1170 1167 //usage: IF_LONG_OPTS( 1171 1168 //usage: "\n -i,--interface IFACE Interface to use (default eth0)" 1169 //usage: IF_FEATURE_UDHCP_PORT( 1170 //usage: "\n -P,--client-port PORT Use PORT (default 68)" 1171 //usage: ) 1172 //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 1172 1173 //usage: "\n -p,--pidfile FILE Create pidfile" 1173 //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"1174 1174 //usage: "\n -B,--broadcast Request broadcast replies" 1175 //usage: "\n -t,--retries N Send up to N discover packets" 1176 //usage: "\n -T,--timeout N Pause between packets (default 3 seconds)" 1177 //usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)" 1175 //usage: "\n -t,--retries N Send up to N discover packets (default 3)" 1176 //usage: "\n -T,--timeout SEC Pause between packets (default 3)" 1177 //usage: "\n -A,--tryagain SEC Wait if lease is not obtained (default 20)" 1178 //usage: "\n -n,--now Exit if lease is not obtained" 1179 //usage: "\n -q,--quit Exit after obtaining lease" 1180 //usage: "\n -R,--release Release IP on exit" 1178 1181 //usage: "\n -f,--foreground Run in foreground" 1179 1182 //usage: USE_FOR_MMU( 1180 1183 //usage: "\n -b,--background Background if lease is not obtained" 1181 1184 //usage: ) 1182 //usage: "\n -n,--now Exit if lease is not obtained"1183 //usage: "\n -q,--quit Exit after obtaining lease"1184 //usage: "\n -R,--release Release IP on exit"1185 1185 //usage: "\n -S,--syslog Log to syslog too" 1186 //usage: IF_FEATURE_UDHCP _PORT(1187 //usage: "\n - P,--client-port N Use port N (default 68)"1186 //usage: IF_FEATURE_UDHCPC_ARPING( 1187 //usage: "\n -a[MSEC],--arping[=MSEC] Validate offered address with ARP ping" 1188 1188 //usage: ) 1189 //usage: IF_FEATURE_UDHCPC_ARPING( 1190 //usage: "\n -a,--arping Use arping to validate offered address" 1191 //usage: ) 1189 //usage: "\n -r,--request IP Request this IP address" 1190 //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" 1192 1191 //usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)" 1193 //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)"1194 //usage: "\n -r,--request IP Request this IP address"1195 1192 //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" 1196 1193 //usage: "\n Examples of string, numeric, and hex byte opts:" … … 1207 1204 //usage: IF_NOT_LONG_OPTS( 1208 1205 //usage: "\n -i IFACE Interface to use (default eth0)" 1206 //usage: IF_FEATURE_UDHCP_PORT( 1207 //usage: "\n -P PORT Use PORT (default 68)" 1208 //usage: ) 1209 //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 1209 1210 //usage: "\n -p FILE Create pidfile" 1210 //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"1211 1211 //usage: "\n -B Request broadcast replies" 1212 //usage: "\n -t N Send up to N discover packets" 1213 //usage: "\n -T N Pause between packets (default 3 seconds)" 1214 //usage: "\n -A N Wait N seconds (default 20) after failure" 1212 //usage: "\n -t N Send up to N discover packets (default 3)" 1213 //usage: "\n -T SEC Pause between packets (default 3)" 1214 //usage: "\n -A SEC Wait if lease is not obtained (default 20)" 1215 //usage: "\n -n Exit if lease is not obtained" 1216 //usage: "\n -q Exit after obtaining lease" 1217 //usage: "\n -R Release IP on exit" 1215 1218 //usage: "\n -f Run in foreground" 1216 1219 //usage: USE_FOR_MMU( 1217 1220 //usage: "\n -b Background if lease is not obtained" 1218 1221 //usage: ) 1219 //usage: "\n -n Exit if lease is not obtained"1220 //usage: "\n -q Exit after obtaining lease"1221 //usage: "\n -R Release IP on exit"1222 1222 //usage: "\n -S Log to syslog too" 1223 //usage: IF_FEATURE_UDHCP _PORT(1224 //usage: "\n - P N Use port N (default 68)"1223 //usage: IF_FEATURE_UDHCPC_ARPING( 1224 //usage: "\n -a[MSEC] Validate offered address with ARP ping" 1225 1225 //usage: ) 1226 //usage: IF_FEATURE_UDHCPC_ARPING( 1227 //usage: "\n -a Use arping to validate offered address" 1228 //usage: ) 1226 //usage: "\n -r IP Request this IP address" 1227 //usage: "\n -o Don't request any options (unless -O is given)" 1229 1228 //usage: "\n -O OPT Request option OPT from server (cumulative)" 1230 //usage: "\n -o Don't request any options (unless -O is given)"1231 //usage: "\n -r IP Request this IP address"1232 1229 //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" 1233 1230 //usage: "\n Examples of string, numeric, and hex byte opts:" … … 1250 1247 int udhcpc_main(int argc UNUSED_PARAM, char **argv) 1251 1248 { 1252 uint8_t * temp, *message;1249 uint8_t *message; 1253 1250 const char *str_V, *str_h, *str_F, *str_r; 1251 IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";) 1254 1252 IF_FEATURE_UDHCP_PORT(char *str_P;) 1255 1253 void *clientid_mac_ptr; … … 1266 1264 unsigned already_waited_sec; 1267 1265 unsigned opt; 1266 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) 1268 1267 int max_fd; 1269 1268 int retval; 1270 1269 fd_set rfds; 1270 1271 setup_common_bufsiz(); 1271 1272 1272 1273 /* Default options */ … … 1283 1284 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" 1284 1285 USE_FOR_MMU("b") 1285 IF_FEATURE_UDHCPC_ARPING("a ")1286 IF_FEATURE_UDHCPC_ARPING("a::") 1286 1287 IF_FEATURE_UDHCP_PORT("P:") 1287 1288 "v" … … 1292 1293 , &list_O 1293 1294 , &list_x 1295 IF_FEATURE_UDHCPC_ARPING(, &str_a) 1294 1296 IF_FEATURE_UDHCP_PORT(, &str_P) 1295 1297 IF_UDHCP_VERBOSE(, &dhcp_verbose) … … 1323 1325 } 1324 1326 #endif 1327 IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);) 1325 1328 while (list_O) { 1326 1329 char *optstr = llist_pop(&list_O); … … 1395 1398 write_pidfile(client_config.pidfile); 1396 1399 /* Goes to stdout (unless NOMMU) and possibly syslog */ 1397 bb_ info_msg("%s (v"BB_VER") started", applet_name);1400 bb_error_msg("started, v"BB_VER); 1398 1401 /* Set up the signal pipe */ 1399 1402 udhcp_sp_setup(); … … 1434 1437 /* If we already timed out, fall through with retval = 0, else... */ 1435 1438 if ((int)tv.tv_sec > 0) { 1436 log1(" Waiting on select %u seconds", (int)tv.tv_sec);1439 log1("waiting on select %u seconds", (int)tv.tv_sec); 1437 1440 timestamp_before_wait = (unsigned)monotonic_sec(); 1438 1441 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); … … 1485 1488 #if BB_MMU /* -b is not supported on NOMMU */ 1486 1489 if (opt & OPT_b) { /* background if no lease */ 1487 bb_ info_msg("No lease, forking to background");1490 bb_error_msg("no lease, forking to background"); 1488 1491 client_background(); 1489 1492 /* do not background again! */ … … 1492 1495 #endif 1493 1496 if (opt & OPT_n) { /* abort if no lease */ 1494 bb_ info_msg("No lease, failing");1497 bb_error_msg("no lease, failing"); 1495 1498 retval = 1; 1496 1499 goto ret; … … 1501 1504 continue; 1502 1505 case REQUESTING: 1503 if ( !discover_retries || packet_num < discover_retries) {1506 if (packet_num < 3) { 1504 1507 /* send broadcast select packet */ 1505 1508 send_select(xid, server_addr, requested_ip); … … 1520 1523 client_config.first_secs = 0; /* make secs field count from 0 */ 1521 1524 change_listen_mode(LISTEN_KERNEL); 1522 log1(" Entering renew state");1525 log1("entering renew state"); 1523 1526 /* fall right through */ 1524 1527 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ … … 1540 1543 } 1541 1544 /* Timed out, enter rebinding state */ 1542 log1(" Entering rebinding state");1545 log1("entering rebinding state"); 1543 1546 state = REBINDING; 1544 1547 /* fall right through */ … … 1555 1558 } 1556 1559 /* Timed out, enter init state */ 1557 bb_ info_msg("Lease lost, entering init state");1560 bb_error_msg("lease lost, entering init state"); 1558 1561 udhcp_run_script(NULL, "deconfig"); 1559 1562 state = INIT_SELECTING; … … 1603 1606 continue; 1604 1607 case SIGTERM: 1605 bb_ info_msg("ReceivedSIGTERM");1608 bb_error_msg("received %s", "SIGTERM"); 1606 1609 goto ret0; 1607 1610 } … … 1621 1624 if (len == -1) { 1622 1625 /* Error is severe, reopen socket */ 1623 bb_ info_msg("Read error: %s, reopening socket", strerror(errno));1626 bb_error_msg("read error: %s, reopening socket", strerror(errno)); 1624 1627 sleep(discover_timeout); /* 3 seconds by default */ 1625 1628 change_listen_mode(listen_mode); /* just close and reopen */ … … 1658 1661 /* Must be a DHCPOFFER */ 1659 1662 if (*message == DHCPOFFER) { 1663 uint8_t *temp; 1664 1660 1665 /* What exactly is server's IP? There are several values. 1661 1666 * Example DHCP offer captured with tchdump: … … 1677 1682 * "Next server" and router are definitely wrong ones to use, though... 1678 1683 */ 1684 /* We used to ignore pcakets without DHCP_SERVER_ID. 1685 * I've got user reports from people who run "address-less" servers. 1686 * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all. 1687 * They say ISC DHCP client supports this case. 1688 */ 1689 server_addr = 0; 1679 1690 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1680 1691 if (!temp) { 1681 bb_error_msg("no server ID, ignoring packet"); 1682 continue; 1683 /* still selecting - this server looks bad */ 1692 bb_error_msg("no server ID, using 0.0.0.0"); 1693 } else { 1694 /* it IS unaligned sometimes, don't "optimize" */ 1695 move_from_unaligned32(server_addr, temp); 1684 1696 } 1685 /* it IS unaligned sometimes, don't "optimize" */1686 move_from_unaligned32(server_addr, temp);1687 1697 /*xid = packet.xid; - already is */ 1688 1698 requested_ip = packet.yiaddr; … … 1700 1710 case REBINDING: 1701 1711 if (*message == DHCPACK) { 1712 unsigned start; 1702 1713 uint32_t lease_seconds; 1703 1714 struct in_addr temp_addr; 1715 uint8_t *temp; 1704 1716 1705 1717 temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); … … 1732 1744 (uint32_t) 0, 1733 1745 client_config.client_mac, 1734 client_config.interface) 1746 client_config.interface, 1747 arpping_ms) 1735 1748 ) { 1736 bb_ info_msg("Offered address is in use "1749 bb_error_msg("offered address is in use " 1737 1750 "(got ARP reply), declining"); 1738 1751 send_decline(/*xid,*/ server_addr, packet.yiaddr); … … 1752 1765 #endif 1753 1766 /* enter bound state */ 1754 timeout = lease_seconds / 2;1755 1767 temp_addr.s_addr = packet.yiaddr; 1756 bb_ info_msg("Lease of %s obtained, lease time %u",1768 bb_error_msg("lease of %s obtained, lease time %u", 1757 1769 inet_ntoa(temp_addr), (unsigned)lease_seconds); 1758 1770 requested_ip = packet.yiaddr; 1771 1772 start = monotonic_sec(); 1759 1773 udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); 1774 already_waited_sec = (unsigned)monotonic_sec() - start; 1775 timeout = lease_seconds / 2; 1776 if ((unsigned)timeout < already_waited_sec) { 1777 /* Something went wrong. Back to discover state */ 1778 timeout = already_waited_sec = 0; 1779 } 1760 1780 1761 1781 state = BOUND; … … 1775 1795 /* make future renew packets use different xid */ 1776 1796 /* xid = random_xid(); ...but why bother? */ 1777 already_waited_sec = 0; 1797 1778 1798 continue; /* back to main loop */ 1779 1799 } 1780 1800 if (*message == DHCPNAK) { 1801 /* If network has more than one DHCP server, 1802 * "wrong" server can reply first, with a NAK. 1803 * Do not interpret it as a NAK from "our" server. 1804 */ 1805 if (server_addr != 0) { 1806 uint32_t svid; 1807 uint8_t *temp; 1808 1809 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1810 if (!temp) { 1811 non_matching_svid: 1812 log1("%s with wrong server ID, ignoring packet", 1813 "Received DHCP NAK" 1814 ); 1815 continue; 1816 } 1817 move_from_unaligned32(svid, temp); 1818 if (svid != server_addr) 1819 goto non_matching_svid; 1820 } 1781 1821 /* return to init state */ 1782 bb_ info_msg("ReceivedDHCP NAK");1822 bb_error_msg("received %s", "DHCP NAK"); 1783 1823 udhcp_run_script(&packet, "nak"); 1784 1824 if (state != REQUESTING)
Note:
See TracChangeset
for help on using the changeset viewer.