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