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

📄 mdb.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* mdb.c   Server-specific in-memory database support. *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *   Internet Systems Consortium, Inc. *   950 Charter Street *   Redwood City, CA 94063 *   <info@isc.org> *   http://www.isc.org/ * * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about Internet Systems Consortium, see * ``http://www.isc.org/''.  To learn more about Vixie Enterprises, * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#ifndef lintstatic char copyright[] ="$Id: mdb.c,v 1.67.2.19 2004/06/10 17:59:56 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include "omapip/hash.h"struct subnet *subnets;struct shared_network *shared_networks;host_hash_t *host_hw_addr_hash;host_hash_t *host_uid_hash;host_hash_t *host_name_hash;lease_hash_t *lease_uid_hash;lease_hash_t *lease_ip_addr_hash;lease_hash_t *lease_hw_addr_hash;omapi_object_type_t *dhcp_type_host;static int find_uid_statement (struct executable_statement *esp,			       void *vp, int condp){	struct executable_statement **evp = vp;	if (esp -> op == supersede_option_statement &&	    esp -> data.option &&	    (esp -> data.option -> option -> universe ==	     &dhcp_universe) &&	    (esp -> data.option -> option -> code ==	     DHO_DHCP_CLIENT_IDENTIFIER)) {		if (condp) {			log_error ("dhcp client identifier may not be %s",				   "specified conditionally.");		} else if (!(*evp)) {			executable_statement_reference (evp, esp, MDL);			return 1;		} else {			log_error ("only one dhcp client identifier may be %s",				   "specified");		}	}	return 0;}isc_result_t enter_host (hd, dynamicp, commit)	struct host_decl *hd;	int dynamicp;	int commit;{	struct host_decl *hp = (struct host_decl *)0;	struct host_decl *np = (struct host_decl *)0;	struct executable_statement *esp;	if (!host_name_hash) {		if (!host_new_hash (&host_name_hash, 0, MDL))			log_fatal ("Can't allocate host name hash");		host_hash_add (host_name_hash,			       (unsigned char *)hd -> name,			       strlen (hd -> name), hd, MDL);	} else {		host_hash_lookup (&hp, host_name_hash,				  (unsigned char *)hd -> name,				  strlen (hd -> name), MDL);		/* If it's deleted, we can supersede it. */		if (hp && (hp -> flags & HOST_DECL_DELETED)) {			host_hash_delete (host_name_hash,					  (unsigned char *)hd -> name,					  strlen (hd -> name), MDL);			/* If the old entry wasn't dynamic, then we			   always have to keep the deletion. */			if (hp -> flags & HOST_DECL_STATIC) {				hd -> flags |= HOST_DECL_STATIC;			}			host_dereference (&hp, MDL);		}		/* If we are updating an existing host declaration, we		   can just delete it and add it again. */		if (hp && hp == hd) {			host_dereference (&hp, MDL);			delete_host (hd, 0);			if (!write_host (hd))				return ISC_R_IOERROR;			hd -> flags &= ~HOST_DECL_DELETED;		}		/* If there isn't already a host decl matching this		   address, add it to the hash table. */		if (!hp) {			host_hash_add (host_name_hash,				       (unsigned char *)hd -> name,				       strlen (hd -> name), hd, MDL);		} else {			/* XXX actually, we have to delete the old one			   XXX carefully and replace it.   Not done yet. */			host_dereference (&hp, MDL);			return ISC_R_EXISTS;		}	}	if (hd -> n_ipaddr)		host_dereference (&hd -> n_ipaddr, MDL);	if (!hd -> type)		hd -> type = dhcp_type_host;	if (hd -> interface.hlen) {		if (!host_hw_addr_hash) {			if (!host_new_hash (&host_hw_addr_hash, 0, MDL))				log_fatal ("Can't allocate host/hw hash");		} else {			/* If there isn't already a host decl matching this			   address, add it to the hash table. */			host_hash_lookup (&hp, host_hw_addr_hash,					  hd -> interface.hbuf,					  hd -> interface.hlen, MDL);		}		if (!hp)			host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,				       hd -> interface.hlen, hd, MDL);		else {			/* If there was already a host declaration for			   this hardware address, add this one to the			   end of the list. */			for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)				;			host_reference (&np -> n_ipaddr, hd, MDL);			host_dereference (&hp, MDL);		}	}	/* See if there's a statement that sets the client identifier.	   This is a kludge - the client identifier really shouldn't be	   set with an executable statement. */	esp = (struct executable_statement *)0;	if (executable_statement_foreach (hd -> group -> statements,					  find_uid_statement, &esp, 0)) {		evaluate_option_cache (&hd -> client_identifier,				       (struct packet *)0,				       (struct lease *)0,				       (struct client_state *)0,				       (struct option_state *)0,				       (struct option_state *)0, &global_scope,				       esp -> data.option, MDL);	}	/* If we got a client identifier, hash this entry by	   client identifier. */	if (hd -> client_identifier.len) {		/* If there's no uid hash, make one; otherwise, see if		   there's already an entry in the hash for this host. */		if (!host_uid_hash) {			if (!host_new_hash (&host_uid_hash, 0, MDL))				log_fatal ("Can't allocate host/uid hash");			host_hash_add (host_uid_hash,				       hd -> client_identifier.data,				       hd -> client_identifier.len,				       hd, MDL);		} else {			/* If there's already a host declaration for this			   client identifier, add this one to the end of the			   list.  Otherwise, add it to the hash table. */			if (host_hash_lookup (&hp, host_uid_hash,					      hd -> client_identifier.data,					      hd -> client_identifier.len,					      MDL)) {				/* Don't link it in twice... */				if (!np) {					for (np = hp; np -> n_ipaddr;					     np = np -> n_ipaddr) {						if (hd == np)						    break;					}					if (hd != np)					    host_reference (&np -> n_ipaddr,							    hd, MDL);				}				host_dereference (&hp, MDL);			} else {				host_hash_add (host_uid_hash,					       hd -> client_identifier.data,					       hd -> client_identifier.len,					       hd, MDL);			}		}	}	if (dynamicp && commit) {		if (!write_host (hd))			return ISC_R_IOERROR;		if (!commit_leases ())			return ISC_R_IOERROR;	}	return ISC_R_SUCCESS;}isc_result_t delete_host (hd, commit)	struct host_decl *hd;	int commit;{	struct host_decl *hp = (struct host_decl *)0;	struct host_decl *np = (struct host_decl *)0;	struct host_decl *foo;	struct executable_statement *esp;	int hw_head = 0, uid_head = 1;	/* Don't need to do it twice. */	if (hd -> flags & HOST_DECL_DELETED)		return ISC_R_SUCCESS;	/* But we do need to do it once!   :') */	hd -> flags |= HOST_DECL_DELETED;	if (hd -> interface.hlen) {	    if (host_hw_addr_hash) {		if (host_hash_lookup (&hp, host_hw_addr_hash,				      hd -> interface.hbuf,				      hd -> interface.hlen, MDL)) {		    if (hp == hd) {			host_hash_delete (host_hw_addr_hash,					  hd -> interface.hbuf,					  hd -> interface.hlen, MDL);			hw_head = 1;		    } else {			np = (struct host_decl *)0;			foo = (struct host_decl *)0;			host_reference (&foo, hp, MDL);			while (foo) {			    if (foo == hd)				    break;			    if (np)				    host_dereference (&np, MDL);			    host_reference (&np, foo, MDL);			    host_dereference (&foo, MDL);			    if (np -> n_ipaddr)				    host_reference (&foo, np -> n_ipaddr, MDL);			}			if (foo) {			    host_dereference (&np -> n_ipaddr, MDL);			    if (hd -> n_ipaddr)				host_reference (&np -> n_ipaddr,						hd -> n_ipaddr, MDL);			    host_dereference (&foo, MDL);			}			if (np)				host_dereference (&np, MDL);		    }		    host_dereference (&hp, MDL);		}	    }	}	/* If we got a client identifier, hash this entry by	   client identifier. */	if (hd -> client_identifier.len) {	    if (host_uid_hash) {		if (host_hash_lookup (&hp, host_uid_hash,				      hd -> client_identifier.data,				      hd -> client_identifier.len, MDL)) {		    if (hp == hd) {			host_hash_delete (host_uid_hash,					  hd -> client_identifier.data,					  hd -> client_identifier.len, MDL);			uid_head = 1;		    } else {			np = (struct host_decl *)0;			foo = (struct host_decl *)0;			host_reference (&foo, hp, MDL);			while (foo) {			    if (foo == hd)				    break;			    if (np)				host_dereference (&np, MDL);			    host_reference (&np, foo, MDL);			    host_dereference (&foo, MDL);			    if (np -> n_ipaddr)				    host_reference (&foo, np -> n_ipaddr, MDL);			}			if (foo) {			    host_dereference (&np -> n_ipaddr, MDL);			    if (hd -> n_ipaddr)				host_reference (&np -> n_ipaddr,						hd -> n_ipaddr, MDL);			    host_dereference (&foo, MDL);			}			if (np)				host_dereference (&np, MDL);		    }		    host_dereference (&hp, MDL);		}	    }	}	if (hd -> n_ipaddr) {		if (uid_head && hd -> n_ipaddr -> client_identifier.len) {			host_hash_add				(host_uid_hash,				 hd -> n_ipaddr -> client_identifier.data,				 hd -> n_ipaddr -> client_identifier.len,				 hd -> n_ipaddr, MDL);		}		if (hw_head && hd -> n_ipaddr -> interface.hlen) {			host_hash_add (host_hw_addr_hash,				       hd -> n_ipaddr -> interface.hbuf,				       hd -> n_ipaddr -> interface.hlen,				       hd -> n_ipaddr, MDL);		}		host_dereference (&hd -> n_ipaddr, MDL);	}	if (host_name_hash) {		if (host_hash_lookup (&hp, host_name_hash,				      (unsigned char *)hd -> name,				      strlen (hd -> name), MDL)) {			if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {				host_hash_delete (host_name_hash,						  (unsigned char *)hd -> name,						  strlen (hd -> name), MDL);			}			host_dereference (&hp, MDL);		}	}	if (commit) {		if (!write_host (hd))			return ISC_R_IOERROR;		if (!commit_leases ())			return ISC_R_IOERROR;	}	return ISC_R_SUCCESS;}int find_hosts_by_haddr (struct host_decl **hp, int htype,			 const unsigned char *haddr, unsigned hlen,			 const char *file, int line){	struct host_decl *foo;	struct hardware h;	h.hlen = hlen + 1;	h.hbuf [0] = htype;	memcpy (&h.hbuf [1], haddr, hlen);	return host_hash_lookup (hp, host_hw_addr_hash,				 h.hbuf, h.hlen, file, line);}int find_hosts_by_uid (struct host_decl **hp,		       const unsigned char *data, unsigned len,		       const char *file, int line){	return host_hash_lookup (hp, host_uid_hash, data, len, file, line);}/* More than one host_decl can be returned by find_hosts_by_haddr or   find_hosts_by_uid, and each host_decl can have multiple addresses.   Loop through the list of hosts, and then for each host, through the   list of addresses, looking for an address that's in the same shared   network as the one specified.    Store the matching address through   the addr pointer, update the host pointer to point at the host_decl   that matched, and return the subnet that matched. */int find_host_for_network (struct subnet **sp, struct host_decl **host,			   struct iaddr *addr, struct shared_network *share){	int i;	struct subnet *subnet;	struct iaddr ip_address;	struct host_decl *hp;	struct data_string fixed_addr;	memset (&fixed_addr, 0, sizeof fixed_addr);	for (hp = *host; hp; hp = hp -> n_ipaddr) {		if (!hp -> fixed_addr)			continue;		if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,					    (struct lease *)0,					    (struct client_state *)0,					    (struct option_state *)0,					    (struct option_state *)0,					    &global_scope,					    hp -> fixed_addr, MDL))			continue;		for (i = 0; i < fixed_addr.len; i += 4) {			ip_address.len = 4;			memcpy (ip_address.iabuf,				fixed_addr.data + i, 4);			if (find_grouped_subnet (sp, share, ip_address, MDL)) {				struct host_decl *tmp = (struct host_decl *)0;				*addr = ip_address;				/* This is probably not necessary, but				   just in case *host is the only reference				   to that host declaration, make a temporary				   reference so that dereferencing it doesn't				   dereference hp out from under us. */				host_reference (&tmp, *host, MDL);				host_dereference (host, MDL);				host_reference (host, hp, MDL);				host_dereference (&tmp, MDL);				data_string_forget (&fixed_addr, MDL);				return 1;			}		}		data_string_forget (&fixed_addr, MDL);	}	return 0;}void new_address_range (cfile, low, high, subnet, pool, lpchain)	struct parse *cfile;	struct iaddr low, high;

⌨️ 快捷键说明

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