Пример #1
0
int udhcpc_main(int argc, char *argv[])
{
	uint8_t *temp, *message;
	char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t;
	unsigned long t1 = 0, t2 = 0, xid = 0;
	unsigned long start = 0, lease = 0;
	long now;
	unsigned opt;
	int max_fd;
	int sig;
	int retval;
	int len;
	int no_clientid = 0;
	fd_set rfds;
	struct timeval tv;
	struct dhcpMessage packet;
	struct in_addr temp_addr;

	enum {
		OPT_c = 1 << 0,
		OPT_C = 1 << 1,
		OPT_V = 1 << 2,
		OPT_f = 1 << 3,
		OPT_b = 1 << 4,
		OPT_H = 1 << 5,
		OPT_h = 1 << 6,
		OPT_F = 1 << 7,
		OPT_i = 1 << 8,
		OPT_n = 1 << 9,
		OPT_p = 1 << 10,
		OPT_q = 1 << 11,
		OPT_R = 1 << 12,
		OPT_r = 1 << 13,
		OPT_s = 1 << 14,
		OPT_T = 1 << 15,
		OPT_t = 1 << 16,
		OPT_v = 1 << 17,
	};
#if ENABLE_GETOPT_LONG
	static const struct option arg_options[] = {
		{ "clientid",   required_argument,      0, 'c' },
		{ "clientid-none", no_argument,         0, 'C' },
		{ "vendorclass", required_argument,     0, 'V' },
		{ "foreground", no_argument,            0, 'f' },
		{ "background", no_argument,            0, 'b' },
		{ "hostname",   required_argument,      0, 'H' },
		{ "hostname",   required_argument,      0, 'h' },
		{ "fqdn",       required_argument,      0, 'F' },
		{ "interface",  required_argument,      0, 'i' },
		{ "now",        no_argument,            0, 'n' },
		{ "pidfile",    required_argument,      0, 'p' },
		{ "quit",       no_argument,            0, 'q' },
		{ "release",    no_argument,            0, 'R' },
		{ "request",    required_argument,      0, 'r' },
		{ "script",     required_argument,      0, 's' },
		{ "timeout",    required_argument,      0, 'T' },
		{ "version",    no_argument,            0, 'v' },
		{ "retries",    required_argument,      0, 't' },
		{ 0, 0, 0, 0 }
	};
#endif
	/* Default options. */
	client_config.interface = "eth0";
	client_config.script = DEFAULT_SCRIPT;
	client_config.retries = 3;
	client_config.timeout = 3;

	/* Parse command line */
	opt_complementary = "?:c--C:C--c" // mutually exclusive
	                    ":hH:Hh"; // -h and -H are the same
#if ENABLE_GETOPT_LONG
	applet_long_options = arg_options;
#endif
	opt = getopt32(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v",
		&str_c, &str_V, &str_h, &str_h, &str_F,
		&client_config.interface, &client_config.pidfile, &str_r,
		&client_config.script, &str_T, &str_t
		);

	if (opt & OPT_c)
		client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
	if (opt & OPT_C)
		no_clientid = 1;
	if (opt & OPT_V)
		client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
	if (opt & OPT_f)
		client_config.foreground = 1;
	if (opt & OPT_b)
		client_config.background_if_no_lease = 1;
	if (opt & OPT_h)
		client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
	if (opt & OPT_F) {
		client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
		/* Flags: 0000NEOS
		S: 1 => Client requests Server to update A RR in DNS as well as PTR
		O: 1 => Server indicates to client that DNS has been updated regardless
		E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
		N: 1 => Client requests Server to not update DNS
		*/
		client_config.fqdn[OPT_DATA + 0] = 0x1;
		/* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */
		/* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */
	}
	// if (opt & OPT_i) client_config.interface = ...
	if (opt & OPT_n)
		client_config.abort_if_no_lease = 1;
	// if (opt & OPT_p) client_config.pidfile = ...
	if (opt & OPT_q)
		client_config.quit_after_lease = 1;
	if (opt & OPT_R)
		client_config.release_on_quit = 1;
	if (opt & OPT_r)
		requested_ip = inet_addr(str_r);
	// if (opt & OPT_s) client_config.script = ...
	if (opt & OPT_T)
		client_config.timeout = xatoi_u(str_T);
	if (opt & OPT_t)
		client_config.retries = xatoi_u(str_t);
	if (opt & OPT_v) {
		printf("version %s\n\n", BB_VER);
		return 0;
	}

	/* Start the log, sanitize fd's, and write a pid file */
	udhcp_start_log_and_pid(client_config.pidfile);

	if (read_interface(client_config.interface, &client_config.ifindex,
			   NULL, client_config.arp) < 0)
		return 1;

	/* if not set, and not suppressed, setup the default client ID */
	if (!client_config.clientid && !no_clientid) {
		client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
		client_config.clientid[OPT_DATA] = 1;
		memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6);
	}

	if (!client_config.vendorclass)
		client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);

	/* setup the signal pipe */
	udhcp_sp_setup();

	state = INIT_SELECTING;
	udhcp_run_script(NULL, "deconfig");
	change_mode(LISTEN_RAW);

	for (;;) {
		tv.tv_sec = timeout - uptime();
		tv.tv_usec = 0;

		/* When running on a bridge, the ifindex may have changed (e.g. if
		 * member interfaces were added/removed or if the status of the
		 * bridge changed).
		 * Workaround: refresh it here before processing the next packet */
		read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.arp);

		if (listen_mode != LISTEN_NONE && fd < 0) {
			if (listen_mode == LISTEN_KERNEL)
				fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
			else
				fd = raw_socket(client_config.ifindex);
		}
		max_fd = udhcp_sp_fd_set(&rfds, fd);

		if (tv.tv_sec > 0) {
			DEBUG("Waiting on select...");
			retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
		} else retval = 0; /* If we already timed out, fall through */

		now = uptime();
		if (retval == 0) {
			/* timeout dropped to zero */
			switch (state) {
			case INIT_SELECTING:
				if (!client_config.retries || (packet_num < client_config.retries)) {
					if (packet_num == 0)
						xid = random_xid();

					/* send discover packet */
					send_discover(xid, requested_ip); /* broadcast */

					timeout = now + client_config.timeout;
					packet_num++;
				} else {
					udhcp_run_script(NULL, "leasefail");
					if (client_config.background_if_no_lease) {
						bb_info_msg("No lease, forking to background");
						client_background();
					} else if (client_config.abort_if_no_lease) {
						bb_info_msg("No lease, failing");
						return 1;
					}
					/* wait to try again */
					packet_num = 0;
					timeout = now + 60;
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
				if (!client_config.retries || (packet_num < client_config.retries)) {
					/* send request packet */
					if (state == RENEW_REQUESTED)
						send_renew(xid, server_addr, requested_ip); /* unicast */
					else send_selecting(xid, server_addr, requested_ip); /* broadcast */

					timeout = now + ((packet_num == 2) ? 10 : 2);
					packet_num++;
				} else {
					/* timed out, go back to init state */
					if (state == RENEW_REQUESTED) udhcp_run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = now;
					packet_num = 0;
					change_mode(LISTEN_RAW);
				}
				break;
			case BOUND:
				/* Lease is starting to run out, time to enter renewing state */
				state = RENEWING;
				change_mode(LISTEN_KERNEL);
				DEBUG("Entering renew state");
				/* fall right through */
			case RENEWING:
				/* Either set a new T1, or enter REBINDING state */
				if ((t2 - t1) <= (lease / 14400 + 1)) {
					/* timed out, enter rebinding state */
					state = REBINDING;
					timeout = now + (t2 - t1);
					DEBUG("Entering rebinding state");
				} else {
					/* send a request packet */
					send_renew(xid, server_addr, requested_ip); /* unicast */

					t1 = (t2 - t1) / 2 + t1;
					timeout = t1 + start;
				}
				break;
			case REBINDING:
				/* Either set a new T2, or enter INIT state */
				if ((lease - t2) <= (lease / 14400 + 1)) {
					/* timed out, enter init state */
					state = INIT_SELECTING;
					bb_info_msg("Lease lost, entering init state");
					udhcp_run_script(NULL, "deconfig");
					timeout = now;
					packet_num = 0;
					change_mode(LISTEN_RAW);
				} else {
					/* send a request packet */
					send_renew(xid, 0, requested_ip); /* broadcast */

					t2 = (lease - t2) / 2 + t2;
					timeout = t2 + start;
				}
				break;
			case RELEASED:
				/* yah, I know, *you* say it would never happen */
				timeout = 0x7fffffff;
				break;
			}
		} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
			/* a packet is ready, read it */

			if (listen_mode == LISTEN_KERNEL)
				len = udhcp_get_packet(&packet, fd);
			else len = get_raw_packet(&packet, fd);

			if (len == -1 && errno != EINTR) {
				DEBUG("error on read, %s, reopening socket", strerror(errno));
				change_mode(listen_mode); /* just close and reopen */
			}
			if (len < 0) continue;

			if (packet.xid != xid) {
				DEBUG("Ignoring XID %lx (our xid is %lx)",
					(unsigned long) packet.xid, xid);
				continue;
			}

			/* Ignore packets that aren't for us */
			if (memcmp(packet.chaddr, client_config.arp, 6)) {
				DEBUG("Packet does not have our chaddr - ignoring");
				continue;
			}

			if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
				bb_error_msg("cannot get option from packet - ignoring");
				continue;
			}

			switch (state) {
			case INIT_SELECTING:
				/* Must be a DHCPOFFER to one of our xid's */
				if (*message == DHCPOFFER) {
					temp = get_option(&packet, DHCP_SERVER_ID);
					if (temp) {
						/* can be misaligned, thus memcpy */
						memcpy(&server_addr, temp, 4);
						xid = packet.xid;
						requested_ip = packet.yiaddr;

						/* enter requesting state */
						state = REQUESTING;
						timeout = now;
						packet_num = 0;
					} else {
						bb_error_msg("no server ID in message");
					}
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
			case RENEWING:
			case REBINDING:
				if (*message == DHCPACK) {
					temp = get_option(&packet, DHCP_LEASE_TIME);
					if (!temp) {
						bb_error_msg("no lease time with ACK, using 1 hour lease");
						lease = 60 * 60;
					} else {
						/* can be misaligned, thus memcpy */
                        unsigned int lease_tmp = 0;
                        memcpy(&lease_tmp, temp, 4);
						lease = ntohl(lease_tmp);
					}
					if (!arpping(packet.yiaddr,
							(uint32_t) 0,
							client_config.arp,
							client_config.interface)
					) {
						bb_info_msg("Offered address is in use "
							"(got ARP reply), declining");
						send_decline(xid, server_addr, packet.yiaddr);

						if (state != REQUESTING)
							udhcp_run_script(NULL, "deconfig");
						change_mode(LISTEN_RAW);
						state = INIT_SELECTING;
						requested_ip = 0;
						timeout = now + 20;
						packet_num = 0;
						continue; /* back to main loop */
					}
					/* enter bound state */
					t1 = lease / 2;

					/* little fixed point for n * .875 */
					t2 = (lease * 0x7) >> 3;
					temp_addr.s_addr = packet.yiaddr;
					bb_info_msg("Lease of %s obtained, lease time %ld",
						inet_ntoa(temp_addr), lease);
					start = now;
					timeout = t1 + start;
					requested_ip = packet.yiaddr;
					udhcp_run_script(&packet,
						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));

					state = BOUND;
					change_mode(LISTEN_NONE);
					if (client_config.quit_after_lease) {
						if (client_config.release_on_quit)
							perform_release();
						return 0;
					}
					if (!client_config.foreground)
						client_background();

				} else if (*message == DHCPNAK) {
					/* return to init state */
					bb_info_msg("Received DHCP NAK");
					udhcp_run_script(&packet, "nak");
					if (state != REQUESTING)
						udhcp_run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = now;
					requested_ip = 0;
					packet_num = 0;
					change_mode(LISTEN_RAW);
					sleep(3); /* avoid excessive network traffic */
				}
				break;
			/* case BOUND, RELEASED: - ignore all packets */
			}
		} else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) {
Пример #2
0
int main(int argc, char *argv[])
#endif
{
	char *temp, *message;
	unsigned long t1 = 0, t2 = 0, xid = 0;
	unsigned long start = 0, lease;
	fd_set rfds;
	int fd, retval;
	struct timeval tv;
	int c, len;
	struct ifreq ifr;
	struct dhcpMessage packet;
	struct in_addr temp_addr;
	int pid_fd;

	static struct option options[] = {
		{"clientid",	required_argument,	0, 'c'},
		{"foreground",	no_argument,		0, 'f'},
		{"hostname",	required_argument,	0, 'H'},
		{"help",	no_argument,		0, 'h'},
		{"interface",	required_argument,	0, 'i'},
		{"now", 	no_argument,		0, 'n'},
		{"pidfile",	required_argument,	0, 'p'},
		{"quit",	no_argument,		0, 'q'},
		{"request",	required_argument,	0, 'r'},
		{"script",	required_argument,	0, 's'},
		{"version",	no_argument,		0, 'v'},
		{"6rd",	no_argument,		0, '6'},
		{0, 0, 0, 0}
	};

	/* get options */
	while (1) {
		int option_index = 0;
// brcm
		c = getopt_long(argc, argv, "c:fH:hi:np:qr:s:d:v:6I:D:O:S:P:", options, &option_index);
		if (c == -1) break;
		
		switch (c) {
		case 'c':
			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
			if (client_config.clientid) free(client_config.clientid);
			client_config.clientid = malloc(len + 2);
			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
			client_config.clientid[OPT_LEN] = len;
			strncpy(client_config.clientid + 2, optarg, len);
			break;
		case 'f':
			client_config.foreground = 1;
			break;
		case 'H':
			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
			if (client_config.hostname) free(client_config.hostname);
			client_config.hostname = malloc(len + 2);
			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
			client_config.hostname[OPT_LEN] = len;
			strncpy(client_config.hostname + 2, optarg, len);
			break;
		case 'h':
			print_usage();
			return 0;
		case 'i':
			client_config.interface =  optarg;
// brcm
			strcpy(session_path, optarg);
			break;
		case 'n':
			client_config.abort_if_no_lease = 1;
			break;
		case 'p':
			client_config.pidfile = optarg;
			break;
		case 'q':
			client_config.quit_after_lease = 1;
			break;
		case 'r':
			requested_ip = inet_addr(optarg);
			break;
// brcm
		case 'd':
			strcpy(vendor_class_id, optarg);
			en_vendor_class_id=1;
			break;
		case '6':
			ipv6rd_opt = 1;
			break;
		case 's':
			client_config.script = optarg;
			break;
		case 'v':
			printf("udhcpcd, version %s\n\n", VERSION);
			break;
		case 'I':
			strcpy(iaid, optarg);
            en_client_id = 1;
			break;
		case 'D':
			strcpy(duid, optarg);
            en_client_id = 1;
			break;
		case 'O':
			strcpy(oui_125, optarg);
			en_125 = 1;
			break;
		case 'S':
			strcpy(sn_125, optarg);
			en_125 = 1;
			break;
		case 'P':
			strcpy(prod_125, optarg);
			en_125 = 1;
			break;
		}
	}

	// brcm
        if (strlen(session_path) > 0) {
	    sprintf(status_path, "%s/%s/%s", _PATH_WAN_DIR, session_path, _PATH_MSG);
	    sprintf(pid_path, "%s/%s/%s", _PATH_WAN_DIR, session_path, _PATH_PID);
	}

	OPEN_LOG("udhcpc");
#ifdef VERBOSE
   cmsLog_setLevel(LOG_LEVEL_DEBUG);
#else
   cmsLog_setLevel(DEFAULT_LOG_LEVEL);
#endif

	LOG(LOG_INFO, "udhcp client (v%s) started", VERSION);

   cmsMsg_init(EID_DHCPC, &msgHandle);

	pid_fd = pidfile_acquire(client_config.pidfile);
	pidfile_write_release(pid_fd);

	if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {
		strcpy(ifr.ifr_name, client_config.interface);
		if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {
			DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex);
			client_config.ifindex = ifr.ifr_ifindex;
		} else {
			LOG(LOG_ERR, "SIOCGIFINDEX failed! %s", strerror(errno));
			exit_client(1);
		}
		if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
			memcpy(client_config.arp, ifr.ifr_hwaddr.sa_data, 6);
			DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x",
				client_config.arp[0], client_config.arp[1], client_config.arp[2], 
				client_config.arp[3], client_config.arp[4], client_config.arp[5]);
		} else {
			LOG(LOG_ERR, "SIOCGIFHWADDR failed! %s", strerror(errno));
			exit_client(1);
		}
	} else {
		LOG(LOG_ERR, "socket failed! %s", strerror(errno));
		exit_client(1);
	}
	close(fd);
	fd = -1;

	/* setup signal handlers */
	signal(SIGUSR1, renew_requested);
	signal(SIGUSR2, release_requested);
	signal(SIGTERM, terminate);
	
	state = INIT_SELECTING;
	// brcm
	// run_script(NULL, "deconfig");

	// brcm
	setStatus(0);

	for (;;) {

		// brcm
		if ((old_mode != listen_mode) || (fd == -1)) {
		    old_mode = listen_mode;
		
        /*
        * After dhcpc runs as daemon(backgroud)mode, fd 0-2 be closed.  
        *  The sock fd may be 0.
        */
		    if (fd >= 0) {
			    close(fd);
			    fd = -1;
		    }
		
		    if (listen_mode == LISTEN_RAW) {
			    if ((fd = raw_socket(client_config.ifindex)) < 0) {
				    LOG(LOG_ERR, "couldn't create raw socket -- au revoir");
				    exit_client(0);
			    }
		    }
		    else if (listen_mode == LISTEN_KERNEL) {
			    if ((fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface)) < 0) {
				    LOG(LOG_ERR, "couldn't create server socket -- au revoir");
				    exit_client(0);
			    }			
		    } else 
			fd = -1;
		}

		tv.tv_sec = timeout - time(0);
		tv.tv_usec = 0;
		FD_ZERO(&rfds);
		if (listen_mode) FD_SET(fd, &rfds);

		if (tv.tv_sec > 0) {
			retval = select(fd + 1, &rfds, NULL, NULL, &tv);
		} else retval = 0; /* If we already timed out, fall through */

		if (retval == 0) {
			/* timeout dropped to zero */
			switch (state) {
			case INIT_SELECTING:
				// brcm
				setStatus(0);
				if (packet_num < 3) {
					if (packet_num == 0)
						xid = random_xid();

					/* send discover packet */
					send_discover(xid, requested_ip); /* broadcast */
					
					timeout = time(0) + ((packet_num == 2) ? REQ_TIMEOUT : 2);
					packet_num++;
				} else {
					if (client_config.abort_if_no_lease) {
						LOG(LOG_INFO,
						    "No lease, failing.");
						exit_client(1);
				  	}
					/* wait to try again */
					packet_num = 0;
					timeout = time(0) + INIT_TIMEOUT;
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
				if (packet_num < 3) {
					/* send request packet */
					if (state == RENEW_REQUESTED)
						send_renew(xid, server_addr, requested_ip); /* unicast */
					else send_selecting(xid, server_addr, requested_ip); /* broadcast */
					
					timeout = time(0) + ((packet_num == 2) ? REQ_TIMEOUT : 2);
					packet_num++;
				} else {
					/* timed out, go back to init state */
					state = INIT_SELECTING;
					timeout = time(0);
					packet_num = 0;
					listen_mode = LISTEN_RAW;
					
				}
				break;
			case BOUND:
				/* Lease is starting to run out, time to enter renewing state */
				state = RENEWING;
				listen_mode = LISTEN_KERNEL;
				DEBUG(LOG_INFO, "Entering renew state");
				/* fall right through */
			case RENEWING:
				/* Either set a new T1, or enter REBINDING state */
				if ((t2 - t1) <= (lease / 14400 + 1)) {
					/* timed out, enter rebinding state */
					state = REBINDING;
					timeout = time(0) + (t2 - t1);
					DEBUG(LOG_INFO, "Entering rebinding state");
				} else {
					/* send a request packet */
					send_renew(xid, server_addr, requested_ip); /* unicast */
					
					t1 = (t2 - t1) / 2 + t1;
					timeout = t1 + start;
				}
				break;
			case REBINDING:
				/* Either set a new T2, or enter INIT state */
				if ((lease - t2) <= (lease / 14400 + 1)) {
					/* timed out, enter init state */
					state = INIT_SELECTING;
					LOG(LOG_INFO, "Lease lost, entering init state");
					run_script(NULL, "deconfig");
					timeout = time(0);
					packet_num = 0;
					listen_mode = LISTEN_RAW;
				} else {
					/* send a request packet */
					send_renew(xid, 0, requested_ip); /* broadcast */

					t2 = (lease - t2) / 2 + t2;
					timeout = t2 + start;
				}
				break;
			case RELEASED:
				/* yah, I know, *you* say it would never happen */
				timeout = 0xffffffff;
				break;
			}
		} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
			/* a packet is ready, read it */

			if (listen_mode == LISTEN_KERNEL) {
				if (get_packet(&packet, fd) < 0) continue;
			} else {
				if (get_raw_packet(&packet, fd) < 0) continue;
			} 

			if (packet.xid != xid) {
				DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
					(unsigned long) packet.xid, xid);
				continue;
			}
			
			if ((message = (char *)get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
				DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
				continue;
			}

			switch (state) {
			case INIT_SELECTING:
				/* Must be a DHCPOFFER to one of our xid's */
				if (*message == DHCPOFFER) {
					if ((temp = (char *)get_option(&packet, DHCP_SERVER_ID))) {
						memcpy(&server_addr, temp, 4);
						xid = packet.xid;
						requested_ip = packet.yiaddr;
						
						/* enter requesting state */
						state = REQUESTING;
						timeout = time(0);
						packet_num = 0;
					} else {
						DEBUG(LOG_ERR, "No server ID in message");
					}
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
			case RENEWING:
			case REBINDING:
				if (*message == DHCPACK) {
					if (!(temp = (char *)get_option(&packet, DHCP_LEASE_TIME))) {
						LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
						lease = 60*60;
					} else {
						memcpy(&lease, temp, 4);
						lease = ntohl(lease);
					}
						
					/* enter bound state */
					t1 = lease / 2;
					
					/* little fixed point for n * .875 */
					t2 = (lease * 0x7) >> 3;
					temp_addr.s_addr = packet.yiaddr;
					LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", 
						inet_ntoa(temp_addr), lease);
					start = time(0);
					timeout = t1 + start;
					requested_ip = packet.yiaddr;
					run_script(&packet,
						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));

					state = BOUND;
					listen_mode = LISTEN_NONE;
					
					// brcm
                    close(fd);
                    fd = -1;
					setStatus(1);
					background();
					
				} else if (*message == DHCPNAK) {
					/* return to init state */
					LOG(LOG_INFO, "Received DHCP NAK");
					if (state != REQUESTING)
						run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = time(0);
					requested_ip = 0;
					packet_num = 0;
					listen_mode = LISTEN_RAW;

					// brcm
					setStatus(0);
				}
				break;
			case BOUND:
			case RELEASED:
				/* ignore all packets */
				break;
			}					
		} else if (retval == -1 && errno == EINTR) {
Пример #3
0
int udhcpc_main(int argc, char *argv[])
{
	unsigned char *temp, *message;
	unsigned long t1 = 0, t2 = 0, xid = 0;
	unsigned long start = 0, lease;
	fd_set rfds;
	int retval;
	struct timeval tv;
	int c, len;
	struct dhcpMessage packet;
	struct in_addr temp_addr;
	time_t now;
	int max_fd;
	int sig;
	
#if 1
	FILE *f;	
	f=fopen("/var/run/udhcpc.pid","w");
	fprintf(f,"%d",getpid());
	fclose(f);
#endif	
	

	static const struct option arg_options[] = {
		{"clientid",	required_argument,	0, 'c'},
		{"foreground",	no_argument,		0, 'f'},
		{"background",	no_argument,		0, 'b'},
		{"hostname",	required_argument,	0, 'H'},
		{"hostname",    required_argument,      0, 'h'},
		{"interface",	required_argument,	0, 'i'},
		{"now", 	no_argument,		0, 'n'},
		{"pidfile",	required_argument,	0, 'p'},
		{"quit",	no_argument,		0, 'q'},
		{"request",	required_argument,	0, 'r'},
		{"script",	required_argument,	0, 's'},
		{"version",	no_argument,		0, 'v'},
		{0, 0, 0, 0}
	};

	/* get options */
	while (1) {
		int option_index = 0;
		c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:v", arg_options, &option_index);
		if (c == -1) break;
		
		switch (c) {
		case 'c':
			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
			if (client_config.clientid) free(client_config.clientid);
			client_config.clientid = xmalloc(len + 2);
			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
			client_config.clientid[OPT_LEN] = len;
			client_config.clientid[OPT_DATA] = '\0';
			strncpy(client_config.clientid + OPT_DATA, optarg, len);
			break;
		case 'f':
			client_config.foreground = 1;
			break;
		case 'b':
			client_config.background_if_no_lease = 1;
			break;
		case 'h':
		case 'H':
			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
			if (client_config.hostname) free(client_config.hostname);
			client_config.hostname = xmalloc(len + 2);
			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
			client_config.hostname[OPT_LEN] = len;
			strncpy(client_config.hostname + 2, optarg, len);
			break;
		case 'i':
			client_config.interface =  optarg;
			break;
		case 'n':
			client_config.abort_if_no_lease = 1;
			break;
		case 'p':
			client_config.pidfile = optarg;
			break;
		case 'q':
			client_config.quit_after_lease = 1;
			break;
		case 'r':
			requested_ip = inet_addr(optarg);
			break;
		case 's':
			client_config.script = optarg;
			break;
		case 'v':
			bb_error_msg("version %s\n", VERSION);
			return(0);
			break;
		default:
			bb_show_usage();
		}
	}


	start_log("client");
	if (read_interface(client_config.interface, &client_config.ifindex, 
			   NULL, client_config.arp) < 0)
		return(1);
		
	if (!client_config.clientid) {
		client_config.clientid = xmalloc(6 + 3);
		client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
		client_config.clientid[OPT_LEN] = 7;
		client_config.clientid[OPT_DATA] = 1;
		memcpy(client_config.clientid + 3, client_config.arp, 6);
	}

	background(client_config.pidfile);
	/* setup signal handlers */
	udhcp_set_signal_pipe(SIGUSR2);
	
	state = INIT_SELECTING;
	run_script(NULL, "deconfig");
	change_mode(LISTEN_RAW);

	for (;;) {

		tv.tv_sec = timeout - time(0);
		tv.tv_usec = 0;
		FD_ZERO(&rfds);

		if (listen_mode != LISTEN_NONE && fd < 0) {
			if (listen_mode == LISTEN_KERNEL)
				fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
			else
				fd = raw_socket(client_config.ifindex);
			if (fd < 0) {
				LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m");
				return(0);
			}
		}
		if (fd >= 0) FD_SET(fd, &rfds);
		FD_SET(udhcp_signal_pipe[0], &rfds);

		if (tv.tv_sec > 0) {
			DEBUG(LOG_INFO, "Waiting on select...\n");
			max_fd = udhcp_signal_pipe[0] > fd ? udhcp_signal_pipe[0] : fd;
			retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
		} else retval = 0; /* If we already timed out, fall through */

		now = time(0);
		if (retval == 0) {
			/* timeout dropped to zero */
			switch (state) {
			case INIT_SELECTING:
				if (packet_num < 3) {
					if (packet_num == 0)
						xid = random_xid();

					/* send discover packet */
					send_discover(xid, requested_ip); /* broadcast */
					
					timeout = now + ((packet_num == 2) ? 4 : 2);
					packet_num++;
				} else {
					if (client_config.background_if_no_lease) {
						LOG(LOG_INFO, "No lease, forking to background.");
						client_background();
					} else if (client_config.abort_if_no_lease) {
						LOG(LOG_INFO, "No lease, failing.");
						return(1);
				  	}
					/* wait to try again */
					packet_num = 0;
					timeout = now + 60;
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
				if (packet_num < 3) {
					/* send request packet */
					if (state == RENEW_REQUESTED)
						send_renew(xid, server_addr, requested_ip); /* unicast */
					else send_selecting(xid, server_addr, requested_ip); /* broadcast */
					
					timeout = now + ((packet_num == 2) ? 10 : 2);
					packet_num++;
				} else {
					/* timed out, go back to init state */
					if (state == RENEW_REQUESTED) run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = now;
					packet_num = 0;
					change_mode(LISTEN_RAW);
				}
				break;
			case BOUND:
				/* Lease is starting to run out, time to enter renewing state */
				state = RENEWING;
				change_mode(LISTEN_KERNEL);
				DEBUG(LOG_INFO, "Entering renew state");
				/* fall right through */
			case RENEWING:
				/* Either set a new T1, or enter REBINDING state */
				if ((t2 - t1) <= (lease / 14400 + 1)) {
					/* timed out, enter rebinding state */
					state = REBINDING;
					timeout = now + (t2 - t1);
					DEBUG(LOG_INFO, "Entering rebinding state");
				} else {
					/* send a request packet */
					send_renew(xid, server_addr, requested_ip); /* unicast */
					
					t1 = (t2 - t1) / 2 + t1;
					timeout = t1 + start;
				}
				break;
			case REBINDING:
				/* Either set a new T2, or enter INIT state */
				if ((lease - t2) <= (lease / 14400 + 1)) {
					/* timed out, enter init state */
					state = INIT_SELECTING;
					LOG(LOG_INFO, "Lease lost, entering init state");
					run_script(NULL, "deconfig");
					timeout = now;
					packet_num = 0;
					change_mode(LISTEN_RAW);
				} else {
					/* send a request packet */
					send_renew(xid, 0, requested_ip); /* broadcast */

					t2 = (lease - t2) / 2 + t2;
					timeout = t2 + start;
				}
				break;
			case RELEASED:
				/* yah, I know, *you* say it would never happen */
				timeout = 0x7fffffff;
				break;
			}
		} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
			/* a packet is ready, read it */
			
			if (listen_mode == LISTEN_KERNEL)
				len = get_packet(&packet, fd);
			else len = get_raw_packet(&packet, fd);
			
			if (len == -1 && errno != EINTR) {
				DEBUG(LOG_INFO, "error on read, %m, reopening socket");
				change_mode(listen_mode); /* just close and reopen */
			}
			if (len < 0) continue;
			
			if (packet.xid != xid) {
				DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
					(unsigned long) packet.xid, xid);
				continue;
			}
			
			if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
				DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
				continue;
			}
			
			switch (state) {
			case INIT_SELECTING:
				/* Must be a DHCPOFFER to one of our xid's */
				if (*message == DHCPOFFER) {
					if ((temp = get_option(&packet, DHCP_SERVER_ID))) {
						memcpy(&server_addr, temp, 4);
						xid = packet.xid;
						requested_ip = packet.yiaddr;
						
						/* enter requesting state */
						state = REQUESTING;
						timeout = now;
						packet_num = 0;
					} else {
						DEBUG(LOG_ERR, "No server ID in message");
					}
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
			case RENEWING:
			case REBINDING:
				if (*message == DHCPACK) {
					if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) {
						LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
						lease = 60 * 60;
					} else {
						memcpy(&lease, temp, 4);
						lease = ntohl(lease);
					}
						
					/* enter bound state */
					t1 = lease / 2;
					
					/* little fixed point for n * .875 */
					t2 = (lease * 0x7) >> 3;
					temp_addr.s_addr = packet.yiaddr;
					LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", 
						inet_ntoa(temp_addr), lease);
					start = now;
					timeout = t1 + start;
					requested_ip = packet.yiaddr;
					run_script(&packet,
						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));

					state = BOUND;
					change_mode(LISTEN_NONE);
					if (client_config.quit_after_lease) 
						return(0);
					if (!client_config.foreground)
						client_background();

				} else if (*message == DHCPNAK) {
					/* return to init state */
					LOG(LOG_INFO, "Received DHCP NAK");
					run_script(&packet, "nak");
					if (state != REQUESTING)
						run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = now;
					requested_ip = 0;
					packet_num = 0;
					change_mode(LISTEN_RAW);
					sleep(3); /* avoid excessive network traffic */
				}
				break;
			/* case BOUND, RELEASED: - ignore all packets */
			}	
		} else if (retval > 0 && FD_ISSET(udhcp_signal_pipe[0], &rfds)) {
Пример #4
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_dhcp(void))
{
  PT_BEGIN(&s.pt);
  
  /* try_again:*/
  s.state = STATE_SENDING;
  s.ticks = CLOCK_SECOND;

  do {
    send_discover();
    timer_set(&s.timer, s.ticks);
    uip_flags = 0;
    PT_WAIT_UNTIL(&s.pt, uip_newdata() || timer_expired(&s.timer));

    if(uip_newdata() && parse_msg() == DHCPOFFER) {
      s.state = STATE_OFFER_RECEIVED;
      break;
    }

    if(s.ticks < CLOCK_SECOND * 60) {
      s.ticks *= 2;
    }
  } while(s.state != STATE_OFFER_RECEIVED);
  
  s.ticks = CLOCK_SECOND;

  do {
    send_request();
    timer_set(&s.timer, s.ticks);
    uip_flags = 0;
    PT_WAIT_UNTIL(&s.pt, uip_newdata() || timer_expired(&s.timer));

    if(uip_newdata() && parse_msg() == DHCPACK) {
      s.state = STATE_CONFIG_RECEIVED;
      break;
    }

    if(s.ticks <= CLOCK_SECOND * 10) {
      s.ticks += CLOCK_SECOND;
    } else {
      PT_RESTART(&s.pt);
    }
  } while(s.state != STATE_CONFIG_RECEIVED);
  
#if 0
  printf("Got IP address %d.%d.%d.%d\n",
	 uip_ipaddr1(s.ipaddr), uip_ipaddr2(s.ipaddr),
	 uip_ipaddr3(s.ipaddr), uip_ipaddr4(s.ipaddr));
  printf("Got netmask %d.%d.%d.%d\n",
	 uip_ipaddr1(s.netmask), uip_ipaddr2(s.netmask),
	 uip_ipaddr3(s.netmask), uip_ipaddr4(s.netmask));
  printf("Got DNS server %d.%d.%d.%d\n",
	 uip_ipaddr1(s.dnsaddr), uip_ipaddr2(s.dnsaddr),
	 uip_ipaddr3(s.dnsaddr), uip_ipaddr4(s.dnsaddr));
  printf("Got default router %d.%d.%d.%d\n",
	 uip_ipaddr1(s.default_router), uip_ipaddr2(s.default_router),
	 uip_ipaddr3(s.default_router), uip_ipaddr4(s.default_router));
  printf("Lease expires in %ld seconds\n",
	 ntohs(s.lease_time[0])*65536ul + ntohs(s.lease_time[1]));
#endif

  dhcpc_configured(&s);
  
  /*  timer_stop(&s.timer);*/

  /*
   * PT_END restarts the thread so we do this instead. Eventually we
   * should reacquire expired leases here.
   */
  while(1) {
    PT_YIELD(&s.pt);
  }

  PT_END(&s.pt);
}
Пример #5
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_dhcp(process_event_t ev, void *data))
{
    clock_time_t ticks;

    PT_BEGIN(&s.pt);

init:
    xid++;
    s.state = STATE_SENDING;
    s.ticks = CLOCK_SECOND;
    while (1)
    {
        while(ev != tcpip_event)
        {
            tcpip_poll_udp(s.conn);
            PT_YIELD(&s.pt);
        }
        send_discover();
        etimer_set(&s.etimer, s.ticks);
        do
        {
            PT_YIELD(&s.pt);
            if(ev == tcpip_event && uip_newdata() && msg_for_me() == DHCPOFFER)
            {
                parse_msg();
                s.state = STATE_OFFER_RECEIVED;
                goto selecting;
            }
        }
        while (!etimer_expired(&s.etimer));

        if(s.ticks < CLOCK_SECOND * 60)
        {
            s.ticks *= 2;
        }
    }

selecting:
    xid++;
    s.ticks = CLOCK_SECOND;
    do
    {
        while(ev != tcpip_event)
        {
            tcpip_poll_udp(s.conn);
            PT_YIELD(&s.pt);
        }
        send_request();
        etimer_set(&s.etimer, s.ticks);
        do
        {
            PT_YIELD(&s.pt);
            if(ev == tcpip_event && uip_newdata() && msg_for_me() == DHCPACK)
            {
                parse_msg();
                s.state = STATE_CONFIG_RECEIVED;
                goto bound;
            }
        }
        while (!etimer_expired(&s.etimer));

        if(s.ticks <= CLOCK_SECOND * 10)
        {
            s.ticks += CLOCK_SECOND;
        }
        else
        {
            goto init;
        }
    }
    while(s.state != STATE_CONFIG_RECEIVED);

bound:
#if 0
    printf("Got IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.ipaddr));
    printf("Got netmask %d.%d.%d.%d\n",	 uip_ipaddr_to_quad(&s.netmask));
    printf("Got DNS server %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.dnsaddr));
    printf("Got default router %d.%d.%d.%d\n",
           uip_ipaddr_to_quad(&s.default_router));
    printf("Lease expires in %ld seconds\n",
           uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]));
#endif

    dhcpc_configured(&s);

#define MAX_TICKS (~((clock_time_t)0) / 2)
#define MAX_TICKS32 (~((uint32_t)0))
#define IMIN(a, b) ((a) < (b) ? (a) : (b))

    if((uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]))*CLOCK_SECOND/2
            <= MAX_TICKS32)
    {
        s.ticks = (uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])
                  )*CLOCK_SECOND/2;
    }
    else
    {
        s.ticks = MAX_TICKS32;
    }

    while(s.ticks > 0)
    {
        ticks = IMIN(s.ticks, MAX_TICKS);
        s.ticks -= ticks;
        etimer_set(&s.etimer, ticks);
        PT_YIELD_UNTIL(&s.pt, etimer_expired(&s.etimer));
    }

    if((uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]))*CLOCK_SECOND/2
            <= MAX_TICKS32)
    {
        s.ticks = (uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])
                  )*CLOCK_SECOND/2;
    }
    else
    {
        s.ticks = MAX_TICKS32;
    }

    /* renewing: */
    xid++;
    do
    {
        while(ev != tcpip_event)
        {
            tcpip_poll_udp(s.conn);
            PT_YIELD(&s.pt);
        }
        send_request();
        ticks = IMIN(s.ticks / 2, MAX_TICKS);
        s.ticks -= ticks;
        etimer_set(&s.etimer, ticks);
        do
        {
            PT_YIELD(&s.pt);
            if(ev == tcpip_event && uip_newdata() && msg_for_me() == DHCPACK)
            {
                parse_msg();
                goto bound;
            }
        }
        while(!etimer_expired(&s.etimer));
    }
    while(s.ticks >= CLOCK_SECOND*3);

    /* rebinding: */

    /* lease_expired: */
    dhcpc_unconfigured(&s);
    goto init;

    PT_END(&s.pt);
}
Пример #6
0
static PT_THREAD (handle_dhcp (void))
{
  PT_BEGIN (&dhcpcState->pt);

  dhcpcState->state = STATE_SENDING;
  dhcpcState->ticks = CLOCK_SECOND;

  do 
  {
    send_discover ();
    timer_set (&dhcpcState->timer, dhcpcState->ticks);

    PT_WAIT_UNTIL (&dhcpcState->pt, uip_newdata () || timer_expired (&dhcpcState->timer));

    if (uip_newdata () && (parse_msg () == DHCPOFFER)) 
    {
      uip_flags &= ~UIP_NEWDATA;
      dhcpcState->state = STATE_OFFER_RECEIVED;
      break;
    }

    uip_flags &= ~UIP_NEWDATA;

    if (dhcpcState->ticks < CLOCK_SECOND * 60)
      dhcpcState->ticks *= 2;
    else 
    {
      dhcpcState->ipaddr [0] = dhcpcState->ipaddr [1] = 0;
      goto dhcpcf;
    }
  } 
  while (dhcpcState->state != STATE_OFFER_RECEIVED);

  dhcpcState->ticks = CLOCK_SECOND;

  do 
  {
    send_request ();
    timer_set (&dhcpcState->timer, dhcpcState->ticks);

    PT_WAIT_UNTIL (&dhcpcState->pt, uip_newdata () || timer_expired (&dhcpcState->timer));

    if (uip_newdata () && (parse_msg () == DHCPACK))
    {
      uip_flags &= ~UIP_NEWDATA;
      dhcpcState->state = STATE_CONFIG_RECEIVED;
      break;
    }

    uip_flags &= ~UIP_NEWDATA;

    if (dhcpcState->ticks <= CLOCK_SECOND * 10)
      dhcpcState->ticks += CLOCK_SECOND;
    else
      PT_RESTART (&dhcpcState->pt);
  } 
  while (dhcpcState->state != STATE_CONFIG_RECEIVED);

dhcpcf:
  dhcpc_configured (dhcpcState);

  /*  timer_stop (&dhcpcState->timer);*/

  /*
   * PT_END restarts the thread so we do this instead. Eventually we
   * should reacquire expired leases here.
   */
  while (1)
    PT_YIELD (&dhcpcState->pt);

  PT_END (&dhcpcState->pt);
}
Пример #7
0
static void
handle_dhcp(process_event_t message)
{
	time_t seconds;

	switch( dhcpc_state.state )
	{
	case DHCP_STATE_INITIAL:

		dhcpc_state.state = DHCP_STATE_DISCOVER;
		xid++;

		send_discover();

		stimer_set(&dhcpc_state.stimer, (time_t)10 );	// normally set the timer for 60 seconds,
														// but because the ARP table is empty give DHCP server only 10 seconds.
		break;

	case DHCP_STATE_DISCOVER:

		if( !stimer_expired(&dhcpc_state.stimer) && message == DHCP_OFFER )
		{
			parse_msg();

			dhcpc_state.state = DHCP_STATE_REQUEST;
			xid++;

			send_request();

			stimer_set(&dhcpc_state.stimer, (time_t)10 ); // set the timer for 10 seconds

		} else {
			dhcpc_state.state = DHCP_STATE_INITIAL;
		}
		break;

	case DHCP_STATE_REQUEST:

		if( !stimer_expired(&dhcpc_state.stimer) && message == DHCP_ACK )
		{
			parse_msg();
			dhcpc_state.state = DHCP_STATE_LEASED;

			PRINTF("Got IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&dhcpc_state.ipaddr));
			PRINTF("Got netmask %d.%d.%d.%d\n", uip_ipaddr_to_quad(&dhcpc_state.netmask));
			PRINTF("Got DNS server %d.%d.%d.%d\n", uip_ipaddr_to_quad(&dhcpc_state.dnsaddr));
			PRINTF("Got default router %d.%d.%d.%d\n", uip_ipaddr_to_quad(&dhcpc_state.default_router));
			PRINTF("Lease expires in %ld seconds\n", uip_ntohs(dhcpc_state.lease_time[0])*65536ul + uip_ntohs(dhcpc_state.lease_time[1]));

			dhcpc_configured(&dhcpc_state);

			#define MAX_TICKS (~((time_t)0) / 2)
			#define MAX_TICKS32 (~((time_t)0))

			if((uip_ntohs(dhcpc_state.lease_time[0])*65536ul + uip_ntohs(dhcpc_state.lease_time[1]))/2 <= MAX_TICKS32)
			{
				seconds = ( uip_ntohs(dhcpc_state.lease_time[0])*65536ul + uip_ntohs(dhcpc_state.lease_time[1]) )/2;
			} else {
				seconds = MAX_TICKS32;
			}

			stimer_set(&dhcpc_state.stimer, seconds); // set the timer for half of lease_time seconds

		} else {
			dhcpc_state.state = DHCP_STATE_INITIAL;
		}
		break;

	case DHCP_STATE_LEASED:
		if( stimer_expired(&dhcpc_state.stimer) )
		{
			dhcpc_state.state = DHCP_STATE_INITIAL;
		}
		break;

	case DHCP_STATE_REREQUEST:
	case DHCP_STATE_RELEASE:
	default:
		dhcpc_state.state = DHCP_STATE_INITIAL;
		break;
	}
}
Пример #8
0
int main(int argc, char *argv[])
#endif
{
	uint8_t *temp, *message;
	unsigned long t1 = 0, t2 = 0, xid = 0;
	unsigned long start = 0, lease;
	fd_set rfds;
	int retval;
	struct timeval tv;
	int c, len;
	struct dhcpMessage packet;
	struct in_addr temp_addr;
	long now;
	int max_fd;
	int sig;
	int no_clientid = 0;
	int fail_times = 0;		/* how many times that we fail to find a dhcp server */
	int server_unicast = 0;		


	static const struct option arg_options[] = {
		{"clientid",	required_argument,	0, 'c'},
		{"clientid-none", no_argument,		0, 'C'},
		{"foreground",	no_argument,		0, 'f'},
		{"background",	no_argument,		0, 'b'},
		{"hostname",	required_argument,	0, 'H'},
		{"hostname",    required_argument,      0, 'h'},
		{"interface",	required_argument,	0, 'i'},
		{"now", 	no_argument,		0, 'n'},
		{"pidfile",	required_argument,	0, 'p'},
		{"quit",	no_argument,		0, 'q'},
		{"request",	required_argument,	0, 'r'},
		{"script",	required_argument,	0, 's'},
		{"unicast",	no_argument,		0, 'u'},	/* unicast flag */
		{"version",	no_argument,		0, 'v'},
		{0, 0, 0, 0}
	};

	/* get options */
	while (1) {
		int option_index = 0;
		c = getopt_long(argc, argv, "c:CfbH:h:i:np:qr:s:uv", arg_options, &option_index);
		if (c == -1) break;

		switch (c) {
		case 'c':
			if (no_clientid) show_usage();
			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
			if (client_config.clientid) free(client_config.clientid);
			client_config.clientid = xmalloc(len + 2);
			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
			client_config.clientid[OPT_LEN] = len;
			client_config.clientid[OPT_DATA] = '\0';
			strncpy(client_config.clientid + OPT_DATA, optarg, len);
			break;
		case 'C':
			if (client_config.clientid) show_usage();
			no_clientid = 1;
			break;
		case 'f':
			client_config.foreground = 1;
			break;
		case 'b':
			client_config.background_if_no_lease = 1;
			break;
		case 'h':
		case 'H':
			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
			if (client_config.hostname) free(client_config.hostname);
			client_config.hostname = xmalloc(len + 2);
			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
			client_config.hostname[OPT_LEN] = len;
			strncpy(client_config.hostname + 2, optarg, len);
			break;
		case 'i':
			client_config.interface =  optarg;
			break;
		case 'n':
			client_config.abort_if_no_lease = 1;
			break;
		case 'p':
			client_config.pidfile = optarg;
			break;
		case 'q':
			client_config.quit_after_lease = 1;
			break;
		case 'r':
			requested_ip = inet_addr(optarg);
			break;
		case 's':
			client_config.script = optarg;
			break;
		case 'u':
			server_unicast = 1;
			break;
		case 'v':
			printf("udhcpcd, version %s\n\n", VERSION);
			return 0;
			break;
		default:
			show_usage();
		}
	}

	/* Start the log, sanitize fd's, and write a pid file */
	start_log_and_pid("udhcpc", client_config.pidfile);

	if (read_interface(client_config.interface, &client_config.ifindex,
			   NULL, client_config.arp) < 0)
		return 1;

	/* if not set, and not suppressed, setup the default client ID */
	if (!client_config.clientid && !no_clientid) {
		client_config.clientid = xmalloc(6 + 3);
		client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
		client_config.clientid[OPT_LEN] = 7;
		client_config.clientid[OPT_DATA] = 1;
		memcpy(client_config.clientid + 3, client_config.arp, 6);
	}

	/* changed by lsz 070621 */
	client_background();
	
	/* setup the signal pipe */
	udhcp_sp_setup();

	//if (dhcpc_shm_init() != 0)
	//	return -1;
	#include "msgq.h"
	dhcp_ipc_fork(DHCPC);

	state = INIT_SELECTING;
	run_script(NULL, "deconfig");
	change_mode(LISTEN_RAW);

	for (;;) {
		tv.tv_sec = timeout - uptime();
		tv.tv_usec = 0;

		if (listen_mode != LISTEN_NONE && fd < 0) {
			if (listen_mode == LISTEN_KERNEL)
				fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
			else
				fd = raw_socket(client_config.ifindex);
			if (fd < 0) {
				LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m");
				return 0;
			}
		}
		
        /* 
         * select don't return when timeout value is larger than 1.5 hours
         * we just wait multiple times
         * added by tiger 090819, should fix later
         */
        struct timeval tp_timeout;
        #define TP_TIMEOUT_MAX  (30*60)
        
		if (tv.tv_sec > 0) 
		{
            do
            {
                max_fd = udhcp_sp_fd_set(&rfds, fd);
                
                tp_timeout.tv_sec = (tv.tv_sec > TP_TIMEOUT_MAX) ? TP_TIMEOUT_MAX : tv.tv_sec;
                tv.tv_sec -= tp_timeout.tv_sec;                                
                tp_timeout.tv_usec = 0;

                retval = select(max_fd + 1, &rfds, NULL, NULL, &tp_timeout);                
                
            } while (tv.tv_sec > 0 && retval == 0);
		}
		else
		{
			retval = 0; /* If we already timed out, fall through */
		}
        
		now = uptime();
		if (retval == 0) {
			/* timeout dropped to zero */
			switch (state) {
			case INIT_SELECTING:
               
#define     DISCOVER_RETRY_TIMES    5
#define     DISCOVER_INVERT_TIMES   3

				if (packet_num < DISCOVER_RETRY_TIMES) {
					if (packet_num == 0)
					{
						xid = random_xid();
                        /* use user config dhcp flags when first discover, added by tiger 20090821 */
                        if (server_unicast)
                        {
                            set_runtime_dhcp_flags(DHCP_FLAGS_UNICAST);
                        }
                        else
                        {
                            set_runtime_dhcp_flags(DHCP_FLAGS_BROADCAST);                            
                        }
					}

                    /* change runtime dhcp flags when exceed DISCOVER_INVERT_TIMES added by tiger 20090819 apply 11G and XP's option */
                    if (DISCOVER_INVERT_TIMES == packet_num)
                    {                        
                        invert_runtime_dhcp_flags();
                    }
                    
					/* send discover packet */
					//send_discover(xid, requested_ip, server_unicast); /* broadcast */
					/* modified by tiger 20090304, reply mode's setting way changed */
					send_discover(xid, requested_ip);
					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Send DISCOVER with request ip %X and unicast flag %d", requested_ip, get_runtime_dhcp_flags());                    
                    
					timeout = now + ((packet_num == 2) ? 4 : 2);
					packet_num++;
				} else {
					run_script(NULL, "leasefail");
					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC DHCP Service unavailable, recv no OFFER");
					if (client_config.background_if_no_lease) {
						LOG(LOG_INFO, "No lease, forking to background.");
						client_background();
					} else if (client_config.abort_if_no_lease) {
						LOG(LOG_INFO, "No lease, failing.");
						return 1;
				  	}
					/* wait to try again */
					packet_num = 0;
					
					timeout = now + 10 + (fail_times ++) * 30;	
					/* 60->6000, we dont need to try again -- lsz, 080722 */
					/* 6000->30*fail_times -- lsz, 081008 */
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
				if (packet_num < 3) {
					/* send request packet */
					if (state == RENEW_REQUESTED)
					{
						send_renew(xid, server_addr, requested_ip); /* unicast */
					}
					else
					{
						send_selecting(xid, server_addr, requested_ip); /* broadcast */
					}

					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Send REQUEST to server %x with request ip %x", server_addr, requested_ip);

					timeout = now + ((packet_num == 2) ? 10 : 2);
					packet_num++;
				} else {
					/* timed out, go back to init state */
					if (state == RENEW_REQUESTED) run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = now;
					packet_num = 0;
					change_mode(LISTEN_RAW);
				}
				break;
			case BOUND:
				/* Lease is starting to run out, time to enter renewing state */
				state = RENEWING;
				change_mode(LISTEN_KERNEL);
				DEBUG(LOG_INFO, "Entering renew state");
				/* fall right through */
			case RENEWING:
				/* Either set a new T1, or enter REBINDING state */
				if ((t2 - t1) <= (lease / 14400 + 1)) {
					/* timed out, enter rebinding state */
					state = REBINDING;
					timeout = now + (t2 - t1);
					DEBUG(LOG_INFO, "Entering rebinding state");
				} else {
					/* send a request packet */				
					send_renew(xid, server_addr, requested_ip); /* unicast */

					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Send REQUEST to server %x with request ip %x", server_addr, requested_ip);
              
					t1 = (t2 - t1) / 2 + t1;
					timeout = t1 + start;
				}
				break;
			case REBINDING:
				/* Either set a new T2, or enter INIT state */
				if ((lease - t2) <= (lease / 14400 + 1)) {
					/* timed out, enter init state */
					state = INIT_SELECTING;
					LOG(LOG_INFO, "Lease lost, entering init state");
					run_script(NULL, "deconfig");
					timeout = now;
					packet_num = 0;
					change_mode(LISTEN_RAW);
				} else {
					/* send a request packet */
					send_renew(xid, 0, requested_ip); /* broadcast */

					
					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Broadcast REQUEST with request ip %x", requested_ip);
					t2 = (lease - t2) / 2 + t2;
					timeout = t2 + start;
				}
				break;
			case RELEASED:
				/* yah, I know, *you* say it would never happen */
				timeout = 0x7fffffff;
				break;
			}
		}
		else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
			/* a packet is ready, read it */
			if (listen_mode == LISTEN_KERNEL)
				len = get_packet(&packet, fd);
			else len = get_raw_packet(&packet, fd);

			if (len == -1 && errno != EINTR) {
				DEBUG(LOG_INFO, "error on read, %m, reopening socket");
				change_mode(listen_mode); /* just close and reopen */
			}
			if (len < 0) continue;

			if (packet.xid != xid) {
				DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
					(unsigned long) packet.xid, xid);
				continue;
			}
			/* Ignore packets that aren't for us */
			if (memcmp(packet.chaddr, client_config.arp, 6)) {
				DEBUG(LOG_INFO, "packet does not have our chaddr -- ignoring");
				continue;
			}

			if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
				DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
				continue;
			}

			switch (state) {
			case INIT_SELECTING:
				/* Must be a DHCPOFFER to one of our xid's */
				if (*message == DHCPOFFER) {
					if ((temp = get_option(&packet, DHCP_SERVER_ID))) {
						memcpy(&server_addr, temp, 4);
						xid = packet.xid;
						requested_ip = packet.yiaddr;

						msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Recv OFFER from server %x with ip %x", server_addr, requested_ip);

						/* enter requesting state */
						state = REQUESTING;
						timeout = now;
						packet_num = 0;
					} else {
						DEBUG(LOG_ERR, "No server ID in message");
					}
				}
				break;
			case RENEW_REQUESTED:
			case REQUESTING:
			case RENEWING:
			case REBINDING:
				if (*message == DHCPACK) {
					if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) {
						LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
						lease = 60 * 60;
					} else {
						memcpy(&lease, temp, 4);
						lease = ntohl(lease);
					}

/* RFC 2131 3.1 paragraph 5:
 * "The client receives the DHCPACK message with configuration
 * parameters. The client SHOULD perform a final check on the
 * parameters (e.g., ARP for allocated network address), and notes
 * the duration of the lease specified in the DHCPACK message. At this
 * point, the client is configured. If the client detects that the
 * address is already in use (e.g., through the use of ARP),
 * the client MUST send a DHCPDECLINE message to the server and restarts
 * the configuration process..." 
 * added by tiger 20090827
 */                    
					if (!arpping(packet.yiaddr,
						    (uint32_t) 0,
						    packet.yiaddr,
						    client_config.arp,
						    client_config.interface)
					) {
					
						msglogd (LOG_INFO, LOGTYPE_DHCP, "DHCPC: offered address is in use "
							"(got ARP reply), Send decline");
						send_decline(xid, server_addr, packet.yiaddr);

						if (state != REQUESTING)
							run_script(NULL, "deconfig");
						change_mode(LISTEN_RAW);
						state = INIT_SELECTING;
						requested_ip = 0;
						timeout = now + 12;
						packet_num = 0;
						continue; /* back to main loop */
					}
                    
					/* enter bound state */
					t1 = lease / 2;

					/* little fixed point for n * .875 */
					t2 = (lease * 0x7) >> 3;
					temp_addr.s_addr = packet.yiaddr;
					LOG(LOG_INFO, "Lease of %s obtained, lease time %ld",
						inet_ntoa(temp_addr), lease);
					start = now;
					timeout = t1 + start;
					requested_ip = packet.yiaddr;

					if ((temp = get_option(&packet, DHCP_SERVER_ID))) 
						memcpy(&server_addr, temp, 4);
					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Recv ACK from server %x with ip %x lease time %ld", 
						server_addr, requested_ip, lease);
					
					run_script(&packet,
						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));

					fail_times = 0;		/* clear the retry counter */
					state = BOUND;
					change_mode(LISTEN_NONE);
					if (client_config.quit_after_lease)
						return 0;
					if (!client_config.foreground)
						client_background();

				} else if (*message == DHCPNAK) {
					/* return to init state */
					LOG(LOG_INFO, "Received DHCP NAK");

					if ((temp = get_option(&packet, DHCP_SERVER_ID))) 
						memcpy(&server_addr, temp, 4);
					msglogd(LOG_INFO, LOGTYPE_DHCP, "DHCPC Recv NAK from server %x with ip %x", server_addr, requested_ip);

					run_script(&packet, "nak");
					if (state != REQUESTING)
						run_script(NULL, "deconfig");
					state = INIT_SELECTING;
					timeout = now + 3;	/* change by lsz 080905, without this 3 seconds,
										 * the udhcpc will keep on trying and the release
										 * msg cant be recved by udhcpc, even if we are
										 * wan static ip now, the udhcpc is still sending 
										 * discover pkts. 
										 */
					requested_ip = 0;
					packet_num = 0;
					change_mode(LISTEN_RAW);
					//sleep(3); /* avoid excessive network traffic */
				}
				break;
			/* case BOUND, RELEASED: - ignore all packets */
			}
		} 
		else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) {
Пример #9
0
static void dhcp_run(void)
{
	static bool udp_open_fail = FALSE;

	if(di.state == DHCP_STATE_INIT && di.action != DHCP_ACT_START) {
		DBG("wrong attempt");
		return;
	} else if(GetUDPSocketStatus(di.sock) == SOCKSTAT_CLOSED) {
		if(udp_open_fail == TRUE && !IS_TIME_PASSED(dhcp_run_tick, DHCP_RETRY_DELAY)) 
			goto RET_ALARM;
		if(UDPOpen(di.sock, DHCP_CLIENT_PORT) == RET_OK) {
			if(dhcp_async) sockwatch_open(di.sock, dhcp_async_cb);
			udp_open_fail = FALSE;
			dhcp_run_tick = wizpf_get_systick();
			dhcp_run_cnt = 0;
		} else {
			ERR("UDPOpen fail");
			udp_open_fail = TRUE;
			dhcp_run_tick = wizpf_get_systick();
			goto RET_ALARM;
		}
	}

	switch(di.state) {
	case DHCP_STATE_INIT:
		if(dhcp_run_cnt==0 && !IS_TIME_PASSED(dhcp_run_tick, DHCP_OPEN_DELAY)) 
			goto RET_ALARM;

		if(dhcp_run_cnt < DHCP_SEND_RETRY_COUNT) {
			dhcp_run_cnt++;
			if(send_discover() == RET_OK) {	// Discover ok
				if(dhcp_async) {
					DBG("DHCP Discovery Send Async");
					sockwatch_set(di.sock, WATCH_SOCK_UDP_SEND);
					return;	// alarm set is not needed
				} else {
					DBG("DHCP Discovery Sent");
					SET_STATE(DHCP_STATE_SEARCHING);
					dhcp_run_tick = wizpf_get_systick();
				}
			} else {
				ERRA("DHCP Discovery SEND fail - (%d)times", dhcp_run_cnt);
				dhcp_run_tick = wizpf_get_systick();
			}
		} else {
			ERRA("DHCP Discovery SEND fail - (%d)times", dhcp_run_cnt);
			dhcp_run_cnt = 0;
			UDPClose(di.sock);
			if(dhcp_async) sockwatch_close(di.sock);
			dhcp_fail();
			return; // alarm set is not needed
		}
		break;
	case DHCP_STATE_SEARCHING:
		if(!IS_TIME_PASSED(dhcp_run_tick, DHCP_RETRY_DELAY)) {
			int8 ret = recv_handler();
			if(ret == DHCP_MSG_OFFER) {
				SET_STATE(DHCP_STATE_SELECTING);
				dhcp_run_tick = wizpf_get_systick();
				dhcp_run_cnt = 0;
			} else if(ret != RET_NOK) DBGCRTCA(TRUE, "recv wrong packet(%d)", ret);
		} else {
			ERRA("DHCP Offer RECV fail - for (%d)msec", DHCP_RETRY_DELAY);
			SET_STATE(DHCP_STATE_INIT);
			dhcp_run_tick = wizpf_get_systick();
		}
		break;
	case DHCP_STATE_SELECTING:
		if(dhcp_run_cnt < DHCP_SEND_RETRY_COUNT) {
			dhcp_run_cnt++;
			if(send_request() == RET_OK) {	// Request ok
				if(dhcp_async) {
					DBG("DHCP Request Send Async");
					sockwatch_set(di.sock, WATCH_SOCK_UDP_SEND);
					return;	// alarm set is not needed
				} else {
					DBG("DHCP Request Sent");
					SET_STATE(DHCP_STATE_REQUESTING);
					dhcp_run_tick = wizpf_get_systick();
				}
			} else {
				ERRA("DHCP Request SEND fail - (%d)times", dhcp_run_cnt);
				dhcp_run_tick = wizpf_get_systick();
			}
		} else {
			ERRA("DHCP Request SEND fail - (%d)times", dhcp_run_cnt);
			dhcp_run_cnt = 0;
			UDPClose(di.sock);
			if(dhcp_async) sockwatch_close(di.sock);
			dhcp_fail();
			return; // alarm set is not needed
		}
		break;
	case DHCP_STATE_REQUESTING:
		if(!IS_TIME_PASSED(dhcp_run_tick, DHCP_RETRY_DELAY)) {
			int8 ret = recv_handler();
			if(ret == DHCP_MSG_ACK) {	// Recv ACK
				LOG("DHCP Success");
				SET_STATE(DHCP_STATE_IP_CHECK);
				dhcp_run_tick = wizpf_get_systick();
				dhcp_run_cnt = 0;
			} else if(ret == DHCP_MSG_NAK) {	// Recv NAK
				if(di.action == DHCP_ACT_START) {
					SET_STATE(DHCP_STATE_INIT);
					dhcp_run_tick = wizpf_get_systick();
				} else {
					SET_STATE(DHCP_STATE_BOUND);
				}
				dhcp_run_cnt = 0;
			} else if(ret != RET_NOK) DBGCRTCA(TRUE, "recv wrong packet(%d)", ret);
		} else {
			ERRA("DHCP ACK RECV fail - for (%d)msec", DHCP_RETRY_DELAY);
			if(di.action == DHCP_ACT_START) {
				SET_STATE(DHCP_STATE_INIT);
				dhcp_run_tick = wizpf_get_systick();
			} else {
				SET_STATE(DHCP_STATE_BOUND);
			}
		}
		break;
	case DHCP_STATE_IP_CHECK:
		//if(send_checker() == RET_OK) {
			SET_STATE(DHCP_STATE_BOUND);
			workinfo.DHCP = NETINFO_DHCP_STABLE;
			SetNetInfo(&workinfo);
			if(di.ip_update) di.ip_update();
			LOGA("DHCP ok - New IP (%d.%d.%d.%d)", workinfo.IP[0], workinfo.IP[1], workinfo.IP[2], workinfo.IP[3]);
			//bound_tick = wizpf_get_systick();
			UDPClose(di.sock);
			if(dhcp_async) sockwatch_close(di.sock);
		//} else {
		//	SET_STATE(DHCP_STATE_INIT);
		//	ERR("IP Addr conflicted - IP(%d.%d.%d.%d)", workinfo.IP[0], workinfo.IP[1], workinfo.IP[2], workinfo.IP[3]);
		//	send_rel_dec(DHCP_MSG_DECLINE);
		//	if(di.ip_conflict) (*di.ip_conflict)();
		//}
		break;
	case DHCP_STATE_BOUND:
		return; // alarm set is not needed
	default:
		ERRA("wrong state(%d)", di.state);
		return; // alarm set is not needed
	}

RET_ALARM:
	if(dhcp_alarm) alarm_set(10, dhcp_alarm_cb, 0);
}
Пример #10
0
void Casan::loop ()
{
    Msg in (l2_) ;
    Msg out (l2_) ;
    l2net::l2_recv_t ret ;
    uint8_t oldstatus ;
    long int hlid ;
    l2addr *srcaddr ;
    int mtu ;				// mtu announced by master in assoc msg

    oldstatus = status_ ;		// keep old value for debug display
    sync_time (curtime) ;		// get current time
    retrans_.loop (*l2_, curtime) ;	// check needed retransmissions

    srcaddr = NULL ;

    ret = in.recv () ;			// get received message
    if (ret == l2net::RECV_OK)
	srcaddr = l2_->get_src () ;	// get a new address

    switch (status_)
    {
	case SL_COLDSTART :
	    send_discover (out) ;
	    twait_.init (curtime) ;
	    status_ = SL_WAITING_UNKNOWN ;
	    break ;

	case SL_WAITING_UNKNOWN :
	    if (ret == l2net::RECV_OK)
	    {
		retrans_.check_msg_received (in) ;

		if (is_ctl_msg (in))
		{
		    if (is_hello (in, hlid))
		    {
			DBGLN1 (F ("Received a CTL HELLO msg")) ;
			change_master (hlid, -1) ;	// don't change mtu
			twait_.init (curtime) ;
			status_ = SL_WAITING_KNOWN ;
		    }
		    else if (is_assoc (in, sttl_, mtu))
		    {
			DBGLN1 (F ("Received a CTL ASSOC msg")) ;
			change_master (-1, mtu) ;	// "unknown" hlid
			send_assoc_answer (in, out) ;
			trenew_.init (curtime, sttl_) ;
			status_ = SL_RUNNING ;
		    }
		    else DBGLN1 (F (RED ("Unkwnon CTL"))) ;
		}
	    }

	    if (status_ == SL_WAITING_UNKNOWN && twait_.next (curtime))
		send_discover (out) ;

	    break ;

	case SL_WAITING_KNOWN :
	    if (ret == l2net::RECV_OK)
	    {
		retrans_.check_msg_received (in) ;

		if (is_ctl_msg (in))
		{
		    if (is_hello (in, hlid))
		    {
			DBGLN1 (F ("Received a CTL HELLO msg")) ;
			change_master (hlid, -1) ;	// don't change mtu
		    }
		    else if (is_assoc (in, sttl_, mtu))
		    {
			DBGLN1 (F ("Received a CTL ASSOC msg")) ;
			change_master (-1, mtu) ;	// unknown hlid
			send_assoc_answer (in, out) ;
			trenew_.init (curtime, sttl_) ;
			status_ = SL_RUNNING ;
		    }
		    else DBGLN1 (F (RED ("Unkwnon CTL"))) ;
		}
	    }

	    if (status_ == SL_WAITING_KNOWN)
	    {
		if (twait_.expired (curtime))
		{
		    reset_master () ;		// master_ is no longer known
		    send_discover (out) ;
		    twait_.init (curtime) ;	// reset timer
		    status_ = SL_WAITING_UNKNOWN ;
		}
		else if (twait_.next (curtime))
		{
		    send_discover (out) ;
		}
	    }

	    break ;

	case SL_RUNNING :
	case SL_RENEW :
	    if (ret == l2net::RECV_OK)
	    {
		retrans_.check_msg_received (in) ;

		if (is_ctl_msg (in))
		{
		    if (is_hello (in, hlid))
		    {
			DBGLN1 (F ("Received a CTL HELLO msg")) ;
			if (! same_master (srcaddr) || hlid != hlid_)
			{
			    int oldhlid = hlid_ ;

			    change_master (hlid, 0) ;	// reset mtu
			    if (oldhlid != -1)
			    {
				twait_.init (curtime) ;
				status_ = SL_WAITING_KNOWN ;
			    }
			}
		    }
		    else if (is_assoc (in, sttl_, mtu))
		    {
			DBGLN1 (F ("Received a CTL ASSOC msg")) ;
			if (same_master (srcaddr))
			{
			    negociate_mtu (mtu) ;
			    send_assoc_answer (in, out) ;
			    trenew_.init (curtime, sttl_) ;
			    status_ = SL_RUNNING ;
			}
		    }
		    else DBGLN1 (F (RED ("Unkwnon CTL"))) ;
		}
		else		// request for a normal resource
		{
		    // deduplicate () ;
		    process_request (in, out) ;
		    out.send (*master_) ;
		}
	    }
	    else if (ret == l2net::RECV_TRUNCATED)
	    {
		DBGLN1 (F (RED ("Request too large"))) ;
		out.set_type (COAP_TYPE_ACK) ;
		out.set_id (in.get_id ()) ;
		out.set_token (in.get_token ()) ;
		option o (option::MO_Size1, l2_->mtu ()) ;
		out.push_option (o) ;
		out.set_code (COAP_CODE_TOO_LARGE) ;
		out.send (*master_) ;
	    }

	    check_observed_resources (out) ;

	    if (status_ == SL_RUNNING && trenew_.renew (curtime))
	    {
		send_discover (out) ;
		status_ = SL_RENEW ;
	    }

	    if (status_ == SL_RENEW && trenew_.next (curtime))
	    {
		send_discover (out) ;
	    }

	    if (status_ == SL_RENEW && trenew_.expired (curtime))
	    {
		reset_master () ;	// master_ is no longer known
		send_discover (out) ;
		twait_.init (curtime) ;	// reset timer
		status_ = SL_WAITING_UNKNOWN ;
	    }

	    break ;

	default :
	    DBGLN1 (F ("Error : casan status not known")) ;
	    DBGLN1 (status_) ;
	    break ;
    }

    if (oldstatus != status_)
    {
	DBG1 (F ("Status: " C_GREEN)) ;
	print_status (oldstatus) ;
	DBG1 (F (C_RESET " -> " C_GREEN)) ;
	print_status (status_) ;
	DBGLN1 (F (C_RESET)) ;
    }

    if (srcaddr != NULL)
	delete srcaddr ;
}
Пример #11
0
void dhcp_net_main(void) {


  if(uip_newdata()) {

    switch (uip_udp_conn->appstate.dhcp.state) {
      
    case STATE_DISCOVERING:

      if (parse_msg() == DHCPOFFER) {
	send_request();
	uip_flags &= ~UIP_NEWDATA;
	uip_udp_conn->appstate.dhcp.state = STATE_REQUESTING;
	uip_udp_conn->appstate.dhcp.retry_timer   = 2; // retry
	uip_udp_conn->appstate.dhcp.retry_counter = 1;
	tick_sec = 0;
      }

      break;

    case STATE_REQUESTING:

      if (parse_msg() == DHCPACK) {
	uip_udp_conn->appstate.dhcp.state = STATE_CONFIGURED;

	uip_sethostaddr(uip_udp_conn->appstate.dhcp.ipaddr);
	uip_setdraddr(uip_udp_conn->appstate.dhcp.default_router);
	uip_setnetmask(uip_udp_conn->appstate.dhcp.netmask);

#ifdef DNS_SUPPORT
	resolv_conf(uip_udp_conn->appstate.dhcp.dnsaddr);
	//	eeprom_save(dns_server, &uip_udp_conn->appstate.dhcp.dnsaddr, IPADDR_LEN);
#endif

	// eeprom_save(ip, &uip_udp_conn->appstate.dhcp.ipaddr, IPADDR_LEN);
	// eeprom_save(netmask, &uip_udp_conn->appstate.dhcp.netmask, IPADDR_LEN);
	// eeprom_save(gateway, &uip_udp_conn->appstate.dhcp.default_router, IPADDR_LEN);

	// eeprom_update_chksum();

	/* Remove the bootp connection */
	uip_udp_remove(uip_udp_conn);

      }

      break;

    }
    
  } else {

    // No data yet
    
    switch (uip_udp_conn->appstate.dhcp.state) {
      
    case STATE_INITIAL:
    case STATE_DISCOVERING:
      
      if (tick_sec>uip_udp_conn->appstate.dhcp.retry_timer) {
	send_discover();
	uip_flags &= ~UIP_NEWDATA;
	uip_udp_conn->appstate.dhcp.state = STATE_DISCOVERING;
	if (uip_udp_conn->appstate.dhcp.retry_counter++>10)
	  return dhcp_set_static();
	uip_udp_conn->appstate.dhcp.retry_timer = 2 * uip_udp_conn->appstate.dhcp.retry_counter; // retry
	tick_sec = 0;
      }
      break;
      

    case STATE_REQUESTING:
      if (tick_sec>uip_udp_conn->appstate.dhcp.retry_timer) {
	send_request();
	uip_flags &= ~UIP_NEWDATA;
	if (uip_udp_conn->appstate.dhcp.retry_counter++>10)
	  return dhcp_set_static();
	uip_udp_conn->appstate.dhcp.retry_timer = 2; // retry
	tick_sec = 0;
      }
      break;
      
    }
    
  }


}