Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / common / options.c
blob260e4dcef6cdd6d28cb1fc094df6aa4bbee8cd7c
1 /* options.c
3 DHCP options parsing and reassembly. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: options.c,v 1.6 2006/05/11 09:29:39 mrg Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #define DHCP_OPTION_DATA
41 #include "dhcpd.h"
42 #include <omapip/omapip_p.h>
44 struct option *vendor_cfg_option;
46 /* Parse all available options out of the specified packet. */
48 int parse_options (packet)
49 struct packet *packet;
51 struct option_cache *op = (struct option_cache *)0;
53 /* Allocate a new option state. */
54 if (!option_state_allocate (&packet -> options, MDL)) {
55 packet -> options_valid = 0;
56 return 0;
59 /* If we don't see the magic cookie, there's nothing to parse. */
60 if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
61 packet -> options_valid = 0;
62 return 1;
65 /* Go through the options field, up to the end of the packet
66 or the End field. */
67 if (!parse_option_buffer (packet -> options,
68 &packet -> raw -> options [4],
69 (packet -> packet_length -
70 DHCP_FIXED_NON_UDP - 4),
71 &dhcp_universe))
72 return 0;
74 /* If we parsed a DHCP Option Overload option, parse more
75 options out of the buffer(s) containing them. */
76 if (packet -> options_valid &&
77 (op = lookup_option (&dhcp_universe, packet -> options,
78 DHO_DHCP_OPTION_OVERLOAD))) {
79 if (op -> data.data [0] & 1) {
80 if (!parse_option_buffer
81 (packet -> options,
82 (unsigned char *)packet -> raw -> file,
83 sizeof packet -> raw -> file,
84 &dhcp_universe))
85 return 0;
87 if (op -> data.data [0] & 2) {
88 if (!parse_option_buffer
89 (packet -> options,
90 (unsigned char *)packet -> raw -> sname,
91 sizeof packet -> raw -> sname,
92 &dhcp_universe))
93 return 0;
96 packet -> options_valid = 1;
97 return 1;
100 /* Parse options out of the specified buffer, storing addresses of option
101 values in packet -> options and setting packet -> options_valid if no
102 errors are encountered. */
104 int parse_option_buffer (options, buffer, length, universe)
105 struct option_state *options;
106 const unsigned char *buffer;
107 unsigned length;
108 struct universe *universe;
110 unsigned len, offset;
111 int code;
112 struct option_cache *op = (struct option_cache *)0;
113 struct buffer *bp = (struct buffer *)0;
115 if (!buffer_allocate (&bp, length, MDL)) {
116 log_error ("no memory for option buffer.");
117 return 0;
119 memcpy (bp -> data, buffer, length);
121 for (offset = 0; buffer [offset] != DHO_END && offset < length; ) {
122 code = buffer [offset];
123 /* Pad options don't have a length - just skip them. */
124 if (code == DHO_PAD) {
125 ++offset;
126 continue;
129 /* Don't look for length if the buffer isn't that big. */
130 if (offset + 2 > length) {
131 len = 65536;
132 goto bogus;
135 /* All other fields (except end, see above) have a
136 one-byte length. */
137 len = buffer [offset + 1];
139 /* If the length is outrageous, the options are bad. */
140 if (offset + len + 2 > length) {
141 bogus:
142 log_error ("parse_option_buffer: option %s (%d) %s.",
143 dhcp_options [code].name, len,
144 "larger than buffer");
145 buffer_dereference (&bp, MDL);
146 return 0;
149 /* If the option contains an encapsulation, parse it. If
150 the parse fails, or the option isn't an encapsulation (by
151 far the most common case), or the option isn't entirely
152 an encapsulation, keep the raw data as well. */
153 if (universe -> options [code] &&
154 !((universe -> options [code] -> format [0] == 'e' ||
155 universe -> options [code] -> format [0] == 'E') &&
156 (parse_encapsulated_suboptions
157 (options, universe -> options [code],
158 buffer + offset + 2, len,
159 universe, (const char *)0)))) {
160 op = lookup_option (universe, options, code);
161 if (op) {
162 struct data_string new;
163 memset (&new, 0, sizeof new);
164 if (!buffer_allocate (&new.buffer, op -> data.len + len,
165 MDL)) {
166 log_error ("parse_option_buffer: No memory.");
167 return 0;
169 memcpy (new.buffer -> data, op -> data.data,
170 op -> data.len);
171 memcpy (&new.buffer -> data [op -> data.len],
172 &bp -> data [offset + 2], len);
173 new.len = op -> data.len + len;
174 new.data = new.buffer -> data;
175 data_string_forget (&op -> data, MDL);
176 data_string_copy (&op -> data, &new, MDL);
177 data_string_forget (&new, MDL);
178 } else {
179 save_option_buffer (universe, options, bp,
180 &bp -> data [offset + 2], len,
181 universe -> options [code], 1);
184 offset += len + 2;
186 buffer_dereference (&bp, MDL);
187 return 1;
190 /* If an option in an option buffer turns out to be an encapsulation,
191 figure out what to do. If we don't know how to de-encapsulate it,
192 or it's not well-formed, return zero; otherwise, return 1, indicating
193 that we succeeded in de-encapsulating it. */
195 struct universe *find_option_universe (struct option *eopt, const char *uname)
197 int i;
198 char *s, *t;
199 struct universe *universe = (struct universe *)0;
201 /* Look for the E option in the option format. */
202 s = strchr (eopt -> format, 'E');
203 if (!s) {
204 log_error ("internal encapsulation format error 1.");
205 return 0;
207 /* Look for the universe name in the option format. */
208 t = strchr (++s, '.');
209 /* If there was no trailing '.', or there's something after the
210 trailing '.', the option is bogus and we can't use it. */
211 if (!t || t [1]) {
212 log_error ("internal encapsulation format error 2.");
213 return 0;
215 if (t == s && uname) {
216 for (i = 0; i < universe_count; i++) {
217 if (!strcmp (universes [i] -> name, uname)) {
218 universe = universes [i];
219 break;
222 } else if (t != s) {
223 for (i = 0; i < universe_count; i++) {
224 if (strlen (universes [i] -> name) == t - s &&
225 !memcmp (universes [i] -> name,
226 s, (unsigned)(t - s))) {
227 universe = universes [i];
228 break;
232 return universe;
235 /* If an option in an option buffer turns out to be an encapsulation,
236 figure out what to do. If we don't know how to de-encapsulate it,
237 or it's not well-formed, return zero; otherwise, return 1, indicating
238 that we succeeded in de-encapsulating it. */
240 int parse_encapsulated_suboptions (struct option_state *options,
241 struct option *eopt,
242 const unsigned char *buffer,
243 unsigned len, struct universe *eu,
244 const char *uname)
246 int i;
247 struct universe *universe = find_option_universe (eopt, uname);
249 /* If we didn't find the universe, we can't do anything with it
250 right now (e.g., we can't decode vendor options until we've
251 decoded the packet and executed the scopes that it matches). */
252 if (!universe)
253 return 0;
255 /* If we don't have a decoding function for it, we can't decode
256 it. */
257 if (!universe -> decode)
258 return 0;
260 i = (*universe -> decode) (options, buffer, len, universe);
262 /* If there is stuff before the suboptions, we have to keep it. */
263 if (eopt -> format [0] != 'E')
264 return 0;
265 /* Otherwise, return the status of the decode function. */
266 return i;
269 int fqdn_universe_decode (struct option_state *options,
270 const unsigned char *buffer,
271 unsigned length, struct universe *u)
273 struct buffer *bp = (struct buffer *)0;
275 /* FQDN options have to be at least four bytes long. */
276 if (length < 3)
277 return 0;
279 /* Save the contents of the option in a buffer. */
280 if (!buffer_allocate (&bp, length + 4, MDL)) {
281 log_error ("no memory for option buffer.");
282 return 0;
284 memcpy (&bp -> data [3], buffer + 1, length - 1);
286 if (buffer [0] & 4) /* encoded */
287 bp -> data [0] = 1;
288 else
289 bp -> data [0] = 0;
290 if (!save_option_buffer (&fqdn_universe, options, bp,
291 &bp -> data [0], 1,
292 &fqdn_options [FQDN_ENCODED], 0)) {
293 bad:
294 buffer_dereference (&bp, MDL);
295 return 0;
298 if (buffer [0] & 1) /* server-update */
299 bp -> data [2] = 1;
300 else
301 bp -> data [2] = 0;
302 if (buffer [0] & 2) /* no-client-update */
303 bp -> data [1] = 1;
304 else
305 bp -> data [1] = 0;
307 /* XXX Ideally we should store the name in DNS format, so if the
308 XXX label isn't in DNS format, we convert it to DNS format,
309 XXX rather than converting labels specified in DNS format to
310 XXX the plain ASCII representation. But that's hard, so
311 XXX not now. */
313 /* Not encoded using DNS format? */
314 if (!bp -> data [0]) {
315 unsigned i;
317 /* Some broken clients NUL-terminate this option. */
318 if (buffer [length - 1] == 0) {
319 --length;
320 bp -> data [1] = 1;
323 /* Determine the length of the hostname component of the
324 name. If the name contains no '.' character, it
325 represents a non-qualified label. */
326 for (i = 3; i < length && buffer [i] != '.'; i++);
327 i -= 3;
329 /* Note: If the client sends a FQDN, the first '.' will
330 be used as a NUL terminator for the hostname. */
331 if (i)
332 if (!save_option_buffer (&fqdn_universe, options, bp,
333 &bp -> data[5], i,
334 &fqdn_options [FQDN_HOSTNAME],
336 goto bad;
337 /* Note: If the client sends a single label, the
338 FQDN_DOMAINNAME option won't be set. */
339 if (length > 4 + i &&
340 !save_option_buffer (&fqdn_universe, options, bp,
341 &bp -> data[6 + i], length - 4 - i,
342 &fqdn_options [FQDN_DOMAINNAME], 1))
343 goto bad;
344 /* Also save the whole name. */
345 if (length > 3)
346 if (!save_option_buffer (&fqdn_universe, options, bp,
347 &bp -> data [5], length - 3,
348 &fqdn_options [FQDN_FQDN], 1))
349 goto bad;
350 } else {
351 unsigned len;
352 unsigned total_len = 0;
353 unsigned first_len = 0;
354 int terminated = 0;
355 unsigned char *s;
357 s = &bp -> data[5];
359 while (s < &bp -> data[0] + length + 2) {
360 len = *s;
361 if (len > 63) {
362 log_info ("fancy bits in fqdn option");
363 return 0;
365 if (len == 0) {
366 terminated = 1;
367 break;
369 if (s + len > &bp -> data [0] + length + 3) {
370 log_info ("fqdn tag longer than buffer");
371 return 0;
374 if (first_len == 0) {
375 first_len = len;
378 *s = '.';
379 s += len + 1;
380 total_len += len + 1;
383 /* We wind up with a length that's one too many because
384 we shouldn't increment for the last label, but there's
385 no way to tell we're at the last label until we exit
386 the loop. :'*/
387 if (total_len > 0)
388 total_len--;
390 if (!terminated) {
391 first_len = total_len;
394 if (first_len > 0 &&
395 !save_option_buffer (&fqdn_universe, options, bp,
396 &bp -> data[6], first_len,
397 &fqdn_options [FQDN_HOSTNAME], 0))
398 goto bad;
399 if (total_len > 0 && first_len != total_len) {
400 if (!save_option_buffer
401 (&fqdn_universe, options, bp,
402 &bp -> data[6 + first_len], total_len - first_len,
403 &fqdn_options [FQDN_DOMAINNAME], 1))
404 goto bad;
406 if (total_len > 0)
407 if (!save_option_buffer (&fqdn_universe, options, bp,
408 &bp -> data [6], total_len,
409 &fqdn_options [FQDN_FQDN], 1))
410 goto bad;
413 if (!save_option_buffer (&fqdn_universe, options, bp,
414 &bp -> data [1], 1,
415 &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
416 goto bad;
417 if (!save_option_buffer (&fqdn_universe, options, bp,
418 &bp -> data [2], 1,
419 &fqdn_options [FQDN_SERVER_UPDATE], 0))
420 goto bad;
422 if (!save_option_buffer (&fqdn_universe, options, bp,
423 &bp -> data [3], 1,
424 &fqdn_options [FQDN_RCODE1], 0))
425 goto bad;
426 if (!save_option_buffer (&fqdn_universe, options, bp,
427 &bp -> data [4], 1,
428 &fqdn_options [FQDN_RCODE2], 0))
429 goto bad;
431 buffer_dereference (&bp, MDL);
432 return 1;
435 /* cons options into a big buffer, and then split them out into the
436 three seperate buffers if needed. This allows us to cons up a set
437 of vendor options using the same routine. */
439 int cons_options (inpacket, outpacket, lease, client_state,
440 mms, in_options, cfg_options,
441 scope, overload, terminate, bootpp, prl, vuname)
442 struct packet *inpacket;
443 struct dhcp_packet *outpacket;
444 struct lease *lease;
445 struct client_state *client_state;
446 int mms;
447 struct option_state *in_options;
448 struct option_state *cfg_options;
449 struct binding_scope **scope;
450 int overload; /* Overload flags that may be set. */
451 int terminate;
452 int bootpp;
453 struct data_string *prl;
454 const char *vuname;
456 #define PRIORITY_COUNT 300
457 unsigned priority_list [PRIORITY_COUNT];
458 int priority_len;
459 unsigned char buffer [4096]; /* Really big buffer... */
460 unsigned main_buffer_size;
461 unsigned mainbufix, bufix, agentix;
462 int fileix;
463 int snameix;
464 unsigned option_size;
465 unsigned length;
466 int i;
467 struct option_cache *op;
468 struct data_string ds;
469 pair pp, *hash;
470 int need_endopt = 0;
471 int ocount = 0;
472 int ofbuf1=0, ofbuf2=0;
474 memset (&ds, 0, sizeof ds);
476 /* If there's a Maximum Message Size option in the incoming packet
477 and no alternate maximum message size has been specified, take the
478 one in the packet. */
480 if (inpacket &&
481 (op = lookup_option (&dhcp_universe, inpacket -> options,
482 DHO_DHCP_MAX_MESSAGE_SIZE))) {
483 evaluate_option_cache (&ds, inpacket,
484 lease, client_state, in_options,
485 cfg_options, scope, op, MDL);
486 if (ds.len >= sizeof (u_int16_t)) {
487 i = getUShort (ds.data);
489 if(!mms || (i < mms))
490 mms = i;
492 data_string_forget (&ds, MDL);
495 /* If the client has provided a maximum DHCP message size,
496 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
497 use up to the minimum IP MTU size (576 bytes). */
498 /* XXX if a BOOTP client specifies a max message size, we will
499 honor it. */
501 if (mms) {
502 main_buffer_size = mms - DHCP_FIXED_LEN;
504 /* Enforce a minimum packet size... */
505 if (main_buffer_size < (576 - DHCP_FIXED_LEN))
506 main_buffer_size = 576 - DHCP_FIXED_LEN;
507 } else if (bootpp) {
508 if (inpacket) {
509 main_buffer_size =
510 inpacket -> packet_length - DHCP_FIXED_LEN;
511 if (main_buffer_size < 64)
512 main_buffer_size = 64;
513 } else
514 main_buffer_size = 64;
515 } else
516 main_buffer_size = 576 - DHCP_FIXED_LEN;
518 /* Set a hard limit at the size of the output buffer. */
519 if (main_buffer_size > sizeof buffer)
520 main_buffer_size = sizeof buffer;
522 /* Preload the option priority list with mandatory options. */
523 priority_len = 0;
524 priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE;
525 priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
526 priority_list [priority_len++] = DHO_DHCP_LEASE_TIME;
527 priority_list [priority_len++] = DHO_DHCP_MESSAGE;
528 priority_list [priority_len++] = DHO_DHCP_REQUESTED_ADDRESS;
529 priority_list [priority_len++] = DHO_FQDN;
531 if (prl && prl -> len > 0) {
532 if ((op = lookup_option (&dhcp_universe, cfg_options,
533 DHO_SUBNET_SELECTION))) {
534 if (priority_len < PRIORITY_COUNT)
535 priority_list [priority_len++] =
536 DHO_SUBNET_SELECTION;
539 data_string_truncate (prl, (PRIORITY_COUNT - priority_len));
541 for (i = 0; i < prl -> len; i++) {
542 /* Prevent client from changing order of delivery
543 of relay agent information option. */
544 if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS)
545 priority_list [priority_len++] =
546 prl -> data [i];
548 } else {
549 /* First, hardcode some more options that ought to be
550 sent first... */
551 priority_list [priority_len++] = DHO_SUBNET_MASK;
552 priority_list [priority_len++] = DHO_ROUTERS;
553 priority_list [priority_len++] = DHO_DOMAIN_NAME_SERVERS;
554 priority_list [priority_len++] = DHO_HOST_NAME;
556 /* Append a list of the standard DHCP options from the
557 standard DHCP option space. Actually, if a site
558 option space hasn't been specified, we wind up
559 treating the dhcp option space as the site option
560 space, and the first for loop is skipped, because
561 it's slightly more general to do it this way,
562 taking the 1Q99 DHCP futures work into account. */
563 if (cfg_options -> site_code_min) {
564 for (i = 0; i < OPTION_HASH_SIZE; i++) {
565 hash = cfg_options -> universes [dhcp_universe.index];
566 if (hash) {
567 for (pp = hash [i]; pp; pp = pp -> cdr) {
568 op = (struct option_cache *)(pp -> car);
569 if (op -> option -> code <
570 cfg_options -> site_code_min &&
571 priority_len < PRIORITY_COUNT &&
572 (op -> option -> code !=
573 DHO_DHCP_AGENT_OPTIONS))
574 priority_list [priority_len++] =
575 op -> option -> code;
581 /* Now cycle through the site option space, or if there
582 is no site option space, we'll be cycling through the
583 dhcp option space. */
584 for (i = 0; i < OPTION_HASH_SIZE; i++) {
585 hash = (cfg_options -> universes
586 [cfg_options -> site_universe]);
587 if (hash)
588 for (pp = hash [i]; pp; pp = pp -> cdr) {
589 op = (struct option_cache *)(pp -> car);
590 if (op -> option -> code >=
591 cfg_options -> site_code_min &&
592 priority_len < PRIORITY_COUNT &&
593 (op -> option -> code !=
594 DHO_DHCP_AGENT_OPTIONS))
595 priority_list [priority_len++] =
596 op -> option -> code;
600 /* Now go through all the universes for which options
601 were set and see if there are encapsulations for
602 them; if there are, put the encapsulation options
603 on the priority list as well. */
604 for (i = 0; i < cfg_options -> universe_count; i++) {
605 if (cfg_options -> universes [i] &&
606 universes [i] -> enc_opt &&
607 priority_len < PRIORITY_COUNT &&
608 universes [i] -> enc_opt -> universe == &dhcp_universe)
610 if (universes [i] -> enc_opt -> code !=
611 DHO_DHCP_AGENT_OPTIONS)
612 priority_list [priority_len++] =
613 universes [i] -> enc_opt -> code;
617 /* The vendor option space can't stand on its own, so always
618 add it to the list. */
619 if (priority_len < PRIORITY_COUNT)
620 priority_list [priority_len++] =
621 DHO_VENDOR_ENCAPSULATED_OPTIONS;
624 /* Figure out the overload buffer offset(s). */
625 if (overload) {
626 ofbuf1 = main_buffer_size - 4;
627 if (overload == 3)
628 ofbuf2 = main_buffer_size - 4 + DHCP_FILE_LEN;
631 /* Copy the options into the big buffer... */
632 option_size = store_options (&ocount, buffer,
633 (main_buffer_size - 4 +
634 ((overload & 1) ? DHCP_FILE_LEN : 0) +
635 ((overload & 2) ? DHCP_SNAME_LEN : 0)),
636 inpacket, lease, client_state,
637 in_options, cfg_options, scope,
638 priority_list, priority_len,
639 ofbuf1, ofbuf2, terminate, vuname);
640 /* If store_options failed. */
641 if (option_size == 0)
642 return 0;
643 if (overload) {
644 if (ocount == 1 && (overload & 1))
645 overload = 1;
646 else if (ocount == 1 && (overload & 2))
647 overload = 2;
648 else if (ocount == 3)
649 overload = 3;
650 else
651 overload = 0;
654 /* Put the cookie up front... */
655 memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4);
656 mainbufix = 4;
658 /* If we're going to have to overload, store the overload
659 option at the beginning. If we can, though, just store the
660 whole thing in the packet's option buffer and leave it at
661 that. */
662 memcpy (&outpacket -> options [mainbufix],
663 buffer, option_size);
664 mainbufix += option_size;
665 if (overload) {
666 outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
667 outpacket -> options [mainbufix++] = 1;
668 outpacket -> options [mainbufix++] = overload;
670 if (overload & 1) {
671 memcpy (outpacket -> file,
672 &buffer [ofbuf1], DHCP_FILE_LEN);
674 if (overload & 2) {
675 if (ofbuf2) {
676 memcpy (outpacket -> sname, &buffer [ofbuf2],
677 DHCP_SNAME_LEN);
678 } else {
679 memcpy (outpacket -> sname, &buffer [ofbuf1],
680 DHCP_SNAME_LEN);
684 agentix = mainbufix;
685 if (mainbufix < main_buffer_size)
686 need_endopt = 1;
687 length = DHCP_FIXED_NON_UDP + mainbufix;
689 /* Now hack in the agent options if there are any. */
690 priority_list [0] = DHO_DHCP_AGENT_OPTIONS;
691 priority_len = 1;
692 agentix +=
693 store_options (0, &outpacket -> options [agentix],
694 1500 - DHCP_FIXED_LEN - agentix,
695 inpacket, lease, client_state,
696 in_options, cfg_options, scope,
697 priority_list, priority_len,
698 0, 0, 0, (char *)0);
700 /* Tack a DHO_END option onto the packet if we need to. */
701 if (agentix < 1500 - DHCP_FIXED_LEN && need_endopt)
702 outpacket -> options [agentix++] = DHO_END;
704 /* Figure out the length. */
705 length = DHCP_FIXED_NON_UDP + agentix;
706 return length;
709 /* Store all the requested options into the requested buffer. */
711 int store_options (ocount, buffer, buflen, packet, lease, client_state,
712 in_options, cfg_options, scope, priority_list, priority_len,
713 first_cutoff, second_cutoff, terminate, vuname)
714 int *ocount;
715 unsigned char *buffer;
716 unsigned buflen;
717 struct packet *packet;
718 struct lease *lease;
719 struct client_state *client_state;
720 struct option_state *in_options;
721 struct option_state *cfg_options;
722 struct binding_scope **scope;
723 unsigned *priority_list;
724 int priority_len;
725 unsigned first_cutoff, second_cutoff;
726 int terminate;
727 const char *vuname;
729 int bufix = 0, six = 0, tix = 0;
730 int i;
731 int ix;
732 int tto;
733 int bufend, sbufend;
734 struct data_string od;
735 struct option_cache *oc;
736 unsigned code;
738 if (first_cutoff) {
739 if (first_cutoff >= buflen)
740 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL);
742 bufend = first_cutoff;
743 } else
744 bufend = buflen;
746 if (second_cutoff) {
747 if (second_cutoff >= buflen)
748 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL);
750 sbufend = second_cutoff;
751 } else
752 sbufend = buflen;
754 memset (&od, 0, sizeof od);
756 /* Eliminate duplicate options in the parameter request list.
757 There's got to be some clever knuthian way to do this:
758 Eliminate all but the first occurance of a value in an array
759 of values without otherwise disturbing the order of the array. */
760 for (i = 0; i < priority_len - 1; i++) {
761 tto = 0;
762 for (ix = i + 1; ix < priority_len + tto; ix++) {
763 if (tto)
764 priority_list [ix - tto] =
765 priority_list [ix];
766 if (priority_list [i] == priority_list [ix]) {
767 tto++;
768 priority_len--;
773 /* Copy out the options in the order that they appear in the
774 priority list... */
775 for (i = 0; i < priority_len; i++) {
776 /* Number of bytes left to store (some may already
777 have been stored by a previous pass). */
778 unsigned length;
779 int optstart, soptstart, toptstart;
780 struct universe *u;
781 int have_encapsulation = 0;
782 struct data_string encapsulation;
783 int splitup;
785 memset (&encapsulation, 0, sizeof encapsulation);
787 /* Code for next option to try to store. */
788 code = priority_list [i];
790 /* Look up the option in the site option space if the code
791 is above the cutoff, otherwise in the DHCP option space. */
792 if (code >= cfg_options -> site_code_min)
793 u = universes [cfg_options -> site_universe];
794 else
795 u = &dhcp_universe;
797 oc = lookup_option (u, cfg_options, code);
799 /* It's an encapsulation, try to find the universe
800 to be encapsulated first, except that if it's a straight
801 encapsulation and the user has provided a value for the
802 encapsulation option, use the user-provided value. */
803 if (u -> options [code] &&
804 ((u -> options [code] -> format [0] == 'E' && !oc) ||
805 u -> options [code] -> format [0] == 'e')) {
806 static char *s, *t;
807 struct option_cache *tmp;
808 struct data_string name;
810 s = strchr (u -> options [code] -> format, 'E');
811 if (s)
812 t = strchr (++s, '.');
813 if (s && t) {
814 memset (&name, 0, sizeof name);
816 /* A zero-length universe name means the vendor
817 option space, if one is defined. */
818 if (t == s) {
819 if (vendor_cfg_option) {
820 tmp = lookup_option (vendor_cfg_option -> universe,
821 cfg_options,
822 vendor_cfg_option -> code);
823 if (tmp)
824 evaluate_option_cache (&name, packet, lease,
825 client_state,
826 in_options,
827 cfg_options,
828 scope, tmp, MDL);
829 } else if (vuname) {
830 name.data = (unsigned char *)s;
831 name.len = strlen (s);
833 } else {
834 name.data = (unsigned char *)s;
835 name.len = t - s;
838 /* If we found a universe, and there are options configured
839 for that universe, try to encapsulate it. */
840 if (name.len) {
841 have_encapsulation =
842 (option_space_encapsulate
843 (&encapsulation, packet, lease, client_state,
844 in_options, cfg_options, scope, &name));
845 data_string_forget (&name, MDL);
850 /* In order to avoid memory leaks, we have to get to here
851 with any option cache that we allocated in tmp not being
852 referenced by tmp, and whatever option cache is referenced
853 by oc being an actual reference. lookup_option doesn't
854 generate a reference (this needs to be fixed), so the
855 preceding goop ensures that if we *didn't* generate a new
856 option cache, oc still winds up holding an actual reference. */
858 /* If no data is available for this option, skip it. */
859 if (!oc && !have_encapsulation) {
860 continue;
863 /* Find the value of the option... */
864 if (oc) {
865 evaluate_option_cache (&od, packet,
866 lease, client_state, in_options,
867 cfg_options, scope, oc, MDL);
868 if (!od.len) {
869 data_string_forget (&encapsulation, MDL);
870 data_string_forget (&od, MDL);
871 have_encapsulation = 0;
872 continue;
876 /* We should now have a constant length for the option. */
877 length = od.len;
878 if (have_encapsulation) {
879 length += encapsulation.len;
880 if (!od.len) {
881 data_string_copy (&od, &encapsulation, MDL);
882 data_string_forget (&encapsulation, MDL);
883 } else {
884 struct buffer *bp = (struct buffer *)0;
885 if (!buffer_allocate (&bp, length, MDL)) {
886 option_cache_dereference (&oc, MDL);
887 data_string_forget (&od, MDL);
888 data_string_forget (&encapsulation, MDL);
889 continue;
891 memcpy (&bp -> data [0], od.data, od.len);
892 memcpy (&bp -> data [od.len], encapsulation.data,
893 encapsulation.len);
894 data_string_forget (&od, MDL);
895 data_string_forget (&encapsulation, MDL);
896 od.data = &bp -> data [0];
897 buffer_reference (&od.buffer, bp, MDL);
898 buffer_dereference (&bp, MDL);
899 od.len = length;
900 od.terminated = 0;
904 /* Do we add a NUL? */
905 if (terminate && dhcp_options [code].format [0] == 't') {
906 length++;
907 tto = 1;
908 } else {
909 tto = 0;
912 /* Try to store the option. */
914 /* If the option's length is more than 255, we must store it
915 in multiple hunks. Store 255-byte hunks first. However,
916 in any case, if the option data will cross a buffer
917 boundary, split it across that boundary. */
920 if (length > 255)
921 splitup = 1;
922 else
923 splitup = 0;
925 ix = 0;
926 optstart = bufix;
927 soptstart = six;
928 toptstart = tix;
929 while (length) {
930 unsigned incr = length;
931 int *pix;
932 u_char *base;
934 /* Try to fit it in the options buffer. */
935 if (!splitup &&
936 ((!six && !tix && (i == priority_len - 1) &&
937 (bufix + 2 + length < bufend)) ||
938 (bufix + 5 + length < bufend))) {
939 base = buffer;
940 pix = &bufix;
941 /* Try to fit it in the second buffer. */
942 } else if (!splitup && first_cutoff &&
943 (first_cutoff + six + 3 + length < sbufend)) {
944 base = &buffer[first_cutoff];
945 pix = &six;
946 /* Try to fit it in the third buffer. */
947 } else if (!splitup && second_cutoff &&
948 (second_cutoff + tix + 3 + length < buflen)) {
949 base = &buffer[second_cutoff];
950 pix = &tix;
951 /* Split the option up into the remaining space. */
952 } else {
953 splitup = 1;
955 /* Use any remaining options space. */
956 if (bufix + 6 < bufend) {
957 incr = bufend - bufix - 5;
958 base = buffer;
959 pix = &bufix;
960 /* Use any remaining first_cutoff space. */
961 } else if (first_cutoff &&
962 (first_cutoff + six + 4 < sbufend)) {
963 incr = sbufend - (first_cutoff + six) - 3;
964 base = &buffer[first_cutoff];
965 pix = &six;
966 /* Use any remaining second_cutoff space. */
967 } else if (second_cutoff &&
968 (second_cutoff + tix + 4 < buflen)) {
969 incr = buflen - (second_cutoff + tix) - 3;
970 base = &buffer[second_cutoff];
971 pix = &tix;
972 /* Give up, roll back this option. */
973 } else {
974 bufix = optstart;
975 six = soptstart;
976 tix = toptstart;
977 break;
981 if (incr > length)
982 incr = length;
983 if (incr > 255)
984 incr = 255;
986 /* Everything looks good - copy it in! */
987 base [*pix] = code;
988 base [*pix + 1] = (unsigned char)incr;
989 if (tto && incr == length) {
990 if (incr > 1)
991 memcpy (base + *pix + 2,
992 od.data + ix, (unsigned)(incr - 1));
993 base [*pix + 2 + incr - 1] = 0;
994 } else {
995 memcpy (base + *pix + 2,
996 od.data + ix, (unsigned)incr);
998 length -= incr;
999 ix += incr;
1000 *pix += 2 + incr;
1002 data_string_forget (&od, MDL);
1005 /* If we can overload, and we have, then PAD and END those spaces. */
1006 if (first_cutoff && six) {
1007 if ((first_cutoff + six + 1) < sbufend)
1008 memset (&buffer[first_cutoff + six + 1], DHO_PAD,
1009 sbufend - (first_cutoff + six + 1));
1010 else if (first_cutoff + six >= sbufend)
1011 log_fatal("Second buffer overflow in overloaded options.");
1013 buffer[first_cutoff + six] = DHO_END;
1014 *ocount |= 1; /* So that caller knows there's data there. */
1017 if (second_cutoff && tix) {
1018 if (second_cutoff + tix + 1 < buflen) {
1019 memset (&buffer[second_cutoff + tix + 1], DHO_PAD,
1020 buflen - (second_cutoff + tix + 1));
1021 } else if (second_cutoff + tix >= buflen)
1022 log_fatal("Third buffer overflow in overloaded options.");
1024 buffer[second_cutoff + tix] = DHO_END;
1025 *ocount |= 2; /* So that caller knows there's data there. */
1028 if ((six || tix) && (bufix + 3 > bufend))
1029 log_fatal("Not enough space for option overload option.");
1031 return bufix;
1034 /* Format the specified option so that a human can easily read it. */
1036 const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
1037 struct option *option;
1038 const unsigned char *data;
1039 unsigned len;
1040 int emit_commas;
1041 int emit_quotes;
1043 static char optbuf [32768]; /* XXX */
1044 int hunksize = 0;
1045 int opthunk = 0;
1046 int hunkinc = 0;
1047 int numhunk = -1;
1048 int numelem = 0;
1049 char fmtbuf [32];
1050 struct enumeration *enumbuf [32];
1051 int i, j, k, l;
1052 char *op = optbuf;
1053 const unsigned char *dp = data;
1054 struct in_addr foo;
1055 char comma;
1056 unsigned long tval;
1058 if (emit_commas)
1059 comma = ',';
1060 else
1061 comma = ' ';
1063 memset (enumbuf, 0, sizeof enumbuf);
1065 /* Figure out the size of the data. */
1066 for (l = i = 0; option -> format [i]; i++, l++) {
1067 if (!numhunk) {
1068 log_error ("%s: Extra codes in format string: %s",
1069 option -> name,
1070 &(option -> format [i]));
1071 break;
1073 numelem++;
1074 fmtbuf [l] = option -> format [i];
1075 switch (option -> format [i]) {
1076 case 'a':
1077 --numelem;
1078 fmtbuf [l] = 0;
1079 numhunk = 0;
1080 break;
1081 case 'A':
1082 --numelem;
1083 fmtbuf [l] = 0;
1084 numhunk = 0;
1085 break;
1086 case 'E':
1087 /* Skip the universe name. */
1088 while (option -> format [i] &&
1089 option -> format [i] != '.')
1090 i++;
1091 case 'X':
1092 for (k = 0; k < len; k++) {
1093 if (!isascii (data [k]) ||
1094 !isprint (data [k]))
1095 break;
1097 /* If we found no bogus characters, or the bogus
1098 character we found is a trailing NUL, it's
1099 okay to print this option as text. */
1100 if (k == len || (k + 1 == len && data [k] == 0)) {
1101 fmtbuf [l] = 't';
1102 numhunk = -2;
1103 } else {
1104 fmtbuf [l] = 'x';
1105 hunksize++;
1106 comma = ':';
1107 numhunk = 0;
1109 fmtbuf [l + 1] = 0;
1110 break;
1111 case 'd':
1112 case 't':
1113 fmtbuf [l] = 't';
1114 fmtbuf [l + 1] = 0;
1115 numhunk = -2;
1116 break;
1117 case 'N':
1118 k = i;
1119 while (option -> format [i] &&
1120 option -> format [i] != '.')
1121 i++;
1122 enumbuf [l] =
1123 find_enumeration (&option -> format [k] + 1,
1124 i - k - 1);
1125 hunksize += 1;
1126 hunkinc = 1;
1127 break;
1128 case 'I':
1129 case 'l':
1130 case 'L':
1131 case 'T':
1132 hunksize += 4;
1133 hunkinc = 4;
1134 break;
1135 case 's':
1136 case 'S':
1137 hunksize += 2;
1138 hunkinc = 2;
1139 break;
1140 case 'b':
1141 case 'B':
1142 case 'f':
1143 hunksize++;
1144 hunkinc = 1;
1145 break;
1146 case 'e':
1147 break;
1148 case 'o':
1149 opthunk += hunkinc;
1150 break;
1151 default:
1152 log_error ("%s: garbage in format string: %s",
1153 option -> name,
1154 &(option -> format [i]));
1155 break;
1159 /* Check for too few bytes... */
1160 if (hunksize - opthunk > len) {
1161 log_error ("%s: expecting at least %d bytes; got %d",
1162 option -> name,
1163 hunksize, len);
1164 return "<error>";
1166 /* Check for too many bytes... */
1167 if (numhunk == -1 && hunksize < len)
1168 log_error ("%s: %d extra bytes",
1169 option -> name,
1170 len - hunksize);
1172 /* If this is an array, compute its size. */
1173 if (!numhunk)
1174 numhunk = len / hunksize;
1175 /* See if we got an exact number of hunks. */
1176 if (numhunk > 0 && numhunk * hunksize < len)
1177 log_error ("%s: %d extra bytes at end of array\n",
1178 option -> name,
1179 len - numhunk * hunksize);
1181 /* A one-hunk array prints the same as a single hunk. */
1182 if (numhunk < 0)
1183 numhunk = 1;
1185 /* Cycle through the array (or hunk) printing the data. */
1186 for (i = 0; i < numhunk; i++) {
1187 for (j = 0; j < numelem; j++) {
1188 switch (fmtbuf [j]) {
1189 case 't':
1190 if (emit_quotes)
1191 *op++ = '"';
1192 for (; dp < data + len; dp++) {
1193 if (!isascii (*dp) ||
1194 !isprint (*dp)) {
1195 /* Skip trailing NUL. */
1196 if (dp + 1 != data + len ||
1197 *dp != 0) {
1198 sprintf (op, "\\%03o",
1199 *dp);
1200 op += 4;
1202 } else if (*dp == '"' ||
1203 *dp == '\'' ||
1204 *dp == '$' ||
1205 *dp == '`' ||
1206 *dp == '\\') {
1207 *op++ = '\\';
1208 *op++ = *dp;
1209 } else
1210 *op++ = *dp;
1212 if (emit_quotes)
1213 *op++ = '"';
1214 *op = 0;
1215 break;
1216 /* pretty-printing an array of enums is
1217 going to get ugly. */
1218 case 'N':
1219 if (!enumbuf [j])
1220 goto enum_as_num;
1221 for (i = 0; ;i++) {
1222 if (!enumbuf [j] -> values [i].name)
1223 goto enum_as_num;
1224 if (enumbuf [j] -> values [i].value ==
1225 *dp)
1226 break;
1228 strcpy (op, enumbuf [j] -> values [i].name);
1229 op += strlen (op);
1230 break;
1231 case 'I':
1232 foo.s_addr = htonl (getULong (dp));
1233 strcpy (op, inet_ntoa (foo));
1234 dp += 4;
1235 break;
1236 case 'l':
1237 sprintf (op, "%ld", (long)getLong (dp));
1238 dp += 4;
1239 break;
1240 case 'T':
1241 tval = getULong (dp);
1242 if (tval == -1)
1243 sprintf (op, "%s", "infinite");
1244 else
1245 sprintf (op, "%ld", tval);
1246 break;
1247 case 'L':
1248 sprintf (op, "%ld",
1249 (unsigned long)getULong (dp));
1250 dp += 4;
1251 break;
1252 case 's':
1253 sprintf (op, "%d", (int)getShort (dp));
1254 dp += 2;
1255 break;
1256 case 'S':
1257 sprintf (op, "%d", (unsigned)getUShort (dp));
1258 dp += 2;
1259 break;
1260 case 'b':
1261 sprintf (op, "%d", *(const char *)dp++);
1262 break;
1263 case 'B':
1264 enum_as_num:
1265 sprintf (op, "%d", *dp++);
1266 break;
1267 case 'x':
1268 sprintf (op, "%x", *dp++);
1269 break;
1270 case 'f':
1271 strcpy (op, *dp++ ? "true" : "false");
1272 break;
1273 default:
1274 log_error ("Unexpected format code %c",
1275 fmtbuf [j]);
1277 op += strlen (op);
1278 if (dp == data + len)
1279 break;
1280 if (j + 1 < numelem && comma != ':')
1281 *op++ = ' ';
1283 if (i + 1 < numhunk) {
1284 *op++ = comma;
1286 if (dp == data + len)
1287 break;
1289 return optbuf;
1292 int get_option (result, universe, packet, lease, client_state,
1293 in_options, cfg_options, options, scope, code, file, line)
1294 struct data_string *result;
1295 struct universe *universe;
1296 struct packet *packet;
1297 struct lease *lease;
1298 struct client_state *client_state;
1299 struct option_state *in_options;
1300 struct option_state *cfg_options;
1301 struct option_state *options;
1302 struct binding_scope **scope;
1303 unsigned code;
1304 const char *file;
1305 int line;
1307 struct option_cache *oc;
1309 if (!universe -> lookup_func)
1310 return 0;
1311 oc = ((*universe -> lookup_func) (universe, options, code));
1312 if (!oc)
1313 return 0;
1314 if (!evaluate_option_cache (result, packet, lease, client_state,
1315 in_options, cfg_options, scope, oc,
1316 file, line))
1317 return 0;
1318 return 1;
1321 void set_option (universe, options, option, op)
1322 struct universe *universe;
1323 struct option_state *options;
1324 struct option_cache *option;
1325 enum statement_op op;
1327 struct option_cache *oc, *noc;
1329 switch (op) {
1330 case if_statement:
1331 case add_statement:
1332 case eval_statement:
1333 case break_statement:
1334 default:
1335 log_error ("bogus statement type in set_option.");
1336 break;
1338 case default_option_statement:
1339 oc = lookup_option (universe, options,
1340 option -> option -> code);
1341 if (oc)
1342 break;
1343 save_option (universe, options, option);
1344 break;
1346 case supersede_option_statement:
1347 case send_option_statement:
1348 /* Install the option, replacing any existing version. */
1349 save_option (universe, options, option);
1350 break;
1352 case append_option_statement:
1353 case prepend_option_statement:
1354 oc = lookup_option (universe, options,
1355 option -> option -> code);
1356 if (!oc) {
1357 save_option (universe, options, option);
1358 break;
1360 /* If it's not an expression, make it into one. */
1361 if (!oc -> expression && oc -> data.len) {
1362 if (!expression_allocate (&oc -> expression, MDL)) {
1363 log_error ("Can't allocate const expression.");
1364 break;
1366 oc -> expression -> op = expr_const_data;
1367 data_string_copy
1368 (&oc -> expression -> data.const_data,
1369 &oc -> data, MDL);
1370 data_string_forget (&oc -> data, MDL);
1372 noc = (struct option_cache *)0;
1373 if (!option_cache_allocate (&noc, MDL))
1374 break;
1375 if (op == append_option_statement) {
1376 if (!make_concat (&noc -> expression,
1377 oc -> expression,
1378 option -> expression)) {
1379 option_cache_dereference (&noc, MDL);
1380 break;
1382 } else {
1383 if (!make_concat (&noc -> expression,
1384 option -> expression,
1385 oc -> expression)) {
1386 option_cache_dereference (&noc, MDL);
1387 break;
1390 noc -> option = oc -> option;
1391 save_option (universe, options, noc);
1392 option_cache_dereference (&noc, MDL);
1393 break;
1397 struct option_cache *lookup_option (universe, options, code)
1398 struct universe *universe;
1399 struct option_state *options;
1400 unsigned code;
1402 if (!options)
1403 return (struct option_cache *)0;
1404 if (universe -> lookup_func)
1405 return (*universe -> lookup_func) (universe, options, code);
1406 else
1407 log_error ("can't look up options in %s space.",
1408 universe -> name);
1409 return (struct option_cache *)0;
1412 struct option_cache *lookup_hashed_option (universe, options, code)
1413 struct universe *universe;
1414 struct option_state *options;
1415 unsigned code;
1417 int hashix;
1418 pair bptr;
1419 pair *hash;
1421 /* Make sure there's a hash table. */
1422 if (universe -> index >= options -> universe_count ||
1423 !(options -> universes [universe -> index]))
1424 return (struct option_cache *)0;
1426 hash = options -> universes [universe -> index];
1428 hashix = compute_option_hash (code);
1429 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1430 if (((struct option_cache *)(bptr -> car)) -> option -> code ==
1431 code)
1432 return (struct option_cache *)(bptr -> car);
1434 return (struct option_cache *)0;
1437 int save_option_buffer (struct universe *universe,
1438 struct option_state *options,
1439 struct buffer *bp,
1440 unsigned char *buffer, unsigned length,
1441 struct option *option, int tp)
1443 struct buffer *lbp = (struct buffer *)0;
1444 struct option_cache *op = (struct option_cache *)0;
1446 if (!option_cache_allocate (&op, MDL)) {
1447 log_error ("No memory for option %s.%s.",
1448 universe -> name,
1449 option -> name);
1450 return 0;
1453 /* If we weren't passed a buffer in which the data are saved and
1454 refcounted, allocate one now. */
1455 if (!bp) {
1456 if (!buffer_allocate (&lbp, length, MDL)) {
1457 log_error ("no memory for option buffer.");
1459 option_cache_dereference (&op, MDL);
1460 return 0;
1462 memcpy (lbp -> data, buffer, length + tp);
1463 bp = lbp;
1464 buffer = &bp -> data [0]; /* Refer to saved buffer. */
1467 /* Reference buffer copy to option cache. */
1468 op -> data.buffer = (struct buffer *)0;
1469 buffer_reference (&op -> data.buffer, bp, MDL);
1471 /* Point option cache into buffer. */
1472 op -> data.data = buffer;
1473 op -> data.len = length;
1475 if (tp) {
1476 /* NUL terminate (we can get away with this because we (or
1477 the caller!) allocated one more than the buffer size, and
1478 because the byte following the end of an option is always
1479 the code of the next option, which the caller is getting
1480 out of the *original* buffer. */
1481 buffer [length] = 0;
1482 op -> data.terminated = 1;
1483 } else
1484 op -> data.terminated = 0;
1486 op -> option = option;
1488 /* Now store the option. */
1489 save_option (universe, options, op);
1491 /* And let go of our reference. */
1492 option_cache_dereference (&op, MDL);
1494 return 1;
1497 void save_option (struct universe *universe,
1498 struct option_state *options, struct option_cache *oc)
1500 if (universe -> save_func)
1501 (*universe -> save_func) (universe, options, oc);
1502 else
1503 log_error ("can't store options in %s space.",
1504 universe -> name);
1507 void save_hashed_option (universe, options, oc)
1508 struct universe *universe;
1509 struct option_state *options;
1510 struct option_cache *oc;
1512 int hashix;
1513 pair bptr;
1514 pair *hash = options -> universes [universe -> index];
1516 if (oc -> refcnt == 0)
1517 abort ();
1519 /* Compute the hash. */
1520 hashix = compute_option_hash (oc -> option -> code);
1522 /* If there's no hash table, make one. */
1523 if (!hash) {
1524 hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL);
1525 if (!hash) {
1526 log_error ("no memory to store %s.%s",
1527 universe -> name, oc -> option -> name);
1528 return;
1530 memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash);
1531 options -> universes [universe -> index] = (VOIDPTR)hash;
1532 } else {
1533 /* Try to find an existing option matching the new one. */
1534 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1535 if (((struct option_cache *)
1536 (bptr -> car)) -> option -> code ==
1537 oc -> option -> code)
1538 break;
1541 /* If we find one, dereference it and put the new one
1542 in its place. */
1543 if (bptr) {
1544 option_cache_dereference
1545 ((struct option_cache **)&bptr -> car, MDL);
1546 option_cache_reference
1547 ((struct option_cache **)&bptr -> car,
1548 oc, MDL);
1549 return;
1553 /* Otherwise, just put the new one at the head of the list. */
1554 bptr = new_pair (MDL);
1555 if (!bptr) {
1556 log_error ("No memory for option_cache reference.");
1557 return;
1559 bptr -> cdr = hash [hashix];
1560 bptr -> car = 0;
1561 option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL);
1562 hash [hashix] = bptr;
1565 void delete_option (universe, options, code)
1566 struct universe *universe;
1567 struct option_state *options;
1568 int code;
1570 if (universe -> delete_func)
1571 (*universe -> delete_func) (universe, options, code);
1572 else
1573 log_error ("can't delete options from %s space.",
1574 universe -> name);
1577 void delete_hashed_option (universe, options, code)
1578 struct universe *universe;
1579 struct option_state *options;
1580 int code;
1582 int hashix;
1583 pair bptr, prev = (pair)0;
1584 pair *hash = options -> universes [universe -> index];
1586 /* There may not be any options in this space. */
1587 if (!hash)
1588 return;
1590 /* Try to find an existing option matching the new one. */
1591 hashix = compute_option_hash (code);
1592 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1593 if (((struct option_cache *)(bptr -> car)) -> option -> code
1594 == code)
1595 break;
1596 prev = bptr;
1598 /* If we found one, wipe it out... */
1599 if (bptr) {
1600 if (prev)
1601 prev -> cdr = bptr -> cdr;
1602 else
1603 hash [hashix] = bptr -> cdr;
1604 option_cache_dereference
1605 ((struct option_cache **)(&bptr -> car), MDL);
1606 free_pair (bptr, MDL);
1610 extern struct option_cache *free_option_caches; /* XXX */
1612 int option_cache_dereference (ptr, file, line)
1613 struct option_cache **ptr;
1614 const char *file;
1615 int line;
1617 if (!ptr || !*ptr) {
1618 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1619 file, line);
1620 #if defined (POINTER_DEBUG)
1621 abort ();
1622 #else
1623 return 0;
1624 #endif
1627 (*ptr) -> refcnt--;
1628 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
1629 if (!(*ptr) -> refcnt) {
1630 if ((*ptr) -> data.buffer)
1631 data_string_forget (&(*ptr) -> data, file, line);
1632 if ((*ptr) -> expression)
1633 expression_dereference (&(*ptr) -> expression,
1634 file, line);
1635 if ((*ptr) -> next)
1636 option_cache_dereference (&((*ptr) -> next),
1637 file, line);
1638 /* Put it back on the free list... */
1639 (*ptr) -> expression = (struct expression *)free_option_caches;
1640 free_option_caches = *ptr;
1641 dmalloc_reuse (free_option_caches, (char *)0, 0, 0);
1643 if ((*ptr) -> refcnt < 0) {
1644 log_error ("%s(%d): negative refcnt!", file, line);
1645 #if defined (DEBUG_RC_HISTORY)
1646 dump_rc_history (*ptr);
1647 #endif
1648 #if defined (POINTER_DEBUG)
1649 abort ();
1650 #else
1651 *ptr = (struct option_cache *)0;
1652 return 0;
1653 #endif
1655 *ptr = (struct option_cache *)0;
1656 return 1;
1660 int hashed_option_state_dereference (universe, state, file, line)
1661 struct universe *universe;
1662 struct option_state *state;
1663 const char *file;
1664 int line;
1666 pair *heads;
1667 pair cp, next;
1668 int i;
1670 /* Get the pointer to the array of hash table bucket heads. */
1671 heads = (pair *)(state -> universes [universe -> index]);
1672 if (!heads)
1673 return 0;
1675 /* For each non-null head, loop through all the buckets dereferencing
1676 the attached option cache structures and freeing the buckets. */
1677 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1678 for (cp = heads [i]; cp; cp = next) {
1679 next = cp -> cdr;
1680 option_cache_dereference
1681 ((struct option_cache **)&cp -> car,
1682 file, line);
1683 free_pair (cp, file, line);
1687 dfree (heads, file, line);
1688 state -> universes [universe -> index] = (void *)0;
1689 return 1;
1692 int store_option (result, universe, packet, lease, client_state,
1693 in_options, cfg_options, scope, oc)
1694 struct data_string *result;
1695 struct universe *universe;
1696 struct packet *packet;
1697 struct lease *lease;
1698 struct client_state *client_state;
1699 struct option_state *in_options;
1700 struct option_state *cfg_options;
1701 struct binding_scope **scope;
1702 struct option_cache *oc;
1704 struct data_string d1, d2;
1706 memset (&d1, 0, sizeof d1);
1707 memset (&d2, 0, sizeof d2);
1709 if (evaluate_option_cache (&d2, packet, lease, client_state,
1710 in_options, cfg_options, scope, oc, MDL)) {
1711 if (!buffer_allocate (&d1.buffer,
1712 (result -> len +
1713 universe -> length_size +
1714 universe -> tag_size + d2.len), MDL)) {
1715 data_string_forget (result, MDL);
1716 data_string_forget (&d2, MDL);
1717 return 0;
1719 d1.data = &d1.buffer -> data [0];
1720 if (result -> len)
1721 memcpy (d1.buffer -> data,
1722 result -> data, result -> len);
1723 d1.len = result -> len;
1724 (*universe -> store_tag) (&d1.buffer -> data [d1.len],
1725 oc -> option -> code);
1726 d1.len += universe -> tag_size;
1727 (*universe -> store_length) (&d1.buffer -> data [d1.len],
1728 d2.len);
1729 d1.len += universe -> length_size;
1730 memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len);
1731 d1.len += d2.len;
1732 data_string_forget (&d2, MDL);
1733 data_string_forget (result, MDL);
1734 data_string_copy (result, &d1, MDL);
1735 data_string_forget (&d1, MDL);
1736 return 1;
1738 return 0;
1741 int option_space_encapsulate (result, packet, lease, client_state,
1742 in_options, cfg_options, scope, name)
1743 struct data_string *result;
1744 struct packet *packet;
1745 struct lease *lease;
1746 struct client_state *client_state;
1747 struct option_state *in_options;
1748 struct option_state *cfg_options;
1749 struct binding_scope **scope;
1750 struct data_string *name;
1752 struct universe *u;
1754 u = (struct universe *)0;
1755 universe_hash_lookup (&u, universe_hash,
1756 (const char *)name -> data, name -> len, MDL);
1757 if (!u)
1758 return 0;
1760 if (u -> encapsulate)
1761 return (*u -> encapsulate) (result, packet, lease,
1762 client_state,
1763 in_options, cfg_options, scope, u);
1764 log_error ("encapsulation requested for %s with no support.",
1765 name -> data);
1766 return 0;
1769 int hashed_option_space_encapsulate (result, packet, lease, client_state,
1770 in_options, cfg_options, scope, universe)
1771 struct data_string *result;
1772 struct packet *packet;
1773 struct lease *lease;
1774 struct client_state *client_state;
1775 struct option_state *in_options;
1776 struct option_state *cfg_options;
1777 struct binding_scope **scope;
1778 struct universe *universe;
1780 pair p, *hash;
1781 int status;
1782 int i;
1784 if (universe -> index >= cfg_options -> universe_count)
1785 return 0;
1787 hash = cfg_options -> universes [universe -> index];
1788 if (!hash)
1789 return 0;
1791 status = 0;
1792 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1793 for (p = hash [i]; p; p = p -> cdr) {
1794 if (store_option (result, universe, packet,
1795 lease, client_state, in_options,
1796 cfg_options, scope,
1797 (struct option_cache *)p -> car))
1798 status = 1;
1802 return status;
1805 int nwip_option_space_encapsulate (result, packet, lease, client_state,
1806 in_options, cfg_options, scope, universe)
1807 struct data_string *result;
1808 struct packet *packet;
1809 struct lease *lease;
1810 struct client_state *client_state;
1811 struct option_state *in_options;
1812 struct option_state *cfg_options;
1813 struct binding_scope **scope;
1814 struct universe *universe;
1816 pair ocp;
1817 int status;
1818 static struct option_cache *no_nwip;
1819 struct data_string ds;
1820 struct option_chain_head *head;
1822 if (universe -> index >= cfg_options -> universe_count)
1823 return 0;
1824 head = ((struct option_chain_head *)
1825 cfg_options -> universes [fqdn_universe.index]);
1826 if (!head)
1827 return 0;
1829 status = 0;
1830 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
1831 if (store_option (result, universe, packet,
1832 lease, client_state, in_options,
1833 cfg_options, scope,
1834 (struct option_cache *)ocp -> car))
1835 status = 1;
1838 /* If there's no data, the nwip suboption is supposed to contain
1839 a suboption saying there's no data. */
1840 if (!status) {
1841 if (!no_nwip) {
1842 static unsigned char nni [] = { 1, 0 };
1843 memset (&ds, 0, sizeof ds);
1844 ds.data = nni;
1845 ds.len = 2;
1846 if (option_cache_allocate (&no_nwip, MDL))
1847 data_string_copy (&no_nwip -> data, &ds, MDL);
1848 no_nwip -> option = nwip_universe.options [1];
1850 if (no_nwip) {
1851 if (store_option (result, universe, packet, lease,
1852 client_state, in_options,
1853 cfg_options, scope, no_nwip))
1854 status = 1;
1856 } else {
1857 memset (&ds, 0, sizeof ds);
1859 /* If we have nwip options, the first one has to be the
1860 nwip-exists-in-option-area option. */
1861 if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) {
1862 data_string_forget (result, MDL);
1863 return 0;
1865 ds.data = &ds.buffer -> data [0];
1866 ds.buffer -> data [0] = 2;
1867 ds.buffer -> data [1] = 0;
1868 memcpy (&ds.buffer -> data [2], result -> data, result -> len);
1869 data_string_forget (result, MDL);
1870 data_string_copy (result, &ds, MDL);
1871 data_string_forget (&ds, MDL);
1874 return status;
1877 int fqdn_option_space_encapsulate (result, packet, lease, client_state,
1878 in_options, cfg_options, scope, universe)
1879 struct data_string *result;
1880 struct packet *packet;
1881 struct lease *lease;
1882 struct client_state *client_state;
1883 struct option_state *in_options;
1884 struct option_state *cfg_options;
1885 struct binding_scope **scope;
1886 struct universe *universe;
1888 pair ocp;
1889 struct data_string results [FQDN_SUBOPTION_COUNT + 1];
1890 unsigned i;
1891 unsigned len;
1892 struct buffer *bp = (struct buffer *)0;
1893 struct option_chain_head *head;
1895 /* If there's no FQDN universe, don't encapsulate. */
1896 if (fqdn_universe.index >= cfg_options -> universe_count)
1897 return 0;
1898 head = ((struct option_chain_head *)
1899 cfg_options -> universes [fqdn_universe.index]);
1900 if (!head)
1901 return 0;
1903 /* Figure out the values of all the suboptions. */
1904 memset (results, 0, sizeof results);
1905 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
1906 struct option_cache *oc = (struct option_cache *)(ocp -> car);
1907 if (oc -> option -> code > FQDN_SUBOPTION_COUNT)
1908 continue;
1909 evaluate_option_cache (&results [oc -> option -> code],
1910 packet, lease, client_state, in_options,
1911 cfg_options, scope, oc, MDL);
1913 len = 4 + results [FQDN_FQDN].len;
1914 /* Save the contents of the option in a buffer. */
1915 if (!buffer_allocate (&bp, len, MDL)) {
1916 log_error ("no memory for option buffer.");
1917 return 0;
1919 buffer_reference (&result -> buffer, bp, MDL);
1920 result -> len = 3;
1921 result -> data = &bp -> data [0];
1923 memset (&bp -> data [0], 0, len);
1924 if (results [FQDN_NO_CLIENT_UPDATE].len &&
1925 results [FQDN_NO_CLIENT_UPDATE].data [0])
1926 bp -> data [0] |= 2;
1927 if (results [FQDN_SERVER_UPDATE].len &&
1928 results [FQDN_SERVER_UPDATE].data [0])
1929 bp -> data [0] |= 1;
1930 if (results [FQDN_RCODE1].len)
1931 bp -> data [1] = results [FQDN_RCODE1].data [0];
1932 if (results [FQDN_RCODE2].len)
1933 bp -> data [2] = results [FQDN_RCODE2].data [0];
1935 if (results [FQDN_ENCODED].len &&
1936 results [FQDN_ENCODED].data [0]) {
1937 unsigned char *out;
1938 int i;
1939 bp -> data [0] |= 4;
1940 out = &bp -> data [3];
1941 if (results [FQDN_FQDN].len) {
1942 i = 0;
1943 while (i < results [FQDN_FQDN].len) {
1944 int j;
1945 for (j = i; ('.' !=
1946 results [FQDN_FQDN].data [j]) &&
1947 j < results [FQDN_FQDN].len; j++)
1949 *out++ = j - i;
1950 memcpy (out, &results [FQDN_FQDN].data [i],
1951 (unsigned)(j - i));
1952 out += j - i;
1953 i = j;
1954 if (results [FQDN_FQDN].data [j] == '.')
1955 i++;
1957 if ((results [FQDN_FQDN].data
1958 [results [FQDN_FQDN].len - 1] == '.'))
1959 *out++ = 0;
1960 result -> len = out - result -> data;
1961 result -> terminated = 0;
1963 } else {
1964 if (results [FQDN_FQDN].len) {
1965 memcpy (&bp -> data [3], results [FQDN_FQDN].data,
1966 results [FQDN_FQDN].len);
1967 result -> len += results [FQDN_FQDN].len;
1968 result -> terminated = 0;
1971 for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) {
1972 if (results [i].len)
1973 data_string_forget (&results [i], MDL);
1975 buffer_dereference (&bp, MDL);
1976 return 1;
1979 void option_space_foreach (struct packet *packet, struct lease *lease,
1980 struct client_state *client_state,
1981 struct option_state *in_options,
1982 struct option_state *cfg_options,
1983 struct binding_scope **scope,
1984 struct universe *u, void *stuff,
1985 void (*func) (struct option_cache *,
1986 struct packet *,
1987 struct lease *, struct client_state *,
1988 struct option_state *,
1989 struct option_state *,
1990 struct binding_scope **,
1991 struct universe *, void *))
1993 if (u -> foreach)
1994 (*u -> foreach) (packet, lease, client_state, in_options,
1995 cfg_options, scope, u, stuff, func);
1998 void suboption_foreach (struct packet *packet, struct lease *lease,
1999 struct client_state *client_state,
2000 struct option_state *in_options,
2001 struct option_state *cfg_options,
2002 struct binding_scope **scope,
2003 struct universe *u, void *stuff,
2004 void (*func) (struct option_cache *,
2005 struct packet *,
2006 struct lease *, struct client_state *,
2007 struct option_state *,
2008 struct option_state *,
2009 struct binding_scope **,
2010 struct universe *, void *),
2011 struct option_cache *oc,
2012 const char *vsname)
2014 struct universe *universe = find_option_universe (oc -> option,
2015 vsname);
2017 if (universe -> foreach)
2018 (*universe -> foreach) (packet, lease, client_state,
2019 in_options, cfg_options,
2020 scope, universe, stuff, func);
2023 void hashed_option_space_foreach (struct packet *packet, struct lease *lease,
2024 struct client_state *client_state,
2025 struct option_state *in_options,
2026 struct option_state *cfg_options,
2027 struct binding_scope **scope,
2028 struct universe *u, void *stuff,
2029 void (*func) (struct option_cache *,
2030 struct packet *,
2031 struct lease *,
2032 struct client_state *,
2033 struct option_state *,
2034 struct option_state *,
2035 struct binding_scope **,
2036 struct universe *, void *))
2038 pair *hash;
2039 int i;
2040 struct option_cache *oc;
2042 if (cfg_options -> universe_count <= u -> index)
2043 return;
2045 hash = cfg_options -> universes [u -> index];
2046 if (!hash)
2047 return;
2048 for (i = 0; i < OPTION_HASH_SIZE; i++) {
2049 pair p;
2050 /* XXX save _all_ options! XXX */
2051 for (p = hash [i]; p; p = p -> cdr) {
2052 oc = (struct option_cache *)p -> car;
2053 (*func) (oc, packet, lease, client_state,
2054 in_options, cfg_options, scope, u, stuff);
2059 void save_linked_option (universe, options, oc)
2060 struct universe *universe;
2061 struct option_state *options;
2062 struct option_cache *oc;
2064 pair *tail;
2065 struct option_chain_head *head;
2067 if (universe -> index >= options -> universe_count)
2068 return;
2069 head = ((struct option_chain_head *)
2070 options -> universes [universe -> index]);
2071 if (!head) {
2072 if (!option_chain_head_allocate (((struct option_chain_head **)
2073 &options -> universes
2074 [universe -> index]), MDL))
2075 return;
2076 head = ((struct option_chain_head *)
2077 options -> universes [universe -> index]);
2080 /* Find the tail of the list. */
2081 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2082 if (oc -> option ==
2083 ((struct option_cache *)((*tail) -> car)) -> option) {
2084 option_cache_dereference ((struct option_cache **)
2085 (&(*tail) -> car), MDL);
2086 option_cache_reference ((struct option_cache **)
2087 (&(*tail) -> car), oc, MDL);
2088 return;
2092 *tail = cons (0, 0);
2093 if (*tail) {
2094 option_cache_reference ((struct option_cache **)
2095 (&(*tail) -> car), oc, MDL);
2099 int linked_option_space_encapsulate (result, packet, lease, client_state,
2100 in_options, cfg_options, scope, universe)
2101 struct data_string *result;
2102 struct packet *packet;
2103 struct lease *lease;
2104 struct client_state *client_state;
2105 struct option_state *in_options;
2106 struct option_state *cfg_options;
2107 struct binding_scope **scope;
2108 struct universe *universe;
2110 int status;
2111 pair oc;
2112 struct option_chain_head *head;
2114 if (universe -> index >= cfg_options -> universe_count)
2115 return 0;
2116 head = ((struct option_chain_head *)
2117 cfg_options -> universes [universe -> index]);
2118 if (!head)
2119 return 0;
2121 status = 0;
2122 for (oc = head -> first; oc; oc = oc -> cdr) {
2123 if (store_option (result, universe, packet,
2124 lease, client_state, in_options, cfg_options,
2125 scope, (struct option_cache *)(oc -> car)))
2126 status = 1;
2129 return status;
2132 void delete_linked_option (universe, options, code)
2133 struct universe *universe;
2134 struct option_state *options;
2135 int code;
2137 pair *tail, tmp = (pair)0;
2138 struct option_chain_head *head;
2140 if (universe -> index >= options -> universe_count)
2141 return;
2142 head = ((struct option_chain_head *)
2143 options -> universes [universe -> index]);
2144 if (!head)
2145 return;
2147 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2148 if (code ==
2149 ((struct option_cache *)(*tail) -> car) -> option -> code)
2151 tmp = (*tail) -> cdr;
2152 option_cache_dereference ((struct option_cache **)
2153 (&(*tail) -> car), MDL);
2154 dfree (*tail, MDL);
2155 (*tail) = tmp;
2156 break;
2161 struct option_cache *lookup_linked_option (universe, options, code)
2162 struct universe *universe;
2163 struct option_state *options;
2164 unsigned code;
2166 pair oc;
2167 struct option_chain_head *head;
2169 if (universe -> index >= options -> universe_count)
2170 return 0;
2171 head = ((struct option_chain_head *)
2172 options -> universes [universe -> index]);
2173 if (!head)
2174 return 0;
2176 for (oc = head -> first; oc; oc = oc -> cdr) {
2177 if (code ==
2178 ((struct option_cache *)(oc -> car)) -> option -> code) {
2179 return (struct option_cache *)(oc -> car);
2183 return (struct option_cache *)0;
2186 int linked_option_state_dereference (universe, state, file, line)
2187 struct universe *universe;
2188 struct option_state *state;
2189 const char *file;
2190 int line;
2192 return (option_chain_head_dereference
2193 ((struct option_chain_head **)
2194 (&state -> universes [universe -> index]), MDL));
2197 void linked_option_space_foreach (struct packet *packet, struct lease *lease,
2198 struct client_state *client_state,
2199 struct option_state *in_options,
2200 struct option_state *cfg_options,
2201 struct binding_scope **scope,
2202 struct universe *u, void *stuff,
2203 void (*func) (struct option_cache *,
2204 struct packet *,
2205 struct lease *,
2206 struct client_state *,
2207 struct option_state *,
2208 struct option_state *,
2209 struct binding_scope **,
2210 struct universe *, void *))
2212 pair car;
2213 struct option_chain_head *head;
2215 if (u -> index >= cfg_options -> universe_count)
2216 return;
2217 head = ((struct option_chain_head *)
2218 cfg_options -> universes [u -> index]);
2219 if (!head)
2220 return;
2221 for (car = head -> first; car; car = car -> cdr) {
2222 (*func) ((struct option_cache *)(car -> car),
2223 packet, lease, client_state,
2224 in_options, cfg_options, scope, u, stuff);
2228 void do_packet (interface, packet, len, from_port, from, hfrom)
2229 struct interface_info *interface;
2230 struct dhcp_packet *packet;
2231 unsigned len;
2232 unsigned int from_port;
2233 struct iaddr from;
2234 struct hardware *hfrom;
2236 struct option_cache *op;
2237 struct packet *decoded_packet;
2238 #if defined (DEBUG_MEMORY_LEAKAGE)
2239 unsigned long previous_outstanding = dmalloc_outstanding;
2240 #endif
2242 #if defined (TRACING)
2243 trace_inpacket_stash (interface, packet, len, from_port, from, hfrom);
2244 #endif
2246 decoded_packet = (struct packet *)0;
2247 if (!packet_allocate (&decoded_packet, MDL)) {
2248 log_error ("do_packet: no memory for incoming packet!");
2249 return;
2251 decoded_packet -> raw = packet;
2252 decoded_packet -> packet_length = len;
2253 decoded_packet -> client_port = from_port;
2254 decoded_packet -> client_addr = from;
2255 interface_reference (&decoded_packet -> interface, interface, MDL);
2256 decoded_packet -> haddr = hfrom;
2258 if (packet -> hlen > sizeof packet -> chaddr) {
2259 packet_dereference (&decoded_packet, MDL);
2260 log_info ("Discarding packet with bogus hlen.");
2261 return;
2264 /* If there's an option buffer, try to parse it. */
2265 if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) {
2266 if (!parse_options (decoded_packet)) {
2267 if (decoded_packet -> options)
2268 option_state_dereference
2269 (&decoded_packet -> options, MDL);
2270 packet_dereference (&decoded_packet, MDL);
2271 return;
2274 if (decoded_packet -> options_valid &&
2275 (op = lookup_option (&dhcp_universe,
2276 decoded_packet -> options,
2277 DHO_DHCP_MESSAGE_TYPE))) {
2278 struct data_string dp;
2279 memset (&dp, 0, sizeof dp);
2280 evaluate_option_cache (&dp, decoded_packet,
2281 (struct lease *)0,
2282 (struct client_state *)0,
2283 decoded_packet -> options,
2284 (struct option_state *)0,
2285 (struct binding_scope **)0,
2286 op, MDL);
2287 if (dp.len > 0)
2288 decoded_packet -> packet_type = dp.data [0];
2289 else
2290 decoded_packet -> packet_type = 0;
2291 data_string_forget (&dp, MDL);
2295 if (decoded_packet -> packet_type)
2296 dhcp (decoded_packet);
2297 else
2298 bootp (decoded_packet);
2300 /* If the caller kept the packet, they'll have upped the refcnt. */
2301 packet_dereference (&decoded_packet, MDL);
2303 #if defined (DEBUG_MEMORY_LEAKAGE)
2304 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2305 dmalloc_generation,
2306 dmalloc_outstanding - previous_outstanding,
2307 dmalloc_outstanding, dmalloc_longterm);
2308 #endif
2309 #if defined (DEBUG_MEMORY_LEAKAGE)
2310 dmalloc_dump_outstanding ();
2311 #endif
2312 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2313 dump_rc_history (0);
2314 #endif