76static void post_process_lifetimes(
struct parse *);
77static size_t post_process_reservations(
struct parse *);
78static void post_process_classes(
struct parse *);
79static void post_process_generated_classes(
struct parse *);
81static void post_process_option_definitions(
struct parse *);
82static void add_host_reservation_identifiers(
struct parse *,
const char *);
83static void add_host_id_option(
struct parse *,
const struct option *,
int);
84static void subclass_inherit(
struct parse *,
struct element *,
86static void add_match_class(
struct parse *,
struct element *,
88static void option_data_derive(
struct parse *,
struct handle *,
92static void new_network_interface(
struct parse *,
struct element *);
93static struct string *addrmask(
const struct string *,
const struct string *);
96static struct element *find_location(
struct element *,
struct range *);
97static int get_prefix_length(
const char *,
const char *);
103static struct string *CLASS_ALL;
104static struct string *CLASS_KNOWN;
130 cfile->
stack[0] = top;
145 ifconf =
mapGet(cfile->
stack[1],
"interfaces-config");
146 if (ifconf == NULL) {
150 "declares some subnets but "
151 "has no interfaces-config");
158 post_process_lifetimes(cfile);
160 issues += post_process_reservations(cfile);
161 post_process_classes(cfile);
162 post_process_generated_classes(cfile);
163 post_process_option_definitions(cfile);
170post_process_lifetimes(
struct parse *cfile)
185 entry =
mapGet(cfile->
stack[1],
"min-valid-lifetime");
193 mapSet(cfile->
stack[1], entry,
"min-valid-lifetime");
196 entry =
mapGet(cfile->
stack[1],
"max-valid-lifetime");
204 mapSet(cfile->
stack[1], entry,
"max-valid-lifetime");
218post_process_reservations(
struct parse *cfile)
239 where = find_match(cfile, host, &used_heuristic);
240 if (where == cfile->
stack[1])
243 dest =
mapGet(where,
"reservations");
247 mapSet(where, dest,
"reservations");
270post_process_classes(
struct parse *cfile)
282 classes =
mapGet(cfile->
stack[1],
"client-classes");
283 if ((classes == NULL) || (
listSize(classes) == 0))
285 for (i = 0; i <
listSize(classes); i++) {
290 name =
mapGet(
class,
"name");
293 "without a name", (
unsigned)i);
295 goto cleanup_superclass;
299 entry =
mapGet(
class,
"string");
303 "a bad string selector",
305 msg =
makeString(-1,
"/// subclass selector ");
314 entry =
mapGet(
class,
"binary");
318 msg =
makeString(-1,
"/// subclass selector 0x");
326 entry =
mapGet(
class,
"spawning");
335 "are not supported by Kea");
338 msg =
makeString(-1,
"/// Reference Kea #248");
344 entry =
mapGet(
class,
"submatch");
347 parse_error(cfile,
"superclass %s has no submatch",
360 entry =
mapGet(
class,
"match-if");
363 reduced =
mapGet(
class,
"test");
372 if (reduced != NULL) {
385post_process_generated_classes(
struct parse *cfile)
391 generated =
mapGet(cfile->
stack[1],
"generated-classes");
392 if (generated == NULL)
397 classes =
mapGet(cfile->
stack[1],
"client-classes");
398 if (classes == NULL) {
400 mapSet(cfile->
stack[1], classes,
"client-classes");
406 check_depend(
class, classes);
418 list =
mapGet(
class,
"depend");
430 assert(depend != NULL);
437 for (i = 0; i <
listSize(classes); i++) {
442 assert(item != NULL);
444 name =
mapGet(item,
"name");
455 msg =
makeString(-1,
"/// Depend on missing '");
465post_process_option_definitions(
struct parse *cfile)
488 if ((
file = open (filename, O_RDONLY)) < 0)
491 filename, strerror(errno));
495 parse_error(parent,
"Can't create new parse structure");
498 if (cfile->
stack == NULL)
499 parse_error(parent,
"Can't create new element stack");
516 if (parent->
stack == NULL)
617 "host declarations not allowed here.");
626 "group declarations not allowed here.");
635 parse_error(cfile,
"shared-network parameters not %s.",
646 "subnet declarations not allowed here.");
667 "class declarations not allowed here.");
675 add_host_reservation_identifiers(cfile,
690 parse_error(cfile,
"hardware address parameter %s",
691 "not allowed here.");
693 parse_error(cfile,
"Host hardware address already "
714 "fixed-address parameter not "
722 "declaration per host.");
730 cache,
"extra-ip-addresses");
736 "declaration per host.");
746 parse_error(cfile,
"pool declared outside of network");
763 "range declaration not allowed here.");
781 "range6 declaration not allowed here.");
799 "prefix6 declaration not allowed here.");
817 "fixed-prefix6 declaration not "
830 "pool6 declared outside of network");
852 parse_error(cfile,
"authority makes no sense here.");
888 if (token ==
SPACE) {
891 "option space definitions %s",
892 "may not be scoped.");
903 "option definitions%s",
904 " may not be scoped.");
923 fprintf(stderr,
"ignoring failover\n");
942 parse_error(cfile,
"directives are only supported "
959 "expecting a declaration");
962 "expecting a parameter %s",
1009 struct string *alias = NULL;
1043 alias =
makeString(-1,
"authenticated clients");
1045 authenticated_clients:
1047 "not supported by ISC DHCP and Kea");
1052 alias =
makeString(-1,
"unauthenticated clients");
1053 goto authenticated_clients;
1068 alias =
makeString(-1,
"dynamic bootp clients");
1071 "supported by Kea");
1097 "supported by Kea");
1151 int declaration = 0;
1152 unsigned range_counter = 0;
1159 parse_error(cfile,
"Dynamic pools are only valid inside "
1160 "subnet or shared-network statements.");
1175 fprintf(stderr,
"ignoring failover\n");
1218 generate_class(cfile,
pool,
permit, prohibit);
1221 if (
pools == NULL) {
1226 if (range_counter == 0) {
1238 while (--range_counter != 0) {
1290 int declaration = 0;
1299 parse_error(cfile,
"expecting a name for host declaration.");
1320 "in the config file");
1327 "in the config file");
1330 if (token ==
GROUP) {
1338 "expecting string or identifier.");
1343 "host reservations");
1353 struct string *client_id;
1356 add_host_reservation_identifiers(cfile,
1365 "client identifier.",
1378 (cfile, NULL, &len,
':', 16, 8);
1381 "expecting hex list.");
1400 add_host_reservation_identifiers(cfile,
1408 "only one host-identifier allowed "
1419 "host-identifier v6relopt "
1420 "must have a number");
1426 "host-identifier v6relopt "
1427 "must have a number >= 0");
1430 }
else if (token !=
OPTION)
1432 "host-identifier must be an option"
1453 mapSet(host, expr,
"host-identifier");
1456 add_host_id_option(cfile,
option, relays);
1486 where = find_match(cfile, host, &used_heuristic);
1487 hosts =
mapGet(where,
"reservations");
1488 if (hosts == NULL) {
1491 mapSet(where, hosts,
"reservations");
1492 if (used_heuristic) {
1496 "without fixed addresses "
1497 "were put in the last "
1509add_host_reservation_identifiers(
struct parse *cfile,
const char *
id)
1513 ids =
mapGet(cfile->
stack[1],
"host-reservation-identifiers");
1516 mapSet(cfile->
stack[1], ids,
"host-reservation-identifiers");
1523add_host_id_option(
struct parse *cfile,
1542 mapSet(cfile->
stack[1], hooks,
"hooks-libraries");
1544 "is a premium feature");
1558 mapSet(entry, params,
"library");
1560 mapSet(entry, params,
"parameters");
1562 snprintf(buf,
sizeof(buf),
"%soption[%u].hex",
1563 relays > 0 ?
"relay[0]." :
"",
option->
code);
1568static void add_host_reservation_identifiers(
struct parse *,
const char *);
1586 const char *val = NULL;
1590 struct element *group_classes = NULL;
1591 struct element *classes = NULL;
1598 int declaration = 0;
1599 struct string *name = NULL;
1609 classes =
mapGet(cfile->
stack[1],
"client-classes");
1610 if (classes == NULL) {
1613 mapSet(cfile->
stack[1], classes,
"client-classes");
1628 if (group_classes == NULL) {
1635 group_classes = classes;
1638 for (i = 0; i <
listSize(classes); i++) {
1642 name =
mapGet(tmp,
"name");
1645 if (strcmp(
stringValue(name)->content, val) == 0) {
1663 parse_error(cfile,
"found class name %s but it is "
1664 "not a suitable superclass", val);
1681 parse_error(cfile,
"Expecting string or hex list.");
1688 for (i = 0; i <
listSize(classes); i++) {
1693 super =
mapGet(tmp,
"super");
1699 selector =
mapGet(tmp,
"binary");
1701 selector =
mapGet(tmp,
"string");
1702 if (selector == NULL)
1713 if (group_classes != classes) {
1723 mapSet(gc, tmp,
"super");
1726 mapSet(gc, data,
"binary");
1728 mapSet(gc, data,
"string");
1746 mapSet(
class, tmp,
"super");
1749 mapSet(
class, data,
"binary");
1751 mapSet(
class, data,
"string");
1754 snprintf(buf,
sizeof(buf),
1767 if (token ==
SEMI) {
1769 subclass_inherit(cfile,
class,
copy(pc));
1786 }
else if (token ==
DYNAMIC) {
1789 "in the config file");
1793 "in the config file");
1794 }
else if (token ==
MATCH) {
1798 "invalid match in subclass.");
1803 mapSet(
class, expr,
"spawning");
1810 "A class may only have "
1811 "one 'match if' clause.");
1817 "expecting boolean expr.");
1820 mapSet(
class, expr,
"match-if");
1821 add_match_class(cfile,
class,
copy(expr));
1824 }
else if (token ==
SPAWN) {
1828 "invalid spawn in subclass.");
1832 mapSet(
class, expr,
"spawning");
1836 "expecting with after spawn");
1840 "can't override existing "
1847 "expecting data expr.");
1851 mapSet(
class, expr,
"submatch");
1854 }
else if (token ==
LEASE) {
1868 "supported by Kea");
1872 mapSet(
class, tmp,
"lease-limit");
1882 subclass_inherit(cfile,
class,
copy(pc));
1892subclass_inherit(
struct parse *cfile,
1913 expr =
mapGet(superclass,
"name");
1917 guard =
mapGet(superclass,
"match-if");
1918 submatch =
mapGet(superclass,
"submatch");
1919 if (submatch == NULL)
1920 parse_error(cfile,
"can't get superclass submatch");
1923 while (
mapSize(superclass) > 0) {
1927 parse_error(cfile,
"can't get superclass %s item at "
1931 if ((strcmp(
handle->
key,
"name") == 0) ||
1932 (strcmp(
handle->
key,
"spawning") == 0) ||
1933 (strcmp(
handle->
key,
"match-if") == 0) ||
1938 if ((strcmp(
handle->
key,
"super") == 0) ||
1941 parse_error(cfile,
"superclass %s has unexpected %s "
1945 if (strcmp(
handle->
key,
"option-data") == 0) {
1949 if (opt_list != NULL)
1956 if ((strcmp(
handle->
key,
"lease-limit") == 0) ||
1957 (strcmp(
handle->
key,
"boot-file-name") == 0) ||
1958 (strcmp(
handle->
key,
"serverhostname") == 0) ||
1959 (strcmp(
handle->
key,
"next-server") == 0)) {
1979 expr =
mapGet(
class,
"binary");
1984 data =
mapGet(
class,
"string");
1992 mapSet(expr, match,
"equal");
1994 if (guard != NULL) {
1997 mapSet(match, expr,
"right");
1999 mapSet(expr, match,
"and");
2001 gmsg =
makeString(-1,
"/// from: match-if ");
2017 parse_error(cfile,
"class matching rule evaluated to a "
2018 "constant boolean expression: %s = %s",
2033 mapSet(
class, reduced,
"test");
2041add_match_class(
struct parse *cfile,
2053 parse_error(cfile,
"'match if' with a constant boolean "
2057 mapSet(
class, reduced,
"test");
2065relocate_pools(
struct element *share)
2070 struct range *range;
2073 srcs =
mapGet(share,
"pools");
2079 if (range->share != share)
2081 subnet = find_location(share, range);
2084 for (i = 0; i <
listSize(srcs); i++) {
2088 if (range->pool !=
pool)
2114 int declaration = 0;
2126 parse_error(cfile,
"zero-length shared network name");
2132 "expecting a name for shared-network");
2157 "A shared network can't be "
2158 "connected to two interfaces.");
2160 mapSet(share, interface,
"interface");
2161 new_network_interface(cfile, interface);
2180 if (shares == NULL) {
2186 shares,
"shared-networks");
2188 "are different, cf Kea #236");
2194 relocate_pools(share);
2200 if (
pools != NULL) {
2216 if (
pools != NULL) {
2261 opt_list =
mapGet(share,
"option-data");
2287common_subnet_parsing(
struct parse *cfile,
2294 int declaration = 0;
2314 "A subnet can't be connected "
2315 "to two interfaces.");
2318 new_network_interface(cfile, interface);
2347 unsigned char addr[4];
2348 unsigned len =
sizeof(addr);
2360 chain = (
struct subnet *)malloc(
sizeof(*chain));
2363 memset(chain, 0,
sizeof(*chain));
2368 for (i = cfile->
stack_top; i > 0; --i) {
2378 parse_error(cfile,
"can't find a place to put subnet");
2384 parse_error(cfile,
"shared network without subnets");
2392 if (address == NULL)
2393 parse_error(cfile,
"can't decode network number");
2394 if (address->
length != 4)
2396 chain->
addr = address;
2410 prefix = addrmask(address,
netmask);
2411 if (prefix == NULL) {
2412 char bufa[INET_ADDRSTRLEN];
2413 char bufm[INET_ADDRSTRLEN];
2415 inet_ntop(AF_INET, address->
content, bufa, INET_ADDRSTRLEN);
2416 inet_ntop(AF_INET,
netmask->content, bufm, INET_ADDRSTRLEN);
2417 parse_error(cfile,
"can't get a prefix from %s mask %s",
2445 parse_error(cfile,
"subnet6 statement is only supported "
2455 chain = (
struct subnet *)malloc(
sizeof(*chain));
2458 memset(chain, 0,
sizeof(*chain));
2463 for (i = cfile->
stack_top; i > 0; --i) {
2473 parse_error(cfile,
"can't find a place to put subnet");
2479 parse_error(cfile,
"shared network without subnets");
2486 if (address == NULL)
2487 parse_error(cfile,
"can't decode network number");
2488 if (address->
length != 16)
2490 chain->
addr = address;
2505 memset(
netmask->content, 0, 16);
2507 for (i = atoi(val); i >= 8; i -= 8)
2509 *p = 0xff << (8 - i);
2525 int declaration = 0;
2526 struct string *name = NULL;
2529 parse_error(cfile,
"another group is already open");
2542 parse_error(cfile,
"no memory for group decl name %s",
2562 "in the config file");
2563 }
else if (token ==
DYNAMIC) {
2566 "in the config file");
2567 }
else if (token ==
STATIC) {
2570 "in the config file");
2596 struct handle *hosts = NULL;
2597 struct handle *shares = NULL;
2599 struct handle *classes = NULL;
2600 struct handle *pdpools = NULL;
2602 struct handles downs;
2604 const char *key = NULL;
2605 const char *name = NULL;
2614 parse_error(cfile,
"unexpected kind for group parent %d",
2616 item =
mapGet(parent,
"group");
2620 parse_error(cfile,
"got a different group from parent");
2636 parse_error(cfile,
"impossible group item (kind %d) "
2637 "for %s at order %u",
2641 if (strcmp(
handle->
key,
"reservations") != 0)
2648 hosts->
order, order);
2658 if (strcmp(
handle->
key,
"shared-networks") != 0)
2667 "not allowed here.");
2690 if (strcmp(
handle->
key,
"client-classes") != 0)
2694 if (classes != NULL)
2696 key, classes->
order, order);
2705 if (strcmp(
handle->
key,
"pd-pools") == 0) {
2706 if (pdpools != NULL)
2708 "twice at %u and %u",
2709 pdpools->
order, order);
2711 }
else if (strcmp(
handle->
key,
"pools") == 0) {
2715 pools->order, order);
2745 if ((strcmp(
handle->
key,
"reservations") == 0) ||
2747 (strcmp(
handle->
key,
"shared-networks") == 0) ||
2748 (strcmp(
handle->
key,
"subnet4") == 0) ||
2749 (strcmp(
handle->
key,
"subnet6") == 0) ||
2751 (strcmp(
handle->
key,
"client-classes") == 0) ||
2752 (strcmp(
handle->
key,
"hw-address") == 0) ||
2753 (strcmp(
handle->
key,
"ip-address") == 0) ||
2754 (strcmp(
handle->
key,
"extra-ip-addresses") == 0) ||
2755 (strcmp(
handle->
key,
"ip-addresses") == 0) ||
2756 (strcmp(
handle->
key,
"prefixes") == 0) ||
2759 (strcmp(
handle->
key,
"delegated-len") == 0) ||
2760 (strcmp(
handle->
key,
"prefix-len") == 0) ||
2761 (strcmp(
handle->
key,
"prefix-highest") == 0) ||
2762 (strcmp(
handle->
key,
"option-def") == 0) ||
2763 (strcmp(
handle->
key,
"hostname") == 0) ||
2764 (strcmp(
handle->
key,
"client-id") == 0) ||
2765 (strcmp(
handle->
key,
"host-identifier") == 0) ||
2766 (strcmp(
handle->
key,
"flex-id") == 0) ||
2768 (strcmp(
handle->
key,
"authoritative") == 0) ||
2769 (strcmp(
handle->
key,
"dhcp-ddns") == 0) ||
2770 (strcmp(
handle->
key,
"host-reservation-identifiers") == 0))
2776 if ((strcmp(
handle->
key,
"option-space") == 0) ||
2777 (strcmp(
handle->
key,
"server-duid") == 0) ||
2778 (strcmp(
handle->
key,
"statement") == 0) ||
2780 (strcmp(
handle->
key,
"ddns-update-style") == 0) ||
2781 (strcmp(
handle->
key,
"echo-client-id") == 0)) {
2786 msg =
makeString(-1,
"/// moved from group");
2798 if ((strcmp(
handle->
key,
"option-data") == 0) ||
2801 (strcmp(
handle->
key,
"interface") == 0) ||
2802 (strcmp(
handle->
key,
"valid-lifetime") == 0) ||
2803 (strcmp(
handle->
key,
"preferred-lifetime") == 0) ||
2804 (strcmp(
handle->
key,
"renew-timer") == 0) ||
2805 (strcmp(
handle->
key,
"rebind-timer") == 0) ||
2806 (strcmp(
handle->
key,
"boot-file-name") == 0) ||
2807 (strcmp(
handle->
key,
"server-hostname") == 0) ||
2808 (strcmp(
handle->
key,
"next-server") == 0) ||
2809 (strcmp(
handle->
key,
"match-client-id") == 0)) {
2818 msg =
makeString(-1,
"/// moved from group");
2833 if (strcmp(
handle->
key,
"option-data") == 0) {
2834 option_data_derive(cfile,
handle, hosts);
2835 option_data_derive(cfile,
handle, shares);
2837 derive_classes(cfile,
handle, classes);
2838 option_data_derive(cfile,
handle, pdpools);
2840 }
else if ((strcmp(
handle->
key,
"allow") == 0) ||
2844 }
else if ((strcmp(
handle->
key,
"interface") == 0) ||
2845 (strcmp(
handle->
key,
"valid-lifetime") == 0) ||
2846 (strcmp(
handle->
key,
"preferred-lifetime") == 0) ||
2847 (strcmp(
handle->
key,
"renew-timer") == 0) ||
2848 (strcmp(
handle->
key,
"rebind-timer") == 0) ||
2849 (strcmp(
handle->
key,
"match-client-id") == 0)) {
2852 }
else if ((strcmp(
handle->
key,
"boot-file-name") == 0) ||
2853 (strcmp(
handle->
key,
"server-hostname") == 0)) {
2855 derive_classes(cfile,
handle, classes);
2856 }
else if (strcmp(
handle->
key,
"next-server") == 0) {
2859 derive_classes(cfile,
handle, classes);
2861 parse_error(cfile,
"unexpected parameter %s to derive",
2864 if (hosts != NULL) {
2873 if (shares != NULL) {
2876 upper =
mapGet(parent,
"shared-networks");
2892 if (classes != NULL) {
2897 for (where = cfile->
stack_top; where > 0; --where) {
2903 upper =
mapGet(cfile->
stack[where],
"client-classes");
2909 concat_classes(cfile, upper, classes->
value);
2912 if (pdpools != NULL) {
2915 upper =
mapGet(parent,
"pd-pools");
2921 if (
pools != NULL) {
2924 upper =
mapGet(parent,
"pools");
2948 assert(list != NULL);
2950 for (i = 0; i <
listSize(list); i++) {
2952 assert(item != NULL);
2955 if (opt_list != NULL) {
2978 assert(list != NULL);
2980 for (i = 0; i <
listSize(list); i++) {
2982 assert(item != NULL);
2984 item = get_class(cfile, item);
2987 if (strcmp(src->
key,
"option-data") == 0) {
2990 opt_list =
mapGet(item,
"option-data");
2991 if (opt_list != NULL)
3026 if (address == NULL)
3035 }
while (token ==
COMMA);
3055parse_binding_value(
struct parse *cfile)
3072 }
else if (token ==
PERCENT) {
3078 }
else if (token ==
NAME) {
3080 if (!strcasecmp(val,
"true"))
3082 else if (!strcasecmp(val,
"false"))
3087 parse_error(cfile,
"expecting a constant value.");
3099 struct string *low, *high, *range;
3100 unsigned char addr[4];
3101 unsigned len =
sizeof(addr);
3106 struct range *chain;
3156 struct string *dyn_bootp;
3158 dyn_bootp =
makeString(-1,
"dynamic bootp clients");
3165 if (
pools == NULL) {
3191 chain = (
struct range *)malloc(
sizeof(*chain));
3194 memset(chain, 0,
sizeof(*chain));
3196 for (i = where; i > 0; --i) {
3199 chain->share = cfile->
stack[i];
3214 struct string *low, *high, *range;
3220 struct range *chain;
3225 parse_error(cfile,
"range6 statement is only supported "
3233 parse_error(cfile,
"can't parse range6 address (low)");
3241 if (token ==
SLASH) {
3280 "can't parse range6 address (high)");
3297 if (
pools == NULL) {
3314 chain = (
struct range *)malloc(
sizeof(*chain));
3317 memset(chain, 0,
sizeof(*chain));
3319 for (i = where; i > 0; --i) {
3322 chain->share = cfile->
stack[i];
3344 parse_error(cfile,
"prefix6 statement is only supported "
3352 parse_error(cfile,
"can't parse prefix6 address (low)");
3356 parse_error(cfile,
"can't parse prefix6 address (high)");
3368 if ((bits <= 0) || (bits >= 128))
3369 parse_error(cfile,
"networks have 0 to 128 bits (exclusive)");
3382 if (
pools == NULL) {
3419 parse_error(cfile,
"fixed-prefix6 statement is only "
3420 "supported in DHCPv6 mode.");
3426 prefixes =
mapGet(host,
"prefixes");
3427 if (prefixes == NULL) {
3429 mapSet(host, prefixes,
"prefixes");
3434 parse_error(cfile,
"can't parse fixed-prefix6 address");
3483 int declaration = 0;
3484 unsigned range_counter = 0;
3485 unsigned prefix_counter = 0;
3488 parse_error(cfile,
"pool6 statement is only supported "
3496 parse_error(cfile,
"pool6s are only valid inside "
3497 "subnet statements.");
3554 generate_class(cfile,
pool,
permit, prohibit);
3559 if (prefix_counter == 0) {
3562 if (
pools == NULL) {
3569 if (range_counter == 0) {
3582 if (pdpools == NULL) {
3586 pdpools,
"pd-pools");
3607 while (--prefix_counter != 0) {
3614 saved =
copy(pdpool);
3621 if (strcmp(
handle->
key,
"***mark***") == 0) {
3628 if ((strcmp(
handle->
key,
"prefix") != 0) &&
3629 (strcmp(
handle->
key,
"prefix-len") != 0) &&
3631 "delegated-len") != 0) &&
3633 "excluded-prefix") != 0) &&
3635 "excluded-prefix-len") != 0))
3656 if (range_counter != 0) {
3659 if (
pools == NULL) {
3666 while (--range_counter != 0) {
3730 name =
"allow-bootp";
3734 name =
"allow-booting";
3738 name =
"dynamic-bootp";
3742 name =
"boot-unknown-clients";
3746 name =
"duplicates";
3754 name =
"client-updates";
3758 name =
"leasequery";
3818 mapSet(duid, item,
"type");
3827 mapSet(duid, item,
"enterprise-id");
3833 if (is_hexa_only(val, len))
3837 mapSet(duid, item,
"identifier");
3847 else if (token ==
LL) {
3849 mapSet(duid, item,
"type");
3870 mapSet(duid, item,
"htype");
3873 if (ll_addr == NULL)
3875 "can't get hardware address");
3877 mapSet(duid, item,
"identifier");
3888 else if (token ==
LLT) {
3890 mapSet(duid, item,
"type");
3911 mapSet(duid, item,
"htype");
3917 mapSet(duid, item,
"time");
3920 if (ll_addr == NULL)
3922 "can't get hardware address");
3924 mapSet(duid, item,
"identifier");
3937 else if (token ==
NUMBER) {
3943 mapSet(duid, item,
"type");
3949 mapSet(duid, item,
"identifier");
3956 parse_error(cfile,
"DUID type of LLT, EN, or LL expected");
3967 parse_error(cfile,
"there is already a server-id");
3978is_hexa_only(
const char *s,
unsigned l)
3982 for (i = 0; i < l; i++)
3983 if (!isxdigit((
int)s[i]))
4014 if (token ==
SPACE) {
4022 if (token ==
CHECK) {
4030 printf(
"option ISC DHCP (Kea)\n"
4032 " format \"%s\" (type \"%s\" "
4033 "array %s encap %s)\n"
4038 is_array ?
"true" :
"false",
4039 encapsulate ?
"true" :
"false",
4045 parse_error(cfile,
"attempt to modify config %s.%s",
4047 if (token ==
ALIAS) {
4051 "expecting identifier after "
4055 "attempt to rename %s.%s to %s",
4062 if (token ==
CODE) {
4071 if (token ==
LOCAL) {
4081 parse_error(cfile,
"unknown option directive %s", val);
4106 if (token ==
CHECK) {
4107 printf(
"space ISC DHCP (kea)\n"
4108 " %s (%s)\n status %s\n%s",
4115 if (token ==
ALIAS) {
4119 "expecting identifier after "
4123 "attempt to rename %s to %s",
4140 parse_error(cfile,
"expected KNOW or UNKNOWN or DYNAMIC");
4176 parse_error(cfile,
"expecting option code number.");
4182 struct option *from_code;
4186 if (from_code != NULL)
4193 parse_error(cfile,
"attempt to redefine %s.%s code %u",
4207 if ((datatype == NULL) && (strchr(datatype->
content,
'?') != NULL))
4208 parse_error(cfile,
"failed to convert format \"%s\" for "
4209 "option %s.%s code %u",
4213 parse_error(cfile,
"option %s.%s code %u encapsulate?",
4216 if (strchr(datatype->
content,
',') == NULL)
4226 if (optdef == NULL) {
4241 else if (token ==
KNOWN) {
4250 parse_error(cfile,
"expected KNOW or UNKNOWN or DYNAMIC");
4256 "%s.%s code %u is known by nobody",
4277 parse_error(cfile,
"unknown code for option %s.%s",
4281 if (optdef == NULL) {
4286 for (i = 0; i <
listSize(optdef); i++) {
4288 elem =
mapGet(def,
"space");
4291 "without space at %u", (
unsigned)i);
4295 elem =
mapGet(def,
"code");
4298 "without code at %u", (
unsigned)i);
4309 parse_error(cfile,
"can't find option %s.%s code %u in definitions",
4328 parse_error(cfile,
"unknown code for option %s.%s",
4332 if (optdef == NULL) {
4337 for (i = 0; i <
listSize(optdef); i++) {
4339 elem =
mapGet(def,
"space");
4342 "without space at %u", (
unsigned)i);
4346 elem =
mapGet(def,
"code");
4349 "without code at %u", (
unsigned)i);
4352 "option %s.%s code %u",
4366 if ((datatype == NULL) && (strchr(datatype->
content,
'?') != NULL))
4367 parse_error(cfile,
"failed to convert format \"%s\" for "
4368 "option %s.%s code %u",
4373 parse_error(cfile,
"option %s.%s code %u encapsulate?",
4376 if (strchr(datatype->
content,
',') == NULL)
4395new_network_interface(
struct parse *cfile,
struct element *iface)
4402 ifconf =
mapGet(cfile->
stack[1],
"interfaces-config");
4403 if (ifconf == NULL) {
4405 mapSet(cfile->
stack[1], ifconf,
"interfaces-config");
4408 iflist =
mapGet(ifconf,
"interfaces");
4409 if (iflist == NULL) {
4411 mapSet(ifconf, iflist,
"interfaces");
4414 for (i = 0; i <
listSize(iflist); i++) {
4418 if ((item != NULL) &&
4429static const uint32_t bitmasks[32 + 1] = {
4430 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
4431 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
4432 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
4433 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
4434 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
4435 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
4436 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
4437 0x0000000f, 0x00000007, 0x00000003, 0x00000001,
4441addrmask(
const struct string *address,
const struct string *netmask)
4449 memcpy(&mask, netmask->
content, 4);
4451 for (plen = 0; plen <= 32; ++plen)
4452 if (~mask == bitmasks[plen])
4488 "reservation-mode");
4493 return cfile->
stack[1];
4507 address =
mapGet(host,
"ip-address");
4508 if (address == NULL) {
4510 return cfile->
stack[1];
4511 if (used_heuristicp)
4517 address =
mapGet(host,
"ip-addresses");
4518 if (address == NULL) {
4520 return cfile->
stack[1];
4521 if (used_heuristicp)
4525 address =
listGet(address, 0);
4526 if (address == NULL)
4539 for (i = 0; i < len; i++)
4548 return cfile->
stack[1];
4557find_location(
struct element *share,
struct range *range)
4569 for (i = 0; i < range->low->length; i++)
4570 if ((range->low->content[i] &
4586static const uint8_t bytemasks[8] = {
4587 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
4591get_prefix_length(
const char *low,
const char *high)
4598 if ((inet_pton(AF_INET6, low, lo) != 1) ||
4599 (inet_pton(AF_INET6, high, hi) != 1))
4602 for (i = 0; i < 16; i++)
4603 xor[i] = lo[i] ^ hi[i];
4604 for (plen = 0; plen < 128; plen += 8)
4605 if (xor[plen / 8] != 0)
4609 for (i = (plen / 8) + 1; i < 16; i++)
4612 for (i = 0; i < 8; i++) {
4613 uint8_t msk = ~xor[plen / 8];
4615 if (msk == bytemasks[i])
4616 return plen + i + 1;
4636 classes =
mapGet(cfile->
stack[1],
"client-classes");
4637 if ((classes == NULL) || (
listSize(classes) == 0))
4640 name =
mapGet(ref,
"super");
4642 name =
mapGet(ref,
"name");
4645 for (i = 0; i <
listSize(classes); i++) {
4649 param =
mapGet(
class,
"name");
4657 selector =
mapGet(ref,
"string");
4658 if (selector == NULL) {
4659 selector =
mapGet(ref,
"binary");
4660 if (selector == NULL)
4662 for (i = 0; i <
listSize(classes); i++) {
4664 param =
mapGet(
class,
"super");
4669 param =
mapGet(
class,
"binary");
4678 for (i = 0; i <
listSize(classes); i++) {
4680 param =
mapGet(
class,
"super");
4685 param =
mapGet(
class,
"string");
4711 class = get_class(cfile, sitem);
4716 for (i = 0; i <
listSize(dst); i++) {
4718 if (
class == get_class(cfile, ditem)) {
4740 struct element *result = NULL;
4744 struct comments comments;
4752 classes =
mapGet(cfile->
stack[1],
"generated-classes");
4753 if (classes == NULL) {
4755 mapSet(cfile->
stack[1], classes,
"generated-classes");
4762 for (i = 0; i <
listSize(allow); i++) {
4766 assert(elem != NULL);
4767 prop =
mapGet(elem,
"class");
4768 assert(prop != NULL);
4770 alias =
mapGet(elem,
"real");
4776 for (i = 0; i <
listSize(deny); i++) {
4780 assert(elem != NULL);
4781 prop =
mapGet(elem,
"class");
4782 assert(prop != NULL);
4784 alias =
mapGet(elem,
"real");
4796 for (i = 0; i <
listSize(allow); i++) {
4798 assert(elem != NULL);
4799 prop =
mapGet(elem,
"way");
4800 assert(prop != NULL);
4802 class =
mapGet(elem,
"class");
4803 assert(
class != NULL);
4826 for (i = 0; i <
listSize(deny); i++) {
4828 assert(elem != NULL);
4829 prop =
mapGet(elem,
"way");
4830 assert(prop != NULL);
4832 class =
mapGet(elem,
"class");
4833 assert(
class != NULL);
4871 assert(elem != NULL);
4872 prop =
mapGet(elem,
"way");
4873 assert(prop != NULL);
4875 class =
mapGet(elem,
"class");
4876 assert(
class != NULL);
4888 for (i = 0; i <
listSize(allow); i++) {
4890 assert(elem != NULL);
4891 prop =
mapGet(elem,
"way");
4892 assert(prop != NULL);
4896 prop =
mapGet(elem,
"class");
4897 assert(prop != NULL);
4904 for (i = 0; i <
listSize(deny); i++) {
4906 assert(elem != NULL);
4907 prop =
mapGet(elem,
"way");
4908 assert(prop != NULL);
4912 prop =
mapGet(elem,
"class");
4913 assert(prop != NULL);
4921 for (i = 0; i <
listSize(classes); i++) {
4925 assert(
class != NULL);
4926 descr =
mapGet(
class,
"name");
4927 assert(descr != NULL);
4945 for (i = 0; i <
listSize(allow); i++) {
4951 prop =
mapGet(elem,
"way");
4953 prop =
mapGet(elem,
"class");
4965 for (i = 0; i <
listSize(deny); i++) {
4971 prop =
mapGet(elem,
"way");
4973 prop =
mapGet(elem,
"class");
4984 mapSet(
class, depend,
"depend");
4986 class->skip |= allow->
skip || deny->
skip;
enum dhcp_token next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile)
enum dhcp_token peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile)
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
enum dhcp_token next_token(const char **rval, unsigned *rlen, struct parse *cfile)
isc_result_t end_parse(struct parse **cfile)
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
unsigned char * parse_numeric_aggregate(struct parse *cfile, unsigned char *buf, unsigned *max, int separator, int base, unsigned size)
int parse_boolean_expression(struct expression **expr, struct parse *cfile, int *lose)
void skip_to_semi(struct parse *cfile)
int parse_option_statement(struct executable_statement **result, struct parse *cfile, int lookups, struct option *option, enum statement_op op)
int parse_semi(struct parse *cfile)
int parse_option_code_definition(struct parse *cfile, struct option *option)
int parse_ip6_addr(struct parse *cfile, struct iaddr *addr)
int parse_data_expression(struct expression **expr, struct parse *cfile, int *lose)
char * parse_host_name(struct parse *cfile)
int parse_ip_addr_or_hostname(struct expression **expr, struct parse *cfile, int uniform)
void parse_hardware_param(struct parse *cfile, struct hardware *hardware)
void parse_option_space_decl(struct parse *cfile)
int parse_executable_statement(struct executable_statement **result, struct parse *cfile, int *lose, enum expression_context case_context)
isc_result_t parse_option_name(struct parse *cfile, int allocate, int *known, struct option **opt)
void parse_option_status_dir(struct parse *cfile, struct option *option, enum dhcp_token token)
void parse_address_range(struct parse *cfile, int type, size_t where)
void parse_pool6_statement(struct parse *cfile, int type)
Parse a pool6 statement.
void parse_server_duid_conf(struct parse *cfile)
void parse_prefix6(struct parse *cfile, int type, size_t where)
void get_permit(struct parse *cfile, struct element *permit_head)
Parse allow and deny statements.
void parse_class_declaration(struct parse *cfile, int type)
void parse_address_range6(struct parse *cfile, int type, size_t where)
void parse_subnet_declaration(struct parse *cfile)
isc_boolean_t failover_once
void close_group(struct parse *cfile, struct element *group)
void parse_option_code_dir(struct parse *cfile, struct option *option)
isc_boolean_t use_flex_id
void read_conf_file(struct parse *parent, const char *filename, int group_type)
void parse_option_space_dir(struct parse *cfile)
isc_boolean_t parse_statement(struct parse *cfile, int type, isc_boolean_t declaration)
void parse_option_local_dir(struct parse *cfile, struct option *option)
void parse_subnet6_declaration(struct parse *cfile)
void parse_host_declaration(struct parse *cfile)
void parse_lbrace(struct parse *cfile)
struct element * parse_fixed_addr_param(struct parse *cfile, enum dhcp_token type)
void parse_pool_statement(struct parse *cfile, int type)
Parse a pool statement.
unsigned subclass_counter
struct element * parse_allow_deny(struct parse *cfile, int flag)
void parse_option_define_dir(struct parse *cfile, struct option *option)
const struct option * host_id_option
isc_boolean_t use_hw_address
isc_boolean_t use_client_id
void parse_fixed_prefix6(struct parse *cfile, size_t host_decl)
void parse_shared_net_declaration(struct parse *cfile)
void parse_directive(struct parse *cfile)
Parse (and execute) a directive (extension)
void parse_group_declaration(struct parse *cfile)
size_t conf_file_subparse(struct parse *cfile, int type)
void concatString(struct string *s, const struct string *a)
void listPush(struct element *l, struct element *e)
struct comment * createComment(const char *line)
isc_boolean_t eqString(const struct string *s, const struct string *o)
struct string * makeString(int l, const char *s)
isc_boolean_t boolValue(const struct element *e)
struct element * copy(struct element *e)
struct element * createHexa(struct string *h)
void listRemove(struct element *l, int i)
struct element * createList(void)
struct element * createBool(isc_boolean_t b)
struct string * allocString(void)
struct handle * mapPop(struct element *m)
size_t mapSize(const struct element *m)
void appendString(struct string *s, const char *a)
struct element * listGet(struct element *l, int i)
struct string * stringValue(struct element *e)
struct element * createNull(void)
void resetList(struct element *e)
void concat(struct element *l, struct element *o)
isc_boolean_t mapContains(const struct element *m, const char *k)
void derive(struct handle *src, struct handle *dst)
struct element * createInt(int64_t i)
void merge(struct element *m, struct element *o)
void mapSet(struct element *m, struct element *e, const char *k)
size_t listSize(const struct element *l)
struct element * createMap(void)
struct element * createString(const struct string *s)
void mapRemove(struct element *m, const char *k)
struct element * mapGet(struct element *m, const char *k)
int64_t intValue(const struct element *e)
struct string * makeStringExt(int l, const char *s, char fmt)
#define TAILQ_FOREACH_SAFE(var, head, tvar)
#define TAILQ_INSERT_TAIL(head, elm)
#define TAILQ_FOREACH(var, head)
#define TAILQ_HEAD(name, type)
#define TAILQ_CONCAT(head1, head2)
#define TAILQ_REMOVE(head, elm)
#define TAILQ_EMPTY(head)
#define TAILQ_LAST(head, headname)
#define TAILQ_ENTRY(type)
void dhcp(struct packet *packet)
#define DHO_DHCP_SERVER_IDENTIFIER
#define skip_token(a, b, c)
struct ipv6_pool ** pools
#define CLASS_TYPE_SUBCLASS
struct element * eval_boolean_expression(struct element *expr, isc_boolean_t *modifiedp)
isc_boolean_t use_isc_lifetimes
void parse_error(struct parse *cfile, const char *fmt,...)
void stackPush(struct parse *pc, struct element *elem)
struct option * option_lookup_code(const char *, unsigned)
struct element * reduce_boolean_expression(struct element *)
struct option * option_lookup_name(const char *, const char *)
struct string * parse_option_textbin(struct parse *, struct option *)
size_t conf_file_parse(struct parse *)
const char * print_data_expression(struct element *, isc_boolean_t *)
const char * print_boolean_expression(struct element *, isc_boolean_t *)
struct string * parse_ip6_addr_txt(struct parse *)
@ supersede_option_statement
struct string * parse_hexa(struct parse *)
struct string * convert_format(const char *, isc_boolean_t *, isc_boolean_t *)
struct space * space_lookup(const char *)
const char * display_status(enum option_status)
void merge_option_data(struct element *, struct element *)
enum option_status status
const struct space * space
enum option_status status