aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-08-23 14:31:28 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-08-23 14:31:28 +0000
commit0be933b5057d33e61aa8b1e3806666765b621f2f (patch)
tree773d0e2464aa351f8fc2806199fead56d0a04a9d
parent50812fff219a3d0b9eccb9ff9647d6d66a7934c7 (diff)
downloadbusybox-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.c702
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
55static int state; 55static int state;
56static unsigned long requested_ip; /* = 0 */ 56static unsigned long requested_ip; /* = 0 */
57static unsigned long server_addr; 57static unsigned long server_addr;
58static unsigned long timeout; 58static unsigned long timeout;
59static int packet_num; /* = 0 */ 59static int packet_num; /* = 0 */
60static int fd_main; 60static 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
150enum { 151enum {
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
192struct 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};
204extern struct client_config_t client_config;
205
206struct dhcpMessage { 193struct 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
212struct 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
225struct client_config_t client_config = { 225struct 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
239struct dhcp_option { 239struct dhcp_option {
@@ -249,70 +249,72 @@ struct udp_dhcp_packet {
249}; 249};
250 250
251static const struct dhcp_option options[] = { 251static 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 */
283static const unsigned char option_lengths[] = { 283static 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...) */
296static const unsigned char max_option_length[] = { 296static 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) */
309static int end_option(unsigned char *optionptr) 309static 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)
322static int add_option_string(unsigned char *optionptr, unsigned char *string) 324static 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 */
338static int add_simple_option(unsigned char *optionptr, unsigned char code, u_int32_t data) 341static 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
374void 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
396static u_int16_t checksum(void *addr, int count) 385static 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 */
422static int raw_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port, 413static 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 */
474static int kernel_packet(struct dhcpMessage *payload, u_int32_t source_ip, int source_port, 468static 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 */
509static void init_packet(struct dhcpMessage *packet, char type) 510static 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 */
577static inline int send_selecting(unsigned long xid, unsigned long server, unsigned long requested) 583static 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 */
597static int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr) 604static 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 */
614static unsigned long random_xid(void) 624static 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 */
625int 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 */
642static void change_mode(int new_mode) 636static 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
727static 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
734static int sprintip(char *dest, char *pre, unsigned char *ip) { 723static 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'. */
740extern inline void fill_options(char *dest, unsigned char *option, const struct dhcp_option *type_p) 730static 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)
929static int pidfile_acquire(char *pidfile) 936static 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)
961static void exit_client(int retval) 971static 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
979extern inline int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp) 991static 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
1025extern inline int listen_socket(unsigned int ip, int port, char *inf) 1040static 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
1130extern inline int get_raw_packet(struct dhcpMessage *payload, int l_fd) 1150static 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}