#ifndef lint
static char copyright[] =
-"$Id: options.c,v 1.50 2000/01/08 01:35:06 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+"$Id: options.c,v 1.51 2000/01/25 01:09:06 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#define DHCP_OPTION_DATA
struct option_cache *op = (struct option_cache *)0;
/* Allocate a new option state. */
- if (!option_state_allocate (&packet -> options, "parse_options")) {
+ if (!option_state_allocate (&packet -> options, MDL)) {
packet -> options_valid = 0;
return 0;
}
struct option_cache *op = (struct option_cache *)0;
struct buffer *bp = (struct buffer *)0;
- if (!buffer_allocate (&bp, length, "parse_option_buffer")) {
+ if (!buffer_allocate (&bp, length, MDL)) {
log_error ("no memory for option buffer.");
return 0;
}
if (offset + len + 2 > length) {
log_error ("Client option %s (%d) larger than buffer.",
dhcp_options [code].name, len);
- buffer_dereference (&bp, "parse_option_buffer");
+ buffer_dereference (&bp, MDL);
return 0;
}
if (!parse_agent_information_option
(packet, len, buffer + offset + 2)) {
log_error ("bad agent information option.");
- buffer_dereference (&bp,
- "parse_option_buffer");
+ buffer_dereference (&bp, MDL);
return 0;
}
} else {
- if (!option_cache_allocate (&op,
- "parse_option_buffer")) {
+ if (!option_cache_allocate (&op, MDL)) {
log_error ("No memory for option %s.",
dhcp_options [code].name);
- buffer_dereference (&bp,
- "parse_option_buffer");
+ buffer_dereference (&bp, MDL);
return 0;
}
/* Reference buffer copy to option cache. */
op -> data.buffer = (struct buffer *)0;
- buffer_reference (&op -> data.buffer, bp,
- "parse_option_buffer");
+ buffer_reference (&op -> data.buffer, bp, MDL);
/* Point option cache into buffer. */
op -> data.data = &bp -> data [offset + 2];
save_option (&dhcp_universe, packet -> options, op);
/* And let go of our reference. */
- option_cache_dereference (&op,
- "parse_option_buffer");
+ option_cache_dereference (&op, MDL);
}
offset += len + 2;
}
packet -> options_valid = 1;
- buffer_dereference (&bp, "parse_option_buffer");
+ buffer_dereference (&bp, MDL);
return 1;
}
of vendor options using the same routine. */
int cons_options (inpacket, outpacket, lease, mms, in_options, cfg_options,
- overload, terminate, bootpp, prl)
+ scope, overload, terminate, bootpp, prl)
struct packet *inpacket;
struct dhcp_packet *outpacket;
struct lease *lease;
int mms;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
int overload; /* Overload flags that may be set. */
int terminate;
int bootpp;
if (!mms && inpacket &&
(op = lookup_option (&dhcp_universe, inpacket -> options,
DHO_DHCP_MAX_MESSAGE_SIZE))) {
- evaluate_option_cache (&ds, inpacket, lease,
- in_options, cfg_options, op);
+ evaluate_option_cache (&ds, inpacket, lease, in_options,
+ cfg_options, scope, op, MDL);
if (ds.len >= sizeof (u_int16_t))
mms = getUShort (ds.data);
- data_string_forget (&ds, "cons_options");
+ data_string_forget (&ds, MDL);
}
/* If the client has provided a maximum DHCP message size,
((overload & 2) ? DHCP_SNAME_LEN : 0)),
inpacket,
lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
priority_list, priority_len,
main_buffer_size,
(main_buffer_size +
/* Store all the requested options into the requested buffer. */
int store_options (buffer, buflen, packet, lease,
- in_options, cfg_options, priority_list,
+ in_options, cfg_options, scope, priority_list,
priority_len, first_cutoff, second_cutoff, terminate)
unsigned char *buffer;
unsigned buflen;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
unsigned *priority_list;
int priority_len;
unsigned first_cutoff, second_cutoff;
}
/* Find the value of the option... */
- evaluate_option_cache (&od, packet, lease,
- in_options, cfg_options, oc);
+ evaluate_option_cache (&od, packet, lease, in_options,
+ cfg_options, scope, oc, MDL);
if (!od.len) {
continue;
}
ix += incr;
bufix += 2 + incr;
}
- data_string_forget (&od, "store_options");
+ data_string_forget (&od, MDL);
}
return bufix;
}
!isprint (data [k]))
break;
}
- if (k == len) {
+ /* If we found no bogus characters, or the bogus
+ character we found is a trailing NUL, it's
+ okay to print this option as text. */
+ if (k == len || (k + 1 == len && data [k] == 0)) {
fmtbuf [i] = 't';
numhunk = -2;
} else {
}
int hashed_option_get (result, universe, packet, lease,
- in_options, cfg_options, options, code)
+ in_options, cfg_options, options, scope, code)
struct data_string *result;
struct universe *universe;
struct packet *packet;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_state *options;
+ struct binding_scope *scope;
unsigned code;
{
struct option_cache *oc;
oc = ((*universe -> lookup_func) (universe, options, code));
if (!oc)
return 0;
- if (!evaluate_option_cache (result, packet, lease,
- in_options, cfg_options, oc))
+ if (!evaluate_option_cache (result, packet, lease, in_options,
+ cfg_options, scope, oc, MDL))
return 0;
return 1;
}
int agent_option_get (result, universe, packet, lease,
- in_options, cfg_options, options, code)
+ in_options, cfg_options, options, scope, code)
struct data_string *result;
struct universe *universe;
struct packet *packet;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_state *options;
+ struct binding_scope *scope;
unsigned code;
{
struct agent_options *ao;
for (t = ao -> first; t; t = t -> next) {
if (t -> data [0] == code) {
result -> len = t -> data [1];
- if (!(buffer_allocate
- (&result -> buffer, result -> len + 1,
- "agent_suboption_get"))) {
+ if (!(buffer_allocate (&result -> buffer,
+ result -> len + 1,
+ MDL))) {
result -> len = 0;
buffer_dereference
- (&result -> buffer,
- "agent_suboption_get");
+ (&result -> buffer, MDL);
return 0;
}
result -> data = &result -> buffer -> data [0];
}
/* If it's not an expression, make it into one. */
if (!oc -> expression && oc -> data.len) {
- if (!expression_allocate (&oc -> expression,
- "do_option_set")) {
+ if (!expression_allocate (&oc -> expression, MDL)) {
log_error ("Can't allocate const expression.");
break;
}
oc -> expression -> op = expr_const_data;
data_string_copy
(&oc -> expression -> data.const_data,
- &oc -> data, "do_option_set");
- data_string_forget (&oc -> data, "do_option_set");
+ &oc -> data, MDL);
+ data_string_forget (&oc -> data, MDL);
}
noc = (struct option_cache *)0;
- if (!option_cache_allocate (&noc, "do_option_set"))
+ if (!option_cache_allocate (&noc, MDL))
break;
if (op == append_option_statement) {
if (!make_concat (&noc -> expression,
oc -> expression,
option -> expression)) {
- option_cache_dereference (&noc,
- "do_option_set");
+ option_cache_dereference (&noc, MDL);
break;
}
} else {
if (!make_concat (&noc -> expression,
option -> expression,
oc -> expression)) {
- option_cache_dereference (&noc,
- "do_option_set");
+ option_cache_dereference (&noc, MDL);
break;
}
}
noc -> option = oc -> option;
save_option (universe, options, noc);
- option_cache_dereference (&noc, "do_option_set");
+ option_cache_dereference (&noc, MDL);
break;
}
}
/* If there's no hash table, make one. */
if (!hash) {
- hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash,
- "save_hashed_options");
+ hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL);
if (!hash) {
log_error ("no memory to store %s.%s",
universe -> name, oc -> option -> name);
in its place. */
if (bptr) {
option_cache_dereference
- ((struct option_cache **)&bptr -> car,
- "save_option");
+ ((struct option_cache **)&bptr -> car, MDL);
option_cache_reference
((struct option_cache **)&bptr -> car,
- oc, "save_option");
+ oc, MDL);
return;
}
}
/* Otherwise, just put the new one at the head of the list. */
- bptr = new_pair ("save_option");
+ bptr = new_pair (MDL);
if (!bptr) {
log_error ("No memory for option_cache reference.");
return;
}
bptr -> cdr = hash [hashix];
bptr -> car = 0;
- option_cache_reference ((struct option_cache **)&bptr -> car,
- oc, "save_option");
+ option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL);
hash [hashix] = bptr;
}
else
hash [hashix] = bptr -> cdr;
option_cache_dereference
- ((struct option_cache **)(&bptr -> car),
- "delete_option");
- free_pair (bptr, "delete_option");
+ ((struct option_cache **)(&bptr -> car), MDL);
+ free_pair (bptr, MDL);
}
}
extern struct option_cache *free_option_caches; /* XXX */
-int option_cache_dereference (ptr, name)
+int option_cache_dereference (ptr, file, line)
struct option_cache **ptr;
- const char *name;
+ const char *file;
+ int line;
{
if (!ptr || !*ptr) {
- log_error ("Null pointer in option_cache_dereference: %s",
- name);
+ log_error ("Null pointer in option_cache_dereference: %s(%d)",
+ file, line);
#if defined (POINTER_DEBUG)
abort ();
#else
}
(*ptr) -> refcnt--;
+ rc_register (file, line, *ptr, (*ptr) -> refcnt);
if (!(*ptr) -> refcnt) {
if ((*ptr) -> data.buffer)
data_string_forget (&(*ptr) -> data, name);
/* Put it back on the free list... */
(*ptr) -> expression = (struct expression *)free_option_caches;
free_option_caches = *ptr;
+ dmalloc_reuse (free_option_caches, (char *)0, 0, 0);
+ }
+ if ((*ptr) -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history ();
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
}
*ptr = (struct option_cache *)0;
return 1;
for (cp = heads [i]; cp; cp = next) {
next = cp -> cdr;
option_cache_dereference
- ((struct option_cache **)&cp -> car,
- "option_state_dereference");
- free_pair (cp, "hashed_option_state_dereference");
+ ((struct option_cache **)&cp -> car, MDL);
+ free_pair (cp, MDL);
}
}
- dfree (heads, "hashed_option_state_dereference");
+ dfree (heads, MDL);
state -> universes [universe -> index] = (void *)0;
return 1;
}
na = a -> next;
for (ot = a -> first; ot; ot = not) {
not = ot -> next;
- free (ot);
+ dfree (ot, MDL);
}
}
- dfree (state -> universes [universe -> index],
- "agent_option_state_dereference");
+ dfree (state -> universes [universe -> index], MDL);
state -> universes [universe -> index] = (void *)0;
return 1;
}
-int store_option (result, universe, packet, lease, in_options, cfg_options, oc)
+int store_option (result, universe, packet, lease,
+ in_options, cfg_options, scope, oc)
struct data_string *result;
struct universe *universe;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct option_cache *oc;
{
struct data_string d1, d2;
memset (&d1, 0, sizeof d1);
memset (&d2, 0, sizeof d2);
- if (evaluate_option_cache (&d2, packet, lease,
- in_options, cfg_options, oc)) {
+ if (evaluate_option_cache (&d2, packet, lease, in_options,
+ cfg_options, scope, oc, MDL)) {
if (!buffer_allocate (&d1.buffer,
(result -> len +
universe -> length_size +
- universe -> tag_size +
- d2.len), "store_option")) {
- data_string_forget (result, "store_option");
- data_string_forget (&d2, "store_option");
+ universe -> tag_size + d2.len), MDL)) {
+ data_string_forget (result, MDL);
+ data_string_forget (&d2, MDL);
return 0;
}
d1.data = &d1.buffer -> data [0];
d1.len += universe -> length_size;
memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len);
d1.len += d2.len;
- data_string_forget (&d2, "store_option");
- data_string_forget (result, "store_option");
- data_string_copy (result, &d1, "store_option");
- data_string_forget (&d1, "store_option");
+ data_string_forget (&d2, MDL);
+ data_string_forget (result, MDL);
+ data_string_copy (result, &d1, MDL);
+ data_string_forget (&d1, MDL);
return 1;
}
return 0;
}
int option_space_encapsulate (result, packet, lease,
- in_options, cfg_options, name)
+ in_options, cfg_options, scope, name)
struct data_string *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct data_string *name;
{
struct universe *u;
if (u -> encapsulate)
return (*u -> encapsulate) (result, packet, lease,
- in_options, cfg_options, u);
+ in_options, cfg_options, scope, u);
log_error ("encapsulation requested for %s with no support.",
name -> data);
return 0;
}
int hashed_option_space_encapsulate (result, packet, lease,
- in_options, cfg_options, universe)
+ in_options, cfg_options, scope, universe)
struct data_string *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct universe *universe;
{
pair p, *hash;
for (i = 0; i < OPTION_HASH_SIZE; i++) {
for (p = hash [i]; p; p = p -> cdr) {
if (store_option (result, universe, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
(struct option_cache *)p -> car))
status = 1;
}
}
int nwip_option_space_encapsulate (result, packet, lease,
- in_options, cfg_options, universe)
+ in_options, cfg_options, scope, universe)
struct data_string *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct universe *universe;
{
pair p, *hash;
for (i = 0; hash && i < OPTION_HASH_SIZE; i++) {
for (p = hash [i]; p; p = p -> cdr) {
if (store_option (result, universe, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
(struct option_cache *)p -> car))
status = 1;
}
memset (&ds, 0, sizeof ds);
ds.data = nni;
ds.len = 2;
- if (option_cache_allocate
- (&no_nwip, "nwip_option_space_encapsulate")) {
- data_string_copy
- (&no_nwip -> data, &ds,
- "nwip_option_space_encapsulate");
- }
+ if (option_cache_allocate (&no_nwip, MDL))
+ data_string_copy (&no_nwip -> data, &ds, MDL);
+ no_nwip -> option = nwip_universe.options [1];
}
if (no_nwip) {
if (store_option (result, universe, packet, lease,
in_options, cfg_options,
- (struct option_cache *)p -> car))
+ scope, no_nwip))
status = 1;
}
} else {
/* If we have nwip options, the first one has to be the
nwip-exists-in-option-area option. */
- if (!buffer_allocate (&ds.buffer, result -> len + 2,
- "nwip_option_space_encapsulate")) {
- data_string_forget (result,
- "nwip_option_space_encapsulate");
+ if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) {
+ data_string_forget (result, MDL);
return 0;
}
ds.data = &ds.buffer -> data [0];
ds.buffer -> data [0] = 2;
ds.buffer -> data [1] = 0;
memcpy (&ds.buffer -> data [2], result -> data, result -> len);
- data_string_forget (result, "nwip_option_space_encapsulate");
- data_string_copy (result, &ds,
- "nwip_option_space_encapsulate");
- data_string_forget (&ds, "nwip_option_space_encapsulate");
+ data_string_forget (result, MDL);
+ data_string_copy (result, &ds, MDL);
+ data_string_forget (&ds, MDL);
}
return status;
int i;
struct option_cache *op;
struct packet *decoded_packet;
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ unsigned long previous_outstanding = dmalloc_outstanding;
+#endif
decoded_packet = (struct packet *)0;
- if (!packet_allocate (&decoded_packet, "do_packet")) {
+ if (!packet_allocate (&decoded_packet, MDL)) {
log_error ("do_packet: no memory for incoming packet!");
return;
}
decoded_packet -> haddr = hfrom;
if (packet -> hlen > sizeof packet -> chaddr) {
- packet_dereference (&decoded_packet, "do_packet");
+ packet_dereference (&decoded_packet, MDL);
log_info ("Discarding packet with bogus hlen.");
return;
}
if (!parse_options (decoded_packet)) {
if (decoded_packet -> options)
option_state_dereference
- (&decoded_packet -> options,
- "do_packet");
- packet_dereference (&decoded_packet, "do_packet");
+ (&decoded_packet -> options, MDL);
+ packet_dereference (&decoded_packet, MDL);
return;
}
evaluate_option_cache (&dp, decoded_packet,
(struct lease *)0,
decoded_packet -> options,
- (struct option_state *)0, op);
+ (struct option_state *)0,
+ (struct binding_scope *)0,
+ op, MDL);
if (dp.len > 0)
decoded_packet -> packet_type = dp.data [0];
else
decoded_packet -> packet_type = 0;
- data_string_forget (&dp, "do_packet");
+ data_string_forget (&dp, MDL);
}
}
else
bootp (decoded_packet);
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
+ dmalloc_generation,
+ dmalloc_outstanding - previous_outstanding,
+ dmalloc_outstanding, dmalloc_longterm);
+#endif
+#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL)
+ dmalloc_dump_outstanding ();
+#endif
/* If the caller kept the packet, they'll have upped the refcnt. */
- packet_dereference (&decoded_packet, "do_packet");
+ packet_dereference (&decoded_packet, MDL);
}