ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
options.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019 by Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Internet Systems Consortium, Inc.
17  * 950 Charter Street
18  * Redwood City, CA 94063
19  * <info@isc.org>
20  * https://www.isc.org/
21  *
22  */
23 
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "keama.h"
29 
30 TAILQ_HEAD(spaces, space) spaces;
31 TAILQ_HEAD(options, option) options;
32 
33 /* From common/tables.c */
34 
35 /* Additional format codes:
36 
37  x - ISC DHCP and Kea string
38  Y - force full binary
39  u - undefined (parsed as X)
40 */
41 
43 struct space_def space_defs[] = {
44  { "dhcp", "dhcp4", 2},
45  { "nwip", "nwip", 0},
46  { "agent", "dhcp-agent-options-space", 2},
47  { "vendor-class", "_vivco_", 0},
48  { "vendor", "_vivso_", 3},
49  { "isc", "_isc_", 0},
50  { "", "vendor-encapsulated-options-space", 1},
51  { "_docsis3_", "vendor-4491", 1},
52  { "dhcp6", "dhcp6", 2},
53  { "vsio", "_vendor-opts-space_", 3},
54  { "_vsio_", "vendor-opts-space", 1},
55  { "isc6", "_isc6_", 0},
56  { "_rsoo_", "rsoo-opts", 1},
57  { "_isc6_", "vendor-2495", 1},
58  { "server", "_server_", 0},
59  { NULL, NULL, 0}
60 };
61 
63 struct option_def options4[] = {
64  { "subnet-mask", "I", "dhcp", 1, 2},
65  { "time-offset", "l", "dhcp", 2, 2},
66  { "routers", "Ia", "dhcp", 3, 2},
67  { "time-servers", "Ia", "dhcp", 4, 2},
68  { "ien116-name-servers", "Ia", "dhcp", 5, 2},
70  { "domain-name-servers", "Ia", "dhcp", 6, 2},
71  { "log-servers", "Ia", "dhcp", 7, 2},
72  { "cookie-servers", "Ia", "dhcp", 8, 2},
73  { "lpr-servers", "Ia", "dhcp", 9, 2},
74  { "impress-servers", "Ia", "dhcp", 10, 2},
75  { "resource-location-servers", "Ia", "dhcp", 11, 2},
76  { "host-name", "t", "dhcp", 12, 2},
77  { "boot-size", "S", "dhcp", 13, 2},
78  { "merit-dump", "t", "dhcp", 14, 2},
79  { "domain-name", "t", "dhcp", 15, 2},
80  { "swap-server", "I", "dhcp", 16, 2},
81  { "root-path", "t", "dhcp", 17, 2},
82  { "extensions-path", "t", "dhcp", 18, 2},
83  { "ip-forwarding", "f", "dhcp", 19, 2},
84  { "non-local-source-routing", "f", "dhcp", 20, 2},
85  { "policy-filter", "IIa", "dhcp", 21, 2},
86  { "max-dgram-reassembly", "S", "dhcp", 22, 2},
87  { "default-ip-ttl", "B", "dhcp", 23, 2},
88  { "path-mtu-aging-timeout", "L", "dhcp", 24, 2},
89  { "path-mtu-plateau-table", "Sa", "dhcp", 25, 2},
90  { "interface-mtu", "S", "dhcp", 26, 2},
91  { "all-subnets-local", "f", "dhcp", 27, 2},
92  { "broadcast-address", "I", "dhcp", 28, 2},
93  { "perform-mask-discovery", "f", "dhcp", 29, 2},
94  { "mask-supplier", "f", "dhcp", 30, 2},
95  { "router-discovery", "f", "dhcp", 31, 2},
96  { "router-solicitation-address", "I", "dhcp", 32, 2},
97  { "static-routes", "IIa", "dhcp", 33, 2},
98  { "trailer-encapsulation", "f", "dhcp", 34, 2},
99  { "arp-cache-timeout", "L", "dhcp", 35, 2},
100  { "ieee802-3-encapsulation", "f", "dhcp", 36, 2},
101  { "default-tcp-ttl", "B", "dhcp", 37, 2},
102  { "tcp-keepalive-interval", "L", "dhcp", 38, 2},
103  { "tcp-keepalive-garbage", "f", "dhcp", 39, 2},
104  { "nis-domain", "t", "dhcp", 40, 2},
105  { "nis-servers", "Ia", "dhcp", 41, 2},
106  { "ntp-servers", "Ia", "dhcp", 42, 2},
107  { "vendor-encapsulated-options", "E.", "dhcp", 43, 2},
108  { "netbios-name-servers", "Ia", "dhcp", 44, 2},
109  { "netbios-dd-server", "Ia", "dhcp", 45, 2},
110  { "netbios-node-type", "B", "dhcp", 46, 2},
111  { "netbios-scope", "t", "dhcp", 47, 2},
112  { "font-servers", "Ia", "dhcp", 48, 2},
113  { "x-display-manager", "Ia", "dhcp", 49, 2},
114  { "dhcp-requested-address", "I", "dhcp", 50, 2},
115  { "dhcp-lease-time", "L", "dhcp", 51, 2},
116  { "dhcp-option-overload", "B", "dhcp", 52, 2},
117  { "dhcp-message-type", "B", "dhcp", 53, 2},
118  { "dhcp-server-identifier", "I", "dhcp", 54, 2},
119  { "dhcp-parameter-request-list", "Ba", "dhcp", 55, 2},
120  { "dhcp-message", "t", "dhcp", 56, 2},
121  { "dhcp-max-message-size", "S", "dhcp", 57, 2},
122  { "dhcp-renewal-time", "L", "dhcp", 58, 2},
123  { "dhcp-rebinding-time", "L", "dhcp", 59, 2},
124  { "vendor-class-identifier", "x", "dhcp", 60, 2},
125  { "dhcp-client-identifier", "X", "dhcp", 61, 2},
126  { "nwip-domain", "t", "dhcp", 62, 2},
128  { "nwip-suboptions", "Enwip.", "dhcp", 63, 2},
129  { "nisplus-domain", "t", "dhcp", 64, 2},
131  { "nisplus-servers", "Ia", "dhcp", 65, 2},
132  { "tftp-server-name", "t", "dhcp", 66, 2},
133  { "bootfile-name", "t", "dhcp", 67, 2},
135  { "mobile-ip-home-agent", "Ia", "dhcp", 68, 2},
136  { "smtp-server", "Ia", "dhcp", 69, 2},
137  { "pop-server", "Ia", "dhcp", 70, 2},
138  { "nntp-server", "Ia", "dhcp", 71, 2},
139  { "www-server", "Ia", "dhcp", 72, 2},
140  { "finger-server", "Ia", "dhcp", 73, 2},
141  { "irc-server", "Ia", "dhcp", 74, 2},
142  { "streettalk-server", "Ia", "dhcp", 75, 2},
143  { "streettalk-directory-assistance-server", "Ia",
144  "dhcp", 76, 2},
145  { "user-class", "tY", "dhcp", 77, 2},
146  { "slp-directory-agent", "fIa", "dhcp", 78, 2},
147  { "slp-service-scope", "fto", "dhcp", 79, 2},
148  /* 80 is the zero-length rapid-commit (RFC 4039) */
149  { "fqdn", "Efqdn.", "dhcp", 81, 2},
150  { "relay-agent-information", "Eagent.", "dhcp", 82, 2},
152  /* 83 is iSNS (RFC 4174) */
153  /* 84 is unassigned */
154  { "nds-servers", "Ia", "dhcp", 85, 2},
155  { "nds-tree-name", "t", "dhcp", 86, 2},
156  { "nds-context", "t", "dhcp", 87, 2},
157  { "bcms-controller-names", "D", "dhcp", 88, 2},
158  { "bcms-controller-address", "Ia", "dhcp", 89, 2},
159  { "authenticate", "X", "dhcp", 90, 1},
161  { "client-last-transaction-time", "L", "dhcp", 91, 2},
162  { "associated-ip", "Ia", "dhcp", 92, 2},
163  { "pxe-system-type", "Sa", "dhcp", 93, 2},
164  // pxe-system-type client-system
165  { "pxe-interface-id", "BBB", "dhcp", 94, 2},
166  // pxe-interface-id client-ndi
167  { "pxe-client-id", "BX", "dhcp", 97, 2},
168  // pxe-client-id uuid-guid
169  { "uap-servers", "t", "dhcp", 98, 2},
170  { "geoconf-civic", "X", "dhcp", 99, 2},
171  { "pcode", "t", "dhcp", 100, 2},
172  { "tcode", "t", "dhcp", 101, 2},
173  { "netinfo-server-address", "Ia", "dhcp", 112, 2},
174  { "netinfo-server-tag", "t", "dhcp", 113, 2},
175  { "default-url", "t", "dhcp", 114, 2},
176  { "auto-config", "B", "dhcp", 116, 2},
177  { "name-service-search", "Sa", "dhcp", 117, 2},
178  { "subnet-selection", "I", "dhcp", 118, 2},
179  { "domain-search", "Dc", "dhcp", 119, 2},
180  { "vivco", "Evendor-class.", "dhcp", 124, 2},
182  { "vivso", "Evendor.", "dhcp", 125, 2},
184  {"pana-agent", "Ia", "dhcp", 136, 2},
185  {"v4-lost", "d", "dhcp", 137, 2},
186  {"capwap-ac-v4", "Ia", "dhcp", 138, 2},
187  { "sip-ua-cs-domains", "Dc", "dhcp", 141, 2},
188  { "ipv4-address-andsf", "Ia", "dhcp", 142, 0},
190  { "rdnss-selection", "BIID", "dhcp", 146, 2},
191  { "tftp-server-address", "Ia", "dhcp", 150, 0},
193  { "v4-portparams", "BBS", "dhcp", 159, 2},
194  { "v4-captive-portal", "t", "dhcp", 160, 2},
195  { "option-6rd", "BB6Ia", "dhcp", 212, 2},
196  {"v4-access-domain", "d", "dhcp", 213, 2},
197  { NULL, NULL, NULL, 0, 0 }
198 };
199 
201 struct option_def options6[] = {
202  { "client-id", "X", "dhcp6", 1, 2},
204  { "server-id", "X", "dhcp6", 2, 2},
206  { "ia-na", "X", "dhcp6", 3, 2},
207  { "ia-ta", "X", "dhcp6", 4, 2},
208  { "ia-addr", "X", "dhcp6", 5, 2},
210  { "oro", "Sa", "dhcp6", 6, 2},
211  { "preference", "B", "dhcp6", 7, 2},
212  { "elapsed-time", "S", "dhcp6", 8, 2},
213  { "relay-msg", "X", "dhcp6", 9, 2},
215  { "auth", "X", "dhcp6", 11, 1},
217  { "unicast", "6", "dhcp6", 12, 2},
218  { "status-code", "Nstatus-codes.to", "dhcp6", 13, 2},
219  { "rapid-commit", "Z", "dhcp6", 14, 2},
220  { "user-class", "X", "dhcp6", 15, 1},
222  { "vendor-class", "LX", "dhcp6", 16, 1},
224  { "vendor-opts", "Evsio.", "dhcp6", 17, 2},
225  { "interface-id", "X", "dhcp6", 18, 2},
226  { "reconf-msg", "Ndhcpv6-messages.", "dhcp6", 19, 2},
227  { "reconf-accept", "Z", "dhcp6", 20, 2},
228  { "sip-servers-names", "D", "dhcp6", 21, 2},
230  { "sip-servers-addresses", "6a", "dhcp6", 22, 2},
232  { "name-servers", "6a", "dhcp6", 23, 2},
234  { "domain-search", "D", "dhcp6", 24, 2},
235  { "ia-pd", "X", "dhcp6", 25, 2},
236  { "ia-prefix", "X", "dhcp6", 26, 2},
238  { "nis-servers", "6a", "dhcp6", 27, 2},
239  { "nisp-servers", "6a", "dhcp6", 28, 2},
240  { "nis-domain-name", "D", "dhcp6", 29, 2},
241  { "nisp-domain-name", "D", "dhcp6", 30, 2},
242  { "sntp-servers", "6a", "dhcp6", 31, 2},
243  { "info-refresh-time", "T", "dhcp6", 32, 2},
245  { "bcms-server-d", "D", "dhcp6", 33, 2},
247  { "bcms-server-a", "6a", "dhcp6", 34, 2},
249  /* Note that 35 is not assigned. */
250  { "geoconf-civic", "X", "dhcp6", 36, 2},
251  { "remote-id", "X", "dhcp6", 37, 2},
252  { "subscriber-id", "X", "dhcp6", 38, 2},
253  { "fqdn", "Efqdn6-if-you-see-me-its-a-bug-bug-bug.",
254  "dhcp6", 39, 2},
256  { "pana-agent", "6a", "dhcp6", 40, 2},
257  { "new-posix-timezone", "t", "dhcp6", 41, 2},
258  { "new-tzdb-timezone", "t", "dhcp6", 42, 2},
259  { "ero", "Sa", "dhcp6", 43, 2},
260  { "lq-query", "X", "dhcp6", 44, 2},
261  { "client-data", "X", "dhcp6", 45, 2},
262  { "clt-time", "L", "dhcp6", 46, 2},
263  { "lq-relay-data", "6X", "dhcp6", 47, 2},
264  { "lq-client-link", "6a", "dhcp6", 48, 2},
265  { "v6-lost", "d", "dhcp6", 51, 2},
266  { "capwap-ac-v6", "6a", "dhcp6", 52, 2},
267  { "relay-id", "X", "dhcp6", 53, 2},
268  { "v6-access-domain", "d", "dhcp6", 57, 2},
269  { "sip-ua-cs-list", "D", "dhcp6", 58, 2},
270  { "bootfile-url", "t", "dhcp6", 59, 2},
271  { "bootfile-param", "X", "dhcp6", 60, 2},
272  { "client-arch-type", "Sa", "dhcp6", 61, 2},
273  { "nii", "BBB", "dhcp6", 62, 2},
274  { "aftr-name", "d", "dhcp6", 64, 2},
275  { "erp-local-domain-name", "d", "dhcp6", 65, 2},
276  { "rsoo", "Ersoo.", "dhcp6", 66, 1},
278  { "pd-exclude", "X", "dhcp6", 67, 1},
280  { "rdnss-selection", "6BD", "dhcp6", 74, 2},
281  { "client-linklayer-addr", "X", "dhcp6", 79, 2},
282  { "link-address", "6", "dhcp6", 80, 2},
283  { "solmax-rt", "L", "dhcp6", 82, 2},
284  { "inf-max-rt", "L", "dhcp6", 83, 2},
285  { "dhcpv4-msg", "X", "dhcp6", 87, 2},
287  { "dhcp4-o-dhcp6-server", "6a", "dhcp6", 88, 2},
289  { "v6-captive-portal", "t", "dhcp6", 103, 2},
290  { "relay-source-port", "S", "dhcp6", 135, 2},
291  { "ipv6-address-andsf", "6a", "dhcp6", 143, 2},
292  { NULL, NULL, NULL, 0, 0 }
293 };
294 
296 struct option_def agents[] = {
298  { "circuit-id", "X", "agent", 1, 0},
299  { "remote-id", "X", "agent", 2, 0},
300  { "agent-id", "I", "agent", 3, 0},
301  { "DOCSIS-device-class", "L", "agent", 4, 0},
302  { "link-selection", "I", "agent", 5, 0},
303  { "relay-port", "Z", "agent", 19, 0},
304  { NULL, NULL, NULL, 0, 0 }
305 };
306 
308 struct option_def configs[] = {
309  { "default-lease-time", "T", "server", 1, 3},
310  { "max-lease-time", "T", "server", 2, 3},
311  { "min-lease-time", "T", "server", 3, 3},
312  { "dynamic-bootp-lease-cutoff", "T", "server", 4, 0},
313  { "dynamic-bootp-lease-length", "L", "server", 5, 0},
314  { "boot-unknown-clients", "f", "server", 6, 0},
315  { "dynamic-bootp", "f", "server", 7, 0},
316  { "allow-bootp", "f", "server", 8, 0},
317  { "allow-booting", "f", "server", 9, 0},
318  { "one-lease-per-client", "f", "server", 10, 0},
319  { "get-lease-hostnames", "f", "server", 11, 0},
320  { "use-host-decl-names", "f", "server", 12, 0},
321  { "use-lease-addr-for-default-route", "f",
322  "server", 13, 0},
323  { "min-secs", "B", "server", 14, 0},
324  { "filename", "t", "server", 15, 3},
325  { "server-name", "t", "server", 16, 3},
326  { "next-server", "I", "server", 17, 3},
327  { "authoritative", "f", "server", 18, 3},
328  { "vendor-option-space", "U", "server", 19, 3},
329  { "always-reply-rfc1048", "f", "server", 20, 0},
330  { "site-option-space", "X", "server", 21, 3},
331  { "always-broadcast", "f", "server", 22, 0},
332  { "ddns-domainname", "t", "server", 23, 3},
333  { "ddns-hostname", "t", "server", 24, 0},
334  { "ddns-rev-domainname", "t", "server", 25, 0},
335  { "lease-file-name", "t", "server", 26, 0},
336  { "pid-file-name", "t", "server", 27, 0},
337  { "duplicates", "f", "server", 28, 0},
338  { "declines", "f", "server", 29, 0},
339  { "ddns-updates", "f", "server", 30, 3},
340  { "omapi-port", "S", "server", 31, 0},
341  { "local-port", "S", "server", 32, 0},
342  { "limited-broadcast-address", "I", "server", 33, 0},
343  { "remote-port", "S", "server", 34, 0},
344  { "local-address", "I", "server", 35, 0},
345  { "omapi-key", "d", "server", 36, 0},
346  { "stash-agent-options", "f", "server", 37, 0},
347  { "ddns-ttl", "T", "server", 38, 0},
348  { "ddns-update-style", "Nddns-styles.", "server", 39, 3},
349  { "client-updates", "f", "server", 40, 0},
350  { "update-optimization", "f", "server", 41, 0},
351  { "ping-check", "f", "server", 42, 0},
352  { "update-static-leases", "f", "server", 43, 0},
353  { "log-facility", "Nsyslog-facilities.",
354  "server", 44, 0},
355  { "do-forward-updates", "f", "server", 45, 0},
356  { "ping-timeout", "T", "server", 46, 0},
357  { "infinite-is-reserved", "f", "server", 47, 0},
358  { "update-conflict-detection", "f", "server", 48, 0},
359  { "leasequery", "f", "server", 49, 0},
360  { "adaptive-lease-time-threshold", "B", "server", 50, 0},
361  { "do-reverse-updates", "f", "server", 51, 0},
362  { "fqdn-reply", "f", "server", 52, 0},
363  { "preferred-lifetime", "T", "server", 53, 3},
364  { "dhcpv6-lease-file-name", "t", "server", 54, 0},
365  { "dhcpv6-pid-file-name", "t", "server", 55, 0},
366  { "limit-addrs-per-ia", "L", "server", 56, 0},
367  { "limit-prefs-per-ia", "L", "server", 57, 0},
368  { "delayed-ack", "S", "server", 58, 0},
369  { "max-ack-delay", "L", "server", 59, 0},
370  /* LDAP */
371  { "dhcp-cache-threshold", "B", "server", 78, 0},
372  { "dont-use-fsync", "f", "server", 79, 0},
373  { "ddns-local-address4", "I", "server", 80, 0},
374  { "ddns-local-address6", "6", "server", 81, 0},
375  { "ignore-client-uids", "f", "server", 82, 3},
376  { "log-threshold-low", "B", "server", 83, 0},
377  { "log-threshold-high", "B", "server", 84, 0},
378  { "echo-client-id", "f", "server", 85, 3},
379  { "server-id-check", "f", "server", 86, 0},
380  { "prefix-length-mode", "Nprefix_length_modes.",
381  "server", 87, 0},
382  { "dhcpv6-set-tee-times", "f", "server", 88, 0},
383  { "abandon-lease-time", "T", "server", 89, 0},
384  { "use-eui-64", "f", "server", 90, 0},
385  { "check-secs-byte-order", "f", "server", 91, 0},
386  { "persist-eui-64-leases", "f", "server", 92, 0},
387  { "ddns-dual-stack-mixed-mode", "f", "server", 93, 0},
388  { "ddns-guard-id-must-match", "f", "server", 94, 0},
389  { "ddns-other-guard-is-dynamic", "f", "server", 95, 0},
390  { "release-on-roam", "f", "server", 96, 0},
391  { "local-address6", "6", "server", 97, 0},
392  { "bind-local-address6", "f", "server", 98, 0},
393  { "ping-cltt-secs", "T", "server", 99, 0},
394  { "ping-timeout-ms", "T", "server", 100, 0},
395  { NULL, NULL, NULL, 0, 0 }
396 };
397 
398 void
400 {
401  struct space_def *def;
402  struct space *space;
403 
404  TAILQ_INIT(&spaces);
405 
406  /* Fill spaces */
407  for (def = space_defs; def->name != NULL; def++) {
408  space = (struct space *)malloc(sizeof(*space));
409  assert(space != NULL);
410  memset(space, 0, sizeof(*space));
411  space->old = def->old;
412  space->name = def->name;
413  space->status = def->status;
414  TAILQ_INSERT_TAIL(&spaces, space);
415  }
416 }
417 
418 void
420 {
421  struct option_def *def;
422  struct option *option;
423 
424  TAILQ_INIT(&options);
425 
426  /* Fill DHCPv4 options */
427  for (def = options4; def->name != NULL; def++) {
428  option = (struct option *)malloc(sizeof(*option));
429  assert(option != NULL);
430  memset(option, 0, sizeof(*option));
431  option->old = def->name;
432  switch (def->code) {
433  case 5:
434  option->name = "name-servers";
435  break;
436  case 62:
437  option->name = "nwip-domain-name";
438  break;
439  case 64:
440  option->name = "nisplus-domain-name";
441  break;
442  case 67:
443  option->name = "boot-file-name";
444  break;
445  case 82:
446  option->name = "dhcp-agent-options";
447  break;
448  case 93:
449  option->name = "client-system";
450  break;
451  case 94:
452  option->name = "client-ndi";
453  break;
454  case 97:
455  option->name = "uuid-guid";
456  break;
457  case 124:
458  option->name = "vivco-suboptions";
459  break;
460  case 125:
461  option->name = "vivso-suboptions";
462  break;
463  default:
464  option->name = def->name;
465  }
466  option->format = def->format;
467  option->space = space_lookup(def->space);
468  assert(option->space != NULL);
469  option->code = def->code;
470  option->status = def->status;
471  TAILQ_INSERT_TAIL(&options, option);
472  }
473 
474  /* Fill DHCPv6 options */
475  for (def = options6; def->name != NULL; def++) {
476  option = (struct option *)malloc(sizeof(*option));
477  assert(option != NULL);
478  memset(option, 0, sizeof(*option));
479  option->old = def->name;
480  switch (def->code) {
481  case 1:
482  option->name = "clientid";
483  break;
484  case 2:
485  option->name = "serverid";
486  break;
487  case 5:
488  option->name = "iaaddr";
489  break;
490  case 21:
491  option->name = "sip-server-dns";
492  break;
493  case 22:
494  option->name = "sip-server-addr";
495  break;
496  case 23:
497  option->name = "dns-servers";
498  break;
499  case 26:
500  option->name = "iaprefix";
501  break;
502  case 32:
503  option->name = "information-refresh-time";
504  break;
505  case 33:
506  option->name = "bcms-server-dns";
507  break;
508  case 34:
509  option->name = "bcms-server-addr ";
510  break;
511  case 39:
512  option->name = "client-fqdn";
513  break;
514  case 87:
515  option->name = "dhcpv4-message";
516  break;
517  case 88:
518  option->name = "dhcp4o6-server-addr";
519  break;
520  default:
521  option->name = def->name;
522  break;
523  }
524  option->format = def->format;
525  option->space = space_lookup(def->space);
526  assert(option->space != NULL);
527  option->code = def->code;
528  option->status = def->status;
529  TAILQ_INSERT_TAIL(&options, option);
530  }
531 
532  /* Fill agent options */
533  for (def = agents; def->name != NULL; def++) {
534  option = (struct option *)malloc(sizeof(*option));
535  assert(option != NULL);
536  memset(option, 0, sizeof(*option));
537  option->old = def->name;
538  option->name = def->name;
539  option->format = def->format;
540  option->space = space_lookup(def->space);
541  assert(option->space != NULL);
542  option->code = def->code;
543  option->status = def->status;
544  TAILQ_INSERT_TAIL(&options, option);
545  }
546 
547  /* Fill server config options */
548  for (def = configs; def->name != NULL; def++) {
549  option = (struct option *)malloc(sizeof(*option));
550  assert(option != NULL);
551  memset(option, 0, sizeof(*option));
552  option->old = def->name;
553  option->name = def->name;
554  option->format = def->format;
555  option->space = space_lookup(def->space);
556  assert(option->space != NULL);
557  option->code = def->code;
558  option->status = def->status;
559  TAILQ_INSERT_TAIL(&options, option);
560  }
561 }
562 
563 struct space *
564 space_lookup(const char *name)
565 {
566  struct space *space;
567 
568  TAILQ_FOREACH(space, &spaces) {
569  if (space->status == isc_dhcp_unknown)
570  continue;
571  if (strcmp(name, space->old) == 0)
572  return space;
573  }
574  return NULL;
575 }
576 
577 struct option *
578 option_lookup_name(const char *space, const char *name)
579 {
580  struct space *universe;
581  struct option *option;
582 
584  if (universe == NULL)
585  return NULL;
586  TAILQ_FOREACH(option, &options) {
588  continue;
589  if (universe != option->space)
590  continue;
591  if (strcmp(name, option->old) == 0)
592  return option;
593  }
594  return NULL;
595 }
596 
597 struct option *
598 kea_lookup_name(const char *space, const char *name)
599 {
600  struct space *universe;
601  struct option *option;
602 
603  TAILQ_FOREACH(universe, &spaces) {
604  if (universe->status == kea_unknown)
605  continue;
606  if (strcmp(name, universe->name) == 0)
607  break;
608  }
609  if (universe == NULL)
610  return NULL;
611  TAILQ_FOREACH(option, &options) {
612  if (option->status == kea_unknown)
613  continue;
614  if (universe != option->space)
615  continue;
616  if (strcmp(name, option->name) == 0)
617  return option;
618  }
619  return NULL;
620 }
621 
622 struct option *
623 option_lookup_code(const char *space, unsigned code)
624 {
625  struct space *universe;
626  struct option *option;
627 
629  if (universe == NULL)
630  return NULL;
631  TAILQ_FOREACH(option, &options) {
632  if (universe != option->space)
633  continue;
634  if (code == option->code)
635  return option;
636  }
637  return NULL;
638 }
639 
640 void
642 {
643  space->status = dynamic;
644  TAILQ_INSERT_TAIL(&spaces, space);
645 }
646 
647 void
649 {
650  assert(option->space != NULL);
651  option->old = option->name;
652  option->status = dynamic;
653  TAILQ_INSERT_TAIL(&options, option);
654 }
655 
656 void
657 add_option_data(struct element *src, struct element *dst)
658 {
659  struct string *sspace;
660  struct element *scode;
661  struct element *name;
662  struct option *option;
663  size_t i;
664 
665  sspace = stringValue(mapGet(src, "space"));
666  scode = mapGet(src, "code");
667  name = mapGet(src, "name");
668  assert((scode != NULL) || (name != NULL));
669 
670  /* We'll use the code so fill it even it should always be available */
671  if (scode == NULL) {
672  option = kea_lookup_name(sspace->content,
673  stringValue(name)->content);
674  assert(option != NULL);
675  scode = createInt(option->code);
676  mapSet(src, scode, "code");
677  }
678  assert(intValue(scode) != 0);
679 
680  for (i = 0; i < listSize(dst); i++) {
681  struct element *od;
682  struct element *space;
683  struct element *code;
684 
685  od = listGet(dst, i);
686  space = mapGet(od, "space");
687  if (!eqString(sspace, stringValue(space)))
688  continue;
689  code = mapGet(od, "code");
690  if (code == NULL) {
691  name = mapGet(od, "name");
692  assert(name != NULL);
693  option = kea_lookup_name(sspace->content,
694  stringValue(name)->content);
695  assert(option != NULL);
696  code = createInt(option->code);
697  mapSet(od, code, "code");
698  }
699  /* check if the option is already present */
700  if (intValue(scode) == intValue(code))
701  return;
702  }
703  listPush(dst, copy(src));
704 }
705 
706 void
707 merge_option_data(struct element *src, struct element *dst)
708 {
709  struct element *od;
710  size_t i;
711 
712  for (i = 0; i < listSize(src); i++) {
713  od = listGet(src, i);
714  add_option_data(od, dst);
715  }
716 }
717 
718 struct comments *
719 get_config_comments(unsigned code)
720 {
721  static struct comments comments;
722  struct comment *comment = NULL;
723 
724  TAILQ_INIT(&comments);
725  switch (code) {
726  case 4: /* dynamic-bootp-lease-cutoff */
727  case 5: /* dynamic-bootp-lease-length */
728  case 6: /* boot-unknown-clients */
729  case 7: /* dynamic-bootp */
730  case 8: /* allow-bootp */
731  no_bootp:
732  comment = createComment("/// bootp protocol is not supported");
733  TAILQ_INSERT_TAIL(&comments, comment);
734  break;
735 
736  case 9: /* allow-booting */
737  comment = createComment("/// allow-booting is not supported");
738  TAILQ_INSERT_TAIL(&comments, comment);
739  comment = createComment("/// no concrete usage known?");
740  TAILQ_INSERT_TAIL(&comments, comment);
741  comment = createComment("/// Reference Kea #239");
742  TAILQ_INSERT_TAIL(&comments, comment);
743  break;
744 
745  case 10: /* one-lease-per-client */
746  comment = createComment("/// one-lease-per-client is not "
747  "supported");
748  TAILQ_INSERT_TAIL(&comments, comment);
749  comment = createComment("/// Reference Kea #238");
750  TAILQ_INSERT_TAIL(&comments, comment);
751  break;
752 
753  case 11: /* get-lease-hostnames */
754  comment = createComment("/// get-lease-hostnames is not "
755  "supported");
756  TAILQ_INSERT_TAIL(&comments, comment);
757  comment = createComment("/// Reference Kea #240");
758  TAILQ_INSERT_TAIL(&comments, comment);
759  break;
760 
761  case 12: /* use-host-decl-names */
762  comment = createComment("/// use-host-decl-names defaults "
763  "to always on");
764  TAILQ_INSERT_TAIL(&comments, comment);
765  break;
766 
767  case 13: /* use-lease-addr-for-default-route */
768  comment = createComment("/// use-lease-addr-for-default-route "
769  "is obsolete");
770  TAILQ_INSERT_TAIL(&comments, comment);
771  break;
772 
773  case 14: /* min-secs */
774  comment = createComment("/// min-secs is not (yet?) "
775  "supported");
776  TAILQ_INSERT_TAIL(&comments, comment);
777  comment = createComment("/// Reference Kea #223");
778  TAILQ_INSERT_TAIL(&comments, comment);
779  break;
780 
781  case 20: /* always-reply-rfc1048 */
782  goto no_bootp;
783 
784  case 22: /* always-broadcast */
785  comment = createComment("/// always-broadcast is not "
786  "supported");
787  TAILQ_INSERT_TAIL(&comments, comment);
788  comment = createComment("/// Reference Kea #241");
789  TAILQ_INSERT_TAIL(&comments, comment);
790  break;
791 
792  case 24: /* ddns-hostname */
793  comment = createComment("/// ddns-hostname is not supported");
794  TAILQ_INSERT_TAIL(&comments, comment);
795  comment = createComment("/// Please use hostname in a "
796  "host reservation instead");
797  TAILQ_INSERT_TAIL(&comments, comment);
798  break;
799 
800  case 25: /* ddns-rev-domainname */
801  comment = createComment("/// ddns-rev-domainname is an "
802  "obsolete (so not supported) feature");
803  TAILQ_INSERT_TAIL(&comments, comment);
804  break;
805 
806  case 26: /* lease-file-name */
807  comment = createComment("/// lease-file-name is an internal "
808  "ISC DHCP feature");
809  TAILQ_INSERT_TAIL(&comments, comment);
810  break;
811 
812  case 27: /* pid-file-name */
813  comment = createComment("/// pid-file-nam is an internal "
814  "ISC DHCP feature");
815  TAILQ_INSERT_TAIL(&comments, comment);
816  break;
817 
818  case 28: /* duplicates */
819  comment = createComment("/// duplicates is not supported");
820  TAILQ_INSERT_TAIL(&comments, comment);
821  comment = createComment("/// Kea model is different (and "
822  "stricter)");
823  TAILQ_INSERT_TAIL(&comments, comment);
824  break;
825 
826  case 29: /* declines */
827  comment = createComment("/// declines is not supported");
828  TAILQ_INSERT_TAIL(&comments, comment);
829  comment = createComment("/// Kea honors decline messages "
830  " and holds address for "
831  "decline-probation-period");
832  TAILQ_INSERT_TAIL(&comments, comment);
833  break;
834 
835  case 31: /* omapi-port */
836  comment = createComment("/// omapi-port is an internal "
837  "ISC DHCP feature");
838  TAILQ_INSERT_TAIL(&comments, comment);
839  break;
840 
841  case 32: /* local-port */
842  comment = createComment("/// local-port is not supported");
843  TAILQ_INSERT_TAIL(&comments, comment);
844  comment = createComment("/// command line -p parameter "
845  "should be used instead");
846  TAILQ_INSERT_TAIL(&comments, comment);
847  break;
848 
849  case 33: /* limited-broadcast-address */
850  comment = createComment("/// limited-broadcast-address "
851  "is not (yet?) supported");
852  TAILQ_INSERT_TAIL(&comments, comment);
853  comment = createComment("/// Reference Kea #224");
854  TAILQ_INSERT_TAIL(&comments, comment);
855  break;
856 
857  case 34: /* remote-port */
858  comment = createComment("/// remote-port is a not portable "
859  "(so not supported) feature");
860  TAILQ_INSERT_TAIL(&comments, comment);
861  break;
862 
863  case 35: /* local-address */
864  comment = createComment("/// local-address is not supported");
865  TAILQ_INSERT_TAIL(&comments, comment);
866  comment = createComment("/// Kea equivalent feature is "
867  "to specify an interface address");
868  TAILQ_INSERT_TAIL(&comments, comment);
869  break;
870 
871  case 36: /* omapi-key */
872  comment = createComment("/// omapi-key is an internal "
873  "ISC DHCP feature");
874  TAILQ_INSERT_TAIL(&comments, comment);
875  break;
876 
877  case 37: /* stash-agent-options */
878  comment = createComment("/// stash-agent-options is not "
879  "(yet?) supported");
880  TAILQ_INSERT_TAIL(&comments, comment);
881  comment = createComment("/// Reference Kea #218");
882  TAILQ_INSERT_TAIL(&comments, comment);
883  break;
884 
885  case 38: /* ddns-ttl */
886  comment = createComment("/// ddns-ttl is a D2 not (yet?) "
887  "supported feature");
888  TAILQ_INSERT_TAIL(&comments, comment);
889  comment = createComment("/// Reference Kea #225");
890  TAILQ_INSERT_TAIL(&comments, comment);
891  break;
892 
893  case 40: /* client-updates */
894  comment = createComment("/// ddns-ttl client-updates is "
895  "not supported");
896  TAILQ_INSERT_TAIL(&comments, comment);
897  comment = createComment("/// Kea model is very different");
898  TAILQ_INSERT_TAIL(&comments, comment);
899  break;
900 
901  case 41: /* update-optimization */
902  comment = createComment("/// update-optimization is not "
903  "supported");
904  TAILQ_INSERT_TAIL(&comments, comment);
905  comment = createComment("/// Kea follows RFC 4702");
906  TAILQ_INSERT_TAIL(&comments, comment);
907  break;
908 
909  case 42: /* ping-check */
910  comment = createComment("/// ping-check is not supported");
911  TAILQ_INSERT_TAIL(&comments, comment);
912  no_ping:
913  comment = createComment("/// Kea has no ping probing");
914  TAILQ_INSERT_TAIL(&comments, comment);
915  break;
916 
917  case 43: /* update-static-leases */
918  comment = createComment("/// update-static-leases is an "
919  "obsolete feature");
920  TAILQ_INSERT_TAIL(&comments, comment);
921  break;
922 
923  case 44: /* log-facility */
924  comment = createComment("/// log-facility is not supported");
925  TAILQ_INSERT_TAIL(&comments, comment);
926  comment = createComment("/// Please use the "
927  "KEA_LOGGER_DESTINATION environment "
928  "variable instead");
929  TAILQ_INSERT_TAIL(&comments, comment);
930  break;
931 
932  case 45: /* do-forward-updates */
933  comment = createComment("/// do-forward-updates is not "
934  "supported");
935  TAILQ_INSERT_TAIL(&comments, comment);
936  ddns_updates:
937  comment = createComment("/// Kea model is equivalent but "
938  "different");
939  TAILQ_INSERT_TAIL(&comments, comment);
940  break;
941 
942  case 46: /* ping-timeout */
943  comment = createComment("/// ping-timeout is not supported");
944  TAILQ_INSERT_TAIL(&comments, comment);
945  goto no_ping;
946 
947  case 47: /* infinite-is-reserved */
948  comment = createComment("/// infinite-is-reserved is not "
949  "supported");
950  TAILQ_INSERT_TAIL(&comments, comment);
951  comment = createComment("/// Kea does not support reserved "
952  "leases");
953  TAILQ_INSERT_TAIL(&comments, comment);
954  break;
955 
956  case 48: /* update-conflict-detection */
957  comment = createComment("/// update-conflict-detection is not "
958  "supported");
959  TAILQ_INSERT_TAIL(&comments, comment);
960  comment = createComment("/// DDNS is handled by the D2 "
961  "server using a dedicated config");
962  TAILQ_INSERT_TAIL(&comments, comment);
963  break;
964 
965  case 49: /* leasequery */
966  comment = createComment("/// leasequery is not supported");
967  TAILQ_INSERT_TAIL(&comments, comment);
968  comment = createComment("/// Kea does not (yet) support "
969  "the leasequery protocol");
970  TAILQ_INSERT_TAIL(&comments, comment);
971  break;
972 
973  case 50: /* adaptive-lease-time-threshold */
974  comment = createComment("/// adaptive-lease-time-threshold is "
975  "not supported");
976  TAILQ_INSERT_TAIL(&comments, comment);
977  comment = createComment("/// Reference Kea #226");
978  TAILQ_INSERT_TAIL(&comments, comment);
979  break;
980 
981  case 51: /* do-reverse-updates */
982  comment = createComment("/// do-reverse-updates is not "
983  "supported");
984  TAILQ_INSERT_TAIL(&comments, comment);
985  goto ddns_updates;
986 
987  case 52: /* fqdn-reply */
988  comment = createComment("/// fqdn-reply is an obsolete "
989  "feature");
990  TAILQ_INSERT_TAIL(&comments, comment);
991  break;
992 
993  case 54: /* dhcpv6-lease-file-name */
994  comment = createComment("/// dhcpv6-lease-file-name "
995  "is an internal ISC DHCP feature");
996  TAILQ_INSERT_TAIL(&comments, comment);
997  break;
998 
999  case 55: /* dhcpv6-pid-file-name */
1000  comment = createComment("/// dhcpv6-pid-file-name "
1001  "is an internal ISC DHCP feature");
1002  TAILQ_INSERT_TAIL(&comments, comment);
1003  break;
1004 
1005  case 56: /* limit-addrs-per-ia */
1006  comment = createComment("/// limit-addrs-per-ia "
1007  "is not (yet?) supported");
1008  TAILQ_INSERT_TAIL(&comments, comment);
1009  limit_resources:
1010  comment = createComment("/// Reference Kea #227");
1011  TAILQ_INSERT_TAIL(&comments, comment);
1012  break;
1013 
1014  case 57: /* limit-prefs-per-ia */
1015  comment = createComment("/// limit-prefs-per-ia"
1016  "is not (yet?) supported");
1017  TAILQ_INSERT_TAIL(&comments, comment);
1018  goto limit_resources;
1019 
1020  case 58: /* delayed-ack */
1021  case 59: /* max-ack-delay */
1022  comment = createComment("/// delayed ack no supported");
1023  TAILQ_INSERT_TAIL(&comments, comment);
1024  break;
1025 
1026  case 78: /* dhcp-cache-threshold */
1027  comment = createComment("/// dhcp-cache-threshold "
1028  "is not (yet?) supported");
1029  TAILQ_INSERT_TAIL(&comments, comment);
1030  comment = createComment("/// Reference Kea #228");
1031  TAILQ_INSERT_TAIL(&comments, comment);
1032  break;
1033 
1034  case 79: /* dont-use-fsync */
1035  comment = createComment("/// dont-use-fsync is an internal "
1036  "ISC DHCP feature");
1037  TAILQ_INSERT_TAIL(&comments, comment);
1038  break;
1039 
1040  case 80: /* ddns-local-address4 */
1041  comment = createComment("/// ddns-local-address4 is not "
1042  "supported");
1043  TAILQ_INSERT_TAIL(&comments, comment);
1044  d2_ip_address:
1045  comment = createComment("/// Kea D2 equivalent config is "
1046  "ip-address");
1047  TAILQ_INSERT_TAIL(&comments, comment);
1048  break;
1049 
1050  case 81: /* ddns-local-address6 */
1051  comment = createComment("/// ddns-local-address6 is not "
1052  "supported");
1053  TAILQ_INSERT_TAIL(&comments, comment);
1054  goto d2_ip_address;
1055 
1056  case 83: /* log-threshold-low */
1057  comment = createComment("/// log-threshold-low is not (yet?) "
1058  "supported");
1059  TAILQ_INSERT_TAIL(&comments, comment);
1060  log_threshold:
1061  comment = createComment("/// Reference Kea #222");
1062  TAILQ_INSERT_TAIL(&comments, comment);
1063  break;
1064 
1065  case 84: /* log-threshold-high */
1066  comment = createComment("/// log-threshold-high is not (yet?) "
1067  "supported");
1068  TAILQ_INSERT_TAIL(&comments, comment);
1069  goto log_threshold;
1070 
1071  case 86: /* server-id-check */
1072  comment = createComment("/// server-id-check is not (yet?) "
1073  "supported");
1074  TAILQ_INSERT_TAIL(&comments, comment);
1075  comment = createComment("/// Reference Kea #242");
1076  TAILQ_INSERT_TAIL(&comments, comment);
1077  break;
1078 
1079  case 87: /* prefix-length-mode */
1080  comment = createComment("/// prefix-length-mode is not "
1081  "supported");
1082  TAILQ_INSERT_TAIL(&comments, comment);
1083  comment = createComment("/// Kea model is different (and "
1084  "simpler?)");
1085  TAILQ_INSERT_TAIL(&comments, comment);
1086  break;
1087  case 88: /* dhcpv6-set-tee-times */
1088  comment = createComment("/// dhcpv6-set-tee-times is a "
1089  "transitional (so not supported) "
1090  "feature");
1091  TAILQ_INSERT_TAIL(&comments, comment);
1092  comment = createComment("/// T1 and T2 are .5 and .8 times "
1093  "preferred-lifetime");
1094  TAILQ_INSERT_TAIL(&comments, comment);
1095  break;
1096  case 89: /* abandon-lease-time */
1097  comment = createComment("/// abandon-lease-time is not "
1098  "supported");
1099  TAILQ_INSERT_TAIL(&comments, comment);
1100  comment = createComment("/// Kea support equivalent (and "
1101  "richer) expired-lease-processing "
1102  "and decline-probation-period");
1103  TAILQ_INSERT_TAIL(&comments, comment);
1104  break;
1105  case 90: /* use-eui-64 */
1106  comment = createComment("/// EUI-64 is not (yet) supported");
1107  TAILQ_INSERT_TAIL(&comments, comment);
1108  comment = createComment("/// Reference Kea #265");
1109  TAILQ_INSERT_TAIL(&comments, comment);
1110  break;
1111  case 96: /* release-on-roam */
1112  comment = createComment("/// release-on-roam is not (yet) "
1113  "supported");
1114  TAILQ_INSERT_TAIL(&comments, comment);
1115  comment = createComment("/// Reference Kea #266");
1116  TAILQ_INSERT_TAIL(&comments, comment);
1117  break;
1118  case 97: /* local-address6 */
1119  comment = createComment("/// local-address6 is not supported");
1120  TAILQ_INSERT_TAIL(&comments, comment);
1121  comment = createComment("/// Kea equivalent feature is "
1122  "to specify an interface address");
1123  TAILQ_INSERT_TAIL(&comments, comment);
1124  break;
1125  case 99: /* ping-cltt-secs */
1126  comment = createComment("/// ping-cltt-secs is not supported");
1127  TAILQ_INSERT_TAIL(&comments, comment);
1128  goto no_ping;
1129  case 100: /* ping-timeout-ms */
1130  comment = createComment("/// ping-timeout-ms is not "
1131  "supported");
1132  TAILQ_INSERT_TAIL(&comments, comment);
1133  goto no_ping;
1134  }
1135  return &comments;
1136 }
1137 
1138 const char *
1140 {
1141  switch (status) {
1142  case kea_unknown:
1143  case special:
1144  return "known (unknown)";
1145  case isc_dhcp_unknown:
1146  return "unknown (known)";
1147  case known:
1148  return "known (known)";
1149  case dynamic:
1150  return "dynamic (dynamic)";
1151  default:
1152  return "??? (" "???" ")";
1153  }
1154 }
const char * name
Definition: tree.h:302
struct option * option_lookup_name(const char *space, const char *name)
Definition: options.c:578
void add_option_data(struct element *src, struct element *dst)
Definition: options.c:657
unsigned code
Definition: keama.h:271
const char * display_status(enum option_status status)
Definition: options.c:1139
#define TAILQ_INIT(head)
Definition: data.h:72
TAILQ_HEAD(spaces, space)
SPACES.
Definition: options.c:30
struct option * kea_lookup_name(const char *space, const char *name)
Definition: options.c:598
Definition: keama.h:281
struct element * createInt(int64_t i)
Definition: data.c:445
const char * old
Definition: keama.h:276
enum option_status status
Definition: keama.h:284
const char * space
Definition: keama.h:270
Definition: tree.h:301
Definition: keama.h:263
const char * old
Definition: keama.h:290
struct option_def agents[]
DHCPv4 AGENT.
Definition: options.c:296
const char * format
Definition: tree.h:347
Definition: data.h:216
const char * name
Definition: tree.h:346
char * content
Definition: data.h:173
Definition: tree.h:345
Definition: keama.h:262
unsigned code
Definition: tree.h:349
struct element * mapGet(struct element *m, const char *k)
Definition: data.c:759
void mapSet(struct element *m, struct element *e, const char *k)
Definition: data.c:777
Definition: data.h:190
void push_space(struct space *space)
Definition: options.c:641
const struct space * space
Definition: keama.h:293
struct string * stringValue(struct element *e)
Definition: data.c:408
#define TAILQ_INSERT_TAIL(head, elm)
Definition: data.h:105
isc_boolean_t eqString(const struct string *s, const struct string *o)
Definition: data.c:343
Definition: data.h:171
Definition: keama.h:264
enum option_status status
Definition: keama.h:295
const char * old
Definition: keama.h:282
struct option_def configs[]
SERVER.
Definition: options.c:308
size_t listSize(const struct element *l)
Definition: data.c:730
int ddns_updates(struct packet *, struct lease *, struct lease *, struct iasubopt *, struct iasubopt *, struct option_state *)
enum option_status status
Definition: keama.h:278
void listPush(struct element *l, struct element *e)
Definition: data.c:697
void push_option(struct option *option)
Definition: options.c:648
option_status
Definition: keama.h:259
enum option_status status
Definition: keama.h:272
struct space * space_lookup(const char *name)
Definition: options.c:564
struct comments * get_config_comments(unsigned code)
Definition: options.c:719
struct option * option_lookup_code(const char *space, unsigned code)
Definition: options.c:623
struct element * copy(struct element *e)
Definition: data.c:1115
struct option_def options6[]
DHCPv6.
Definition: options.c:201
#define TAILQ_FOREACH(var, head)
Definition: data.h:62
const char * name
Definition: keama.h:283
const char * format
Definition: keama.h:269
void merge_option_data(struct element *src, struct element *dst)
Definition: options.c:707
void options_init(void)
Definition: options.c:419
const char * name
Definition: keama.h:277
struct option_def options4[]
DHCPv4.
Definition: options.c:63
int64_t intValue(const struct element *e)
Definition: data.c:383
void spaces_init(void)
Definition: options.c:399
const char * name
Definition: keama.h:268
struct element * listGet(struct element *l, int i)
Definition: data.c:646
struct comment * createComment(const char *line)
Definition: data.c:367