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 *);
97static int get_prefix_length(
const char *,
const char *);
150 "declares some subnets but "
151 "has no interfaces-config");
158 post_process_lifetimes(
cfile);
161 post_process_classes(
cfile);
162 post_process_generated_classes(
cfile);
163 post_process_option_definitions(
cfile);
282 classes =
mapGet(
cfile->stack[1],
"client-classes");
290 name =
mapGet(
class,
"name");
293 "without a name", (
unsigned)
i);
303 "a bad string selector",
335 "are not supported by Kea");
385post_process_generated_classes(
struct parse *
cfile)
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");
465post_process_option_definitions(
struct parse *
cfile)
549 return cfile->issue_counter;
617 "host declarations not allowed here.");
626 "group declarations not allowed here.");
646 "subnet declarations not allowed here.");
667 "class declarations not allowed here.");
675 add_host_reservation_identifiers(
cfile,
682 for (
i =
cfile->stack_top;
i > 0; --
i) {
691 "not allowed here.");
705 for (
i =
cfile->stack_top;
i > 0; --
i) {
714 "fixed-address parameter not "
722 "declaration per host.");
728 cfile->issue_counter++;
730 cache,
"extra-ip-addresses");
736 "declaration per host.");
754 for (
i =
cfile->stack_top;
i > 0; --
i) {
763 "range declaration not allowed here.");
772 for (
i =
cfile->stack_top;
i > 0; --
i) {
781 "range6 declaration not allowed here.");
790 for (
i =
cfile->stack_top;
i > 0; --
i) {
799 "prefix6 declaration not allowed here.");
808 for (
i =
cfile->stack_top;
i > 0; --
i) {
817 "fixed-prefix6 declaration not "
830 "pool6 declared outside of network");
854 for (
i =
cfile->stack_top;
i > 0; --
i) {
888 if (token ==
SPACE) {
891 "option space definitions %s",
892 "may not be scoped.");
903 "option definitions%s",
904 " may not be scoped.");
959 "expecting a declaration");
962 "expecting a parameter %s",
971 cfile->issue_counter++;
1043 alias =
makeString(-1,
"authenticated clients");
1047 "not supported by ISC DHCP and Kea");
1052 alias =
makeString(-1,
"unauthenticated clients");
1068 alias =
makeString(-1,
"dynamic bootp clients");
1069 cfile->issue_counter++;
1071 "supported by Kea");
1095 cfile->issue_counter++;
1097 "supported by Kea");
1160 "subnet or shared-network statements.");
1233 cfile->issue_counter++;
1320 "in the config file");
1327 "in the config file");
1330 if (token ==
GROUP) {
1338 "expecting string or identifier.");
1341 cfile->issue_counter++;
1343 "host reservations");
1356 add_host_reservation_identifiers(
cfile,
1365 "client identifier.",
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"
1452 cfile->issue_counter++;
1453 mapSet(host, expr,
"host-identifier");
1496 "without fixed addresses "
1497 "were put in the last "
1509add_host_reservation_identifiers(
struct parse *
cfile,
const char *
id)
1544 "is a premium feature");
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;
1609 classes =
mapGet(
cfile->stack[1],
"client-classes");
1610 if (classes ==
NULL) {
1613 mapSet(
cfile->stack[1], classes,
"client-classes");
1664 "not a suitable superclass", val);
1743 cfile->issue_counter++;
1749 mapSet(
class, data,
"binary");
1751 mapSet(
class, data,
"string");
1767 if (token ==
SEMI) {
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.");
1831 cfile->issue_counter++;
1832 mapSet(
class, expr,
"spawning");
1836 "expecting with after spawn");
1840 "can't override existing "
1847 "expecting data expr.");
1850 cfile->issue_counter++;
1851 mapSet(
class, expr,
"submatch");
1854 }
else if (token ==
LEASE) {
1866 cfile->issue_counter++;
1868 "supported by Kea");
1913 expr =
mapGet(superclass,
"name");
1918 submatch =
mapGet(superclass,
"submatch");
1919 if (submatch ==
NULL)
1923 while (
mapSize(superclass) > 0) {
1973 cfile->issue_counter++;
1979 expr =
mapGet(
class,
"binary");
1984 data =
mapGet(
class,
"string");
1992 mapSet(expr, match,
"equal");
1997 mapSet(match, expr,
"right");
1999 mapSet(expr, match,
"and");
2018 "constant boolean expression: %s = %s",
2059 cfile->issue_counter++;
2065relocate_pools(
struct element *share)
2079 if (
range->share != share)
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);
2186 shares,
"shared-networks");
2188 "are different, cf Kea #236");
2194 relocate_pools(share);
2204 cfile->issue_counter++;
2220 cfile->issue_counter++;
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);
2368 for (
i =
cfile->stack_top;
i > 0; --
i) {
2369 kind =
cfile->stack[
i]->kind;
2392 if (address ==
NULL)
2394 if (address->
length != 4)
2396 chain->addr = address;
2410 prefix = addrmask(address,
netmask);
2411 if (prefix ==
NULL) {
2463 for (
i =
cfile->stack_top;
i > 0; --
i) {
2464 kind =
cfile->stack[
i]->kind;
2486 if (address ==
NULL)
2488 if (address->
length != 16)
2490 chain->addr = address;
2507 for (
i =
atoi(val);
i >= 8;
i -= 8)
2509 *
p = 0xff << (8 -
i);
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");
2604 const char *key =
NULL;
2605 const char *name =
NULL;
2637 "for %s at order %u",
2648 hosts->order, order);
2667 "not allowed here.");
2694 if (classes !=
NULL)
2696 key, classes->
order, order);
2708 "twice at %u and %u",
2715 pools->order, order);
2828 cfile->issue_counter++;
2892 if (classes !=
NULL) {
2987 if (
strcmp(
src->key,
"option-data") == 0) {
3026 if (address ==
NULL)
3035 }
while (token ==
COMMA);
3072 }
else if (token ==
PERCENT) {
3078 }
else if (token ==
NAME) {
3100 unsigned char addr[4];
3101 unsigned len =
sizeof(addr);
3197 kind =
cfile->stack[
i]->kind;
3241 if (token ==
SLASH) {
3280 "can't parse range6 address (high)");
3310 cfile->issue_counter++;
3320 kind =
cfile->stack[
i]->kind;
3368 if ((bits <= 0) || (bits >= 128))
3395 plen = get_prefix_length(
lo->content,
hi->content);
3400 cfile->issue_counter++;
3420 "supported in DHCPv6 mode.");
3497 "subnet statements.");
3575 cfile->issue_counter++;
3631 "delegated-len") != 0) &&
3633 "excluded-prefix") != 0) &&
3635 "excluded-prefix-len") != 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";
3774 cfile->issue_counter++;
3833 if (is_hexa_only(val, len))
3847 else if (token ==
LL) {
3875 "can't get hardware address");
3888 else if (token ==
LLT) {
3922 "can't get hardware address");
3937 else if (token ==
NUMBER) {
3942 cfile->issue_counter++;
3971 cfile->issue_counter++;
3978is_hexa_only(
const char *
s,
unsigned l)
3982 for (
i = 0;
i <
l;
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"
4039 encapsulate ?
"true" :
"false",
4047 if (token ==
ALIAS) {
4051 "expecting identifier after "
4055 "attempt to rename %s.%s to %s",
4062 if (token ==
CODE) {
4071 if (token ==
LOCAL) {
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",
4209 "option %s.%s code %u",
4241 else if (token ==
KNOWN) {
4256 "%s.%s code %u is known by nobody",
4291 "without space at %u", (
unsigned)
i);
4298 "without code at %u", (
unsigned)
i);
4342 "without space at %u", (
unsigned)
i);
4349 "without code at %u", (
unsigned)
i);
4352 "option %s.%s code %u",
4368 "option %s.%s code %u",
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)
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];
4517 address =
mapGet(host,
"ip-addresses");
4518 if (address ==
NULL) {
4520 return cfile->stack[1];
4525 address =
listGet(address, 0);
4526 if (address ==
NULL)
4539 for (
i = 0;
i < len;
i++)
4548 return cfile->stack[1];
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)
4602 for (
i = 0;
i < 16;
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++) {
4615 if (
msk == bytemasks[
i])
4616 return plen +
i + 1;
4636 classes =
mapGet(
cfile->stack[1],
"client-classes");
4640 name =
mapGet(ref,
"super");
4642 name =
mapGet(ref,
"name");
4744 struct comments comments;
4752 classes =
mapGet(
cfile->stack[1],
"generated-classes");
4753 if (classes ==
NULL) {
4755 mapSet(
cfile->stack[1], classes,
"generated-classes");
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