diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 322 |
1 files changed, 168 insertions, 154 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 6666cbce6..4e3d8ca5e 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -55,8 +55,7 @@ struct tpacket_auxdata { | |||
55 | #if ENABLE_LONG_OPTS | 55 | #if ENABLE_LONG_OPTS |
56 | static const char udhcpc_longopts[] ALIGN1 = | 56 | static const char udhcpc_longopts[] ALIGN1 = |
57 | "clientid-none\0" No_argument "C" | 57 | "clientid-none\0" No_argument "C" |
58 | "vendorclass\0" Required_argument "V" | 58 | "vendorclass\0" Required_argument "V" //deprecated |
59 | "hostname\0" Required_argument "H" | ||
60 | "fqdn\0" Required_argument "F" | 59 | "fqdn\0" Required_argument "F" |
61 | "interface\0" Required_argument "i" | 60 | "interface\0" Required_argument "i" |
62 | "now\0" No_argument "n" | 61 | "now\0" No_argument "n" |
@@ -84,27 +83,25 @@ static const char udhcpc_longopts[] ALIGN1 = | |||
84 | enum { | 83 | enum { |
85 | OPT_C = 1 << 0, | 84 | OPT_C = 1 << 0, |
86 | OPT_V = 1 << 1, | 85 | OPT_V = 1 << 1, |
87 | OPT_H = 1 << 2, | 86 | OPT_F = 1 << 2, |
88 | OPT_h = 1 << 3, | 87 | OPT_i = 1 << 3, |
89 | OPT_F = 1 << 4, | 88 | OPT_n = 1 << 4, |
90 | OPT_i = 1 << 5, | 89 | OPT_p = 1 << 5, |
91 | OPT_n = 1 << 6, | 90 | OPT_q = 1 << 6, |
92 | OPT_p = 1 << 7, | 91 | OPT_R = 1 << 7, |
93 | OPT_q = 1 << 8, | 92 | OPT_r = 1 << 8, |
94 | OPT_R = 1 << 9, | 93 | OPT_s = 1 << 9, |
95 | OPT_r = 1 << 10, | 94 | OPT_T = 1 << 10, |
96 | OPT_s = 1 << 11, | 95 | OPT_t = 1 << 11, |
97 | OPT_T = 1 << 12, | 96 | OPT_S = 1 << 12, |
98 | OPT_t = 1 << 13, | 97 | OPT_A = 1 << 13, |
99 | OPT_S = 1 << 14, | 98 | OPT_O = 1 << 14, |
100 | OPT_A = 1 << 15, | 99 | OPT_o = 1 << 15, |
101 | OPT_O = 1 << 16, | 100 | OPT_x = 1 << 16, |
102 | OPT_o = 1 << 17, | 101 | OPT_f = 1 << 17, |
103 | OPT_x = 1 << 18, | 102 | OPT_B = 1 << 18, |
104 | OPT_f = 1 << 19, | ||
105 | OPT_B = 1 << 20, | ||
106 | /* The rest has variable bit positions, need to be clever */ | 103 | /* The rest has variable bit positions, need to be clever */ |
107 | OPTBIT_B = 20, | 104 | OPTBIT_B = 18, |
108 | USE_FOR_MMU( OPTBIT_b,) | 105 | USE_FOR_MMU( OPTBIT_b,) |
109 | IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) | 106 | IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) |
110 | IF_FEATURE_UDHCP_PORT( OPTBIT_P,) | 107 | IF_FEATURE_UDHCP_PORT( OPTBIT_P,) |
@@ -569,8 +566,8 @@ static void fill_envp(struct dhcp_packet *packet) | |||
569 | } | 566 | } |
570 | } | 567 | } |
571 | 568 | ||
572 | /* Call a script with a par file and env vars */ | 569 | /* Call a script with env vars */ |
573 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | 570 | static void d4_run_script(struct dhcp_packet *packet, const char *name) |
574 | { | 571 | { |
575 | char *argv[3]; | 572 | char *argv[3]; |
576 | 573 | ||
@@ -588,6 +585,10 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | |||
588 | client_data.envp = NULL; | 585 | client_data.envp = NULL; |
589 | } | 586 | } |
590 | 587 | ||
588 | static void d4_run_script_deconfig(void) | ||
589 | { | ||
590 | d4_run_script(NULL, "deconfig"); | ||
591 | } | ||
591 | 592 | ||
592 | /*** Sending/receiving packets ***/ | 593 | /*** Sending/receiving packets ***/ |
593 | 594 | ||
@@ -613,8 +614,6 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
613 | packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff; | 614 | packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff; |
614 | 615 | ||
615 | memcpy(packet->chaddr, client_data.client_mac, 6); | 616 | memcpy(packet->chaddr, client_data.client_mac, 6); |
616 | if (client_data.clientid) | ||
617 | udhcp_add_binary_option(packet, client_data.clientid); | ||
618 | } | 617 | } |
619 | 618 | ||
620 | static void add_client_options(struct dhcp_packet *packet) | 619 | static void add_client_options(struct dhcp_packet *packet) |
@@ -640,13 +639,6 @@ static void add_client_options(struct dhcp_packet *packet) | |||
640 | packet->options[end + OPT_DATA + len] = DHCP_END; | 639 | packet->options[end + OPT_DATA + len] = DHCP_END; |
641 | } | 640 | } |
642 | 641 | ||
643 | if (client_data.vendorclass) | ||
644 | udhcp_add_binary_option(packet, client_data.vendorclass); | ||
645 | if (client_data.hostname) | ||
646 | udhcp_add_binary_option(packet, client_data.hostname); | ||
647 | if (client_data.fqdn) | ||
648 | udhcp_add_binary_option(packet, client_data.fqdn); | ||
649 | |||
650 | /* Request broadcast replies if we have no IP addr */ | 642 | /* Request broadcast replies if we have no IP addr */ |
651 | if ((option_mask32 & OPT_B) && packet->ciaddr == 0) | 643 | if ((option_mask32 & OPT_B) && packet->ciaddr == 0) |
652 | packet->flags |= htons(BROADCAST_FLAG); | 644 | packet->flags |= htons(BROADCAST_FLAG); |
@@ -715,7 +707,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
715 | 707 | ||
716 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 708 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
717 | * random xid field (we override it below), | 709 | * random xid field (we override it below), |
718 | * client-id option (unless -C), message type option: | 710 | * message type option: |
719 | */ | 711 | */ |
720 | init_packet(&packet, DHCPDISCOVER); | 712 | init_packet(&packet, DHCPDISCOVER); |
721 | 713 | ||
@@ -724,7 +716,6 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
724 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 716 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
725 | 717 | ||
726 | /* Add options: maxsize, | 718 | /* Add options: maxsize, |
727 | * optionally: hostname, fqdn, vendorclass, | ||
728 | * "param req" option according to -O, options specified with -x | 719 | * "param req" option according to -O, options specified with -x |
729 | */ | 720 | */ |
730 | add_client_options(&packet); | 721 | add_client_options(&packet); |
@@ -758,7 +749,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
758 | */ | 749 | */ |
759 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 750 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
760 | * random xid field (we override it below), | 751 | * random xid field (we override it below), |
761 | * client-id option (unless -C), message type option: | 752 | * message type option: |
762 | */ | 753 | */ |
763 | init_packet(&packet, DHCPREQUEST); | 754 | init_packet(&packet, DHCPREQUEST); |
764 | 755 | ||
@@ -768,7 +759,6 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
768 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 759 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
769 | 760 | ||
770 | /* Add options: maxsize, | 761 | /* Add options: maxsize, |
771 | * optionally: hostname, fqdn, vendorclass, | ||
772 | * "param req" option according to -O, and options specified with -x | 762 | * "param req" option according to -O, and options specified with -x |
773 | */ | 763 | */ |
774 | add_client_options(&packet); | 764 | add_client_options(&packet); |
@@ -805,7 +795,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
805 | */ | 795 | */ |
806 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 796 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
807 | * random xid field (we override it below), | 797 | * random xid field (we override it below), |
808 | * client-id option (unless -C), message type option: | 798 | * message type option: |
809 | */ | 799 | */ |
810 | init_packet(&packet, DHCPREQUEST); | 800 | init_packet(&packet, DHCPREQUEST); |
811 | 801 | ||
@@ -813,7 +803,6 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
813 | packet.ciaddr = ciaddr; | 803 | packet.ciaddr = ciaddr; |
814 | 804 | ||
815 | /* Add options: maxsize, | 805 | /* Add options: maxsize, |
816 | * optionally: hostname, fqdn, vendorclass, | ||
817 | * "param req" option according to -O, and options specified with -x | 806 | * "param req" option according to -O, and options specified with -x |
818 | */ | 807 | */ |
819 | add_client_options(&packet); | 808 | add_client_options(&packet); |
@@ -837,7 +826,7 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req | |||
837 | struct dhcp_packet packet; | 826 | struct dhcp_packet packet; |
838 | 827 | ||
839 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | 828 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, |
840 | * client-id option (unless -C), message type option: | 829 | * message type option: |
841 | */ | 830 | */ |
842 | init_packet(&packet, DHCPDECLINE); | 831 | init_packet(&packet, DHCPDECLINE); |
843 | 832 | ||
@@ -854,6 +843,8 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req | |||
854 | 843 | ||
855 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 844 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
856 | 845 | ||
846 | //TODO: add client-id opt? | ||
847 | |||
857 | bb_simple_info_msg("broadcasting decline"); | 848 | bb_simple_info_msg("broadcasting decline"); |
858 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); | 849 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); |
859 | } | 850 | } |
@@ -865,9 +856,10 @@ ALWAYS_INLINE /* one caller, help compiler to use this fact */ | |||
865 | int send_release(uint32_t server, uint32_t ciaddr) | 856 | int send_release(uint32_t server, uint32_t ciaddr) |
866 | { | 857 | { |
867 | struct dhcp_packet packet; | 858 | struct dhcp_packet packet; |
859 | struct option_set *ci; | ||
868 | 860 | ||
869 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | 861 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, |
870 | * client-id option (unless -C), message type option: | 862 | * message type option: |
871 | */ | 863 | */ |
872 | init_packet(&packet, DHCPRELEASE); | 864 | init_packet(&packet, DHCPRELEASE); |
873 | 865 | ||
@@ -876,6 +868,14 @@ int send_release(uint32_t server, uint32_t ciaddr) | |||
876 | 868 | ||
877 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 869 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
878 | 870 | ||
871 | /* RFC 2131 section 3.1.6: | ||
872 | * If the client used a 'client identifier' when it obtained the lease, | ||
873 | * it MUST use the same 'client identifier' in the DHCPRELEASE message. | ||
874 | */ | ||
875 | ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID); | ||
876 | if (ci) | ||
877 | udhcp_add_binary_option(&packet, ci->data); | ||
878 | |||
879 | bb_info_msg("sending %s", "release"); | 879 | bb_info_msg("sending %s", "release"); |
880 | /* Note: normally we unicast here since "server" is not zero. | 880 | /* Note: normally we unicast here since "server" is not zero. |
881 | * However, there _are_ people who run "address-less" DHCP servers, | 881 | * However, there _are_ people who run "address-less" DHCP servers, |
@@ -886,7 +886,7 @@ int send_release(uint32_t server, uint32_t ciaddr) | |||
886 | 886 | ||
887 | /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ | 887 | /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ |
888 | /* NOINLINE: limit stack usage in caller */ | 888 | /* NOINLINE: limit stack usage in caller */ |
889 | static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | 889 | static NOINLINE int d4_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) |
890 | { | 890 | { |
891 | int bytes; | 891 | int bytes; |
892 | struct ip_udp_dhcp_packet packet; | 892 | struct ip_udp_dhcp_packet packet; |
@@ -979,11 +979,12 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
979 | skip_udp_sum_check: | 979 | skip_udp_sum_check: |
980 | 980 | ||
981 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { | 981 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { |
982 | bb_simple_info_msg("packet with bad magic, ignoring"); | 982 | log1s("packet with bad magic, ignoring"); |
983 | return -2; | 983 | return -2; |
984 | } | 984 | } |
985 | 985 | ||
986 | log1("received %s", "a packet"); | 986 | log2("received %s", "a packet"); |
987 | /* log2 because more informative msg for valid packets is printed later at log1 level */ | ||
987 | udhcp_dump_packet(&packet.data); | 988 | udhcp_dump_packet(&packet.data); |
988 | 989 | ||
989 | bytes -= sizeof(packet.ip) + sizeof(packet.udp); | 990 | bytes -= sizeof(packet.ip) + sizeof(packet.udp); |
@@ -1096,8 +1097,6 @@ static int udhcp_raw_socket(int ifindex) | |||
1096 | log1s("can't set PACKET_AUXDATA on raw socket"); | 1097 | log1s("can't set PACKET_AUXDATA on raw socket"); |
1097 | } | 1098 | } |
1098 | 1099 | ||
1099 | log1s("created raw socket"); | ||
1100 | |||
1101 | return fd; | 1100 | return fd; |
1102 | } | 1101 | } |
1103 | 1102 | ||
@@ -1126,6 +1125,8 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) | |||
1126 | char buffer[sizeof("255.255.255.255")]; | 1125 | char buffer[sizeof("255.255.255.255")]; |
1127 | struct in_addr temp_addr; | 1126 | struct in_addr temp_addr; |
1128 | 1127 | ||
1128 | change_listen_mode(LISTEN_NONE); | ||
1129 | |||
1129 | /* send release packet */ | 1130 | /* send release packet */ |
1130 | if (client_data.state == BOUND | 1131 | if (client_data.state == BOUND |
1131 | || client_data.state == RENEWING | 1132 | || client_data.state == RENEWING |
@@ -1146,23 +1147,10 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) | |||
1146 | * Users requested to be notified in all cases, even if not in one | 1147 | * Users requested to be notified in all cases, even if not in one |
1147 | * of the states above. | 1148 | * of the states above. |
1148 | */ | 1149 | */ |
1149 | udhcp_run_script(NULL, "deconfig"); | 1150 | d4_run_script_deconfig(); |
1150 | |||
1151 | change_listen_mode(LISTEN_NONE); | ||
1152 | client_data.state = RELEASED; | 1151 | client_data.state = RELEASED; |
1153 | } | 1152 | } |
1154 | 1153 | ||
1155 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | ||
1156 | { | ||
1157 | uint8_t *storage; | ||
1158 | int len = strnlen(str, 255); | ||
1159 | storage = xzalloc(len + extra + OPT_DATA); | ||
1160 | storage[OPT_CODE] = code; | ||
1161 | storage[OPT_LEN] = len + extra; | ||
1162 | memcpy(storage + extra + OPT_DATA, str, len); | ||
1163 | return storage; | ||
1164 | } | ||
1165 | |||
1166 | #if BB_MMU | 1154 | #if BB_MMU |
1167 | static void client_background(void) | 1155 | static void client_background(void) |
1168 | { | 1156 | { |
@@ -1227,10 +1215,10 @@ int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
1227 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) | 1215 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) |
1228 | { | 1216 | { |
1229 | uint8_t *message; | 1217 | uint8_t *message; |
1230 | const char *str_V, *str_h, *str_F, *str_r; | 1218 | const char *str_V, *str_F, *str_r; |
1231 | IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";) | 1219 | IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";) |
1232 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 1220 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
1233 | void *clientid_mac_ptr; | 1221 | uint8_t *clientid_mac_ptr; |
1234 | llist_t *list_O = NULL; | 1222 | llist_t *list_O = NULL; |
1235 | llist_t *list_x = NULL; | 1223 | llist_t *list_x = NULL; |
1236 | int tryagain_timeout = 20; | 1224 | int tryagain_timeout = 20; |
@@ -1263,14 +1251,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1263 | /* Parse command line */ | 1251 | /* Parse command line */ |
1264 | opt = getopt32long(argv, "^" | 1252 | opt = getopt32long(argv, "^" |
1265 | /* O,x: list; -T,-t,-A take numeric param */ | 1253 | /* O,x: list; -T,-t,-A take numeric param */ |
1266 | "CV:H:h:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB" | 1254 | "CV:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB" |
1267 | USE_FOR_MMU("b") | 1255 | USE_FOR_MMU("b") |
1268 | IF_FEATURE_UDHCPC_ARPING("a::") | 1256 | IF_FEATURE_UDHCPC_ARPING("a::") |
1269 | IF_FEATURE_UDHCP_PORT("P:") | 1257 | IF_FEATURE_UDHCP_PORT("P:") |
1270 | "v" | 1258 | "v" |
1271 | "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ | 1259 | "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ |
1272 | , udhcpc_longopts | 1260 | , udhcpc_longopts |
1273 | , &str_V, &str_h, &str_h, &str_F | 1261 | , &str_V, &str_F |
1274 | , &client_data.interface, &client_data.pidfile /* i,p */ | 1262 | , &client_data.interface, &client_data.pidfile /* i,p */ |
1275 | , &str_r /* r */ | 1263 | , &str_r /* r */ |
1276 | , &client_data.script /* s */ | 1264 | , &client_data.script /* s */ |
@@ -1281,14 +1269,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1281 | IF_FEATURE_UDHCP_PORT(, &str_P) | 1269 | IF_FEATURE_UDHCP_PORT(, &str_P) |
1282 | IF_UDHCP_VERBOSE(, &dhcp_verbose) | 1270 | IF_UDHCP_VERBOSE(, &dhcp_verbose) |
1283 | ); | 1271 | ); |
1284 | if (opt & (OPT_h|OPT_H)) { | ||
1285 | //msg added 2011-11 | ||
1286 | bb_simple_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); | ||
1287 | client_data.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); | ||
1288 | } | ||
1289 | if (opt & OPT_F) { | 1272 | if (opt & OPT_F) { |
1273 | char *p; | ||
1274 | unsigned len; | ||
1290 | /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ | 1275 | /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ |
1291 | client_data.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); | 1276 | len = strlen(str_F); |
1277 | p = udhcp_insert_new_option( | ||
1278 | &client_data.options, DHCP_FQDN, | ||
1279 | len + 3, /*dhcp6:*/ 0); | ||
1292 | /* Flag bits: 0000NEOS | 1280 | /* Flag bits: 0000NEOS |
1293 | * S: 1 = Client requests server to update A RR in DNS as well as PTR | 1281 | * S: 1 = Client requests server to update A RR in DNS as well as PTR |
1294 | * O: 1 = Server indicates to client that DNS has been updated regardless | 1282 | * O: 1 = Server indicates to client that DNS has been updated regardless |
@@ -1297,9 +1285,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1297 | * N: 1 = Client requests server to not update DNS (S must be 0 then) | 1285 | * N: 1 = Client requests server to not update DNS (S must be 0 then) |
1298 | * Two [0] bytes which follow are deprecated and must be 0. | 1286 | * Two [0] bytes which follow are deprecated and must be 0. |
1299 | */ | 1287 | */ |
1300 | client_data.fqdn[OPT_DATA + 0] = 0x1; | 1288 | p[OPT_DATA + 0] = 0x1; |
1301 | /*client_data.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */ | 1289 | /*p[OPT_DATA + 1] = 0; - xzalloc did it */ |
1302 | /*client_data.fqdn[OPT_DATA + 2] = 0; */ | 1290 | /*p[OPT_DATA + 2] = 0; */ |
1291 | memcpy(p + OPT_DATA + 3, str_F, len); /* do not store NUL byte */ | ||
1303 | } | 1292 | } |
1304 | if (opt & OPT_r) | 1293 | if (opt & OPT_r) |
1305 | requested_ip = inet_addr(str_r); | 1294 | requested_ip = inet_addr(str_r); |
@@ -1335,7 +1324,29 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1335 | ); | 1324 | ); |
1336 | free(optstr); | 1325 | free(optstr); |
1337 | } | 1326 | } |
1327 | if (str_V[0] != '\0') { | ||
1328 | char *p; | ||
1329 | unsigned len = strnlen(str_V, 254); | ||
1330 | p = udhcp_insert_new_option( | ||
1331 | &client_data.options, DHCP_VENDOR, | ||
1332 | len, /*dhcp6:*/ 0); | ||
1333 | memcpy(p + OPT_DATA, str_V, len); /* do not store NUL byte */ | ||
1334 | } | ||
1335 | |||
1336 | clientid_mac_ptr = NULL; | ||
1337 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { | ||
1338 | /* not suppressed and not set, create default client ID */ | ||
1339 | clientid_mac_ptr = udhcp_insert_new_option( | ||
1340 | &client_data.options, DHCP_CLIENT_ID, | ||
1341 | 1 + 6, /*dhcp6:*/ 0); | ||
1342 | clientid_mac_ptr[OPT_DATA] = 1; /* type: ethernet */ | ||
1343 | clientid_mac_ptr += OPT_DATA + 1; /* skip option code, len, ethernet */ | ||
1344 | } | ||
1338 | 1345 | ||
1346 | /* Not really necessary (we redo it on every iteration) | ||
1347 | * but allows early (before daemonization) detection | ||
1348 | * of bad interface name. | ||
1349 | */ | ||
1339 | if (udhcp_read_interface(client_data.interface, | 1350 | if (udhcp_read_interface(client_data.interface, |
1340 | &client_data.ifindex, | 1351 | &client_data.ifindex, |
1341 | NULL, | 1352 | NULL, |
@@ -1344,24 +1355,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1344 | return 1; | 1355 | return 1; |
1345 | } | 1356 | } |
1346 | 1357 | ||
1347 | clientid_mac_ptr = NULL; | ||
1348 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { | ||
1349 | /* not suppressed and not set, set the default client ID */ | ||
1350 | client_data.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); | ||
1351 | client_data.clientid[OPT_DATA] = 1; /* type: ethernet */ | ||
1352 | clientid_mac_ptr = client_data.clientid + OPT_DATA+1; | ||
1353 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); | ||
1354 | } | ||
1355 | if (str_V[0] != '\0') { | ||
1356 | // can drop -V, str_V, client_data.vendorclass, | ||
1357 | // but need to add "vendor" to the list of recognized | ||
1358 | // string opts for this to work; | ||
1359 | // and need to tweak add_client_options() too... | ||
1360 | // ...so the question is, should we? | ||
1361 | //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR"); | ||
1362 | client_data.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); | ||
1363 | } | ||
1364 | |||
1365 | #if !BB_MMU | 1358 | #if !BB_MMU |
1366 | /* on NOMMU reexec (i.e., background) early */ | 1359 | /* on NOMMU reexec (i.e., background) early */ |
1367 | if (!(opt & OPT_f)) { | 1360 | if (!(opt & OPT_f)) { |
@@ -1382,8 +1375,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1382 | srand(monotonic_us()); | 1375 | srand(monotonic_us()); |
1383 | 1376 | ||
1384 | client_data.state = INIT_SELECTING; | 1377 | client_data.state = INIT_SELECTING; |
1385 | udhcp_run_script(NULL, "deconfig"); | 1378 | d4_run_script_deconfig(); |
1386 | change_listen_mode(LISTEN_RAW); | ||
1387 | packet_num = 0; | 1379 | packet_num = 0; |
1388 | timeout = 0; | 1380 | timeout = 0; |
1389 | lease_remaining = 0; | 1381 | lease_remaining = 0; |
@@ -1417,14 +1409,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1417 | log1("waiting %u seconds", timeout); | 1409 | log1("waiting %u seconds", timeout); |
1418 | diff = (unsigned)monotonic_sec(); | 1410 | diff = (unsigned)monotonic_sec(); |
1419 | retval = poll(pfds, 2, timeout * 1000); | 1411 | retval = poll(pfds, 2, timeout * 1000); |
1412 | diff = (unsigned)monotonic_sec() - diff; | ||
1413 | lease_remaining -= diff; | ||
1414 | if (lease_remaining < 0) | ||
1415 | lease_remaining = 0; | ||
1416 | timeout -= diff; | ||
1417 | if (timeout < 0) | ||
1418 | timeout = 0; | ||
1419 | |||
1420 | if (retval < 0) { | 1420 | if (retval < 0) { |
1421 | /* EINTR? A signal was caught, don't panic */ | 1421 | /* EINTR? A signal was caught, don't panic */ |
1422 | if (errno == EINTR) { | 1422 | if (errno == EINTR) { |
1423 | diff = (unsigned)monotonic_sec() - diff; | ||
1424 | lease_remaining -= diff; | ||
1425 | if (lease_remaining < 0) | ||
1426 | lease_remaining = 0; | ||
1427 | timeout -= diff; | ||
1428 | continue; | 1423 | continue; |
1429 | } | 1424 | } |
1430 | /* Else: an error occurred, panic! */ | 1425 | /* Else: an error occurred, panic! */ |
@@ -1454,8 +1449,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1454 | switch (client_data.state) { | 1449 | switch (client_data.state) { |
1455 | case INIT_SELECTING: | 1450 | case INIT_SELECTING: |
1456 | if (!discover_retries || packet_num < discover_retries) { | 1451 | if (!discover_retries || packet_num < discover_retries) { |
1457 | if (packet_num == 0) | 1452 | if (packet_num == 0) { |
1453 | change_listen_mode(LISTEN_RAW); | ||
1458 | xid = random_xid(); | 1454 | xid = random_xid(); |
1455 | } | ||
1459 | /* broadcast */ | 1456 | /* broadcast */ |
1460 | send_discover(xid, requested_ip); | 1457 | send_discover(xid, requested_ip); |
1461 | timeout = discover_timeout; | 1458 | timeout = discover_timeout; |
@@ -1463,7 +1460,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1463 | continue; | 1460 | continue; |
1464 | } | 1461 | } |
1465 | leasefail: | 1462 | leasefail: |
1466 | udhcp_run_script(NULL, "leasefail"); | 1463 | change_listen_mode(LISTEN_NONE); |
1464 | d4_run_script(NULL, "leasefail"); | ||
1467 | #if BB_MMU /* -b is not supported on NOMMU */ | 1465 | #if BB_MMU /* -b is not supported on NOMMU */ |
1468 | if (opt & OPT_b) { /* background if no lease */ | 1466 | if (opt & OPT_b) { /* background if no lease */ |
1469 | bb_simple_info_msg("no lease, forking to background"); | 1467 | bb_simple_info_msg("no lease, forking to background"); |
@@ -1483,7 +1481,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1483 | retval = 1; | 1481 | retval = 1; |
1484 | goto ret; | 1482 | goto ret; |
1485 | } | 1483 | } |
1486 | /* wait before trying again */ | 1484 | /* Wait before trying again */ |
1487 | timeout = tryagain_timeout; | 1485 | timeout = tryagain_timeout; |
1488 | packet_num = 0; | 1486 | packet_num = 0; |
1489 | continue; | 1487 | continue; |
@@ -1499,22 +1497,20 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1499 | * "discover...select...discover..." loops | 1497 | * "discover...select...discover..." loops |
1500 | * were seen in the wild. Treat them similarly | 1498 | * were seen in the wild. Treat them similarly |
1501 | * to "no response to discover" case */ | 1499 | * to "no response to discover" case */ |
1502 | change_listen_mode(LISTEN_RAW); | ||
1503 | client_data.state = INIT_SELECTING; | 1500 | client_data.state = INIT_SELECTING; |
1504 | goto leasefail; | 1501 | goto leasefail; |
1505 | case BOUND: | 1502 | case BOUND: |
1506 | /* 1/2 lease passed, enter renewing state */ | 1503 | /* 1/2 lease passed, enter renewing state */ |
1507 | client_data.state = RENEWING; | 1504 | client_data.state = RENEWING; |
1508 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1505 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1509 | change_listen_mode(LISTEN_KERNEL); | 1506 | got_SIGUSR1: |
1510 | log1s("entering renew state"); | 1507 | log1s("entering renew state"); |
1508 | change_listen_mode(LISTEN_KERNEL); | ||
1511 | /* fall right through */ | 1509 | /* fall right through */ |
1512 | case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ | 1510 | case RENEW_REQUESTED: /* in manual (SIGUSR1) renew */ |
1513 | case_RENEW_REQUESTED: | ||
1514 | case RENEWING: | 1511 | case RENEWING: |
1515 | if (packet_num < 3) { | 1512 | if (packet_num == 0) { |
1516 | packet_num++; | 1513 | /* Send an unicast renew request */ |
1517 | /* send an unicast renew request */ | ||
1518 | /* Sometimes observed to fail (EADDRNOTAVAIL) to bind | 1514 | /* Sometimes observed to fail (EADDRNOTAVAIL) to bind |
1519 | * a new UDP socket for sending inside send_renew. | 1515 | * a new UDP socket for sending inside send_renew. |
1520 | * I hazard to guess existing listening socket | 1516 | * I hazard to guess existing listening socket |
@@ -1525,7 +1521,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1525 | */ | 1521 | */ |
1526 | if (send_renew(xid, server_addr, requested_ip) >= 0) { | 1522 | if (send_renew(xid, server_addr, requested_ip) >= 0) { |
1527 | timeout = discover_timeout; | 1523 | timeout = discover_timeout; |
1528 | /* ^^^ used to be = lease_remaining / 2 - WAY too long */ | 1524 | packet_num++; |
1529 | continue; | 1525 | continue; |
1530 | } | 1526 | } |
1531 | /* else: error sending. | 1527 | /* else: error sending. |
@@ -1533,27 +1529,34 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1533 | * which gave us bogus server ID 1.1.1.1 | 1529 | * which gave us bogus server ID 1.1.1.1 |
1534 | * which wasn't reachable (and probably did not exist). | 1530 | * which wasn't reachable (and probably did not exist). |
1535 | */ | 1531 | */ |
1532 | } /* else: we had sent one packet, but got no reply */ | ||
1533 | log1s("no response to renew"); | ||
1534 | if (lease_remaining > 30) { | ||
1535 | /* Some lease time remains, try to renew later */ | ||
1536 | change_listen_mode(LISTEN_NONE); | ||
1537 | goto BOUND_for_half_lease; | ||
1536 | } | 1538 | } |
1537 | //TODO: if 3 renew's failed (no reply) but remaining lease is large, | 1539 | /* Enter rebinding state */ |
1538 | //it might make sense to make a large pause (~1 hour?) and try later? | ||
1539 | /* Timed out or error, enter rebinding state */ | ||
1540 | log1s("entering rebinding state"); | ||
1541 | client_data.state = REBINDING; | 1540 | client_data.state = REBINDING; |
1542 | /* fall right through */ | 1541 | log1s("entering rebinding state"); |
1543 | case REBINDING: | ||
1544 | /* Switch to bcast receive */ | 1542 | /* Switch to bcast receive */ |
1545 | change_listen_mode(LISTEN_RAW); | 1543 | change_listen_mode(LISTEN_RAW); |
1544 | packet_num = 0; | ||
1545 | /* fall right through */ | ||
1546 | case REBINDING: | ||
1546 | /* Lease is *really* about to run out, | 1547 | /* Lease is *really* about to run out, |
1547 | * try to find DHCP server using broadcast */ | 1548 | * try to find DHCP server using broadcast */ |
1548 | if (lease_remaining > 0) { | 1549 | if (lease_remaining > 0 && packet_num < 3) { |
1549 | /* send a broadcast renew request */ | 1550 | /* send a broadcast renew request */ |
1550 | send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); | 1551 | send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); |
1551 | timeout = discover_timeout; | 1552 | timeout = discover_timeout; |
1553 | packet_num++; | ||
1552 | continue; | 1554 | continue; |
1553 | } | 1555 | } |
1554 | /* Timed out, enter init state */ | 1556 | /* Timed out, enter init state */ |
1557 | change_listen_mode(LISTEN_NONE); | ||
1555 | bb_simple_info_msg("lease lost, entering init state"); | 1558 | bb_simple_info_msg("lease lost, entering init state"); |
1556 | udhcp_run_script(NULL, "deconfig"); | 1559 | d4_run_script_deconfig(); |
1557 | client_data.state = INIT_SELECTING; | 1560 | client_data.state = INIT_SELECTING; |
1558 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1561 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1559 | timeout = 0; | 1562 | timeout = 0; |
@@ -1561,7 +1564,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1561 | continue; | 1564 | continue; |
1562 | /* case RELEASED: */ | 1565 | /* case RELEASED: */ |
1563 | } | 1566 | } |
1564 | /* yah, I know, *you* say it would never happen */ | 1567 | /* RELEASED state (when we got SIGUSR2) ends up here. |
1568 | * (wait for SIGUSR1 to re-init, or for TERM, etc) | ||
1569 | */ | ||
1565 | timeout = INT_MAX; | 1570 | timeout = INT_MAX; |
1566 | continue; /* back to main loop */ | 1571 | continue; /* back to main loop */ |
1567 | } /* if poll timed out */ | 1572 | } /* if poll timed out */ |
@@ -1571,33 +1576,42 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1571 | /* Is it a signal? */ | 1576 | /* Is it a signal? */ |
1572 | switch (udhcp_sp_read()) { | 1577 | switch (udhcp_sp_read()) { |
1573 | case SIGUSR1: | 1578 | case SIGUSR1: |
1579 | if (client_data.state <= REQUESTING) | ||
1580 | /* Initial negotiations in progress, do not disturb */ | ||
1581 | break; | ||
1582 | if (client_data.state == REBINDING) | ||
1583 | /* Do not go back from rebind to renew state */ | ||
1584 | break; | ||
1585 | |||
1586 | if (lease_remaining > 30) /* if renew fails, do not go back to BOUND */ | ||
1587 | lease_remaining = 30; | ||
1574 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1588 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1575 | bb_simple_info_msg("performing DHCP renew"); | 1589 | packet_num = 0; |
1576 | 1590 | ||
1577 | switch (client_data.state) { | 1591 | switch (client_data.state) { |
1578 | /* Try to renew/rebind */ | ||
1579 | case BOUND: | 1592 | case BOUND: |
1580 | case RENEWING: | 1593 | case RENEWING: |
1581 | case REBINDING: | 1594 | /* Try to renew/rebind */ |
1582 | change_listen_mode(LISTEN_KERNEL); | ||
1583 | client_data.state = RENEW_REQUESTED; | 1595 | client_data.state = RENEW_REQUESTED; |
1584 | goto case_RENEW_REQUESTED; | 1596 | goto got_SIGUSR1; |
1585 | 1597 | ||
1586 | /* Start things over */ | 1598 | case RENEW_REQUESTED: |
1587 | case RENEW_REQUESTED: /* two or more SIGUSR1 received */ | 1599 | /* Two SIGUSR1 received, start things over */ |
1588 | udhcp_run_script(NULL, "deconfig"); | 1600 | change_listen_mode(LISTEN_NONE); |
1589 | /* case REQUESTING: break; */ | 1601 | d4_run_script_deconfig(); |
1590 | /* case RELEASED: break; */ | 1602 | |
1591 | /* case INIT_SELECTING: break; */ | 1603 | default: |
1604 | /* case RELEASED: */ | ||
1605 | /* Wake from SIGUSR2-induced deconfigured state */ | ||
1606 | change_listen_mode(LISTEN_NONE); | ||
1592 | } | 1607 | } |
1593 | change_listen_mode(LISTEN_RAW); | ||
1594 | client_data.state = INIT_SELECTING; | 1608 | client_data.state = INIT_SELECTING; |
1595 | packet_num = 0; | ||
1596 | /* Kill any timeouts, user wants this to hurry along */ | 1609 | /* Kill any timeouts, user wants this to hurry along */ |
1597 | timeout = 0; | 1610 | timeout = 0; |
1598 | continue; | 1611 | continue; |
1599 | case SIGUSR2: | 1612 | case SIGUSR2: |
1600 | perform_release(server_addr, requested_ip); | 1613 | perform_release(server_addr, requested_ip); |
1614 | /* ^^^ switches to LISTEN_NONE */ | ||
1601 | timeout = INT_MAX; | 1615 | timeout = INT_MAX; |
1602 | continue; | 1616 | continue; |
1603 | case SIGTERM: | 1617 | case SIGTERM: |
@@ -1616,7 +1630,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1616 | if (client_data.listen_mode == LISTEN_KERNEL) | 1630 | if (client_data.listen_mode == LISTEN_KERNEL) |
1617 | len = udhcp_recv_kernel_packet(&packet, client_data.sockfd); | 1631 | len = udhcp_recv_kernel_packet(&packet, client_data.sockfd); |
1618 | else | 1632 | else |
1619 | len = udhcp_recv_raw_packet(&packet, client_data.sockfd); | 1633 | len = d4_recv_raw_packet(&packet, client_data.sockfd); |
1620 | if (len == -1) { | 1634 | if (len == -1) { |
1621 | /* Error is severe, reopen socket */ | 1635 | /* Error is severe, reopen socket */ |
1622 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); | 1636 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); |
@@ -1640,13 +1654,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1640 | || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 | 1654 | || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 |
1641 | ) { | 1655 | ) { |
1642 | //FIXME: need to also check that last 10 bytes are zero | 1656 | //FIXME: need to also check that last 10 bytes are zero |
1643 | log1("chaddr does not match%s", ", ignoring packet"); // log2? | 1657 | log1("chaddr does not match%s", ", ignoring packet"); |
1644 | continue; | 1658 | continue; |
1645 | } | 1659 | } |
1646 | 1660 | ||
1647 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); | 1661 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
1648 | if (message == NULL) { | 1662 | if (message == NULL) { |
1649 | bb_info_msg("no message type option%s", ", ignoring packet"); | 1663 | log1("no message type option%s", ", ignoring packet"); |
1650 | continue; | 1664 | continue; |
1651 | } | 1665 | } |
1652 | 1666 | ||
@@ -1654,6 +1668,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1654 | case INIT_SELECTING: | 1668 | case INIT_SELECTING: |
1655 | /* Must be a DHCPOFFER */ | 1669 | /* Must be a DHCPOFFER */ |
1656 | if (*message == DHCPOFFER) { | 1670 | if (*message == DHCPOFFER) { |
1671 | struct in_addr temp_addr; | ||
1657 | uint8_t *temp; | 1672 | uint8_t *temp; |
1658 | 1673 | ||
1659 | /* What exactly is server's IP? There are several values. | 1674 | /* What exactly is server's IP? There are several values. |
@@ -1689,7 +1704,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1689 | move_from_unaligned32(server_addr, temp); | 1704 | move_from_unaligned32(server_addr, temp); |
1690 | } | 1705 | } |
1691 | /*xid = packet.xid; - already is */ | 1706 | /*xid = packet.xid; - already is */ |
1692 | requested_ip = packet.yiaddr; | 1707 | temp_addr.s_addr = requested_ip = packet.yiaddr; |
1708 | log1("received offer of %s", inet_ntoa(temp_addr)); | ||
1693 | 1709 | ||
1694 | /* enter requesting state */ | 1710 | /* enter requesting state */ |
1695 | client_data.state = REQUESTING; | 1711 | client_data.state = REQUESTING; |
@@ -1707,14 +1723,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1707 | char server_str[sizeof("255.255.255.255")]; | 1723 | char server_str[sizeof("255.255.255.255")]; |
1708 | uint8_t *temp; | 1724 | uint8_t *temp; |
1709 | 1725 | ||
1726 | change_listen_mode(LISTEN_NONE); | ||
1727 | |||
1710 | temp_addr.s_addr = server_addr; | 1728 | temp_addr.s_addr = server_addr; |
1711 | strcpy(server_str, inet_ntoa(temp_addr)); | 1729 | strcpy(server_str, inet_ntoa(temp_addr)); |
1712 | temp_addr.s_addr = packet.yiaddr; | 1730 | temp_addr.s_addr = packet.yiaddr; |
1713 | 1731 | ||
1732 | lease_remaining = 60 * 60; | ||
1714 | temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); | 1733 | temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); |
1715 | if (!temp) { | 1734 | if (temp) { |
1716 | lease_remaining = 60 * 60; | ||
1717 | } else { | ||
1718 | uint32_t lease; | 1735 | uint32_t lease; |
1719 | /* it IS unaligned sometimes, don't "optimize" */ | 1736 | /* it IS unaligned sometimes, don't "optimize" */ |
1720 | move_from_unaligned32(lease, temp); | 1737 | move_from_unaligned32(lease, temp); |
@@ -1758,8 +1775,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1758 | send_decline(/*xid,*/ server_addr, packet.yiaddr); | 1775 | send_decline(/*xid,*/ server_addr, packet.yiaddr); |
1759 | 1776 | ||
1760 | if (client_data.state != REQUESTING) | 1777 | if (client_data.state != REQUESTING) |
1761 | udhcp_run_script(NULL, "deconfig"); | 1778 | d4_run_script_deconfig(); |
1762 | change_listen_mode(LISTEN_RAW); | ||
1763 | client_data.state = INIT_SELECTING; | 1779 | client_data.state = INIT_SELECTING; |
1764 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1780 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1765 | requested_ip = 0; | 1781 | requested_ip = 0; |
@@ -1769,17 +1785,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1769 | } | 1785 | } |
1770 | } | 1786 | } |
1771 | #endif | 1787 | #endif |
1772 | |||
1773 | /* enter bound state */ | 1788 | /* enter bound state */ |
1774 | start = monotonic_sec(); | 1789 | start = monotonic_sec(); |
1775 | udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); | 1790 | d4_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); |
1776 | timeout = (unsigned)lease_remaining / 2; | 1791 | lease_remaining -= (unsigned)monotonic_sec() - start; |
1777 | //TODO: why / 2? | 1792 | if (lease_remaining < 0) |
1778 | timeout -= (unsigned)monotonic_sec() - start; | 1793 | lease_remaining = 0; |
1779 | packet_num = 0; | ||
1780 | |||
1781 | client_data.state = BOUND; | ||
1782 | change_listen_mode(LISTEN_NONE); | ||
1783 | if (opt & OPT_q) { /* quit after lease */ | 1794 | if (opt & OPT_q) { /* quit after lease */ |
1784 | goto ret0; | 1795 | goto ret0; |
1785 | } | 1796 | } |
@@ -1792,9 +1803,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1792 | opt = ((opt & ~OPT_b) | OPT_f); | 1803 | opt = ((opt & ~OPT_b) | OPT_f); |
1793 | } | 1804 | } |
1794 | #endif | 1805 | #endif |
1806 | BOUND_for_half_lease: | ||
1807 | timeout = (unsigned)lease_remaining / 2; | ||
1808 | client_data.state = BOUND; | ||
1795 | /* make future renew packets use different xid */ | 1809 | /* make future renew packets use different xid */ |
1796 | /* xid = random_xid(); ...but why bother? */ | 1810 | /* xid = random_xid(); ...but why bother? */ |
1797 | 1811 | packet_num = 0; | |
1798 | continue; /* back to main loop */ | 1812 | continue; /* back to main loop */ |
1799 | } | 1813 | } |
1800 | if (*message == DHCPNAK) { | 1814 | if (*message == DHCPNAK) { |
@@ -1818,11 +1832,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1818 | goto non_matching_svid; | 1832 | goto non_matching_svid; |
1819 | } | 1833 | } |
1820 | /* return to init state */ | 1834 | /* return to init state */ |
1835 | change_listen_mode(LISTEN_NONE); | ||
1821 | bb_info_msg("received %s", "DHCP NAK"); | 1836 | bb_info_msg("received %s", "DHCP NAK"); |
1822 | udhcp_run_script(&packet, "nak"); | 1837 | d4_run_script(&packet, "nak"); |
1823 | if (client_data.state != REQUESTING) | 1838 | if (client_data.state != REQUESTING) |
1824 | udhcp_run_script(NULL, "deconfig"); | 1839 | d4_run_script_deconfig(); |
1825 | change_listen_mode(LISTEN_RAW); | ||
1826 | sleep(3); /* avoid excessive network traffic */ | 1840 | sleep(3); /* avoid excessive network traffic */ |
1827 | client_data.state = INIT_SELECTING; | 1841 | client_data.state = INIT_SELECTING; |
1828 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1842 | client_data.first_secs = 0; /* make secs field count from 0 */ |