ISC DHCP  4.3.3
A reference DHCPv4 and DHCPv6 implementation
print.c
Go to the documentation of this file.
1 /* print.c
2 
3  Turn data structures into printable text. */
4 
5 /*
6  * Copyright (c) 2009-2014 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1995-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Internet Systems Consortium, Inc.
23  * 950 Charter Street
24  * Redwood City, CA 94063
25  * <info@isc.org>
26  * https://www.isc.org/
27  *
28  */
29 
30 #include "dhcpd.h"
31 
33 
34 char *quotify_string (const char *s, const char *file, int line)
35 {
36  unsigned len = 0;
37  const char *sp;
38  char *buf, *nsp;
39 
40  for (sp = s; sp && *sp; sp++) {
41  if (*sp == ' ')
42  len++;
43  else if (!isascii ((int)*sp) || !isprint ((int)*sp))
44  len += 4;
45  else if (*sp == '"' || *sp == '\\')
46  len += 2;
47  else
48  len++;
49  }
50 
51  buf = dmalloc (len + 1, file, line);
52  if (buf) {
53  nsp = buf;
54  for (sp = s; sp && *sp; sp++) {
55  if (*sp == ' ')
56  *nsp++ = ' ';
57  else if (!isascii ((int)*sp) || !isprint ((int)*sp)) {
58  sprintf (nsp, "\\%03o",
59  *(const unsigned char *)sp);
60  nsp += 4;
61  } else if (*sp == '"' || *sp == '\\') {
62  *nsp++ = '\\';
63  *nsp++ = *sp;
64  } else
65  *nsp++ = *sp;
66  }
67  *nsp++ = 0;
68  }
69  return buf;
70 }
71 
72 char *quotify_buf (const unsigned char *s, unsigned len,
73  const char *file, int line)
74 {
75  unsigned nulen = 0;
76  char *buf, *nsp;
77  int i;
78 
79  for (i = 0; i < len; i++) {
80  if (s [i] == ' ')
81  nulen++;
82  else if (!isascii (s [i]) || !isprint (s [i]))
83  nulen += 4;
84  else if (s [i] == '"' || s [i] == '\\')
85  nulen += 2;
86  else
87  nulen++;
88  }
89 
90  buf = dmalloc (nulen + 1, MDL);
91  if (buf) {
92  nsp = buf;
93  for (i = 0; i < len; i++) {
94  if (s [i] == ' ')
95  *nsp++ = ' ';
96  else if (!isascii (s [i]) || !isprint (s [i])) {
97  sprintf (nsp, "\\%03o", s [i]);
98  nsp += 4;
99  } else if (s [i] == '"' || s [i] == '\\') {
100  *nsp++ = '\\';
101  *nsp++ = s [i];
102  } else
103  *nsp++ = s [i];
104  }
105  *nsp++ = 0;
106  }
107  return buf;
108 }
109 
110 char *print_base64 (const unsigned char *buf, unsigned len,
111  const char *file, int line)
112 {
113  char *s, *b;
114  unsigned bl;
115  int i;
116  unsigned val, extra;
117  static char to64 [] =
118  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
119 
120  bl = ((len * 4 + 2) / 3) + 1;
121  b = dmalloc (bl + 1, file, line);
122  if (!b)
123  return (char *)0;
124 
125  i = 0;
126  s = b;
127  while (i != len) {
128  val = buf [i++];
129  extra = val & 3;
130  val = val >> 2;
131  *s++ = to64 [val];
132  if (i == len) {
133  *s++ = to64 [extra << 4];
134  *s++ = '=';
135  break;
136  }
137  val = (extra << 8) + buf [i++];
138  extra = val & 15;
139  val = val >> 4;
140  *s++ = to64 [val];
141  if (i == len) {
142  *s++ = to64 [extra << 2];
143  *s++ = '=';
144  break;
145  }
146  val = (extra << 8) + buf [i++];
147  extra = val & 0x3f;
148  val = val >> 6;
149  *s++ = to64 [val];
150  *s++ = to64 [extra];
151  }
152  if (!len)
153  *s++ = '=';
154  *s++ = 0;
155  if (s > b + bl + 1)
156  abort ();
157  return b;
158 }
159 
160 char *print_hw_addr (htype, hlen, data)
161  const int htype;
162  const int hlen;
163  const unsigned char *data;
164 {
165  static char habuf [49];
166  char *s;
167  int i;
168 
169  if (hlen <= 0)
170  habuf [0] = 0;
171  else {
172  s = habuf;
173  for (i = 0; i < hlen; i++) {
174  sprintf (s, "%02x", data [i]);
175  s += strlen (s);
176  *s++ = ':';
177  }
178  *--s = 0;
179  }
180  return habuf;
181 }
182 
184  struct lease *lease;
185 {
186  struct tm *t;
187  char tbuf [32];
188 
189  log_debug (" Lease %s",
190  piaddr (lease -> ip_addr));
191 
192  t = gmtime (&lease -> starts);
193  strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
194  log_debug (" start %s", tbuf);
195 
196  t = gmtime (&lease -> ends);
197  strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
198  log_debug (" end %s", tbuf);
199 
200  if (lease -> hardware_addr.hlen)
201  log_debug (" hardware addr = %s",
202  print_hw_addr (lease -> hardware_addr.hbuf [0],
203  lease -> hardware_addr.hlen - 1,
204  &lease -> hardware_addr.hbuf [1]));
205  log_debug (" host %s ",
206  lease -> host ? lease -> host -> name : "<none>");
207 }
208 
209 #if defined (DEBUG_PACKET)
210 void dump_packet_option (struct option_cache *oc,
211  struct packet *packet,
212  struct lease *lease,
213  struct client_state *client,
214  struct option_state *in_options,
215  struct option_state *cfg_options,
216  struct binding_scope **scope,
217  struct universe *u, void *foo)
218 {
219  const char *name, *dot;
220  struct data_string ds;
221  memset (&ds, 0, sizeof ds);
222 
223  if (u != &dhcp_universe) {
224  name = u -> name;
225  dot = ".";
226  } else {
227  name = "";
228  dot = "";
229  }
230  if (evaluate_option_cache (&ds, packet, lease, client,
231  in_options, cfg_options, scope, oc, MDL)) {
232  log_debug (" option %s%s%s %s;\n",
233  name, dot, oc -> option -> name,
235  ds.data, ds.len, 1, 1));
236  data_string_forget (&ds, MDL);
237  }
238 }
239 
240 void dump_packet (tp)
241  struct packet *tp;
242 {
243  struct dhcp_packet *tdp = tp -> raw;
244 
245  log_debug ("packet length %d", tp -> packet_length);
246  log_debug ("op = %d htype = %d hlen = %d hops = %d",
247  tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
248  log_debug ("xid = %x secs = %ld flags = %x",
249  tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
250  log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
251  log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
252  log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
253  log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
254  log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
255  ((unsigned char *)(tdp -> chaddr)) [0],
256  ((unsigned char *)(tdp -> chaddr)) [1],
257  ((unsigned char *)(tdp -> chaddr)) [2],
258  ((unsigned char *)(tdp -> chaddr)) [3],
259  ((unsigned char *)(tdp -> chaddr)) [4],
260  ((unsigned char *)(tdp -> chaddr)) [5]);
261  log_debug ("filename = %s", tdp -> file);
262  log_debug ("server_name = %s", tdp -> sname);
263  if (tp -> options_valid) {
264  int i;
265 
266  for (i = 0; i < tp -> options -> universe_count; i++) {
267  if (tp -> options -> universes [i]) {
268  option_space_foreach (tp, (struct lease *)0,
269  (struct client_state *)0,
270  (struct option_state *)0,
271  tp -> options,
272  &global_scope,
273  universes [i], 0,
275  }
276  }
277  }
278  log_debug ("%s", "");
279 }
280 #endif
281 
282 void dump_raw (buf, len)
283  const unsigned char *buf;
284  unsigned len;
285 {
286  int i;
287  char lbuf [80];
288  int lbix = 0;
289 
290 /*
291  1 2 3 4 5 6 7
292 01234567890123456789012345678901234567890123456789012345678901234567890123
293 280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .................
294 */
295 
296  memset(lbuf, ' ', 79);
297  lbuf [79] = 0;
298 
299  for (i = 0; i < len; i++) {
300  if ((i & 15) == 0) {
301  if (lbix) {
302  lbuf[53]=' ';
303  lbuf[54]=' ';
304  lbuf[55]=' ';
305  lbuf[73]='\0';
306  log_info ("%s", lbuf);
307  }
308  memset(lbuf, ' ', 79);
309  lbuf [79] = 0;
310  sprintf (lbuf, "%03x:", i);
311  lbix = 4;
312  } else if ((i & 7) == 0)
313  lbuf [lbix++] = ' ';
314 
315  if(isprint(buf[i])) {
316  lbuf[56+(i%16)]=buf[i];
317  } else {
318  lbuf[56+(i%16)]='.';
319  }
320 
321  sprintf (&lbuf [lbix], " %02x", buf [i]);
322  lbix += 3;
323  lbuf[lbix]=' ';
324 
325  }
326  lbuf[53]=' ';
327  lbuf[54]=' ';
328  lbuf[55]=' ';
329  lbuf[73]='\0';
330  log_info ("%s", lbuf);
331 }
332 
333 void hash_dump (table)
334  struct hash_table *table;
335 {
336  int i;
337  struct hash_bucket *bp;
338 
339  if (!table)
340  return;
341 
342  for (i = 0; i < table -> hash_count; i++) {
343  if (!table -> buckets [i])
344  continue;
345  log_info ("hash bucket %d:", i);
346  for (bp = table -> buckets [i]; bp; bp = bp -> next) {
347  if (bp -> len)
348  dump_raw (bp -> name, bp -> len);
349  else
350  log_info ("%s", (const char *)bp -> name);
351  }
352  }
353 }
354 
355 /*
356  * print a string as hex. This only outputs
357  * colon separated hex list no matter what
358  * the input looks like. See print_hex
359  * for a function that prints either cshl
360  * or a string if all bytes are printible
361  * It only uses limit characters from buf
362  * and doesn't do anything if buf == NULL
363  *
364  * len - length of data
365  * data - input data
366  * limit - length of buf to use
367  * buf - output buffer
368  */
369 void print_hex_only (len, data, limit, buf)
370  unsigned len;
371  const u_int8_t *data;
372  unsigned limit;
373  char *buf;
374 {
375  unsigned i;
376 
377  if ((buf == NULL) || (limit < 3))
378  return;
379 
380  for (i = 0; (i < limit / 3) && (i < len); i++) {
381  sprintf(&buf[i*3], "%02x:", data[i]);
382  }
383  buf[(i * 3) - 1] = 0;
384  return;
385 }
386 
387 /*
388  * print a string as either text if all the characters
389  * are printable or colon separated hex if they aren't
390  *
391  * len - length of data
392  * data - input data
393  * limit - length of buf to use
394  * buf - output buffer
395  */
396 void print_hex_or_string (len, data, limit, buf)
397  unsigned len;
398  const u_int8_t *data;
399  unsigned limit;
400  char *buf;
401 {
402  unsigned i;
403  if ((buf == NULL) || (limit < 3))
404  return;
405 
406  for (i = 0; (i < (limit - 3)) && (i < len); i++) {
407  if (!isascii(data[i]) || !isprint(data[i])) {
408  print_hex_only(len, data, limit, buf);
409  return;
410  }
411  }
412 
413  buf[0] = '"';
414  i = len;
415  if (i > (limit - 3))
416  i = limit - 3;
417  memcpy(&buf[1], data, i);
418  buf[i + 1] = '"';
419  buf[i + 2] = 0;
420  return;
421 }
422 
423 /*
424  * print a string as either hex or text
425  * using static buffers to hold the output
426  *
427  * len - length of data
428  * data - input data
429  * limit - length of buf
430  * buf_num - the output buffer to use
431  */
432 #define HBLEN 1024
433 char *print_hex(len, data, limit, buf_num)
434  unsigned len;
435  const u_int8_t *data;
436  unsigned limit;
437  unsigned buf_num;
438 {
439  static char hex_buf_1[HBLEN + 1];
440  static char hex_buf_2[HBLEN + 1];
441  static char hex_buf_3[HBLEN + 1];
442  char *hex_buf;
443 
444  switch(buf_num) {
445  case 0:
446  hex_buf = hex_buf_1;
447  if (limit >= sizeof(hex_buf_1))
448  limit = sizeof(hex_buf_1);
449  break;
450  case 1:
451  hex_buf = hex_buf_2;
452  if (limit >= sizeof(hex_buf_2))
453  limit = sizeof(hex_buf_2);
454  break;
455  case 2:
456  hex_buf = hex_buf_3;
457  if (limit >= sizeof(hex_buf_3))
458  limit = sizeof(hex_buf_3);
459  break;
460  default:
461  return(NULL);
462  }
463 
464  print_hex_or_string(len, data, limit, hex_buf);
465  return(hex_buf);
466 }
467 
468 #define DQLEN 80
469 
470 char *print_dotted_quads (len, data)
471  unsigned len;
472  const u_int8_t *data;
473 {
474  static char dq_buf [DQLEN + 1];
475  int i;
476  char *s;
477 
478  s = &dq_buf [0];
479 
480  i = 0;
481 
482  /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
483  * The sprintf can't exceed 18 bytes, and since the loop enforces
484  * 21 bytes of space per iteration at no time can we exit the
485  * loop without at least 3 bytes spare.
486  */
487  do {
488  sprintf (s, "%u.%u.%u.%u, ",
489  data [i], data [i + 1], data [i + 2], data [i + 3]);
490  s += strlen (s);
491  i += 4;
492  } while ((s - &dq_buf [0] > DQLEN - 21) &&
493  i + 3 < len);
494  if (i == len)
495  s [-2] = 0;
496  else
497  strcpy (s, "...");
498  return dq_buf;
499 }
500 
501 char *print_dec_1 (val)
502  unsigned long val;
503 {
504  static char vbuf [32];
505  sprintf (vbuf, "%lu", val);
506  return vbuf;
507 }
508 
509 char *print_dec_2 (val)
510  unsigned long val;
511 {
512  static char vbuf [32];
513  sprintf (vbuf, "%lu", val);
514  return vbuf;
515 }
516 
517 static unsigned print_subexpression (struct expression *, char *, unsigned);
518 
519 static unsigned print_subexpression (expr, buf, len)
520  struct expression *expr;
521  char *buf;
522  unsigned len;
523 {
524  unsigned rv, left;
525  const char *s;
526 
527  switch (expr -> op) {
528  case expr_none:
529  if (len > 3) {
530  strcpy (buf, "nil");
531  return 3;
532  }
533  break;
534 
535  case expr_match:
536  if (len > 7) {
537  strcpy (buf, "(match)");
538  return 7;
539  }
540  break;
541 
542  case expr_check:
543  rv = 10 + strlen (expr -> data.check -> name);
544  if (len > rv) {
545  sprintf (buf, "(check %s)",
546  expr -> data.check -> name);
547  return rv;
548  }
549  break;
550 
551  case expr_equal:
552  if (len > 6) {
553  rv = 4;
554  strcpy (buf, "(eq ");
555  rv += print_subexpression (expr -> data.equal [0],
556  buf + rv, len - rv - 2);
557  buf [rv++] = ' ';
558  rv += print_subexpression (expr -> data.equal [1],
559  buf + rv, len - rv - 1);
560  buf [rv++] = ')';
561  buf [rv] = 0;
562  return rv;
563  }
564  break;
565 
566  case expr_not_equal:
567  if (len > 7) {
568  rv = 5;
569  strcpy (buf, "(neq ");
570  rv += print_subexpression (expr -> data.equal [0],
571  buf + rv, len - rv - 2);
572  buf [rv++] = ' ';
573  rv += print_subexpression (expr -> data.equal [1],
574  buf + rv, len - rv - 1);
575  buf [rv++] = ')';
576  buf [rv] = 0;
577  return rv;
578  }
579  break;
580 
581  case expr_regex_match:
582  if (len > 10) {
583  rv = 4;
584  strcpy(buf, "(regex ");
585  rv += print_subexpression(expr->data.equal[0],
586  buf + rv, len - rv - 2);
587  buf[rv++] = ' ';
588  rv += print_subexpression(expr->data.equal[1],
589  buf + rv, len - rv - 1);
590  buf[rv++] = ')';
591  buf[rv] = 0;
592  return rv;
593  }
594  break;
595 
596  case expr_substring:
597  if (len > 11) {
598  rv = 8;
599  strcpy (buf, "(substr ");
600  rv += print_subexpression (expr -> data.substring.expr,
601  buf + rv, len - rv - 3);
602  buf [rv++] = ' ';
603  rv += print_subexpression
604  (expr -> data.substring.offset,
605  buf + rv, len - rv - 2);
606  buf [rv++] = ' ';
607  rv += print_subexpression (expr -> data.substring.len,
608  buf + rv, len - rv - 1);
609  buf [rv++] = ')';
610  buf [rv] = 0;
611  return rv;
612  }
613  break;
614 
615  case expr_suffix:
616  if (len > 10) {
617  rv = 8;
618  strcpy (buf, "(suffix ");
619  rv += print_subexpression (expr -> data.suffix.expr,
620  buf + rv, len - rv - 2);
621  if (len > rv)
622  buf [rv++] = ' ';
623  rv += print_subexpression (expr -> data.suffix.len,
624  buf + rv, len - rv - 1);
625  if (len > rv)
626  buf [rv++] = ')';
627  buf [rv] = 0;
628  return rv;
629  }
630  break;
631 
632  case expr_lcase:
633  if (len > 9) {
634  rv = 7;
635  strcpy(buf, "(lcase ");
636  rv += print_subexpression(expr->data.lcase,
637  buf + rv, len - rv - 1);
638  buf[rv++] = ')';
639  buf[rv] = 0;
640  return rv;
641  }
642  break;
643 
644  case expr_ucase:
645  if (len > 9) {
646  rv = 7;
647  strcpy(buf, "(ucase ");
648  rv += print_subexpression(expr->data.ucase,
649  buf + rv, len - rv - 1);
650  buf[rv++] = ')';
651  buf[rv] = 0;
652  return rv;
653  }
654  break;
655 
656  case expr_concat:
657  if (len > 10) {
658  rv = 8;
659  strcpy (buf, "(concat ");
660  rv += print_subexpression (expr -> data.concat [0],
661  buf + rv, len - rv - 2);
662  buf [rv++] = ' ';
663  rv += print_subexpression (expr -> data.concat [1],
664  buf + rv, len - rv - 1);
665  buf [rv++] = ')';
666  buf [rv] = 0;
667  return rv;
668  }
669  break;
670 
672  if (len > 8) {
673  rv = 6;
674  strcpy (buf, "(pick1st ");
675  rv += print_subexpression
676  (expr -> data.pick_first_value.car,
677  buf + rv, len - rv - 2);
678  buf [rv++] = ' ';
679  rv += print_subexpression
680  (expr -> data.pick_first_value.cdr,
681  buf + rv, len - rv - 1);
682  buf [rv++] = ')';
683  buf [rv] = 0;
684  return rv;
685  }
686  break;
687 
688  case expr_host_lookup:
689  rv = 15 + strlen (expr -> data.host_lookup -> hostname);
690  if (len > rv) {
691  sprintf (buf, "(dns-lookup %s)",
692  expr -> data.host_lookup -> hostname);
693  return rv;
694  }
695  break;
696 
697  case expr_and:
698  s = "and";
699  binop:
700  rv = strlen (s);
701  if (len > rv + 4) {
702  buf [0] = '(';
703  strcpy (&buf [1], s);
704  rv += 1;
705  buf [rv++] = ' ';
706  rv += print_subexpression (expr -> data.and [0],
707  buf + rv, len - rv - 2);
708  buf [rv++] = ' ';
709  rv += print_subexpression (expr -> data.and [1],
710  buf + rv, len - rv - 1);
711  buf [rv++] = ')';
712  buf [rv] = 0;
713  return rv;
714  }
715  break;
716 
717  case expr_or:
718  s = "or";
719  goto binop;
720 
721  case expr_add:
722  s = "+";
723  goto binop;
724 
725  case expr_subtract:
726  s = "-";
727  goto binop;
728 
729  case expr_multiply:
730  s = "*";
731  goto binop;
732 
733  case expr_divide:
734  s = "/";
735  goto binop;
736 
737  case expr_remainder:
738  s = "%";
739  goto binop;
740 
741  case expr_binary_and:
742  s = "&";
743  goto binop;
744 
745  case expr_binary_or:
746  s = "|";
747  goto binop;
748 
749  case expr_binary_xor:
750  s = "^";
751  goto binop;
752 
753  case expr_not:
754  if (len > 6) {
755  rv = 5;
756  strcpy (buf, "(not ");
757  rv += print_subexpression (expr -> data.not,
758  buf + rv, len - rv - 1);
759  buf [rv++] = ')';
760  buf [rv] = 0;
761  return rv;
762  }
763  break;
764 
765  case expr_config_option:
766  s = "cfg-option";
767  goto dooption;
768 
769  case expr_option:
770  s = "option";
771  dooption:
772  rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
773  strlen (expr -> data.option -> universe -> name));
774  if (len > rv) {
775  sprintf (buf, "(option %s.%s)",
776  expr -> data.option -> universe -> name,
777  expr -> data.option -> name);
778  return rv;
779  }
780  break;
781 
782  case expr_hardware:
783  if (len > 10) {
784  strcpy (buf, "(hardware)");
785  return 10;
786  }
787  break;
788 
789  case expr_packet:
790  if (len > 10) {
791  rv = 8;
792  strcpy (buf, "(substr ");
793  rv += print_subexpression (expr -> data.packet.offset,
794  buf + rv, len - rv - 2);
795  buf [rv++] = ' ';
796  rv += print_subexpression (expr -> data.packet.len,
797  buf + rv, len - rv - 1);
798  buf [rv++] = ')';
799  buf [rv] = 0;
800  return rv;
801  }
802  break;
803 
804  case expr_const_data:
805  s = print_hex_1 (expr -> data.const_data.len,
806  expr -> data.const_data.data, len);
807  rv = strlen (s);
808  if (rv >= len)
809  rv = len - 1;
810  strncpy (buf, s, rv);
811  buf [rv] = 0;
812  return rv;
813 
814  case expr_encapsulate:
815  rv = 13;
816  strcpy (buf, "(encapsulate ");
817  rv += expr -> data.encapsulate.len;
818  if (rv + 2 > len)
819  rv = len - 2;
820  strncpy (buf,
821  (const char *)expr -> data.encapsulate.data, rv - 13);
822  buf [rv++] = ')';
823  buf [rv++] = 0;
824  break;
825 
826  case expr_extract_int8:
827  if (len > 7) {
828  rv = 6;
829  strcpy (buf, "(int8 ");
830  rv += print_subexpression (expr -> data.extract_int,
831  buf + rv, len - rv - 1);
832  buf [rv++] = ')';
833  buf [rv] = 0;
834  return rv;
835  }
836  break;
837 
838  case expr_extract_int16:
839  if (len > 8) {
840  rv = 7;
841  strcpy (buf, "(int16 ");
842  rv += print_subexpression (expr -> data.extract_int,
843  buf + rv, len - rv - 1);
844  buf [rv++] = ')';
845  buf [rv] = 0;
846  return rv;
847  }
848  break;
849 
850  case expr_extract_int32:
851  if (len > 8) {
852  rv = 7;
853  strcpy (buf, "(int32 ");
854  rv += print_subexpression (expr -> data.extract_int,
855  buf + rv, len - rv - 1);
856  buf [rv++] = ')';
857  buf [rv] = 0;
858  return rv;
859  }
860  break;
861 
862  case expr_encode_int8:
863  if (len > 7) {
864  rv = 6;
865  strcpy (buf, "(to-int8 ");
866  rv += print_subexpression (expr -> data.encode_int,
867  buf + rv, len - rv - 1);
868  buf [rv++] = ')';
869  buf [rv] = 0;
870  return rv;
871  }
872  break;
873 
874  case expr_encode_int16:
875  if (len > 8) {
876  rv = 7;
877  strcpy (buf, "(to-int16 ");
878  rv += print_subexpression (expr -> data.encode_int,
879  buf + rv, len - rv - 1);
880  buf [rv++] = ')';
881  buf [rv] = 0;
882  return rv;
883  }
884  break;
885 
886  case expr_encode_int32:
887  if (len > 8) {
888  rv = 7;
889  strcpy (buf, "(to-int32 ");
890  rv += print_subexpression (expr -> data.encode_int,
891  buf + rv, len - rv - 1);
892  buf [rv++] = ')';
893  buf [rv] = 0;
894  return rv;
895  }
896  break;
897 
898  case expr_const_int:
899  s = print_dec_1 (expr -> data.const_int);
900  rv = strlen (s);
901  if (len > rv) {
902  strcpy (buf, s);
903  return rv;
904  }
905  break;
906 
907  case expr_exists:
908  rv = 10 + (strlen (expr -> data.option -> name) +
909  strlen (expr -> data.option -> universe -> name));
910  if (len > rv) {
911  sprintf (buf, "(exists %s.%s)",
912  expr -> data.option -> universe -> name,
913  expr -> data.option -> name);
914  return rv;
915  }
916  break;
917 
919  rv = 10 + strlen (expr -> data.variable);
920  if (len > rv) {
921  sprintf (buf, "(defined %s)", expr -> data.variable);
922  return rv;
923  }
924  break;
925 
927  rv = strlen (expr -> data.variable);
928  if (len > rv) {
929  sprintf (buf, "%s", expr -> data.variable);
930  return rv;
931  }
932  break;
933 
934  case expr_known:
935  s = "known";
936  astring:
937  rv = strlen (s);
938  if (len > rv) {
939  strcpy (buf, s);
940  return rv;
941  }
942  break;
943 
944  case expr_leased_address:
945  s = "leased-address";
946  goto astring;
947 
948  case expr_client_state:
949  s = "client-state";
950  goto astring;
951 
952  case expr_host_decl_name:
953  s = "host-decl-name";
954  goto astring;
955 
956  case expr_lease_time:
957  s = "lease-time";
958  goto astring;
959 
960  case expr_static:
961  s = "static";
962  goto astring;
963 
964  case expr_filename:
965  s = "filename";
966  goto astring;
967 
968  case expr_sname:
969  s = "server-name";
970  goto astring;
971 
972  case expr_reverse:
973  if (len > 11) {
974  rv = 13;
975  strcpy (buf, "(reverse ");
976  rv += print_subexpression (expr -> data.reverse.width,
977  buf + rv, len - rv - 2);
978  buf [rv++] = ' ';
979  rv += print_subexpression (expr -> data.reverse.buffer,
980  buf + rv, len - rv - 1);
981  buf [rv++] = ')';
982  buf [rv] = 0;
983  return rv;
984  }
985  break;
986 
988  if (len > 5) {
989  rv = 9;
990  strcpy (buf, "(b2a ");
991  rv += print_subexpression (expr -> data.b2a.base,
992  buf + rv, len - rv - 4);
993  buf [rv++] = ' ';
994  rv += print_subexpression (expr -> data.b2a.width,
995  buf + rv, len - rv - 3);
996  buf [rv++] = ' ';
997  rv += print_subexpression (expr -> data.b2a.separator,
998  buf + rv, len - rv - 2);
999  buf [rv++] = ' ';
1000  rv += print_subexpression (expr -> data.b2a.buffer,
1001  buf + rv, len - rv - 1);
1002  buf [rv++] = ')';
1003  buf [rv] = 0;
1004  return rv;
1005  }
1006  break;
1007 
1008  case expr_dns_transaction:
1009  rv = 10;
1010  if (len < rv + 2) {
1011  buf [0] = '(';
1012  strcpy (&buf [1], "ns-update ");
1013  while (len < rv + 2) {
1014  rv += print_subexpression
1015  (expr -> data.dns_transaction.car,
1016  buf + rv, len - rv - 2);
1017  buf [rv++] = ' ';
1018  expr = expr -> data.dns_transaction.cdr;
1019  }
1020  buf [rv - 1] = ')';
1021  buf [rv] = 0;
1022  return rv;
1023  }
1024  return 0;
1025 
1026  case expr_ns_delete:
1027  s = "delete";
1028  left = 4;
1029  goto dodnsupd;
1030  case expr_ns_exists:
1031  s = "exists";
1032  left = 4;
1033  goto dodnsupd;
1034  case expr_ns_not_exists:
1035  s = "not_exists";
1036  left = 4;
1037  goto dodnsupd;
1038  case expr_ns_add:
1039  s = "update";
1040  left = 5;
1041  dodnsupd:
1042  rv = strlen (s);
1043  if (len > strlen (s) + 1) {
1044  buf [0] = '(';
1045  strcpy (buf + 1, s);
1046  rv++;
1047  buf [rv++] = ' ';
1048  s = print_dec_1 (expr -> data.ns_add.rrclass);
1049  if (len > rv + strlen (s) + left) {
1050  strcpy (&buf [rv], s);
1051  rv += strlen (&buf [rv]);
1052  }
1053  buf [rv++] = ' ';
1054  left--;
1055  s = print_dec_1 (expr -> data.ns_add.rrtype);
1056  if (len > rv + strlen (s) + left) {
1057  strcpy (&buf [rv], s);
1058  rv += strlen (&buf [rv]);
1059  }
1060  buf [rv++] = ' ';
1061  left--;
1062  rv += print_subexpression
1063  (expr -> data.ns_add.rrname,
1064  buf + rv, len - rv - left);
1065  buf [rv++] = ' ';
1066  left--;
1067  rv += print_subexpression
1068  (expr -> data.ns_add.rrdata,
1069  buf + rv, len - rv - left);
1070  buf [rv++] = ' ';
1071  left--;
1072  rv += print_subexpression
1073  (expr -> data.ns_add.ttl,
1074  buf + rv, len - rv - left);
1075  buf [rv++] = ')';
1076  buf [rv] = 0;
1077  return rv;
1078  }
1079  break;
1080 
1081  case expr_null:
1082  if (len > 6) {
1083  strcpy (buf, "(null)");
1084  return 6;
1085  }
1086  break;
1087  case expr_funcall:
1088  rv = 12 + strlen (expr -> data.funcall.name);
1089  if (len > rv + 1) {
1090  strcpy (buf, "(funcall ");
1091  strcpy (buf + 9, expr -> data.funcall.name);
1092  buf [rv++] = ' ';
1093  rv += print_subexpression
1094  (expr -> data.funcall.arglist, buf + rv,
1095  len - rv - 1);
1096  buf [rv++] = ')';
1097  buf [rv] = 0;
1098  return rv;
1099  }
1100  break;
1101 
1102  case expr_arg:
1103  rv = print_subexpression (expr -> data.arg.val, buf, len);
1104  if (expr -> data.arg.next && rv + 2 < len) {
1105  buf [rv++] = ' ';
1106  rv += print_subexpression (expr -> data.arg.next,
1107  buf, len);
1108  if (rv + 1 < len)
1109  buf [rv++] = 0;
1110  return rv;
1111  }
1112  break;
1113 
1114  case expr_function:
1115  rv = 9;
1116  if (len > rv + 1) {
1117  struct string_list *foo;
1118  strcpy (buf, "(function");
1119  for (foo = expr -> data.func -> args;
1120  foo; foo = foo -> next) {
1121  if (len > rv + 2 + strlen (foo -> string)) {
1122  buf [rv - 1] = ' ';
1123  strcpy (&buf [rv], foo -> string);
1124  rv += strlen (foo -> string);
1125  }
1126  }
1127  buf [rv++] = ')';
1128  buf [rv] = 0;
1129  return rv;
1130  }
1131  break;
1132 
1133  case expr_gethostname:
1134  if (len > 13) {
1135  strcpy(buf, "(gethostname)");
1136  return 13;
1137  }
1138  break;
1139 
1140  default:
1141  log_fatal("Impossible case at %s:%d (undefined expression "
1142  "%d).", MDL, expr->op);
1143  break;
1144  }
1145  return 0;
1146 }
1147 
1148 void print_expression (name, expr)
1149  const char *name;
1150  struct expression *expr;
1151 {
1152  char buf [1024];
1153 
1154  print_subexpression (expr, buf, sizeof buf);
1155  log_info ("%s: %s", name, buf);
1156 }
1157 
1158 int token_print_indent_concat (FILE *file, int col, int indent,
1159  const char *prefix,
1160  const char *suffix, ...)
1161 {
1162  va_list list;
1163  unsigned len;
1164  char *s, *t, *u;
1165 
1166  va_start (list, suffix);
1167  s = va_arg (list, char *);
1168  len = 0;
1169  while (s) {
1170  len += strlen (s);
1171  s = va_arg (list, char *);
1172  }
1173  va_end (list);
1174 
1175  t = dmalloc (len + 1, MDL);
1176  if (!t)
1177  log_fatal ("token_print_indent: no memory for copy buffer");
1178 
1179  va_start (list, suffix);
1180  s = va_arg (list, char *);
1181  u = t;
1182  while (s) {
1183  len = strlen (s);
1184  strcpy (u, s);
1185  u += len;
1186  s = va_arg (list, char *);
1187  }
1188  va_end (list);
1189 
1190  col = token_print_indent (file, col, indent,
1191  prefix, suffix, t);
1192  dfree (t, MDL);
1193  return col;
1194 }
1195 
1196 int token_indent_data_string (FILE *file, int col, int indent,
1197  const char *prefix, const char *suffix,
1198  struct data_string *data)
1199 {
1200  int i;
1201  char *buf;
1202  char obuf [3];
1203 
1204  /* See if this is just ASCII. */
1205  for (i = 0; i < data -> len; i++)
1206  if (!isascii (data -> data [i]) ||
1207  !isprint (data -> data [i]))
1208  break;
1209 
1210  /* If we have a purely ASCII string, output it as text. */
1211  if (i == data -> len) {
1212  buf = dmalloc (data -> len + 3, MDL);
1213  if (buf) {
1214  buf [0] = '"';
1215  memcpy (buf + 1, data -> data, data -> len);
1216  buf [data -> len + 1] = '"';
1217  buf [data -> len + 2] = 0;
1218  i = token_print_indent (file, col, indent,
1219  prefix, suffix, buf);
1220  dfree (buf, MDL);
1221  return i;
1222  }
1223  }
1224 
1225  for (i = 0; i < data -> len; i++) {
1226  sprintf (obuf, "%2.2x", data -> data [i]);
1227  col = token_print_indent (file, col, indent,
1228  i == 0 ? prefix : "",
1229  (i + 1 == data -> len
1230  ? suffix
1231  : ""), obuf);
1232  if (i + 1 != data -> len)
1233  col = token_print_indent (file, col, indent,
1234  prefix, suffix, ":");
1235  }
1236  return col;
1237 }
1238 
1239 int token_print_indent (FILE *file, int col, int indent,
1240  const char *prefix,
1241  const char *suffix, const char *buf)
1242 {
1243  int len = 0;
1244  if (prefix != NULL)
1245  len += strlen (prefix);
1246  if (buf != NULL)
1247  len += strlen (buf);
1248 
1249  if (col + len > 79) {
1250  if (indent + len < 79) {
1251  indent_spaces (file, indent);
1252  col = indent;
1253  } else {
1254  indent_spaces (file, col);
1255  col = len > 79 ? 0 : 79 - len - 1;
1256  }
1257  } else if (prefix && *prefix) {
1258  fputs (prefix, file);
1259  col += strlen (prefix);
1260  }
1261  if ((buf != NULL) && (*buf != 0)) {
1262  fputs (buf, file);
1263  col += strlen(buf);
1264  }
1265  if (suffix && *suffix) {
1266  if (col + strlen (suffix) > 79) {
1267  indent_spaces (file, indent);
1268  col = indent;
1269  } else {
1270  fputs (suffix, file);
1271  col += strlen (suffix);
1272  }
1273  }
1274  return col;
1275 }
1276 
1277 void indent_spaces (FILE *file, int indent)
1278 {
1279  int i;
1280  fputc ('\n', file);
1281  for (i = 0; i < indent; i++)
1282  fputc (' ', file);
1283 }
1284 
1285 #if defined (NSUPDATE)
1286 #if defined (DEBUG_DNS_UPDATES)
1287 /*
1288  * direction outbound (messages to the dns server)
1289  * inbound (messages from the dns server)
1290  * ddns_cb is the control block associated with the message
1291  * result is the result from the dns code. For outbound calls
1292  * it is from the call to pass the message to the dns library.
1293  * For inbound calls it is from the event returned by the library.
1294  *
1295  * For outbound messages we print whatever we think is interesting
1296  * from the control block.
1297  * For inbound messages we only print the transaction id pointer
1298  * and the result and expect that the user will match them up as
1299  * necessary. Note well: the transaction information is opaque to
1300  * us so we simply print the pointer to it. This should be sufficient
1301  * to match requests and replys in a short sequence but is awkward
1302  * when trying to use it for longer sequences.
1303  */
1304 void
1305 print_dns_status (int direction,
1306  struct dhcp_ddns_cb *ddns_cb,
1307  isc_result_t result)
1308 {
1309  char obuf[1024];
1310  char *s = obuf, *end = &obuf[sizeof(obuf)-2];
1311  char *en;
1312  const char *result_str;
1313  char ddns_address[
1314  sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
1315 
1316  if (direction == DDNS_PRINT_INBOUND) {
1317  log_info("DDNS reply: id ptr %p, result: %s",
1318  ddns_cb->transaction, isc_result_totext(result));
1319  return;
1320  }
1321 
1322  /*
1323  * To avoid having to figure out if any of the strings
1324  * aren't NULL terminated, just 0 the whole string
1325  */
1326  memset(obuf, 0, 1024);
1327 
1328  en = "DDNS request: id ptr ";
1329  if (s + strlen(en) + 16 < end) {
1330  sprintf(s, "%s%p", en, ddns_cb->transaction);
1331  s += strlen(s);
1332  } else {
1333  goto bailout;
1334  }
1335 
1336  switch (ddns_cb->state) {
1338  en = " add forward ";
1339  break;
1341  en = " modify forward ";
1342  break;
1343 
1344  case DDNS_STATE_ADD_PTR:
1345  en = " add reverse ";
1346  break;
1347 
1349  en = " remove forward ";
1350  break;
1351 
1353  en = " remove rrset ";
1354  break;
1355 
1356  case DDNS_STATE_REM_PTR:
1357  en = " remove reverse ";
1358  break;
1359 
1360  case DDNS_STATE_CLEANUP:
1361  en = " cleanup ";
1362  break;
1363 
1364  default:
1365  en = " unknown state ";
1366  break;
1367  }
1368 
1369  switch (ddns_cb->state) {
1374  strcpy(ddns_address, piaddr(ddns_cb->address));
1375  if (s + strlen(en) + strlen(ddns_address) +
1376  ddns_cb->fwd_name.len + 5 < end) {
1377  sprintf(s, "%s%s for %.*s", en, ddns_address,
1378  ddns_cb->fwd_name.len,
1379  ddns_cb->fwd_name.data);
1380  s += strlen(s);
1381  } else {
1382  goto bailout;
1383  }
1384  break;
1385 
1386  case DDNS_STATE_ADD_PTR:
1387  case DDNS_STATE_REM_PTR:
1388  if (s + strlen(en) + ddns_cb->fwd_name.len +
1389  ddns_cb->rev_name.len + 5 < end) {
1390  sprintf(s, "%s%.*s for %.*s", en,
1391  ddns_cb->fwd_name.len,
1392  ddns_cb->fwd_name.data,
1393  ddns_cb->rev_name.len,
1394  ddns_cb->rev_name.data);
1395  s += strlen(s);
1396  } else {
1397  goto bailout;
1398  }
1399  break;
1400 
1401  case DDNS_STATE_CLEANUP:
1402  default:
1403  if (s + strlen(en) < end) {
1404  sprintf(s, "%s", en);
1405  s += strlen(s);
1406  } else {
1407  goto bailout;
1408  }
1409  break;
1410  }
1411 
1412  en = " zone: ";
1413  if (s + strlen(en) + strlen((char *)ddns_cb->zone_name) < end) {
1414  sprintf(s, "%s%s", en, ddns_cb->zone_name);
1415  s += strlen(s);
1416  } else {
1417  goto bailout;
1418  }
1419 
1420  en = " dhcid: ";
1421  if (ddns_cb->dhcid.len > 0) {
1422  if (s + strlen(en) + ddns_cb->dhcid.len-1 < end) {
1423  strcpy(s, en);
1424  s += strlen(s);
1425  strncpy(s, (char *)ddns_cb->dhcid.data+1,
1426  ddns_cb->dhcid.len-1);
1427  s += strlen(s);
1428  } else {
1429  goto bailout;
1430  }
1431  } else {
1432  en = " dhcid: <empty>";
1433  if (s + strlen(en) < end) {
1434  strcpy(s, en);
1435  s += strlen(s);
1436  } else {
1437  goto bailout;
1438  }
1439  }
1440 
1441  en = " ttl: ";
1442  if (s + strlen(en) + 10 < end) {
1443  sprintf(s, "%s%ld", en, ddns_cb->ttl);
1444  s += strlen(s);
1445  } else {
1446  goto bailout;
1447  }
1448 
1449  en = " result: ";
1450  result_str = isc_result_totext(result);
1451  if (s + strlen(en) + strlen(result_str) < end) {
1452  sprintf(s, "%s%s", en, result_str);
1453  s += strlen(s);
1454  } else {
1455  goto bailout;
1456  }
1457 
1458  bailout:
1459  /*
1460  * We either finished building the string or ran out
1461  * of space, print whatever we have in case it is useful
1462  */
1463  log_info("%s", obuf);
1464 
1465  return;
1466 }
1467 #endif
1468 #endif /* NSUPDATE */
1469 
1470 /* Format the given time as "A; # B", where A is the format
1471  * used by the parser, and B is the local time, for humans.
1472  */
1473 const char *
1475 {
1476  static char buf[sizeof("epoch 9223372036854775807; "
1477  "# Wed Jun 30 21:49:08 2147483647")];
1478  static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
1479  time_t since_epoch;
1480  /* The string: "6 2147483647/12/31 23:59:60;"
1481  * is smaller than the other, used to declare the buffer size, so
1482  * we can use one buffer for both.
1483  */
1484 
1485  if (t == MAX_TIME)
1486  return "never;";
1487 
1488  if (t < 0)
1489  return NULL;
1490 
1491  /* For those lucky enough to have a 128-bit time_t, ensure that
1492  * whatever (corrupt) value we're given doesn't exceed the static
1493  * buffer.
1494  */
1495 #if (MAX_TIME > 0x7fffffffffffffff)
1496  if (t > 0x7fffffffffffffff)
1497  return NULL;
1498 #endif
1499 
1501  since_epoch = mktime(localtime(&t));
1502  if ((strftime(buf1, sizeof(buf1),
1503  "# %a %b %d %H:%M:%S %Y",
1504  localtime(&t)) == 0) ||
1505  (snprintf(buf, sizeof(buf), "epoch %lu; %s",
1506  (unsigned long)since_epoch, buf1) >= sizeof(buf)))
1507  return NULL;
1508 
1509  } else {
1510  /* No bounds check for the year is necessary - in this case,
1511  * strftime() will run out of space and assert an error.
1512  */
1513  if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
1514  gmtime(&t)) == 0)
1515  return NULL;
1516  }
1517 
1518  return buf;
1519 }
const char int line
Definition: dhcpd.h:3676
char sname[DHCP_SNAME_LEN]
Definition: dhcp.h:61
#define DDNS_PRINT_INBOUND
Definition: dhcpd.h:1739
struct binding_scope * global_scope
Definition: tree.c:39
unsigned char zone_name[DHCP_MAXDNS_WIRE]
Definition: dhcpd.h:1756
Definition: tree.h:142
Definition: dhcpd.h:550
unsigned len
Definition: tree.h:80
const char * piaddr(const struct iaddr addr)
Definition: inet.c:581
#define DDNS_STATE_ADD_FW_NXDOMAIN
Definition: dhcpd.h:1728
struct hash_bucket * next
Definition: hash.h:51
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
u_int16_t secs
Definition: dhcp.h:54
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition: inet.c:65
#define MDL
Definition: omapip.h:568
#define print_hex_1(len, data, limit)
Definition: dhcpd.h:2533
#define DDNS_STATE_REM_PTR
Definition: dhcpd.h:1734
u_int8_t hlen
Definition: dhcp.h:51
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1340
const char * pretty_print_option(struct option *option, const unsigned char *data, unsigned len, int emit_commas, int emit_quotes)
Definition: options.c:1676
Definition: tree.h:141
void print_dns_status(int, struct dhcp_ddns_cb *, isc_result_t)
struct in_addr siaddr
Definition: dhcp.h:58
Definition: tree.h:177
void dump_packet(struct packet *)
#define DDNS_STATE_REM_FW_YXDHCID
Definition: dhcpd.h:1732
struct data_string fwd_name
Definition: dhcpd.h:1748
u_int16_t flags
Definition: dhcp.h:55
#define LOCAL_TIME_FORMAT
Definition: dhcpd.h:2516
struct iaddr address
Definition: dhcpd.h:1751
unsigned long ttl
Definition: dhcpd.h:1754
Definition: tree.h:302
void log_fatal(const char *,...) __attribute__((__format__(__printf__
unsigned len
Definition: hash.h:53
struct data_string dhcid
Definition: dhcpd.h:1750
struct data_string rev_name
Definition: dhcpd.h:1749
union expression::expr_union data
u_int8_t htype
Definition: dhcp.h:50
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition: tree.c:2688
Definition: tree.h:346
unsigned char chaddr[16]
Definition: dhcp.h:60
u_int32_t xid
Definition: dhcp.h:53
#define DDNS_STATE_ADD_PTR
Definition: dhcpd.h:1730
Definition: dhcpd.h:405
struct in_addr yiaddr
Definition: dhcp.h:57
struct in_addr giaddr
Definition: dhclient.c:73
void dfree(void *, const char *, int)
Definition: alloc.c:131
#define DEFAULT_TIME_FORMAT
Definition: dhcpd.h:2515
int int log_info(const char *,...) __attribute__((__format__(__printf__
Definition: tree.h:143
struct universe ** universes
Definition: tables.c:918
void option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
Definition: options.c:3632
void indent(int)
struct string_list * next
Definition: dhcpd.h:348
time_t TIME
Definition: dhcpd.h:85
int state
Definition: dhcpd.h:1764
#define DDNS_STATE_ADD_FW_YXDHCID
Definition: dhcpd.h:1729
u_int8_t hops
Definition: dhcp.h:52
#define MAX_TIME
Definition: dhcpd.h:1572
void * transaction
Definition: dhcpd.h:1773
void dump_packet_option(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)
const char * file
Definition: dhcpd.h:3676
const unsigned char * data
Definition: tree.h:79
struct in_addr ciaddr
Definition: dhcp.h:56
#define DDNS_STATE_CLEANUP
Definition: dhcpd.h:1726
#define DDNS_STATE_REM_FW_NXRR
Definition: dhcpd.h:1733
u_int8_t op
Definition: dhcp.h:49
int universe_count
Definition: tables.c:919
unsigned char options[DHCP_MAX_OPTION_LEN]
Definition: dhcp.h:63
Definition: tree.h:180