]> git.ipfire.org Git - thirdparty/dhcp.git/blame - keama/options.c
Added option definition
[thirdparty/dhcp.git] / keama / options.c
CommitLineData
0cd94b5e 1/*
82e0ea57 2 * Copyright (c) 2017-2019 by Internet Systems Consortium, Inc. ("ISC")
0cd94b5e
TM
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
42/// SPACES
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
62/// DHCPv4
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},
69 /// ien116-name-servers -> name-servers
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},
127 /// nwip-domain nwip-domain-name
128 { "nwip-suboptions", "Enwip.", "dhcp", 63, 2},
129 { "nisplus-domain", "t", "dhcp", 64, 2},
130 /// nisplus-domain nisplus-domain-name
131 { "nisplus-servers", "Ia", "dhcp", 65, 2},
132 { "tftp-server-name", "t", "dhcp", 66, 2},
133 { "bootfile-name", "t", "dhcp", 67, 2},
134 /// bootfile-name boot-file-name
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},
151 /// relay-agent-information dhcp-agent-options
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},
160 /// not supported by ISC DHCP
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},
25f124c8 173 { "v6-only-preferred", "L", "dhcp", 108, 2},
0cd94b5e
TM
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},
182 /// vivco vivco-suboptions
183 { "vivso", "Evendor.", "dhcp", 125, 2},
184 /// vivso vivso-suboptions
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},
190 /// not supported by Kea
191 { "rdnss-selection", "BIID", "dhcp", 146, 2},
192 { "tftp-server-address", "Ia", "dhcp", 150, 0},
193 /// not supported by Kea
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
201/// DHCPv6
202struct option_def options6[] = {
203 { "client-id", "X", "dhcp6", 1, 2},
204 /// client-id clientid
205 { "server-id", "X", "dhcp6", 2, 2},
206 /// server-id serverid
207 { "ia-na", "X", "dhcp6", 3, 2},
208 { "ia-ta", "X", "dhcp6", 4, 2},
209 { "ia-addr", "X", "dhcp6", 5, 2},
210 /// ia-addr iaaddr
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},
215 /// 10 is unassigned
216 { "auth", "X", "dhcp6", 11, 1},
217 /// not supported by ISC DHCP
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},
222 /// not supported by ISC DHCP
223 { "vendor-class", "LX", "dhcp6", 16, 1},
224 /// not supported by ISC DHCP
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},
230 /// sip-servers-names sip-server-dns
231 { "sip-servers-addresses", "6a", "dhcp6", 22, 2},
232 /// sip-servers-addresses sip-server-addr
233 { "name-servers", "6a", "dhcp6", 23, 2},
234 /// name-servers dns-servers
235 { "domain-search", "D", "dhcp6", 24, 2},
236 { "ia-pd", "X", "dhcp6", 25, 2},
237 { "ia-prefix", "X", "dhcp6", 26, 2},
238 /// ia-prefix iaprefix
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},
245 /// info-refresh-time information-refresh-time
246 { "bcms-server-d", "D", "dhcp6", 33, 2},
247 /// bcms-server-d bcms-server-dns
248 { "bcms-server-a", "6a", "dhcp6", 34, 2},
249 /// bcms-server-a bcms-server-addr
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},
256 /// fqdn client-fqdn
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},
278 /// not supported by ISC DHCP
279 { "pd-exclude", "X", "dhcp6", 67, 1},
280 /// not supported by ISC DHCP (prefix6 format)
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},
287 /// dhcpv4-msg dhcpv4-message
288 { "dhcp4-o-dhcp6-server", "6a", "dhcp6", 88, 2},
289 /// dhcp4-o-dhcp6-server dhcp4o6-server-addr
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
296/// DHCPv4 AGENT
297struct option_def agents[] = {
298 /// All not supported by Kea
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
308/// SERVER
309struct 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
399void
400spaces_init(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
419void
420options_init(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
564struct space *
565space_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
578struct option *
579option_lookup_name(const char *space, const char *name)
580{
581 struct space *universe;
582 struct option *option;
583
584 universe = space_lookup(space);
585 if (universe == NULL)
586 return NULL;
587 TAILQ_FOREACH(option, &options) {
588 if (option->status == isc_dhcp_unknown)
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
598struct option *
599kea_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
623struct option *
624option_lookup_code(const char *space, unsigned code)
625{
626 struct space *universe;
627 struct option *option;
628
629 universe = space_lookup(space);
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
641void
642push_space(struct space *space)
643{
644 space->status = dynamic;
645 TAILQ_INSERT_TAIL(&spaces, space);
646}
647
648void
649push_option(struct option *option)
650{
651 assert(option->space != NULL);
652 option->old = option->name;
653 option->status = dynamic;
654 TAILQ_INSERT_TAIL(&options, option);
655}
656
657void
658add_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
707void
708merge_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
719struct comments *
720get_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
1139const char *
1140display_status(enum option_status status)
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}