diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2002-08-23 14:31:28 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2002-08-23 14:31:28 +0000 |
commit | 0be933b5057d33e61aa8b1e3806666765b621f2f (patch) | |
tree | 773d0e2464aa351f8fc2806199fead56d0a04a9d | |
parent | 50812fff219a3d0b9eccb9ff9647d6d66a7934c7 (diff) | |
download | busybox-w32-0be933b5057d33e61aa8b1e3806666765b621f2f.tar.gz busybox-w32-0be933b5057d33e61aa8b1e3806666765b621f2f.tar.bz2 busybox-w32-0be933b5057d33e61aa8b1e3806666765b621f2f.zip |
Use static instead of extern, braces around if's, run through indent
-rw-r--r-- | networking/udhcpc.c | 702 |
1 files changed, 372 insertions, 330 deletions
diff --git a/networking/udhcpc.c b/networking/udhcpc.c index 5f9b5c488..01e6f5ef9 100644 --- a/networking/udhcpc.c +++ b/networking/udhcpc.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | #include <sys/time.h> | 25 | #include <sys/time.h> |
26 | #include <sys/types.h> | 26 | #include <sys/types.h> |
@@ -41,7 +41,7 @@ | |||
41 | #include <netinet/udp.h> | 41 | #include <netinet/udp.h> |
42 | #include <sys/types.h> | 42 | #include <sys/types.h> |
43 | #include <sys/wait.h> | 43 | #include <sys/wait.h> |
44 | 44 | ||
45 | #if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 | 45 | #if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 |
46 | #include <netpacket/packet.h> | 46 | #include <netpacket/packet.h> |
47 | #include <net/ethernet.h> | 47 | #include <net/ethernet.h> |
@@ -53,11 +53,12 @@ | |||
53 | #include "libbb.h" | 53 | #include "libbb.h" |
54 | 54 | ||
55 | static int state; | 55 | static int state; |
56 | static unsigned long requested_ip; /* = 0 */ | 56 | static unsigned long requested_ip; /* = 0 */ |
57 | static unsigned long server_addr; | 57 | static unsigned long server_addr; |
58 | static unsigned long timeout; | 58 | static unsigned long timeout; |
59 | static int packet_num; /* = 0 */ | 59 | static int packet_num; /* = 0 */ |
60 | static int fd_main; | 60 | static int fd_main; |
61 | |||
61 | /* #define DEBUG */ | 62 | /* #define DEBUG */ |
62 | 63 | ||
63 | #define VERSION "0.9.7" | 64 | #define VERSION "0.9.7" |
@@ -148,7 +149,7 @@ static int listen_mode; | |||
148 | #define OPT_DATA 2 | 149 | #define OPT_DATA 2 |
149 | 150 | ||
150 | enum { | 151 | enum { |
151 | OPTION_IP=1, | 152 | OPTION_IP = 1, |
152 | OPTION_IP_PAIR, | 153 | OPTION_IP_PAIR, |
153 | OPTION_STRING, | 154 | OPTION_STRING, |
154 | OPTION_BOOLEAN, | 155 | OPTION_BOOLEAN, |
@@ -159,8 +160,8 @@ enum { | |||
159 | OPTION_S32 | 160 | OPTION_S32 |
160 | }; | 161 | }; |
161 | 162 | ||
162 | #define OPTION_REQ 0x10 /* have the client request this option */ | 163 | #define OPTION_REQ 0x10 /* have the client request this option */ |
163 | #define OPTION_LIST 0x20 /* There can be a list of 1 or more of these */ | 164 | #define OPTION_LIST 0x20 /* There can be a list of 1 or more of these */ |
164 | 165 | ||
165 | #ifdef SYSLOG | 166 | #ifdef SYSLOG |
166 | # define LOG(level, str, args...) do { printf(str, ## args); \ | 167 | # define LOG(level, str, args...) do { printf(str, ## args); \ |
@@ -189,20 +190,6 @@ enum { | |||
189 | # define DEBUG(level, str, args...) do {;} while(0) | 190 | # define DEBUG(level, str, args...) do {;} while(0) |
190 | #endif | 191 | #endif |
191 | 192 | ||
192 | struct client_config_t { | ||
193 | char foreground; /* Do not fork */ | ||
194 | char quit_after_lease; /* Quit after obtaining lease */ | ||
195 | char abort_if_no_lease; /* Abort if no lease */ | ||
196 | char *interface; /* The name of the interface to use */ | ||
197 | char *pidfile; /* Optionally store the process ID */ | ||
198 | char *script; /* User script to run at dhcp events */ | ||
199 | unsigned char *clientid; /* Optional client id to use */ | ||
200 | unsigned char *hostname; /* Optional hostname to use */ | ||
201 | int ifindex; /* Index number of the interface to use */ | ||
202 | unsigned char arp[6]; /* Our arp address */ | ||
203 | }; | ||
204 | extern struct client_config_t client_config; | ||
205 | |||
206 | struct dhcpMessage { | 193 | struct dhcpMessage { |
207 | u_int8_t op; | 194 | u_int8_t op; |
208 | u_int8_t htype; | 195 | u_int8_t htype; |
@@ -219,21 +206,34 @@ struct dhcpMessage { | |||
219 | u_int8_t sname[64]; | 206 | u_int8_t sname[64]; |
220 | u_int8_t file[128]; | 207 | u_int8_t file[128]; |
221 | u_int32_t cookie; | 208 | u_int32_t cookie; |
222 | u_int8_t options[308]; /* 312 - cookie */ | 209 | u_int8_t options[308]; /* 312 - cookie */ |
210 | }; | ||
211 | |||
212 | struct client_config_t { | ||
213 | char foreground; /* Do not fork */ | ||
214 | char quit_after_lease; /* Quit after obtaining lease */ | ||
215 | char abort_if_no_lease; /* Abort if no lease */ | ||
216 | char *interface; /* The name of the interface to use */ | ||
217 | char *pidfile; /* Optionally store the process ID */ | ||
218 | char *script; /* User script to run at dhcp events */ | ||
219 | unsigned char *clientid; /* Optional client id to use */ | ||
220 | unsigned char *hostname; /* Optional hostname to use */ | ||
221 | int ifindex; /* Index number of the interface to use */ | ||
222 | unsigned char arp[6]; /* Our arp address */ | ||
223 | }; | 223 | }; |
224 | 224 | ||
225 | struct client_config_t client_config = { | 225 | struct client_config_t client_config = { |
226 | /* Default options. */ | 226 | /* Default options. */ |
227 | abort_if_no_lease: 0, | 227 | abort_if_no_lease:0, |
228 | foreground: 0, | 228 | foreground:0, |
229 | quit_after_lease: 0, | 229 | quit_after_lease:0, |
230 | interface: "eth0", | 230 | interface:"eth0", |
231 | pidfile: NULL, | 231 | pidfile:NULL, |
232 | script: DEFAULT_SCRIPT, | 232 | script:DEFAULT_SCRIPT, |
233 | clientid: NULL, | 233 | clientid:NULL, |
234 | hostname: NULL, | 234 | hostname:NULL, |
235 | ifindex: 0, | 235 | ifindex:0, |
236 | arp: "\0\0\0\0\0\0", /* appease gcc-3.0 */ | 236 | arp:"\0\0\0\0\0\0", /* appease gcc-3.0 */ |
237 | }; | 237 | }; |
238 | 238 | ||
239 | struct dhcp_option { | 239 | struct dhcp_option { |
@@ -249,70 +249,72 @@ struct udp_dhcp_packet { | |||
249 | }; | 249 | }; |
250 | 250 | ||
251 | static const struct dhcp_option options[] = { | 251 | static const struct dhcp_option options[] = { |
252 | /* name[10] flags code */ | 252 | /* name[10] flags code */ |
253 | {"subnet", OPTION_IP | OPTION_REQ, 0x01}, | 253 | {"subnet", OPTION_IP | OPTION_REQ, 0x01}, |
254 | {"timezone", OPTION_S32, 0x02}, | 254 | {"timezone", OPTION_S32, 0x02}, |
255 | {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, | 255 | {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, |
256 | {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, | 256 | {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, |
257 | {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, | 257 | {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, |
258 | {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, | 258 | {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, |
259 | {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, | 259 | {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, |
260 | {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, | 260 | {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, |
261 | {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, | 261 | {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, |
262 | {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, | 262 | {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, |
263 | {"bootsize", OPTION_U16, 0x0d}, | 263 | {"bootsize", OPTION_U16, 0x0d}, |
264 | {"domain", OPTION_STRING | OPTION_REQ, 0x0f}, | 264 | {"domain", OPTION_STRING | OPTION_REQ, 0x0f}, |
265 | {"swapsvr", OPTION_IP, 0x10}, | 265 | {"swapsvr", OPTION_IP, 0x10}, |
266 | {"rootpath", OPTION_STRING, 0x11}, | 266 | {"rootpath", OPTION_STRING, 0x11}, |
267 | {"ipttl", OPTION_U8, 0x17}, | 267 | {"ipttl", OPTION_U8, 0x17}, |
268 | {"mtu", OPTION_U16, 0x1a}, | 268 | {"mtu", OPTION_U16, 0x1a}, |
269 | {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, | 269 | {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, |
270 | {"ntpsrv", OPTION_IP | OPTION_LIST, 0x2a}, | 270 | {"ntpsrv", OPTION_IP | OPTION_LIST, 0x2a}, |
271 | {"wins", OPTION_IP | OPTION_LIST, 0x2c}, | 271 | {"wins", OPTION_IP | OPTION_LIST, 0x2c}, |
272 | {"requestip", OPTION_IP, 0x32}, | 272 | {"requestip", OPTION_IP, 0x32}, |
273 | {"lease", OPTION_U32, 0x33}, | 273 | {"lease", OPTION_U32, 0x33}, |
274 | {"dhcptype", OPTION_U8, 0x35}, | 274 | {"dhcptype", OPTION_U8, 0x35}, |
275 | {"serverid", OPTION_IP, 0x36}, | 275 | {"serverid", OPTION_IP, 0x36}, |
276 | {"message", OPTION_STRING, 0x38}, | 276 | {"message", OPTION_STRING, 0x38}, |
277 | {"tftp", OPTION_STRING, 0x42}, | 277 | {"tftp", OPTION_STRING, 0x42}, |
278 | {"bootfile", OPTION_STRING, 0x43}, | 278 | {"bootfile", OPTION_STRING, 0x43}, |
279 | {"", 0x00, 0x00} | 279 | {"", 0x00, 0x00} |
280 | }; | 280 | }; |
281 | 281 | ||
282 | /* Lengths of the different option types */ | 282 | /* Lengths of the different option types */ |
283 | static const unsigned char option_lengths[] = { | 283 | static const unsigned char option_lengths[] = { |
284 | [OPTION_IP] = 4, | 284 | [OPTION_IP] = 4, |
285 | [OPTION_IP_PAIR] = 8, | 285 | [OPTION_IP_PAIR] = 8, |
286 | [OPTION_BOOLEAN] = 1, | 286 | [OPTION_BOOLEAN] = 1, |
287 | [OPTION_STRING] = 1, | 287 | [OPTION_STRING] = 1, |
288 | [OPTION_U8] = 1, | 288 | [OPTION_U8] = 1, |
289 | [OPTION_U16] = 2, | 289 | [OPTION_U16] = 2, |
290 | [OPTION_S16] = 2, | 290 | [OPTION_S16] = 2, |
291 | [OPTION_U32] = 4, | 291 | [OPTION_U32] = 4, |
292 | [OPTION_S32] = 4 | 292 | [OPTION_S32] = 4 |
293 | }; | 293 | }; |
294 | 294 | ||
295 | /* get a rough idea of how long an option will be (rounding up...) */ | 295 | /* get a rough idea of how long an option will be (rounding up...) */ |
296 | static const unsigned char max_option_length[] = { | 296 | static const unsigned char max_option_length[] = { |
297 | [OPTION_IP] = sizeof("255.255.255.255 "), | 297 | [OPTION_IP] = sizeof("255.255.255.255 "), |
298 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, | 298 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, |
299 | [OPTION_STRING] = 1, | 299 | [OPTION_STRING] = 1, |
300 | [OPTION_BOOLEAN] = sizeof("yes "), | 300 | [OPTION_BOOLEAN] = sizeof("yes "), |
301 | [OPTION_U8] = sizeof("255 "), | 301 | [OPTION_U8] = sizeof("255 "), |
302 | [OPTION_U16] = sizeof("65535 "), | 302 | [OPTION_U16] = sizeof("65535 "), |
303 | [OPTION_S16] = sizeof("-32768 "), | 303 | [OPTION_S16] = sizeof("-32768 "), |
304 | [OPTION_U32] = sizeof("4294967295 "), | 304 | [OPTION_U32] = sizeof("4294967295 "), |
305 | [OPTION_S32] = sizeof("-2147483684 "), | 305 | [OPTION_S32] = sizeof("-2147483684 "), |
306 | }; | 306 | }; |
307 | 307 | ||
308 | /* return the position of the 'end' option (no bounds checking) */ | 308 | /* return the position of the 'end' option (no bounds checking) */ |
309 | static int end_option(unsigned char *optionptr) | 309 | static int end_option(unsigned char *optionptr) |
310 | { | 310 | { |
311 | int i = 0; | 311 | int i = 0; |
312 | 312 | ||
313 | while (optionptr[i] != DHCP_END) { | 313 | while (optionptr[i] != DHCP_END) { |
314 | if (optionptr[i] == DHCP_PADDING) i++; | 314 | if (optionptr[i] == DHCP_PADDING) |
315 | else i += optionptr[i + OPT_LEN] + 2; | 315 | i++; |
316 | else | ||
317 | i += optionptr[i + OPT_LEN] + 2; | ||
316 | } | 318 | } |
317 | return i; | 319 | return i; |
318 | } | 320 | } |
@@ -322,10 +324,11 @@ static int end_option(unsigned char *optionptr) | |||
322 | static int add_option_string(unsigned char *optionptr, unsigned char *string) | 324 | static int add_option_string(unsigned char *optionptr, unsigned char *string) |
323 | { | 325 | { |
324 | int end = end_option(optionptr); | 326 | int end = end_option(optionptr); |
325 | 327 | ||
326 | /* end position + string length + option code/length + end option */ | 328 | /* end position + string length + option code/length + end option */ |
327 | if (end + string[OPT_LEN] + 2 + 1 >= 308) { | 329 | if (end + string[OPT_LEN] + 2 + 1 >= 308) { |
328 | LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", string[OPT_CODE]); | 330 | LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", |
331 | string[OPT_CODE]); | ||
329 | return 0; | 332 | return 0; |
330 | } | 333 | } |
331 | DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]); | 334 | DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]); |
@@ -335,7 +338,8 @@ static int add_option_string(unsigned char *optionptr, unsigned char *string) | |||
335 | } | 338 | } |
336 | 339 | ||
337 | /* add a one to four byte option to a packet */ | 340 | /* add a one to four byte option to a packet */ |
338 | static int add_simple_option(unsigned char *optionptr, unsigned char code, u_int32_t data) | 341 | static int add_simple_option(unsigned char *optionptr, unsigned char code, |
342 | u_int32_t data) | ||
339 | { | 343 | { |
340 | char length = 0; | 344 | char length = 0; |
341 | int i; | 345 | int i; |
@@ -344,55 +348,40 @@ static int add_simple_option(unsigned char *optionptr, unsigned char code, u_int | |||
344 | u_int16_t *u16; | 348 | u_int16_t *u16; |
345 | u_int32_t *u32; | 349 | u_int32_t *u32; |
346 | u_int32_t aligned; | 350 | u_int32_t aligned; |
351 | |||
347 | u8 = (unsigned char *) &aligned; | 352 | u8 = (unsigned char *) &aligned; |
348 | u16 = (u_int16_t *) &aligned; | 353 | u16 = (u_int16_t *) & aligned; |
349 | u32 = &aligned; | 354 | u32 = &aligned; |
350 | 355 | ||
351 | for (i = 0; options[i].code; i++) | 356 | for (i = 0; options[i].code; i++) |
352 | if (options[i].code == code) { | 357 | if (options[i].code == code) { |
353 | length = option_lengths[options[i].flags & TYPE_MASK]; | 358 | length = option_lengths[options[i].flags & TYPE_MASK]; |
354 | } | 359 | } |
355 | 360 | ||
356 | if (!length) { | 361 | if (!length) { |
357 | DEBUG(LOG_ERR, "Could not add option 0x%02x", code); | 362 | DEBUG(LOG_ERR, "Could not add option 0x%02x", code); |
358 | return 0; | 363 | return 0; |
359 | } | 364 | } |
360 | 365 | ||
361 | option[OPT_CODE] = code; | 366 | option[OPT_CODE] = code; |
362 | option[OPT_LEN] = length; | 367 | option[OPT_LEN] = length; |
363 | 368 | ||
364 | switch (length) { | 369 | switch (length) { |
365 | case 1: *u8 = data; break; | 370 | case 1: |
366 | case 2: *u16 = data; break; | 371 | *u8 = data; |
367 | case 4: *u32 = data; break; | 372 | break; |
373 | case 2: | ||
374 | *u16 = data; | ||
375 | break; | ||
376 | case 4: | ||
377 | *u32 = data; | ||
378 | break; | ||
368 | } | 379 | } |
369 | 380 | ||
370 | memcpy(option + 2, &aligned, length); | 381 | memcpy(option + 2, &aligned, length); |
371 | return add_option_string(optionptr, option); | 382 | return add_option_string(optionptr, option); |
372 | } | 383 | } |
373 | #if 0 | 384 | |
374 | void init_header(struct dhcpMessage *packet, char type) | ||
375 | { | ||
376 | memset(packet, 0, sizeof(struct dhcpMessage)); | ||
377 | switch (type) { | ||
378 | case DHCPDISCOVER: | ||
379 | case DHCPREQUEST: | ||
380 | case DHCPRELEASE: | ||
381 | case DHCPINFORM: | ||
382 | packet->op = BOOTREQUEST; | ||
383 | break; | ||
384 | case DHCPOFFER: | ||
385 | case DHCPACK: | ||
386 | case DHCPNAK: | ||
387 | packet->op = BOOTREPLY; | ||
388 | } | ||
389 | packet->htype = ETH_10MB; | ||
390 | packet->hlen = ETH_10MB_LEN; | ||
391 | packet->cookie = htonl(DHCP_MAGIC); | ||
392 | packet->options[0] = DHCP_END; | ||
393 | add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type); | ||
394 | } | ||
395 | #endif | ||
396 | static u_int16_t checksum(void *addr, int count) | 385 | static u_int16_t checksum(void *addr, int count) |
397 | { | 386 | { |
398 | /* Compute Internet Checksum for "count" bytes | 387 | /* Compute Internet Checksum for "count" bytes |
@@ -401,26 +390,29 @@ static u_int16_t checksum(void *addr, int count) | |||
401 | register int32_t sum = 0; | 390 | register int32_t sum = 0; |
402 | u_int16_t *source = (u_int16_t *) addr; | 391 | u_int16_t *source = (u_int16_t *) addr; |
403 | 392 | ||
404 | while( count > 1 ) { | 393 | while (count > 1) { |
405 | /* This is the inner loop */ | 394 | /* This is the inner loop */ |
406 | sum += *source++; | 395 | sum += *source++; |
407 | count -= 2; | 396 | count -= 2; |
408 | } | 397 | } |
409 | 398 | ||
410 | /* Add left-over byte, if any */ | 399 | /* Add left-over byte, if any */ |
411 | if( count > 0 ) | 400 | if (count > 0) { |
412 | sum += * (unsigned char *) source; | 401 | sum += *(unsigned char *) source; |
402 | } | ||
413 | 403 | ||
414 | /* Fold 32-bit sum to 16 bits */ | 404 | /* Fold 32-bit sum to 16 bits */ |
415 | while (sum>>16) | 405 | while (sum >> 16) { |
416 | sum = (sum & 0xffff) + (sum >> 16); | 406 | sum = (sum & 0xffff) + (sum >> 16); |
407 | } | ||
417 | 408 | ||
418 | return ~sum; | 409 | return ~sum; |
419 | } | 410 | } |
420 | 411 | ||
421 | /* Constuct a ip/udp header for a packet, and specify the source and dest hardware address */ | 412 | /* Constuct a ip/udp header for a packet, and specify the source and dest hardware address */ |
422 | static int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port, | 413 | static int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, |
423 | u_int32_t dest_ip, int dest_port, unsigned char *dest_arp, int ifindex) | 414 | int source_port, u_int32_t dest_ip, int dest_port, |
415 | unsigned char *dest_arp, int ifindex) | ||
424 | { | 416 | { |
425 | int l_fd; | 417 | int l_fd; |
426 | int result; | 418 | int result; |
@@ -431,16 +423,16 @@ static int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int sour | |||
431 | DEBUG(LOG_ERR, "socket call failed: %s", sys_errlist[errno]); | 423 | DEBUG(LOG_ERR, "socket call failed: %s", sys_errlist[errno]); |
432 | return -1; | 424 | return -1; |
433 | } | 425 | } |
434 | 426 | ||
435 | memset(&dest, 0, sizeof(dest)); | 427 | memset(&dest, 0, sizeof(dest)); |
436 | memset(&packet, 0, sizeof(packet)); | 428 | memset(&packet, 0, sizeof(packet)); |
437 | 429 | ||
438 | dest.sll_family = AF_PACKET; | 430 | dest.sll_family = AF_PACKET; |
439 | dest.sll_protocol = htons(ETH_P_IP); | 431 | dest.sll_protocol = htons(ETH_P_IP); |
440 | dest.sll_ifindex = ifindex; | 432 | dest.sll_ifindex = ifindex; |
441 | dest.sll_halen = 6; | 433 | dest.sll_halen = 6; |
442 | memcpy(dest.sll_addr, dest_arp, 6); | 434 | memcpy(dest.sll_addr, dest_arp, 6); |
443 | if (bind(l_fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) { | 435 | if (bind(l_fd, (struct sockaddr *) &dest, sizeof(struct sockaddr_ll)) < 0) { |
444 | DEBUG(LOG_ERR, "bind call failed: %s", sys_errlist[errno]); | 436 | DEBUG(LOG_ERR, "bind call failed: %s", sys_errlist[errno]); |
445 | close(l_fd); | 437 | close(l_fd); |
446 | return -1; | 438 | return -1; |
@@ -451,18 +443,20 @@ static int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int sour | |||
451 | packet.ip.daddr = dest_ip; | 443 | packet.ip.daddr = dest_ip; |
452 | packet.udp.source = htons(source_port); | 444 | packet.udp.source = htons(source_port); |
453 | packet.udp.dest = htons(dest_port); | 445 | packet.udp.dest = htons(dest_port); |
454 | packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */ | 446 | packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */ |
455 | packet.ip.tot_len = packet.udp.len; | 447 | packet.ip.tot_len = packet.udp.len; |
456 | memcpy(&(packet.data), payload, sizeof(struct dhcpMessage)); | 448 | memcpy(&(packet.data), payload, sizeof(struct dhcpMessage)); |
457 | packet.udp.check = checksum(&packet, sizeof(struct udp_dhcp_packet)); | 449 | packet.udp.check = checksum(&packet, sizeof(struct udp_dhcp_packet)); |
458 | 450 | ||
459 | packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet)); | 451 | packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet)); |
460 | packet.ip.ihl = sizeof(packet.ip) >> 2; | 452 | packet.ip.ihl = sizeof(packet.ip) >> 2; |
461 | packet.ip.version = IPVERSION; | 453 | packet.ip.version = IPVERSION; |
462 | packet.ip.ttl = IPDEFTTL; | 454 | packet.ip.ttl = IPDEFTTL; |
463 | packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip)); | 455 | packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip)); |
464 | 456 | ||
465 | result = sendto(l_fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest)); | 457 | result = |
458 | sendto(l_fd, &packet, sizeof(struct udp_dhcp_packet), 0, | ||
459 | (struct sockaddr *) &dest, sizeof(dest)); | ||
466 | if (result <= 0) { | 460 | if (result <= 0) { |
467 | DEBUG(LOG_ERR, "write on socket failed: %s", sys_errlist[errno]); | 461 | DEBUG(LOG_ERR, "write on socket failed: %s", sys_errlist[errno]); |
468 | } | 462 | } |
@@ -471,34 +465,41 @@ static int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int sour | |||
471 | } | 465 | } |
472 | 466 | ||
473 | /* Let the kernel do all the work for packet generation */ | 467 | /* Let the kernel do all the work for packet generation */ |
474 | static int kernel_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port, | 468 | static int kernel_packet(struct dhcpMessage *payload, u_int32_t source_ip, |
475 | u_int32_t dest_ip, int dest_port) | 469 | int source_port, u_int32_t dest_ip, int dest_port) |
476 | { | 470 | { |
477 | int n = 1; | 471 | int n = 1; |
478 | int l_fd, result; | 472 | int l_fd, result; |
479 | struct sockaddr_in client; | 473 | struct sockaddr_in client; |
480 | 474 | ||
481 | if ((l_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) | 475 | if ((l_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { |
482 | return -1; | 476 | return -1; |
483 | 477 | } | |
484 | if (setsockopt(l_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) | 478 | |
479 | if (setsockopt(l_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == | ||
480 | -1) { | ||
485 | return -1; | 481 | return -1; |
482 | } | ||
486 | 483 | ||
487 | memset(&client, 0, sizeof(client)); | 484 | memset(&client, 0, sizeof(client)); |
488 | client.sin_family = AF_INET; | 485 | client.sin_family = AF_INET; |
489 | client.sin_port = htons(source_port); | 486 | client.sin_port = htons(source_port); |
490 | client.sin_addr.s_addr = source_ip; | 487 | client.sin_addr.s_addr = source_ip; |
491 | 488 | ||
492 | if (bind(l_fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) | 489 | if (bind(l_fd, (struct sockaddr *) &client, sizeof(struct sockaddr)) == |
490 | -1) { | ||
493 | return -1; | 491 | return -1; |
492 | } | ||
494 | 493 | ||
495 | memset(&client, 0, sizeof(client)); | 494 | memset(&client, 0, sizeof(client)); |
496 | client.sin_family = AF_INET; | 495 | client.sin_family = AF_INET; |
497 | client.sin_port = htons(dest_port); | 496 | client.sin_port = htons(dest_port); |
498 | client.sin_addr.s_addr = dest_ip; | 497 | client.sin_addr.s_addr = dest_ip; |
499 | 498 | ||
500 | if (connect(l_fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) | 499 | if (connect(l_fd, (struct sockaddr *) &client, sizeof(struct sockaddr)) == |
500 | -1) { | ||
501 | return -1; | 501 | return -1; |
502 | } | ||
502 | 503 | ||
503 | result = write(l_fd, payload, sizeof(struct dhcpMessage)); | 504 | result = write(l_fd, payload, sizeof(struct dhcpMessage)); |
504 | close(l_fd); | 505 | close(l_fd); |
@@ -508,12 +509,13 @@ static int kernel_packet(struct dhcpMessage *payload, u_int32_t source_ip, int s | |||
508 | /* initialize a packet with the proper defaults */ | 509 | /* initialize a packet with the proper defaults */ |
509 | static void init_packet(struct dhcpMessage *packet, char type) | 510 | static void init_packet(struct dhcpMessage *packet, char type) |
510 | { | 511 | { |
511 | struct vendor { | 512 | struct vendor { |
512 | char vendor, length; | 513 | char vendor, length; |
513 | char str[sizeof("udhcp "VERSION)]; | 514 | char str[sizeof("udhcp " VERSION)]; |
514 | } vendor_id = { DHCP_VENDOR, sizeof("udhcp "VERSION) - 1, "udhcp "VERSION}; | 515 | } |
515 | 516 | vendor_id = { | |
516 | // init_header(packet, type); | 517 | DHCP_VENDOR, sizeof("udhcp " VERSION) - 1, "udhcp " VERSION}; |
518 | |||
517 | memset(packet, 0, sizeof(struct dhcpMessage)); | 519 | memset(packet, 0, sizeof(struct dhcpMessage)); |
518 | switch (type) { | 520 | switch (type) { |
519 | case DHCPDISCOVER: | 521 | case DHCPDISCOVER: |
@@ -535,7 +537,9 @@ static void init_packet(struct dhcpMessage *packet, char type) | |||
535 | 537 | ||
536 | memcpy(packet->chaddr, client_config.arp, 6); | 538 | memcpy(packet->chaddr, client_config.arp, 6); |
537 | add_option_string(packet->options, client_config.clientid); | 539 | add_option_string(packet->options, client_config.clientid); |
538 | if (client_config.hostname) add_option_string(packet->options, client_config.hostname); | 540 | if (client_config.hostname) { |
541 | add_option_string(packet->options, client_config.hostname); | ||
542 | } | ||
539 | add_option_string(packet->options, (unsigned char *) &vendor_id); | 543 | add_option_string(packet->options, (unsigned char *) &vendor_id); |
540 | } | 544 | } |
541 | 545 | ||
@@ -547,11 +551,13 @@ static void add_requests(struct dhcpMessage *packet) | |||
547 | { | 551 | { |
548 | int end = end_option(packet->options); | 552 | int end = end_option(packet->options); |
549 | int i, len = 0; | 553 | int i, len = 0; |
550 | 554 | ||
551 | packet->options[end + OPT_CODE] = DHCP_PARAM_REQ; | 555 | packet->options[end + OPT_CODE] = DHCP_PARAM_REQ; |
552 | for (i = 0; options[i].code; i++) | 556 | for (i = 0; options[i].code; i++) { |
553 | if (options[i].flags & OPTION_REQ) | 557 | if (options[i].flags & OPTION_REQ) { |
554 | packet->options[end + OPT_DATA + len++] = options[i].code; | 558 | packet->options[end + OPT_DATA + len++] = options[i].code; |
559 | } | ||
560 | } | ||
555 | packet->options[end + OPT_LEN] = len; | 561 | packet->options[end + OPT_LEN] = len; |
556 | packet->options[end + OPT_DATA + len] = DHCP_END; | 562 | packet->options[end + OPT_DATA + len] = DHCP_END; |
557 | 563 | ||
@@ -564,17 +570,18 @@ static inline int send_discover(unsigned long xid, unsigned long requested) | |||
564 | 570 | ||
565 | init_packet(&packet, DHCPDISCOVER); | 571 | init_packet(&packet, DHCPDISCOVER); |
566 | packet.xid = xid; | 572 | packet.xid = xid; |
567 | if (requested) | 573 | if (requested) { |
568 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 574 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
569 | 575 | } | |
570 | add_requests(&packet); | 576 | add_requests(&packet); |
571 | DEBUG(LOG_DEBUG, "Sending discover..."); | 577 | DEBUG(LOG_DEBUG, "Sending discover..."); |
572 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | 578 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, |
573 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | 579 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); |
574 | } | 580 | } |
575 | 581 | ||
576 | /* Broadcasts a DHCP request message */ | 582 | /* Broadcasts a DHCP request message */ |
577 | static inline int send_selecting(unsigned long xid, unsigned long server, unsigned long requested) | 583 | static inline int send_selecting(unsigned long xid, unsigned long server, |
584 | unsigned long requested) | ||
578 | { | 585 | { |
579 | struct dhcpMessage packet; | 586 | struct dhcpMessage packet; |
580 | struct in_addr addr; | 587 | struct in_addr addr; |
@@ -584,17 +591,18 @@ static inline int send_selecting(unsigned long xid, unsigned long server, unsign | |||
584 | 591 | ||
585 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 592 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
586 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 593 | add_simple_option(packet.options, DHCP_SERVER_ID, server); |
587 | 594 | ||
588 | add_requests(&packet); | 595 | add_requests(&packet); |
589 | addr.s_addr = requested; | 596 | addr.s_addr = requested; |
590 | DEBUG(LOG_DEBUG, "Sending select for %s...", inet_ntoa(addr)); | 597 | DEBUG(LOG_DEBUG, "Sending select for %s...", inet_ntoa(addr)); |
591 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | 598 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, |
592 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | 599 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); |
593 | } | 600 | } |
594 | 601 | ||
595 | 602 | ||
596 | /* Unicasts or broadcasts a DHCP renew message */ | 603 | /* Unicasts or broadcasts a DHCP renew message */ |
597 | static int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr) | 604 | static int send_renew(unsigned long xid, unsigned long server, |
605 | unsigned long ciaddr) | ||
598 | { | 606 | { |
599 | struct dhcpMessage packet; | 607 | struct dhcpMessage packet; |
600 | 608 | ||
@@ -604,45 +612,31 @@ static int send_renew(unsigned long xid, unsigned long server, unsigned long cia | |||
604 | 612 | ||
605 | add_requests(&packet); | 613 | add_requests(&packet); |
606 | DEBUG(LOG_DEBUG, "Sending renew..."); | 614 | DEBUG(LOG_DEBUG, "Sending renew..."); |
607 | if (server) | 615 | if (server) { |
608 | return kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); | 616 | return kernel_packet(&packet, ciaddr, CLIENT_PORT, server, |
617 | SERVER_PORT); | ||
618 | } | ||
609 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | 619 | return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, |
610 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | 620 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); |
611 | } | 621 | } |
612 | 622 | ||
613 | /* Create a random xid */ | 623 | /* Create a random xid */ |
614 | static unsigned long random_xid(void) | 624 | static unsigned long random_xid(void) |
615 | { | 625 | { |
616 | static int initialized; | 626 | static int initialized; |
627 | |||
617 | if (!initialized) { | 628 | if (!initialized) { |
618 | srand(time(0)); | 629 | srand(time(0)); |
619 | initialized++; | 630 | initialized++; |
620 | } | 631 | } |
621 | return rand(); | 632 | return rand(); |
622 | } | 633 | } |
623 | #if 0 | ||
624 | /* Unicasts a DHCP release message */ | ||
625 | int send_release(unsigned long server, unsigned long ciaddr) | ||
626 | { | ||
627 | struct dhcpMessage packet; | ||
628 | |||
629 | init_packet(&packet, DHCPRELEASE); | ||
630 | packet.xid = random_xid(); | ||
631 | packet.ciaddr = ciaddr; | ||
632 | |||
633 | add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr); | ||
634 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | ||
635 | |||
636 | LOG(LOG_DEBUG, "Sending release..."); | ||
637 | return kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); | ||
638 | } | ||
639 | #endif | ||
640 | 634 | ||
641 | /* just a little helper */ | 635 | /* just a little helper */ |
642 | static void change_mode(int new_mode) | 636 | static void change_mode(int new_mode) |
643 | { | 637 | { |
644 | DEBUG(LOG_INFO, "entering %s listen mode", | 638 | DEBUG(LOG_INFO, "entering %s listen mode", |
645 | new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); | 639 | new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); |
646 | close(fd_main); | 640 | close(fd_main); |
647 | fd_main = -1; | 641 | fd_main = -1; |
648 | listen_mode = new_mode; | 642 | listen_mode = new_mode; |
@@ -655,8 +649,8 @@ static void renew_requested(int sig) | |||
655 | sig = 0; | 649 | sig = 0; |
656 | LOG(LOG_INFO, "Received SIGUSR1"); | 650 | LOG(LOG_INFO, "Received SIGUSR1"); |
657 | if (state == BOUND || state == RENEWING || state == REBINDING || | 651 | if (state == BOUND || state == RENEWING || state == REBINDING || |
658 | state == RELEASED) { | 652 | state == RELEASED) { |
659 | change_mode(LISTEN_KERNEL); | 653 | change_mode(LISTEN_KERNEL); |
660 | packet_num = 0; | 654 | packet_num = 0; |
661 | state = RENEW_REQUESTED; | 655 | state = RENEW_REQUESTED; |
662 | } | 656 | } |
@@ -676,7 +670,7 @@ static unsigned char *get_option(struct dhcpMessage *packet, int code) | |||
676 | int i, length; | 670 | int i, length; |
677 | unsigned char *optionptr; | 671 | unsigned char *optionptr; |
678 | int over = 0, done = 0, curr = OPTION_FIELD; | 672 | int over = 0, done = 0, curr = OPTION_FIELD; |
679 | 673 | ||
680 | optionptr = packet->options; | 674 | optionptr = packet->options; |
681 | i = 0; | 675 | i = 0; |
682 | length = 308; | 676 | length = 308; |
@@ -691,7 +685,7 @@ static unsigned char *get_option(struct dhcpMessage *packet, int code) | |||
691 | return NULL; | 685 | return NULL; |
692 | } | 686 | } |
693 | return optionptr + i + 2; | 687 | return optionptr + i + 2; |
694 | } | 688 | } |
695 | switch (optionptr[i + OPT_CODE]) { | 689 | switch (optionptr[i + OPT_CODE]) { |
696 | case DHCP_PADDING: | 690 | case DHCP_PADDING: |
697 | i++; | 691 | i++; |
@@ -715,7 +709,9 @@ static unsigned char *get_option(struct dhcpMessage *packet, int code) | |||
715 | i = 0; | 709 | i = 0; |
716 | length = 64; | 710 | length = 64; |
717 | curr = SNAME_FIELD; | 711 | curr = SNAME_FIELD; |
718 | } else done = 1; | 712 | } else { |
713 | done = 1; | ||
714 | } | ||
719 | break; | 715 | break; |
720 | default: | 716 | default: |
721 | i += optionptr[OPT_LEN + i] + 2; | 717 | i += optionptr[OPT_LEN + i] + 2; |
@@ -723,21 +719,16 @@ static unsigned char *get_option(struct dhcpMessage *packet, int code) | |||
723 | } | 719 | } |
724 | return NULL; | 720 | return NULL; |
725 | } | 721 | } |
726 | #if 0 | ||
727 | static int upper_length(int length, struct dhcp_option *option) | ||
728 | { | ||
729 | return max_option_length[option->flags & TYPE_MASK] * | ||
730 | (length / option_lengths[option->flags & TYPE_MASK]); | ||
731 | } | ||
732 | #endif | ||
733 | 722 | ||
734 | static int sprintip(char *dest, char *pre, unsigned char *ip) { | 723 | static int sprintip(char *dest, char *pre, unsigned char *ip) |
724 | { | ||
735 | return sprintf(dest, "%s%d.%d.%d.%d ", pre, ip[0], ip[1], ip[2], ip[3]); | 725 | return sprintf(dest, "%s%d.%d.%d.%d ", pre, ip[0], ip[1], ip[2], ip[3]); |
736 | } | 726 | } |
737 | 727 | ||
738 | 728 | ||
739 | /* Fill dest with the text of option 'option'. */ | 729 | /* Fill dest with the text of option 'option'. */ |
740 | extern inline void fill_options(char *dest, unsigned char *option, const struct dhcp_option *type_p) | 730 | static inline void fill_options(char *dest, unsigned char *option, |
731 | const struct dhcp_option *type_p) | ||
741 | { | 732 | { |
742 | int type, optlen; | 733 | int type, optlen; |
743 | u_int16_t val_u16; | 734 | u_int16_t val_u16; |
@@ -750,7 +741,7 @@ extern inline void fill_options(char *dest, unsigned char *option, const struct | |||
750 | 741 | ||
751 | type = type_p->flags & TYPE_MASK; | 742 | type = type_p->flags & TYPE_MASK; |
752 | optlen = option_lengths[type]; | 743 | optlen = option_lengths[type]; |
753 | for(;;) { | 744 | for (;;) { |
754 | switch (type) { | 745 | switch (type) { |
755 | case OPTION_IP_PAIR: | 746 | case OPTION_IP_PAIR: |
756 | dest += sprintip(dest, "", option); | 747 | dest += sprintip(dest, "", option); |
@@ -759,7 +750,7 @@ extern inline void fill_options(char *dest, unsigned char *option, const struct | |||
759 | optlen = 4; | 750 | optlen = 4; |
760 | case OPTION_IP: /* Works regardless of host byte order. */ | 751 | case OPTION_IP: /* Works regardless of host byte order. */ |
761 | dest += sprintip(dest, "", option); | 752 | dest += sprintip(dest, "", option); |
762 | break; | 753 | break; |
763 | case OPTION_BOOLEAN: | 754 | case OPTION_BOOLEAN: |
764 | dest += sprintf(dest, *option ? "yes " : "no "); | 755 | dest += sprintf(dest, *option ? "yes " : "no "); |
765 | break; | 756 | break; |
@@ -785,11 +776,13 @@ extern inline void fill_options(char *dest, unsigned char *option, const struct | |||
785 | case OPTION_STRING: | 776 | case OPTION_STRING: |
786 | memcpy(dest, option, len); | 777 | memcpy(dest, option, len); |
787 | dest[len] = '\0'; | 778 | dest[len] = '\0'; |
788 | return; /* Short circuit this case */ | 779 | return; /* Short circuit this case */ |
789 | } | 780 | } |
790 | option += optlen; | 781 | option += optlen; |
791 | len -= optlen; | 782 | len -= optlen; |
792 | if (len <= 0) break; | 783 | if (len <= 0) { |
784 | break; | ||
785 | } | ||
793 | } | 786 | } |
794 | } | 787 | } |
795 | 788 | ||
@@ -800,8 +793,9 @@ static char *find_env(const char *prefix, char *defaultstr) | |||
800 | const int len = strlen(prefix); | 793 | const int len = strlen(prefix); |
801 | 794 | ||
802 | for (ptr = environ; *ptr != NULL; ptr++) { | 795 | for (ptr = environ; *ptr != NULL; ptr++) { |
803 | if (strncmp(prefix, *ptr, len) == 0) | 796 | if (strncmp(prefix, *ptr, len) == 0) { |
804 | return *ptr; | 797 | return *ptr; |
798 | } | ||
805 | } | 799 | } |
806 | return defaultstr; | 800 | return defaultstr; |
807 | } | 801 | } |
@@ -816,19 +810,28 @@ static char **fill_envp(struct dhcpMessage *packet) | |||
816 | unsigned char *temp; | 810 | unsigned char *temp; |
817 | char over = 0; | 811 | char over = 0; |
818 | 812 | ||
819 | if (packet == NULL) | 813 | if (packet == NULL) { |
820 | num_options = 0; | 814 | num_options = 0; |
821 | else { | 815 | } else { |
822 | for (i = 0; options[i].code; i++) | 816 | for (i = 0; options[i].code; i++) { |
823 | if (get_option(packet, options[i].code)) | 817 | if (get_option(packet, options[i].code)) { |
824 | num_options++; | 818 | num_options++; |
825 | if (packet->siaddr) num_options++; | 819 | } |
826 | if ((temp = get_option(packet, DHCP_OPTION_OVER))) | 820 | } |
821 | if (packet->siaddr) { | ||
822 | num_options++; | ||
823 | } | ||
824 | if ((temp = get_option(packet, DHCP_OPTION_OVER))) { | ||
827 | over = *temp; | 825 | over = *temp; |
828 | if (!(over & FILE_FIELD) && packet->file[0]) num_options++; | 826 | } |
829 | if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++; | 827 | if (!(over & FILE_FIELD) && packet->file[0]) { |
828 | num_options++; | ||
829 | } | ||
830 | if (!(over & SNAME_FIELD) && packet->sname[0]) { | ||
831 | num_options++; | ||
832 | } | ||
830 | } | 833 | } |
831 | 834 | ||
832 | envp = xmalloc((num_options + 5) * sizeof(char *)); | 835 | envp = xmalloc((num_options + 5) * sizeof(char *)); |
833 | envp[0] = xmalloc(sizeof("interface=") + strlen(client_config.interface)); | 836 | envp[0] = xmalloc(sizeof("interface=") + strlen(client_config.interface)); |
834 | sprintf(envp[0], "interface=%s", client_config.interface); | 837 | sprintf(envp[0], "interface=%s", client_config.interface); |
@@ -844,8 +847,11 @@ static char **fill_envp(struct dhcpMessage *packet) | |||
844 | sprintip(envp[3], "ip=", (unsigned char *) &packet->yiaddr); | 847 | sprintip(envp[3], "ip=", (unsigned char *) &packet->yiaddr); |
845 | for (i = 0, j = 4; options[i].code; i++) { | 848 | for (i = 0, j = 4; options[i].code; i++) { |
846 | if ((temp = get_option(packet, options[i].code))) { | 849 | if ((temp = get_option(packet, options[i].code))) { |
847 | envp[j] = xmalloc(max_option_length[(&options[i])->flags & TYPE_MASK] * (temp[OPT_LEN - 2] / option_lengths[(&options[i])->flags & TYPE_MASK]) + strlen((&options[i])->name) + 2); | 850 | envp[j] = |
848 | // envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], &options[i]) + strlen(options[i].name) + 2); | 851 | xmalloc(max_option_length[(&options[i])->flags & TYPE_MASK] * |
852 | (temp[OPT_LEN - 2] / | ||
853 | option_lengths[(&options[i])->flags & TYPE_MASK]) + | ||
854 | strlen((&options[i])->name) + 2); | ||
849 | fill_options(envp[j], temp, &options[i]); | 855 | fill_options(envp[j], temp, &options[i]); |
850 | j++; | 856 | j++; |
851 | } | 857 | } |
@@ -865,7 +871,7 @@ static char **fill_envp(struct dhcpMessage *packet) | |||
865 | packet->sname[sizeof(packet->sname) - 1] = '\0'; | 871 | packet->sname[sizeof(packet->sname) - 1] = '\0'; |
866 | envp[j] = xmalloc(sizeof("sname=") + strlen(packet->sname)); | 872 | envp[j] = xmalloc(sizeof("sname=") + strlen(packet->sname)); |
867 | sprintf(envp[j++], "sname=%s", packet->sname); | 873 | sprintf(envp[j++], "sname=%s", packet->sname); |
868 | } | 874 | } |
869 | envp[j] = NULL; | 875 | envp[j] = NULL; |
870 | return envp; | 876 | return envp; |
871 | } | 877 | } |
@@ -876,8 +882,9 @@ static void run_script(struct dhcpMessage *packet, const char *name) | |||
876 | int pid; | 882 | int pid; |
877 | char **envp; | 883 | char **envp; |
878 | 884 | ||
879 | if (client_config.script == NULL) | 885 | if (client_config.script == NULL) { |
880 | return; | 886 | return; |
887 | } | ||
881 | 888 | ||
882 | /* call script */ | 889 | /* call script */ |
883 | pid = fork(); | 890 | pid = fork(); |
@@ -886,17 +893,16 @@ static void run_script(struct dhcpMessage *packet, const char *name) | |||
886 | return; | 893 | return; |
887 | } else if (pid == 0) { | 894 | } else if (pid == 0) { |
888 | envp = fill_envp(packet); | 895 | envp = fill_envp(packet); |
889 | 896 | ||
890 | /* close fd's? */ | 897 | /* close fd's? */ |
891 | 898 | ||
892 | /* exec script */ | 899 | /* exec script */ |
893 | DEBUG(LOG_INFO, "execle'ing %s", client_config.script); | 900 | DEBUG(LOG_INFO, "execle'ing %s", client_config.script); |
894 | execle(client_config.script, client_config.script, | 901 | execle(client_config.script, client_config.script, name, NULL, envp); |
895 | name, NULL, envp); | ||
896 | LOG(LOG_ERR, "script %s failed: %s", | 902 | LOG(LOG_ERR, "script %s failed: %s", |
897 | client_config.script, sys_errlist[errno]); | 903 | client_config.script, sys_errlist[errno]); |
898 | exit(1); | 904 | exit(1); |
899 | } | 905 | } |
900 | } | 906 | } |
901 | 907 | ||
902 | /* SIGUSR2 handler (release) */ | 908 | /* SIGUSR2 handler (release) */ |
@@ -911,12 +917,13 @@ static void release_requested(int sig) | |||
911 | init_packet(&packet, DHCPRELEASE); | 917 | init_packet(&packet, DHCPRELEASE); |
912 | packet.xid = random_xid(); | 918 | packet.xid = random_xid(); |
913 | packet.ciaddr = requested_ip; | 919 | packet.ciaddr = requested_ip; |
914 | 920 | ||
915 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested_ip); | 921 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested_ip); |
916 | add_simple_option(packet.options, DHCP_SERVER_ID, server_addr); | 922 | add_simple_option(packet.options, DHCP_SERVER_ID, server_addr); |
917 | 923 | ||
918 | DEBUG(LOG_DEBUG, "Sending release..."); | 924 | DEBUG(LOG_DEBUG, "Sending release..."); |
919 | kernel_packet(&packet, requested_ip, CLIENT_PORT, server_addr, SERVER_PORT); | 925 | kernel_packet(&packet, requested_ip, CLIENT_PORT, server_addr, |
926 | SERVER_PORT); | ||
920 | run_script(NULL, "deconfig"); | 927 | run_script(NULL, "deconfig"); |
921 | } | 928 | } |
922 | 929 | ||
@@ -929,16 +936,18 @@ static void release_requested(int sig) | |||
929 | static int pidfile_acquire(char *pidfile) | 936 | static int pidfile_acquire(char *pidfile) |
930 | { | 937 | { |
931 | int pid_fd; | 938 | int pid_fd; |
932 | if (pidfile == NULL) return -1; | ||
933 | 939 | ||
940 | if (pidfile == NULL) { | ||
941 | return -1; | ||
942 | } | ||
934 | pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644); | 943 | pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644); |
935 | if (pid_fd < 0) { | 944 | if (pid_fd < 0) { |
936 | LOG(LOG_ERR, "Unable to open pidfile %s: %s\n", | 945 | LOG(LOG_ERR, "Unable to open pidfile %s: %s\n", |
937 | pidfile, strerror(errno)); | 946 | pidfile, strerror(errno)); |
938 | } else { | 947 | } else { |
939 | lockf(pid_fd, F_LOCK, 0); | 948 | lockf(pid_fd, F_LOCK, 0); |
940 | } | 949 | } |
941 | 950 | ||
942 | return pid_fd; | 951 | return pid_fd; |
943 | } | 952 | } |
944 | 953 | ||
@@ -947,8 +956,9 @@ static void pidfile_write_release(int pid_fd) | |||
947 | { | 956 | { |
948 | FILE *out; | 957 | FILE *out; |
949 | 958 | ||
950 | if (pid_fd < 0) return; | 959 | if (pid_fd < 0) { |
951 | 960 | return; | |
961 | } | ||
952 | if ((out = fdopen(pid_fd, "w")) != NULL) { | 962 | if ((out = fdopen(pid_fd, "w")) != NULL) { |
953 | fprintf(out, "%d\n", getpid()); | 963 | fprintf(out, "%d\n", getpid()); |
954 | fclose(out); | 964 | fclose(out); |
@@ -961,7 +971,9 @@ static void pidfile_write_release(int pid_fd) | |||
961 | static void exit_client(int retval) | 971 | static void exit_client(int retval) |
962 | { | 972 | { |
963 | unlink(client_config.pidfile); | 973 | unlink(client_config.pidfile); |
964 | if (client_config.pidfile) unlink(client_config.pidfile); | 974 | if (client_config.pidfile) { |
975 | unlink(client_config.pidfile); | ||
976 | } | ||
965 | CLOSE_LOG(); | 977 | CLOSE_LOG(); |
966 | exit(retval); | 978 | exit(retval); |
967 | } | 979 | } |
@@ -976,28 +988,30 @@ static void terminate(int sig) | |||
976 | } | 988 | } |
977 | 989 | ||
978 | 990 | ||
979 | extern inline int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp) | 991 | static inline int read_interface(char *interface, int *ifindex, |
992 | u_int32_t * addr, unsigned char *arp) | ||
980 | { | 993 | { |
981 | int l_fd; | 994 | int l_fd; |
982 | struct ifreq ifr; | 995 | struct ifreq ifr; |
983 | struct sockaddr_in *s_in; | 996 | struct sockaddr_in *s_in; |
984 | 997 | ||
985 | memset(&ifr, 0, sizeof(struct ifreq)); | 998 | memset(&ifr, 0, sizeof(struct ifreq)); |
986 | if((l_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) { | 999 | if ((l_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) { |
987 | ifr.ifr_addr.sa_family = AF_INET; | 1000 | ifr.ifr_addr.sa_family = AF_INET; |
988 | strcpy(ifr.ifr_name, interface); | 1001 | strcpy(ifr.ifr_name, interface); |
989 | 1002 | ||
990 | if (addr) { | 1003 | if (addr) { |
991 | if (ioctl(l_fd, SIOCGIFADDR, &ifr) == 0) { | 1004 | if (ioctl(l_fd, SIOCGIFADDR, &ifr) == 0) { |
992 | s_in = (struct sockaddr_in *) &ifr.ifr_addr; | 1005 | s_in = (struct sockaddr_in *) &ifr.ifr_addr; |
993 | *addr = s_in->sin_addr.s_addr; | 1006 | *addr = s_in->sin_addr.s_addr; |
994 | DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, inet_ntoa(s_in->sin_addr)); | 1007 | DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, |
1008 | inet_ntoa(s_in->sin_addr)); | ||
995 | } else { | 1009 | } else { |
996 | LOG(LOG_ERR, "SIOCGIFADDR failed!: %s", sys_errlist[errno]); | 1010 | LOG(LOG_ERR, "SIOCGIFADDR failed!: %s", sys_errlist[errno]); |
997 | return -1; | 1011 | return -1; |
998 | } | 1012 | } |
999 | } | 1013 | } |
1000 | 1014 | ||
1001 | if (ioctl(l_fd, SIOCGIFINDEX, &ifr) == 0) { | 1015 | if (ioctl(l_fd, SIOCGIFINDEX, &ifr) == 0) { |
1002 | DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex); | 1016 | DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex); |
1003 | *ifindex = ifr.ifr_ifindex; | 1017 | *ifindex = ifr.ifr_ifindex; |
@@ -1007,8 +1021,9 @@ extern inline int read_interface(char *interface, int *ifindex, u_int32_t *addr, | |||
1007 | } | 1021 | } |
1008 | if (ioctl(l_fd, SIOCGIFHWADDR, &ifr) == 0) { | 1022 | if (ioctl(l_fd, SIOCGIFHWADDR, &ifr) == 0) { |
1009 | memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); | 1023 | memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); |
1010 | DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", | 1024 | DEBUG(LOG_INFO, |
1011 | arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); | 1025 | "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", |
1026 | arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); | ||
1012 | } else { | 1027 | } else { |
1013 | LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %s", sys_errlist[errno]); | 1028 | LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %s", sys_errlist[errno]); |
1014 | return -1; | 1029 | return -1; |
@@ -1022,7 +1037,7 @@ extern inline int read_interface(char *interface, int *ifindex, u_int32_t *addr, | |||
1022 | } | 1037 | } |
1023 | 1038 | ||
1024 | 1039 | ||
1025 | extern inline int listen_socket(unsigned int ip, int port, char *inf) | 1040 | static inline int listen_socket(unsigned int ip, int port, char *inf) |
1026 | { | 1041 | { |
1027 | struct ifreq interface; | 1042 | struct ifreq interface; |
1028 | int l_fd; | 1043 | int l_fd; |
@@ -1034,32 +1049,36 @@ extern inline int listen_socket(unsigned int ip, int port, char *inf) | |||
1034 | DEBUG(LOG_ERR, "socket call failed: %s", sys_errlist[errno]); | 1049 | DEBUG(LOG_ERR, "socket call failed: %s", sys_errlist[errno]); |
1035 | return -1; | 1050 | return -1; |
1036 | } | 1051 | } |
1037 | 1052 | ||
1038 | memset(&addr, 0, sizeof(addr)); | 1053 | memset(&addr, 0, sizeof(addr)); |
1039 | addr.sin_family = AF_INET; | 1054 | addr.sin_family = AF_INET; |
1040 | addr.sin_port = htons(port); | 1055 | addr.sin_port = htons(port); |
1041 | addr.sin_addr.s_addr = ip; | 1056 | addr.sin_addr.s_addr = ip; |
1042 | 1057 | ||
1043 | if (setsockopt(l_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) { | 1058 | if (setsockopt(l_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == |
1059 | -1) { | ||
1044 | close(l_fd); | 1060 | close(l_fd); |
1045 | return -1; | 1061 | return -1; |
1046 | } | 1062 | } |
1047 | if (setsockopt(l_fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) { | 1063 | if (setsockopt(l_fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == |
1064 | -1) { | ||
1048 | close(l_fd); | 1065 | close(l_fd); |
1049 | return -1; | 1066 | return -1; |
1050 | } | 1067 | } |
1051 | 1068 | ||
1052 | strncpy(interface.ifr_ifrn.ifrn_name, inf, IFNAMSIZ); | 1069 | strncpy(interface.ifr_ifrn.ifrn_name, inf, IFNAMSIZ); |
1053 | if (setsockopt(l_fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) { | 1070 | if (setsockopt |
1071 | (l_fd, SOL_SOCKET, SO_BINDTODEVICE, (char *) &interface, | ||
1072 | sizeof(interface)) < 0) { | ||
1054 | close(l_fd); | 1073 | close(l_fd); |
1055 | return -1; | 1074 | return -1; |
1056 | } | 1075 | } |
1057 | 1076 | ||
1058 | if (bind(l_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) { | 1077 | if (bind(l_fd, (struct sockaddr *) &addr, sizeof(struct sockaddr)) == -1) { |
1059 | close(l_fd); | 1078 | close(l_fd); |
1060 | return -1; | 1079 | return -1; |
1061 | } | 1080 | } |
1062 | 1081 | ||
1063 | return l_fd; | 1082 | return l_fd; |
1064 | } | 1083 | } |
1065 | 1084 | ||
@@ -1074,7 +1093,7 @@ static int raw_socket(int ifindex) | |||
1074 | DEBUG(LOG_ERR, "socket call failed: %s", sys_errlist[errno]); | 1093 | DEBUG(LOG_ERR, "socket call failed: %s", sys_errlist[errno]); |
1075 | return -1; | 1094 | return -1; |
1076 | } | 1095 | } |
1077 | 1096 | ||
1078 | sock.sll_family = AF_PACKET; | 1097 | sock.sll_family = AF_PACKET; |
1079 | sock.sll_protocol = htons(ETH_P_IP); | 1098 | sock.sll_protocol = htons(ETH_P_IP); |
1080 | sock.sll_ifindex = ifindex; | 1099 | sock.sll_ifindex = ifindex; |
@@ -1111,23 +1130,24 @@ static int get_packet(struct dhcpMessage *packet, int l_fd) | |||
1111 | return -2; | 1130 | return -2; |
1112 | } | 1131 | } |
1113 | DEBUG(LOG_INFO, "Received a packet"); | 1132 | DEBUG(LOG_INFO, "Received a packet"); |
1114 | 1133 | ||
1115 | if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) { | 1134 | if (packet->op == BOOTREQUEST |
1135 | && (vendor = get_option(packet, DHCP_VENDOR))) { | ||
1116 | for (i = 0; broken_vendors[i][0]; i++) { | 1136 | for (i = 0; broken_vendors[i][0]; i++) { |
1117 | if (vendor[OPT_LEN - 2] == (unsigned char) strlen(broken_vendors[i]) && | 1137 | if (vendor[OPT_LEN - 2] == |
1118 | !strncmp(vendor, broken_vendors[i], vendor[OPT_LEN - 2])) { | 1138 | (unsigned char) strlen(broken_vendors[i]) |
1119 | DEBUG(LOG_INFO, "broken client (%s), forcing broadcast", | 1139 | && !strncmp(vendor, broken_vendors[i], vendor[OPT_LEN - 2])) { |
1120 | broken_vendors[i]); | 1140 | DEBUG(LOG_INFO, "broken client (%s), forcing broadcast", |
1121 | packet->flags |= htons(BROADCAST_FLAG); | 1141 | broken_vendors[i]); |
1142 | packet->flags |= htons(BROADCAST_FLAG); | ||
1122 | } | 1143 | } |
1123 | } | 1144 | } |
1124 | } | 1145 | } |
1125 | |||
1126 | 1146 | ||
1127 | return bytes; | 1147 | return bytes; |
1128 | } | 1148 | } |
1129 | 1149 | ||
1130 | extern inline int get_raw_packet(struct dhcpMessage *payload, int l_fd) | 1150 | static inline int get_raw_packet(struct dhcpMessage *payload, int l_fd) |
1131 | { | 1151 | { |
1132 | int bytes; | 1152 | int bytes; |
1133 | struct udp_dhcp_packet packet; | 1153 | struct udp_dhcp_packet packet; |
@@ -1138,30 +1158,31 @@ extern inline int get_raw_packet(struct dhcpMessage *payload, int l_fd) | |||
1138 | bytes = read(l_fd, &packet, sizeof(struct udp_dhcp_packet)); | 1158 | bytes = read(l_fd, &packet, sizeof(struct udp_dhcp_packet)); |
1139 | if (bytes < 0) { | 1159 | if (bytes < 0) { |
1140 | DEBUG(LOG_INFO, "couldn't read on raw listening socket -- ignoring"); | 1160 | DEBUG(LOG_INFO, "couldn't read on raw listening socket -- ignoring"); |
1141 | usleep(500000); /* possible down interface, looping condition */ | 1161 | usleep(500000); /* possible down interface, looping condition */ |
1142 | return -1; | 1162 | return -1; |
1143 | } | 1163 | } |
1144 | 1164 | ||
1145 | if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) { | 1165 | if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) { |
1146 | DEBUG(LOG_INFO, "message too short, ignoring"); | 1166 | DEBUG(LOG_INFO, "message too short, ignoring"); |
1147 | return -1; | 1167 | return -1; |
1148 | } | 1168 | } |
1149 | 1169 | ||
1150 | if (bytes < ntohs(packet.ip.tot_len)) { | 1170 | if (bytes < ntohs(packet.ip.tot_len)) { |
1151 | DEBUG(LOG_INFO, "Truncated packet"); | 1171 | DEBUG(LOG_INFO, "Truncated packet"); |
1152 | return -1; | 1172 | return -1; |
1153 | } | 1173 | } |
1154 | 1174 | ||
1155 | /* ignore any extra garbage bytes */ | 1175 | /* ignore any extra garbage bytes */ |
1156 | bytes = ntohs(packet.ip.tot_len); | 1176 | bytes = ntohs(packet.ip.tot_len); |
1157 | 1177 | ||
1158 | /* Make sure its the right packet for us, and that it passes sanity checks */ | 1178 | /* Make sure its the right packet for us, and that it passes sanity checks */ |
1159 | if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION || | 1179 | if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION || |
1160 | packet.ip.ihl != sizeof(packet.ip) >> 2 || packet.udp.dest != htons(CLIENT_PORT) || | 1180 | packet.ip.ihl != sizeof(packet.ip) >> 2 |
1161 | bytes > (int) sizeof(struct udp_dhcp_packet) || | 1181 | || packet.udp.dest != htons(CLIENT_PORT) |
1162 | ntohs(packet.udp.len) != (short) (bytes - sizeof(packet.ip))) { | 1182 | || bytes > (int) sizeof(struct udp_dhcp_packet) |
1163 | DEBUG(LOG_INFO, "unrelated/bogus packet"); | 1183 | || ntohs(packet.udp.len) != (short) (bytes - sizeof(packet.ip))) { |
1164 | return -1; | 1184 | DEBUG(LOG_INFO, "unrelated/bogus packet"); |
1185 | return -1; | ||
1165 | } | 1186 | } |
1166 | 1187 | ||
1167 | /* check IP checksum */ | 1188 | /* check IP checksum */ |
@@ -1171,7 +1192,7 @@ extern inline int get_raw_packet(struct dhcpMessage *payload, int l_fd) | |||
1171 | DEBUG(LOG_INFO, "bad IP header checksum, ignoring"); | 1192 | DEBUG(LOG_INFO, "bad IP header checksum, ignoring"); |
1172 | return -1; | 1193 | return -1; |
1173 | } | 1194 | } |
1174 | 1195 | ||
1175 | /* verify the UDP checksum by replacing the header with a psuedo header */ | 1196 | /* verify the UDP checksum by replacing the header with a psuedo header */ |
1176 | source = packet.ip.saddr; | 1197 | source = packet.ip.saddr; |
1177 | dest = packet.ip.daddr; | 1198 | dest = packet.ip.daddr; |
@@ -1182,14 +1203,15 @@ extern inline int get_raw_packet(struct dhcpMessage *payload, int l_fd) | |||
1182 | packet.ip.protocol = IPPROTO_UDP; | 1203 | packet.ip.protocol = IPPROTO_UDP; |
1183 | packet.ip.saddr = source; | 1204 | packet.ip.saddr = source; |
1184 | packet.ip.daddr = dest; | 1205 | packet.ip.daddr = dest; |
1185 | packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */ | 1206 | packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */ |
1186 | if (check && check != checksum(&packet, bytes)) { | 1207 | if (check && check != checksum(&packet, bytes)) { |
1187 | DEBUG(LOG_ERR, "packet with bad UDP checksum received, ignoring"); | 1208 | DEBUG(LOG_ERR, "packet with bad UDP checksum received, ignoring"); |
1188 | return -1; | 1209 | return -1; |
1189 | } | 1210 | } |
1190 | 1211 | ||
1191 | memcpy(payload, &(packet.data), bytes - (sizeof(packet.ip) + sizeof(packet.udp))); | 1212 | memcpy(payload, &(packet.data), |
1192 | 1213 | bytes - (sizeof(packet.ip) + sizeof(packet.udp))); | |
1214 | |||
1193 | if (ntohl(payload->cookie) != DHCP_MAGIC) { | 1215 | if (ntohl(payload->cookie) != DHCP_MAGIC) { |
1194 | LOG(LOG_ERR, "received bogus message (bad magic) -- ignoring"); | 1216 | LOG(LOG_ERR, "received bogus message (bad magic) -- ignoring"); |
1195 | return -1; | 1217 | return -1; |
@@ -1214,31 +1236,39 @@ int udhcpc_main(int argc, char *argv[]) | |||
1214 | time_t now; | 1236 | time_t now; |
1215 | 1237 | ||
1216 | static struct option l_options[] = { | 1238 | static struct option l_options[] = { |
1217 | {"clientid", required_argument, 0, 'c'}, | 1239 | {"clientid", required_argument, 0, 'c'}, |
1218 | {"foreground", no_argument, 0, 'f'}, | 1240 | {"foreground", no_argument, 0, 'f'}, |
1219 | {"hostname", required_argument, 0, 'H'}, | 1241 | {"hostname", required_argument, 0, 'H'}, |
1220 | {"help", no_argument, 0, 'h'}, | 1242 | {"help", no_argument, 0, 'h'}, |
1221 | {"interface", required_argument, 0, 'i'}, | 1243 | {"interface", required_argument, 0, 'i'}, |
1222 | {"now", no_argument, 0, 'n'}, | 1244 | {"now", no_argument, 0, 'n'}, |
1223 | {"pidfile", required_argument, 0, 'p'}, | 1245 | {"pidfile", required_argument, 0, 'p'}, |
1224 | {"quit", no_argument, 0, 'q'}, | 1246 | {"quit", no_argument, 0, 'q'}, |
1225 | {"request", required_argument, 0, 'r'}, | 1247 | {"request", required_argument, 0, 'r'}, |
1226 | {"script", required_argument, 0, 's'}, | 1248 | {"script", required_argument, 0, 's'}, |
1227 | {"version", no_argument, 0, 'v'}, | 1249 | {"version", no_argument, 0, 'v'}, |
1228 | {0, 0, 0, 0} | 1250 | {0, 0, 0, 0} |
1229 | }; | 1251 | }; |
1230 | 1252 | ||
1231 | /* get options */ | 1253 | /* get options */ |
1232 | while (1) { | 1254 | while (1) { |
1233 | int option_index = 0; | 1255 | int option_index = 0; |
1234 | c = getopt_long(argc, argv, "c:fH:hi:np:qr:s:v", l_options, &option_index); | 1256 | |
1235 | if (c == -1) break; | 1257 | c = getopt_long(argc, argv, "c:fH:hi:np:qr:s:v", l_options, |
1236 | 1258 | &option_index); | |
1259 | if (c == -1) { | ||
1260 | break; | ||
1261 | } | ||
1262 | |||
1237 | switch (c) { | 1263 | switch (c) { |
1238 | case 'c': | 1264 | case 'c': |
1239 | len = strlen(optarg); | 1265 | len = strlen(optarg); |
1240 | if (len > 255) len = 255; | 1266 | if (len > 255) { |
1241 | if (client_config.clientid) free(client_config.clientid); | 1267 | len = 255; |
1268 | } | ||
1269 | if (client_config.clientid) { | ||
1270 | free(client_config.clientid); | ||
1271 | } | ||
1242 | client_config.clientid = xmalloc(len + 2); | 1272 | client_config.clientid = xmalloc(len + 2); |
1243 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; | 1273 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; |
1244 | client_config.clientid[OPT_LEN] = len; | 1274 | client_config.clientid[OPT_LEN] = len; |
@@ -1250,32 +1280,34 @@ int udhcpc_main(int argc, char *argv[]) | |||
1250 | break; | 1280 | break; |
1251 | case 'H': | 1281 | case 'H': |
1252 | len = strlen(optarg); | 1282 | len = strlen(optarg); |
1253 | if (len > 255) len = 255; | 1283 | if (len > 255) { |
1254 | if (client_config.hostname) free(client_config.hostname); | 1284 | len = 255; |
1285 | } | ||
1286 | if (client_config.hostname) { | ||
1287 | free(client_config.hostname); | ||
1288 | } | ||
1255 | client_config.hostname = xmalloc(len + 2); | 1289 | client_config.hostname = xmalloc(len + 2); |
1256 | client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; | 1290 | client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; |
1257 | client_config.hostname[OPT_LEN] = len; | 1291 | client_config.hostname[OPT_LEN] = len; |
1258 | strncpy(client_config.hostname + 2, optarg, len); | 1292 | strncpy(client_config.hostname + 2, optarg, len); |
1259 | break; | 1293 | break; |
1260 | case 'h': | 1294 | case 'h': |
1261 | puts( | 1295 | puts("Usage: udhcpcd [OPTIONS]\n\n" |
1262 | "Usage: udhcpcd [OPTIONS]\n\n" | 1296 | " -c, --clientid=CLIENTID Client identifier\n" |
1263 | " -c, --clientid=CLIENTID Client identifier\n" | 1297 | " -H, --hostname=HOSTNAME Client hostname\n" |
1264 | " -H, --hostname=HOSTNAME Client hostname\n" | 1298 | " -f, --foreground Do not fork after getting lease\n" |
1265 | " -f, --foreground Do not fork after getting lease\n" | 1299 | " -i, --interface=INTERFACE Interface to use (default: eth0)\n" |
1266 | " -i, --interface=INTERFACE Interface to use (default: eth0)\n" | 1300 | " -n, --now Exit with failure if lease cannot be\n" |
1267 | " -n, --now Exit with failure if lease cannot be\n" | 1301 | " immediately negotiated.\n" |
1268 | " immediately negotiated.\n" | 1302 | " -p, --pidfile=file Store process ID of daemon in file\n" |
1269 | " -p, --pidfile=file Store process ID of daemon in file\n" | 1303 | " -q, --quit Quit after obtaining lease\n" |
1270 | " -q, --quit Quit after obtaining lease\n" | 1304 | " -r, --request=IP IP address to request (default: none)\n" |
1271 | " -r, --request=IP IP address to request (default: none)\n" | 1305 | " -s, --script=file Run file at dhcp events (default:\n" |
1272 | " -s, --script=file Run file at dhcp events (default:\n" | 1306 | " " DEFAULT_SCRIPT ")\n" |
1273 | " " DEFAULT_SCRIPT ")\n" | 1307 | " -v, --version Display version"); |
1274 | " -v, --version Display version" | ||
1275 | ); | ||
1276 | return 0; | 1308 | return 0; |
1277 | case 'i': | 1309 | case 'i': |
1278 | client_config.interface = optarg; | 1310 | client_config.interface = optarg; |
1279 | break; | 1311 | break; |
1280 | case 'n': | 1312 | case 'n': |
1281 | client_config.abort_if_no_lease = 1; | 1313 | client_config.abort_if_no_lease = 1; |
@@ -1305,10 +1337,12 @@ int udhcpc_main(int argc, char *argv[]) | |||
1305 | pid_fd = pidfile_acquire(client_config.pidfile); | 1337 | pid_fd = pidfile_acquire(client_config.pidfile); |
1306 | pidfile_write_release(pid_fd); | 1338 | pidfile_write_release(pid_fd); |
1307 | 1339 | ||
1308 | if (read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.arp) < 0) { | 1340 | if (read_interface |
1341 | (client_config.interface, &client_config.ifindex, NULL, | ||
1342 | client_config.arp) < 0) { | ||
1309 | exit_client(1); | 1343 | exit_client(1); |
1310 | } | 1344 | } |
1311 | 1345 | ||
1312 | if (!client_config.clientid) { | 1346 | if (!client_config.clientid) { |
1313 | client_config.clientid = xmalloc(6 + 3); | 1347 | client_config.clientid = xmalloc(6 + 3); |
1314 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; | 1348 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; |
@@ -1321,7 +1355,7 @@ int udhcpc_main(int argc, char *argv[]) | |||
1321 | signal(SIGUSR1, renew_requested); | 1355 | signal(SIGUSR1, renew_requested); |
1322 | signal(SIGUSR2, release_requested); | 1356 | signal(SIGUSR2, release_requested); |
1323 | signal(SIGTERM, terminate); | 1357 | signal(SIGTERM, terminate); |
1324 | 1358 | ||
1325 | state = INIT_SELECTING; | 1359 | state = INIT_SELECTING; |
1326 | run_script(NULL, "deconfig"); | 1360 | run_script(NULL, "deconfig"); |
1327 | change_mode(LISTEN_RAW); | 1361 | change_mode(LISTEN_RAW); |
@@ -1333,12 +1367,15 @@ int udhcpc_main(int argc, char *argv[]) | |||
1333 | 1367 | ||
1334 | if (listen_mode != LISTEN_NONE && fd_main < 0) { | 1368 | if (listen_mode != LISTEN_NONE && fd_main < 0) { |
1335 | if (listen_mode == LISTEN_KERNEL) { | 1369 | if (listen_mode == LISTEN_KERNEL) { |
1336 | fd_main = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); | 1370 | fd_main = |
1371 | listen_socket(INADDR_ANY, CLIENT_PORT, | ||
1372 | client_config.interface); | ||
1337 | } else { | 1373 | } else { |
1338 | fd_main = raw_socket(client_config.ifindex); | 1374 | fd_main = raw_socket(client_config.ifindex); |
1339 | } | 1375 | } |
1340 | if (fd_main < 0) { | 1376 | if (fd_main < 0) { |
1341 | LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", sys_errlist[errno]); | 1377 | LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", |
1378 | sys_errlist[errno]); | ||
1342 | exit_client(0); | 1379 | exit_client(0); |
1343 | } | 1380 | } |
1344 | } | 1381 | } |
@@ -1350,7 +1387,7 @@ int udhcpc_main(int argc, char *argv[]) | |||
1350 | DEBUG(LOG_INFO, "Waiting on select...\n"); | 1387 | DEBUG(LOG_INFO, "Waiting on select...\n"); |
1351 | retval = select(fd_main + 1, &rfds, NULL, NULL, &tv); | 1388 | retval = select(fd_main + 1, &rfds, NULL, NULL, &tv); |
1352 | } else { | 1389 | } else { |
1353 | retval = 0; /* If we already timed out, fall through */ | 1390 | retval = 0; /* If we already timed out, fall through */ |
1354 | } | 1391 | } |
1355 | 1392 | ||
1356 | now = time(0); | 1393 | now = time(0); |
@@ -1363,7 +1400,7 @@ int udhcpc_main(int argc, char *argv[]) | |||
1363 | xid = random_xid(); | 1400 | xid = random_xid(); |
1364 | } | 1401 | } |
1365 | /* send discover packet */ | 1402 | /* send discover packet */ |
1366 | send_discover(xid, requested_ip); /* broadcast */ | 1403 | send_discover(xid, requested_ip); /* broadcast */ |
1367 | 1404 | ||
1368 | timeout = now + ((packet_num == 2) ? 10 : 2); | 1405 | timeout = now + ((packet_num == 2) ? 10 : 2); |
1369 | packet_num++; | 1406 | packet_num++; |
@@ -1382,9 +1419,9 @@ int udhcpc_main(int argc, char *argv[]) | |||
1382 | if (packet_num < 3) { | 1419 | if (packet_num < 3) { |
1383 | /* send request packet */ | 1420 | /* send request packet */ |
1384 | if (state == RENEW_REQUESTED) { | 1421 | if (state == RENEW_REQUESTED) { |
1385 | send_renew(xid, server_addr, requested_ip); /* unicast */ | 1422 | send_renew(xid, server_addr, requested_ip); /* unicast */ |
1386 | } else { | 1423 | } else { |
1387 | send_selecting(xid, server_addr, requested_ip); /* broadcast */ | 1424 | send_selecting(xid, server_addr, requested_ip); /* broadcast */ |
1388 | } | 1425 | } |
1389 | timeout = now + ((packet_num == 2) ? 10 : 2); | 1426 | timeout = now + ((packet_num == 2) ? 10 : 2); |
1390 | packet_num++; | 1427 | packet_num++; |
@@ -1411,8 +1448,8 @@ int udhcpc_main(int argc, char *argv[]) | |||
1411 | DEBUG(LOG_INFO, "Entering rebinding state"); | 1448 | DEBUG(LOG_INFO, "Entering rebinding state"); |
1412 | } else { | 1449 | } else { |
1413 | /* send a request packet */ | 1450 | /* send a request packet */ |
1414 | send_renew(xid, server_addr, requested_ip); /* unicast */ | 1451 | send_renew(xid, server_addr, requested_ip); /* unicast */ |
1415 | 1452 | ||
1416 | t1 = (t2 - t1) / 2 + t1; | 1453 | t1 = (t2 - t1) / 2 + t1; |
1417 | timeout = t1 + start; | 1454 | timeout = t1 + start; |
1418 | } | 1455 | } |
@@ -1429,7 +1466,7 @@ int udhcpc_main(int argc, char *argv[]) | |||
1429 | change_mode(LISTEN_RAW); | 1466 | change_mode(LISTEN_RAW); |
1430 | } else { | 1467 | } else { |
1431 | /* send a request packet */ | 1468 | /* send a request packet */ |
1432 | send_renew(xid, 0, requested_ip); /* broadcast */ | 1469 | send_renew(xid, 0, requested_ip); /* broadcast */ |
1433 | 1470 | ||
1434 | t2 = (lease - t2) / 2 + t2; | 1471 | t2 = (lease - t2) / 2 + t2; |
1435 | timeout = t2 + start; | 1472 | timeout = t2 + start; |
@@ -1440,17 +1477,19 @@ int udhcpc_main(int argc, char *argv[]) | |||
1440 | timeout = 0x7fffffff; | 1477 | timeout = 0x7fffffff; |
1441 | break; | 1478 | break; |
1442 | } | 1479 | } |
1443 | } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd_main, &rfds)) { | 1480 | } else if (retval > 0 && listen_mode != LISTEN_NONE |
1481 | && FD_ISSET(fd_main, &rfds)) { | ||
1444 | /* a packet is ready, read it */ | 1482 | /* a packet is ready, read it */ |
1445 | 1483 | ||
1446 | if (listen_mode == LISTEN_KERNEL) { | 1484 | if (listen_mode == LISTEN_KERNEL) { |
1447 | len = get_packet(&packet, fd_main); | 1485 | len = get_packet(&packet, fd_main); |
1448 | } else { | 1486 | } else { |
1449 | len = get_raw_packet(&packet, fd_main); | 1487 | len = get_raw_packet(&packet, fd_main); |
1450 | } | 1488 | } |
1451 | if (len == -1 && errno != EINTR) { | 1489 | if (len == -1 && errno != EINTR) { |
1452 | DEBUG(LOG_INFO, "error on read, %s, reopening socket", sys_errlist[errno]); | 1490 | DEBUG(LOG_INFO, "error on read, %s, reopening socket", |
1453 | change_mode(listen_mode); /* just close and reopen */ | 1491 | sys_errlist[errno]); |
1492 | change_mode(listen_mode); /* just close and reopen */ | ||
1454 | } | 1493 | } |
1455 | if (len < 0) { | 1494 | if (len < 0) { |
1456 | continue; | 1495 | continue; |
@@ -1458,15 +1497,15 @@ int udhcpc_main(int argc, char *argv[]) | |||
1458 | 1497 | ||
1459 | if (packet.xid != xid) { | 1498 | if (packet.xid != xid) { |
1460 | DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)", | 1499 | DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)", |
1461 | (unsigned long) packet.xid, xid); | 1500 | (unsigned long) packet.xid, xid); |
1462 | continue; | 1501 | continue; |
1463 | } | 1502 | } |
1464 | 1503 | ||
1465 | if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { | 1504 | if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { |
1466 | DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); | 1505 | DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); |
1467 | continue; | 1506 | continue; |
1468 | } | 1507 | } |
1469 | 1508 | ||
1470 | switch (state) { | 1509 | switch (state) { |
1471 | case INIT_SELECTING: | 1510 | case INIT_SELECTING: |
1472 | /* Must be a DHCPOFFER to one of our xid's */ | 1511 | /* Must be a DHCPOFFER to one of our xid's */ |
@@ -1475,7 +1514,7 @@ int udhcpc_main(int argc, char *argv[]) | |||
1475 | memcpy(&server_addr, temp, 4); | 1514 | memcpy(&server_addr, temp, 4); |
1476 | xid = packet.xid; | 1515 | xid = packet.xid; |
1477 | requested_ip = packet.yiaddr; | 1516 | requested_ip = packet.yiaddr; |
1478 | 1517 | ||
1479 | /* enter requesting state */ | 1518 | /* enter requesting state */ |
1480 | state = REQUESTING; | 1519 | state = REQUESTING; |
1481 | timeout = now; | 1520 | timeout = now; |
@@ -1491,43 +1530,47 @@ int udhcpc_main(int argc, char *argv[]) | |||
1491 | case REBINDING: | 1530 | case REBINDING: |
1492 | if (*message == DHCPACK) { | 1531 | if (*message == DHCPACK) { |
1493 | if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { | 1532 | if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { |
1494 | LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease"); | 1533 | LOG(LOG_ERR, |
1534 | "No lease time with ACK, using 1 hour lease"); | ||
1495 | lease = 60 * 60; | 1535 | lease = 60 * 60; |
1496 | } else { | 1536 | } else { |
1497 | memcpy(&lease, temp, 4); | 1537 | memcpy(&lease, temp, 4); |
1498 | lease = ntohl(lease); | 1538 | lease = ntohl(lease); |
1499 | } | 1539 | } |
1500 | 1540 | ||
1501 | /* enter bound state */ | 1541 | /* enter bound state */ |
1502 | t1 = lease / 2; | 1542 | t1 = lease / 2; |
1503 | 1543 | ||
1504 | /* little fixed point for n * .875 */ | 1544 | /* little fixed point for n * .875 */ |
1505 | t2 = (lease * 0x7) >> 3; | 1545 | t2 = (lease * 0x7) >> 3; |
1506 | temp_addr.s_addr = packet.yiaddr; | 1546 | temp_addr.s_addr = packet.yiaddr; |
1507 | LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", inet_ntoa(temp_addr), lease); | 1547 | LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", |
1548 | inet_ntoa(temp_addr), lease); | ||
1508 | start = now; | 1549 | start = now; |
1509 | timeout = t1 + start; | 1550 | timeout = t1 + start; |
1510 | requested_ip = packet.yiaddr; | 1551 | requested_ip = packet.yiaddr; |
1511 | run_script(&packet, ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); | 1552 | run_script(&packet, |
1553 | ((state == RENEWING | ||
1554 | || state == REBINDING) ? "renew" : "bound")); | ||
1512 | 1555 | ||
1513 | state = BOUND; | 1556 | state = BOUND; |
1514 | change_mode(LISTEN_NONE); | 1557 | change_mode(LISTEN_NONE); |
1515 | { | 1558 | { |
1516 | int pid_fd2; | 1559 | int pid_fd2; |
1560 | |||
1517 | if (client_config.quit_after_lease) { | 1561 | if (client_config.quit_after_lease) { |
1518 | exit_client(0); | 1562 | exit_client(0); |
1519 | } else if (!client_config.foreground) { | 1563 | } else if (!client_config.foreground) { |
1520 | pid_fd2 = pidfile_acquire(client_config.pidfile); /* hold lock during fork. */ | 1564 | pid_fd2 = pidfile_acquire(client_config.pidfile); /* hold lock during fork. */ |
1521 | if (daemon(0, 0) == -1) { | 1565 | if (daemon(0, 0) == -1) { |
1522 | perror("fork"); | 1566 | perror("fork"); |
1523 | exit_client(1); | 1567 | exit_client(1); |
1524 | } | 1568 | } |
1525 | client_config.foreground = 1; /* Do not fork again. */ | 1569 | client_config.foreground = 1; /* Do not fork again. */ |
1526 | pidfile_write_release(pid_fd2); | 1570 | pidfile_write_release(pid_fd2); |
1527 | } | 1571 | } |
1528 | } | 1572 | } |
1529 | } | 1573 | } else if (*message == DHCPNAK) { |
1530 | else if (*message == DHCPNAK) { | ||
1531 | /* return to init state */ | 1574 | /* return to init state */ |
1532 | LOG(LOG_INFO, "Received DHCP NAK"); | 1575 | LOG(LOG_INFO, "Received DHCP NAK"); |
1533 | run_script(&packet, "nak"); | 1576 | run_script(&packet, "nak"); |
@@ -1539,20 +1582,19 @@ int udhcpc_main(int argc, char *argv[]) | |||
1539 | requested_ip = 0; | 1582 | requested_ip = 0; |
1540 | packet_num = 0; | 1583 | packet_num = 0; |
1541 | change_mode(LISTEN_RAW); | 1584 | change_mode(LISTEN_RAW); |
1542 | sleep(3); /* avoid excessive network traffic */ | 1585 | sleep(3); /* avoid excessive network traffic */ |
1543 | } | 1586 | } |
1544 | break; | 1587 | break; |
1545 | /* case BOUND, RELEASED: - ignore all packets */ | 1588 | /* case BOUND, RELEASED: - ignore all packets */ |
1546 | } | 1589 | } |
1547 | } | 1590 | } else if (retval == -1 && errno == EINTR) { |
1548 | else if (retval == -1 && errno == EINTR) { | ||
1549 | /* a signal was caught */ | 1591 | /* a signal was caught */ |
1550 | 1592 | ||
1551 | } else { | 1593 | } else { |
1552 | /* An error occured */ | 1594 | /* An error occured */ |
1553 | DEBUG(LOG_ERR, "Error on select"); | 1595 | DEBUG(LOG_ERR, "Error on select"); |
1554 | } | 1596 | } |
1555 | 1597 | ||
1556 | } | 1598 | } |
1557 | return 0; | 1599 | return 0; |
1558 | } | 1600 | } |