1/* dhcpc.c
2 *
3 * udhcp DHCP client
4 *
5 * Russ Dill <Russ.Dill@asu.edu> July 2001
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <stdio.h>
23#include <sys/time.h>
24#include <sys/types.h>
25#include <sys/file.h>
26#include <unistd.h>
27#include <getopt.h>
28#include <stdlib.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <signal.h>
33#include <time.h>
34#include <string.h>
35#include <sys/ioctl.h>
36#include <net/if.h>
37#include <errno.h>
38#include <sys/sysinfo.h>
39
40#include "dhcpd.h"
41#include "dhcpc.h"
42#include "options.h"
43#include "clientpacket.h"
44#include "packet.h"
45#include "script.h"
46#include "socket.h"
47#include "debug.h"
48#include "pidfile.h"
49
50static int state;
51static unsigned long requested_ip; /* = 0 */
52static unsigned long server_addr;
53static unsigned long timeout = 0;;
54static int packet_num; /* = 0 */
55static int fd;
56static int signal_pipe[2];
57
58#define LISTEN_NONE 0
59#define LISTEN_KERNEL 1
60#define LISTEN_RAW 2
61//static int listen_mode;
62static int listen_mode = LISTEN_NONE;/* Foxconn modified by Max Ding, 04/12/2008 @dhcp_issue_of_KO */
63
64static int run_on_lan = 0;	/* Foxconn added pling 02/24/2011 */
65
66#define DEFAULT_SCRIPT	"/usr/share/udhcpc/default.script"
67
68struct client_config_t client_config = {
69	/* Default options. */
70	abort_if_no_lease: 0,
71	foreground: 0,
72	quit_after_lease: 0,
73	background_if_no_lease: 0,
74	interface: "eth0",
75	pidfile: NULL,
76	script: DEFAULT_SCRIPT,
77	clientid: NULL,
78	hostname: NULL,
79	ifindex: 0,
80	arp: "\0\0\0\0\0\0",		/* appease gcc-3.0 */
81};
82
83/* Foxconn add start, Max Ding, 04/12/2008 for @dhcp_issue_of_KO */
84#define MAJOR_NUM 100
85#define AG_MAX_ARG_CNT	    32
86#define DEVICE_FILE_NAME "acos_nat_cli"
87#define DEV_FILE_NAME_W_PATH    "/dev/"DEVICE_FILE_NAME
88#define IOCTL_AG_FW_LISTEN_PORT_SET         _IOR(MAJOR_NUM, 61, char *)
89#define DEV_LISTEN_PORT_DHCPC   5       /* DHCP listen port: 68 */
90
91typedef struct agIoctlParamPackage
92{
93    int        paramCnt;
94    int       paramLen[AG_MAX_ARG_CNT];
95    void*   param[AG_MAX_ARG_CNT];
96
97} T_agIoctlParamPkg;
98
99static int agApi_setDeviceListenPort(int port_idx, int port_num, int enable)
100{
101   	int ret_val=0, file_desc;
102	T_agIoctlParamPkg paramPkg;
103
104    file_desc = open(DEV_FILE_NAME_W_PATH, O_RDWR);
105	if (file_desc < 0)
106	{
107        return 0;
108	}
109
110    memset(&paramPkg, 0, sizeof(paramPkg));
111    paramPkg.paramCnt = 3;
112    paramPkg.param[0] = (void *)port_idx;
113    paramPkg.param[1] = (void *)port_num;
114    paramPkg.param[2] = (void *)enable;
115
116	ret_val = ioctl(file_desc, IOCTL_AG_FW_LISTEN_PORT_SET, &paramPkg);
117
118    close(file_desc);
119
120    if (paramPkg.paramCnt <= -1)
121        return paramPkg.paramCnt;
122
123    return ret_val;
124}
125/* Foxconn add end, Max Ding, 04/12/2008 */
126
127
128#ifndef BB_VER
129static void show_usage(void)
130{
131	printf(
132"Usage: udhcpc [OPTIONS]\n\n"
133"  -c, --clientid=CLIENTID         Client identifier\n"
134"  -H, --hostname=HOSTNAME         Client hostname\n"
135"  -h                              Alias for -H\n"
136"  -f, --foreground                Do not fork after getting lease\n"
137"  -b, --background                Fork to background if lease cannot be\n"
138"                                  immediately negotiated.\n"
139"  -i, --interface=INTERFACE       Interface to use (default: eth0)\n"
140"  -n, --now                       Exit with failure if lease cannot be\n"
141"                                  immediately negotiated.\n"
142"  -p, --pidfile=file              Store process ID of daemon in file\n"
143"  -q, --quit                      Quit after obtaining lease\n"
144"  -r, --request=IP                IP address to request (default: none)\n"
145"  -s, --script=file               Run file at dhcp events (default:\n"
146"                                  " DEFAULT_SCRIPT ")\n"
147"  -v, --version                   Display version\n"
148	);
149	exit(0);
150}
151#endif
152
153
154/* just a little helper */
155static void change_mode(int new_mode)
156{
157	DEBUG(LOG_INFO, "entering %s listen mode",
158		new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
159	close(fd);
160	fd = -1;
161	/* Foxconn add start, Max Ding, 04/12/2008 for @dhcp_issue_of_KO */
162	if (new_mode == LISTEN_NONE)
163	{
164	    if (listen_mode != LISTEN_NONE)
165	        agApi_setDeviceListenPort(DEV_LISTEN_PORT_DHCPC, 68, 0);
166	}
167	else
168	{
169	    if (listen_mode == LISTEN_NONE)
170	        agApi_setDeviceListenPort(DEV_LISTEN_PORT_DHCPC, 68, 1);
171	}
172	/* Foxconn add end, Max Ding, 04/12/2008 */
173	listen_mode = new_mode;
174}
175
176
177/* perform a renew */
178static void perform_renew(void)
179{
180	LOG(LOG_INFO, "Performing a DHCP renew");
181	switch (state) {
182	case BOUND:
183		change_mode(LISTEN_KERNEL);
184	case RENEWING:
185	case REBINDING:
186		state = RENEW_REQUESTED;
187		break;
188	case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
189		run_script(NULL, "deconfig");
190	case REQUESTING:
191	case RELEASED:
192		change_mode(LISTEN_RAW);
193		state = INIT_SELECTING;
194		break;
195	case INIT_SELECTING:
196		break;
197	}
198
199	/* start things over */
200	packet_num = 0;
201
202	/* Kill any timeouts because the user wants this to hurry along */
203	timeout = 0;
204}
205
206
207/* perform a release */
208static void perform_release(void)
209{
210	char buffer[16];
211	struct in_addr temp_addr;
212
213	/* send release packet */
214	if (state == BOUND || state == RENEWING || state == REBINDING) {
215		temp_addr.s_addr = server_addr;
216		sprintf(buffer, "%s", inet_ntoa(temp_addr));
217		temp_addr.s_addr = requested_ip;
218		LOG(LOG_INFO, "Unicasting a release of %s to %s",
219				inet_ntoa(temp_addr), buffer);
220		send_release(server_addr, requested_ip); /* unicast */
221		run_script(NULL, "deconfig");
222	}
223	LOG(LOG_INFO, "Entering released state");
224
225	change_mode(LISTEN_NONE);
226	state = RELEASED;
227	timeout = 0x7fffffff;
228}
229
230
231/* Exit and cleanup */
232static void exit_client(int retval)
233{
234	/* Foxconn added start pling 02/07/2012 */
235	/* WNDR4000 #TD53: GRC test port 68 is not closed.
236	 * Force disable NAT device list port for port 68, before we termiante */
237	if (listen_mode != LISTEN_NONE)
238		change_mode(LISTEN_NONE);
239	/* Foxconn added end pling 02/07/2012 */
240
241	pidfile_delete(client_config.pidfile);
242	CLOSE_LOG();
243	exit(retval);
244}
245
246
247/* Signal handler */
248static void signal_handler(int sig)
249{
250	if (write(signal_pipe[1], &sig, sizeof(sig)) < 0) {
251		LOG(LOG_ERR, "Could not send signal: %s",
252			strerror(errno));
253	}
254}
255
256
257static void background(void)
258{
259	int pid_fd;
260
261	pid_fd = pidfile_acquire(client_config.pidfile); /* hold lock during fork. */
262	while (pid_fd >= 0 && pid_fd < 3) pid_fd = dup(pid_fd); /* don't let daemon close it */
263	if (daemon(0, 0) == -1) {
264		perror("fork");
265		exit_client(1);
266	}
267	client_config.foreground = 1; /* Do not fork again. */
268	pidfile_write_release(pid_fd);
269}
270
271
272#ifdef COMBINED_BINARY
273int udhcpc_main(int argc, char *argv[])
274#else
275int main(int argc, char *argv[])
276#endif
277{
278	unsigned char *temp, *message;
279	unsigned long t1 = 0, t2 = 0, xid = 0;
280	unsigned long start = 0, lease;
281	fd_set rfds;
282	int retval;
283	struct timeval tv;
284	int c, len;
285	/* Foxconn modify start, Max Ding, 06/11/2010 fix memory overwrite issue */
286	/* struct dhcpMessage packet; */
287	struct udp_dhcp_packet_rcv packet;
288	/* Foxconn modify end, Max Ding, 06/11/2010 */
289	struct in_addr temp_addr;
290	int pid_fd;
291	time_t now;
292	int max_fd;
293	int sig;
294    unsigned long curr_time;
295    struct sysinfo info;
296
297	/* Foxconn added start pling 08/06/2012 */
298	/* WNDR4500v2 Mantis 2303, per Router Spec,
299	 *  restart DHCP client retry process every 5 minutes.
300	 */
301#define DHCPC_TIMEOUT_RESTART_INTERVAL		300
302	int packet_timeout = 1;
303	int accumulated_timeout = 0;
304	/* Foxconn added end pling 08/06/2012 */
305
306	static struct option arg_options[] = {
307		{"clientid",	required_argument,	0, 'c'},
308		{"foreground",	no_argument,		0, 'f'},
309		{"background",	no_argument,		0, 'b'},
310		{"hostname",	required_argument,	0, 'H'},
311		{"hostname",    required_argument,      0, 'h'},
312		{"interface",	required_argument,	0, 'i'},
313		{"now", 	no_argument,		0, 'n'},
314		{"pidfile",	required_argument,	0, 'p'},
315		{"quit",	no_argument,		0, 'q'},
316		{"request",	required_argument,	0, 'r'},
317		{"script",	required_argument,	0, 's'},
318		{"version",	no_argument,		0, 'v'},
319		{"help",	no_argument,		0, '?'},
320		{0, 0, 0, 0}
321	};
322
323	/* get options */
324	while (1) {
325		int option_index = 0;
326		/* Foxconn modified start pling 02/24/2011 */
327		/* Add option '-l' to tell this runs on LAN (LAN auto ip) */
328#if 0
329		c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:v", arg_options, &option_index);
330#endif
331		c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:vl",
332				arg_options, &option_index);
333		/* Foxconn modified end pling 02/24/2011 */
334		if (c == -1) break;
335
336		switch (c) {
337		case 'c':
338			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
339			if (client_config.clientid) free(client_config.clientid);
340			client_config.clientid = xmalloc(len + 2);
341			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
342			client_config.clientid[OPT_LEN] = len;
343			client_config.clientid[OPT_DATA] = '\0';
344			strncpy(client_config.clientid + OPT_DATA, optarg, len);
345			break;
346		case 'f':
347			client_config.foreground = 1;
348			break;
349		case 'b':
350			client_config.background_if_no_lease = 1;
351			break;
352		case 'h':
353		case 'H':
354			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
355			if (client_config.hostname) free(client_config.hostname);
356			client_config.hostname = xmalloc(len + 2);
357			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
358			client_config.hostname[OPT_LEN] = len;
359			strncpy(client_config.hostname + 2, optarg, len);
360			break;
361		case 'i':
362			client_config.interface =  optarg;
363			break;
364		case 'n':
365			client_config.abort_if_no_lease = 1;
366			break;
367		case 'p':
368			client_config.pidfile = optarg;
369			break;
370		case 'q':
371			client_config.quit_after_lease = 1;
372			break;
373		case 'r':
374			requested_ip = inet_addr(optarg);
375			break;
376		case 's':
377			client_config.script = optarg;
378			break;
379		case 'v':
380			printf("udhcpcd, version %s\n\n", VERSION);
381			exit_client(0);
382			break;
383		/* Foxconn added start pling 02/24/2011 */
384		/* LAN Auto IP changes */
385		case 'l':
386			run_on_lan = 1;
387			LOG(LOG_INFO, "run on LAN!\n");
388			break;
389		/* Foxconn added end pling 02/24/2011 */
390		default:
391			show_usage();
392		}
393	}
394
395	OPEN_LOG("udhcpc");
396	LOG(LOG_INFO, "udhcp client (v%s) started", VERSION);
397
398	pid_fd = pidfile_acquire(client_config.pidfile);
399	pidfile_write_release(pid_fd);
400
401	if (read_interface(client_config.interface, &client_config.ifindex,
402			   NULL, client_config.arp) < 0)
403		exit_client(1);
404
405	if (!client_config.clientid) {
406		client_config.clientid = xmalloc(6 + 3);
407		client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
408		client_config.clientid[OPT_LEN] = 7;
409		client_config.clientid[OPT_DATA] = 1;
410		memcpy(client_config.clientid + 3, client_config.arp, 6);
411	}
412
413	/* ensure that stdin/stdout/stderr are never returned by pipe() */
414	if (fcntl(STDIN_FILENO, F_GETFL) == -1)
415		(void) open("/dev/null", O_RDONLY);
416	if (fcntl(STDOUT_FILENO, F_GETFL) == -1)
417		(void) open("/dev/null", O_WRONLY);
418	if (fcntl(STDERR_FILENO, F_GETFL) == -1)
419		(void) open("/dev/null", O_WRONLY);
420
421	/* setup signal handlers */
422	pipe(signal_pipe);
423	signal(SIGUSR1, signal_handler);
424	signal(SIGUSR2, signal_handler);
425	signal(SIGTERM, signal_handler);
426
427	state = INIT_SELECTING;
428	run_script(NULL, "deconfig");
429	change_mode(LISTEN_RAW);
430
431	for (;;) {
432
433        sysinfo(&info);
434        curr_time = (unsigned long)(info.uptime);
435
436        if (timeout > curr_time)
437    		tv.tv_sec = timeout - curr_time;
438        else
439    		tv.tv_sec = 0;
440		tv.tv_usec = 0;
441		FD_ZERO(&rfds);
442
443		if (listen_mode != LISTEN_NONE && fd < 0) {
444			if (listen_mode == LISTEN_KERNEL)
445				fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
446			else
447				fd = raw_socket(client_config.ifindex);
448			if (fd < 0) {
449				LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", strerror(errno));
450				exit_client(0);
451			}
452		}
453		if (fd >= 0) FD_SET(fd, &rfds);
454		FD_SET(signal_pipe[0], &rfds);
455
456		if (tv.tv_sec > 0) {
457			DEBUG(LOG_INFO, "Waiting on select...\n");
458			max_fd = signal_pipe[0] > fd ? signal_pipe[0] : fd;
459			retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
460		} else retval = 0; /* If we already timed out, fall through */
461
462        sysinfo(&info);
463		now = (unsigned long)(info.uptime);
464		if (retval == 0) {
465			/* timeout dropped to zero */
466			switch (state) {
467			case INIT_SELECTING:
468				if (packet_num < 3) {
469					if (packet_num == 0)
470						xid = random_xid();
471
472					/* send discover packet */
473					send_discover(xid, requested_ip); /* broadcast */
474
475					/* foxconn James modified start, 11/12/2008 @new_internet_detection */
476#ifdef NEW_WANDETECT
477					/* Foxconn modified start pling 08/06/2012 */
478					/* WNDR4500v2 Mantis 2303.
479					 * Per Router Spec, restart DHCP client retry process every 5 minutes.
480					 * However, AP mode DHCP client is not changed.
481					 */
482					if (!run_on_lan) {
483						if (packet_num == 0) {
484							packet_timeout = 1;
485							accumulated_timeout = 0;
486						} else
487							packet_timeout <<= 1;
488						timeout = now + packet_timeout;
489						accumulated_timeout += packet_timeout;
490					} else {
491						timeout = now + ((packet_num == 2) ? 4 : 3);
492					}
493					/* Foxconn modified end pling 08/06/2012 */
494#else
495					timeout = now + ((packet_num == 2) ? 4 : 2);
496#endif
497					/* foxconn James modified end, 11/12/2008 @new_internet_detection */
498
499					packet_num++;
500				} else {
501					if (client_config.background_if_no_lease) {
502						LOG(LOG_INFO, "No lease, forking to background.");
503						background();
504					} else if (client_config.abort_if_no_lease) {
505						LOG(LOG_INFO, "No lease, failing.");
506						exit_client(1);
507				  	}
508					/* wait to try again */
509					/* Foxconn modified start pling 08/06/2012 */
510					/* WNDR4500v2 Mantis 2303.
511					 * Per Router Spec, restart DHCP client retry process every 5 minutes.
512					 * However, AP mode DHCP client is not changed.
513					 */
514					if (!run_on_lan) {
515						send_discover(xid, requested_ip); /* broadcast */
516
517						packet_timeout <<= 1;
518						if (accumulated_timeout + packet_timeout >= DHCPC_TIMEOUT_RESTART_INTERVAL) {
519							packet_timeout = DHCPC_TIMEOUT_RESTART_INTERVAL - accumulated_timeout;
520							packet_num = 0;
521						}
522						timeout = now + packet_timeout;
523						accumulated_timeout += packet_timeout;
524					} else {
525						packet_num = 0;
526						timeout = now + 60;
527					}
528					/* Foxconn modified end pling 08/06/2012 */
529
530					/* Foxconn added start pling 02/24/2011 */
531					/* No lease found yet, signal 'autoipd'
532					 * to start Auto IP process */
533					if (run_on_lan) {
534						system("killall -SIGUSR1 autoipd 2>/dev/null");
535						/* Per Netgear Router Spec 2.0, need to resend
536						 * DHCP Discover every 4 minutes.
537						 */
538						timeout = now + 240;
539					}
540					/* Foxconn added end pling 02/24/2011 */
541				}
542				break;
543			case RENEW_REQUESTED:
544			case REQUESTING:
545				if (packet_num < 3) {
546					/* send request packet */
547					if (state == RENEW_REQUESTED)
548						send_renew(xid, server_addr, requested_ip); /* unicast */
549					else send_selecting(xid, server_addr, requested_ip); /* broadcast */
550
551					timeout = now + ((packet_num == 2) ? 10 : 2);
552					packet_num++;
553				} else {
554					/* timed out, go back to init state */
555					if (state == RENEW_REQUESTED) run_script(NULL, "deconfig");
556					state = INIT_SELECTING;
557					timeout = now;
558					packet_num = 0;
559					change_mode(LISTEN_RAW);
560				}
561				break;
562			case BOUND:
563				/* Lease is starting to run out, time to enter renewing state */
564				state = RENEWING;
565				change_mode(LISTEN_KERNEL);
566				DEBUG(LOG_INFO, "Entering renew state");
567				/* fall right through */
568			case RENEWING:
569				/* Either set a new T1, or enter REBINDING state */
570				if ((t2 - t1) <= (lease / 14400 + 1)) {
571					/* timed out, enter rebinding state */
572					state = REBINDING;
573					timeout = now + (t2 - t1);
574					DEBUG(LOG_INFO, "Entering rebinding state");
575				} else {
576					/* send a request packet */
577					send_renew(xid, server_addr, requested_ip); /* unicast */
578
579					t1 = (t2 - t1) / 2 + t1;
580					timeout = t1 + start;
581				}
582				break;
583			case REBINDING:
584				/* Either set a new T2, or enter INIT state */
585				if ((lease - t2) <= (lease / 14400 + 1)) {
586					/* timed out, enter init state */
587					state = INIT_SELECTING;
588					LOG(LOG_INFO, "Lease lost, entering init state");
589					run_script(NULL, "deconfig");
590					timeout = now;
591					packet_num = 0;
592					change_mode(LISTEN_RAW);
593				} else {
594					/* send a request packet */
595					send_renew(xid, 0, requested_ip); /* broadcast */
596
597					t2 = (lease - t2) / 2 + t2;
598					timeout = t2 + start;
599				}
600				break;
601			case RELEASED:
602				/* yah, I know, *you* say it would never happen */
603				timeout = 0x7fffffff;
604				break;
605			}
606		} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
607			/* a packet is ready, read it */
608
609			/* Foxconn modify start, Max Ding, 06/11/2010 */
610			if (listen_mode == LISTEN_KERNEL)
611				/* len = get_packet(&packet, fd); */
612				len = get_packet(&packet.data, fd);
613			/* else len = get_raw_packet(&packet, fd); */
614			else len = get_raw_packet(&packet.data, fd);
615			/* Foxconn modify start, Max Ding, 06/11/2010 */
616
617			if (len == -1 && errno != EINTR) {
618				DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno));
619				change_mode(listen_mode); /* just close and reopen */
620			}
621			if (len < 0) continue;
622
623			/* Foxconn modify start, Max Ding, 06/11/2010 */
624			/* if (packet.xid != xid) { */
625			if (packet.data.xid != xid) {
626				DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
627					/* (unsigned long) packet.xid, xid); */
628					(unsigned long) packet.data.xid, xid);
629				continue;
630			}
631
632			/* if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { */
633			if ((message = get_option(&packet.data, DHCP_MESSAGE_TYPE)) == NULL) {
634				DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
635				continue;
636			}
637			/* Foxconn modify end, Max Ding, 06/11/2010 */
638
639			switch (state) {
640			case INIT_SELECTING:
641				/* Must be a DHCPOFFER to one of our xid's */
642				/* Foxconn modify start, Max Ding, 06/11/2010 */
643				if (*message == DHCPOFFER) {
644					/* if ((temp = get_option(&packet, DHCP_SERVER_ID))) { */
645					if ((temp = get_option(&packet.data, DHCP_SERVER_ID))) {
646						memcpy(&server_addr, temp, 4);
647						/* xid = packet.xid;
648						requested_ip = packet.yiaddr; */
649						xid = packet.data.xid;
650						requested_ip = packet.data.yiaddr;
651						/* enter requesting state */
652						state = REQUESTING;
653						timeout = now;
654						packet_num = 0;
655					} else {
656						DEBUG(LOG_ERR, "No server ID in message");
657					}
658				}
659				/* Foxconn modify end, Max Ding, 06/11/2010 */
660				break;
661			case RENEW_REQUESTED:
662			case REQUESTING:
663			case RENEWING:
664			case REBINDING:
665				if (*message == DHCPACK) {
666					/* Foxconn modify start, Max Ding, 06/11/2010 */
667					/* if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { */
668					if (!(temp = get_option(&packet.data, DHCP_LEASE_TIME))) {
669					/* Foxconn modify end, Max Ding, 06/11/2010 */
670						LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
671						lease = 60 * 60;
672					} else {
673						memcpy(&lease, temp, 4);
674						lease = ntohl(lease);
675					}
676
677					/* wklin added start, 08/10/2007 */
678					/* check before entering requesting state */
679					/* Foxconn modify start, Max Ding, 06/11/2010 */
680					/* Foxconn modified start pling 05/27/2010 */
681					u_int32_t addr_to_arp;
682					if (state == REQUESTING)
683						addr_to_arp = 0;
684					else
685						addr_to_arp = requested_ip;
686					/* if (arpping(packet.yiaddr, 0, */
687					if (arpping(packet.data.yiaddr, addr_to_arp,
688					/* Foxconn modified end pling 05/27/2010 */
689								client_config.arp, client_config.interface)==0) {
690						/* send_decline(packet.xid, server_addr, packet.yiaddr); *//* broadcast */
691						send_decline(packet.data.xid, server_addr, packet.data.yiaddr); /* broadcast */
692						/* return to init state */
693						state = INIT_SELECTING;
694						timeout = now;
695						requested_ip = 0;
696						packet_num = 0;
697						change_mode(LISTEN_RAW);
698						sleep(10); /* per the RFC, avoid excessive network traffic */
699						break;
700					}
701					/* Foxconn modify end, Max Ding, 06/11/2010 */
702					/* wklin added end, 08/10/2007 */
703					/* enter bound state */
704					t1 = lease / 2;
705
706					/* little fixed point for n * .875 */
707					t2 = (lease * 0x7) >> 3;
708					/* Foxconn modify start, Max Ding, 06/11/2010 */
709					/* temp_addr.s_addr = packet.yiaddr; */
710					temp_addr.s_addr = packet.data.yiaddr;
711					LOG(LOG_INFO, "Lease of %s obtained, lease time %ld",
712						inet_ntoa(temp_addr), lease);
713					start = now;
714					timeout = t1 + start;
715					/* requested_ip = packet.yiaddr; */
716					requested_ip = packet.data.yiaddr;
717					remove("/tmp/udhcpc.routes");/*foxconn added, water, 03/08/10, @option249*/
718					/* run_script(&packet, */
719					run_script(&packet.data,
720						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
721					/* Foxconn modify end, Max Ding, 06/11/2010 */
722
723					state = BOUND;
724					change_mode(LISTEN_NONE);
725					if (client_config.quit_after_lease)
726						exit_client(0);
727					if (!client_config.foreground)
728						background();
729
730				} else if (*message == DHCPNAK) {
731					/* return to init state */
732					LOG(LOG_INFO, "Received DHCP NAK");
733					/* run_script(&packet, "nak"); */
734					run_script(&packet.data, "nak");/* Foxconn modified by Max Ding, 06/11/2010 */
735					if (state != REQUESTING)
736						run_script(NULL, "deconfig");
737					state = INIT_SELECTING;
738					timeout = now;
739					requested_ip = 0;
740					packet_num = 0;
741					change_mode(LISTEN_RAW);
742					sleep(3); /* avoid excessive network traffic */
743				}
744				break;
745			/* case BOUND, RELEASED: - ignore all packets */
746			}
747		} else if (retval > 0 && FD_ISSET(signal_pipe[0], &rfds)) {
748			if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) {
749				DEBUG(LOG_ERR, "Could not read signal: %s",
750					strerror(errno));
751				continue; /* probably just EINTR */
752			}
753			switch (sig) {
754			case SIGUSR1:
755				perform_renew();
756				break;
757			case SIGUSR2:
758				perform_release();
759				break;
760			case SIGTERM:
761				LOG(LOG_INFO, "Received SIGTERM");
762				exit_client(0);
763			}
764		} else if (retval == -1 && errno == EINTR) {
765			/* a signal was caught */
766		} else {
767			/* An error occured */
768			DEBUG(LOG_ERR, "Error on select");
769		}
770
771	}
772	return 0;
773}
774
775