diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 168 |
1 files changed, 112 insertions, 56 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 3d4c397ff..2f2016cd5 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <netpacket/packet.h> | 29 | #include <netpacket/packet.h> |
30 | #include <linux/filter.h> | 30 | #include <linux/filter.h> |
31 | 31 | ||
32 | /* struct client_config_t client_config is in bb_common_bufsiz1 */ | 32 | /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ |
33 | 33 | ||
34 | 34 | ||
35 | #if ENABLE_LONG_OPTS | 35 | #if ENABLE_LONG_OPTS |
@@ -46,7 +46,6 @@ static const char udhcpc_longopts[] ALIGN1 = | |||
46 | "request\0" Required_argument "r" | 46 | "request\0" Required_argument "r" |
47 | "script\0" Required_argument "s" | 47 | "script\0" Required_argument "s" |
48 | "timeout\0" Required_argument "T" | 48 | "timeout\0" Required_argument "T" |
49 | "version\0" No_argument "v" | ||
50 | "retries\0" Required_argument "t" | 49 | "retries\0" Required_argument "t" |
51 | "tryagain\0" Required_argument "A" | 50 | "tryagain\0" Required_argument "A" |
52 | "syslog\0" No_argument "S" | 51 | "syslog\0" No_argument "S" |
@@ -124,24 +123,6 @@ static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) | |||
124 | return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); | 123 | return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); |
125 | } | 124 | } |
126 | 125 | ||
127 | static int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) | ||
128 | { | ||
129 | char hexstrbuf[16 * 2]; | ||
130 | bin2hex(hexstrbuf, (void*)ip, 16); | ||
131 | return sprintf(dest, /* "%s" */ | ||
132 | "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s", | ||
133 | /* pre, */ | ||
134 | hexstrbuf + 0 * 4, | ||
135 | hexstrbuf + 1 * 4, | ||
136 | hexstrbuf + 2 * 4, | ||
137 | hexstrbuf + 3 * 4, | ||
138 | hexstrbuf + 4 * 4, | ||
139 | hexstrbuf + 5 * 4, | ||
140 | hexstrbuf + 6 * 4, | ||
141 | hexstrbuf + 7 * 4 | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | /* really simple implementation, just count the bits */ | 126 | /* really simple implementation, just count the bits */ |
146 | static int mton(uint32_t mask) | 127 | static int mton(uint32_t mask) |
147 | { | 128 | { |
@@ -154,6 +135,63 @@ static int mton(uint32_t mask) | |||
154 | return i; | 135 | return i; |
155 | } | 136 | } |
156 | 137 | ||
138 | /* Check if a given label represents a valid DNS label | ||
139 | * Return pointer to the first character after the label upon success, | ||
140 | * NULL otherwise. | ||
141 | * See RFC1035, 2.3.1 | ||
142 | */ | ||
143 | /* We don't need to be particularly anal. For example, allowing _, hyphen | ||
144 | * at the end, or leading and trailing dots would be ok, since it | ||
145 | * can't be used for attacks. (Leading hyphen can be, if someone uses | ||
146 | * cmd "$hostname" | ||
147 | * in the script: then hostname may be treated as an option) | ||
148 | */ | ||
149 | static const char *valid_domain_label(const char *label) | ||
150 | { | ||
151 | unsigned char ch; | ||
152 | unsigned pos = 0; | ||
153 | |||
154 | for (;;) { | ||
155 | ch = *label; | ||
156 | if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { | ||
157 | if (pos == 0) { | ||
158 | /* label must begin with letter */ | ||
159 | return NULL; | ||
160 | } | ||
161 | if (ch < '0' || ch > '9') { | ||
162 | if (ch == '\0' || ch == '.') | ||
163 | return label; | ||
164 | /* DNS allows only '-', but we are more permissive */ | ||
165 | if (ch != '-' && ch != '_') | ||
166 | return NULL; | ||
167 | } | ||
168 | } | ||
169 | label++; | ||
170 | pos++; | ||
171 | //Do we want this? | ||
172 | //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ | ||
173 | // return NULL; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* Check if a given name represents a valid DNS name */ | ||
178 | /* See RFC1035, 2.3.1 */ | ||
179 | static int good_hostname(const char *name) | ||
180 | { | ||
181 | //const char *start = name; | ||
182 | |||
183 | for (;;) { | ||
184 | name = valid_domain_label(name); | ||
185 | if (!name) | ||
186 | return 0; | ||
187 | if (!name[0]) | ||
188 | return 1; | ||
189 | //Do we want this? | ||
190 | //return ((name - start) < 1025); /* NS_MAXDNAME */ | ||
191 | name++; | ||
192 | } | ||
193 | } | ||
194 | |||
157 | /* Create "opt_name=opt_value" string */ | 195 | /* Create "opt_name=opt_value" string */ |
158 | static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) | 196 | static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) |
159 | { | 197 | { |
@@ -206,8 +244,11 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
206 | * the case of list of options. | 244 | * the case of list of options. |
207 | */ | 245 | */ |
208 | case OPTION_STRING: | 246 | case OPTION_STRING: |
247 | case OPTION_STRING_HOST: | ||
209 | memcpy(dest, option, len); | 248 | memcpy(dest, option, len); |
210 | dest[len] = '\0'; | 249 | dest[len] = '\0'; |
250 | if (type == OPTION_STRING_HOST && !good_hostname(dest)) | ||
251 | safe_strncpy(dest, "bad", len); | ||
211 | return ret; | 252 | return ret; |
212 | case OPTION_STATIC_ROUTES: { | 253 | case OPTION_STATIC_ROUTES: { |
213 | /* Option binary format: | 254 | /* Option binary format: |
@@ -387,6 +428,7 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
387 | /* +1 element for each option, +2 for subnet option: */ | 428 | /* +1 element for each option, +2 for subnet option: */ |
388 | if (packet) { | 429 | if (packet) { |
389 | /* note: do not search for "pad" (0) and "end" (255) options */ | 430 | /* note: do not search for "pad" (0) and "end" (255) options */ |
431 | //TODO: change logic to scan packet _once_ | ||
390 | for (i = 1; i < 255; i++) { | 432 | for (i = 1; i < 255; i++) { |
391 | temp = udhcp_get_option(packet, i); | 433 | temp = udhcp_get_option(packet, i); |
392 | if (temp) { | 434 | if (temp) { |
@@ -499,9 +541,6 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | |||
499 | char **envp, **curr; | 541 | char **envp, **curr; |
500 | char *argv[3]; | 542 | char *argv[3]; |
501 | 543 | ||
502 | if (client_config.script == NULL) | ||
503 | return; | ||
504 | |||
505 | envp = fill_envp(packet); | 544 | envp = fill_envp(packet); |
506 | 545 | ||
507 | /* call script */ | 546 | /* call script */ |
@@ -598,6 +637,12 @@ static void add_client_options(struct dhcp_packet *packet) | |||
598 | // if (client_config.boot_file) | 637 | // if (client_config.boot_file) |
599 | // strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1); | 638 | // strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1); |
600 | } | 639 | } |
640 | |||
641 | // This will be needed if we remove -V VENDOR_STR in favor of | ||
642 | // -x vendor:VENDOR_STR | ||
643 | //if (!udhcp_find_option(packet.options, DHCP_VENDOR)) | ||
644 | // /* not set, set the default vendor ID */ | ||
645 | // ...add (DHCP_VENDOR, "udhcp "BB_VER) opt... | ||
601 | } | 646 | } |
602 | 647 | ||
603 | /* RFC 2131 | 648 | /* RFC 2131 |
@@ -742,7 +787,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
742 | #if ENABLE_FEATURE_UDHCPC_ARPING | 787 | #if ENABLE_FEATURE_UDHCPC_ARPING |
743 | /* Broadcast a DHCP decline message */ | 788 | /* Broadcast a DHCP decline message */ |
744 | /* NOINLINE: limit stack usage in caller */ | 789 | /* NOINLINE: limit stack usage in caller */ |
745 | static NOINLINE int send_decline(uint32_t xid, uint32_t server, uint32_t requested) | 790 | static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t requested) |
746 | { | 791 | { |
747 | struct dhcp_packet packet; | 792 | struct dhcp_packet packet; |
748 | 793 | ||
@@ -751,12 +796,14 @@ static NOINLINE int send_decline(uint32_t xid, uint32_t server, uint32_t request | |||
751 | */ | 796 | */ |
752 | init_packet(&packet, DHCPDECLINE); | 797 | init_packet(&packet, DHCPDECLINE); |
753 | 798 | ||
799 | #if 0 | ||
754 | /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client, | 800 | /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client, |
755 | * but in case the server is buggy and wants DHCPDECLINE's xid | 801 | * but in case the server is buggy and wants DHCPDECLINE's xid |
756 | * to match the xid which started entire handshake, | 802 | * to match the xid which started entire handshake, |
757 | * we use the same xid we used in initial DHCPDISCOVER: | 803 | * we use the same xid we used in initial DHCPDISCOVER: |
758 | */ | 804 | */ |
759 | packet.xid = xid; | 805 | packet.xid = xid; |
806 | #endif | ||
760 | /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ | 807 | /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ |
761 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 808 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
762 | 809 | ||
@@ -794,7 +841,6 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
794 | struct ip_udp_dhcp_packet packet; | 841 | struct ip_udp_dhcp_packet packet; |
795 | uint16_t check; | 842 | uint16_t check; |
796 | 843 | ||
797 | memset(&packet, 0, sizeof(packet)); | ||
798 | bytes = safe_read(fd, &packet, sizeof(packet)); | 844 | bytes = safe_read(fd, &packet, sizeof(packet)); |
799 | if (bytes < 0) { | 845 | if (bytes < 0) { |
800 | log1("Packet read error, ignoring"); | 846 | log1("Packet read error, ignoring"); |
@@ -852,7 +898,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
852 | return -2; | 898 | return -2; |
853 | } | 899 | } |
854 | 900 | ||
855 | log1("Got valid DHCP packet"); | 901 | log1("Received a packet"); |
856 | udhcp_dump_packet(&packet.data); | 902 | udhcp_dump_packet(&packet.data); |
857 | 903 | ||
858 | bytes -= sizeof(packet.ip) + sizeof(packet.udp); | 904 | bytes -= sizeof(packet.ip) + sizeof(packet.udp); |
@@ -1004,7 +1050,7 @@ static void perform_renew(void) | |||
1004 | } | 1050 | } |
1005 | } | 1051 | } |
1006 | 1052 | ||
1007 | static void perform_release(uint32_t requested_ip, uint32_t server_addr) | 1053 | static void perform_release(uint32_t server_addr, uint32_t requested_ip) |
1008 | { | 1054 | { |
1009 | char buffer[sizeof("255.255.255.255")]; | 1055 | char buffer[sizeof("255.255.255.255")]; |
1010 | struct in_addr temp_addr; | 1056 | struct in_addr temp_addr; |
@@ -1053,7 +1099,7 @@ static void client_background(void) | |||
1053 | //usage:#endif | 1099 | //usage:#endif |
1054 | //usage:#define udhcpc_trivial_usage | 1100 | //usage:#define udhcpc_trivial_usage |
1055 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" | 1101 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" |
1056 | //usage: " [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") | 1102 | //usage: " [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") |
1057 | //usage:#define udhcpc_full_usage "\n" | 1103 | //usage:#define udhcpc_full_usage "\n" |
1058 | //usage: IF_LONG_OPTS( | 1104 | //usage: IF_LONG_OPTS( |
1059 | //usage: "\n -i,--interface IFACE Interface to use (default eth0)" | 1105 | //usage: "\n -i,--interface IFACE Interface to use (default eth0)" |
@@ -1086,7 +1132,6 @@ static void client_background(void) | |||
1086 | //usage: "\n -x lease:3600 - option 51 (lease time)" | 1132 | //usage: "\n -x lease:3600 - option 51 (lease time)" |
1087 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" | 1133 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" |
1088 | //usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME" | 1134 | //usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME" |
1089 | //usage: "\n -H,-h,--hostname NAME Send NAME as client hostname (default none)" | ||
1090 | //usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')" | 1135 | //usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')" |
1091 | //usage: "\n -C,--clientid-none Don't send MAC as client identifier" | 1136 | //usage: "\n -C,--clientid-none Don't send MAC as client identifier" |
1092 | //usage: IF_UDHCP_VERBOSE( | 1137 | //usage: IF_UDHCP_VERBOSE( |
@@ -1124,7 +1169,6 @@ static void client_background(void) | |||
1124 | //usage: "\n -x lease:3600 - option 51 (lease time)" | 1169 | //usage: "\n -x lease:3600 - option 51 (lease time)" |
1125 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" | 1170 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" |
1126 | //usage: "\n -F NAME Ask server to update DNS mapping for NAME" | 1171 | //usage: "\n -F NAME Ask server to update DNS mapping for NAME" |
1127 | //usage: "\n -H,-h NAME Send NAME as client hostname (default none)" | ||
1128 | //usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" | 1172 | //usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" |
1129 | //usage: "\n -C Don't send MAC as client identifier" | 1173 | //usage: "\n -C Don't send MAC as client identifier" |
1130 | //usage: IF_UDHCP_VERBOSE( | 1174 | //usage: IF_UDHCP_VERBOSE( |
@@ -1132,8 +1176,8 @@ static void client_background(void) | |||
1132 | //usage: ) | 1176 | //usage: ) |
1133 | //usage: ) | 1177 | //usage: ) |
1134 | //usage: "\nSignals:" | 1178 | //usage: "\nSignals:" |
1135 | //usage: "\n USR1 Renew current lease" | 1179 | //usage: "\n USR1 Renew lease" |
1136 | //usage: "\n USR2 Release current lease" | 1180 | //usage: "\n USR2 Release lease" |
1137 | 1181 | ||
1138 | 1182 | ||
1139 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1183 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -1150,16 +1194,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1150 | int discover_retries = 3; | 1194 | int discover_retries = 3; |
1151 | uint32_t server_addr = server_addr; /* for compiler */ | 1195 | uint32_t server_addr = server_addr; /* for compiler */ |
1152 | uint32_t requested_ip = 0; | 1196 | uint32_t requested_ip = 0; |
1153 | uint32_t xid = 0; | 1197 | uint32_t xid = xid; /* for compiler */ |
1154 | uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */ | ||
1155 | int packet_num; | 1198 | int packet_num; |
1156 | int timeout; /* must be signed */ | 1199 | int timeout; /* must be signed */ |
1157 | unsigned already_waited_sec; | 1200 | unsigned already_waited_sec; |
1158 | unsigned opt; | 1201 | unsigned opt; |
1159 | int max_fd; | 1202 | int max_fd; |
1160 | int retval; | 1203 | int retval; |
1161 | struct timeval tv; | ||
1162 | struct dhcp_packet packet; | ||
1163 | fd_set rfds; | 1204 | fd_set rfds; |
1164 | 1205 | ||
1165 | /* Default options */ | 1206 | /* Default options */ |
@@ -1186,9 +1227,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1186 | , &list_x | 1227 | , &list_x |
1187 | IF_FEATURE_UDHCP_PORT(, &str_P) | 1228 | IF_FEATURE_UDHCP_PORT(, &str_P) |
1188 | IF_UDHCP_VERBOSE(, &dhcp_verbose) | 1229 | IF_UDHCP_VERBOSE(, &dhcp_verbose) |
1189 | ); | 1230 | ); |
1190 | if (opt & (OPT_h|OPT_H)) | 1231 | if (opt & (OPT_h|OPT_H)) { |
1232 | //msg added 2011-11 | ||
1233 | bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); | ||
1191 | client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); | 1234 | client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); |
1235 | } | ||
1192 | if (opt & OPT_F) { | 1236 | if (opt & OPT_F) { |
1193 | /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ | 1237 | /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ |
1194 | client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); | 1238 | client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); |
@@ -1249,8 +1293,16 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1249 | clientid_mac_ptr = client_config.clientid + OPT_DATA+1; | 1293 | clientid_mac_ptr = client_config.clientid + OPT_DATA+1; |
1250 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); | 1294 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); |
1251 | } | 1295 | } |
1252 | if (str_V[0] != '\0') | 1296 | if (str_V[0] != '\0') { |
1297 | // can drop -V, str_V, client_config.vendorclass, | ||
1298 | // but need to add "vendor" to the list of recognized | ||
1299 | // string opts for this to work; | ||
1300 | // and need to tweak add_client_options() too... | ||
1301 | // ...so the question is, should we? | ||
1302 | //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR"); | ||
1253 | client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); | 1303 | client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); |
1304 | } | ||
1305 | |||
1254 | #if !BB_MMU | 1306 | #if !BB_MMU |
1255 | /* on NOMMU reexec (i.e., background) early */ | 1307 | /* on NOMMU reexec (i.e., background) early */ |
1256 | if (!(opt & OPT_f)) { | 1308 | if (!(opt & OPT_f)) { |
@@ -1288,6 +1340,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1288 | * "continue" statements in code below jump to the top of the loop. | 1340 | * "continue" statements in code below jump to the top of the loop. |
1289 | */ | 1341 | */ |
1290 | for (;;) { | 1342 | for (;;) { |
1343 | struct timeval tv; | ||
1344 | struct dhcp_packet packet; | ||
1291 | /* silence "uninitialized!" warning */ | 1345 | /* silence "uninitialized!" warning */ |
1292 | unsigned timestamp_before_wait = timestamp_before_wait; | 1346 | unsigned timestamp_before_wait = timestamp_before_wait; |
1293 | 1347 | ||
@@ -1335,7 +1389,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1335 | NULL, | 1389 | NULL, |
1336 | client_config.client_mac) | 1390 | client_config.client_mac) |
1337 | ) { | 1391 | ) { |
1338 | return 1; /* iface is gone? */ | 1392 | goto ret0; /* iface is gone? */ |
1339 | } | 1393 | } |
1340 | if (clientid_mac_ptr) | 1394 | if (clientid_mac_ptr) |
1341 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); | 1395 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); |
@@ -1472,13 +1526,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1472 | timeout = 0; | 1526 | timeout = 0; |
1473 | continue; | 1527 | continue; |
1474 | case SIGUSR2: | 1528 | case SIGUSR2: |
1475 | perform_release(requested_ip, server_addr); | 1529 | perform_release(server_addr, requested_ip); |
1476 | timeout = INT_MAX; | 1530 | timeout = INT_MAX; |
1477 | continue; | 1531 | continue; |
1478 | case SIGTERM: | 1532 | case SIGTERM: |
1479 | bb_info_msg("Received SIGTERM"); | 1533 | bb_info_msg("Received SIGTERM"); |
1480 | if (opt & OPT_R) /* release on quit */ | ||
1481 | perform_release(requested_ip, server_addr); | ||
1482 | goto ret0; | 1534 | goto ret0; |
1483 | } | 1535 | } |
1484 | 1536 | ||
@@ -1531,7 +1583,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1531 | 1583 | ||
1532 | switch (state) { | 1584 | switch (state) { |
1533 | case INIT_SELECTING: | 1585 | case INIT_SELECTING: |
1534 | /* Must be a DHCPOFFER to one of our xid's */ | 1586 | /* Must be a DHCPOFFER */ |
1535 | if (*message == DHCPOFFER) { | 1587 | if (*message == DHCPOFFER) { |
1536 | /* What exactly is server's IP? There are several values. | 1588 | /* What exactly is server's IP? There are several values. |
1537 | * Example DHCP offer captured with tchdump: | 1589 | * Example DHCP offer captured with tchdump: |
@@ -1575,6 +1627,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1575 | case RENEW_REQUESTED: | 1627 | case RENEW_REQUESTED: |
1576 | case REBINDING: | 1628 | case REBINDING: |
1577 | if (*message == DHCPACK) { | 1629 | if (*message == DHCPACK) { |
1630 | uint32_t lease_seconds; | ||
1631 | struct in_addr temp_addr; | ||
1632 | |||
1578 | temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); | 1633 | temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); |
1579 | if (!temp) { | 1634 | if (!temp) { |
1580 | bb_error_msg("no lease time with ACK, using 1 hour lease"); | 1635 | bb_error_msg("no lease time with ACK, using 1 hour lease"); |
@@ -1583,9 +1638,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1583 | /* it IS unaligned sometimes, don't "optimize" */ | 1638 | /* it IS unaligned sometimes, don't "optimize" */ |
1584 | move_from_unaligned32(lease_seconds, temp); | 1639 | move_from_unaligned32(lease_seconds, temp); |
1585 | lease_seconds = ntohl(lease_seconds); | 1640 | lease_seconds = ntohl(lease_seconds); |
1586 | lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */ | 1641 | /* paranoia: must not be too small and not prone to overflows */ |
1587 | if (lease_seconds < 10) /* and not too small */ | 1642 | if (lease_seconds < 0x10) |
1588 | lease_seconds = 10; | 1643 | lease_seconds = 0x10; |
1644 | if (lease_seconds >= 0x10000000) | ||
1645 | lease_seconds = 0x0fffffff; | ||
1589 | } | 1646 | } |
1590 | #if ENABLE_FEATURE_UDHCPC_ARPING | 1647 | #if ENABLE_FEATURE_UDHCPC_ARPING |
1591 | if (opt & OPT_a) { | 1648 | if (opt & OPT_a) { |
@@ -1606,7 +1663,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1606 | ) { | 1663 | ) { |
1607 | bb_info_msg("Offered address is in use " | 1664 | bb_info_msg("Offered address is in use " |
1608 | "(got ARP reply), declining"); | 1665 | "(got ARP reply), declining"); |
1609 | send_decline(xid, server_addr, packet.yiaddr); | 1666 | send_decline(/*xid,*/ server_addr, packet.yiaddr); |
1610 | 1667 | ||
1611 | if (state != REQUESTING) | 1668 | if (state != REQUESTING) |
1612 | udhcp_run_script(NULL, "deconfig"); | 1669 | udhcp_run_script(NULL, "deconfig"); |
@@ -1623,20 +1680,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1623 | #endif | 1680 | #endif |
1624 | /* enter bound state */ | 1681 | /* enter bound state */ |
1625 | timeout = lease_seconds / 2; | 1682 | timeout = lease_seconds / 2; |
1626 | { | 1683 | temp_addr.s_addr = packet.yiaddr; |
1627 | struct in_addr temp_addr; | 1684 | bb_info_msg("Lease of %s obtained, lease time %u", |
1628 | temp_addr.s_addr = packet.yiaddr; | 1685 | inet_ntoa(temp_addr), (unsigned)lease_seconds); |
1629 | bb_info_msg("Lease of %s obtained, lease time %u", | ||
1630 | inet_ntoa(temp_addr), (unsigned)lease_seconds); | ||
1631 | } | ||
1632 | requested_ip = packet.yiaddr; | 1686 | requested_ip = packet.yiaddr; |
1633 | udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); | 1687 | udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); |
1634 | 1688 | ||
1635 | state = BOUND; | 1689 | state = BOUND; |
1636 | change_listen_mode(LISTEN_NONE); | 1690 | change_listen_mode(LISTEN_NONE); |
1637 | if (opt & OPT_q) { /* quit after lease */ | 1691 | if (opt & OPT_q) { /* quit after lease */ |
1638 | if (opt & OPT_R) /* release on quit */ | ||
1639 | perform_release(requested_ip, server_addr); | ||
1640 | goto ret0; | 1692 | goto ret0; |
1641 | } | 1693 | } |
1642 | /* future renew failures should not exit (JM) */ | 1694 | /* future renew failures should not exit (JM) */ |
@@ -1648,6 +1700,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1648 | opt = ((opt & ~OPT_b) | OPT_f); | 1700 | opt = ((opt & ~OPT_b) | OPT_f); |
1649 | } | 1701 | } |
1650 | #endif | 1702 | #endif |
1703 | /* make future renew packets use different xid */ | ||
1704 | /* xid = random_xid(); ...but why bother? */ | ||
1651 | already_waited_sec = 0; | 1705 | already_waited_sec = 0; |
1652 | continue; /* back to main loop */ | 1706 | continue; /* back to main loop */ |
1653 | } | 1707 | } |
@@ -1674,6 +1728,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1674 | } /* for (;;) - main loop ends */ | 1728 | } /* for (;;) - main loop ends */ |
1675 | 1729 | ||
1676 | ret0: | 1730 | ret0: |
1731 | if (opt & OPT_R) /* release on quit */ | ||
1732 | perform_release(server_addr, requested_ip); | ||
1677 | retval = 0; | 1733 | retval = 0; |
1678 | ret: | 1734 | ret: |
1679 | /*if (client_config.pidfile) - remove_pidfile has its own check */ | 1735 | /*if (client_config.pidfile) - remove_pidfile has its own check */ |