📄 mdb.c
字号:
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 (<, lp -> ip_addr, MDL)) { if (lt -> pool) { parse_warn (cfile, "lease %s is declared twice!", piaddr (lp -> ip_addr)); } else pool_reference (< -> pool, pool, MDL); lease_dereference (<, 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 + -