#ifndef lint
static char copyright[] =
-"$Id: dhcp.c,v 1.101 1999/07/13 18:00:22 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
+"$Id: dhcp.c,v 1.102 1999/07/18 19:39:14 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
#if defined (NSUPDATE)
nsupdate (lease, lease -> state, packet, DELETE);
#endif
+ /* If there are statements to execute when the lease is
+ committed, execute them. */
+ if (lease -> on_release) {
+ execute_statements (packet, lease, packet -> options,
+ state -> options,
+ lease -> on_release);
+ executable_statement_dereference (&lease -> on_release,
+ "dhcprelease");
+ }
release_lease (lease);
}
}
(lease -> pool
? lease -> pool -> group
: lease -> subnet -> group));
-
+
/* See if the client is only supposed to have one lease at a time,
and if so, find its other leases and release them. We can only
do this on DHCPREQUEST. It's a little weird to do this before
log_info ("%s: %d secs < %d",
packet -> raw -> secs, d1.data [0]);
free_lease_state (state, "ack_lease");
+ static_lease_dereference (lease, "ack_lease");
return;
}
data_string_forget (&d1, "ack_lease");
log_info ("%s: unknown", msg);
data_string_forget (&d1, "ack_lease");
free_lease_state (state, "ack_lease");
+ static_lease_dereference (lease, "ack_lease");
return;
}
data_string_forget (&d1, "ack_lease"); /* mmm, C... */
data_string_forget (&d1, "ack_lease");
log_info ("%s: bootp disallowed", msg);
free_lease_state (state, "ack_lease");
+ static_lease_dereference (lease, "ack_lease");
return;
}
data_string_forget (&d1, "ack_lease");
log_info ("%s: booting disallowed", msg);
data_string_forget (&d1, "ack_lease");
free_lease_state (state, "ack_lease");
+ static_lease_dereference (lease, "ack_lease");
return;
}
data_string_forget (&d1, "ack_lease");
log_info ("%s: no available billing",
msg);
free_lease_state (state, "ack_lease");
+ /* XXX probably not necessary: */
+ static_lease_dereference (lease,
+ "ack_lease");
return;
}
}
nsupdate (lease, state, packet, ADD);
#endif
+ /* If there are statements to execute when the lease is
+ committed, execute them. */
+ if (lease -> on_commit && (!offer || offer == DHCPACK)) {
+ execute_statements (packet, lease, packet -> options,
+ state -> options, lease -> on_commit);
+ executable_statement_dereference (&lease -> on_commit,
+ "ack_lease");
+ }
+
/* Don't call supersede_lease on a mocked-up lease. */
if (lease -> flags & STATIC_LEASE) {
/* Copy the hardware address into the static lease
|| (offer && offer != DHCPACK))) {
log_info ("%s: database update failed", msg);
free_lease_state (state, "ack_lease");
+ static_lease_dereference (lease, "ack_lease");
return;
}
}
++outstanding_pings;
} else {
lease -> timestamp = cur_time;
+ static_lease_dereference (lease, "ack_lease");
dhcp_reply (lease);
}
}
return &mock;
}
+/* Dereference all dynamically-allocated information that may be dangling
+ off of a static lease. Otherwise, once ack_lease returns, the information
+ dangling from the lease will be lost, so reference counts will be screwed
+ up and memory leaks will occur. */
+
+void static_lease_dereference (lease, name)
+ struct lease *lease;
+ char *name;
+{
+ if (!(lease -> flags & STATIC_LEASE))
+ return;
+ if (lease -> on_release)
+ executable_statement_dereference (&lease -> on_release, name);
+ if (lease -> on_expiry)
+ executable_statement_dereference (&lease -> on_expiry, name);
+ if (lease -> on_commit)
+ executable_statement_dereference (&lease -> on_commit, name);
+}
+
/* Look through all the pools in a list starting with the specified pool
for a free lease. We try to find a virgin lease if we can. If we
don't find a virgin lease, we try to find a non-virgin lease that's