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

📄 dhcp.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Report what we're sending... */	log_info ("DHCPACK to %s", inet_ntoa (raw.ciaddr));#ifdef DEBUG_PACKET	dump_packet (&outgoing);	dump_raw ((unsigned char *)&raw, outgoing.packet_length);#endif	/* Set up the common stuff... */	to.sin_family = AF_INET;#ifdef HAVE_SA_LEN	to.sin_len = sizeof to;#endif	memset (to.sin_zero, 0, sizeof to.sin_zero);	/* Use the IP address we derived for the client. */	memcpy (&to.sin_addr, cip.iabuf, 4);	to.sin_port = remote_port;	errno = 0;	send_packet ((fallback_interface		      ? fallback_interface : packet -> interface),		     &outgoing, &raw, outgoing.packet_length,		     from, &to, (struct hardware *)0);	if (subnet)		subnet_dereference (&subnet, MDL);}void nak_lease (packet, cip)	struct packet *packet;	struct iaddr *cip;{	struct sockaddr_in to;	struct in_addr from;	int result;	struct dhcp_packet raw;	unsigned char nak = DHCPNAK;	struct packet outgoing;	struct hardware hto;	unsigned i;	struct data_string data;	struct option_state *options = (struct option_state *)0;	struct expression *expr;	struct option_cache *oc = (struct option_cache *)0;	struct iaddr myfrom;	option_state_allocate (&options, MDL);	memset (&outgoing, 0, sizeof outgoing);	memset (&raw, 0, sizeof raw);	outgoing.raw = &raw;	/* Set DHCP_MESSAGE_TYPE to DHCPNAK */	if (!option_cache_allocate (&oc, MDL)) {		log_error ("No memory for DHCPNAK message type.");		option_state_dereference (&options, MDL);		return;	}	if (!make_const_data (&oc -> expression, &nak, sizeof nak,			      0, 0, MDL)) {		log_error ("No memory for expr_const expression.");		option_cache_dereference (&oc, MDL);		option_state_dereference (&options, MDL);		return;	}	oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE];	save_option (&dhcp_universe, options, oc);	option_cache_dereference (&oc, MDL);		     	/* Set DHCP_MESSAGE to whatever the message is */	if (!option_cache_allocate (&oc, MDL)) {		log_error ("No memory for DHCPNAK message type.");		option_state_dereference (&options, MDL);		return;	}	if (!make_const_data (&oc -> expression,			      (unsigned char *)dhcp_message,			      strlen (dhcp_message), 1, 0, MDL)) {		log_error ("No memory for expr_const expression.");		option_cache_dereference (&oc, MDL);		option_state_dereference (&options, MDL);		return;	}	oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE];	save_option (&dhcp_universe, options, oc);	option_cache_dereference (&oc, MDL);		     	i = DHO_DHCP_SERVER_IDENTIFIER;	if (!(oc = lookup_option (&dhcp_universe, options, i))) {	      use_primary:		oc = (struct option_cache *)0;		if (option_cache_allocate (&oc, MDL)) {			if (make_const_data			    (&oc -> expression,			     ((unsigned char *)			      &packet -> interface -> primary_address),			     sizeof packet -> interface -> primary_address,			     0, 0, MDL)) {				oc -> option =					dhcp_universe.options [i];				save_option (&dhcp_universe, options, oc);			}			option_cache_dereference (&oc, MDL);		}		myfrom.len = sizeof packet -> interface -> primary_address;		memcpy (myfrom.iabuf,			&packet -> interface -> primary_address, myfrom.len);	} else {		memset (&data, 0, sizeof data);		if (evaluate_option_cache (&data, packet, (struct lease *)0,					   (struct client_state *)0,					   packet -> options, options,					   &global_scope, oc, MDL)) {			if (!data.len ||			    data.len > sizeof myfrom.iabuf) {				data_string_forget (&data, MDL);				goto use_primary;			}			memcpy (myfrom.iabuf, data.data, data.len);			myfrom.len = data.len;			data_string_forget (&data, MDL);		} else			goto use_primary;	}	/* If there were agent options in the incoming packet, return	   them. */	if (packet -> raw -> giaddr.s_addr &&	    packet -> options -> universe_count > agent_universe.index &&	    packet -> options -> universes [agent_universe.index]) {		option_chain_head_reference		    ((struct option_chain_head **)		     &(options -> universes [agent_universe.index]),		     (struct option_chain_head *)		     packet -> options -> universes [agent_universe.index],		     MDL);	}	/* Do not use the client's requested parameter list. */	delete_option (&dhcp_universe, packet -> options,		       DHO_DHCP_PARAMETER_REQUEST_LIST);	/* Set up the option buffer... */	outgoing.packet_length =		cons_options (packet, outgoing.raw, (struct lease *)0,			      (struct client_state *)0,			      0, packet -> options, options, &global_scope,			      0, 0, 0, (struct data_string *)0, (char *)0);	option_state_dereference (&options, MDL);/*	memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/	raw.siaddr = packet -> interface -> primary_address;	raw.giaddr = packet -> raw -> giaddr;	memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);	raw.hlen = packet -> raw -> hlen;	raw.htype = packet -> raw -> htype;	raw.xid = packet -> raw -> xid;	raw.secs = packet -> raw -> secs;	raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);	raw.hops = packet -> raw -> hops;	raw.op = BOOTREPLY;	/* Report what we're sending... */	log_info ("DHCPNAK on %s to %s via %s",	      piaddr (*cip),	      print_hw_addr (packet -> raw -> htype,			     packet -> raw -> hlen,			     packet -> raw -> chaddr),	      packet -> raw -> giaddr.s_addr	      ? inet_ntoa (packet -> raw -> giaddr)	      : packet -> interface -> name);#ifdef DEBUG_PACKET	dump_packet (packet);	dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);	dump_packet (&outgoing);	dump_raw ((unsigned char *)&raw, outgoing.packet_length);#endif#if 0	hto.hbuf [0] = packet -> raw -> htype;	hto.hlen = packet -> raw -> hlen;	memcpy (&hto.hbuf [1], packet -> raw -> chaddr, hto.hlen);	hto.hlen++;#endif	/* Set up the common stuff... */	to.sin_family = AF_INET;#ifdef HAVE_SA_LEN	to.sin_len = sizeof to;#endif	memset (to.sin_zero, 0, sizeof to.sin_zero);	memcpy (&from, myfrom.iabuf, sizeof from);	/* Make sure that the packet is at least as big as a BOOTP packet. */	if (outgoing.packet_length < BOOTP_MIN_LEN)		outgoing.packet_length = BOOTP_MIN_LEN;	/* If this was gatewayed, send it back to the gateway.	   Otherwise, broadcast it on the local network. */	if (raw.giaddr.s_addr) {		to.sin_addr = raw.giaddr;		if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))			to.sin_port = local_port;		else			to.sin_port = remote_port; /* for testing. */		if (fallback_interface) {			result = send_packet (fallback_interface,					      packet, &raw,					      outgoing.packet_length,					      from, &to, &hto);			return;		}	} else {		to.sin_addr = limited_broadcast;		to.sin_port = remote_port;	}	errno = 0;	result = send_packet (packet -> interface,			      packet, &raw, outgoing.packet_length,			      from, &to, (struct hardware *)0);}void ack_lease (packet, lease, offer, when, msg, ms_nulltp)	struct packet *packet;	struct lease *lease;	unsigned int offer;	TIME when;	char *msg;	int ms_nulltp;{	struct lease *lt;	struct lease_state *state;	struct lease *next;	TIME lease_time;	TIME offered_lease_time;	struct data_string d1;	TIME min_lease_time;	TIME max_lease_time;	TIME default_lease_time;	struct option_cache *oc;	struct expression *expr;	int status;	isc_result_t result;	int did_ping = 0;	TIME ping_timeout;	unsigned i, j;	int s1, s2;	int val;	int ignorep;	/* If we're already acking this lease, don't do it again. */	if (lease -> state)		return;	/* Allocate a lease state structure... */	state = new_lease_state (MDL);	if (!state)		log_fatal ("unable to allocate lease state!");	state -> got_requested_address = packet -> got_requested_address;	shared_network_reference (&state -> shared_network,				  packet -> interface -> shared_network, MDL);	/* See if we got a server identifier option. */	if (lookup_option (&dhcp_universe,			   packet -> options, DHO_DHCP_SERVER_IDENTIFIER))		state -> got_server_identifier = 1;	/* If there were agent options in the incoming packet, return	   them.  Do not return the agent options if they were stashed	   on the lease. */	if (packet -> raw -> giaddr.s_addr &&	    packet -> options -> universe_count > agent_universe.index &&	    packet -> options -> universes [agent_universe.index] &&	    (state -> options -> universe_count <= agent_universe.index ||	     !state -> options -> universes [agent_universe.index]) &&	    lease -> agent_options !=	    ((struct option_chain_head *)	     packet -> options -> universes [agent_universe.index])) {		option_chain_head_reference		    ((struct option_chain_head **)		     &(state -> options -> universes [agent_universe.index]),		     (struct option_chain_head *)		     packet -> options -> universes [agent_universe.index],		     MDL);	}	/* If we are offering a lease that is still currently valid, preserve	   the events.  We need to do this because if the client does not	   REQUEST our offer, it will expire in 2 minutes, overriding the	   expire time in the currently in force lease.  We want the expire	   events to be executed at that point. */	if (lease -> ends <= cur_time && offer != DHCPOFFER) {		/* Get rid of any old expiry or release statements - by		   executing the statements below, we will be inserting new		   ones if there are any to insert. */		if (lease -> on_expiry)			executable_statement_dereference (&lease -> on_expiry,							  MDL);		if (lease -> on_commit)			executable_statement_dereference (&lease -> on_commit,							  MDL);		if (lease -> on_release)			executable_statement_dereference (&lease -> on_release,							  MDL);	}	/* Execute statements in scope starting with the subnet scope. */	execute_statements_in_scope ((struct binding_value **)0,				     packet, lease, (struct client_state *)0,				     packet -> options,				     state -> options, &lease -> scope,				     lease -> subnet -> group,				     (struct group *)0);	/* If the lease is from a pool, run the pool scope. */	if (lease -> pool)		(execute_statements_in_scope		 ((struct binding_value **)0, packet, lease,		  (struct client_state *)0, packet -> options,		  state -> options, &lease -> scope, lease -> pool -> group,		  lease -> pool -> shared_network -> group));	/* Execute statements from class scopes. */	for (i = packet -> class_count; i > 0; i--) {		execute_statements_in_scope			((struct binding_value **)0,			 packet, lease, (struct client_state *)0,			 packet -> options, state -> options,			 &lease -> scope, packet -> classes [i - 1] -> group,			 (lease -> pool			  ? lease -> pool -> group			  : lease -> subnet -> group));	}	/* See if the client is only supposed to have one lease at a time,	   and if so, find its other leases and release them.    We can only	   do this on DHCPREQUEST.    It's a little weird to do this before	   looking at permissions, because the client might not actually	   _get_ a lease after we've done the permission check, but the	   assumption for this option is that the client has exactly one	   network interface, and will only ever remember one lease.   So	   if it sends a DHCPREQUEST, and doesn't get the lease, it's already	   forgotten about its old lease, so we can too. */	if (packet -> packet_type == DHCPREQUEST &&	    (oc = lookup_option (&server_universe, state -> options,				 SV_ONE_LEASE_PER_CLIENT)) &&	    evaluate_boolean_option_cache (&ignorep,					   packet, lease,					   (struct client_state *)0,					   packet -> options,					   state -> options, &lease -> scope,					   oc, MDL)) {	    struct lease *seek;	    if (lease -> uid_len) {		do {		    seek = (struct lease *)0;		    find_lease_by_uid (&seek, lease -> uid,				       lease -> uid_len, MDL);		    if (!seek)			break;		    if (seek == lease && !seek -> n_uid) {			lease_dereference (&seek, MDL);			break;		    }		    next = (struct lease *)0;		    /* Don't release expired leases, and don't		       release the lease we're going to assign. */		    next = (struct lease *)0;		    while (seek) {			if (seek -> n_uid)			    lease_reference (&next, seek -> n_uid, MDL);			if (seek != lease &&			    seek -> binding_state != FTS_RELEASED &&			    seek -> binding_state != FTS_EXPIRED &&			    seek -> binding_state != FTS_RESET &&			    seek -> binding_state != FTS_FREE &&			    seek -> binding_state != FTS_BACKUP)				break;			lease_dereference (&seek, MDL);			if (next) {			    lease_reference (&seek, next, MDL);			    lease_dereference (&next, MDL);			}		    }		    if (next)			lease_dereference (&next, MDL);		    if (seek) {			release_lease (seek, packet);			lease_dereference (&seek, MDL);		    } else			break;		} while (1);	    }	    if (!lease -> uid_len ||		(lease -> host &&		 !lease -> host -> client_identifier.len &&		 (oc = lookup_option (&server_universe, state -> options,				      SV_DUPLICATES)) &&		 !evaluate_boolean_option_cache (&ignorep, packet, lease,						 (struct client_state *)0,						 packet -> options,						 state -> options,						 &lease -> scope,						 oc, MDL))) {		do {		    seek = (struct lease *)0;

⌨️ 快捷键说明

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