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