dhcp.c

来自「open source dhcp server client etc...」· C语言 代码 · 共 2,079 行 · 第 1/5 页

C
2,079 行
字号
				free_lease_state (state, MDL);				return;			}			data_string_forget (&d1, MDL);		}	}	/* Try to find a matching host declaration for this lease. */	if (!lease -> host) {		struct host_decl *hp = (struct host_decl *)0;		struct host_decl *h;		/* Try to find a host_decl that matches the client		   identifier or hardware address on the packet, and		   has no fixed IP address.   If there is one, hang		   it off the lease so that its option definitions		   can be used. */		oc = lookup_option (&dhcp_universe, packet -> options,				    DHO_DHCP_CLIENT_IDENTIFIER);		if (oc &&		    evaluate_option_cache (&d1, packet, lease,					   (struct client_state *)0,					   packet -> options, state -> options,					   &lease -> scope, oc, MDL)) {			find_hosts_by_uid (&hp, d1.data, d1.len, MDL);			data_string_forget (&d1, MDL);			if (hp)				host_reference (&lease -> host, hp, MDL);		}		if (!hp) {			find_hosts_by_haddr (&hp,					     packet -> raw -> htype,					     packet -> raw -> chaddr,					     packet -> raw -> hlen,					     MDL);			for (h = hp; h; h = h -> n_ipaddr) {				if (!h -> fixed_addr)					break;			}			if (h)				host_reference (&lease -> host, h, MDL);		}		if (hp)			host_dereference (&hp, MDL);	}	/* Drop the request if it's not allowed for this client.   By	   default, unknown clients are allowed. */	if (!lease -> host &&	    (oc = lookup_option (&server_universe, state -> options,				 SV_BOOT_UNKNOWN_CLIENTS)) &&	    !evaluate_boolean_option_cache (&ignorep,					    packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL)) {		if (!ignorep)			log_info ("%s: unknown client", msg);		free_lease_state (state, MDL);		return;	} 	/* Drop the request if it's not allowed for this client. */	if (!offer &&	    (oc = lookup_option (&server_universe, state -> options,				   SV_ALLOW_BOOTP)) &&	    !evaluate_boolean_option_cache (&ignorep,					    packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL)) {		if (!ignorep)			log_info ("%s: bootp disallowed", msg);		free_lease_state (state, MDL);		return;	} 	/* Drop the request if booting is specifically denied. */	oc = lookup_option (&server_universe, state -> options,			    SV_ALLOW_BOOTING);	if (oc &&	    !evaluate_boolean_option_cache (&ignorep,					    packet, lease,					    (struct client_state *)0,					    packet -> options,					    state -> options,					    &lease -> scope, oc, MDL)) {		if (!ignorep)			log_info ("%s: booting disallowed", msg);		free_lease_state (state, MDL);		return;	}	/* If we are configured to do per-class billing, do it. */	if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {		/* See if the lease is currently being billed to a		   class, and if so, whether or not it can continue to		   be billed to that class. */		if (lease -> billing_class) {			for (i = 0; i < packet -> class_count; i++)				if (packet -> classes [i] ==				    lease -> billing_class)					break;			if (i == packet -> class_count)				unbill_class (lease, lease -> billing_class);		}				/* If we don't have an active billing, see if we need		   one, and if we do, try to do so. */		if (!lease -> billing_class) {			for (i = 0; i < packet -> class_count; i++) {				if (packet -> classes [i] -> lease_limit)					break;			}			if (i != packet -> class_count) {				for (i = 0; i < packet -> class_count; i++)					if ((packet -> 					     classes [i] -> lease_limit) &&					    bill_class (lease,							packet -> classes [i]))						break;				if (i == packet -> class_count) {					log_info ("%s: no available billing",						  msg);					free_lease_state (state, MDL);					/* XXX probably not necessary: */					return;				}			}		}	}	/* Figure out the filename. */	oc = lookup_option (&server_universe, state -> options, SV_FILENAME);	if (oc)		evaluate_option_cache (&state -> filename, packet, lease,				       (struct client_state *)0,				       packet -> options, state -> options,				       &lease -> scope, oc, MDL);	/* Choose a server name as above. */	oc = lookup_option (&server_universe, state -> options,			    SV_SERVER_NAME);	if (oc)		evaluate_option_cache (&state -> server_name, packet, lease,				       (struct client_state *)0,				       packet -> options, state -> options,				       &lease -> scope, oc, MDL);	/* At this point, we have a lease that we can offer the client.	   Now we construct a lease structure that contains what we want,	   and call supersede_lease to do the right thing with it. */	lt = (struct lease *)0;	result = lease_allocate (&lt, MDL);	if (result != ISC_R_SUCCESS) {		log_info ("%s: can't allocate temporary lease structure: %s",			  msg, isc_result_totext (result));		free_lease_state (state, MDL);		return;	}			/* Use the ip address of the lease that we finally found in	   the database. */	lt -> ip_addr = lease -> ip_addr;	/* Start now. */	lt -> starts = cur_time;	/* Figure out how long a lease to assign.    If this is a	   dynamic BOOTP lease, its duration must be infinite. */	if (offer) {		default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;		if ((oc = lookup_option (&server_universe, state -> options,					 SV_DEFAULT_LEASE_TIME))) {			if (evaluate_option_cache (&d1, packet, lease,						   (struct client_state *)0,						   packet -> options,						   state -> options,						   &lease -> scope, oc, MDL)) {				if (d1.len == sizeof (u_int32_t))					default_lease_time =						getULong (d1.data);				data_string_forget (&d1, MDL);			}		}		if ((oc = lookup_option (&dhcp_universe, packet -> options,					 DHO_DHCP_LEASE_TIME)))			s1 = evaluate_option_cache (&d1, packet, lease,						    (struct client_state *)0,						    packet -> options,						    state -> options,						    &lease -> scope, oc, MDL);		else			s1 = 0;		if (s1 && d1.len == sizeof (u_int32_t)) {			lease_time = getULong (d1.data);			data_string_forget (&d1, MDL);		} else {			if (s1)				data_string_forget (&d1, MDL);			lease_time = default_lease_time;		}				/* See if there's a maximum lease time. */		max_lease_time = DEFAULT_MAX_LEASE_TIME;		if ((oc = lookup_option (&server_universe, state -> options,					 SV_MAX_LEASE_TIME))) {			if (evaluate_option_cache (&d1, packet, lease,						   (struct client_state *)0,						   packet -> options,						   state -> options,						   &lease -> scope, oc, MDL)) {				if (d1.len == sizeof (u_int32_t))					max_lease_time =						getULong (d1.data);				data_string_forget (&d1, MDL);			}		}		/* Enforce the maximum lease length. */		if (lease_time < 0 /* XXX */		    || lease_time > max_lease_time)			lease_time = max_lease_time;					min_lease_time = DEFAULT_MIN_LEASE_TIME;		if (min_lease_time > max_lease_time)			min_lease_time = max_lease_time;		if ((oc = lookup_option (&server_universe, state -> options,					 SV_MIN_LEASE_TIME))) {			if (evaluate_option_cache (&d1, packet, lease,						   (struct client_state *)0,						   packet -> options,						   state -> options,						   &lease -> scope, oc, MDL)) {				if (d1.len == sizeof (u_int32_t))					min_lease_time = getULong (d1.data);				data_string_forget (&d1, MDL);			}		}		if (lease_time < min_lease_time) {			if (min_lease_time)				lease_time = min_lease_time;			else				lease_time = default_lease_time;		}#if defined (FAILOVER_PROTOCOL)		/* Okay, we know the lease duration.   Now check the		   failover state, if any. */		if (lease -> pool && lease -> pool -> failover_peer) {			dhcp_failover_state_t *peer =			    lease -> pool -> failover_peer;			/* If the lease time we arrived at exceeds what			   the peer has, we can only issue a lease of			   peer -> mclt, but we can tell the peer we			   want something longer in the future. */			/* XXX This may result in updates that only push			   XXX the peer's expiry time for this lease up			   XXX by a few seconds - think about this again			   XXX later. */			if (lease_time > peer -> mclt &&			    cur_time + lease_time > lease -> tsfp) {				/* Here we're assuming that if we don't have				   to update tstp, there's already an update				   queued.   May want to revisit this.  */				if (peer -> me.state != partner_down &&				    cur_time + lease_time > lease -> tstp)					lt -> tstp = (cur_time + lease_time +						      peer -> mclt / 2);				/* Now choose a lease time that is either				   MCLT, for a lease that's never before been				   assigned, or TSFP + MCLT for a lease that				   has.				   XXX Note that TSFP may be < cur_time.				   XXX What do we do in this case?				   XXX should the expiry timer on the lease				   XXX set tsfp and tstp to zero? */				if (lease -> tsfp < cur_time) {					lease_time = peer -> mclt;				} else {					lease_time = (lease -> tsfp  - cur_time						      + peer -> mclt);				}			} else {				if (cur_time + lease_time > lease -> tsfp &&				    lease_time > peer -> mclt / 2) {					lt -> tstp = (cur_time + lease_time +						      peer -> mclt / 2);				} else { 					lt -> tstp = (cur_time + lease_time +						      lease_time / 2);				}			}			lt -> cltt = cur_time;		}#endif /* FAILOVER_PROTOCOL */		/* If the lease duration causes the time value to wrap,		   use the maximum expiry time. */		if (cur_time + lease_time < cur_time)			state -> offered_expiry = MAX_TIME - 1;		else			state -> offered_expiry = cur_time + lease_time;		if (when)			lt -> ends = when;		else			lt -> ends = state -> offered_expiry;		/* Don't make lease active until we actually get a		   DHCPREQUEST. */		if (offer == DHCPACK)			lt -> next_binding_state = FTS_ACTIVE;		else			lt -> next_binding_state = lease -> binding_state;	} else {		lease_time = MAX_TIME - cur_time;		if ((oc = lookup_option (&server_universe, state -> options,					 SV_BOOTP_LEASE_LENGTH))) {			if (evaluate_option_cache (&d1, packet, lease,						   (struct client_state *)0,						   packet -> options,						   state -> options,						   &lease -> scope, oc, MDL)) {				if (d1.len == sizeof (u_int32_t))					lease_time = getULong (d1.data);				data_string_forget (&d1, MDL);			}		}		if ((oc = lookup_option (&server_universe, state -> options,					 SV_BOOTP_LEASE_CUTOFF))) {			if (evaluate_option_cache (&d1, packet, lease,						   (struct client_state *)0,						   packet -> options,						   state -> options,						   &lease -> scope, oc, MDL)) {				if (d1.len == sizeof (u_int32_t))					lease_time = (getULong (d1.data) -						      cur_time);				data_string_forget (&d1, MDL);			}		}		lt -> ends = state -> offered_expiry = cur_time + lease_time;		lt -> next_binding_state = FTS_BOOTP;	}	lt -> timestamp = cur_time;	/* Record the uid, if given... */	oc = lookup_option (&dhcp_universe, packet -> options,			    DHO_DHCP_CLIENT_IDENTIFIER);	if (oc &&	    evaluate_option_cache (&d1, packet, lease,				   (struct client_state *)0,				   packet -> options, state -> options,				   &lease -> scope, oc, MDL)) {		if (d1.len <= sizeof lt -> uid_buf) {			memcpy (lt -> uid_buf, d1.data, d1.len);			lt -> uid = lt -> uid_buf;			lt -> uid_max = sizeof lt -> uid_buf;			lt -> uid_len = d1.len;		} else {			unsigned char *tuid;			lt -> uid_max = d1.len;			lt -> uid_len = d1.len;			tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL);			/* XXX inelegant */			if (!tuid)				log_fatal ("no memory for large uid.");			memcpy (tuid, d1.data, lt -> uid_len);			lt -> uid = tuid;		}		data_string_forget (&d1, MDL);	}	if (lease -> host)		host_reference (&lt -> host, lease -> host, MDL);	if (lease -> subnet)		subnet_reference (&lt -> subnet, lease -> subnet, MDL);	if (lease -> billing_class)		class_reference (&lt -> billing_class,				 lease -> billing_class, MDL);	/* Set a flag if this client is a broken client that NUL	   terminates string options and expects us to do likewise. */	if (ms_nulltp)		lease -> flags |= MS_NULL_TERMINATION;	else		lease -> flags &= ~MS_NULL_TERMINATION;	/* Save any bindings. */	if (lease -> scope) {		binding_scope_reference (&lt -> scope, lease -> scope, MDL);		binding_scope_dereference (&lease -> scope, MDL);	}	if (lease -> agent_options)		option_chain_head_reference (&lt -> agent_options,					     lease -> agent_options, MDL);	/* If we got relay agent information options, and the packet really	   looks like it came through a relay agent, and if this feature is	   not disabled, save the relay agent information options that came	   in with the packet, so that we can use them at renewal time when	   the packet won't have gone through a relay agent. */	if (p

⌨️ 快捷键说明

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