00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031
00032 int db_time_format = DEFAULT_TIME_FORMAT;
00033
00034 char *quotify_string (const char *s, const char *file, int line)
00035 {
00036 unsigned len = 0;
00037 const char *sp;
00038 char *buf, *nsp;
00039
00040 for (sp = s; sp && *sp; sp++) {
00041 if (*sp == ' ')
00042 len++;
00043 else if (!isascii ((int)*sp) || !isprint ((int)*sp))
00044 len += 4;
00045 else if (*sp == '"' || *sp == '\\')
00046 len += 2;
00047 else
00048 len++;
00049 }
00050
00051 buf = dmalloc (len + 1, file, line);
00052 if (buf) {
00053 nsp = buf;
00054 for (sp = s; sp && *sp; sp++) {
00055 if (*sp == ' ')
00056 *nsp++ = ' ';
00057 else if (!isascii ((int)*sp) || !isprint ((int)*sp)) {
00058 sprintf (nsp, "\\%03o",
00059 *(const unsigned char *)sp);
00060 nsp += 4;
00061 } else if (*sp == '"' || *sp == '\\') {
00062 *nsp++ = '\\';
00063 *nsp++ = *sp;
00064 } else
00065 *nsp++ = *sp;
00066 }
00067 *nsp++ = 0;
00068 }
00069 return buf;
00070 }
00071
00072 char *quotify_buf (const unsigned char *s, unsigned len,
00073 const char *file, int line)
00074 {
00075 unsigned nulen = 0;
00076 char *buf, *nsp;
00077 int i;
00078
00079 for (i = 0; i < len; i++) {
00080 if (s [i] == ' ')
00081 nulen++;
00082 else if (!isascii (s [i]) || !isprint (s [i]))
00083 nulen += 4;
00084 else if (s [i] == '"' || s [i] == '\\')
00085 nulen += 2;
00086 else
00087 nulen++;
00088 }
00089
00090 buf = dmalloc (nulen + 1, MDL);
00091 if (buf) {
00092 nsp = buf;
00093 for (i = 0; i < len; i++) {
00094 if (s [i] == ' ')
00095 *nsp++ = ' ';
00096 else if (!isascii (s [i]) || !isprint (s [i])) {
00097 sprintf (nsp, "\\%03o", s [i]);
00098 nsp += 4;
00099 } else if (s [i] == '"' || s [i] == '\\') {
00100 *nsp++ = '\\';
00101 *nsp++ = s [i];
00102 } else
00103 *nsp++ = s [i];
00104 }
00105 *nsp++ = 0;
00106 }
00107 return buf;
00108 }
00109
00110 char *print_base64 (const unsigned char *buf, unsigned len,
00111 const char *file, int line)
00112 {
00113 char *s, *b;
00114 unsigned bl;
00115 int i;
00116 unsigned val, extra;
00117 static char to64 [] =
00118 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00119
00120 bl = ((len * 4 + 2) / 3) + 1;
00121 b = dmalloc (bl + 1, file, line);
00122 if (!b)
00123 return (char *)0;
00124
00125 i = 0;
00126 s = b;
00127 while (i != len) {
00128 val = buf [i++];
00129 extra = val & 3;
00130 val = val >> 2;
00131 *s++ = to64 [val];
00132 if (i == len) {
00133 *s++ = to64 [extra << 4];
00134 *s++ = '=';
00135 break;
00136 }
00137 val = (extra << 8) + buf [i++];
00138 extra = val & 15;
00139 val = val >> 4;
00140 *s++ = to64 [val];
00141 if (i == len) {
00142 *s++ = to64 [extra << 2];
00143 *s++ = '=';
00144 break;
00145 }
00146 val = (extra << 8) + buf [i++];
00147 extra = val & 0x3f;
00148 val = val >> 6;
00149 *s++ = to64 [val];
00150 *s++ = to64 [extra];
00151 }
00152 if (!len)
00153 *s++ = '=';
00154 *s++ = 0;
00155 if (s > b + bl + 1)
00156 abort ();
00157 return b;
00158 }
00159
00160 char *print_hw_addr (htype, hlen, data)
00161 const int htype;
00162 const int hlen;
00163 const unsigned char *data;
00164 {
00165 static char habuf [49];
00166 char *s;
00167 int i;
00168
00169 if (hlen <= 0)
00170 habuf [0] = 0;
00171 else {
00172 s = habuf;
00173 for (i = 0; i < hlen; i++) {
00174 sprintf (s, "%02x", data [i]);
00175 s += strlen (s);
00176 *s++ = ':';
00177 }
00178 *--s = 0;
00179 }
00180 return habuf;
00181 }
00182
00183 void print_lease (lease)
00184 struct lease *lease;
00185 {
00186 struct tm *t;
00187 char tbuf [32];
00188
00189 log_debug (" Lease %s",
00190 piaddr (lease -> ip_addr));
00191
00192 t = gmtime (&lease -> starts);
00193 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
00194 log_debug (" start %s", tbuf);
00195
00196 t = gmtime (&lease -> ends);
00197 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
00198 log_debug (" end %s", tbuf);
00199
00200 if (lease -> hardware_addr.hlen)
00201 log_debug (" hardware addr = %s",
00202 print_hw_addr (lease -> hardware_addr.hbuf [0],
00203 lease -> hardware_addr.hlen - 1,
00204 &lease -> hardware_addr.hbuf [1]));
00205 log_debug (" host %s ",
00206 lease -> host ? lease -> host -> name : "<none>");
00207 }
00208
00209 #if defined (DEBUG_PACKET)
00210 void dump_packet_option (struct option_cache *oc,
00211 struct packet *packet,
00212 struct lease *lease,
00213 struct client_state *client,
00214 struct option_state *in_options,
00215 struct option_state *cfg_options,
00216 struct binding_scope **scope,
00217 struct universe *u, void *foo)
00218 {
00219 const char *name, *dot;
00220 struct data_string ds;
00221 memset (&ds, 0, sizeof ds);
00222
00223 if (u != &dhcp_universe) {
00224 name = u -> name;
00225 dot = ".";
00226 } else {
00227 name = "";
00228 dot = "";
00229 }
00230 if (evaluate_option_cache (&ds, packet, lease, client,
00231 in_options, cfg_options, scope, oc, MDL)) {
00232 log_debug (" option %s%s%s %s;\n",
00233 name, dot, oc -> option -> name,
00234 pretty_print_option (oc -> option,
00235 ds.data, ds.len, 1, 1));
00236 data_string_forget (&ds, MDL);
00237 }
00238 }
00239
00240 void dump_packet (tp)
00241 struct packet *tp;
00242 {
00243 struct dhcp_packet *tdp = tp -> raw;
00244
00245 log_debug ("packet length %d", tp -> packet_length);
00246 log_debug ("op = %d htype = %d hlen = %d hops = %d",
00247 tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
00248 log_debug ("xid = %x secs = %ld flags = %x",
00249 tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
00250 log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
00251 log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
00252 log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
00253 log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
00254 log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
00255 ((unsigned char *)(tdp -> chaddr)) [0],
00256 ((unsigned char *)(tdp -> chaddr)) [1],
00257 ((unsigned char *)(tdp -> chaddr)) [2],
00258 ((unsigned char *)(tdp -> chaddr)) [3],
00259 ((unsigned char *)(tdp -> chaddr)) [4],
00260 ((unsigned char *)(tdp -> chaddr)) [5]);
00261 log_debug ("filename = %s", tdp -> file);
00262 log_debug ("server_name = %s", tdp -> sname);
00263 if (tp -> options_valid) {
00264 int i;
00265
00266 for (i = 0; i < tp -> options -> universe_count; i++) {
00267 if (tp -> options -> universes [i]) {
00268 option_space_foreach (tp, (struct lease *)0,
00269 (struct client_state *)0,
00270 (struct option_state *)0,
00271 tp -> options,
00272 &global_scope,
00273 universes [i], 0,
00274 dump_packet_option);
00275 }
00276 }
00277 }
00278 log_debug ("%s", "");
00279 }
00280 #endif
00281
00282 void dump_raw (buf, len)
00283 const unsigned char *buf;
00284 unsigned len;
00285 {
00286 int i;
00287 char lbuf [80];
00288 int lbix = 0;
00289
00290
00291
00292
00293
00294
00295
00296 memset(lbuf, ' ', 79);
00297 lbuf [79] = 0;
00298
00299 for (i = 0; i < len; i++) {
00300 if ((i & 15) == 0) {
00301 if (lbix) {
00302 lbuf[53]=' ';
00303 lbuf[54]=' ';
00304 lbuf[55]=' ';
00305 lbuf[73]='\0';
00306 log_info ("%s", lbuf);
00307 }
00308 memset(lbuf, ' ', 79);
00309 lbuf [79] = 0;
00310 sprintf (lbuf, "%03x:", i);
00311 lbix = 4;
00312 } else if ((i & 7) == 0)
00313 lbuf [lbix++] = ' ';
00314
00315 if(isprint(buf[i])) {
00316 lbuf[56+(i%16)]=buf[i];
00317 } else {
00318 lbuf[56+(i%16)]='.';
00319 }
00320
00321 sprintf (&lbuf [lbix], " %02x", buf [i]);
00322 lbix += 3;
00323 lbuf[lbix]=' ';
00324
00325 }
00326 lbuf[53]=' ';
00327 lbuf[54]=' ';
00328 lbuf[55]=' ';
00329 lbuf[73]='\0';
00330 log_info ("%s", lbuf);
00331 }
00332
00333 void hash_dump (table)
00334 struct hash_table *table;
00335 {
00336 int i;
00337 struct hash_bucket *bp;
00338
00339 if (!table)
00340 return;
00341
00342 for (i = 0; i < table -> hash_count; i++) {
00343 if (!table -> buckets [i])
00344 continue;
00345 log_info ("hash bucket %d:", i);
00346 for (bp = table -> buckets [i]; bp; bp = bp -> next) {
00347 if (bp -> len)
00348 dump_raw (bp -> name, bp -> len);
00349 else
00350 log_info ("%s", (const char *)bp -> name);
00351 }
00352 }
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 void print_hex_only (len, data, limit, buf)
00370 unsigned len;
00371 const u_int8_t *data;
00372 unsigned limit;
00373 char *buf;
00374 {
00375 unsigned i;
00376
00377 if ((buf == NULL) || (limit < 3))
00378 return;
00379
00380 for (i = 0; (i < limit / 3) && (i < len); i++) {
00381 sprintf(&buf[i*3], "%02x:", data[i]);
00382 }
00383 buf[(i * 3) - 1] = 0;
00384 return;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 void print_hex_or_string (len, data, limit, buf)
00397 unsigned len;
00398 const u_int8_t *data;
00399 unsigned limit;
00400 char *buf;
00401 {
00402 unsigned i;
00403 if ((buf == NULL) || (limit < 3))
00404 return;
00405
00406 for (i = 0; (i < (limit - 3)) && (i < len); i++) {
00407 if (!isascii(data[i]) || !isprint(data[i])) {
00408 print_hex_only(len, data, limit, buf);
00409 return;
00410 }
00411 }
00412
00413 buf[0] = '"';
00414 i = len;
00415 if (i > (limit - 3))
00416 i = limit - 3;
00417 memcpy(&buf[1], data, i);
00418 buf[i + 1] = '"';
00419 buf[i + 2] = 0;
00420 return;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 #define HBLEN 1024
00433 char *print_hex(len, data, limit, buf_num)
00434 unsigned len;
00435 const u_int8_t *data;
00436 unsigned limit;
00437 unsigned buf_num;
00438 {
00439 static char hex_buf_1[HBLEN + 1];
00440 static char hex_buf_2[HBLEN + 1];
00441 static char hex_buf_3[HBLEN + 1];
00442 char *hex_buf;
00443
00444 switch(buf_num) {
00445 case 0:
00446 hex_buf = hex_buf_1;
00447 if (limit >= sizeof(hex_buf_1))
00448 limit = sizeof(hex_buf_1);
00449 break;
00450 case 1:
00451 hex_buf = hex_buf_2;
00452 if (limit >= sizeof(hex_buf_2))
00453 limit = sizeof(hex_buf_2);
00454 break;
00455 case 2:
00456 hex_buf = hex_buf_3;
00457 if (limit >= sizeof(hex_buf_3))
00458 limit = sizeof(hex_buf_3);
00459 break;
00460 default:
00461 return(NULL);
00462 }
00463
00464 print_hex_or_string(len, data, limit, hex_buf);
00465 return(hex_buf);
00466 }
00467
00468 #define DQLEN 80
00469
00470 char *print_dotted_quads (len, data)
00471 unsigned len;
00472 const u_int8_t *data;
00473 {
00474 static char dq_buf [DQLEN + 1];
00475 int i;
00476 char *s;
00477
00478 s = &dq_buf [0];
00479
00480 i = 0;
00481
00482
00483
00484
00485
00486
00487 do {
00488 sprintf (s, "%u.%u.%u.%u, ",
00489 data [i], data [i + 1], data [i + 2], data [i + 3]);
00490 s += strlen (s);
00491 i += 4;
00492 } while ((s - &dq_buf [0] > DQLEN - 21) &&
00493 i + 3 < len);
00494 if (i == len)
00495 s [-2] = 0;
00496 else
00497 strcpy (s, "...");
00498 return dq_buf;
00499 }
00500
00501 char *print_dec_1 (val)
00502 unsigned long val;
00503 {
00504 static char vbuf [32];
00505 sprintf (vbuf, "%lu", val);
00506 return vbuf;
00507 }
00508
00509 char *print_dec_2 (val)
00510 unsigned long val;
00511 {
00512 static char vbuf [32];
00513 sprintf (vbuf, "%lu", val);
00514 return vbuf;
00515 }
00516
00517 static unsigned print_subexpression (struct expression *, char *, unsigned);
00518
00519 static unsigned print_subexpression (expr, buf, len)
00520 struct expression *expr;
00521 char *buf;
00522 unsigned len;
00523 {
00524 unsigned rv, left;
00525 const char *s;
00526
00527 switch (expr -> op) {
00528 case expr_none:
00529 if (len > 3) {
00530 strcpy (buf, "nil");
00531 return 3;
00532 }
00533 break;
00534
00535 case expr_match:
00536 if (len > 7) {
00537 strcpy (buf, "(match)");
00538 return 7;
00539 }
00540 break;
00541
00542 case expr_check:
00543 rv = 10 + strlen (expr -> data.check -> name);
00544 if (len > rv) {
00545 sprintf (buf, "(check %s)",
00546 expr -> data.check -> name);
00547 return rv;
00548 }
00549 break;
00550
00551 case expr_equal:
00552 if (len > 6) {
00553 rv = 4;
00554 strcpy (buf, "(eq ");
00555 rv += print_subexpression (expr -> data.equal [0],
00556 buf + rv, len - rv - 2);
00557 buf [rv++] = ' ';
00558 rv += print_subexpression (expr -> data.equal [1],
00559 buf + rv, len - rv - 1);
00560 buf [rv++] = ')';
00561 buf [rv] = 0;
00562 return rv;
00563 }
00564 break;
00565
00566 case expr_not_equal:
00567 if (len > 7) {
00568 rv = 5;
00569 strcpy (buf, "(neq ");
00570 rv += print_subexpression (expr -> data.equal [0],
00571 buf + rv, len - rv - 2);
00572 buf [rv++] = ' ';
00573 rv += print_subexpression (expr -> data.equal [1],
00574 buf + rv, len - rv - 1);
00575 buf [rv++] = ')';
00576 buf [rv] = 0;
00577 return rv;
00578 }
00579 break;
00580
00581 case expr_regex_match:
00582 if (len > 10) {
00583 rv = 4;
00584 strcpy(buf, "(regex ");
00585 rv += print_subexpression(expr->data.equal[0],
00586 buf + rv, len - rv - 2);
00587 buf[rv++] = ' ';
00588 rv += print_subexpression(expr->data.equal[1],
00589 buf + rv, len - rv - 1);
00590 buf[rv++] = ')';
00591 buf[rv] = 0;
00592 return rv;
00593 }
00594 break;
00595
00596 case expr_substring:
00597 if (len > 11) {
00598 rv = 8;
00599 strcpy (buf, "(substr ");
00600 rv += print_subexpression (expr -> data.substring.expr,
00601 buf + rv, len - rv - 3);
00602 buf [rv++] = ' ';
00603 rv += print_subexpression
00604 (expr -> data.substring.offset,
00605 buf + rv, len - rv - 2);
00606 buf [rv++] = ' ';
00607 rv += print_subexpression (expr -> data.substring.len,
00608 buf + rv, len - rv - 1);
00609 buf [rv++] = ')';
00610 buf [rv] = 0;
00611 return rv;
00612 }
00613 break;
00614
00615 case expr_suffix:
00616 if (len > 10) {
00617 rv = 8;
00618 strcpy (buf, "(suffix ");
00619 rv += print_subexpression (expr -> data.suffix.expr,
00620 buf + rv, len - rv - 2);
00621 if (len > rv)
00622 buf [rv++] = ' ';
00623 rv += print_subexpression (expr -> data.suffix.len,
00624 buf + rv, len - rv - 1);
00625 if (len > rv)
00626 buf [rv++] = ')';
00627 buf [rv] = 0;
00628 return rv;
00629 }
00630 break;
00631
00632 case expr_lcase:
00633 if (len > 9) {
00634 rv = 7;
00635 strcpy(buf, "(lcase ");
00636 rv += print_subexpression(expr->data.lcase,
00637 buf + rv, len - rv - 1);
00638 buf[rv++] = ')';
00639 buf[rv] = 0;
00640 return rv;
00641 }
00642 break;
00643
00644 case expr_ucase:
00645 if (len > 9) {
00646 rv = 7;
00647 strcpy(buf, "(ucase ");
00648 rv += print_subexpression(expr->data.ucase,
00649 buf + rv, len - rv - 1);
00650 buf[rv++] = ')';
00651 buf[rv] = 0;
00652 return rv;
00653 }
00654 break;
00655
00656 case expr_concat:
00657 if (len > 10) {
00658 rv = 8;
00659 strcpy (buf, "(concat ");
00660 rv += print_subexpression (expr -> data.concat [0],
00661 buf + rv, len - rv - 2);
00662 buf [rv++] = ' ';
00663 rv += print_subexpression (expr -> data.concat [1],
00664 buf + rv, len - rv - 1);
00665 buf [rv++] = ')';
00666 buf [rv] = 0;
00667 return rv;
00668 }
00669 break;
00670
00671 case expr_pick_first_value:
00672 if (len > 8) {
00673 rv = 6;
00674 strcpy (buf, "(pick1st ");
00675 rv += print_subexpression
00676 (expr -> data.pick_first_value.car,
00677 buf + rv, len - rv - 2);
00678 buf [rv++] = ' ';
00679 rv += print_subexpression
00680 (expr -> data.pick_first_value.cdr,
00681 buf + rv, len - rv - 1);
00682 buf [rv++] = ')';
00683 buf [rv] = 0;
00684 return rv;
00685 }
00686 break;
00687
00688 case expr_host_lookup:
00689 rv = 15 + strlen (expr -> data.host_lookup -> hostname);
00690 if (len > rv) {
00691 sprintf (buf, "(dns-lookup %s)",
00692 expr -> data.host_lookup -> hostname);
00693 return rv;
00694 }
00695 break;
00696
00697 case expr_and:
00698 s = "and";
00699 binop:
00700 rv = strlen (s);
00701 if (len > rv + 4) {
00702 buf [0] = '(';
00703 strcpy (&buf [1], s);
00704 rv += 1;
00705 buf [rv++] = ' ';
00706 rv += print_subexpression (expr -> data.and [0],
00707 buf + rv, len - rv - 2);
00708 buf [rv++] = ' ';
00709 rv += print_subexpression (expr -> data.and [1],
00710 buf + rv, len - rv - 1);
00711 buf [rv++] = ')';
00712 buf [rv] = 0;
00713 return rv;
00714 }
00715 break;
00716
00717 case expr_or:
00718 s = "or";
00719 goto binop;
00720
00721 case expr_add:
00722 s = "+";
00723 goto binop;
00724
00725 case expr_subtract:
00726 s = "-";
00727 goto binop;
00728
00729 case expr_multiply:
00730 s = "*";
00731 goto binop;
00732
00733 case expr_divide:
00734 s = "/";
00735 goto binop;
00736
00737 case expr_remainder:
00738 s = "%";
00739 goto binop;
00740
00741 case expr_binary_and:
00742 s = "&";
00743 goto binop;
00744
00745 case expr_binary_or:
00746 s = "|";
00747 goto binop;
00748
00749 case expr_binary_xor:
00750 s = "^";
00751 goto binop;
00752
00753 case expr_not:
00754 if (len > 6) {
00755 rv = 5;
00756 strcpy (buf, "(not ");
00757 rv += print_subexpression (expr -> data.not,
00758 buf + rv, len - rv - 1);
00759 buf [rv++] = ')';
00760 buf [rv] = 0;
00761 return rv;
00762 }
00763 break;
00764
00765 case expr_config_option:
00766 s = "cfg-option";
00767 goto dooption;
00768
00769 case expr_option:
00770 s = "option";
00771 dooption:
00772 rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
00773 strlen (expr -> data.option -> universe -> name));
00774 if (len > rv) {
00775 sprintf (buf, "(option %s.%s)",
00776 expr -> data.option -> universe -> name,
00777 expr -> data.option -> name);
00778 return rv;
00779 }
00780 break;
00781
00782 case expr_hardware:
00783 if (len > 10) {
00784 strcpy (buf, "(hardware)");
00785 return 10;
00786 }
00787 break;
00788
00789 case expr_packet:
00790 if (len > 10) {
00791 rv = 8;
00792 strcpy (buf, "(substr ");
00793 rv += print_subexpression (expr -> data.packet.offset,
00794 buf + rv, len - rv - 2);
00795 buf [rv++] = ' ';
00796 rv += print_subexpression (expr -> data.packet.len,
00797 buf + rv, len - rv - 1);
00798 buf [rv++] = ')';
00799 buf [rv] = 0;
00800 return rv;
00801 }
00802 break;
00803
00804 case expr_const_data:
00805 s = print_hex_1 (expr -> data.const_data.len,
00806 expr -> data.const_data.data, len);
00807 rv = strlen (s);
00808 if (rv >= len)
00809 rv = len - 1;
00810 strncpy (buf, s, rv);
00811 buf [rv] = 0;
00812 return rv;
00813
00814 case expr_encapsulate:
00815 rv = 13;
00816 strcpy (buf, "(encapsulate ");
00817 rv += expr -> data.encapsulate.len;
00818 if (rv + 2 > len)
00819 rv = len - 2;
00820 strncpy (buf,
00821 (const char *)expr -> data.encapsulate.data, rv - 13);
00822 buf [rv++] = ')';
00823 buf [rv++] = 0;
00824 break;
00825
00826 case expr_extract_int8:
00827 if (len > 7) {
00828 rv = 6;
00829 strcpy (buf, "(int8 ");
00830 rv += print_subexpression (expr -> data.extract_int,
00831 buf + rv, len - rv - 1);
00832 buf [rv++] = ')';
00833 buf [rv] = 0;
00834 return rv;
00835 }
00836 break;
00837
00838 case expr_extract_int16:
00839 if (len > 8) {
00840 rv = 7;
00841 strcpy (buf, "(int16 ");
00842 rv += print_subexpression (expr -> data.extract_int,
00843 buf + rv, len - rv - 1);
00844 buf [rv++] = ')';
00845 buf [rv] = 0;
00846 return rv;
00847 }
00848 break;
00849
00850 case expr_extract_int32:
00851 if (len > 8) {
00852 rv = 7;
00853 strcpy (buf, "(int32 ");
00854 rv += print_subexpression (expr -> data.extract_int,
00855 buf + rv, len - rv - 1);
00856 buf [rv++] = ')';
00857 buf [rv] = 0;
00858 return rv;
00859 }
00860 break;
00861
00862 case expr_encode_int8:
00863 if (len > 7) {
00864 rv = 6;
00865 strcpy (buf, "(to-int8 ");
00866 rv += print_subexpression (expr -> data.encode_int,
00867 buf + rv, len - rv - 1);
00868 buf [rv++] = ')';
00869 buf [rv] = 0;
00870 return rv;
00871 }
00872 break;
00873
00874 case expr_encode_int16:
00875 if (len > 8) {
00876 rv = 7;
00877 strcpy (buf, "(to-int16 ");
00878 rv += print_subexpression (expr -> data.encode_int,
00879 buf + rv, len - rv - 1);
00880 buf [rv++] = ')';
00881 buf [rv] = 0;
00882 return rv;
00883 }
00884 break;
00885
00886 case expr_encode_int32:
00887 if (len > 8) {
00888 rv = 7;
00889 strcpy (buf, "(to-int32 ");
00890 rv += print_subexpression (expr -> data.encode_int,
00891 buf + rv, len - rv - 1);
00892 buf [rv++] = ')';
00893 buf [rv] = 0;
00894 return rv;
00895 }
00896 break;
00897
00898 case expr_const_int:
00899 s = print_dec_1 (expr -> data.const_int);
00900 rv = strlen (s);
00901 if (len > rv) {
00902 strcpy (buf, s);
00903 return rv;
00904 }
00905 break;
00906
00907 case expr_exists:
00908 rv = 10 + (strlen (expr -> data.option -> name) +
00909 strlen (expr -> data.option -> universe -> name));
00910 if (len > rv) {
00911 sprintf (buf, "(exists %s.%s)",
00912 expr -> data.option -> universe -> name,
00913 expr -> data.option -> name);
00914 return rv;
00915 }
00916 break;
00917
00918 case expr_variable_exists:
00919 rv = 10 + strlen (expr -> data.variable);
00920 if (len > rv) {
00921 sprintf (buf, "(defined %s)", expr -> data.variable);
00922 return rv;
00923 }
00924 break;
00925
00926 case expr_variable_reference:
00927 rv = strlen (expr -> data.variable);
00928 if (len > rv) {
00929 sprintf (buf, "%s", expr -> data.variable);
00930 return rv;
00931 }
00932 break;
00933
00934 case expr_known:
00935 s = "known";
00936 astring:
00937 rv = strlen (s);
00938 if (len > rv) {
00939 strcpy (buf, s);
00940 return rv;
00941 }
00942 break;
00943
00944 case expr_leased_address:
00945 s = "leased-address";
00946 goto astring;
00947
00948 case expr_client_state:
00949 s = "client-state";
00950 goto astring;
00951
00952 case expr_host_decl_name:
00953 s = "host-decl-name";
00954 goto astring;
00955
00956 case expr_lease_time:
00957 s = "lease-time";
00958 goto astring;
00959
00960 case expr_static:
00961 s = "static";
00962 goto astring;
00963
00964 case expr_filename:
00965 s = "filename";
00966 goto astring;
00967
00968 case expr_sname:
00969 s = "server-name";
00970 goto astring;
00971
00972 case expr_reverse:
00973 if (len > 11) {
00974 rv = 13;
00975 strcpy (buf, "(reverse ");
00976 rv += print_subexpression (expr -> data.reverse.width,
00977 buf + rv, len - rv - 2);
00978 buf [rv++] = ' ';
00979 rv += print_subexpression (expr -> data.reverse.buffer,
00980 buf + rv, len - rv - 1);
00981 buf [rv++] = ')';
00982 buf [rv] = 0;
00983 return rv;
00984 }
00985 break;
00986
00987 case expr_binary_to_ascii:
00988 if (len > 5) {
00989 rv = 9;
00990 strcpy (buf, "(b2a ");
00991 rv += print_subexpression (expr -> data.b2a.base,
00992 buf + rv, len - rv - 4);
00993 buf [rv++] = ' ';
00994 rv += print_subexpression (expr -> data.b2a.width,
00995 buf + rv, len - rv - 3);
00996 buf [rv++] = ' ';
00997 rv += print_subexpression (expr -> data.b2a.separator,
00998 buf + rv, len - rv - 2);
00999 buf [rv++] = ' ';
01000 rv += print_subexpression (expr -> data.b2a.buffer,
01001 buf + rv, len - rv - 1);
01002 buf [rv++] = ')';
01003 buf [rv] = 0;
01004 return rv;
01005 }
01006 break;
01007
01008 case expr_dns_transaction:
01009 rv = 10;
01010 if (len < rv + 2) {
01011 buf [0] = '(';
01012 strcpy (&buf [1], "ns-update ");
01013 while (len < rv + 2) {
01014 rv += print_subexpression
01015 (expr -> data.dns_transaction.car,
01016 buf + rv, len - rv - 2);
01017 buf [rv++] = ' ';
01018 expr = expr -> data.dns_transaction.cdr;
01019 }
01020 buf [rv - 1] = ')';
01021 buf [rv] = 0;
01022 return rv;
01023 }
01024 return 0;
01025
01026 case expr_ns_delete:
01027 s = "delete";
01028 left = 4;
01029 goto dodnsupd;
01030 case expr_ns_exists:
01031 s = "exists";
01032 left = 4;
01033 goto dodnsupd;
01034 case expr_ns_not_exists:
01035 s = "not_exists";
01036 left = 4;
01037 goto dodnsupd;
01038 case expr_ns_add:
01039 s = "update";
01040 left = 5;
01041 dodnsupd:
01042 rv = strlen (s);
01043 if (len > strlen (s) + 1) {
01044 buf [0] = '(';
01045 strcpy (buf + 1, s);
01046 rv++;
01047 buf [rv++] = ' ';
01048 s = print_dec_1 (expr -> data.ns_add.rrclass);
01049 if (len > rv + strlen (s) + left) {
01050 strcpy (&buf [rv], s);
01051 rv += strlen (&buf [rv]);
01052 }
01053 buf [rv++] = ' ';
01054 left--;
01055 s = print_dec_1 (expr -> data.ns_add.rrtype);
01056 if (len > rv + strlen (s) + left) {
01057 strcpy (&buf [rv], s);
01058 rv += strlen (&buf [rv]);
01059 }
01060 buf [rv++] = ' ';
01061 left--;
01062 rv += print_subexpression
01063 (expr -> data.ns_add.rrname,
01064 buf + rv, len - rv - left);
01065 buf [rv++] = ' ';
01066 left--;
01067 rv += print_subexpression
01068 (expr -> data.ns_add.rrdata,
01069 buf + rv, len - rv - left);
01070 buf [rv++] = ' ';
01071 left--;
01072 rv += print_subexpression
01073 (expr -> data.ns_add.ttl,
01074 buf + rv, len - rv - left);
01075 buf [rv++] = ')';
01076 buf [rv] = 0;
01077 return rv;
01078 }
01079 break;
01080
01081 case expr_null:
01082 if (len > 6) {
01083 strcpy (buf, "(null)");
01084 return 6;
01085 }
01086 break;
01087 case expr_funcall:
01088 rv = 12 + strlen (expr -> data.funcall.name);
01089 if (len > rv + 1) {
01090 strcpy (buf, "(funcall ");
01091 strcpy (buf + 9, expr -> data.funcall.name);
01092 buf [rv++] = ' ';
01093 rv += print_subexpression
01094 (expr -> data.funcall.arglist, buf + rv,
01095 len - rv - 1);
01096 buf [rv++] = ')';
01097 buf [rv] = 0;
01098 return rv;
01099 }
01100 break;
01101
01102 case expr_arg:
01103 rv = print_subexpression (expr -> data.arg.val, buf, len);
01104 if (expr -> data.arg.next && rv + 2 < len) {
01105 buf [rv++] = ' ';
01106 rv += print_subexpression (expr -> data.arg.next,
01107 buf, len);
01108 if (rv + 1 < len)
01109 buf [rv++] = 0;
01110 return rv;
01111 }
01112 break;
01113
01114 case expr_function:
01115 rv = 9;
01116 if (len > rv + 1) {
01117 struct string_list *foo;
01118 strcpy (buf, "(function");
01119 for (foo = expr -> data.func -> args;
01120 foo; foo = foo -> next) {
01121 if (len > rv + 2 + strlen (foo -> string)) {
01122 buf [rv - 1] = ' ';
01123 strcpy (&buf [rv], foo -> string);
01124 rv += strlen (foo -> string);
01125 }
01126 }
01127 buf [rv++] = ')';
01128 buf [rv] = 0;
01129 return rv;
01130 }
01131 break;
01132
01133 case expr_gethostname:
01134 if (len > 13) {
01135 strcpy(buf, "(gethostname)");
01136 return 13;
01137 }
01138 break;
01139
01140 default:
01141 log_fatal("Impossible case at %s:%d (undefined expression "
01142 "%d).", MDL, expr->op);
01143 break;
01144 }
01145 return 0;
01146 }
01147
01148 void print_expression (name, expr)
01149 const char *name;
01150 struct expression *expr;
01151 {
01152 char buf [1024];
01153
01154 print_subexpression (expr, buf, sizeof buf);
01155 log_info ("%s: %s", name, buf);
01156 }
01157
01158 int token_print_indent_concat (FILE *file, int col, int indent,
01159 const char *prefix,
01160 const char *suffix, ...)
01161 {
01162 va_list list;
01163 unsigned len;
01164 char *s, *t, *u;
01165
01166 va_start (list, suffix);
01167 s = va_arg (list, char *);
01168 len = 0;
01169 while (s) {
01170 len += strlen (s);
01171 s = va_arg (list, char *);
01172 }
01173 va_end (list);
01174
01175 t = dmalloc (len + 1, MDL);
01176 if (!t)
01177 log_fatal ("token_print_indent: no memory for copy buffer");
01178
01179 va_start (list, suffix);
01180 s = va_arg (list, char *);
01181 u = t;
01182 while (s) {
01183 len = strlen (s);
01184 strcpy (u, s);
01185 u += len;
01186 s = va_arg (list, char *);
01187 }
01188 va_end (list);
01189
01190 col = token_print_indent (file, col, indent,
01191 prefix, suffix, t);
01192 dfree (t, MDL);
01193 return col;
01194 }
01195
01196 int token_indent_data_string (FILE *file, int col, int indent,
01197 const char *prefix, const char *suffix,
01198 struct data_string *data)
01199 {
01200 int i;
01201 char *buf;
01202 char obuf [3];
01203
01204
01205 for (i = 0; i < data -> len; i++)
01206 if (!isascii (data -> data [i]) ||
01207 !isprint (data -> data [i]))
01208 break;
01209
01210
01211 if (i == data -> len) {
01212 buf = dmalloc (data -> len + 3, MDL);
01213 if (buf) {
01214 buf [0] = '"';
01215 memcpy (buf + 1, data -> data, data -> len);
01216 buf [data -> len + 1] = '"';
01217 buf [data -> len + 2] = 0;
01218 i = token_print_indent (file, col, indent,
01219 prefix, suffix, buf);
01220 dfree (buf, MDL);
01221 return i;
01222 }
01223 }
01224
01225 for (i = 0; i < data -> len; i++) {
01226 sprintf (obuf, "%2.2x", data -> data [i]);
01227 col = token_print_indent (file, col, indent,
01228 i == 0 ? prefix : "",
01229 (i + 1 == data -> len
01230 ? suffix
01231 : ""), obuf);
01232 if (i + 1 != data -> len)
01233 col = token_print_indent (file, col, indent,
01234 prefix, suffix, ":");
01235 }
01236 return col;
01237 }
01238
01239 int token_print_indent (FILE *file, int col, int indent,
01240 const char *prefix,
01241 const char *suffix, const char *buf)
01242 {
01243 int len = 0;
01244 if (prefix != NULL)
01245 len += strlen (prefix);
01246 if (buf != NULL)
01247 len += strlen (buf);
01248
01249 if (col + len > 79) {
01250 if (indent + len < 79) {
01251 indent_spaces (file, indent);
01252 col = indent;
01253 } else {
01254 indent_spaces (file, col);
01255 col = len > 79 ? 0 : 79 - len - 1;
01256 }
01257 } else if (prefix && *prefix) {
01258 fputs (prefix, file);
01259 col += strlen (prefix);
01260 }
01261 if ((buf != NULL) && (*buf != 0)) {
01262 fputs (buf, file);
01263 col += strlen(buf);
01264 }
01265 if (suffix && *suffix) {
01266 if (col + strlen (suffix) > 79) {
01267 indent_spaces (file, indent);
01268 col = indent;
01269 } else {
01270 fputs (suffix, file);
01271 col += strlen (suffix);
01272 }
01273 }
01274 return col;
01275 }
01276
01277 void indent_spaces (FILE *file, int indent)
01278 {
01279 int i;
01280 fputc ('\n', file);
01281 for (i = 0; i < indent; i++)
01282 fputc (' ', file);
01283 }
01284
01285 #if defined (NSUPDATE)
01286 #if defined (DEBUG_DNS_UPDATES)
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 void
01305 print_dns_status (int direction,
01306 struct dhcp_ddns_cb *ddns_cb,
01307 isc_result_t result)
01308 {
01309 char obuf[1024];
01310 char *s = obuf, *end = &obuf[sizeof(obuf)-2];
01311 char *en;
01312 const char *result_str;
01313 char ddns_address[
01314 sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
01315
01316 if (direction == DDNS_PRINT_INBOUND) {
01317 log_info("DDNS reply: id ptr %p, result: %s",
01318 ddns_cb->transaction, isc_result_totext(result));
01319 return;
01320 }
01321
01322
01323
01324
01325
01326 memset(obuf, 0, 1024);
01327
01328 en = "DDNS request: id ptr ";
01329 if (s + strlen(en) + 16 < end) {
01330 sprintf(s, "%s%p", en, ddns_cb->transaction);
01331 s += strlen(s);
01332 } else {
01333 goto bailout;
01334 }
01335
01336 switch (ddns_cb->state) {
01337 case DDNS_STATE_ADD_FW_NXDOMAIN:
01338 en = " add forward ";
01339 break;
01340 case DDNS_STATE_ADD_FW_YXDHCID:
01341 en = " modify forward ";
01342 break;
01343
01344 case DDNS_STATE_ADD_PTR:
01345 en = " add reverse ";
01346 break;
01347
01348 case DDNS_STATE_REM_FW_YXDHCID:
01349 en = " remove forward ";
01350 break;
01351
01352 case DDNS_STATE_REM_FW_NXRR:
01353 en = " remove rrset ";
01354 break;
01355
01356 case DDNS_STATE_REM_PTR:
01357 en = " remove reverse ";
01358 break;
01359
01360 case DDNS_STATE_CLEANUP:
01361 en = " cleanup ";
01362 break;
01363
01364 default:
01365 en = " unknown state ";
01366 break;
01367 }
01368
01369 switch (ddns_cb->state) {
01370 case DDNS_STATE_ADD_FW_NXDOMAIN:
01371 case DDNS_STATE_ADD_FW_YXDHCID:
01372 case DDNS_STATE_REM_FW_YXDHCID:
01373 case DDNS_STATE_REM_FW_NXRR:
01374 strcpy(ddns_address, piaddr(ddns_cb->address));
01375 if (s + strlen(en) + strlen(ddns_address) +
01376 ddns_cb->fwd_name.len + 5 < end) {
01377 sprintf(s, "%s%s for %.*s", en, ddns_address,
01378 ddns_cb->fwd_name.len,
01379 ddns_cb->fwd_name.data);
01380 s += strlen(s);
01381 } else {
01382 goto bailout;
01383 }
01384 break;
01385
01386 case DDNS_STATE_ADD_PTR:
01387 case DDNS_STATE_REM_PTR:
01388 if (s + strlen(en) + ddns_cb->fwd_name.len +
01389 ddns_cb->rev_name.len + 5 < end) {
01390 sprintf(s, "%s%.*s for %.*s", en,
01391 ddns_cb->fwd_name.len,
01392 ddns_cb->fwd_name.data,
01393 ddns_cb->rev_name.len,
01394 ddns_cb->rev_name.data);
01395 s += strlen(s);
01396 } else {
01397 goto bailout;
01398 }
01399 break;
01400
01401 case DDNS_STATE_CLEANUP:
01402 default:
01403 if (s + strlen(en) < end) {
01404 sprintf(s, "%s", en);
01405 s += strlen(s);
01406 } else {
01407 goto bailout;
01408 }
01409 break;
01410 }
01411
01412 en = " zone: ";
01413 if (s + strlen(en) + strlen((char *)ddns_cb->zone_name) < end) {
01414 sprintf(s, "%s%s", en, ddns_cb->zone_name);
01415 s += strlen(s);
01416 } else {
01417 goto bailout;
01418 }
01419
01420 en = " dhcid: ";
01421 if (ddns_cb->dhcid.len > 0) {
01422 if (s + strlen(en) + ddns_cb->dhcid.len-1 < end) {
01423 strcpy(s, en);
01424 s += strlen(s);
01425 strncpy(s, (char *)ddns_cb->dhcid.data+1,
01426 ddns_cb->dhcid.len-1);
01427 s += strlen(s);
01428 } else {
01429 goto bailout;
01430 }
01431 } else {
01432 en = " dhcid: <empty>";
01433 if (s + strlen(en) < end) {
01434 strcpy(s, en);
01435 s += strlen(s);
01436 } else {
01437 goto bailout;
01438 }
01439 }
01440
01441 en = " ttl: ";
01442 if (s + strlen(en) + 10 < end) {
01443 sprintf(s, "%s%ld", en, ddns_cb->ttl);
01444 s += strlen(s);
01445 } else {
01446 goto bailout;
01447 }
01448
01449 en = " result: ";
01450 result_str = isc_result_totext(result);
01451 if (s + strlen(en) + strlen(result_str) < end) {
01452 sprintf(s, "%s%s", en, result_str);
01453 s += strlen(s);
01454 } else {
01455 goto bailout;
01456 }
01457
01458 bailout:
01459
01460
01461
01462
01463 log_info("%s", obuf);
01464
01465 return;
01466 }
01467 #endif
01468 #endif
01469
01470
01471
01472
01473 const char *
01474 print_time(TIME t)
01475 {
01476 static char buf[sizeof("epoch 9223372036854775807; "
01477 "# Wed Jun 30 21:49:08 2147483647")];
01478 static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
01479 time_t since_epoch;
01480
01481
01482
01483
01484
01485 if (t == MAX_TIME)
01486 return "never;";
01487
01488 if (t < 0)
01489 return NULL;
01490
01491
01492
01493
01494
01495 #if (MAX_TIME > 0x7fffffffffffffff)
01496 if (t > 0x7fffffffffffffff)
01497 return NULL;
01498 #endif
01499
01500 if (db_time_format == LOCAL_TIME_FORMAT) {
01501 since_epoch = mktime(localtime(&t));
01502 if ((strftime(buf1, sizeof(buf1),
01503 "# %a %b %d %H:%M:%S %Y",
01504 localtime(&t)) == 0) ||
01505 (snprintf(buf, sizeof(buf), "epoch %lu; %s",
01506 (unsigned long)since_epoch, buf1) >= sizeof(buf)))
01507 return NULL;
01508
01509 } else {
01510
01511
01512
01513 if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
01514 gmtime(&t)) == 0)
01515 return NULL;
01516 }
01517
01518 return buf;
01519 }