MFC: following 2 commits:
[dragonfly.git] / contrib / dhcp-3.0 / common / options.c
blobd0d5caccca0d5386bd5dd632de2f86922b06e0be
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.85.2.27 2004/12/04 00:03:18 dhankins 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 static void do_option_set PROTO ((pair *,
47 struct option_cache *,
48 enum statement_op));
50 /* Parse all available options out of the specified packet. */
52 int parse_options (packet)
53 struct packet *packet;
55 int i;
56 struct option_cache *op = (struct option_cache *)0;
58 /* Allocate a new option state. */
59 if (!option_state_allocate (&packet -> options, MDL)) {
60 packet -> options_valid = 0;
61 return 0;
64 /* If we don't see the magic cookie, there's nothing to parse. */
65 if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
66 packet -> options_valid = 0;
67 return 1;
70 /* Go through the options field, up to the end of the packet
71 or the End field. */
72 if (!parse_option_buffer (packet -> options,
73 &packet -> raw -> options [4],
74 (packet -> packet_length -
75 DHCP_FIXED_NON_UDP - 4),
76 &dhcp_universe))
77 return 0;
79 /* If we parsed a DHCP Option Overload option, parse more
80 options out of the buffer(s) containing them. */
81 if (packet -> options_valid &&
82 (op = lookup_option (&dhcp_universe, packet -> options,
83 DHO_DHCP_OPTION_OVERLOAD))) {
84 if (op -> data.data [0] & 1) {
85 if (!parse_option_buffer
86 (packet -> options,
87 (unsigned char *)packet -> raw -> file,
88 sizeof packet -> raw -> file,
89 &dhcp_universe))
90 return 0;
92 if (op -> data.data [0] & 2) {
93 if (!parse_option_buffer
94 (packet -> options,
95 (unsigned char *)packet -> raw -> sname,
96 sizeof packet -> raw -> sname,
97 &dhcp_universe))
98 return 0;
101 packet -> options_valid = 1;
102 return 1;
105 /* Parse options out of the specified buffer, storing addresses of option
106 values in packet -> options and setting packet -> options_valid if no
107 errors are encountered. */
109 int parse_option_buffer (options, buffer, length, universe)
110 struct option_state *options;
111 const unsigned char *buffer;
112 unsigned length;
113 struct universe *universe;
115 unsigned char *t;
116 const unsigned char *end = buffer + length;
117 unsigned len, offset;
118 int code;
119 struct option_cache *op = (struct option_cache *)0;
120 struct buffer *bp = (struct buffer *)0;
122 if (!buffer_allocate (&bp, length, MDL)) {
123 log_error ("no memory for option buffer.");
124 return 0;
126 memcpy (bp -> data, buffer, length);
128 for (offset = 0; buffer [offset] != DHO_END && offset < length; ) {
129 code = buffer [offset];
130 /* Pad options don't have a length - just skip them. */
131 if (code == DHO_PAD) {
132 ++offset;
133 continue;
136 /* Don't look for length if the buffer isn't that big. */
137 if (offset + 2 > length) {
138 len = 65536;
139 goto bogus;
142 /* All other fields (except end, see above) have a
143 one-byte length. */
144 len = buffer [offset + 1];
146 /* If the length is outrageous, the options are bad. */
147 if (offset + len + 2 > length) {
148 bogus:
149 log_error ("parse_option_buffer: option %s (%d) %s.",
150 dhcp_options [code].name, len,
151 "larger than buffer");
152 buffer_dereference (&bp, MDL);
153 return 0;
156 /* If the option contains an encapsulation, parse it. If
157 the parse fails, or the option isn't an encapsulation (by
158 far the most common case), or the option isn't entirely
159 an encapsulation, keep the raw data as well. */
160 if (universe -> options [code] &&
161 !((universe -> options [code] -> format [0] == 'e' ||
162 universe -> options [code] -> format [0] == 'E') &&
163 (parse_encapsulated_suboptions
164 (options, universe -> options [code],
165 buffer + offset + 2, len,
166 universe, (const char *)0)))) {
167 op = lookup_option (universe, options, code);
168 if (op) {
169 struct data_string new;
170 memset (&new, 0, sizeof new);
171 if (!buffer_allocate (&new.buffer, op -> data.len + len,
172 MDL)) {
173 log_error ("parse_option_buffer: No memory.");
174 return 0;
176 memcpy (new.buffer -> data, op -> data.data,
177 op -> data.len);
178 memcpy (&new.buffer -> data [op -> data.len],
179 &bp -> data [offset + 2], len);
180 new.len = op -> data.len + len;
181 new.data = new.buffer -> data;
182 data_string_forget (&op -> data, MDL);
183 data_string_copy (&op -> data, &new, MDL);
184 data_string_forget (&new, MDL);
185 } else {
186 save_option_buffer (universe, options, bp,
187 &bp -> data [offset + 2], len,
188 universe -> options [code], 1);
191 offset += len + 2;
193 buffer_dereference (&bp, MDL);
194 return 1;
197 /* If an option in an option buffer turns out to be an encapsulation,
198 figure out what to do. If we don't know how to de-encapsulate it,
199 or it's not well-formed, return zero; otherwise, return 1, indicating
200 that we succeeded in de-encapsulating it. */
202 struct universe *find_option_universe (struct option *eopt, const char *uname)
204 int i;
205 char *s, *t;
206 struct universe *universe = (struct universe *)0;
208 /* Look for the E option in the option format. */
209 s = strchr (eopt -> format, 'E');
210 if (!s) {
211 log_error ("internal encapsulation format error 1.");
212 return 0;
214 /* Look for the universe name in the option format. */
215 t = strchr (++s, '.');
216 /* If there was no trailing '.', or there's something after the
217 trailing '.', the option is bogus and we can't use it. */
218 if (!t || t [1]) {
219 log_error ("internal encapsulation format error 2.");
220 return 0;
222 if (t == s && uname) {
223 for (i = 0; i < universe_count; i++) {
224 if (!strcmp (universes [i] -> name, uname)) {
225 universe = universes [i];
226 break;
229 } else if (t != s) {
230 for (i = 0; i < universe_count; i++) {
231 if (strlen (universes [i] -> name) == t - s &&
232 !memcmp (universes [i] -> name,
233 s, (unsigned)(t - s))) {
234 universe = universes [i];
235 break;
239 return universe;
242 /* If an option in an option buffer turns out to be an encapsulation,
243 figure out what to do. If we don't know how to de-encapsulate it,
244 or it's not well-formed, return zero; otherwise, return 1, indicating
245 that we succeeded in de-encapsulating it. */
247 int parse_encapsulated_suboptions (struct option_state *options,
248 struct option *eopt,
249 const unsigned char *buffer,
250 unsigned len, struct universe *eu,
251 const char *uname)
253 int i;
254 struct universe *universe = find_option_universe (eopt, uname);
256 /* If we didn't find the universe, we can't do anything with it
257 right now (e.g., we can't decode vendor options until we've
258 decoded the packet and executed the scopes that it matches). */
259 if (!universe)
260 return 0;
262 /* If we don't have a decoding function for it, we can't decode
263 it. */
264 if (!universe -> decode)
265 return 0;
267 i = (*universe -> decode) (options, buffer, len, universe);
269 /* If there is stuff before the suboptions, we have to keep it. */
270 if (eopt -> format [0] != 'E')
271 return 0;
272 /* Otherwise, return the status of the decode function. */
273 return i;
276 int fqdn_universe_decode (struct option_state *options,
277 const unsigned char *buffer,
278 unsigned length, struct universe *u)
280 char *name;
281 struct buffer *bp = (struct buffer *)0;
283 /* FQDN options have to be at least four bytes long. */
284 if (length < 3)
285 return 0;
287 /* Save the contents of the option in a buffer. */
288 if (!buffer_allocate (&bp, length + 4, MDL)) {
289 log_error ("no memory for option buffer.");
290 return 0;
292 memcpy (&bp -> data [3], buffer + 1, length - 1);
294 if (buffer [0] & 4) /* encoded */
295 bp -> data [0] = 1;
296 else
297 bp -> data [0] = 0;
298 if (!save_option_buffer (&fqdn_universe, options, bp,
299 &bp -> data [0], 1,
300 &fqdn_options [FQDN_ENCODED], 0)) {
301 bad:
302 buffer_dereference (&bp, MDL);
303 return 0;
306 if (buffer [0] & 1) /* server-update */
307 bp -> data [2] = 1;
308 else
309 bp -> data [2] = 0;
310 if (buffer [0] & 2) /* no-client-update */
311 bp -> data [1] = 1;
312 else
313 bp -> data [1] = 0;
315 /* XXX Ideally we should store the name in DNS format, so if the
316 XXX label isn't in DNS format, we convert it to DNS format,
317 XXX rather than converting labels specified in DNS format to
318 XXX the plain ASCII representation. But that's hard, so
319 XXX not now. */
321 /* Not encoded using DNS format? */
322 if (!bp -> data [0]) {
323 unsigned i;
325 /* Some broken clients NUL-terminate this option. */
326 if (buffer [length - 1] == 0) {
327 --length;
328 bp -> data [1] = 1;
331 /* Determine the length of the hostname component of the
332 name. If the name contains no '.' character, it
333 represents a non-qualified label. */
334 for (i = 3; i < length && buffer [i] != '.'; i++);
335 i -= 3;
337 /* Note: If the client sends a FQDN, the first '.' will
338 be used as a NUL terminator for the hostname. */
339 if (i)
340 if (!save_option_buffer (&fqdn_universe, options, bp,
341 &bp -> data[5], i,
342 &fqdn_options [FQDN_HOSTNAME],
344 goto bad;
345 /* Note: If the client sends a single label, the
346 FQDN_DOMAINNAME option won't be set. */
347 if (length > 4 + i &&
348 !save_option_buffer (&fqdn_universe, options, bp,
349 &bp -> data[6 + i], length - 4 - i,
350 &fqdn_options [FQDN_DOMAINNAME], 1))
351 goto bad;
352 /* Also save the whole name. */
353 if (length > 3)
354 if (!save_option_buffer (&fqdn_universe, options, bp,
355 &bp -> data [5], length - 3,
356 &fqdn_options [FQDN_FQDN], 1))
357 goto bad;
358 } else {
359 unsigned len;
360 unsigned total_len = 0;
361 unsigned first_len = 0;
362 int terminated = 0;
363 unsigned char *s;
365 s = &bp -> data[5];
367 while (s < &bp -> data[0] + length + 2) {
368 len = *s;
369 if (len > 63) {
370 log_info ("fancy bits in fqdn option");
371 return 0;
373 if (len == 0) {
374 terminated = 1;
375 break;
377 if (s + len > &bp -> data [0] + length + 3) {
378 log_info ("fqdn tag longer than buffer");
379 return 0;
382 if (first_len == 0) {
383 first_len = len;
386 *s = '.';
387 s += len + 1;
388 total_len += len + 1;
391 /* We wind up with a length that's one too many because
392 we shouldn't increment for the last label, but there's
393 no way to tell we're at the last label until we exit
394 the loop. :'*/
395 if (total_len > 0)
396 total_len--;
398 if (!terminated) {
399 first_len = total_len;
402 if (first_len > 0 &&
403 !save_option_buffer (&fqdn_universe, options, bp,
404 &bp -> data[6], first_len,
405 &fqdn_options [FQDN_HOSTNAME], 0))
406 goto bad;
407 if (total_len > 0 && first_len != total_len) {
408 if (!save_option_buffer
409 (&fqdn_universe, options, bp,
410 &bp -> data[6 + first_len], total_len - first_len,
411 &fqdn_options [FQDN_DOMAINNAME], 1))
412 goto bad;
414 if (total_len > 0)
415 if (!save_option_buffer (&fqdn_universe, options, bp,
416 &bp -> data [6], total_len,
417 &fqdn_options [FQDN_FQDN], 1))
418 goto bad;
421 if (!save_option_buffer (&fqdn_universe, options, bp,
422 &bp -> data [1], 1,
423 &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
424 goto bad;
425 if (!save_option_buffer (&fqdn_universe, options, bp,
426 &bp -> data [2], 1,
427 &fqdn_options [FQDN_SERVER_UPDATE], 0))
428 goto bad;
430 if (!save_option_buffer (&fqdn_universe, options, bp,
431 &bp -> data [3], 1,
432 &fqdn_options [FQDN_RCODE1], 0))
433 goto bad;
434 if (!save_option_buffer (&fqdn_universe, options, bp,
435 &bp -> data [4], 1,
436 &fqdn_options [FQDN_RCODE2], 0))
437 goto bad;
439 buffer_dereference (&bp, MDL);
440 return 1;
443 /* cons options into a big buffer, and then split them out into the
444 three seperate buffers if needed. This allows us to cons up a set
445 of vendor options using the same routine. */
447 int cons_options (inpacket, outpacket, lease, client_state,
448 mms, in_options, cfg_options,
449 scope, overload, terminate, bootpp, prl, vuname)
450 struct packet *inpacket;
451 struct dhcp_packet *outpacket;
452 struct lease *lease;
453 struct client_state *client_state;
454 int mms;
455 struct option_state *in_options;
456 struct option_state *cfg_options;
457 struct binding_scope **scope;
458 int overload; /* Overload flags that may be set. */
459 int terminate;
460 int bootpp;
461 struct data_string *prl;
462 const char *vuname;
464 #define PRIORITY_COUNT 300
465 unsigned priority_list [PRIORITY_COUNT];
466 int priority_len;
467 unsigned char buffer [4096]; /* Really big buffer... */
468 unsigned main_buffer_size;
469 unsigned mainbufix, bufix, agentix;
470 int fileix;
471 int snameix;
472 unsigned option_size;
473 unsigned length;
474 int i;
475 struct option_cache *op;
476 struct data_string ds;
477 pair pp, *hash;
478 int need_endopt = 0;
479 int have_sso = 0;
480 int ocount = 0;
481 int ofbuf1=0, ofbuf2=0;
483 memset (&ds, 0, sizeof ds);
485 /* If there's a Maximum Message Size option in the incoming packet
486 and no alternate maximum message size has been specified, take the
487 one in the packet. */
489 if (inpacket &&
490 (op = lookup_option (&dhcp_universe, inpacket -> options,
491 DHO_DHCP_MAX_MESSAGE_SIZE))) {
492 evaluate_option_cache (&ds, inpacket,
493 lease, client_state, in_options,
494 cfg_options, scope, op, MDL);
495 if (ds.len >= sizeof (u_int16_t)) {
496 i = getUShort (ds.data);
498 if(!mms || (i < mms))
499 mms = i;
501 data_string_forget (&ds, MDL);
504 /* If the client has provided a maximum DHCP message size,
505 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
506 use up to the minimum IP MTU size (576 bytes). */
507 /* XXX if a BOOTP client specifies a max message size, we will
508 honor it. */
510 if (mms) {
511 main_buffer_size = mms - DHCP_FIXED_LEN;
513 /* Enforce a minimum packet size... */
514 if (main_buffer_size < (576 - DHCP_FIXED_LEN))
515 main_buffer_size = 576 - DHCP_FIXED_LEN;
516 } else if (bootpp) {
517 if (inpacket) {
518 main_buffer_size =
519 inpacket -> packet_length - DHCP_FIXED_LEN;
520 if (main_buffer_size < 64)
521 main_buffer_size = 64;
522 } else
523 main_buffer_size = 64;
524 } else
525 main_buffer_size = 576 - DHCP_FIXED_LEN;
527 /* Set a hard limit at the size of the output buffer. */
528 if (main_buffer_size > sizeof buffer)
529 main_buffer_size = sizeof buffer;
531 /* Preload the option priority list with mandatory options. */
532 priority_len = 0;
533 priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE;
534 priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
535 priority_list [priority_len++] = DHO_DHCP_LEASE_TIME;
536 priority_list [priority_len++] = DHO_DHCP_MESSAGE;
537 priority_list [priority_len++] = DHO_DHCP_REQUESTED_ADDRESS;
538 priority_list [priority_len++] = DHO_FQDN;
540 if (prl && prl -> len > 0) {
541 if ((op = lookup_option (&dhcp_universe, cfg_options,
542 DHO_SUBNET_SELECTION))) {
543 if (priority_len < PRIORITY_COUNT)
544 priority_list [priority_len++] =
545 DHO_SUBNET_SELECTION;
548 data_string_truncate (prl, (PRIORITY_COUNT - priority_len));
550 for (i = 0; i < prl -> len; i++) {
551 /* Prevent client from changing order of delivery
552 of relay agent information option. */
553 if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS)
554 priority_list [priority_len++] =
555 prl -> data [i];
557 } else {
558 /* First, hardcode some more options that ought to be
559 sent first... */
560 priority_list [priority_len++] = DHO_SUBNET_MASK;
561 priority_list [priority_len++] = DHO_ROUTERS;
562 priority_list [priority_len++] = DHO_DOMAIN_NAME_SERVERS;
563 priority_list [priority_len++] = DHO_HOST_NAME;
565 /* Append a list of the standard DHCP options from the
566 standard DHCP option space. Actually, if a site
567 option space hasn't been specified, we wind up
568 treating the dhcp option space as the site option
569 space, and the first for loop is skipped, because
570 it's slightly more general to do it this way,
571 taking the 1Q99 DHCP futures work into account. */
572 if (cfg_options -> site_code_min) {
573 for (i = 0; i < OPTION_HASH_SIZE; i++) {
574 hash = cfg_options -> universes [dhcp_universe.index];
575 if (hash) {
576 for (pp = hash [i]; pp; pp = pp -> cdr) {
577 op = (struct option_cache *)(pp -> car);
578 if (op -> option -> code <
579 cfg_options -> site_code_min &&
580 priority_len < PRIORITY_COUNT &&
581 (op -> option -> code !=
582 DHO_DHCP_AGENT_OPTIONS))
583 priority_list [priority_len++] =
584 op -> option -> code;
590 /* Now cycle through the site option space, or if there
591 is no site option space, we'll be cycling through the
592 dhcp option space. */
593 for (i = 0; i < OPTION_HASH_SIZE; i++) {
594 hash = (cfg_options -> universes
595 [cfg_options -> site_universe]);
596 if (hash)
597 for (pp = hash [i]; pp; pp = pp -> cdr) {
598 op = (struct option_cache *)(pp -> car);
599 if (op -> option -> code >=
600 cfg_options -> site_code_min &&
601 priority_len < PRIORITY_COUNT &&
602 (op -> option -> code !=
603 DHO_DHCP_AGENT_OPTIONS))
604 priority_list [priority_len++] =
605 op -> option -> code;
609 /* Now go through all the universes for which options
610 were set and see if there are encapsulations for
611 them; if there are, put the encapsulation options
612 on the priority list as well. */
613 for (i = 0; i < cfg_options -> universe_count; i++) {
614 if (cfg_options -> universes [i] &&
615 universes [i] -> enc_opt &&
616 priority_len < PRIORITY_COUNT &&
617 universes [i] -> enc_opt -> universe == &dhcp_universe)
619 if (universes [i] -> enc_opt -> code !=
620 DHO_DHCP_AGENT_OPTIONS)
621 priority_list [priority_len++] =
622 universes [i] -> enc_opt -> code;
626 /* The vendor option space can't stand on its own, so always
627 add it to the list. */
628 if (priority_len < PRIORITY_COUNT)
629 priority_list [priority_len++] =
630 DHO_VENDOR_ENCAPSULATED_OPTIONS;
633 /* Figure out the overload buffer offset(s). */
634 if (overload) {
635 ofbuf1 = main_buffer_size - 4;
636 if (overload == 3)
637 ofbuf2 = main_buffer_size - 4 + DHCP_FILE_LEN;
640 /* Copy the options into the big buffer... */
641 option_size = store_options (&ocount, buffer,
642 (main_buffer_size - 4 +
643 ((overload & 1) ? DHCP_FILE_LEN : 0) +
644 ((overload & 2) ? DHCP_SNAME_LEN : 0)),
645 inpacket, lease, client_state,
646 in_options, cfg_options, scope,
647 priority_list, priority_len,
648 ofbuf1, ofbuf2, terminate, vuname);
649 /* If store_options failed. */
650 if (option_size == 0)
651 return 0;
652 if (overload) {
653 if (ocount == 1 && (overload & 1))
654 overload = 1;
655 else if (ocount == 1 && (overload & 2))
656 overload = 2;
657 else if (ocount == 3)
658 overload = 3;
659 else
660 overload = 0;
663 /* Put the cookie up front... */
664 memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4);
665 mainbufix = 4;
667 /* If we're going to have to overload, store the overload
668 option at the beginning. If we can, though, just store the
669 whole thing in the packet's option buffer and leave it at
670 that. */
671 memcpy (&outpacket -> options [mainbufix],
672 buffer, option_size);
673 mainbufix += option_size;
674 if (overload) {
675 outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
676 outpacket -> options [mainbufix++] = 1;
677 outpacket -> options [mainbufix++] = overload;
679 if (overload & 1) {
680 memcpy (outpacket -> file,
681 &buffer [ofbuf1], DHCP_FILE_LEN);
683 if (overload & 2) {
684 if (ofbuf2) {
685 memcpy (outpacket -> sname, &buffer [ofbuf2],
686 DHCP_SNAME_LEN);
687 } else {
688 memcpy (outpacket -> sname, &buffer [ofbuf1],
689 DHCP_SNAME_LEN);
693 agentix = mainbufix;
694 if (mainbufix < main_buffer_size)
695 need_endopt = 1;
696 length = DHCP_FIXED_NON_UDP + mainbufix;
698 /* Now hack in the agent options if there are any. */
699 priority_list [0] = DHO_DHCP_AGENT_OPTIONS;
700 priority_len = 1;
701 agentix +=
702 store_options (0, &outpacket -> options [agentix],
703 1500 - DHCP_FIXED_LEN - agentix,
704 inpacket, lease, client_state,
705 in_options, cfg_options, scope,
706 priority_list, priority_len,
707 0, 0, 0, (char *)0);
709 /* Tack a DHO_END option onto the packet if we need to. */
710 if (agentix < 1500 - DHCP_FIXED_LEN && need_endopt)
711 outpacket -> options [agentix++] = DHO_END;
713 /* Figure out the length. */
714 length = DHCP_FIXED_NON_UDP + agentix;
715 return length;
718 /* Store all the requested options into the requested buffer. */
720 int store_options (ocount, buffer, buflen, packet, lease, client_state,
721 in_options, cfg_options, scope, priority_list, priority_len,
722 first_cutoff, second_cutoff, terminate, vuname)
723 int *ocount;
724 unsigned char *buffer;
725 unsigned buflen;
726 struct packet *packet;
727 struct lease *lease;
728 struct client_state *client_state;
729 struct option_state *in_options;
730 struct option_state *cfg_options;
731 struct binding_scope **scope;
732 unsigned *priority_list;
733 int priority_len;
734 unsigned first_cutoff, second_cutoff;
735 int terminate;
736 const char *vuname;
738 int bufix = 0, six = 0, tix = 0;
739 int i;
740 int ix;
741 int tto;
742 int bufend, sbufend;
743 struct data_string od;
744 struct option_cache *oc;
745 unsigned code;
747 if (first_cutoff) {
748 if (first_cutoff >= buflen)
749 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL);
751 bufend = first_cutoff;
752 } else
753 bufend = buflen;
755 if (second_cutoff) {
756 if (second_cutoff >= buflen)
757 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL);
759 sbufend = second_cutoff;
760 } else
761 sbufend = buflen;
763 memset (&od, 0, sizeof od);
765 /* Eliminate duplicate options in the parameter request list.
766 There's got to be some clever knuthian way to do this:
767 Eliminate all but the first occurance of a value in an array
768 of values without otherwise disturbing the order of the array. */
769 for (i = 0; i < priority_len - 1; i++) {
770 tto = 0;
771 for (ix = i + 1; ix < priority_len + tto; ix++) {
772 if (tto)
773 priority_list [ix - tto] =
774 priority_list [ix];
775 if (priority_list [i] == priority_list [ix]) {
776 tto++;
777 priority_len--;
782 /* Copy out the options in the order that they appear in the
783 priority list... */
784 for (i = 0; i < priority_len; i++) {
785 /* Number of bytes left to store (some may already
786 have been stored by a previous pass). */
787 unsigned length;
788 int optstart, soptstart, toptstart;
789 struct universe *u;
790 int have_encapsulation = 0;
791 struct data_string encapsulation;
792 int splitup;
794 memset (&encapsulation, 0, sizeof encapsulation);
796 /* Code for next option to try to store. */
797 code = priority_list [i];
799 /* Look up the option in the site option space if the code
800 is above the cutoff, otherwise in the DHCP option space. */
801 if (code >= cfg_options -> site_code_min)
802 u = universes [cfg_options -> site_universe];
803 else
804 u = &dhcp_universe;
806 oc = lookup_option (u, cfg_options, code);
808 /* It's an encapsulation, try to find the universe
809 to be encapsulated first, except that if it's a straight
810 encapsulation and the user has provided a value for the
811 encapsulation option, use the user-provided value. */
812 if (u -> options [code] &&
813 ((u -> options [code] -> format [0] == 'E' && !oc) ||
814 u -> options [code] -> format [0] == 'e')) {
815 int uix;
816 static char *s, *t;
817 struct option_cache *tmp;
818 struct data_string name;
820 s = strchr (u -> options [code] -> format, 'E');
821 if (s)
822 t = strchr (++s, '.');
823 if (s && t) {
824 memset (&name, 0, sizeof name);
826 /* A zero-length universe name means the vendor
827 option space, if one is defined. */
828 if (t == s) {
829 if (vendor_cfg_option) {
830 tmp = lookup_option (vendor_cfg_option -> universe,
831 cfg_options,
832 vendor_cfg_option -> code);
833 if (tmp)
834 evaluate_option_cache (&name, packet, lease,
835 client_state,
836 in_options,
837 cfg_options,
838 scope, tmp, MDL);
839 } else if (vuname) {
840 name.data = (unsigned char *)s;
841 name.len = strlen (s);
843 } else {
844 name.data = (unsigned char *)s;
845 name.len = t - s;
848 /* If we found a universe, and there are options configured
849 for that universe, try to encapsulate it. */
850 if (name.len) {
851 have_encapsulation =
852 (option_space_encapsulate
853 (&encapsulation, packet, lease, client_state,
854 in_options, cfg_options, scope, &name));
855 data_string_forget (&name, MDL);
860 /* In order to avoid memory leaks, we have to get to here
861 with any option cache that we allocated in tmp not being
862 referenced by tmp, and whatever option cache is referenced
863 by oc being an actual reference. lookup_option doesn't
864 generate a reference (this needs to be fixed), so the
865 preceding goop ensures that if we *didn't* generate a new
866 option cache, oc still winds up holding an actual reference. */
868 /* If no data is available for this option, skip it. */
869 if (!oc && !have_encapsulation) {
870 continue;
873 /* Find the value of the option... */
874 if (oc) {
875 evaluate_option_cache (&od, packet,
876 lease, client_state, in_options,
877 cfg_options, scope, oc, MDL);
878 if (!od.len) {
879 data_string_forget (&encapsulation, MDL);
880 data_string_forget (&od, MDL);
881 have_encapsulation = 0;
882 continue;
886 /* We should now have a constant length for the option. */
887 length = od.len;
888 if (have_encapsulation) {
889 length += encapsulation.len;
890 if (!od.len) {
891 data_string_copy (&od, &encapsulation, MDL);
892 data_string_forget (&encapsulation, MDL);
893 } else {
894 struct buffer *bp = (struct buffer *)0;
895 if (!buffer_allocate (&bp, length, MDL)) {
896 option_cache_dereference (&oc, MDL);
897 data_string_forget (&od, MDL);
898 data_string_forget (&encapsulation, MDL);
899 continue;
901 memcpy (&bp -> data [0], od.data, od.len);
902 memcpy (&bp -> data [od.len], encapsulation.data,
903 encapsulation.len);
904 data_string_forget (&od, MDL);
905 data_string_forget (&encapsulation, MDL);
906 od.data = &bp -> data [0];
907 buffer_reference (&od.buffer, bp, MDL);
908 buffer_dereference (&bp, MDL);
909 od.len = length;
910 od.terminated = 0;
914 /* Do we add a NUL? */
915 if (terminate && dhcp_options [code].format [0] == 't') {
916 length++;
917 tto = 1;
918 } else {
919 tto = 0;
922 /* Try to store the option. */
924 /* If the option's length is more than 255, we must store it
925 in multiple hunks. Store 255-byte hunks first. However,
926 in any case, if the option data will cross a buffer
927 boundary, split it across that boundary. */
930 if (length > 255)
931 splitup = 1;
932 else
933 splitup = 0;
935 ix = 0;
936 optstart = bufix;
937 soptstart = six;
938 toptstart = tix;
939 while (length) {
940 unsigned incr = length;
941 int consumed = 0;
942 int *pix;
943 char *base;
945 /* Try to fit it in the options buffer. */
946 if (!splitup &&
947 ((!six && !tix && (i == priority_len - 1) &&
948 (bufix + 2 + length < bufend)) ||
949 (bufix + 5 + length < bufend))) {
950 base = buffer;
951 pix = &bufix;
952 /* Try to fit it in the second buffer. */
953 } else if (!splitup && first_cutoff &&
954 (first_cutoff + six + 3 + length < sbufend)) {
955 base = &buffer[first_cutoff];
956 pix = &six;
957 /* Try to fit it in the third buffer. */
958 } else if (!splitup && second_cutoff &&
959 (second_cutoff + tix + 3 + length < buflen)) {
960 base = &buffer[second_cutoff];
961 pix = &tix;
962 /* Split the option up into the remaining space. */
963 } else {
964 splitup = 1;
966 /* Use any remaining options space. */
967 if (bufix + 6 < bufend) {
968 incr = bufend - bufix - 5;
969 base = buffer;
970 pix = &bufix;
971 /* Use any remaining first_cutoff space. */
972 } else if (first_cutoff &&
973 (first_cutoff + six + 4 < sbufend)) {
974 incr = sbufend - (first_cutoff + six) - 3;
975 base = &buffer[first_cutoff];
976 pix = &six;
977 /* Use any remaining second_cutoff space. */
978 } else if (second_cutoff &&
979 (second_cutoff + tix + 4 < buflen)) {
980 incr = buflen - (second_cutoff + tix) - 3;
981 base = &buffer[second_cutoff];
982 pix = &tix;
983 /* Give up, roll back this option. */
984 } else {
985 bufix = optstart;
986 six = soptstart;
987 tix = toptstart;
988 break;
992 if (incr > length)
993 incr = length;
994 if (incr > 255)
995 incr = 255;
997 /* Everything looks good - copy it in! */
998 base [*pix] = code;
999 base [*pix + 1] = (unsigned char)incr;
1000 if (tto && incr == length) {
1001 if (incr > 1)
1002 memcpy (base + *pix + 2,
1003 od.data + ix, (unsigned)(incr - 1));
1004 base [*pix + 2 + incr - 1] = 0;
1005 } else {
1006 memcpy (base + *pix + 2,
1007 od.data + ix, (unsigned)incr);
1009 length -= incr;
1010 ix += incr;
1011 *pix += 2 + incr;
1013 data_string_forget (&od, MDL);
1016 /* If we can overload, and we have, then PAD and END those spaces. */
1017 if (first_cutoff && six) {
1018 if ((first_cutoff + six + 1) < sbufend)
1019 memset (&buffer[first_cutoff + six + 1], DHO_PAD,
1020 sbufend - (first_cutoff + six + 1));
1021 else if (first_cutoff + six >= sbufend)
1022 log_fatal("Second buffer overflow in overloaded options.");
1024 buffer[first_cutoff + six] = DHO_END;
1025 *ocount |= 1; /* So that caller knows there's data there. */
1028 if (second_cutoff && tix) {
1029 if (second_cutoff + tix + 1 < buflen) {
1030 memset (&buffer[second_cutoff + tix + 1], DHO_PAD,
1031 buflen - (second_cutoff + tix + 1));
1032 } else if (second_cutoff + tix >= buflen)
1033 log_fatal("Third buffer overflow in overloaded options.");
1035 buffer[second_cutoff + tix] = DHO_END;
1036 *ocount |= 2; /* So that caller knows there's data there. */
1039 if ((six || tix) && (bufix + 3 > bufend))
1040 log_fatal("Not enough space for option overload option.");
1042 return bufix;
1045 /* Format the specified option so that a human can easily read it. */
1047 const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
1048 struct option *option;
1049 const unsigned char *data;
1050 unsigned len;
1051 int emit_commas;
1052 int emit_quotes;
1054 static char optbuf [32768]; /* XXX */
1055 int hunksize = 0;
1056 int opthunk = 0;
1057 int hunkinc = 0;
1058 int numhunk = -1;
1059 int numelem = 0;
1060 char fmtbuf [32];
1061 struct enumeration *enumbuf [32];
1062 int i, j, k, l;
1063 char *op = optbuf;
1064 const unsigned char *dp = data;
1065 struct in_addr foo;
1066 char comma;
1067 unsigned long tval;
1069 if (emit_commas)
1070 comma = ',';
1071 else
1072 comma = ' ';
1074 memset (enumbuf, 0, sizeof enumbuf);
1076 /* Figure out the size of the data. */
1077 for (l = i = 0; option -> format [i]; i++, l++) {
1078 if (!numhunk) {
1079 log_error ("%s: Extra codes in format string: %s",
1080 option -> name,
1081 &(option -> format [i]));
1082 break;
1084 numelem++;
1085 fmtbuf [l] = option -> format [i];
1086 switch (option -> format [i]) {
1087 case 'a':
1088 --numelem;
1089 fmtbuf [l] = 0;
1090 numhunk = 0;
1091 break;
1092 case 'A':
1093 --numelem;
1094 fmtbuf [l] = 0;
1095 numhunk = 0;
1096 break;
1097 case 'E':
1098 /* Skip the universe name. */
1099 while (option -> format [i] &&
1100 option -> format [i] != '.')
1101 i++;
1102 case 'X':
1103 for (k = 0; k < len; k++) {
1104 if (!isascii (data [k]) ||
1105 !isprint (data [k]))
1106 break;
1108 /* If we found no bogus characters, or the bogus
1109 character we found is a trailing NUL, it's
1110 okay to print this option as text. */
1111 if (k == len || (k + 1 == len && data [k] == 0)) {
1112 fmtbuf [l] = 't';
1113 numhunk = -2;
1114 } else {
1115 fmtbuf [l] = 'x';
1116 hunksize++;
1117 comma = ':';
1118 numhunk = 0;
1120 fmtbuf [l + 1] = 0;
1121 break;
1122 case 'd':
1123 case 't':
1124 fmtbuf [l] = 't';
1125 fmtbuf [l + 1] = 0;
1126 numhunk = -2;
1127 break;
1128 case 'N':
1129 k = i;
1130 while (option -> format [i] &&
1131 option -> format [i] != '.')
1132 i++;
1133 enumbuf [l] =
1134 find_enumeration (&option -> format [k] + 1,
1135 i - k - 1);
1136 hunksize += 1;
1137 hunkinc = 1;
1138 break;
1139 case 'I':
1140 case 'l':
1141 case 'L':
1142 case 'T':
1143 hunksize += 4;
1144 hunkinc = 4;
1145 break;
1146 case 's':
1147 case 'S':
1148 hunksize += 2;
1149 hunkinc = 2;
1150 break;
1151 case 'b':
1152 case 'B':
1153 case 'f':
1154 hunksize++;
1155 hunkinc = 1;
1156 break;
1157 case 'e':
1158 break;
1159 case 'o':
1160 opthunk += hunkinc;
1161 break;
1162 default:
1163 log_error ("%s: garbage in format string: %s",
1164 option -> name,
1165 &(option -> format [i]));
1166 break;
1170 /* Check for too few bytes... */
1171 if (hunksize - opthunk > len) {
1172 log_error ("%s: expecting at least %d bytes; got %d",
1173 option -> name,
1174 hunksize, len);
1175 return "<error>";
1177 /* Check for too many bytes... */
1178 if (numhunk == -1 && hunksize < len)
1179 log_error ("%s: %d extra bytes",
1180 option -> name,
1181 len - hunksize);
1183 /* If this is an array, compute its size. */
1184 if (!numhunk)
1185 numhunk = len / hunksize;
1186 /* See if we got an exact number of hunks. */
1187 if (numhunk > 0 && numhunk * hunksize < len)
1188 log_error ("%s: %d extra bytes at end of array\n",
1189 option -> name,
1190 len - numhunk * hunksize);
1192 /* A one-hunk array prints the same as a single hunk. */
1193 if (numhunk < 0)
1194 numhunk = 1;
1196 /* Cycle through the array (or hunk) printing the data. */
1197 for (i = 0; i < numhunk; i++) {
1198 for (j = 0; j < numelem; j++) {
1199 switch (fmtbuf [j]) {
1200 case 't':
1201 if (emit_quotes)
1202 *op++ = '"';
1203 for (; dp < data + len; dp++) {
1204 if (!isascii (*dp) ||
1205 !isprint (*dp)) {
1206 /* Skip trailing NUL. */
1207 if (dp + 1 != data + len ||
1208 *dp != 0) {
1209 sprintf (op, "\\%03o",
1210 *dp);
1211 op += 4;
1213 } else if (*dp == '"' ||
1214 *dp == '\'' ||
1215 *dp == '$' ||
1216 *dp == '`' ||
1217 *dp == '\\') {
1218 *op++ = '\\';
1219 *op++ = *dp;
1220 } else
1221 *op++ = *dp;
1223 if (emit_quotes)
1224 *op++ = '"';
1225 *op = 0;
1226 break;
1227 /* pretty-printing an array of enums is
1228 going to get ugly. */
1229 case 'N':
1230 if (!enumbuf [j])
1231 goto enum_as_num;
1232 for (i = 0; ;i++) {
1233 if (!enumbuf [j] -> values [i].name)
1234 goto enum_as_num;
1235 if (enumbuf [j] -> values [i].value ==
1236 *dp)
1237 break;
1239 strcpy (op, enumbuf [j] -> values [i].name);
1240 op += strlen (op);
1241 break;
1242 case 'I':
1243 foo.s_addr = htonl (getULong (dp));
1244 strcpy (op, inet_ntoa (foo));
1245 dp += 4;
1246 break;
1247 case 'l':
1248 sprintf (op, "%ld", (long)getLong (dp));
1249 dp += 4;
1250 break;
1251 case 'T':
1252 tval = getULong (dp);
1253 if (tval == -1)
1254 sprintf (op, "%s", "infinite");
1255 else
1256 sprintf (op, "%ld", tval);
1257 break;
1258 case 'L':
1259 sprintf (op, "%ld",
1260 (unsigned long)getULong (dp));
1261 dp += 4;
1262 break;
1263 case 's':
1264 sprintf (op, "%d", (int)getShort (dp));
1265 dp += 2;
1266 break;
1267 case 'S':
1268 sprintf (op, "%d", (unsigned)getUShort (dp));
1269 dp += 2;
1270 break;
1271 case 'b':
1272 sprintf (op, "%d", *(const char *)dp++);
1273 break;
1274 case 'B':
1275 enum_as_num:
1276 sprintf (op, "%d", *dp++);
1277 break;
1278 case 'x':
1279 sprintf (op, "%x", *dp++);
1280 break;
1281 case 'f':
1282 strcpy (op, *dp++ ? "true" : "false");
1283 break;
1284 default:
1285 log_error ("Unexpected format code %c",
1286 fmtbuf [j]);
1288 op += strlen (op);
1289 if (dp == data + len)
1290 break;
1291 if (j + 1 < numelem && comma != ':')
1292 *op++ = ' ';
1294 if (i + 1 < numhunk) {
1295 *op++ = comma;
1297 if (dp == data + len)
1298 break;
1300 return optbuf;
1303 int get_option (result, universe, packet, lease, client_state,
1304 in_options, cfg_options, options, scope, code, file, line)
1305 struct data_string *result;
1306 struct universe *universe;
1307 struct packet *packet;
1308 struct lease *lease;
1309 struct client_state *client_state;
1310 struct option_state *in_options;
1311 struct option_state *cfg_options;
1312 struct option_state *options;
1313 struct binding_scope **scope;
1314 unsigned code;
1315 const char *file;
1316 int line;
1318 struct option_cache *oc;
1320 if (!universe -> lookup_func)
1321 return 0;
1322 oc = ((*universe -> lookup_func) (universe, options, code));
1323 if (!oc)
1324 return 0;
1325 if (!evaluate_option_cache (result, packet, lease, client_state,
1326 in_options, cfg_options, scope, oc,
1327 file, line))
1328 return 0;
1329 return 1;
1332 void set_option (universe, options, option, op)
1333 struct universe *universe;
1334 struct option_state *options;
1335 struct option_cache *option;
1336 enum statement_op op;
1338 struct option_cache *oc, *noc;
1340 switch (op) {
1341 case if_statement:
1342 case add_statement:
1343 case eval_statement:
1344 case break_statement:
1345 default:
1346 log_error ("bogus statement type in do_option_set.");
1347 break;
1349 case default_option_statement:
1350 oc = lookup_option (universe, options,
1351 option -> option -> code);
1352 if (oc)
1353 break;
1354 save_option (universe, options, option);
1355 break;
1357 case supersede_option_statement:
1358 case send_option_statement:
1359 /* Install the option, replacing any existing version. */
1360 save_option (universe, options, option);
1361 break;
1363 case append_option_statement:
1364 case prepend_option_statement:
1365 oc = lookup_option (universe, options,
1366 option -> option -> code);
1367 if (!oc) {
1368 save_option (universe, options, option);
1369 break;
1371 /* If it's not an expression, make it into one. */
1372 if (!oc -> expression && oc -> data.len) {
1373 if (!expression_allocate (&oc -> expression, MDL)) {
1374 log_error ("Can't allocate const expression.");
1375 break;
1377 oc -> expression -> op = expr_const_data;
1378 data_string_copy
1379 (&oc -> expression -> data.const_data,
1380 &oc -> data, MDL);
1381 data_string_forget (&oc -> data, MDL);
1383 noc = (struct option_cache *)0;
1384 if (!option_cache_allocate (&noc, MDL))
1385 break;
1386 if (op == append_option_statement) {
1387 if (!make_concat (&noc -> expression,
1388 oc -> expression,
1389 option -> expression)) {
1390 option_cache_dereference (&noc, MDL);
1391 break;
1393 } else {
1394 if (!make_concat (&noc -> expression,
1395 option -> expression,
1396 oc -> expression)) {
1397 option_cache_dereference (&noc, MDL);
1398 break;
1401 noc -> option = oc -> option;
1402 save_option (universe, options, noc);
1403 option_cache_dereference (&noc, MDL);
1404 break;
1408 struct option_cache *lookup_option (universe, options, code)
1409 struct universe *universe;
1410 struct option_state *options;
1411 unsigned code;
1413 if (!options)
1414 return (struct option_cache *)0;
1415 if (universe -> lookup_func)
1416 return (*universe -> lookup_func) (universe, options, code);
1417 else
1418 log_error ("can't look up options in %s space.",
1419 universe -> name);
1420 return (struct option_cache *)0;
1423 struct option_cache *lookup_hashed_option (universe, options, code)
1424 struct universe *universe;
1425 struct option_state *options;
1426 unsigned code;
1428 int hashix;
1429 pair bptr;
1430 pair *hash;
1432 /* Make sure there's a hash table. */
1433 if (universe -> index >= options -> universe_count ||
1434 !(options -> universes [universe -> index]))
1435 return (struct option_cache *)0;
1437 hash = options -> universes [universe -> index];
1439 hashix = compute_option_hash (code);
1440 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1441 if (((struct option_cache *)(bptr -> car)) -> option -> code ==
1442 code)
1443 return (struct option_cache *)(bptr -> car);
1445 return (struct option_cache *)0;
1448 int save_option_buffer (struct universe *universe,
1449 struct option_state *options,
1450 struct buffer *bp,
1451 unsigned char *buffer, unsigned length,
1452 struct option *option, int tp)
1454 struct buffer *lbp = (struct buffer *)0;
1455 struct option_cache *op = (struct option_cache *)0;
1457 if (!option_cache_allocate (&op, MDL)) {
1458 log_error ("No memory for option %s.%s.",
1459 universe -> name,
1460 option -> name);
1461 return 0;
1464 /* If we weren't passed a buffer in which the data are saved and
1465 refcounted, allocate one now. */
1466 if (!bp) {
1467 if (!buffer_allocate (&lbp, length, MDL)) {
1468 log_error ("no memory for option buffer.");
1470 option_cache_dereference (&op, MDL);
1471 return 0;
1473 memcpy (lbp -> data, buffer, length + tp);
1474 bp = lbp;
1475 buffer = &bp -> data [0]; /* Refer to saved buffer. */
1478 /* Reference buffer copy to option cache. */
1479 op -> data.buffer = (struct buffer *)0;
1480 buffer_reference (&op -> data.buffer, bp, MDL);
1482 /* Point option cache into buffer. */
1483 op -> data.data = buffer;
1484 op -> data.len = length;
1486 if (tp) {
1487 /* NUL terminate (we can get away with this because we (or
1488 the caller!) allocated one more than the buffer size, and
1489 because the byte following the end of an option is always
1490 the code of the next option, which the caller is getting
1491 out of the *original* buffer. */
1492 buffer [length] = 0;
1493 op -> data.terminated = 1;
1494 } else
1495 op -> data.terminated = 0;
1497 op -> option = option;
1499 /* Now store the option. */
1500 save_option (universe, options, op);
1502 /* And let go of our reference. */
1503 option_cache_dereference (&op, MDL);
1505 return 1;
1508 void save_option (struct universe *universe,
1509 struct option_state *options, struct option_cache *oc)
1511 if (universe -> save_func)
1512 (*universe -> save_func) (universe, options, oc);
1513 else
1514 log_error ("can't store options in %s space.",
1515 universe -> name);
1518 void save_hashed_option (universe, options, oc)
1519 struct universe *universe;
1520 struct option_state *options;
1521 struct option_cache *oc;
1523 int hashix;
1524 pair bptr;
1525 pair *hash = options -> universes [universe -> index];
1527 if (oc -> refcnt == 0)
1528 abort ();
1530 /* Compute the hash. */
1531 hashix = compute_option_hash (oc -> option -> code);
1533 /* If there's no hash table, make one. */
1534 if (!hash) {
1535 hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL);
1536 if (!hash) {
1537 log_error ("no memory to store %s.%s",
1538 universe -> name, oc -> option -> name);
1539 return;
1541 memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash);
1542 options -> universes [universe -> index] = (VOIDPTR)hash;
1543 } else {
1544 /* Try to find an existing option matching the new one. */
1545 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1546 if (((struct option_cache *)
1547 (bptr -> car)) -> option -> code ==
1548 oc -> option -> code)
1549 break;
1552 /* If we find one, dereference it and put the new one
1553 in its place. */
1554 if (bptr) {
1555 option_cache_dereference
1556 ((struct option_cache **)&bptr -> car, MDL);
1557 option_cache_reference
1558 ((struct option_cache **)&bptr -> car,
1559 oc, MDL);
1560 return;
1564 /* Otherwise, just put the new one at the head of the list. */
1565 bptr = new_pair (MDL);
1566 if (!bptr) {
1567 log_error ("No memory for option_cache reference.");
1568 return;
1570 bptr -> cdr = hash [hashix];
1571 bptr -> car = 0;
1572 option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL);
1573 hash [hashix] = bptr;
1576 void delete_option (universe, options, code)
1577 struct universe *universe;
1578 struct option_state *options;
1579 int code;
1581 if (universe -> delete_func)
1582 (*universe -> delete_func) (universe, options, code);
1583 else
1584 log_error ("can't delete options from %s space.",
1585 universe -> name);
1588 void delete_hashed_option (universe, options, code)
1589 struct universe *universe;
1590 struct option_state *options;
1591 int code;
1593 int hashix;
1594 pair bptr, prev = (pair)0;
1595 pair *hash = options -> universes [universe -> index];
1597 /* There may not be any options in this space. */
1598 if (!hash)
1599 return;
1601 /* Try to find an existing option matching the new one. */
1602 hashix = compute_option_hash (code);
1603 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1604 if (((struct option_cache *)(bptr -> car)) -> option -> code
1605 == code)
1606 break;
1607 prev = bptr;
1609 /* If we found one, wipe it out... */
1610 if (bptr) {
1611 if (prev)
1612 prev -> cdr = bptr -> cdr;
1613 else
1614 hash [hashix] = bptr -> cdr;
1615 option_cache_dereference
1616 ((struct option_cache **)(&bptr -> car), MDL);
1617 free_pair (bptr, MDL);
1621 extern struct option_cache *free_option_caches; /* XXX */
1623 int option_cache_dereference (ptr, file, line)
1624 struct option_cache **ptr;
1625 const char *file;
1626 int line;
1628 if (!ptr || !*ptr) {
1629 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1630 file, line);
1631 #if defined (POINTER_DEBUG)
1632 abort ();
1633 #else
1634 return 0;
1635 #endif
1638 (*ptr) -> refcnt--;
1639 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
1640 if (!(*ptr) -> refcnt) {
1641 if ((*ptr) -> data.buffer)
1642 data_string_forget (&(*ptr) -> data, file, line);
1643 if ((*ptr) -> expression)
1644 expression_dereference (&(*ptr) -> expression,
1645 file, line);
1646 if ((*ptr) -> next)
1647 option_cache_dereference (&((*ptr) -> next),
1648 file, line);
1649 /* Put it back on the free list... */
1650 (*ptr) -> expression = (struct expression *)free_option_caches;
1651 free_option_caches = *ptr;
1652 dmalloc_reuse (free_option_caches, (char *)0, 0, 0);
1654 if ((*ptr) -> refcnt < 0) {
1655 log_error ("%s(%d): negative refcnt!", file, line);
1656 #if defined (DEBUG_RC_HISTORY)
1657 dump_rc_history (*ptr);
1658 #endif
1659 #if defined (POINTER_DEBUG)
1660 abort ();
1661 #else
1662 *ptr = (struct option_cache *)0;
1663 return 0;
1664 #endif
1666 *ptr = (struct option_cache *)0;
1667 return 1;
1671 int hashed_option_state_dereference (universe, state, file, line)
1672 struct universe *universe;
1673 struct option_state *state;
1674 const char *file;
1675 int line;
1677 pair *heads;
1678 pair cp, next;
1679 int i;
1681 /* Get the pointer to the array of hash table bucket heads. */
1682 heads = (pair *)(state -> universes [universe -> index]);
1683 if (!heads)
1684 return 0;
1686 /* For each non-null head, loop through all the buckets dereferencing
1687 the attached option cache structures and freeing the buckets. */
1688 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1689 for (cp = heads [i]; cp; cp = next) {
1690 next = cp -> cdr;
1691 option_cache_dereference
1692 ((struct option_cache **)&cp -> car,
1693 file, line);
1694 free_pair (cp, file, line);
1698 dfree (heads, file, line);
1699 state -> universes [universe -> index] = (void *)0;
1700 return 1;
1703 int store_option (result, universe, packet, lease, client_state,
1704 in_options, cfg_options, scope, oc)
1705 struct data_string *result;
1706 struct universe *universe;
1707 struct packet *packet;
1708 struct lease *lease;
1709 struct client_state *client_state;
1710 struct option_state *in_options;
1711 struct option_state *cfg_options;
1712 struct binding_scope **scope;
1713 struct option_cache *oc;
1715 struct data_string d1, d2;
1717 memset (&d1, 0, sizeof d1);
1718 memset (&d2, 0, sizeof d2);
1720 if (evaluate_option_cache (&d2, packet, lease, client_state,
1721 in_options, cfg_options, scope, oc, MDL)) {
1722 if (!buffer_allocate (&d1.buffer,
1723 (result -> len +
1724 universe -> length_size +
1725 universe -> tag_size + d2.len), MDL)) {
1726 data_string_forget (result, MDL);
1727 data_string_forget (&d2, MDL);
1728 return 0;
1730 d1.data = &d1.buffer -> data [0];
1731 if (result -> len)
1732 memcpy (d1.buffer -> data,
1733 result -> data, result -> len);
1734 d1.len = result -> len;
1735 (*universe -> store_tag) (&d1.buffer -> data [d1.len],
1736 oc -> option -> code);
1737 d1.len += universe -> tag_size;
1738 (*universe -> store_length) (&d1.buffer -> data [d1.len],
1739 d2.len);
1740 d1.len += universe -> length_size;
1741 memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len);
1742 d1.len += d2.len;
1743 data_string_forget (&d2, MDL);
1744 data_string_forget (result, MDL);
1745 data_string_copy (result, &d1, MDL);
1746 data_string_forget (&d1, MDL);
1747 return 1;
1749 return 0;
1752 int option_space_encapsulate (result, packet, lease, client_state,
1753 in_options, cfg_options, scope, name)
1754 struct data_string *result;
1755 struct packet *packet;
1756 struct lease *lease;
1757 struct client_state *client_state;
1758 struct option_state *in_options;
1759 struct option_state *cfg_options;
1760 struct binding_scope **scope;
1761 struct data_string *name;
1763 struct universe *u;
1765 u = (struct universe *)0;
1766 universe_hash_lookup (&u, universe_hash,
1767 (const char *)name -> data, name -> len, MDL);
1768 if (!u)
1769 return 0;
1771 if (u -> encapsulate)
1772 return (*u -> encapsulate) (result, packet, lease,
1773 client_state,
1774 in_options, cfg_options, scope, u);
1775 log_error ("encapsulation requested for %s with no support.",
1776 name -> data);
1777 return 0;
1780 int hashed_option_space_encapsulate (result, packet, lease, client_state,
1781 in_options, cfg_options, scope, universe)
1782 struct data_string *result;
1783 struct packet *packet;
1784 struct lease *lease;
1785 struct client_state *client_state;
1786 struct option_state *in_options;
1787 struct option_state *cfg_options;
1788 struct binding_scope **scope;
1789 struct universe *universe;
1791 pair p, *hash;
1792 int status;
1793 int i;
1795 if (universe -> index >= cfg_options -> universe_count)
1796 return 0;
1798 hash = cfg_options -> universes [universe -> index];
1799 if (!hash)
1800 return 0;
1802 status = 0;
1803 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1804 for (p = hash [i]; p; p = p -> cdr) {
1805 if (store_option (result, universe, packet,
1806 lease, client_state, in_options,
1807 cfg_options, scope,
1808 (struct option_cache *)p -> car))
1809 status = 1;
1813 return status;
1816 int nwip_option_space_encapsulate (result, packet, lease, client_state,
1817 in_options, cfg_options, scope, universe)
1818 struct data_string *result;
1819 struct packet *packet;
1820 struct lease *lease;
1821 struct client_state *client_state;
1822 struct option_state *in_options;
1823 struct option_state *cfg_options;
1824 struct binding_scope **scope;
1825 struct universe *universe;
1827 pair ocp;
1828 int status;
1829 int i;
1830 static struct option_cache *no_nwip;
1831 struct data_string ds;
1832 struct option_chain_head *head;
1834 if (universe -> index >= cfg_options -> universe_count)
1835 return 0;
1836 head = ((struct option_chain_head *)
1837 cfg_options -> universes [fqdn_universe.index]);
1838 if (!head)
1839 return 0;
1841 status = 0;
1842 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
1843 struct option_cache *oc = (struct option_cache *)(ocp -> car);
1844 if (store_option (result, universe, packet,
1845 lease, client_state, in_options,
1846 cfg_options, scope,
1847 (struct option_cache *)ocp -> car))
1848 status = 1;
1851 /* If there's no data, the nwip suboption is supposed to contain
1852 a suboption saying there's no data. */
1853 if (!status) {
1854 if (!no_nwip) {
1855 static unsigned char nni [] = { 1, 0 };
1856 memset (&ds, 0, sizeof ds);
1857 ds.data = nni;
1858 ds.len = 2;
1859 if (option_cache_allocate (&no_nwip, MDL))
1860 data_string_copy (&no_nwip -> data, &ds, MDL);
1861 no_nwip -> option = nwip_universe.options [1];
1863 if (no_nwip) {
1864 if (store_option (result, universe, packet, lease,
1865 client_state, in_options,
1866 cfg_options, scope, no_nwip))
1867 status = 1;
1869 } else {
1870 memset (&ds, 0, sizeof ds);
1872 /* If we have nwip options, the first one has to be the
1873 nwip-exists-in-option-area option. */
1874 if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) {
1875 data_string_forget (result, MDL);
1876 return 0;
1878 ds.data = &ds.buffer -> data [0];
1879 ds.buffer -> data [0] = 2;
1880 ds.buffer -> data [1] = 0;
1881 memcpy (&ds.buffer -> data [2], result -> data, result -> len);
1882 data_string_forget (result, MDL);
1883 data_string_copy (result, &ds, MDL);
1884 data_string_forget (&ds, MDL);
1887 return status;
1890 int fqdn_option_space_encapsulate (result, packet, lease, client_state,
1891 in_options, cfg_options, scope, universe)
1892 struct data_string *result;
1893 struct packet *packet;
1894 struct lease *lease;
1895 struct client_state *client_state;
1896 struct option_state *in_options;
1897 struct option_state *cfg_options;
1898 struct binding_scope **scope;
1899 struct universe *universe;
1901 pair ocp;
1902 struct data_string results [FQDN_SUBOPTION_COUNT + 1];
1903 unsigned i;
1904 unsigned len;
1905 struct buffer *bp = (struct buffer *)0;
1906 struct option_chain_head *head;
1908 /* If there's no FQDN universe, don't encapsulate. */
1909 if (fqdn_universe.index >= cfg_options -> universe_count)
1910 return 0;
1911 head = ((struct option_chain_head *)
1912 cfg_options -> universes [fqdn_universe.index]);
1913 if (!head)
1914 return 0;
1916 /* Figure out the values of all the suboptions. */
1917 memset (results, 0, sizeof results);
1918 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
1919 struct option_cache *oc = (struct option_cache *)(ocp -> car);
1920 if (oc -> option -> code > FQDN_SUBOPTION_COUNT)
1921 continue;
1922 evaluate_option_cache (&results [oc -> option -> code],
1923 packet, lease, client_state, in_options,
1924 cfg_options, scope, oc, MDL);
1926 len = 4 + results [FQDN_FQDN].len;
1927 /* Save the contents of the option in a buffer. */
1928 if (!buffer_allocate (&bp, len, MDL)) {
1929 log_error ("no memory for option buffer.");
1930 return 0;
1932 buffer_reference (&result -> buffer, bp, MDL);
1933 result -> len = 3;
1934 result -> data = &bp -> data [0];
1936 memset (&bp -> data [0], 0, len);
1937 if (results [FQDN_NO_CLIENT_UPDATE].len &&
1938 results [FQDN_NO_CLIENT_UPDATE].data [0])
1939 bp -> data [0] |= 2;
1940 if (results [FQDN_SERVER_UPDATE].len &&
1941 results [FQDN_SERVER_UPDATE].data [0])
1942 bp -> data [0] |= 1;
1943 if (results [FQDN_RCODE1].len)
1944 bp -> data [1] = results [FQDN_RCODE1].data [0];
1945 if (results [FQDN_RCODE2].len)
1946 bp -> data [2] = results [FQDN_RCODE2].data [0];
1948 if (results [FQDN_ENCODED].len &&
1949 results [FQDN_ENCODED].data [0]) {
1950 unsigned char *out;
1951 int i;
1952 bp -> data [0] |= 4;
1953 out = &bp -> data [3];
1954 if (results [FQDN_FQDN].len) {
1955 i = 0;
1956 while (i < results [FQDN_FQDN].len) {
1957 int j;
1958 for (j = i; ('.' !=
1959 results [FQDN_FQDN].data [j]) &&
1960 j < results [FQDN_FQDN].len; j++)
1962 *out++ = j - i;
1963 memcpy (out, &results [FQDN_FQDN].data [i],
1964 (unsigned)(j - i));
1965 out += j - i;
1966 i = j;
1967 if (results [FQDN_FQDN].data [j] == '.')
1968 i++;
1970 if ((results [FQDN_FQDN].data
1971 [results [FQDN_FQDN].len - 1] == '.'))
1972 *out++ = 0;
1973 result -> len = out - result -> data;
1974 result -> terminated = 0;
1976 } else {
1977 if (results [FQDN_FQDN].len) {
1978 memcpy (&bp -> data [3], results [FQDN_FQDN].data,
1979 results [FQDN_FQDN].len);
1980 result -> len += results [FQDN_FQDN].len;
1981 result -> terminated = 0;
1984 for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) {
1985 if (results [i].len)
1986 data_string_forget (&results [i], MDL);
1988 buffer_dereference (&bp, MDL);
1989 return 1;
1992 void option_space_foreach (struct packet *packet, struct lease *lease,
1993 struct client_state *client_state,
1994 struct option_state *in_options,
1995 struct option_state *cfg_options,
1996 struct binding_scope **scope,
1997 struct universe *u, void *stuff,
1998 void (*func) (struct option_cache *,
1999 struct packet *,
2000 struct lease *, struct client_state *,
2001 struct option_state *,
2002 struct option_state *,
2003 struct binding_scope **,
2004 struct universe *, void *))
2006 if (u -> foreach)
2007 (*u -> foreach) (packet, lease, client_state, in_options,
2008 cfg_options, scope, u, stuff, func);
2011 void suboption_foreach (struct packet *packet, struct lease *lease,
2012 struct client_state *client_state,
2013 struct option_state *in_options,
2014 struct option_state *cfg_options,
2015 struct binding_scope **scope,
2016 struct universe *u, void *stuff,
2017 void (*func) (struct option_cache *,
2018 struct packet *,
2019 struct lease *, struct client_state *,
2020 struct option_state *,
2021 struct option_state *,
2022 struct binding_scope **,
2023 struct universe *, void *),
2024 struct option_cache *oc,
2025 const char *vsname)
2027 struct universe *universe = find_option_universe (oc -> option,
2028 vsname);
2029 int i;
2031 if (universe -> foreach)
2032 (*universe -> foreach) (packet, lease, client_state,
2033 in_options, cfg_options,
2034 scope, universe, stuff, func);
2037 void hashed_option_space_foreach (struct packet *packet, struct lease *lease,
2038 struct client_state *client_state,
2039 struct option_state *in_options,
2040 struct option_state *cfg_options,
2041 struct binding_scope **scope,
2042 struct universe *u, void *stuff,
2043 void (*func) (struct option_cache *,
2044 struct packet *,
2045 struct lease *,
2046 struct client_state *,
2047 struct option_state *,
2048 struct option_state *,
2049 struct binding_scope **,
2050 struct universe *, void *))
2052 pair *hash;
2053 int i;
2054 struct option_cache *oc;
2056 if (cfg_options -> universe_count <= u -> index)
2057 return;
2059 hash = cfg_options -> universes [u -> index];
2060 if (!hash)
2061 return;
2062 for (i = 0; i < OPTION_HASH_SIZE; i++) {
2063 pair p;
2064 /* XXX save _all_ options! XXX */
2065 for (p = hash [i]; p; p = p -> cdr) {
2066 oc = (struct option_cache *)p -> car;
2067 (*func) (oc, packet, lease, client_state,
2068 in_options, cfg_options, scope, u, stuff);
2073 void save_linked_option (universe, options, oc)
2074 struct universe *universe;
2075 struct option_state *options;
2076 struct option_cache *oc;
2078 pair *tail;
2079 pair np = (pair )0;
2080 struct option_chain_head *head;
2082 if (universe -> index >= options -> universe_count)
2083 return;
2084 head = ((struct option_chain_head *)
2085 options -> universes [universe -> index]);
2086 if (!head) {
2087 if (!option_chain_head_allocate (((struct option_chain_head **)
2088 &options -> universes
2089 [universe -> index]), MDL))
2090 return;
2091 head = ((struct option_chain_head *)
2092 options -> universes [universe -> index]);
2095 /* Find the tail of the list. */
2096 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2097 if (oc -> option ==
2098 ((struct option_cache *)((*tail) -> car)) -> option) {
2099 option_cache_dereference ((struct option_cache **)
2100 (&(*tail) -> car), MDL);
2101 option_cache_reference ((struct option_cache **)
2102 (&(*tail) -> car), oc, MDL);
2103 return;
2107 *tail = cons (0, 0);
2108 if (*tail) {
2109 option_cache_reference ((struct option_cache **)
2110 (&(*tail) -> car), oc, MDL);
2114 int linked_option_space_encapsulate (result, packet, lease, client_state,
2115 in_options, cfg_options, scope, universe)
2116 struct data_string *result;
2117 struct packet *packet;
2118 struct lease *lease;
2119 struct client_state *client_state;
2120 struct option_state *in_options;
2121 struct option_state *cfg_options;
2122 struct binding_scope **scope;
2123 struct universe *universe;
2125 int status;
2126 pair oc;
2127 struct option_chain_head *head;
2129 if (universe -> index >= cfg_options -> universe_count)
2130 return 0;
2131 head = ((struct option_chain_head *)
2132 cfg_options -> universes [universe -> index]);
2133 if (!head)
2134 return 0;
2136 status = 0;
2137 for (oc = head -> first; oc; oc = oc -> cdr) {
2138 if (store_option (result, universe, packet,
2139 lease, client_state, in_options, cfg_options,
2140 scope, (struct option_cache *)(oc -> car)))
2141 status = 1;
2144 return status;
2147 void delete_linked_option (universe, options, code)
2148 struct universe *universe;
2149 struct option_state *options;
2150 int code;
2152 pair *tail, tmp = (pair)0;
2153 struct option_chain_head *head;
2155 if (universe -> index >= options -> universe_count)
2156 return;
2157 head = ((struct option_chain_head *)
2158 options -> universes [universe -> index]);
2159 if (!head)
2160 return;
2162 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2163 if (code ==
2164 ((struct option_cache *)(*tail) -> car) -> option -> code)
2166 tmp = (*tail) -> cdr;
2167 option_cache_dereference ((struct option_cache **)
2168 (&(*tail) -> car), MDL);
2169 dfree (*tail, MDL);
2170 (*tail) = tmp;
2171 break;
2176 struct option_cache *lookup_linked_option (universe, options, code)
2177 struct universe *universe;
2178 struct option_state *options;
2179 unsigned code;
2181 pair oc;
2182 struct option_chain_head *head;
2184 if (universe -> index >= options -> universe_count)
2185 return 0;
2186 head = ((struct option_chain_head *)
2187 options -> universes [universe -> index]);
2188 if (!head)
2189 return 0;
2191 for (oc = head -> first; oc; oc = oc -> cdr) {
2192 if (code ==
2193 ((struct option_cache *)(oc -> car)) -> option -> code) {
2194 return (struct option_cache *)(oc -> car);
2198 return (struct option_cache *)0;
2201 int linked_option_state_dereference (universe, state, file, line)
2202 struct universe *universe;
2203 struct option_state *state;
2204 const char *file;
2205 int line;
2207 return (option_chain_head_dereference
2208 ((struct option_chain_head **)
2209 (&state -> universes [universe -> index]), MDL));
2212 void linked_option_space_foreach (struct packet *packet, struct lease *lease,
2213 struct client_state *client_state,
2214 struct option_state *in_options,
2215 struct option_state *cfg_options,
2216 struct binding_scope **scope,
2217 struct universe *u, void *stuff,
2218 void (*func) (struct option_cache *,
2219 struct packet *,
2220 struct lease *,
2221 struct client_state *,
2222 struct option_state *,
2223 struct option_state *,
2224 struct binding_scope **,
2225 struct universe *, void *))
2227 pair car;
2228 struct option_chain_head *head;
2230 if (u -> index >= cfg_options -> universe_count)
2231 return;
2232 head = ((struct option_chain_head *)
2233 cfg_options -> universes [u -> index]);
2234 if (!head)
2235 return;
2236 for (car = head -> first; car; car = car -> cdr) {
2237 (*func) ((struct option_cache *)(car -> car),
2238 packet, lease, client_state,
2239 in_options, cfg_options, scope, u, stuff);
2243 void do_packet (interface, packet, len, from_port, from, hfrom)
2244 struct interface_info *interface;
2245 struct dhcp_packet *packet;
2246 unsigned len;
2247 unsigned int from_port;
2248 struct iaddr from;
2249 struct hardware *hfrom;
2251 int i;
2252 struct option_cache *op;
2253 struct packet *decoded_packet;
2254 #if defined (DEBUG_MEMORY_LEAKAGE)
2255 unsigned long previous_outstanding = dmalloc_outstanding;
2256 #endif
2258 #if defined (TRACING)
2259 trace_inpacket_stash (interface, packet, len, from_port, from, hfrom);
2260 #endif
2262 decoded_packet = (struct packet *)0;
2263 if (!packet_allocate (&decoded_packet, MDL)) {
2264 log_error ("do_packet: no memory for incoming packet!");
2265 return;
2267 decoded_packet -> raw = packet;
2268 decoded_packet -> packet_length = len;
2269 decoded_packet -> client_port = from_port;
2270 decoded_packet -> client_addr = from;
2271 interface_reference (&decoded_packet -> interface, interface, MDL);
2272 decoded_packet -> haddr = hfrom;
2274 if (packet -> hlen > sizeof packet -> chaddr) {
2275 packet_dereference (&decoded_packet, MDL);
2276 log_info ("Discarding packet with bogus hlen.");
2277 return;
2280 /* If there's an option buffer, try to parse it. */
2281 if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) {
2282 if (!parse_options (decoded_packet)) {
2283 if (decoded_packet -> options)
2284 option_state_dereference
2285 (&decoded_packet -> options, MDL);
2286 packet_dereference (&decoded_packet, MDL);
2287 return;
2290 if (decoded_packet -> options_valid &&
2291 (op = lookup_option (&dhcp_universe,
2292 decoded_packet -> options,
2293 DHO_DHCP_MESSAGE_TYPE))) {
2294 struct data_string dp;
2295 memset (&dp, 0, sizeof dp);
2296 evaluate_option_cache (&dp, decoded_packet,
2297 (struct lease *)0,
2298 (struct client_state *)0,
2299 decoded_packet -> options,
2300 (struct option_state *)0,
2301 (struct binding_scope **)0,
2302 op, MDL);
2303 if (dp.len > 0)
2304 decoded_packet -> packet_type = dp.data [0];
2305 else
2306 decoded_packet -> packet_type = 0;
2307 data_string_forget (&dp, MDL);
2311 if (decoded_packet -> packet_type)
2312 dhcp (decoded_packet);
2313 else
2314 bootp (decoded_packet);
2316 /* If the caller kept the packet, they'll have upped the refcnt. */
2317 packet_dereference (&decoded_packet, MDL);
2319 #if defined (DEBUG_MEMORY_LEAKAGE)
2320 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2321 dmalloc_generation,
2322 dmalloc_outstanding - previous_outstanding,
2323 dmalloc_outstanding, dmalloc_longterm);
2324 #endif
2325 #if defined (DEBUG_MEMORY_LEAKAGE)
2326 dmalloc_dump_outstanding ();
2327 #endif
2328 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2329 dump_rc_history (0);
2330 #endif