📄 memory.c
字号:
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 -> flags & ABANDONED_LEASE) &&
comp -> ends > cur_time &&
(((comp -> uid && lease -> uid) &&
(comp -> uid_len != lease -> uid_len ||
memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
(!comp -> uid &&
((comp -> hardware_addr.htype !=
lease -> hardware_addr.htype) ||
(comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
memcmp (comp -> hardware_addr.haddr,
lease -> hardware_addr.haddr,
comp -> hardware_addr.hlen))))) {
warn ("Lease conflict at %s",
piaddr (comp -> ip_addr));
return 0;
} else {
/* 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]) {
free (comp -> uid);
comp -> uid_max = 0;
comp -> uid_len = 0;
}
comp -> uid = (unsigned char *)0;
} else
enter_uid = 1;
if (comp -> hardware_addr.htype &&
((comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
(comp -> hardware_addr.htype !=
lease -> hardware_addr.htype) ||
memcmp (comp -> hardware_addr.haddr,
lease -> hardware_addr.haddr,
comp -> hardware_addr.hlen))) {
hw_hash_delete (comp);
enter_hwaddr = 1;
} else if (!comp -> hardware_addr.htype)
enter_hwaddr = 1;
/* 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;
} 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;
} else {
error ("corrupt lease uid."); /* XXX */
}
} else {
comp -> uid = (unsigned char *)0;
comp -> uid_max = 0;
}
comp -> uid_len = lease -> uid_len;
comp -> host = lease -> host;
comp -> hardware_addr = lease -> hardware_addr;
comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
(comp -> flags & ~EPHEMERAL_FLAGS));
/* Record the lease in the uid hash if necessary. */
if (enter_uid && lease -> uid) {
uid_hash_add (comp);
}
/* Record it in the hardware address hash if necessary. */
if (enter_hwaddr && lease -> hardware_addr.htype) {
hw_hash_add (comp);
}
/* Remove the lease from its current place in the
timeout sequence. */
if (comp -> prev) {
comp -> prev -> next = comp -> next;
} else {
comp -> shared_network -> leases = comp -> next;
}
if (comp -> next) {
comp -> next -> prev = comp -> prev;
}
if (comp -> shared_network -> last_lease == comp) {
comp -> shared_network -> last_lease = comp -> prev;
}
/* Find the last insertion point... */
if (comp == comp -> shared_network -> insertion_point ||
!comp -> shared_network -> insertion_point) {
lp = comp -> shared_network -> leases;
} else {
lp = comp -> shared_network -> insertion_point;
}
if (!lp) {
/* Nothing on the list yet? Just make comp the
head of the list. */
comp -> shared_network -> leases = comp;
comp -> shared_network -> last_lease = comp;
} else if (lp -> ends > lease -> ends) {
/* Skip down the list until we run out of list
or find a place for comp. */
while (lp -> next && lp -> ends > lease -> ends) {
lp = lp -> next;
}
if (lp -> ends > lease -> ends) {
/* If we ran out of list, put comp
at the end. */
lp -> next = comp;
comp -> prev = lp;
comp -> next = (struct lease *)0;
comp -> shared_network -> last_lease = comp;
} else {
/* If we didn't, put it between lp and
the previous item on the list. */
if ((comp -> prev = lp -> prev))
comp -> prev -> next = comp;
comp -> next = lp;
lp -> prev = comp;
}
} else {
/* Skip up the list until we run out of list
or find a place for comp. */
while (lp -> prev && lp -> ends < lease -> ends) {
lp = lp -> prev;
}
if (lp -> ends < lease -> ends) {
/* If we ran out of list, put comp
at the beginning. */
lp -> prev = comp;
comp -> next = lp;
comp -> prev = (struct lease *)0;
comp -> shared_network -> leases = comp;
} else {
/* If we didn't, put it between lp and
the next item on the list. */
if ((comp -> next = lp -> next))
comp -> next -> prev = comp;
comp -> prev = lp;
lp -> next = comp;
}
}
comp -> shared_network -> insertion_point = comp;
comp -> ends = lease -> ends;
}
/* Return zero if we didn't commit the lease to permanent storage;
nonzero if we did. */
return commit && write_lease (comp) && commit_leases ();
}
/* Release the specified lease and re-hash it as appropriate. */
void release_lease (struct _lease *lease)
{
struct _lease lt;
lt = *lease;
if (lt.ends > cur_time) {
lt.ends = cur_time;
supersede_lease (lease, <, 1);
}
}
/* Abandon the specified lease (set its timeout to infinity and its
particulars to zero, and re-hash it as appropriate. */
void abandon_lease (struct _lease *lease, char *message)
{
struct _lease lt;
lease -> flags |= ABANDONED_LEASE;
lt = *lease;
lt.ends = cur_time;
warn ("Abandoning IP address %s: %s",
piaddr (lease -> ip_addr), message);
lt.hardware_addr.htype = 0;
lt.hardware_addr.hlen = 0;
lt.uid = (unsigned char *)0;
lt.uid_len = 0;
supersede_lease (lease, <, 1);
}
/* Locate the lease associated with a given IP address... */
lease *find_lease_by_ip_addr (iaddr addr)
{
lease *lease = (struct _lease *)hash_lookup (lease_ip_addr_hash,
addr.iabuf,
addr.len);
return lease;
}
lease *find_lease_by_uid (unsigned char *uid, int len)
{
lease *lease = (struct lease *)hash_lookup (lease_uid_hash,
uid, len);
return lease;
}
lease *find_lease_by_hw_addr (unsigned char *hwaddr, int hwlen)
{
struct _lease *lease =
(struct _lease *)hash_lookup (lease_hw_addr_hash,
hwaddr, hwlen);
return lease;
}
/* Add the specified lease to the uid hash. */
void uid_hash_add (lease *lease)
{
struct _lease *head = find_lease_by_uid (lease -> uid, lease -> uid_len);
struct _lease *scan;
#ifdef DEBUG
if (lease -> n_uid)
abort ();
#endif
/* If it's not in the hash, just add it. */
if (!head)
add_hash (lease_uid_hash, lease -> uid,
lease -> uid_len, (unsigned char *)lease);
else {
/* Otherwise, attach it to the end of the list. */
for (scan = head; scan -> n_uid; scan = scan -> n_uid)
#ifdef DEBUG
if (scan == lease)
abort ()
#endif
;
scan -> n_uid = lease;
}
}
/* Delete the specified lease from the uid hash. */
void uid_hash_delete (lease *lease)
{
struct _lease *head =
find_lease_by_uid (lease -> uid, lease -> uid_len);
struct _lease *scan;
/* If it's not in the hash, we have no work to do. */
if (!head) {
lease -> n_uid = (struct lease *)0;
return;
}
/* If the lease we're freeing is at the head of the list,
remove the hash table entry and add a new one with the
next lease on the list (if there is one). */
if (head == lease) {
delete_hash_entry (lease_uid_hash,
lease -> uid, lease -> uid_len);
if (lease -> n_uid)
add_hash (lease_uid_hash,
lease -> n_uid -> uid,
lease -> n_uid -> uid_len,
(unsigned char *)(lease -> n_uid));
} else {
/* Otherwise, look for the lease in the list of leases
attached to the hash table entry, and remove it if
we find it. */
for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
if (scan -> n_uid == lease) {
scan -> n_uid = scan -> n_uid -> n_uid;
break;
}
}
}
lease -> n_uid = (struct lease *)0;
}
/* Add the specified lease to the hardware address hash. */
void hw_hash_add (lease *lease)
{
struct _lease *head =
find_lease_by_hw_addr (lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen);
struct _lease *scan;
/* If it's not in the hash, just add it. */
if (!head)
add_hash (lease_hw_addr_hash,
lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen,
(unsigned char *)lease);
else {
/* Otherwise, attach it to the end of the list. */
for (scan = head; scan -> n_hw; scan = scan -> n_hw)
;
scan -> n_hw = lease;
}
}
/* Delete the specified lease from the hardware address hash. */
void hw_hash_delete (lease *lease)
{
struct _lease *head =
find_lease_by_hw_addr (lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen);
struct _lease *scan;
/* If it's not in the hash, we have no work to do. */
if (!head) {
lease -> n_hw = (struct lease *)0;
return;
}
/* If the lease we're freeing is at the head of the list,
remove the hash table entry and add a new one with the
next lease on the list (if there is one). */
if (head == lease) {
delete_hash_entry (lease_hw_addr_hash,
lease -> hardware_addr.haddr,
lease -> hardware_addr.hlen);
if (lease -> n_hw)
add_hash (lease_hw_addr_hash,
lease -> n_hw -> hardware_addr.haddr,
lease -> n_hw -> hardware_addr.hlen,
(unsigned char *)(lease -> n_hw));
} else {
/* Otherwise, look for the lease in the list of leases
attached to the hash table entry, and remove it if
we find it. */
for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
if (scan -> n_hw == lease) {
scan -> n_hw = scan -> n_hw -> n_hw;
break;
}
}
}
lease -> n_hw = (struct lease *)0;
}
struct class *add_class (type, name)
int type;
char *name;
{
struct class *class = new_class ("add_class");
char *tname = (char *)malloc (strlen (name) + 1);
if (!vendor_class_hash)
vendor_class_hash = new_hash ();
if (!user_class_hash)
user_class_hash = new_hash ();
if (!tname || !class || !vendor_class_hash || !user_class_hash)
return (struct class *)0;
memset (class, 0, sizeof *class);
strcpy (tname, name);
class -> name = tname;
if (type)
add_hash (user_class_hash,
(unsigned char *)tname, strlen (tname),
(unsigned char *)class);
else
add_hash (vendor_class_hash,
(unsigned char *)tname, strlen (tname),
(unsigned char *)class);
return class;
}
struct class *find_class (type, name, len)
int type;
unsigned char *name;
int len;
{
struct class *class =
(struct class *)hash_lookup (type
? user_class_hash
: vendor_class_hash, name, len);
return class;
}
struct group *clone_group (group, caller)
struct group *group;
char *caller;
{
struct group *g = new_group (caller);
if (!g)
error ("%s: can't allocate new group", caller);
*g = *group;
return g;
}
/* Write all interesting leases to permanent storage. */
void write_leases ()
{
lease *l;
shared_network *s;
for (s = shared_networks; s; s = (shared_network *)s -> next) {
for (l = s -> leases; l; l = l -> next) {
if (l -> hardware_addr.hlen ||
l -> uid_len ||
(l -> flags & ABANDONED_LEASE))
if (!write_lease (l))
error ("Can't rewrite lease database");
}
}
if (!commit_leases ())
error ("Can't commit leases to new database: %m");
}
void dump_subnets ()
{
struct _lease *l;
shared_network *s;
subnet *n;
note ("Subnets:");
for (n = subnets; n; n = n -> next_subnet) {
debug (" Subnet %s", piaddr (n -> net));
debug (" netmask %s",
piaddr (n -> netmask));
}
note ("Shared networks:");
for (s = shared_networks; s; s = (shared_network *)s -> next) {
note (" %s", s -> name);
for (l = s -> leases; l; l = l -> next) {
print_lease (l);
}
if (s -> last_lease) {
debug (" Last Lease:");
print_lease (s -> last_lease);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -