/* $NetBSD: options.c,v 1.3.4.2 2024/02/29 11:39:21 martin Exp $ */ /* * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Internet Systems Consortium, Inc. * PO Box 360 * Newmarket, NH 03857 USA * * https://www.isc.org/ * */ #include __RCSID("$NetBSD: options.c,v 1.3.4.2 2024/02/29 11:39:21 martin Exp $"); #include #include #include #include "keama.h" TAILQ_HEAD(spaces, space) spaces; TAILQ_HEAD(options, option) options; /* From common/tables.c */ /* Additional format codes: x - ISC DHCP and Kea string Y - force full binary u - undefined (parsed as X) */ /// SPACES struct space_def space_defs[] = { { "dhcp", "dhcp4", 2}, { "nwip", "nwip", 0}, { "agent", "dhcp-agent-options-space", 2}, { "vendor-class", "_vivco_", 0}, { "vendor", "_vivso_", 3}, { "isc", "_isc_", 0}, { "", "vendor-encapsulated-options-space", 1}, { "_docsis3_", "vendor-4491", 1}, { "dhcp6", "dhcp6", 2}, { "vsio", "_vendor-opts-space_", 3}, { "_vsio_", "vendor-opts-space", 1}, { "isc6", "_isc6_", 0}, { "_rsoo_", "rsoo-opts", 1}, { "_isc6_", "vendor-2495", 1}, { "server", "_server_", 0}, { NULL, NULL, 0} }; /// DHCPv4 struct option_def options4[] = { { "subnet-mask", "I", "dhcp", 1, 2}, { "time-offset", "l", "dhcp", 2, 2}, { "routers", "Ia", "dhcp", 3, 2}, { "time-servers", "Ia", "dhcp", 4, 2}, { "ien116-name-servers", "Ia", "dhcp", 5, 2}, /// ien116-name-servers -> name-servers { "domain-name-servers", "Ia", "dhcp", 6, 2}, { "log-servers", "Ia", "dhcp", 7, 2}, { "cookie-servers", "Ia", "dhcp", 8, 2}, { "lpr-servers", "Ia", "dhcp", 9, 2}, { "impress-servers", "Ia", "dhcp", 10, 2}, { "resource-location-servers", "Ia", "dhcp", 11, 2}, { "host-name", "t", "dhcp", 12, 2}, { "boot-size", "S", "dhcp", 13, 2}, { "merit-dump", "t", "dhcp", 14, 2}, { "domain-name", "t", "dhcp", 15, 2}, { "swap-server", "I", "dhcp", 16, 2}, { "root-path", "t", "dhcp", 17, 2}, { "extensions-path", "t", "dhcp", 18, 2}, { "ip-forwarding", "f", "dhcp", 19, 2}, { "non-local-source-routing", "f", "dhcp", 20, 2}, { "policy-filter", "IIa", "dhcp", 21, 2}, { "max-dgram-reassembly", "S", "dhcp", 22, 2}, { "default-ip-ttl", "B", "dhcp", 23, 2}, { "path-mtu-aging-timeout", "L", "dhcp", 24, 2}, { "path-mtu-plateau-table", "Sa", "dhcp", 25, 2}, { "interface-mtu", "S", "dhcp", 26, 2}, { "all-subnets-local", "f", "dhcp", 27, 2}, { "broadcast-address", "I", "dhcp", 28, 2}, { "perform-mask-discovery", "f", "dhcp", 29, 2}, { "mask-supplier", "f", "dhcp", 30, 2}, { "router-discovery", "f", "dhcp", 31, 2}, { "router-solicitation-address", "I", "dhcp", 32, 2}, { "static-routes", "IIa", "dhcp", 33, 2}, { "trailer-encapsulation", "f", "dhcp", 34, 2}, { "arp-cache-timeout", "L", "dhcp", 35, 2}, { "ieee802-3-encapsulation", "f", "dhcp", 36, 2}, { "default-tcp-ttl", "B", "dhcp", 37, 2}, { "tcp-keepalive-interval", "L", "dhcp", 38, 2}, { "tcp-keepalive-garbage", "f", "dhcp", 39, 2}, { "nis-domain", "t", "dhcp", 40, 2}, { "nis-servers", "Ia", "dhcp", 41, 2}, { "ntp-servers", "Ia", "dhcp", 42, 2}, { "vendor-encapsulated-options", "E.", "dhcp", 43, 2}, { "netbios-name-servers", "Ia", "dhcp", 44, 2}, { "netbios-dd-server", "Ia", "dhcp", 45, 2}, { "netbios-node-type", "B", "dhcp", 46, 2}, { "netbios-scope", "t", "dhcp", 47, 2}, { "font-servers", "Ia", "dhcp", 48, 2}, { "x-display-manager", "Ia", "dhcp", 49, 2}, { "dhcp-requested-address", "I", "dhcp", 50, 2}, { "dhcp-lease-time", "L", "dhcp", 51, 2}, { "dhcp-option-overload", "B", "dhcp", 52, 2}, { "dhcp-message-type", "B", "dhcp", 53, 2}, { "dhcp-server-identifier", "I", "dhcp", 54, 2}, { "dhcp-parameter-request-list", "Ba", "dhcp", 55, 2}, { "dhcp-message", "t", "dhcp", 56, 2}, { "dhcp-max-message-size", "S", "dhcp", 57, 2}, { "dhcp-renewal-time", "L", "dhcp", 58, 2}, { "dhcp-rebinding-time", "L", "dhcp", 59, 2}, { "vendor-class-identifier", "x", "dhcp", 60, 2}, { "dhcp-client-identifier", "X", "dhcp", 61, 2}, { "nwip-domain", "t", "dhcp", 62, 2}, /// nwip-domain nwip-domain-name { "nwip-suboptions", "Enwip.", "dhcp", 63, 2}, { "nisplus-domain", "t", "dhcp", 64, 2}, /// nisplus-domain nisplus-domain-name { "nisplus-servers", "Ia", "dhcp", 65, 2}, { "tftp-server-name", "t", "dhcp", 66, 2}, { "bootfile-name", "t", "dhcp", 67, 2}, /// bootfile-name boot-file-name { "mobile-ip-home-agent", "Ia", "dhcp", 68, 2}, { "smtp-server", "Ia", "dhcp", 69, 2}, { "pop-server", "Ia", "dhcp", 70, 2}, { "nntp-server", "Ia", "dhcp", 71, 2}, { "www-server", "Ia", "dhcp", 72, 2}, { "finger-server", "Ia", "dhcp", 73, 2}, { "irc-server", "Ia", "dhcp", 74, 2}, { "streettalk-server", "Ia", "dhcp", 75, 2}, { "streettalk-directory-assistance-server", "Ia", "dhcp", 76, 2}, { "user-class", "tY", "dhcp", 77, 2}, { "slp-directory-agent", "fIa", "dhcp", 78, 2}, { "slp-service-scope", "fto", "dhcp", 79, 2}, /* 80 is the zero-length rapid-commit (RFC 4039) */ { "fqdn", "Efqdn.", "dhcp", 81, 2}, { "relay-agent-information", "Eagent.", "dhcp", 82, 2}, /// relay-agent-information dhcp-agent-options /* 83 is iSNS (RFC 4174) */ /* 84 is unassigned */ { "nds-servers", "Ia", "dhcp", 85, 2}, { "nds-tree-name", "t", "dhcp", 86, 2}, { "nds-context", "t", "dhcp", 87, 2}, { "bcms-controller-names", "D", "dhcp", 88, 2}, { "bcms-controller-address", "Ia", "dhcp", 89, 2}, { "authenticate", "X", "dhcp", 90, 1}, /// not supported by ISC DHCP { "client-last-transaction-time", "L", "dhcp", 91, 2}, { "associated-ip", "Ia", "dhcp", 92, 2}, { "pxe-system-type", "Sa", "dhcp", 93, 2}, // pxe-system-type client-system { "pxe-interface-id", "BBB", "dhcp", 94, 2}, // pxe-interface-id client-ndi { "pxe-client-id", "BX", "dhcp", 97, 2}, // pxe-client-id uuid-guid { "uap-servers", "t", "dhcp", 98, 2}, { "geoconf-civic", "X", "dhcp", 99, 2}, { "pcode", "t", "dhcp", 100, 2}, { "tcode", "t", "dhcp", 101, 2}, { "v6-only-preferred", "L", "dhcp", 108, 2}, { "netinfo-server-address", "Ia", "dhcp", 112, 2}, { "netinfo-server-tag", "t", "dhcp", 113, 2}, { "default-url", "t", "dhcp", 114, 2}, { "auto-config", "B", "dhcp", 116, 2}, { "name-service-search", "Sa", "dhcp", 117, 2}, { "subnet-selection", "I", "dhcp", 118, 2}, { "domain-search", "Dc", "dhcp", 119, 2}, { "vivco", "Evendor-class.", "dhcp", 124, 2}, /// vivco vivco-suboptions { "vivso", "Evendor.", "dhcp", 125, 2}, /// vivso vivso-suboptions {"pana-agent", "Ia", "dhcp", 136, 2}, {"v4-lost", "d", "dhcp", 137, 2}, {"capwap-ac-v4", "Ia", "dhcp", 138, 2}, { "sip-ua-cs-domains", "Dc", "dhcp", 141, 2}, { "ipv4-address-andsf", "Ia", "dhcp", 142, 0}, /// not supported by Kea { "rdnss-selection", "BIID", "dhcp", 146, 2}, { "tftp-server-address", "Ia", "dhcp", 150, 0}, /// not supported by Kea { "v4-portparams", "BBS", "dhcp", 159, 2}, { "v4-captive-portal", "t", "dhcp", 160, 2}, { "option-6rd", "BB6Ia", "dhcp", 212, 2}, {"v4-access-domain", "d", "dhcp", 213, 2}, { NULL, NULL, NULL, 0, 0 } }; /// DHCPv6 struct option_def options6[] = { { "client-id", "X", "dhcp6", 1, 2}, /// client-id clientid { "server-id", "X", "dhcp6", 2, 2}, /// server-id serverid { "ia-na", "X", "dhcp6", 3, 2}, { "ia-ta", "X", "dhcp6", 4, 2}, { "ia-addr", "X", "dhcp6", 5, 2}, /// ia-addr iaaddr { "oro", "Sa", "dhcp6", 6, 2}, { "preference", "B", "dhcp6", 7, 2}, { "elapsed-time", "S", "dhcp6", 8, 2}, { "relay-msg", "X", "dhcp6", 9, 2}, /// 10 is unassigned { "auth", "X", "dhcp6", 11, 1}, /// not supported by ISC DHCP { "unicast", "6", "dhcp6", 12, 2}, { "status-code", "Nstatus-codes.to", "dhcp6", 13, 2}, { "rapid-commit", "Z", "dhcp6", 14, 2}, { "user-class", "X", "dhcp6", 15, 1}, /// not supported by ISC DHCP { "vendor-class", "LX", "dhcp6", 16, 1}, /// not supported by ISC DHCP { "vendor-opts", "Evsio.", "dhcp6", 17, 2}, { "interface-id", "X", "dhcp6", 18, 2}, { "reconf-msg", "Ndhcpv6-messages.", "dhcp6", 19, 2}, { "reconf-accept", "Z", "dhcp6", 20, 2}, { "sip-servers-names", "D", "dhcp6", 21, 2}, /// sip-servers-names sip-server-dns { "sip-servers-addresses", "6a", "dhcp6", 22, 2}, /// sip-servers-addresses sip-server-addr { "name-servers", "6a", "dhcp6", 23, 2}, /// name-servers dns-servers { "domain-search", "D", "dhcp6", 24, 2}, { "ia-pd", "X", "dhcp6", 25, 2}, { "ia-prefix", "X", "dhcp6", 26, 2}, /// ia-prefix iaprefix { "nis-servers", "6a", "dhcp6", 27, 2}, { "nisp-servers", "6a", "dhcp6", 28, 2}, { "nis-domain-name", "D", "dhcp6", 29, 2}, { "nisp-domain-name", "D", "dhcp6", 30, 2}, { "sntp-servers", "6a", "dhcp6", 31, 2}, { "info-refresh-time", "T", "dhcp6", 32, 2}, /// info-refresh-time information-refresh-time { "bcms-server-d", "D", "dhcp6", 33, 2}, /// bcms-server-d bcms-server-dns { "bcms-server-a", "6a", "dhcp6", 34, 2}, /// bcms-server-a bcms-server-addr /* Note that 35 is not assigned. */ { "geoconf-civic", "X", "dhcp6", 36, 2}, { "remote-id", "X", "dhcp6", 37, 2}, { "subscriber-id", "X", "dhcp6", 38, 2}, { "fqdn", "Efqdn6-if-you-see-me-its-a-bug-bug-bug.", "dhcp6", 39, 2}, /// fqdn client-fqdn { "pana-agent", "6a", "dhcp6", 40, 2}, { "new-posix-timezone", "t", "dhcp6", 41, 2}, { "new-tzdb-timezone", "t", "dhcp6", 42, 2}, { "ero", "Sa", "dhcp6", 43, 2}, { "lq-query", "X", "dhcp6", 44, 2}, { "client-data", "X", "dhcp6", 45, 2}, { "clt-time", "L", "dhcp6", 46, 2}, { "lq-relay-data", "6X", "dhcp6", 47, 2}, { "lq-client-link", "6a", "dhcp6", 48, 2}, { "v6-lost", "d", "dhcp6", 51, 2}, { "capwap-ac-v6", "6a", "dhcp6", 52, 2}, { "relay-id", "X", "dhcp6", 53, 2}, { "v6-access-domain", "d", "dhcp6", 57, 2}, { "sip-ua-cs-list", "D", "dhcp6", 58, 2}, { "bootfile-url", "t", "dhcp6", 59, 2}, { "bootfile-param", "X", "dhcp6", 60, 2}, { "client-arch-type", "Sa", "dhcp6", 61, 2}, { "nii", "BBB", "dhcp6", 62, 2}, { "aftr-name", "d", "dhcp6", 64, 2}, { "erp-local-domain-name", "d", "dhcp6", 65, 2}, { "rsoo", "Ersoo.", "dhcp6", 66, 1}, /// not supported by ISC DHCP { "pd-exclude", "X", "dhcp6", 67, 1}, /// not supported by ISC DHCP (prefix6 format) { "rdnss-selection", "6BD", "dhcp6", 74, 2}, { "client-linklayer-addr", "X", "dhcp6", 79, 2}, { "link-address", "6", "dhcp6", 80, 2}, { "solmax-rt", "L", "dhcp6", 82, 2}, { "inf-max-rt", "L", "dhcp6", 83, 2}, { "dhcpv4-msg", "X", "dhcp6", 87, 2}, /// dhcpv4-msg dhcpv4-message { "dhcp4-o-dhcp6-server", "6a", "dhcp6", 88, 2}, /// dhcp4-o-dhcp6-server dhcp4o6-server-addr { "v6-captive-portal", "t", "dhcp6", 103, 2}, { "relay-source-port", "S", "dhcp6", 135, 2}, { "ipv6-address-andsf", "6a", "dhcp6", 143, 2}, { NULL, NULL, NULL, 0, 0 } }; /// DHCPv4 AGENT struct option_def agents[] = { /// All not supported by Kea { "circuit-id", "X", "agent", 1, 0}, { "remote-id", "X", "agent", 2, 0}, { "agent-id", "I", "agent", 3, 0}, { "DOCSIS-device-class", "L", "agent", 4, 0}, { "link-selection", "I", "agent", 5, 0}, { "relay-port", "Z", "agent", 19, 0}, { NULL, NULL, NULL, 0, 0 } }; /// SERVER struct option_def configs[] = { { "default-lease-time", "T", "server", 1, 3}, { "max-lease-time", "T", "server", 2, 3}, { "min-lease-time", "T", "server", 3, 3}, { "dynamic-bootp-lease-cutoff", "T", "server", 4, 0}, { "dynamic-bootp-lease-length", "L", "server", 5, 0}, { "boot-unknown-clients", "f", "server", 6, 0}, { "dynamic-bootp", "f", "server", 7, 0}, { "allow-bootp", "f", "server", 8, 0}, { "allow-booting", "f", "server", 9, 0}, { "one-lease-per-client", "f", "server", 10, 0}, { "get-lease-hostnames", "f", "server", 11, 0}, { "use-host-decl-names", "f", "server", 12, 0}, { "use-lease-addr-for-default-route", "f", "server", 13, 0}, { "min-secs", "B", "server", 14, 0}, { "filename", "t", "server", 15, 3}, { "server-name", "t", "server", 16, 3}, { "next-server", "I", "server", 17, 3}, { "authoritative", "f", "server", 18, 3}, { "vendor-option-space", "U", "server", 19, 3}, { "always-reply-rfc1048", "f", "server", 20, 0}, { "site-option-space", "X", "server", 21, 3}, { "always-broadcast", "f", "server", 22, 0}, { "ddns-domainname", "t", "server", 23, 3}, { "ddns-hostname", "t", "server", 24, 0}, { "ddns-rev-domainname", "t", "server", 25, 0}, { "lease-file-name", "t", "server", 26, 0}, { "pid-file-name", "t", "server", 27, 0}, { "duplicates", "f", "server", 28, 0}, { "declines", "f", "server", 29, 0}, { "ddns-updates", "f", "server", 30, 3}, { "omapi-port", "S", "server", 31, 0}, { "local-port", "S", "server", 32, 0}, { "limited-broadcast-address", "I", "server", 33, 0}, { "remote-port", "S", "server", 34, 0}, { "local-address", "I", "server", 35, 0}, { "omapi-key", "d", "server", 36, 0}, { "stash-agent-options", "f", "server", 37, 0}, { "ddns-ttl", "T", "server", 38, 0}, { "ddns-update-style", "Nddns-styles.", "server", 39, 3}, { "client-updates", "f", "server", 40, 0}, { "update-optimization", "f", "server", 41, 0}, { "ping-check", "f", "server", 42, 0}, { "update-static-leases", "f", "server", 43, 0}, { "log-facility", "Nsyslog-facilities.", "server", 44, 0}, { "do-forward-updates", "f", "server", 45, 0}, { "ping-timeout", "T", "server", 46, 0}, { "infinite-is-reserved", "f", "server", 47, 0}, { "update-conflict-detection", "f", "server", 48, 0}, { "leasequery", "f", "server", 49, 0}, { "adaptive-lease-time-threshold", "B", "server", 50, 0}, { "do-reverse-updates", "f", "server", 51, 0}, { "fqdn-reply", "f", "server", 52, 0}, { "preferred-lifetime", "T", "server", 53, 3}, { "dhcpv6-lease-file-name", "t", "server", 54, 0}, { "dhcpv6-pid-file-name", "t", "server", 55, 0}, { "limit-addrs-per-ia", "L", "server", 56, 0}, { "limit-prefs-per-ia", "L", "server", 57, 0}, { "delayed-ack", "S", "server", 58, 0}, { "max-ack-delay", "L", "server", 59, 0}, /* LDAP */ { "dhcp-cache-threshold", "B", "server", 78, 0}, { "dont-use-fsync", "f", "server", 79, 0}, { "ddns-local-address4", "I", "server", 80, 0}, { "ddns-local-address6", "6", "server", 81, 0}, { "ignore-client-uids", "f", "server", 82, 3}, { "log-threshold-low", "B", "server", 83, 0}, { "log-threshold-high", "B", "server", 84, 0}, { "echo-client-id", "f", "server", 85, 3}, { "server-id-check", "f", "server", 86, 0}, { "prefix-length-mode", "Nprefix_length_modes.", "server", 87, 0}, { "dhcpv6-set-tee-times", "f", "server", 88, 0}, { "abandon-lease-time", "T", "server", 89, 0}, { "use-eui-64", "f", "server", 90, 0}, { "check-secs-byte-order", "f", "server", 91, 0}, { "persist-eui-64-leases", "f", "server", 92, 0}, { "ddns-dual-stack-mixed-mode", "f", "server", 93, 0}, { "ddns-guard-id-must-match", "f", "server", 94, 0}, { "ddns-other-guard-is-dynamic", "f", "server", 95, 0}, { "release-on-roam", "f", "server", 96, 0}, { "local-address6", "6", "server", 97, 0}, { "bind-local-address6", "f", "server", 98, 0}, { "ping-cltt-secs", "T", "server", 99, 0}, { "ping-timeout-ms", "T", "server", 100, 0}, { NULL, NULL, NULL, 0, 0 } }; void spaces_init(void) { struct space_def *def; struct space *space; TAILQ_INIT(&spaces); /* Fill spaces */ for (def = space_defs; def->name != NULL; def++) { space = (struct space *)malloc(sizeof(*space)); assert(space != NULL); memset(space, 0, sizeof(*space)); space->old = def->old; space->name = def->name; space->status = def->status; TAILQ_INSERT_TAIL(&spaces, space); } } void options_init(void) { struct option_def *def; struct option *option; TAILQ_INIT(&options); /* Fill DHCPv4 options */ for (def = options4; def->name != NULL; def++) { option = (struct option *)malloc(sizeof(*option)); assert(option != NULL); memset(option, 0, sizeof(*option)); option->old = def->name; switch (def->code) { case 5: option->name = "name-servers"; break; case 62: option->name = "nwip-domain-name"; break; case 64: option->name = "nisplus-domain-name"; break; case 67: option->name = "boot-file-name"; break; case 82: option->name = "dhcp-agent-options"; break; case 93: option->name = "client-system"; break; case 94: option->name = "client-ndi"; break; case 97: option->name = "uuid-guid"; break; case 124: option->name = "vivco-suboptions"; break; case 125: option->name = "vivso-suboptions"; break; default: option->name = def->name; } option->format = def->format; option->space = space_lookup(def->space); assert(option->space != NULL); option->code = def->code; option->status = def->status; TAILQ_INSERT_TAIL(&options, option); } /* Fill DHCPv6 options */ for (def = options6; def->name != NULL; def++) { option = (struct option *)malloc(sizeof(*option)); assert(option != NULL); memset(option, 0, sizeof(*option)); option->old = def->name; switch (def->code) { case 1: option->name = "clientid"; break; case 2: option->name = "serverid"; break; case 5: option->name = "iaaddr"; break; case 21: option->name = "sip-server-dns"; break; case 22: option->name = "sip-server-addr"; break; case 23: option->name = "dns-servers"; break; case 26: option->name = "iaprefix"; break; case 32: option->name = "information-refresh-time"; break; case 33: option->name = "bcms-server-dns"; break; case 34: option->name = "bcms-server-addr "; break; case 39: option->name = "client-fqdn"; break; case 87: option->name = "dhcpv4-message"; break; case 88: option->name = "dhcp4o6-server-addr"; break; default: option->name = def->name; break; } option->format = def->format; option->space = space_lookup(def->space); assert(option->space != NULL); option->code = def->code; option->status = def->status; TAILQ_INSERT_TAIL(&options, option); } /* Fill agent options */ for (def = agents; def->name != NULL; def++) { option = (struct option *)malloc(sizeof(*option)); assert(option != NULL); memset(option, 0, sizeof(*option)); option->old = def->name; option->name = def->name; option->format = def->format; option->space = space_lookup(def->space); assert(option->space != NULL); option->code = def->code; option->status = def->status; TAILQ_INSERT_TAIL(&options, option); } /* Fill server config options */ for (def = configs; def->name != NULL; def++) { option = (struct option *)malloc(sizeof(*option)); assert(option != NULL); memset(option, 0, sizeof(*option)); option->old = def->name; option->name = def->name; option->format = def->format; option->space = space_lookup(def->space); assert(option->space != NULL); option->code = def->code; option->status = def->status; TAILQ_INSERT_TAIL(&options, option); } } struct space * space_lookup(const char *name) { struct space *space; TAILQ_FOREACH(space, &spaces) { if (space->status == isc_dhcp_unknown) continue; if (strcmp(name, space->old) == 0) return space; } return NULL; } struct option * option_lookup_name(const char *space, const char *name) { struct space *universe; struct option *option; universe = space_lookup(space); if (universe == NULL) return NULL; TAILQ_FOREACH(option, &options) { if (option->status == isc_dhcp_unknown) continue; if (universe != option->space) continue; if (strcmp(name, option->old) == 0) return option; } return NULL; } struct option * kea_lookup_name(const char *space, const char *name) { struct space *universe; struct option *option; TAILQ_FOREACH(universe, &spaces) { if (universe->status == kea_unknown) continue; if (strcmp(name, universe->name) == 0) break; } if (universe == NULL) return NULL; TAILQ_FOREACH(option, &options) { if (option->status == kea_unknown) continue; if (universe != option->space) continue; if (strcmp(name, option->name) == 0) return option; } return NULL; } struct option * option_lookup_code(const char *space, unsigned code) { struct space *universe; struct option *option; universe = space_lookup(space); if (universe == NULL) return NULL; TAILQ_FOREACH(option, &options) { if (universe != option->space) continue; if (code == option->code) return option; } return NULL; } void push_space(struct space *space) { space->status = dynamic; TAILQ_INSERT_TAIL(&spaces, space); } void push_option(struct option *option) { assert(option->space != NULL); option->old = option->name; option->status = dynamic; TAILQ_INSERT_TAIL(&options, option); } void add_option_data(struct element *src, struct element *dst) { struct string *sspace; struct element *scode; struct element *name; struct option *option; size_t i; sspace = stringValue(mapGet(src, "space")); scode = mapGet(src, "code"); name = mapGet(src, "name"); assert((scode != NULL) || (name != NULL)); /* We'll use the code so fill it even it should always be available */ if (scode == NULL) { option = kea_lookup_name(sspace->content, stringValue(name)->content); assert(option != NULL); scode = createInt(option->code); mapSet(src, scode, "code"); } assert(intValue(scode) != 0); for (i = 0; i < listSize(dst); i++) { struct element *od; struct element *space; struct element *code; od = listGet(dst, i); space = mapGet(od, "space"); if (!eqString(sspace, stringValue(space))) continue; code = mapGet(od, "code"); if (code == NULL) { name = mapGet(od, "name"); assert(name != NULL); option = kea_lookup_name(sspace->content, stringValue(name)->content); assert(option != NULL); code = createInt(option->code); mapSet(od, code, "code"); } /* check if the option is already present */ if (intValue(scode) == intValue(code)) return; } listPush(dst, copy(src)); } void merge_option_data(struct element *src, struct element *dst) { struct element *od; size_t i; for (i = 0; i < listSize(src); i++) { od = listGet(src, i); add_option_data(od, dst); } } struct comments * get_config_comments(unsigned code) { static struct comments comments; struct comment *comment = NULL; TAILQ_INIT(&comments); switch (code) { case 4: /* dynamic-bootp-lease-cutoff */ case 5: /* dynamic-bootp-lease-length */ case 6: /* boot-unknown-clients */ case 7: /* dynamic-bootp */ case 8: /* allow-bootp */ no_bootp: comment = createComment("/// bootp protocol is not supported"); TAILQ_INSERT_TAIL(&comments, comment); break; case 9: /* allow-booting */ comment = createComment("/// allow-booting is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// no concrete usage known?"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #239"); TAILQ_INSERT_TAIL(&comments, comment); break; case 10: /* one-lease-per-client */ comment = createComment("/// one-lease-per-client is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #238"); TAILQ_INSERT_TAIL(&comments, comment); break; case 11: /* get-lease-hostnames */ comment = createComment("/// get-lease-hostnames is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #240"); TAILQ_INSERT_TAIL(&comments, comment); break; case 12: /* use-host-decl-names */ comment = createComment("/// use-host-decl-names defaults " "to always on"); TAILQ_INSERT_TAIL(&comments, comment); break; case 13: /* use-lease-addr-for-default-route */ comment = createComment("/// use-lease-addr-for-default-route " "is obsolete"); TAILQ_INSERT_TAIL(&comments, comment); break; case 14: /* min-secs */ comment = createComment("/// min-secs is not (yet?) " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #223"); TAILQ_INSERT_TAIL(&comments, comment); break; case 20: /* always-reply-rfc1048 */ goto no_bootp; case 22: /* always-broadcast */ comment = createComment("/// always-broadcast is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #241"); TAILQ_INSERT_TAIL(&comments, comment); break; case 24: /* ddns-hostname */ comment = createComment("/// ddns-hostname is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Please use hostname in a " "host reservation instead"); TAILQ_INSERT_TAIL(&comments, comment); break; case 25: /* ddns-rev-domainname */ comment = createComment("/// ddns-rev-domainname is an " "obsolete (so not supported) feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 26: /* lease-file-name */ comment = createComment("/// lease-file-name is an internal " "ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 27: /* pid-file-name */ comment = createComment("/// pid-file-nam is an internal " "ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 28: /* duplicates */ comment = createComment("/// duplicates is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea model is different (and " "stricter)"); TAILQ_INSERT_TAIL(&comments, comment); break; case 29: /* declines */ comment = createComment("/// declines is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea honors decline messages " " and holds address for " "decline-probation-period"); TAILQ_INSERT_TAIL(&comments, comment); break; case 31: /* omapi-port */ comment = createComment("/// omapi-port is an internal " "ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 32: /* local-port */ comment = createComment("/// local-port is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// command line -p parameter " "should be used instead"); TAILQ_INSERT_TAIL(&comments, comment); break; case 33: /* limited-broadcast-address */ comment = createComment("/// limited-broadcast-address " "is not (yet?) supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #224"); TAILQ_INSERT_TAIL(&comments, comment); break; case 34: /* remote-port */ comment = createComment("/// remote-port is a not portable " "(so not supported) feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 35: /* local-address */ comment = createComment("/// local-address is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea equivalent feature is " "to specify an interface address"); TAILQ_INSERT_TAIL(&comments, comment); break; case 36: /* omapi-key */ comment = createComment("/// omapi-key is an internal " "ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 37: /* stash-agent-options */ comment = createComment("/// stash-agent-options is not " "(yet?) supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #218"); TAILQ_INSERT_TAIL(&comments, comment); break; case 38: /* ddns-ttl */ comment = createComment("/// ddns-ttl is a D2 not (yet?) " "supported feature"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #225"); TAILQ_INSERT_TAIL(&comments, comment); break; case 40: /* client-updates */ comment = createComment("/// ddns-ttl client-updates is " "not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea model is very different"); TAILQ_INSERT_TAIL(&comments, comment); break; case 41: /* update-optimization */ comment = createComment("/// update-optimization is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea follows RFC 4702"); TAILQ_INSERT_TAIL(&comments, comment); break; case 42: /* ping-check */ comment = createComment("/// ping-check is not supported"); TAILQ_INSERT_TAIL(&comments, comment); no_ping: comment = createComment("/// Kea has no ping probing"); TAILQ_INSERT_TAIL(&comments, comment); break; case 43: /* update-static-leases */ comment = createComment("/// update-static-leases is an " "obsolete feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 44: /* log-facility */ comment = createComment("/// log-facility is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Please use the " "KEA_LOGGER_DESTINATION environment " "variable instead"); TAILQ_INSERT_TAIL(&comments, comment); break; case 45: /* do-forward-updates */ comment = createComment("/// do-forward-updates is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); ddns_updates: comment = createComment("/// Kea model is equivalent but " "different"); TAILQ_INSERT_TAIL(&comments, comment); break; case 46: /* ping-timeout */ comment = createComment("/// ping-timeout is not supported"); TAILQ_INSERT_TAIL(&comments, comment); goto no_ping; case 47: /* infinite-is-reserved */ comment = createComment("/// infinite-is-reserved is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea does not support reserved " "leases"); TAILQ_INSERT_TAIL(&comments, comment); break; case 48: /* update-conflict-detection */ comment = createComment("/// update-conflict-detection is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// DDNS is handled by the D2 " "server using a dedicated config"); TAILQ_INSERT_TAIL(&comments, comment); break; case 49: /* leasequery */ comment = createComment("/// leasequery is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea does not (yet) support " "the leasequery protocol"); TAILQ_INSERT_TAIL(&comments, comment); break; case 50: /* adaptive-lease-time-threshold */ comment = createComment("/// adaptive-lease-time-threshold is " "not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #226"); TAILQ_INSERT_TAIL(&comments, comment); break; case 51: /* do-reverse-updates */ comment = createComment("/// do-reverse-updates is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); goto ddns_updates; case 52: /* fqdn-reply */ comment = createComment("/// fqdn-reply is an obsolete " "feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 54: /* dhcpv6-lease-file-name */ comment = createComment("/// dhcpv6-lease-file-name " "is an internal ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 55: /* dhcpv6-pid-file-name */ comment = createComment("/// dhcpv6-pid-file-name " "is an internal ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 56: /* limit-addrs-per-ia */ comment = createComment("/// limit-addrs-per-ia " "is not (yet?) supported"); TAILQ_INSERT_TAIL(&comments, comment); limit_resources: comment = createComment("/// Reference Kea #227"); TAILQ_INSERT_TAIL(&comments, comment); break; case 57: /* limit-prefs-per-ia */ comment = createComment("/// limit-prefs-per-ia" "is not (yet?) supported"); TAILQ_INSERT_TAIL(&comments, comment); goto limit_resources; case 58: /* delayed-ack */ case 59: /* max-ack-delay */ comment = createComment("/// delayed ack no supported"); TAILQ_INSERT_TAIL(&comments, comment); break; case 78: /* dhcp-cache-threshold */ comment = createComment("/// dhcp-cache-threshold " "is not (yet?) supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #228"); TAILQ_INSERT_TAIL(&comments, comment); break; case 79: /* dont-use-fsync */ comment = createComment("/// dont-use-fsync is an internal " "ISC DHCP feature"); TAILQ_INSERT_TAIL(&comments, comment); break; case 80: /* ddns-local-address4 */ comment = createComment("/// ddns-local-address4 is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); d2_ip_address: comment = createComment("/// Kea D2 equivalent config is " "ip-address"); TAILQ_INSERT_TAIL(&comments, comment); break; case 81: /* ddns-local-address6 */ comment = createComment("/// ddns-local-address6 is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); goto d2_ip_address; case 83: /* log-threshold-low */ comment = createComment("/// log-threshold-low is not (yet?) " "supported"); TAILQ_INSERT_TAIL(&comments, comment); log_threshold: comment = createComment("/// Reference Kea #222"); TAILQ_INSERT_TAIL(&comments, comment); break; case 84: /* log-threshold-high */ comment = createComment("/// log-threshold-high is not (yet?) " "supported"); TAILQ_INSERT_TAIL(&comments, comment); goto log_threshold; case 86: /* server-id-check */ comment = createComment("/// server-id-check is not (yet?) " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #242"); TAILQ_INSERT_TAIL(&comments, comment); break; case 87: /* prefix-length-mode */ comment = createComment("/// prefix-length-mode is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea model is different (and " "simpler?)"); TAILQ_INSERT_TAIL(&comments, comment); break; case 88: /* dhcpv6-set-tee-times */ comment = createComment("/// dhcpv6-set-tee-times is a " "transitional (so not supported) " "feature"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// T1 and T2 are .5 and .8 times " "preferred-lifetime"); TAILQ_INSERT_TAIL(&comments, comment); break; case 89: /* abandon-lease-time */ comment = createComment("/// abandon-lease-time is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea support equivalent (and " "richer) expired-lease-processing " "and decline-probation-period"); TAILQ_INSERT_TAIL(&comments, comment); break; case 90: /* use-eui-64 */ comment = createComment("/// EUI-64 is not (yet) supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #265"); TAILQ_INSERT_TAIL(&comments, comment); break; case 96: /* release-on-roam */ comment = createComment("/// release-on-roam is not (yet) " "supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Reference Kea #266"); TAILQ_INSERT_TAIL(&comments, comment); break; case 97: /* local-address6 */ comment = createComment("/// local-address6 is not supported"); TAILQ_INSERT_TAIL(&comments, comment); comment = createComment("/// Kea equivalent feature is " "to specify an interface address"); TAILQ_INSERT_TAIL(&comments, comment); break; case 99: /* ping-cltt-secs */ comment = createComment("/// ping-cltt-secs is not supported"); TAILQ_INSERT_TAIL(&comments, comment); goto no_ping; case 100: /* ping-timeout-ms */ comment = createComment("/// ping-timeout-ms is not " "supported"); TAILQ_INSERT_TAIL(&comments, comment); goto no_ping; } return &comments; } const char * display_status(enum option_status status) { switch (status) { case kea_unknown: case special: return "known (unknown)"; case isc_dhcp_unknown: return "unknown (known)"; case known: return "known (known)"; case dynamic: return "dynamic (dynamic)"; default: return "??? (" "???" ")"; } }