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

📄 mdb.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct subnet *subnet;	struct pool *pool;	struct lease **lpchain;{	struct lease *address_range, *lp, *plp;	struct iaddr net;	unsigned min, max, i;	char lowbuf [16], highbuf [16], netbuf [16];	struct shared_network *share = subnet -> shared_network;	isc_result_t status;	struct lease *lt = (struct lease *)0;	/* All subnets should have attached shared network structures. */	if (!share) {		strcpy (netbuf, piaddr (subnet -> net));		log_fatal ("No shared network for network %s (%s)",		       netbuf, piaddr (subnet -> netmask));	}	/* Initialize the hash table if it hasn't been done yet. */	if (!lease_uid_hash) {		if (!lease_new_hash (&lease_uid_hash, 0, MDL))			log_fatal ("Can't allocate lease/uid hash");	}	if (!lease_ip_addr_hash) {		if (!lease_new_hash (&lease_ip_addr_hash, 0, MDL))			log_fatal ("Can't allocate lease/ip hash");	}	if (!lease_hw_addr_hash) {		if (!lease_new_hash (&lease_hw_addr_hash, 0, MDL))			log_fatal ("Can't allocate lease/hw hash");	}	/* Make sure that high and low addresses are in same subnet. */	net = subnet_number (low, subnet -> netmask);	if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {		strcpy (lowbuf, piaddr (low));		strcpy (highbuf, piaddr (high));		strcpy (netbuf, piaddr (subnet -> netmask));		log_fatal ("Address range %s to %s, netmask %s spans %s!",		       lowbuf, highbuf, netbuf, "multiple subnets");	}	/* Make sure that the addresses are on the correct subnet. */	if (!addr_eq (net, subnet -> net)) {		strcpy (lowbuf, piaddr (low));		strcpy (highbuf, piaddr (high));		strcpy (netbuf, piaddr (subnet -> netmask));		log_fatal ("Address range %s to %s not on net %s/%s!",		       lowbuf, highbuf, piaddr (subnet -> net), netbuf);	}	/* Get the high and low host addresses... */	max = host_addr (high, subnet -> netmask);	min = host_addr (low, subnet -> netmask);	/* Allow range to be specified high-to-low as well as low-to-high. */	if (min > max) {		max = min;		min = host_addr (high, subnet -> netmask);	}	/* Get a lease structure for each address in the range. */#if defined (COMPACT_LEASES)	address_range = new_leases (max - min + 1, MDL);	if (!address_range) {		strcpy (lowbuf, piaddr (low));		strcpy (highbuf, piaddr (high));		log_fatal ("No memory for address range %s-%s.",			   lowbuf, highbuf);	}#endif	/* Fill out the lease structures with some minimal information. */	for (i = 0; i < max - min + 1; i++) {		struct lease *lp = (struct lease *)0;#if defined (COMPACT_LEASES)		omapi_object_initialize ((omapi_object_t *)&address_range [i],					 dhcp_type_lease,					 0, sizeof (struct lease), MDL);		lease_reference (&lp, &address_range [i], MDL);#else		status = lease_allocate (&lp, MDL);		if (status != ISC_R_SUCCESS)			log_fatal ("No memory for lease %s: %s",				   piaddr (ip_addr (subnet -> net,						    subnet -> netmask,						    i + min)),				   isc_result_totext (status));#endif		lp -> ip_addr = ip_addr (subnet -> net,					 subnet -> netmask, i + min);		lp -> starts = lp -> timestamp = MIN_TIME;		lp -> ends = MIN_TIME;		subnet_reference (&lp -> subnet, subnet, MDL);		pool_reference (&lp -> pool, pool, MDL);		lp -> binding_state = FTS_FREE;		lp -> next_binding_state = FTS_FREE;		lp -> flags = 0;		/* Remember the lease in the IP address hash. */		if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {			if (lt -> pool) {				parse_warn (cfile,					    "lease %s is declared twice!",					    piaddr (lp -> ip_addr));			} else				pool_reference (&lt -> pool, pool, MDL);			lease_dereference (&lt, MDL);		} else			lease_hash_add (lease_ip_addr_hash,					lp -> ip_addr.iabuf,					lp -> ip_addr.len, lp, MDL);		/* Put the lease on the chain for the caller. */		if (lpchain) {			if (*lpchain) {				lease_reference (&lp -> next, *lpchain, MDL);				lease_dereference (lpchain, MDL);			}			lease_reference (lpchain, lp, MDL);		}		lease_dereference (&lp, MDL);	}}int find_subnet (struct subnet **sp,		 struct iaddr addr, const char *file, int line){	struct subnet *rv;	for (rv = subnets; rv; rv = rv -> next_subnet) {		if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {			if (subnet_reference (sp, rv,					      file, line) != ISC_R_SUCCESS)				return 0;			return 1;		}	}	return 0;}int find_grouped_subnet (struct subnet **sp,			 struct shared_network *share, struct iaddr addr,			 const char *file, int line){	struct subnet *rv;	for (rv = share -> subnets; rv; rv = rv -> next_sibling) {		if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {			if (subnet_reference (sp, rv,					      file, line) != ISC_R_SUCCESS)				return 0;			return 1;		}	}	return 0;}int subnet_inner_than (subnet, scan, warnp)	struct subnet *subnet, *scan;	int warnp;{	if (addr_eq (subnet_number (subnet -> net, scan -> netmask),		     scan -> net) ||	    addr_eq (subnet_number (scan -> net, subnet -> netmask),		     subnet -> net)) {		char n1buf [16];		int i, j;		for (i = 0; i < 32; i++)			if (subnet -> netmask.iabuf [3 - (i >> 3)]			    & (1 << (i & 7)))				break;		for (j = 0; j < 32; j++)			if (scan -> netmask.iabuf [3 - (j >> 3)] &			    (1 << (j & 7)))				break;		strcpy (n1buf, piaddr (subnet -> net));		if (warnp)			log_error ("%ssubnet %s/%d overlaps subnet %s/%d",			      "Warning: ", n1buf, 32 - i,			      piaddr (scan -> net), 32 - j);		if (i < j)			return 1;	}	return 0;}/* Enter a new subnet into the subnet list. */void enter_subnet (subnet)	struct subnet *subnet;{	struct subnet *scan = (struct subnet *)0;	struct subnet *next = (struct subnet *)0;	struct subnet *prev = (struct subnet *)0;	/* Check for duplicates... */	if (subnets)	    subnet_reference (&next, subnets, MDL);	while (next) {	    subnet_reference (&scan, next, MDL);	    subnet_dereference (&next, MDL);	    /* When we find a conflict, make sure that the	       subnet with the narrowest subnet mask comes	       first. */	    if (subnet_inner_than (subnet, scan, 1)) {		if (prev) {		    if (prev -> next_subnet)			subnet_dereference (&prev -> next_subnet, MDL);		    subnet_reference (&prev -> next_subnet, subnet, MDL);		    subnet_dereference (&prev, MDL);		} else {		    subnet_dereference (&subnets, MDL);		    subnet_reference (&subnets, subnet, MDL);		}		subnet_reference (&subnet -> next_subnet, scan, MDL);		subnet_dereference (&scan, MDL);		return;	    }	    subnet_reference (&prev, scan, MDL);	    subnet_dereference (&scan, MDL);	}	if (prev)		subnet_dereference (&prev, MDL);	/* XXX use the BSD radix tree code instead of a linked list. */	if (subnets) {		subnet_reference (&subnet -> next_subnet, subnets, MDL);		subnet_dereference (&subnets, MDL);	}	subnet_reference (&subnets, subnet, MDL);}	/* Enter a new shared network into the shared network list. */void enter_shared_network (share)	struct shared_network *share;{	if (shared_networks) {		shared_network_reference (&share -> next,					  shared_networks, MDL);		shared_network_dereference (&shared_networks, MDL);	}	shared_network_reference (&shared_networks, share, MDL);}	void new_shared_network_interface (cfile, share, name)	struct parse *cfile;	struct shared_network *share;	const char *name;{	struct interface_info *ip;	isc_result_t status;	if (share -> interface) {		parse_warn (cfile, 			    "A subnet or shared network can't be connected %s",			    "to two interfaces.");		return;	}		for (ip = interfaces; ip; ip = ip -> next)		if (!strcmp (ip -> name, name))			break;	if (!ip) {		status = interface_allocate (&ip, MDL);		if (status != ISC_R_SUCCESS)			log_fatal ("new_shared_network_interface %s: %s",				   name, isc_result_totext (status));		if (strlen (name) > sizeof ip -> name) {			memcpy (ip -> name, name, (sizeof ip -> name) - 1);			ip -> name [(sizeof ip -> name) - 1] = 0;		} else			strcpy (ip -> name, name);		if (interfaces) {			interface_reference (&ip -> next, interfaces, MDL);			interface_dereference (&interfaces, MDL);		}		interface_reference (&interfaces, ip, MDL);		ip -> flags = INTERFACE_REQUESTED;		/* XXX this is a reference loop. */		shared_network_reference (&ip -> shared_network, share, MDL);		interface_reference (&share -> interface, ip, MDL);	}}/* Enter a lease into the system.   This is called by the parser each   time it reads in a new lease.   If the subnet for that lease has   already been read in (usually the case), just update that lease;   otherwise, allocate temporary storage for the lease and keep it around   until we're done reading in the config file. */void enter_lease (lease)	struct lease *lease;{	struct lease *comp = (struct lease *)0;	isc_result_t status;	if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {		if (!comp -> pool) {			log_error ("undeclared lease found in database: %s",				   piaddr (lease -> ip_addr));		} else			pool_reference (&lease -> pool, comp -> pool, MDL);		if (comp -> subnet)			subnet_reference (&lease -> subnet,					  comp -> subnet, MDL);		lease_hash_delete (lease_ip_addr_hash,				   lease -> ip_addr.iabuf,				   lease -> ip_addr.len, MDL);		lease_dereference (&comp, MDL);	}	/* The only way a lease can get here without a subnet is if it's in	   the lease file, but not in the dhcpd.conf file.  In this case, we	   *should* keep it around until it's expired, but never reallocate it	   or renew it.  Currently, to maintain consistency, we are not doing	   this.	   XXX fix this so that the lease is kept around until it expires.	   XXX this will be important in IPv6 with addresses that become	   XXX non-renewable as a result of a renumbering event. */	if (!lease -> subnet) {		log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));		return;	}	lease_hash_add (lease_ip_addr_hash,			lease -> ip_addr.iabuf,			lease -> ip_addr.len, lease, MDL);}/* Replace the data in an existing lease with the data in a new lease;   adjust hash tables to suit, and insertion sort the lease into the   list of leases by expiry time so that we can always find the oldest   lease. */int supersede_lease (comp, lease, commit, propogate, pimmediate)	struct lease *comp, *lease;	int commit;	int propogate;	int pimmediate;{	int enter_uid = 0;	int enter_hwaddr = 0;	struct lease *lp, **lq, *prev;	TIME lp_next_state;#if defined (FAILOVER_PROTOCOL)	/* We must commit leases before sending updates regarding them	   to failover peers.  It is, therefore, an error to set pimmediate	   and not commit. */	if (pimmediate && !commit)		return 0;#endif	/* If there is no sample lease, just do the move. */	if (!lease)		goto just_move_it;	/* Static leases are not currently kept in the database... */	if (lease -> flags & STATIC_LEASE)		return 1;	/* If the existing lease hasn't expired and has a different	   unique identifier or, if it doesn't have a unique	   identifier, a different hardware address, then the two	   leases are in conflict.  If the existing lease has a uid	   and the new one doesn't, but they both have the same	   hardware address, and dynamic bootp is allowed on this	   lease, then we allow that, in case a dynamic BOOTP lease is	   requested *after* a DHCP lease has been assigned. */	if (lease -> binding_state != FTS_ABANDONED &&	    lease -> next_binding_state != FTS_ABANDONED &&	    comp -> binding_state == FTS_ACTIVE &&	    (((comp -> uid && lease -> uid) &&	      (comp -> uid_len != lease -> uid_len ||	       memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||	     (!comp -> uid &&	      ((comp -> hardware_addr.hlen !=		lease -> hardware_addr.hlen) ||	       memcmp (comp -> hardware_addr.hbuf,		       lease -> hardware_addr.hbuf,		       comp -> hardware_addr.hlen))))) {		log_error ("Lease conflict at %s",		      piaddr (comp -> ip_addr));	}	/* If there's a Unique ID, dissociate it from the hash	   table and free it if necessary. */	if (comp -> uid) {		uid_hash_delete (comp);		enter_uid = 1;		if (comp -> uid != &comp -> uid_buf [0]) {			dfree (comp -> uid, MDL);			comp -> uid_max = 0;			comp -> uid_len = 0;		}		comp -> uid = (unsigned char *)0;	} else		enter_uid = 1;		if (comp -> hardware_addr.hlen &&	    ((comp -> hardware_addr.hlen !=	      lease -> hardware_addr.hlen) ||	     memcmp (comp -> hardware_addr.hbuf,		     lease -> hardware_addr.hbuf,		     comp -> hardware_addr.hlen))) {		hw_hash_delete (comp);		enter_hwaddr = 1;	} else if (!comp -> hardware_addr.hlen)		enter_hwaddr = 1;		/* If the lease has been billed to a class, remove the billing. */	if (comp -> billing_class != lease -> billing_class) {		if (comp -> billing_class)			unbill_class (comp, comp -> billing_class);		if (lease -> billing_class)			bill_class (comp, lease -> billing_class);	}	/* Copy the data files, but not the linkages. */	comp -> starts = lease -> starts;	if (lease -> uid) {		if (lease -> uid_len <= sizeof (lease -> uid_buf)) {			memcpy (comp -> uid_buf,				lease -> uid, lease -> uid_len);			comp -> uid = &comp -> uid_buf [0];			comp -> uid_max = sizeof comp -> uid_buf;			comp -> uid_len = lease -> uid_len;		} else if (lease -> uid != &lease -> uid_buf [0]) {			comp -> uid = lease -> uid;			comp -> uid_max = lease -> uid_max;			lease -> uid = (unsigned char *)0;			lease -> uid_max = 0;			comp -> uid_len = lease -> uid_len;			lease -> uid_len = 0;		} else {			log_fatal ("corrupt lease uid."); /* XXX */		}	} else {		comp -> uid = (unsigned char *)0;		comp -> uid_len = comp -> uid_max = 0;	}	if (comp -> host)		host_dereference (&comp -> host, MDL);	host_reference (&comp -> host, lease -> host, MDL);	comp -> hardware_addr = lease -> hardware_addr;	comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |			 (comp -> flags & ~EPHEMERAL_FLAGS));

⌨️ 快捷键说明

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