diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 370 |
1 files changed, 318 insertions, 52 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index e79feb7fe..758750907 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "common.h" | 24 | #include "common.h" |
25 | #include "dhcpd.h" | 25 | #include "dhcpd.h" |
26 | #include "dhcpc.h" | 26 | #include "dhcpc.h" |
27 | #include "options.h" | ||
28 | 27 | ||
29 | #include <asm/types.h> | 28 | #include <asm/types.h> |
30 | #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) | 29 | #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) |
@@ -36,34 +35,278 @@ | |||
36 | #endif | 35 | #endif |
37 | #include <linux/filter.h> | 36 | #include <linux/filter.h> |
38 | 37 | ||
38 | /* struct client_config_t client_config is in bb_common_bufsiz1 */ | ||
39 | 39 | ||
40 | static int sockfd = -1; | ||
41 | 40 | ||
42 | #define LISTEN_NONE 0 | 41 | /*** Script execution code ***/ |
43 | #define LISTEN_KERNEL 1 | ||
44 | #define LISTEN_RAW 2 | ||
45 | static smallint listen_mode; | ||
46 | 42 | ||
47 | /* initial state: (re)start DHCP negotiation */ | 43 | /* get a rough idea of how long an option will be (rounding up...) */ |
48 | #define INIT_SELECTING 0 | 44 | static const uint8_t len_of_option_as_string[] = { |
49 | /* discover was sent, DHCPOFFER reply received */ | 45 | [OPTION_IP] = sizeof("255.255.255.255 "), |
50 | #define REQUESTING 1 | 46 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, |
51 | /* select/renew was sent, DHCPACK reply received */ | 47 | [OPTION_STATIC_ROUTES]= sizeof("255.255.255.255/32 255.255.255.255 "), |
52 | #define BOUND 2 | 48 | [OPTION_STRING] = 1, |
53 | /* half of lease passed, want to renew it by sending unicast renew requests */ | 49 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
54 | #define RENEWING 3 | 50 | [OPTION_STR1035] = 1, |
55 | /* renew requests were not answered, lease is almost over, send broadcast renew */ | 51 | #endif |
56 | #define REBINDING 4 | 52 | [OPTION_BOOLEAN] = sizeof("yes "), |
57 | /* manually requested renew (SIGUSR1) */ | 53 | [OPTION_U8] = sizeof("255 "), |
58 | #define RENEW_REQUESTED 5 | 54 | [OPTION_U16] = sizeof("65535 "), |
59 | /* release, possibly manually requested (SIGUSR2) */ | 55 | [OPTION_S16] = sizeof("-32768 "), |
60 | #define RELEASED 6 | 56 | [OPTION_U32] = sizeof("4294967295 "), |
61 | static smallint state; | 57 | [OPTION_S32] = sizeof("-2147483684 "), |
58 | }; | ||
59 | |||
60 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ | ||
61 | static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) | ||
62 | { | ||
63 | return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); | ||
64 | } | ||
62 | 65 | ||
63 | /* struct client_config_t client_config is in bb_common_bufsiz1 */ | 66 | /* really simple implementation, just count the bits */ |
67 | static int mton(uint32_t mask) | ||
68 | { | ||
69 | int i = 0; | ||
70 | mask = ntohl(mask); /* 111110000-like bit pattern */ | ||
71 | while (mask) { | ||
72 | i++; | ||
73 | mask <<= 1; | ||
74 | } | ||
75 | return i; | ||
76 | } | ||
77 | |||
78 | /* Create "opt_name=opt_value" string */ | ||
79 | static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) | ||
80 | { | ||
81 | unsigned upper_length; | ||
82 | int len, type, optlen; | ||
83 | uint16_t val_u16; | ||
84 | int16_t val_s16; | ||
85 | uint32_t val_u32; | ||
86 | int32_t val_s32; | ||
87 | char *dest, *ret; | ||
88 | |||
89 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ | ||
90 | len = option[OPT_LEN - OPT_DATA]; | ||
91 | type = type_p->flags & OPTION_TYPE_MASK; | ||
92 | optlen = dhcp_option_lengths[type]; | ||
93 | upper_length = len_of_option_as_string[type] * (len / optlen); | ||
94 | |||
95 | dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); | ||
96 | dest += sprintf(ret, "%s=", opt_name); | ||
97 | |||
98 | while (len >= optlen) { | ||
99 | switch (type) { | ||
100 | case OPTION_IP_PAIR: | ||
101 | dest += sprint_nip(dest, "", option); | ||
102 | *dest++ = '/'; | ||
103 | option += 4; | ||
104 | optlen = 4; | ||
105 | case OPTION_IP: | ||
106 | dest += sprint_nip(dest, "", option); | ||
107 | // TODO: it can be a list only if (type_p->flags & OPTION_LIST). | ||
108 | // Should we bail out/warn if we see multi-ip option which is | ||
109 | // not allowed to be such? For example, DHCP_BROADCAST... | ||
110 | break; | ||
111 | case OPTION_BOOLEAN: | ||
112 | dest += sprintf(dest, *option ? "yes" : "no"); | ||
113 | break; | ||
114 | case OPTION_U8: | ||
115 | dest += sprintf(dest, "%u", *option); | ||
116 | break; | ||
117 | case OPTION_U16: | ||
118 | move_from_unaligned16(val_u16, option); | ||
119 | dest += sprintf(dest, "%u", ntohs(val_u16)); | ||
120 | break; | ||
121 | case OPTION_S16: | ||
122 | move_from_unaligned16(val_s16, option); | ||
123 | dest += sprintf(dest, "%d", ntohs(val_s16)); | ||
124 | break; | ||
125 | case OPTION_U32: | ||
126 | move_from_unaligned32(val_u32, option); | ||
127 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); | ||
128 | break; | ||
129 | case OPTION_S32: | ||
130 | move_from_unaligned32(val_s32, option); | ||
131 | dest += sprintf(dest, "%ld", (long) ntohl(val_s32)); | ||
132 | break; | ||
133 | case OPTION_STRING: | ||
134 | memcpy(dest, option, len); | ||
135 | dest[len] = '\0'; | ||
136 | return ret; /* Short circuit this case */ | ||
137 | case OPTION_STATIC_ROUTES: { | ||
138 | /* Option binary format: | ||
139 | * mask [one byte, 0..32] | ||
140 | * ip [big endian, 0..4 bytes depending on mask] | ||
141 | * router [big endian, 4 bytes] | ||
142 | * may be repeated | ||
143 | * | ||
144 | * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2" | ||
145 | */ | ||
146 | const char *pfx = ""; | ||
147 | |||
148 | while (len >= 1 + 4) { /* mask + 0-byte ip + router */ | ||
149 | uint32_t nip; | ||
150 | uint8_t *p; | ||
151 | unsigned mask; | ||
152 | int bytes; | ||
153 | |||
154 | mask = *option++; | ||
155 | if (mask > 32) | ||
156 | break; | ||
157 | len--; | ||
158 | |||
159 | nip = 0; | ||
160 | p = (void*) &nip; | ||
161 | bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */ | ||
162 | while (--bytes >= 0) { | ||
163 | *p++ = *option++; | ||
164 | len--; | ||
165 | } | ||
166 | if (len < 4) | ||
167 | break; | ||
168 | |||
169 | /* print ip/mask */ | ||
170 | dest += sprint_nip(dest, pfx, (void*) &nip); | ||
171 | pfx = " "; | ||
172 | dest += sprintf(dest, "/%u ", mask); | ||
173 | /* print router */ | ||
174 | dest += sprint_nip(dest, "", option); | ||
175 | option += 4; | ||
176 | len -= 4; | ||
177 | } | ||
178 | |||
179 | return ret; | ||
180 | } | ||
181 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
182 | case OPTION_STR1035: | ||
183 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ | ||
184 | dest = dname_dec(option, len, ret); | ||
185 | if (dest) { | ||
186 | free(ret); | ||
187 | return dest; | ||
188 | } | ||
189 | /* error. return "optname=" string */ | ||
190 | return ret; | ||
191 | #endif | ||
192 | } | ||
193 | option += optlen; | ||
194 | len -= optlen; | ||
195 | if (len <= 0) | ||
196 | break; | ||
197 | *dest++ = ' '; | ||
198 | *dest = '\0'; | ||
199 | } | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | /* put all the parameters into the environment */ | ||
204 | static char **fill_envp(struct dhcp_packet *packet) | ||
205 | { | ||
206 | int num_options = 0; | ||
207 | int i; | ||
208 | char **envp, **curr; | ||
209 | const char *opt_name; | ||
210 | uint8_t *temp; | ||
211 | uint8_t over = 0; | ||
212 | |||
213 | if (packet) { | ||
214 | for (i = 0; dhcp_options[i].code; i++) { | ||
215 | if (udhcp_get_option(packet, dhcp_options[i].code)) { | ||
216 | num_options++; | ||
217 | if (dhcp_options[i].code == DHCP_SUBNET) | ||
218 | num_options++; /* for mton */ | ||
219 | } | ||
220 | } | ||
221 | if (packet->siaddr_nip) | ||
222 | num_options++; | ||
223 | temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD); | ||
224 | if (temp) | ||
225 | over = *temp; | ||
226 | if (!(over & FILE_FIELD) && packet->file[0]) | ||
227 | num_options++; | ||
228 | if (!(over & SNAME_FIELD) && packet->sname[0]) | ||
229 | num_options++; | ||
230 | } | ||
231 | |||
232 | curr = envp = xzalloc(sizeof(char *) * (num_options + 3)); | ||
233 | *curr = xasprintf("interface=%s", client_config.interface); | ||
234 | putenv(*curr++); | ||
235 | |||
236 | if (packet == NULL) | ||
237 | return envp; | ||
238 | |||
239 | *curr = xmalloc(sizeof("ip=255.255.255.255")); | ||
240 | sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); | ||
241 | putenv(*curr++); | ||
242 | |||
243 | opt_name = dhcp_option_strings; | ||
244 | i = 0; | ||
245 | while (*opt_name) { | ||
246 | temp = udhcp_get_option(packet, dhcp_options[i].code); | ||
247 | if (!temp) | ||
248 | goto next; | ||
249 | *curr = xmalloc_optname_optval(temp, &dhcp_options[i], opt_name); | ||
250 | putenv(*curr++); | ||
251 | |||
252 | /* Fill in a subnet bits option for things like /24 */ | ||
253 | if (dhcp_options[i].code == DHCP_SUBNET) { | ||
254 | uint32_t subnet; | ||
255 | move_from_unaligned32(subnet, temp); | ||
256 | *curr = xasprintf("mask=%d", mton(subnet)); | ||
257 | putenv(*curr++); | ||
258 | } | ||
259 | next: | ||
260 | opt_name += strlen(opt_name) + 1; | ||
261 | i++; | ||
262 | } | ||
263 | if (packet->siaddr_nip) { | ||
264 | *curr = xmalloc(sizeof("siaddr=255.255.255.255")); | ||
265 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); | ||
266 | putenv(*curr++); | ||
267 | } | ||
268 | if (!(over & FILE_FIELD) && packet->file[0]) { | ||
269 | /* watch out for invalid packets */ | ||
270 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); | ||
271 | putenv(*curr++); | ||
272 | } | ||
273 | if (!(over & SNAME_FIELD) && packet->sname[0]) { | ||
274 | /* watch out for invalid packets */ | ||
275 | *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); | ||
276 | putenv(*curr++); | ||
277 | } | ||
278 | return envp; | ||
279 | } | ||
280 | |||
281 | /* Call a script with a par file and env vars */ | ||
282 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | ||
283 | { | ||
284 | char **envp, **curr; | ||
285 | char *argv[3]; | ||
286 | |||
287 | if (client_config.script == NULL) | ||
288 | return; | ||
289 | |||
290 | envp = fill_envp(packet); | ||
291 | |||
292 | /* call script */ | ||
293 | log1("Executing %s %s", client_config.script, name); | ||
294 | argv[0] = (char*) client_config.script; | ||
295 | argv[1] = (char*) name; | ||
296 | argv[2] = NULL; | ||
297 | spawn_and_wait(argv); | ||
298 | |||
299 | for (curr = envp; *curr; curr++) { | ||
300 | log2(" %s", *curr); | ||
301 | bb_unsetenv(*curr); | ||
302 | free(*curr); | ||
303 | } | ||
304 | free(envp); | ||
305 | } | ||
64 | 306 | ||
65 | 307 | ||
66 | /* Create a random xid */ | 308 | /*** Sending/receiving packets ***/ |
309 | |||
67 | static ALWAYS_INLINE uint32_t random_xid(void) | 310 | static ALWAYS_INLINE uint32_t random_xid(void) |
68 | { | 311 | { |
69 | return rand(); | 312 | return rand(); |
@@ -75,16 +318,16 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
75 | udhcp_init_header(packet, type); | 318 | udhcp_init_header(packet, type); |
76 | memcpy(packet->chaddr, client_config.client_mac, 6); | 319 | memcpy(packet->chaddr, client_config.client_mac, 6); |
77 | if (client_config.clientid) | 320 | if (client_config.clientid) |
78 | add_option_string(packet->options, client_config.clientid); | 321 | udhcp_add_option_string(packet->options, client_config.clientid); |
79 | if (client_config.hostname) | 322 | if (client_config.hostname) |
80 | add_option_string(packet->options, client_config.hostname); | 323 | udhcp_add_option_string(packet->options, client_config.hostname); |
81 | if (client_config.fqdn) | 324 | if (client_config.fqdn) |
82 | add_option_string(packet->options, client_config.fqdn); | 325 | udhcp_add_option_string(packet->options, client_config.fqdn); |
83 | if (type != DHCPDECLINE | 326 | if (type != DHCPDECLINE |
84 | && type != DHCPRELEASE | 327 | && type != DHCPRELEASE |
85 | && client_config.vendorclass | 328 | && client_config.vendorclass |
86 | ) { | 329 | ) { |
87 | add_option_string(packet->options, client_config.vendorclass); | 330 | udhcp_add_option_string(packet->options, client_config.vendorclass); |
88 | } | 331 | } |
89 | } | 332 | } |
90 | 333 | ||
@@ -94,7 +337,7 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
94 | static void add_param_req_option(struct dhcp_packet *packet) | 337 | static void add_param_req_option(struct dhcp_packet *packet) |
95 | { | 338 | { |
96 | uint8_t c; | 339 | uint8_t c; |
97 | int end = end_option(packet->options); | 340 | int end = udhcp_end_option(packet->options); |
98 | int i, len = 0; | 341 | int i, len = 0; |
99 | 342 | ||
100 | for (i = 0; (c = dhcp_options[i].code) != 0; i++) { | 343 | for (i = 0; (c = dhcp_options[i].code) != 0; i++) { |
@@ -148,10 +391,10 @@ static int send_discover(uint32_t xid, uint32_t requested) | |||
148 | init_packet(&packet, DHCPDISCOVER); | 391 | init_packet(&packet, DHCPDISCOVER); |
149 | packet.xid = xid; | 392 | packet.xid = xid; |
150 | if (requested) | 393 | if (requested) |
151 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 394 | udhcp_add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
152 | /* Explicitly saying that we want RFC-compliant packets helps | 395 | /* Explicitly saying that we want RFC-compliant packets helps |
153 | * some buggy DHCP servers to NOT send bigger packets */ | 396 | * some buggy DHCP servers to NOT send bigger packets */ |
154 | add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576)); | 397 | udhcp_add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576)); |
155 | add_param_req_option(&packet); | 398 | add_param_req_option(&packet); |
156 | 399 | ||
157 | bb_info_msg("Sending discover..."); | 400 | bb_info_msg("Sending discover..."); |
@@ -169,8 +412,8 @@ static int send_select(uint32_t xid, uint32_t server, uint32_t requested) | |||
169 | 412 | ||
170 | init_packet(&packet, DHCPREQUEST); | 413 | init_packet(&packet, DHCPREQUEST); |
171 | packet.xid = xid; | 414 | packet.xid = xid; |
172 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 415 | udhcp_add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
173 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 416 | udhcp_add_simple_option(packet.options, DHCP_SERVER_ID, server); |
174 | add_param_req_option(&packet); | 417 | add_param_req_option(&packet); |
175 | 418 | ||
176 | addr.s_addr = requested; | 419 | addr.s_addr = requested; |
@@ -204,8 +447,8 @@ static int send_decline(uint32_t xid, uint32_t server, uint32_t requested) | |||
204 | 447 | ||
205 | init_packet(&packet, DHCPDECLINE); | 448 | init_packet(&packet, DHCPDECLINE); |
206 | packet.xid = xid; | 449 | packet.xid = xid; |
207 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 450 | udhcp_add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
208 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 451 | udhcp_add_simple_option(packet.options, DHCP_SERVER_ID, server); |
209 | 452 | ||
210 | bb_info_msg("Sending decline..."); | 453 | bb_info_msg("Sending decline..."); |
211 | return raw_bcast_from_client_config_ifindex(&packet); | 454 | return raw_bcast_from_client_config_ifindex(&packet); |
@@ -221,7 +464,7 @@ static int send_release(uint32_t server, uint32_t ciaddr) | |||
221 | packet.xid = random_xid(); | 464 | packet.xid = random_xid(); |
222 | packet.ciaddr = ciaddr; | 465 | packet.ciaddr = ciaddr; |
223 | 466 | ||
224 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 467 | udhcp_add_simple_option(packet.options, DHCP_SERVER_ID, server); |
225 | 468 | ||
226 | bb_info_msg("Sending release..."); | 469 | bb_info_msg("Sending release..."); |
227 | return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); | 470 | return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); |
@@ -297,6 +540,32 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
297 | return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); | 540 | return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); |
298 | } | 541 | } |
299 | 542 | ||
543 | |||
544 | /*** Main ***/ | ||
545 | |||
546 | static int sockfd = -1; | ||
547 | |||
548 | #define LISTEN_NONE 0 | ||
549 | #define LISTEN_KERNEL 1 | ||
550 | #define LISTEN_RAW 2 | ||
551 | static smallint listen_mode; | ||
552 | |||
553 | /* initial state: (re)start DHCP negotiation */ | ||
554 | #define INIT_SELECTING 0 | ||
555 | /* discover was sent, DHCPOFFER reply received */ | ||
556 | #define REQUESTING 1 | ||
557 | /* select/renew was sent, DHCPACK reply received */ | ||
558 | #define BOUND 2 | ||
559 | /* half of lease passed, want to renew it by sending unicast renew requests */ | ||
560 | #define RENEWING 3 | ||
561 | /* renew requests were not answered, lease is almost over, send broadcast renew */ | ||
562 | #define REBINDING 4 | ||
563 | /* manually requested renew (SIGUSR1) */ | ||
564 | #define RENEW_REQUESTED 5 | ||
565 | /* release, possibly manually requested (SIGUSR2) */ | ||
566 | #define RELEASED 6 | ||
567 | static smallint state; | ||
568 | |||
300 | static int udhcp_raw_socket(int ifindex) | 569 | static int udhcp_raw_socket(int ifindex) |
301 | { | 570 | { |
302 | int fd; | 571 | int fd; |
@@ -368,7 +637,6 @@ static int udhcp_raw_socket(int ifindex) | |||
368 | return fd; | 637 | return fd; |
369 | } | 638 | } |
370 | 639 | ||
371 | /* just a little helper */ | ||
372 | static void change_listen_mode(int new_mode) | 640 | static void change_listen_mode(int new_mode) |
373 | { | 641 | { |
374 | log1("Entering listen mode: %s", | 642 | log1("Entering listen mode: %s", |
@@ -389,7 +657,6 @@ static void change_listen_mode(int new_mode) | |||
389 | /* else LISTEN_NONE: sockfd stays closed */ | 657 | /* else LISTEN_NONE: sockfd stays closed */ |
390 | } | 658 | } |
391 | 659 | ||
392 | /* perform a renew */ | ||
393 | static void perform_renew(void) | 660 | static void perform_renew(void) |
394 | { | 661 | { |
395 | bb_info_msg("Performing a DHCP renew"); | 662 | bb_info_msg("Performing a DHCP renew"); |
@@ -412,7 +679,6 @@ static void perform_renew(void) | |||
412 | } | 679 | } |
413 | } | 680 | } |
414 | 681 | ||
415 | /* perform a release */ | ||
416 | static void perform_release(uint32_t requested_ip, uint32_t server_addr) | 682 | static void perform_release(uint32_t requested_ip, uint32_t server_addr) |
417 | { | 683 | { |
418 | char buffer[sizeof("255.255.255.255")]; | 684 | char buffer[sizeof("255.255.255.255")]; |
@@ -434,16 +700,6 @@ static void perform_release(uint32_t requested_ip, uint32_t server_addr) | |||
434 | state = RELEASED; | 700 | state = RELEASED; |
435 | } | 701 | } |
436 | 702 | ||
437 | #if BB_MMU | ||
438 | static void client_background(void) | ||
439 | { | ||
440 | bb_daemonize(0); | ||
441 | logmode &= ~LOGMODE_STDIO; | ||
442 | /* rewrite pidfile, as our pid is different now */ | ||
443 | write_pidfile(client_config.pidfile); | ||
444 | } | ||
445 | #endif | ||
446 | |||
447 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | 703 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) |
448 | { | 704 | { |
449 | uint8_t *storage; | 705 | uint8_t *storage; |
@@ -455,6 +711,16 @@ static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | |||
455 | return storage; | 711 | return storage; |
456 | } | 712 | } |
457 | 713 | ||
714 | #if BB_MMU | ||
715 | static void client_background(void) | ||
716 | { | ||
717 | bb_daemonize(0); | ||
718 | logmode &= ~LOGMODE_STDIO; | ||
719 | /* rewrite pidfile, as our pid is different now */ | ||
720 | write_pidfile(client_config.pidfile); | ||
721 | } | ||
722 | #endif | ||
723 | |||
458 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 724 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
459 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) | 725 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) |
460 | { | 726 | { |
@@ -541,7 +807,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
541 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) | 807 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) |
542 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) | 808 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) |
543 | client_config.interface = "eth0"; | 809 | client_config.interface = "eth0"; |
544 | client_config.script = DEFAULT_SCRIPT; | 810 | client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
545 | str_V = "udhcp "BB_VER; | 811 | str_V = "udhcp "BB_VER; |
546 | 812 | ||
547 | /* Parse command line */ | 813 | /* Parse command line */ |
@@ -861,7 +1127,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
861 | continue; | 1127 | continue; |
862 | } | 1128 | } |
863 | 1129 | ||
864 | message = get_option(&packet, DHCP_MESSAGE_TYPE); | 1130 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
865 | if (message == NULL) { | 1131 | if (message == NULL) { |
866 | bb_error_msg("no message type option, ignoring packet"); | 1132 | bb_error_msg("no message type option, ignoring packet"); |
867 | continue; | 1133 | continue; |
@@ -872,7 +1138,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
872 | /* Must be a DHCPOFFER to one of our xid's */ | 1138 | /* Must be a DHCPOFFER to one of our xid's */ |
873 | if (*message == DHCPOFFER) { | 1139 | if (*message == DHCPOFFER) { |
874 | /* TODO: why we don't just fetch server's IP from IP header? */ | 1140 | /* TODO: why we don't just fetch server's IP from IP header? */ |
875 | temp = get_option(&packet, DHCP_SERVER_ID); | 1141 | temp = udhcp_get_option(&packet, DHCP_SERVER_ID); |
876 | if (!temp) { | 1142 | if (!temp) { |
877 | bb_error_msg("no server ID in message"); | 1143 | bb_error_msg("no server ID in message"); |
878 | continue; | 1144 | continue; |
@@ -895,7 +1161,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
895 | case RENEW_REQUESTED: | 1161 | case RENEW_REQUESTED: |
896 | case REBINDING: | 1162 | case REBINDING: |
897 | if (*message == DHCPACK) { | 1163 | if (*message == DHCPACK) { |
898 | temp = get_option(&packet, DHCP_LEASE_TIME); | 1164 | temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); |
899 | if (!temp) { | 1165 | if (!temp) { |
900 | bb_error_msg("no lease time with ACK, using 1 hour lease"); | 1166 | bb_error_msg("no lease time with ACK, using 1 hour lease"); |
901 | lease_seconds = 60 * 60; | 1167 | lease_seconds = 60 * 60; |