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	static struct option arg_options[] = {
298		{"clientid",	required_argument,	0, 'c'},
299		{"foreground",	no_argument,		0, 'f'},
300		{"background",	no_argument,		0, 'b'},
301		{"hostname",	required_argument,	0, 'H'},
302		{"hostname",    required_argument,      0, 'h'},
303		{"interface",	required_argument,	0, 'i'},
304		{"now", 	no_argument,		0, 'n'},
305		{"pidfile",	required_argument,	0, 'p'},
306		{"quit",	no_argument,		0, 'q'},
307		{"request",	required_argument,	0, 'r'},
308		{"script",	required_argument,	0, 's'},
309		{"version",	no_argument,		0, 'v'},
310		{"help",	no_argument,		0, '?'},
311		{0, 0, 0, 0}
312	};
313
314	/* get options */
315	while (1) {
316		int option_index = 0;
317		/* Foxconn modified start pling 02/24/2011 */
318		/* Add option '-l' to tell this runs on LAN (LAN auto ip) */
319#if 0
320		c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:v", arg_options, &option_index);
321#endif
322		c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:vl",
323				arg_options, &option_index);
324		/* Foxconn modified end pling 02/24/2011 */
325		if (c == -1) break;
326
327		switch (c) {
328		case 'c':
329			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
330			if (client_config.clientid) free(client_config.clientid);
331			client_config.clientid = xmalloc(len + 2);
332			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
333			client_config.clientid[OPT_LEN] = len;
334			client_config.clientid[OPT_DATA] = '\0';
335			strncpy(client_config.clientid + OPT_DATA, optarg, len);
336			break;
337		case 'f':
338			client_config.foreground = 1;
339			break;
340		case 'b':
341			client_config.background_if_no_lease = 1;
342			break;
343		case 'h':
344		case 'H':
345			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
346			if (client_config.hostname) free(client_config.hostname);
347			client_config.hostname = xmalloc(len + 2);
348			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
349			client_config.hostname[OPT_LEN] = len;
350			strncpy(client_config.hostname + 2, optarg, len);
351			break;
352		case 'i':
353			client_config.interface =  optarg;
354			break;
355		case 'n':
356			client_config.abort_if_no_lease = 1;
357			break;
358		case 'p':
359			client_config.pidfile = optarg;
360			break;
361		case 'q':
362			client_config.quit_after_lease = 1;
363			break;
364		case 'r':
365			requested_ip = inet_addr(optarg);
366			break;
367		case 's':
368			client_config.script = optarg;
369			break;
370		case 'v':
371			printf("udhcpcd, version %s\n\n", VERSION);
372			exit_client(0);
373			break;
374		/* Foxconn added start pling 02/24/2011 */
375		/* LAN Auto IP changes */
376		case 'l':
377			run_on_lan = 1;
378			LOG(LOG_INFO, "run on LAN!\n");
379			break;
380		/* Foxconn added end pling 02/24/2011 */
381		default:
382			show_usage();
383		}
384	}
385
386	OPEN_LOG("udhcpc");
387	LOG(LOG_INFO, "udhcp client (v%s) started", VERSION);
388
389	pid_fd = pidfile_acquire(client_config.pidfile);
390	pidfile_write_release(pid_fd);
391
392	if (read_interface(client_config.interface, &client_config.ifindex,
393			   NULL, client_config.arp) < 0)
394		exit_client(1);
395
396	if (!client_config.clientid) {
397		client_config.clientid = xmalloc(6 + 3);
398		client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
399		client_config.clientid[OPT_LEN] = 7;
400		client_config.clientid[OPT_DATA] = 1;
401		memcpy(client_config.clientid + 3, client_config.arp, 6);
402	}
403
404	/* ensure that stdin/stdout/stderr are never returned by pipe() */
405	if (fcntl(STDIN_FILENO, F_GETFL) == -1)
406		(void) open("/dev/null", O_RDONLY);
407	if (fcntl(STDOUT_FILENO, F_GETFL) == -1)
408		(void) open("/dev/null", O_WRONLY);
409	if (fcntl(STDERR_FILENO, F_GETFL) == -1)
410		(void) open("/dev/null", O_WRONLY);
411
412	/* setup signal handlers */
413	pipe(signal_pipe);
414	signal(SIGUSR1, signal_handler);
415	signal(SIGUSR2, signal_handler);
416	signal(SIGTERM, signal_handler);
417
418	state = INIT_SELECTING;
419	run_script(NULL, "deconfig");
420	change_mode(LISTEN_RAW);
421
422	for (;;) {
423
424        sysinfo(&info);
425        curr_time = (unsigned long)(info.uptime);
426
427        if (timeout > curr_time)
428    		tv.tv_sec = timeout - curr_time;
429        else
430    		tv.tv_sec = 0;
431		tv.tv_usec = 0;
432		FD_ZERO(&rfds);
433
434		if (listen_mode != LISTEN_NONE && fd < 0) {
435			if (listen_mode == LISTEN_KERNEL)
436				fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
437			else
438				fd = raw_socket(client_config.ifindex);
439			if (fd < 0) {
440				LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", strerror(errno));
441				exit_client(0);
442			}
443		}
444		if (fd >= 0) FD_SET(fd, &rfds);
445		FD_SET(signal_pipe[0], &rfds);
446
447		if (tv.tv_sec > 0) {
448			DEBUG(LOG_INFO, "Waiting on select...\n");
449			max_fd = signal_pipe[0] > fd ? signal_pipe[0] : fd;
450			retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
451		} else retval = 0; /* If we already timed out, fall through */
452
453        sysinfo(&info);
454		now = (unsigned long)(info.uptime);
455		if (retval == 0) {
456			/* timeout dropped to zero */
457			switch (state) {
458			case INIT_SELECTING:
459				if (packet_num < 3) {
460					if (packet_num == 0)
461						xid = random_xid();
462
463					/* send discover packet */
464					send_discover(xid, requested_ip); /* broadcast */
465
466					/* foxconn James modified start, 11/12/2008 @new_internet_detection */
467#ifdef NEW_WANDETECT
468					timeout = now + ((packet_num == 2) ? 4 : 3);
469#else
470					timeout = now + ((packet_num == 2) ? 4 : 2);
471#endif
472					/* foxconn James modified end, 11/12/2008 @new_internet_detection */
473
474					packet_num++;
475				} else {
476					if (client_config.background_if_no_lease) {
477						LOG(LOG_INFO, "No lease, forking to background.");
478						background();
479					} else if (client_config.abort_if_no_lease) {
480						LOG(LOG_INFO, "No lease, failing.");
481						exit_client(1);
482				  	}
483					/* wait to try again */
484					packet_num = 0;
485					timeout = now + 60;
486
487					/* Foxconn added start pling 02/24/2011 */
488					/* No lease found yet, signal 'autoipd'
489					 * to start Auto IP process */
490					if (run_on_lan) {
491						system("killall -SIGUSR1 autoipd 2>/dev/null");
492						/* Per Netgear Router Spec 2.0, need to resend
493						 * DHCP Discover every 4 minutes.
494						 */
495						timeout = now + 240;
496					}
497					/* Foxconn added end pling 02/24/2011 */
498				}
499				break;
500			case RENEW_REQUESTED:
501			case REQUESTING:
502				if (packet_num < 3) {
503					/* send request packet */
504					if (state == RENEW_REQUESTED)
505						send_renew(xid, server_addr, requested_ip); /* unicast */
506					else send_selecting(xid, server_addr, requested_ip); /* broadcast */
507
508					timeout = now + ((packet_num == 2) ? 10 : 2);
509					packet_num++;
510				} else {
511					/* timed out, go back to init state */
512					if (state == RENEW_REQUESTED) run_script(NULL, "deconfig");
513					state = INIT_SELECTING;
514					timeout = now;
515					packet_num = 0;
516					change_mode(LISTEN_RAW);
517				}
518				break;
519			case BOUND:
520				/* Lease is starting to run out, time to enter renewing state */
521				state = RENEWING;
522				change_mode(LISTEN_KERNEL);
523				DEBUG(LOG_INFO, "Entering renew state");
524				/* fall right through */
525			case RENEWING:
526				/* Either set a new T1, or enter REBINDING state */
527				if ((t2 - t1) <= (lease / 14400 + 1)) {
528					/* timed out, enter rebinding state */
529					state = REBINDING;
530					timeout = now + (t2 - t1);
531					DEBUG(LOG_INFO, "Entering rebinding state");
532				} else {
533					/* send a request packet */
534					send_renew(xid, server_addr, requested_ip); /* unicast */
535
536					t1 = (t2 - t1) / 2 + t1;
537					timeout = t1 + start;
538				}
539				break;
540			case REBINDING:
541				/* Either set a new T2, or enter INIT state */
542				if ((lease - t2) <= (lease / 14400 + 1)) {
543					/* timed out, enter init state */
544					state = INIT_SELECTING;
545					LOG(LOG_INFO, "Lease lost, entering init state");
546					run_script(NULL, "deconfig");
547					timeout = now;
548					packet_num = 0;
549					change_mode(LISTEN_RAW);
550				} else {
551					/* send a request packet */
552					send_renew(xid, 0, requested_ip); /* broadcast */
553
554					t2 = (lease - t2) / 2 + t2;
555					timeout = t2 + start;
556				}
557				break;
558			case RELEASED:
559				/* yah, I know, *you* say it would never happen */
560				timeout = 0x7fffffff;
561				break;
562			}
563		} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
564			/* a packet is ready, read it */
565
566			/* Foxconn modify start, Max Ding, 06/11/2010 */
567			if (listen_mode == LISTEN_KERNEL)
568				/* len = get_packet(&packet, fd); */
569				len = get_packet(&packet.data, fd);
570			/* else len = get_raw_packet(&packet, fd); */
571			else len = get_raw_packet(&packet.data, fd);
572			/* Foxconn modify start, Max Ding, 06/11/2010 */
573
574			if (len == -1 && errno != EINTR) {
575				DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno));
576				change_mode(listen_mode); /* just close and reopen */
577			}
578			if (len < 0) continue;
579
580			/* Foxconn modify start, Max Ding, 06/11/2010 */
581			/* if (packet.xid != xid) { */
582			if (packet.data.xid != xid) {
583				DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
584					/* (unsigned long) packet.xid, xid); */
585					(unsigned long) packet.data.xid, xid);
586				continue;
587			}
588
589			/* if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { */
590			if ((message = get_option(&packet.data, DHCP_MESSAGE_TYPE)) == NULL) {
591				DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
592				continue;
593			}
594			/* Foxconn modify end, Max Ding, 06/11/2010 */
595
596			switch (state) {
597			case INIT_SELECTING:
598				/* Must be a DHCPOFFER to one of our xid's */
599				/* Foxconn modify start, Max Ding, 06/11/2010 */
600				if (*message == DHCPOFFER) {
601					/* if ((temp = get_option(&packet, DHCP_SERVER_ID))) { */
602					if ((temp = get_option(&packet.data, DHCP_SERVER_ID))) {
603						memcpy(&server_addr, temp, 4);
604						/* xid = packet.xid;
605						requested_ip = packet.yiaddr; */
606						xid = packet.data.xid;
607						requested_ip = packet.data.yiaddr;
608						/* enter requesting state */
609						state = REQUESTING;
610						timeout = now;
611						packet_num = 0;
612					} else {
613						DEBUG(LOG_ERR, "No server ID in message");
614					}
615				}
616				/* Foxconn modify end, Max Ding, 06/11/2010 */
617				break;
618			case RENEW_REQUESTED:
619			case REQUESTING:
620			case RENEWING:
621			case REBINDING:
622				if (*message == DHCPACK) {
623					/* Foxconn modify start, Max Ding, 06/11/2010 */
624					/* if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { */
625					if (!(temp = get_option(&packet.data, DHCP_LEASE_TIME))) {
626					/* Foxconn modify end, Max Ding, 06/11/2010 */
627						LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
628						lease = 60 * 60;
629					} else {
630						memcpy(&lease, temp, 4);
631						lease = ntohl(lease);
632					}
633
634					/* wklin added start, 08/10/2007 */
635					/* check before entering requesting state */
636					/* Foxconn modify start, Max Ding, 06/11/2010 */
637					/* Foxconn modified start pling 05/27/2010 */
638					u_int32_t addr_to_arp;
639					if (state == REQUESTING)
640						addr_to_arp = 0;
641					else
642						addr_to_arp = requested_ip;
643					/* if (arpping(packet.yiaddr, 0, */
644					if (arpping(packet.data.yiaddr, addr_to_arp,
645					/* Foxconn modified end pling 05/27/2010 */
646								client_config.arp, client_config.interface)==0) {
647						/* send_decline(packet.xid, server_addr, packet.yiaddr); *//* broadcast */
648						send_decline(packet.data.xid, server_addr, packet.data.yiaddr); /* broadcast */
649						/* return to init state */
650						state = INIT_SELECTING;
651						timeout = now;
652						requested_ip = 0;
653						packet_num = 0;
654						change_mode(LISTEN_RAW);
655						sleep(10); /* per the RFC, avoid excessive network traffic */
656						break;
657					}
658					/* Foxconn modify end, Max Ding, 06/11/2010 */
659					/* wklin added end, 08/10/2007 */
660					/* enter bound state */
661					t1 = lease / 2;
662
663					/* little fixed point for n * .875 */
664					t2 = (lease * 0x7) >> 3;
665					/* Foxconn modify start, Max Ding, 06/11/2010 */
666					/* temp_addr.s_addr = packet.yiaddr; */
667					temp_addr.s_addr = packet.data.yiaddr;
668					LOG(LOG_INFO, "Lease of %s obtained, lease time %ld",
669						inet_ntoa(temp_addr), lease);
670					start = now;
671					timeout = t1 + start;
672					/* requested_ip = packet.yiaddr; */
673					requested_ip = packet.data.yiaddr;
674					remove("/tmp/udhcpc.routes");/*foxconn added, water, 03/08/10, @option249*/
675					/* run_script(&packet, */
676					run_script(&packet.data,
677						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
678					/* Foxconn modify end, Max Ding, 06/11/2010 */
679
680					state = BOUND;
681					change_mode(LISTEN_NONE);
682					if (client_config.quit_after_lease)
683						exit_client(0);
684					if (!client_config.foreground)
685						background();
686
687				} else if (*message == DHCPNAK) {
688					/* return to init state */
689					LOG(LOG_INFO, "Received DHCP NAK");
690					/* run_script(&packet, "nak"); */
691					run_script(&packet.data, "nak");/* Foxconn modified by Max Ding, 06/11/2010 */
692					if (state != REQUESTING)
693						run_script(NULL, "deconfig");
694					state = INIT_SELECTING;
695					timeout = now;
696					requested_ip = 0;
697					packet_num = 0;
698					change_mode(LISTEN_RAW);
699					sleep(3); /* avoid excessive network traffic */
700				}
701				break;
702			/* case BOUND, RELEASED: - ignore all packets */
703			}
704		} else if (retval > 0 && FD_ISSET(signal_pipe[0], &rfds)) {
705			if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) {
706				DEBUG(LOG_ERR, "Could not read signal: %s",
707					strerror(errno));
708				continue; /* probably just EINTR */
709			}
710			switch (sig) {
711			case SIGUSR1:
712				perform_renew();
713				break;
714			case SIGUSR2:
715				perform_release();
716				break;
717			case SIGTERM:
718				LOG(LOG_INFO, "Received SIGTERM");
719				exit_client(0);
720			}
721		} else if (retval == -1 && errno == EINTR) {
722			/* a signal was caught */
723		} else {
724			/* An error occured */
725			DEBUG(LOG_ERR, "Error on select");
726		}
727
728	}
729	return 0;
730}
731
732