?? mdb.c
字號:
/* mdb.c Server-specific in-memory database support. *//* * Copyright (c) 1996-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of The Internet Software Consortium nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This software has been written for the Internet Software Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about the Internet Software 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.9 2001/08/23 16:30:58 mellon Exp $ Copyright (c) 1996-2001 The Internet Software Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"struct subnet *subnets;struct shared_network *shared_networks;struct hash_table *host_hw_addr_hash;struct hash_table *host_uid_hash;struct hash_table *lease_uid_hash;struct hash_table *lease_ip_addr_hash;struct hash_table *lease_hw_addr_hash;struct hash_table *host_name_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) { host_name_hash = new_hash ((hash_reference)host_reference, (hash_dereference)host_dereference, 0, MDL); if (!host_name_hash) 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_DYNAMIC) hd -> flags |= HOST_DECL_STATIC; } /* 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) { host_hw_addr_hash = new_hash ((hash_reference)host_reference, (hash_dereference)host_dereference, 0, MDL); if (!host_hw_addr_hash) 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) { host_uid_hash = new_hash ((hash_reference)host_reference, (hash_dereference)host_dereference, 0, MDL); if (!host_uid_hash) 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; 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; 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. */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -