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(¶mPkg, 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, ¶mPkg); 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