⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhclient.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
void send_discover (cpp)	void *cpp;{	struct client_state *client = cpp;	int result;	int interval;	int increase = 1;	/* Figure out how long it's been since we started transmitting. */	interval = cur_time - client -> first_sending;	/* If we're past the panic timeout, call the script and tell it	   we haven't found anything for this interface yet. */	if (interval > client -> config -> timeout) {		state_panic (client);		return;	}	/* If we're selecting media, try the whole list before doing	   the exponential backoff, but if we've already received an	   offer, stop looping, because we obviously have it right. */	if (!client -> offered_leases &&	    client -> config -> media) {		int fail = 0;	      again:		if (client -> medium) {			client -> medium = client -> medium -> next;			increase = 0;		} 		if (!client -> medium) {			if (fail)				log_fatal ("No valid media types for %s!",				       client -> interface -> name);			client -> medium =				client -> config -> media;			increase = 1;		}					log_info ("Trying medium \"%s\" %d",			  client -> medium -> string, increase);		script_init (client, "MEDIUM", client -> medium);		if (script_go (client)) {			fail = 1;			goto again;		}	}	/* If we're supposed to increase the interval, do so.  If it's	   currently zero (i.e., we haven't sent any packets yet), set	   it to one; otherwise, add to it a random number between	   zero and two times itself.  On average, this means that it	   will double with every transmission. */	if (increase) {		if (!client -> interval)			client -> interval =				client -> config -> initial_interval;		else			client -> interval += ((random () >> 2) %					       (2 * client -> interval));		/* Don't backoff past cutoff. */		if (client -> interval >		    client -> config -> backoff_cutoff)			client -> interval =				((client -> config -> backoff_cutoff / 2)				 + ((random () >> 2) %				    client -> config -> backoff_cutoff));	} else if (!client -> interval)		client -> interval = client -> config -> initial_interval;			/* If the backoff would take us to the panic timeout, just use that	   as the interval. */	if (cur_time + client -> interval >	    client -> first_sending + client -> config -> timeout)		client -> interval =			(client -> first_sending +			 client -> config -> timeout) - cur_time + 1;	/* Record the number of seconds since we started sending. */	if (interval < 65536)		client -> packet.secs = htons (interval);	else		client -> packet.secs = htons (65535);	client -> secs = client -> packet.secs;	log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",	      client -> name ? client -> name : client -> interface -> name,	      inet_ntoa (sockaddr_broadcast.sin_addr),	      ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));	/* Send out a packet. */	result = send_packet (client -> interface, (struct packet *)0,			      &client -> packet,			      client -> packet_length,			      inaddr_any, &sockaddr_broadcast,			      (struct hardware *)0);	add_timeout (cur_time + client -> interval,		     send_discover, client, 0, 0);}/* state_panic gets called if we haven't received any offers in a preset   amount of time.   When this happens, we try to use existing leases that   haven't yet expired, and failing that, we call the client script and   hope it can do something. */void state_panic (cpp)	void *cpp;{	struct client_state *client = cpp;	struct client_lease *loop;	struct client_lease *lp;	loop = lp = client -> active;	log_info ("No DHCPOFFERS received.");	/* We may not have an active lease, but we may have some	   predefined leases that we can try. */	if (!client -> active && client -> leases)		goto activate_next;	/* Run through the list of leases and see if one can be used. */	while (client -> active) {		if (client -> active -> expiry > cur_time) {			log_info ("Trying recorded lease %s",			      piaddr (client -> active -> address));			/* Run the client script with the existing			   parameters. */			script_init (client, "TIMEOUT",				     client -> active -> medium);			script_write_params (client, "new_", client -> active);			if (client -> alias)				script_write_params (client, "alias_",						     client -> alias);			/* If the old lease is still good and doesn't			   yet need renewal, go into BOUND state and			   timeout at the renewal time. */			if (!script_go (client)) {			    if (cur_time < client -> active -> renewal) {				client -> state = S_BOUND;				log_info ("bound: renewal in %ld %s.",					  (long)(client -> active -> renewal -						 cur_time), "seconds");				add_timeout (client -> active -> renewal,					     state_bound, client, 0, 0);			    } else {				client -> state = S_BOUND;				log_info ("bound: immediate renewal.");				state_bound (client);			    }			    reinitialize_interfaces ();			    go_daemon ();			    return;			}		}		/* If there are no other leases, give up. */		if (!client -> leases) {			client -> leases = client -> active;			client -> active = (struct client_lease *)0;			break;		}	activate_next:		/* Otherwise, put the active lease at the end of the		   lease list, and try another lease.. */		for (lp = client -> leases; lp -> next; lp = lp -> next)			;		lp -> next = client -> active;		if (lp -> next) {			lp -> next -> next = (struct client_lease *)0;		}		client -> active = client -> leases;		client -> leases = client -> leases -> next;		/* If we already tried this lease, we've exhausted the		   set of leases, so we might as well give up for		   now. */		if (client -> active == loop)			break;		else if (!loop)			loop = client -> active;	}	/* No leases were available, or what was available didn't work, so	   tell the shell script that we failed to allocate an address,	   and try again later. */	if (onetry) {		if (!quiet)			log_info ("Unable to obtain a lease on first try.%s",				  "  Exiting.");		exit (2);	}	log_info ("No working leases in persistent database - sleeping.");	script_init (client, "FAIL", (struct string_list *)0);	if (client -> alias)		script_write_params (client, "alias_", client -> alias);	script_go (client);	client -> state = S_INIT;	add_timeout (cur_time +		     ((client -> config -> retry_interval + 1) / 2 +		      (random () % client -> config -> retry_interval)),		     state_init, client, 0, 0);	go_daemon ();}void send_request (cpp)	void *cpp;{	struct client_state *client = cpp;	int result;	int interval;	struct sockaddr_in destination;	struct in_addr from;	/* Figure out how long it's been since we started transmitting. */	interval = cur_time - client -> first_sending;	/* If we're in the INIT-REBOOT or REQUESTING state and we're	   past the reboot timeout, go to INIT and see if we can	   DISCOVER an address... */	/* XXX In the INIT-REBOOT state, if we don't get an ACK, it	   means either that we're on a network with no DHCP server,	   or that our server is down.  In the latter case, assuming	   that there is a backup DHCP server, DHCPDISCOVER will get	   us a new address, but we could also have successfully	   reused our old address.  In the former case, we're hosed	   anyway.  This is not a win-prone situation. */	if ((client -> state == S_REBOOTING ||	     client -> state == S_REQUESTING) &&	    interval > client -> config -> reboot_timeout) {	cancel:		client -> state = S_INIT;		cancel_timeout (send_request, client);		state_init (client);		return;	}	/* If we're in the reboot state, make sure the media is set up	   correctly. */	if (client -> state == S_REBOOTING &&	    !client -> medium &&	    client -> active -> medium ) {		script_init (client, "MEDIUM", client -> active -> medium);		/* If the medium we chose won't fly, go to INIT state. */		if (script_go (client))			goto cancel;		/* Record the medium. */		client -> medium = client -> active -> medium;	}	/* If the lease has expired, relinquish the address and go back	   to the INIT state. */	if (client -> state != S_REQUESTING &&	    cur_time > client -> active -> expiry) {		/* Run the client script with the new parameters. */		script_init (client, "EXPIRE", (struct string_list *)0);		script_write_params (client, "old_", client -> active);		if (client -> alias)			script_write_params (client, "alias_",					     client -> alias);		script_go (client);		/* Now do a preinit on the interface so that we can		   discover a new address. */		script_init (client, "PREINIT", (struct string_list *)0);		if (client -> alias)			script_write_params (client, "alias_",					     client -> alias);		script_go (client);		client -> state = S_INIT;		state_init (client);		return;	}	/* Do the exponential backoff... */	if (!client -> interval)		client -> interval = client -> config -> initial_interval;	else {		client -> interval += ((random () >> 2) %				       (2 * client -> interval));	}		/* Don't backoff past cutoff. */	if (client -> interval >	    client -> config -> backoff_cutoff)		client -> interval =			((client -> config -> backoff_cutoff / 2)			 + ((random () >> 2) % client -> interval));	/* If the backoff would take us to the expiry time, just set the	   timeout to the expiry time. */	if (client -> state != S_REQUESTING &&	    cur_time + client -> interval > client -> active -> expiry)		client -> interval =			client -> active -> expiry - cur_time + 1;	/* If the lease T2 time has elapsed, or if we're not yet bound,	   broadcast the DHCPREQUEST rather than unicasting. */	if (client -> state == S_REQUESTING ||	    client -> state == S_REBOOTING ||	    cur_time > client -> active -> rebind)		destination.sin_addr = sockaddr_broadcast.sin_addr;	else		memcpy (&destination.sin_addr.s_addr,			client -> destination.iabuf,			sizeof destination.sin_addr.s_addr);	destination.sin_port = remote_port;	destination.sin_family = AF_INET;#ifdef HAVE_SA_LEN	destination.sin_len = sizeof destination;#endif	if (client -> state == S_RENEWING ||	    client -> state == S_REBINDING)		memcpy (&from, client -> active -> address.iabuf,			sizeof from);	else		from.s_addr = INADDR_ANY;	/* Record the number of seconds since we started sending. */	if (client -> state == S_REQUESTING)		client -> packet.secs = client -> secs;	else {		if (interval < 65536)			client -> packet.secs = htons (interval);		else			client -> packet.secs = htons (65535);	}	log_info ("DHCPREQUEST on %s to %s port %d",	      client -> name ? client -> name : client -> interface -> name,	      inet_ntoa (destination.sin_addr),	      ntohs (destination.sin_port));	if (destination.sin_addr.s_addr != INADDR_BROADCAST &&	    fallback_interface)		result = send_packet (fallback_interface,				      (struct packet *)0,				      &client -> packet,				      client -> packet_length,				      from, &destination,				      (struct hardware *)0);	else		/* Send out a packet. */		result = send_packet (client -> interface, (struct packet *)0,				      &client -> packet,				      client -> packet_length,				      from, &destination,				      (struct hardware *)0);	add_timeout (cur_time + client -> interval,		     send_request, client, 0, 0);}void send_decline (cpp)	void *cpp;{	struct client_state *client = cpp;	int result;	log_info ("DHCPDECLINE on %s to %s port %d",	      client -> name ? client -> name : client -> interface -> name,	      inet_ntoa (sockaddr_broadcast.sin_addr),	      ntohs (sockaddr_broadcast.sin_port));	/* Send out a packet. */	result = send_packet (client -> interface, (struct packet *)0,			      &client -> packet,			      client -> packet_length,			      inaddr_any, &sockaddr_broadcast,			      (struct hardware *)0);}void send_release (cpp)	void *cpp;{	struct client_state *client = cpp;	int result;	struct sockaddr_in destination;	struct in_addr from;	memcpy (&from, client -> active -> address.iabuf,		sizeof from);	memcpy (&destination.sin_addr.s_addr,		client -> destination.iabuf,		sizeof destination.sin_addr.s_addr);	destination.sin_port = remote_port;	destination.sin_family = AF_INET;#ifdef HAVE_SA_LEN	destination.sin_len = sizeof destination;#endif	/* Set the lease to end now, so that we don't accidentally	   reuse it if we restart before the old expiry time. */	client -> active -> expiry =		client -> active -> renewal =		client -> active -> rebind = cur_time;	if (!write_client_lease (client, client -> active, 1, 1)) {		log_error ("Can't release lease: lease write failed.");		return;	}	log_info ("DHCPRELEASE on %s to %s port %d",	      client -> name ? client -> name : client -> interface -> name,	      inet_ntoa (destination.sin_addr),	      ntohs (destination.sin_port));	if (fallback_interface)		result = send_packet (fallback_interface,				      (struct packet *)0,				      &client -> packet,				      client -> packet_length,				      from, &destination,				      (struct hardware *)0);	else		/* Send out a packet. */		result = send_packet (client -> interface, (struct packet *)0,				      &client -> packet,				      client -> packet_length,				      from, &destination,				      (struct hardware *)0);}void make_client_options (client, lease, type, sid, rip, prl, op)	struct client_state *client;	struct client_lease *lease;	u_int8_t *type;	struct option_cache *sid;	struct iaddr *rip;	u_int32_t *prl;	struct option_state **op;{	unsigned i;	struct option_cache *oc;	struct buffer *bp = (struct buffer *)0;	/* If there are any leftover options, get rid of them. */	if (*op)		option_state_dereference (op, MDL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -