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
30TAILQ_HEAD(spaces, space) spaces;
31TAILQ_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
43struct 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
63struct 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
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
296struct 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
308struct 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
398void
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
418void
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;
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;
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;
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;
556 assert(option->space != NULL);
557 option->code = def->code;
558 option->status = def->status;
559 TAILQ_INSERT_TAIL(&options, option);
560 }
561}
562
563struct space *
564space_lookup(const char *name)
565{
566 struct space *space;
567
568 TAILQ_FOREACH(space, &spaces) {
570 continue;
571 if (strcmp(name, space->old) == 0)
572 return space;
573 }
574 return NULL;
575}
576
577struct option *
578option_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
597struct option *
598kea_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
622struct option *
623option_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
640void
642{
644 TAILQ_INSERT_TAIL(&spaces, space);
645}
646
647void
649{
650 assert(option->space != NULL);
651 option->old = option->name;
653 TAILQ_INSERT_TAIL(&options, option);
654}
655
656void
657add_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) {
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);
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
706void
707merge_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
718struct comments *
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);
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
1138const 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}
void listPush(struct element *l, struct element *e)
Definition: data.c:697
struct comment * createComment(const char *line)
Definition: data.c:367
isc_boolean_t eqString(const struct string *s, const struct string *o)
Definition: data.c:343
struct element * copy(struct element *e)
Definition: data.c:1115
struct element * listGet(struct element *l, int i)
Definition: data.c:646
struct string * stringValue(struct element *e)
Definition: data.c:408
struct element * createInt(int64_t i)
Definition: data.c:445
void mapSet(struct element *m, struct element *e, const char *k)
Definition: data.c:777
size_t listSize(const struct element *l)
Definition: data.c:730
struct element * mapGet(struct element *m, const char *k)
Definition: data.c:759
int64_t intValue(const struct element *e)
Definition: data.c:383
#define TAILQ_INSERT_TAIL(head, elm)
Definition: data.h:105
#define TAILQ_FOREACH(var, head)
Definition: data.h:62
#define TAILQ_INIT(head)
Definition: data.h:72
int ddns_updates(struct packet *, struct lease *, struct lease *, struct iasubopt *, struct iasubopt *, struct option_state *)
void merge_option_data(struct element *src, struct element *dst)
Definition: options.c:707
void push_space(struct space *space)
Definition: options.c:641
void add_option_data(struct element *src, struct element *dst)
Definition: options.c:657
struct option_def configs[]
SERVER.
Definition: options.c:308
struct space * space_lookup(const char *name)
Definition: options.c:564
struct option * option_lookup_code(const char *space, unsigned code)
Definition: options.c:623
struct option_def agents[]
DHCPv4 AGENT.
Definition: options.c:296
TAILQ_HEAD(spaces, space)
SPACES.
Definition: options.c:30
void options_init(void)
Definition: options.c:419
struct option_def options4[]
DHCPv4.
Definition: options.c:63
void spaces_init(void)
Definition: options.c:399
struct comments * get_config_comments(unsigned code)
Definition: options.c:719
struct option * option_lookup_name(const char *space, const char *name)
Definition: options.c:578
struct option_def options6[]
DHCPv6.
Definition: options.c:201
struct option * kea_lookup_name(const char *space, const char *name)
Definition: options.c:598
void push_option(struct option *option)
Definition: options.c:648
const char * display_status(enum option_status status)
Definition: options.c:1139
option_status
Definition: keama.h:259
@ kea_unknown
Definition: keama.h:260
@ dynamic
Definition: keama.h:264
@ isc_dhcp_unknown
Definition: keama.h:261
@ special
Definition: keama.h:263
@ known
Definition: keama.h:262
Definition: data.h:190
Definition: data.h:216
const char * format
Definition: keama.h:269
enum option_status status
Definition: keama.h:272
unsigned code
Definition: keama.h:271
const char * name
Definition: keama.h:268
const char * space
Definition: keama.h:270
Definition: tree.h:345
const char * format
Definition: tree.h:347
unsigned code
Definition: tree.h:349
enum option_status status
Definition: keama.h:295
const char * old
Definition: keama.h:290
const struct space * space
Definition: keama.h:293
const char * name
Definition: tree.h:346
const char * name
Definition: keama.h:277
const char * old
Definition: keama.h:276
enum option_status status
Definition: keama.h:278
Definition: keama.h:281
const char * old
Definition: keama.h:282
enum option_status status
Definition: keama.h:284
const char * name
Definition: keama.h:283
Definition: data.h:171
char * content
Definition: data.h:173
Definition: tree.h:301
const char * name
Definition: tree.h:302