"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/option.c" between
dnsmasq-2.80.tar.gz and dnsmasq-2.81.tar.xz

About: Dnsmasq is a lightweight caching DNS forwarder and DHCP server.

option.c  (dnsmasq-2.80):option.c  (dnsmasq-2.81.tar.xz)
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley /* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007. (at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
skipping to change at line 132 skipping to change at line 132
#define LOPT_CLVERBIND 311 #define LOPT_CLVERBIND 311
#define LOPT_MAXCTTL 312 #define LOPT_MAXCTTL 312
#define LOPT_AUTHZONE 313 #define LOPT_AUTHZONE 313
#define LOPT_AUTHSERV 314 #define LOPT_AUTHSERV 314
#define LOPT_AUTHTTL 315 #define LOPT_AUTHTTL 315
#define LOPT_AUTHSOA 316 #define LOPT_AUTHSOA 316
#define LOPT_AUTHSFS 317 #define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318 #define LOPT_AUTHPEER 318
#define LOPT_IPSET 319 #define LOPT_IPSET 319
#define LOPT_SYNTH 320 #define LOPT_SYNTH 320
#ifdef OPTION6_PREFIX_CLASS
#define LOPT_PREF_CLSS 321
#endif
#define LOPT_RELAY 323 #define LOPT_RELAY 323
#define LOPT_RA_PARAM 324 #define LOPT_RA_PARAM 324
#define LOPT_ADD_SBNET 325 #define LOPT_ADD_SBNET 325
#define LOPT_QUIET_DHCP 326 #define LOPT_QUIET_DHCP 326
#define LOPT_QUIET_DHCP6 327 #define LOPT_QUIET_DHCP6 327
#define LOPT_QUIET_RA 328 #define LOPT_QUIET_RA 328
#define LOPT_SEC_VALID 329 #define LOPT_SEC_VALID 329
#define LOPT_TRUST_ANCHOR 330 #define LOPT_TRUST_ANCHOR 330
#define LOPT_DNSSEC_DEBUG 331 #define LOPT_DNSSEC_DEBUG 331
#define LOPT_REV_SERV 332 #define LOPT_REV_SERV 332
skipping to change at line 169 skipping to change at line 166
#define LOPT_SCRIPT_ARP 347 #define LOPT_SCRIPT_ARP 347
#define LOPT_DHCPTTL 348 #define LOPT_DHCPTTL 348
#define LOPT_TFTP_MTU 349 #define LOPT_TFTP_MTU 349
#define LOPT_REPLY_DELAY 350 #define LOPT_REPLY_DELAY 350
#define LOPT_RAPID_COMMIT 351 #define LOPT_RAPID_COMMIT 351
#define LOPT_DUMPFILE 352 #define LOPT_DUMPFILE 352
#define LOPT_DUMPMASK 353 #define LOPT_DUMPMASK 353
#define LOPT_UBUS 354 #define LOPT_UBUS 354
#define LOPT_NAME_MATCH 355 #define LOPT_NAME_MATCH 355
#define LOPT_CAA 356 #define LOPT_CAA 356
#define LOPT_SHARED_NET 357
#define LOPT_IGNORE_CLID 358
#define LOPT_SINGLE_PORT 359
#define LOPT_SCRIPT_TIME 360
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
#else #else
static const struct myoption opts[] = static const struct myoption opts[] =
#endif #endif
{ {
{ "version", 0, 0, 'v' }, { "version", 0, 0, 'v' },
{ "no-hosts", 0, 0, 'h' }, { "no-hosts", 0, 0, 'h' },
{ "no-poll", 0, 0, 'n' }, { "no-poll", 0, 0, 'n' },
skipping to change at line 240 skipping to change at line 241
{ "dhcp-ignore", 1, 0, 'J' }, { "dhcp-ignore", 1, 0, 'J' },
{ "edns-packet-max", 1, 0, 'P' }, { "edns-packet-max", 1, 0, 'P' },
{ "keep-in-foreground", 0, 0, 'k' }, { "keep-in-foreground", 0, 0, 'k' },
{ "dhcp-authoritative", 0, 0, 'K' }, { "dhcp-authoritative", 0, 0, 'K' },
{ "srv-host", 1, 0, 'W' }, { "srv-host", 1, 0, 'W' },
{ "localise-queries", 0, 0, 'y' }, { "localise-queries", 0, 0, 'y' },
{ "txt-record", 1, 0, 'Y' }, { "txt-record", 1, 0, 'Y' },
{ "caa-record", 1, 0 , LOPT_CAA }, { "caa-record", 1, 0 , LOPT_CAA },
{ "dns-rr", 1, 0, LOPT_RR }, { "dns-rr", 1, 0, LOPT_RR },
{ "enable-dbus", 2, 0, '1' }, { "enable-dbus", 2, 0, '1' },
{ "enable-ubus", 0, 0, LOPT_UBUS }, { "enable-ubus", 2, 0, LOPT_UBUS },
{ "bootp-dynamic", 2, 0, '3' }, { "bootp-dynamic", 2, 0, '3' },
{ "dhcp-mac", 1, 0, '4' }, { "dhcp-mac", 1, 0, '4' },
{ "no-ping", 0, 0, '5' }, { "no-ping", 0, 0, '5' },
{ "dhcp-script", 1, 0, '6' }, { "dhcp-script", 1, 0, '6' },
{ "conf-dir", 1, 0, '7' }, { "conf-dir", 1, 0, '7' },
{ "log-facility", 1, 0 ,'8' }, { "log-facility", 1, 0 ,'8' },
{ "leasefile-ro", 0, 0, '9' }, { "leasefile-ro", 0, 0, '9' },
{ "script-on-renewal", 0, 0, LOPT_SCRIPT_TIME},
{ "dns-forward-max", 1, 0, '0' }, { "dns-forward-max", 1, 0, '0' },
{ "clear-on-reload", 0, 0, LOPT_RELOAD }, { "clear-on-reload", 0, 0, LOPT_RELOAD },
{ "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES }, { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
{ "enable-tftp", 2, 0, LOPT_TFTP }, { "enable-tftp", 2, 0, LOPT_TFTP },
{ "tftp-secure", 0, 0, LOPT_SECURE }, { "tftp-secure", 0, 0, LOPT_SECURE },
{ "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL }, { "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL },
{ "tftp-unique-root", 2, 0, LOPT_APREF }, { "tftp-unique-root", 2, 0, LOPT_APREF },
{ "tftp-root", 1, 0, LOPT_PREFIX }, { "tftp-root", 1, 0, LOPT_PREFIX },
{ "tftp-max", 1, 0, LOPT_TFTP_MAX }, { "tftp-max", 1, 0, LOPT_TFTP_MAX },
{ "tftp-mtu", 1, 0, LOPT_TFTP_MTU }, { "tftp-mtu", 1, 0, LOPT_TFTP_MTU },
{ "tftp-lowercase", 0, 0, LOPT_TFTP_LC }, { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
{ "tftp-single-port", 0, 0, LOPT_SINGLE_PORT },
{ "ptr-record", 1, 0, LOPT_PTR }, { "ptr-record", 1, 0, LOPT_PTR },
{ "naptr-record", 1, 0, LOPT_NAPTR }, { "naptr-record", 1, 0, LOPT_NAPTR },
{ "bridge-interface", 1, 0 , LOPT_BRIDGE }, { "bridge-interface", 1, 0 , LOPT_BRIDGE },
{ "shared-network", 1, 0, LOPT_SHARED_NET },
{ "dhcp-option-force", 1, 0, LOPT_FORCE }, { "dhcp-option-force", 1, 0, LOPT_FORCE },
{ "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK }, { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
{ "log-dhcp", 0, 0, LOPT_LOG_OPTS }, { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
{ "log-async", 2, 0, LOPT_MAX_LOGS }, { "log-async", 2, 0, LOPT_MAX_LOGS },
{ "dhcp-circuitid", 1, 0, LOPT_CIRCUIT }, { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
{ "dhcp-remoteid", 1, 0, LOPT_REMOTE }, { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
{ "dhcp-subscrid", 1, 0, LOPT_SUBSCR }, { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
{ "interface-name", 1, 0, LOPT_INTNAME }, { "interface-name", 1, 0, LOPT_INTNAME },
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST }, { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS }, { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
skipping to change at line 325 skipping to change at line 329
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS }, { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ "auth-peer", 1, 0, LOPT_AUTHPEER }, { "auth-peer", 1, 0, LOPT_AUTHPEER },
{ "ipset", 1, 0, LOPT_IPSET }, { "ipset", 1, 0, LOPT_IPSET },
{ "synth-domain", 1, 0, LOPT_SYNTH }, { "synth-domain", 1, 0, LOPT_SYNTH },
{ "dnssec", 0, 0, LOPT_SEC_VALID }, { "dnssec", 0, 0, LOPT_SEC_VALID },
{ "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR }, { "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG }, { "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
{ "dnssec-check-unsigned", 2, 0, LOPT_DNSSEC_CHECK }, { "dnssec-check-unsigned", 2, 0, LOPT_DNSSEC_CHECK },
{ "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME }, { "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
{ "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP }, { "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP },
#ifdef OPTION6_PREFIX_CLASS
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
#endif
{ "dhcp-relay", 1, 0, LOPT_RELAY }, { "dhcp-relay", 1, 0, LOPT_RELAY },
{ "ra-param", 1, 0, LOPT_RA_PARAM }, { "ra-param", 1, 0, LOPT_RA_PARAM },
{ "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP }, { "quiet-dhcp", 0, 0, LOPT_QUIET_DHCP },
{ "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 }, { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
{ "quiet-ra", 0, 0, LOPT_QUIET_RA }, { "quiet-ra", 0, 0, LOPT_QUIET_RA },
{ "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT }, { "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT },
{ "script-arp", 0, 0, LOPT_SCRIPT_ARP }, { "script-arp", 0, 0, LOPT_SCRIPT_ARP },
{ "dhcp-ttl", 1, 0 , LOPT_DHCPTTL }, { "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
{ "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY }, { "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY },
{ "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT }, { "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT },
{ "dumpfile", 1, 0, LOPT_DUMPFILE }, { "dumpfile", 1, 0, LOPT_DUMPFILE },
{ "dumpmask", 1, 0, LOPT_DUMPMASK }, { "dumpmask", 1, 0, LOPT_DUMPMASK },
{ "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
#define ARG_DUP OPT_LAST #define ARG_DUP OPT_LAST
#define ARG_ONE OPT_LAST + 1 #define ARG_ONE OPT_LAST + 1
#define ARG_USED_CL OPT_LAST + 2 #define ARG_USED_CL OPT_LAST + 2
#define ARG_USED_FILE OPT_LAST + 3 #define ARG_USED_FILE OPT_LAST + 3
static struct { static struct {
int opt; int opt;
skipping to change at line 428 skipping to change at line 430
{ 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL }, { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL },
{ 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE }, { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
{ 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leas es (defaults to %s)."), "&" }, { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leas es (defaults to %s)."), "&" },
{ 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the inter face a query was sent to."), NULL }, { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the inter face a query was sent to."), NULL },
{ 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record.") , NULL }, { 'Y', ARG_DUP, "<name>,<txt>[,<txt]", gettext_noop("Specify TXT DNS record.") , NULL },
{ LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record." ), NULL }, { LOPT_PTR, ARG_DUP, "<name>,<target>", gettext_noop("Specify PTR DNS record." ), NULL },
{ LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL }, { LOPT_INTNAME, ARG_DUP, "<name>,<interface>", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
{ 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL }, { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE }, { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
{ '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for se tting upstream servers, etc."), NULL }, { '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for se tting upstream servers, etc."), NULL },
{ LOPT_UBUS, OPT_UBUS, NULL, gettext_noop("Enable the UBus interface."), NULL }, { LOPT_UBUS, ARG_ONE, "[=<busname>]", gettext_noop("Enable the UBus interface. "), NULL },
{ '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this inter face, only provide DNS."), NULL }, { '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this inter face, only provide DNS."), NULL },
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address alloca tion for bootp."), NULL }, { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address alloca tion for bootp."), NULL },
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL }, { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
{ LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL }, { LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
{ LOPT_SHARED_NET, ARG_DUP, "<iface>|<addr>,<addr>", gettext_noop("Specify ext ra networks sharing a broadcast domain for DHCP"), NULL},
{ '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL }, { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
{ '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease crea tion and destruction."), NULL }, { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease crea tion and destruction."), NULL },
{ LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lea se creation and destruction."), NULL }, { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lea se creation and destruction."), NULL },
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script s as this user."), NULL }, { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script s as this user."), NULL },
{ LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with c hanges to local ARP table."), NULL }, { LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with c hanges to local ARP table."), NULL },
{ '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL }, { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
{ '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL }, { '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL }, { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
{ '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS qu eries. (defaults to %s)"), "!" }, { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS qu eries. (defaults to %s)"), "!" },
{ LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE }, { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
skipping to change at line 455 skipping to change at line 458
{ LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated re ad-only TFTP server."), NULL }, { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated re ad-only TFTP server."), NULL },
{ LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL }, { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
{ LOPT_APREF, ARG_DUP, "[=ip|mac]", gettext_noop("Add client IP or hardware ad dress to tftp-root."), NULL }, { LOPT_APREF, ARG_DUP, "[=ip|mac]", gettext_noop("Add client IP or hardware ad dress to tftp-root."), NULL },
{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL }, { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
{ LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate th e service if TFTP directories are inaccessible."), NULL }, { LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate th e service if TFTP directories are inaccessible."), NULL },
{ LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurr ent TFTP transfers (defaults to %s)."), "#" }, { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurr ent TFTP transfers (defaults to %s)."), "#" },
{ LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum MTU to use for TF TP transfers."), NULL }, { LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum MTU to use for TF TP transfers."), NULL },
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksi ze extension."), NULL }, { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksi ze extension."), NULL },
{ LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to low ercase"), NULL }, { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to low ercase"), NULL },
{ LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL }, { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
{ LOPT_SINGLE_PORT, OPT_SINGLE_PORT, NULL, gettext_noop("Use only one port for TFTP server."), NULL },
{ LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL }, { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
{ LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL }, { LOPT_MAX_LOGS, ARG_ONE, "[=<integer>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
{ LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter p rivate IP ranges when resolving."), NULL }, { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter p rivate IP ranges when resolving."), NULL },
{ LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127 .0.0.0/8, for RBL servers."), NULL }, { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127 .0.0.0/8, for RBL servers."), NULL },
{ LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind prot ection on this domain."), NULL }, { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind prot ection on this domain."), NULL },
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL }, { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
{ LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL }, { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
{ LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL }, { LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL },
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL }, { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS recor d."), NULL }, { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS recor d."), NULL },
skipping to change at line 480 skipping to change at line 484
{ LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<iface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL}, { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<iface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL }, { LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to sen d to PXE clients."), NULL }, { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to sen d to PXE clients."), NULL },
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu ."), NULL }, { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu ."), NULL },
{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL }, { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
{ LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC a ddress to forwarded DNS queries."), NULL }, { LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC a ddress to forwarded DNS queries."), NULL },
{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specifie d IP subnet to forwarded DNS queries."), NULL }, { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specifie d IP subnet to forwarded DNS queries."), NULL },
{ LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client identification to f orwarded DNS queries."), NULL }, { LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client identification to f orwarded DNS queries."), NULL },
{ LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation r esults from upstream nameservers."), NULL }, { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation r esults from upstream nameservers."), NULL },
{ LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate seq uential IP addresses to DHCP clients."), NULL }, { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate seq uential IP addresses to DHCP clients."), NULL },
{ LOPT_IGNORE_CLID, OPT_IGNORE_CLID, NULL, gettext_noop("Ignore client identif ier option sent by DHCP clients."), NULL },
{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mar k from queries to upstream connections."), NULL }, { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mar k from queries to upstream connections."), NULL },
{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do the ir own DDNS updates."), NULL }, { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do the ir own DDNS updates."), NULL },
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfac es doing DHCPv6"), NULL }, { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfac es doing DHCPv6"), NULL },
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-typ e DHCPv6 server DUID"), NULL }, { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-typ e DHCPv6 server DUID"), NULL },
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify ho st (A/AAAA and PTR) records"), NULL }, { LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify ho st (A/AAAA and PTR) records"), NULL },
{ LOPT_CAA, ARG_DUP, "<name>,<flags>,<tag>,<value>", gettext_noop("Specify cer tification authority authorization record"), NULL }, { LOPT_CAA, ARG_DUP, "<name>,<flags>,<tag>,<value>", gettext_noop("Specify cer tification authority authorization record"), NULL },
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbit rary DNS resource record"), NULL }, { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbit rary DNS resource record"), NULL },
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in us e - check for new interfaces"), NULL }, { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in us e - check for new interfaces"), NULL },
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL }, { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to ex port to global DNS"), NULL }, { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to ex port to global DNS"), NULL },
skipping to change at line 502 skipping to change at line 507
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritati ve nameservers for forward domains"), NULL }, { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritati ve nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL }, { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Spe cify ipsets to which matching domains should be added"), NULL }, { LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Spe cify ipsets to which matching domains should be added"), NULL },
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL }, { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC valida tion"), NULL }, { LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC valida tion"), NULL },
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL }, { LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream ch ecking for DNSSEC debugging."), NULL }, { LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream ch ecking for DNSSEC debugging."), NULL },
{ LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSE C are in unsigned zones."), NULL }, { LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSE C are in unsigned zones."), NULL },
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC si gnature timestamps until first cache-reload"), NULL }, { LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC si gnature timestamps until first cache-reload"), NULL },
{ LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL }, { LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 pre
fix class"), NULL },
#endif
{ LOPT_RA_PARAM, ARG_DUP, "<iface>,[mtu:<value>|<interface>|off,][<prio>,]<int val>[,<lifetime>]", gettext_noop("Set MTU, priority, resend-interval and router- lifetime"), NULL }, { LOPT_RA_PARAM, ARG_DUP, "<iface>,[mtu:<value>|<interface>|off,][<prio>,]<int val>[,<lifetime>]", gettext_noop("Set MTU, priority, resend-interval and router- lifetime"), NULL },
{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP ."), NULL }, { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP ."), NULL },
{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DH CPv6."), NULL }, { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DH CPv6."), NULL },
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL }, { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries on ly from directly-connected networks."), NULL }, { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries on ly from directly-connected networks."), NULL },
{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops."), NULL }, { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops."), NULL },
{ LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses co ntaining ipaddr."), NULL }, { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses co ntaining ipaddr."), NULL },
{ LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL }, { LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL },
{ LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL }, { LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
{ LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapi d Commit option."), NULL }, { LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapi d Commit option."), NULL },
{ LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump fi le"), NULL }, { LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump fi le"), NULL },
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL }, { LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
{ LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
/* We hide metacharacters in quoted strings by mapping them into the ASCII contr ol /* We hide metacharacters in quoted strings by mapping them into the ASCII contr ol
character space. Note that the \0, \t \b \r \033 and \n characters are carefu lly placed in the character space. Note that the \0, \t \b \r \033 and \n characters are carefu lly placed in the
following sequence so that they map to themselves: it is therefore possible t o call following sequence so that they map to themselves: it is therefore possible t o call
unhide_metas repeatedly on string without breaking things. unhide_metas repeatedly on string without breaking things.
The transformation gets undone by opt_canonicalise, atoi_check and opt_string _alloc, and a The transformation gets undone by opt_canonicalise, atoi_check and opt_string _alloc, and a
couple of other places. couple of other places.
Note that space is included here so that Note that space is included here so that
skipping to change at line 579 skipping to change at line 582
ret = whine_malloc(size); ret = whine_malloc(size);
if (!ret) if (!ret)
longjmp(mem_jmp, 1); longjmp(mem_jmp, 1);
} }
else else
ret = safe_malloc(size); ret = safe_malloc(size);
return ret; return ret;
} }
static char *opt_string_alloc(char *cp) static char *opt_string_alloc(const char *cp)
{ {
char *ret = NULL; char *ret = NULL;
size_t len;
if (cp && strlen(cp) != 0) if (cp && (len = strlen(cp)) != 0)
{ {
ret = opt_malloc(strlen(cp)+1); ret = opt_malloc(len+1);
strcpy(ret, cp); memcpy(ret, cp, len+1);
/* restore hidden metachars */ /* restore hidden metachars */
unhide_metas(ret); unhide_metas(ret);
} }
return ret; return ret;
} }
/* find next comma, split string with zero and eliminate spaces. /* find next comma, split string with zero and eliminate spaces.
return start of string following comma */ return start of string following comma */
skipping to change at line 760 skipping to change at line 764
for (j = 0; tab[j].handle; j++) for (j = 0; tab[j].handle; j++)
if (tab[j].handle == *(usage[i].arg)) if (tab[j].handle == *(usage[i].arg))
sprintf(buff, "%d", tab[j].val); sprintf(buff, "%d", tab[j].val);
} }
printf(_(usage[i].desc), buff); printf(_(usage[i].desc), buff);
printf("\n"); printf("\n");
} }
} }
#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0) #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
#define ret_err_free(x,m) do { strcpy(errstr, (x)); free((m)); return 0; } while
(0)
#define goto_err(x) do { strcpy(errstr, (x)); goto on_error; } while (0)
static char *parse_mysockaddr(char *arg, union mysockaddr *addr) static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
{ {
if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0) if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
addr->sa.sa_family = AF_INET; addr->sa.sa_family = AF_INET;
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
addr->sa.sa_family = AF_INET6; addr->sa.sa_family = AF_INET6;
#endif
else else
return _("bad address"); return _("bad address");
return NULL; return NULL;
} }
char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a ddr, char *interface, int *flags) char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a ddr, char *interface, int *flags)
{ {
int source_port = 0, serv_port = NAMESERVER_PORT; int source_port = 0, serv_port = NAMESERVER_PORT;
char *portno, *source; char *portno, *source;
char *interface_opt = NULL; char *interface_opt = NULL;
#ifdef HAVE_IPV6
int scope_index = 0; int scope_index = 0;
char *scope_id; char *scope_id;
#endif
if (!arg || strlen(arg) == 0) if (!arg || strlen(arg) == 0)
{ {
*flags |= SERV_NO_ADDR; *flags |= SERV_NO_ADDR;
*interface = 0; *interface = 0;
return NULL; return NULL;
} }
if ((source = split_chr(arg, '@')) && /* is there a source. */ if ((source = split_chr(arg, '@')) && /* is there a source. */
(portno = split_chr(source, '#')) && (portno = split_chr(source, '#')) &&
!atoi_check16(portno, &source_port)) !atoi_check16(portno, &source_port))
return _("bad port"); return _("bad port");
if ((portno = split_chr(arg, '#')) && /* is there a port no. */ if ((portno = split_chr(arg, '#')) && /* is there a port no. */
!atoi_check16(portno, &serv_port)) !atoi_check16(portno, &serv_port))
return _("bad port"); return _("bad port");
#ifdef HAVE_IPV6
scope_id = split_chr(arg, '%'); scope_id = split_chr(arg, '%');
#endif
if (source) { if (source) {
interface_opt = split_chr(source, '@'); interface_opt = split_chr(source, '@');
if (interface_opt) if (interface_opt)
{ {
#if defined(SO_BINDTODEVICE) #if defined(SO_BINDTODEVICE)
safe_strncpy(interface, interface_opt, IF_NAMESIZE); safe_strncpy(interface, interface_opt, IF_NAMESIZE);
#else #else
return _("interface binding not supported"); return _("interface binding not supported");
skipping to change at line 847 skipping to change at line 847
return _("interface can only be specified once"); return _("interface can only be specified once");
source_addr->in.sin_addr.s_addr = INADDR_ANY; source_addr->in.sin_addr.s_addr = INADDR_ANY;
safe_strncpy(interface, source, IF_NAMESIZE); safe_strncpy(interface, source, IF_NAMESIZE);
#else #else
return _("interface binding not supported"); return _("interface binding not supported");
#endif #endif
} }
} }
} }
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
{ {
if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0) if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0)
return _("bad interface name"); return _("bad interface name");
addr->in6.sin6_port = htons(serv_port); addr->in6.sin6_port = htons(serv_port);
addr->in6.sin6_scope_id = scope_index; addr->in6.sin6_scope_id = scope_index;
source_addr->in6.sin6_addr = in6addr_any; source_addr->in6.sin6_addr = in6addr_any;
source_addr->in6.sin6_port = htons(daemon->query_port); source_addr->in6.sin6_port = htons(daemon->query_port);
source_addr->in6.sin6_scope_id = 0; source_addr->in6.sin6_scope_id = 0;
skipping to change at line 882 skipping to change at line 881
return _("interface can only be specified once"); return _("interface can only be specified once");
source_addr->in6.sin6_addr = in6addr_any; source_addr->in6.sin6_addr = in6addr_any;
safe_strncpy(interface, source, IF_NAMESIZE); safe_strncpy(interface, source, IF_NAMESIZE);
#else #else
return _("interface binding not supported"); return _("interface binding not supported");
#endif #endif
} }
} }
} }
#endif
else else
return _("bad address"); return _("bad address");
return NULL; return NULL;
} }
static struct server *add_rev4(struct in_addr addr, int msize) static struct server *add_rev4(struct in_addr addr, int msize)
{ {
struct server *serv = opt_malloc(sizeof(struct server)); struct server *serv = opt_malloc(sizeof(struct server));
in_addr_t a = ntohl(addr.s_addr); in_addr_t a = ntohl(addr.s_addr);
skipping to change at line 913 skipping to change at line 911
case 24: case 24:
p += sprintf(p, "%d.", (a >> 8) & 0xff); p += sprintf(p, "%d.", (a >> 8) & 0xff);
/* fall through */ /* fall through */
case 16: case 16:
p += sprintf(p, "%d.", (a >> 16) & 0xff); p += sprintf(p, "%d.", (a >> 16) & 0xff);
/* fall through */ /* fall through */
case 8: case 8:
p += sprintf(p, "%d.", (a >> 24) & 0xff); p += sprintf(p, "%d.", (a >> 24) & 0xff);
break; break;
default: default:
free(serv->domain);
free(serv);
return NULL; return NULL;
} }
p += sprintf(p, "in-addr.arpa"); p += sprintf(p, "in-addr.arpa");
serv->flags = SERV_HAS_DOMAIN; serv->flags = SERV_HAS_DOMAIN;
serv->next = daemon->servers; serv->next = daemon->servers;
daemon->servers = serv; daemon->servers = serv;
return serv; return serv;
skipping to change at line 967 skipping to change at line 967
} }
static char *set_prefix(char *arg) static char *set_prefix(char *arg)
{ {
if (strstr(arg, "set:") == arg) if (strstr(arg, "set:") == arg)
return arg+4; return arg+4;
return arg; return arg;
} }
static struct dhcp_netid *dhcp_netid_create(const char *net, struct dhcp_netid *
next)
{
struct dhcp_netid *tt;
tt = opt_malloc(sizeof (struct dhcp_netid));
tt->net = opt_string_alloc(net);
tt->next = next;
return tt;
}
static void dhcp_netid_free(struct dhcp_netid *nid)
{
while (nid)
{
struct dhcp_netid *tmp = nid;
nid = nid->next;
free(tmp->net);
free(tmp);
}
}
/* Parse one or more tag:s before parameters.
* Moves arg to the end of tags. */
static struct dhcp_netid * dhcp_tags(char **arg)
{
struct dhcp_netid *id = NULL;
while (is_tag_prefix(*arg))
{
char *comma = split(*arg);
id = dhcp_netid_create((*arg)+4, id);
*arg = comma;
};
if (!*arg)
{
dhcp_netid_free(id);
id = NULL;
}
return id;
}
static void dhcp_netid_list_free(struct dhcp_netid_list *netid)
{
while (netid)
{
struct dhcp_netid_list *tmplist = netid;
netid = netid->next;
dhcp_netid_free(tmplist->list);
free(tmplist);
}
}
static void dhcp_config_free(struct dhcp_config *config)
{
if (config)
{
struct hwaddr_config *hwaddr = config->hwaddr;
while (hwaddr)
{
struct hwaddr_config *tmp = hwaddr;
hwaddr = hwaddr->next;
free(tmp);
}
dhcp_netid_list_free(config->netid);
dhcp_netid_free(config->filter);
if (config->flags & CONFIG_CLID)
free(config->clid);
#ifdef HAVE_DHCP6
if (config->flags & CONFIG_ADDR6)
{
struct addrlist *addr, *tmp;
for (addr = config->addr6; addr; addr = tmp)
{
tmp = addr->next;
free(addr);
}
}
#endif
free(config);
}
}
static void dhcp_context_free(struct dhcp_context *ctx)
{
if (ctx)
{
dhcp_netid_free(ctx->filter);
free(ctx->netid.net);
#ifdef HAVE_DHCP6
free(ctx->template_interface);
#endif
free(ctx);
}
}
static void dhcp_opt_free(struct dhcp_opt *opt)
{
if (opt->flags & DHOPT_VENDOR)
free(opt->u.vendor_class);
dhcp_netid_free(opt->netid);
free(opt->val);
free(opt);
}
/* This is too insanely large to keep in-line in the switch */ /* This is too insanely large to keep in-line in the switch */
static int parse_dhcp_opt(char *errstr, char *arg, int flags) static int parse_dhcp_opt(char *errstr, char *arg, int flags)
{ {
struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt)); struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
char lenchar = 0, *cp; char lenchar = 0, *cp;
int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots; int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
char *comma = NULL; char *comma = NULL;
struct dhcp_netid *np = NULL;
u16 opt_len = 0; u16 opt_len = 0;
int is6 = 0; int is6 = 0;
int option_ok = 0; int option_ok = 0;
new->len = 0; new->len = 0;
new->flags = flags; new->flags = flags;
new->netid = NULL; new->netid = NULL;
new->val = NULL; new->val = NULL;
new->opt = 0; new->opt = 0;
skipping to change at line 1061 skipping to change at line 1169
new->u.encap = atoi(arg+9); new->u.encap = atoi(arg+9);
new->flags |= DHOPT_RFC3925; new->flags |= DHOPT_RFC3925;
if (flags == DHOPT_MATCH) if (flags == DHOPT_MATCH)
{ {
option_ok = 1; option_ok = 1;
break; break;
} }
} }
else else
{ {
new->netid = opt_malloc(sizeof (struct dhcp_netid));
/* allow optional "net:" or "tag:" for consistency */ /* allow optional "net:" or "tag:" for consistency */
if (is_tag_prefix(arg)) const char *name = (is_tag_prefix(arg)) ? arg+4 : set_prefix(arg);
new->netid->net = opt_string_alloc(arg+4); new->netid = dhcp_netid_create(name, new->netid);
else
new->netid->net = opt_string_alloc(set_prefix(arg));
new->netid->next = np;
np = new->netid;
} }
arg = comma; arg = comma;
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
if (is6) if (is6)
{ {
if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE)) if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
ret_err(_("unsupported encapsulation for IPv6 option")); goto_err(_("unsupported encapsulation for IPv6 option"));
if (opt_len == 0 && if (opt_len == 0 &&
!(new->flags & DHOPT_RFC3925)) !(new->flags & DHOPT_RFC3925))
opt_len = lookup_dhcp_len(AF_INET6, new->opt); opt_len = lookup_dhcp_len(AF_INET6, new->opt);
} }
else else
#endif #endif
if (opt_len == 0 && if (opt_len == 0 &&
!(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925))) !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
opt_len = lookup_dhcp_len(AF_INET, new->opt); opt_len = lookup_dhcp_len(AF_INET, new->opt);
/* option may be missing with rfc3925 match */ /* option may be missing with rfc3925 match */
if (!option_ok) if (!option_ok)
ret_err(_("bad dhcp-option")); goto_err(_("bad dhcp-option"));
if (comma) if (comma)
{ {
/* characterise the value */ /* characterise the value */
char c; char c;
int found_dig = 0; int found_dig = 0, found_colon = 0;
is_addr = is_addr6 = is_hex = is_dec = is_string = 1; is_addr = is_addr6 = is_hex = is_dec = is_string = 1;
addrs = digs = 1; addrs = digs = 1;
dots = 0; dots = 0;
for (cp = comma; (c = *cp); cp++) for (cp = comma; (c = *cp); cp++)
if (c == ',') if (c == ',')
{ {
addrs++; addrs++;
is_dec = is_hex = 0; is_dec = is_hex = 0;
} }
else if (c == ':') else if (c == ':')
{ {
digs++; digs++;
is_dec = is_addr = 0; is_dec = is_addr = 0;
found_colon = 1;
} }
else if (c == '/') else if (c == '/')
{ {
is_addr6 = is_dec = is_hex = 0; is_addr6 = is_dec = is_hex = 0;
if (cp == comma) /* leading / means a pathname */ if (cp == comma) /* leading / means a pathname */
is_addr = 0; is_addr = 0;
} }
else if (c == '.') else if (c == '.')
{ {
is_addr6 = is_dec = is_hex = 0; is_addr6 = is_dec = is_hex = 0;
skipping to change at line 1154 skipping to change at line 1258
if (c != '[' && c != ']') if (c != '[' && c != ']')
is_addr6 = 0; is_addr6 = 0;
} }
} }
else else
found_dig = 1; found_dig = 1;
if (!found_dig) if (!found_dig)
is_dec = is_addr = 0; is_dec = is_addr = 0;
if (!found_colon)
is_addr6 = 0;
#ifdef HAVE_DHCP6
/* NTP server option takes hex, addresses or FQDN */
if (is6 && new->opt == OPTION6_NTP_SERVER && !is_hex)
opt_len |= is_addr6 ? OT_ADDR_LIST : OT_RFC1035_NAME;
#endif
/* We know that some options take addresses */ /* We know that some options take addresses */
if (opt_len & OT_ADDR_LIST) if (opt_len & OT_ADDR_LIST)
{ {
is_string = is_dec = is_hex = 0; is_string = is_dec = is_hex = 0;
if (!is6 && (!is_addr || dots == 0)) if (!is6 && (!is_addr || dots == 0))
ret_err(_("bad IP address")); goto_err(_("bad IP address"));
if (is6 && !is_addr6) if (is6 && !is_addr6)
ret_err(_("bad IPv6 address")); goto_err(_("bad IPv6 address"));
} }
/* or names */ /* or names */
else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING)) else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
is_addr6 = is_addr = is_dec = is_hex = 0; is_addr6 = is_addr = is_dec = is_hex = 0;
if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0) if (found_dig && (opt_len & OT_TIME) && strlen(comma) > 0)
{ {
int val, fac = 1; int val, fac = 1;
switch (comma[strlen(comma) - 1]) switch (comma[strlen(comma) - 1])
skipping to change at line 1256 skipping to change at line 1369
{ {
*(op++) = 1; /* RFC 3361 "enc byte" */ *(op++) = 1; /* RFC 3361 "enc byte" */
new->flags &= ~DHOPT_ADDR; new->flags &= ~DHOPT_ADDR;
} }
while (addrs--) while (addrs--)
{ {
cp = comma; cp = comma;
comma = split(cp); comma = split(cp);
slash = split_chr(cp, '/'); slash = split_chr(cp, '/');
if (!inet_pton(AF_INET, cp, &in)) if (!inet_pton(AF_INET, cp, &in))
ret_err(_("bad IPv4 address")); goto_err(_("bad IPv4 address"));
if (!slash) if (!slash)
{ {
memcpy(op, &in, INADDRSZ); memcpy(op, &in, INADDRSZ);
op += INADDRSZ; op += INADDRSZ;
} }
else else
{ {
unsigned char *p = (unsigned char *)&in; unsigned char *p = (unsigned char *)&in;
int netsize = atoi(slash); int netsize = atoi(slash);
*op++ = netsize; *op++ = netsize;
skipping to change at line 1302 skipping to change at line 1415
cp++; cp++;
if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']') if (strlen(cp) > 1 && cp[strlen(cp)-1] == ']')
cp[strlen(cp)-1] = 0; cp[strlen(cp)-1] = 0;
if (inet_pton(AF_INET6, cp, op)) if (inet_pton(AF_INET6, cp, op))
{ {
op += IN6ADDRSZ; op += IN6ADDRSZ;
continue; continue;
} }
ret_err(_("bad IPv6 address")); goto_err(_("bad IPv6 address"));
} }
new->len = op - new->val; new->len = op - new->val;
} }
else if (is_string) else if (is_string)
{ {
/* text arg */ /* text arg */
if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) && if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
!is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RF C3925))) !is6 && !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RF C3925)))
{ {
/* dns search, RFC 3397, or SIP, RFC 3361 */ /* dns search, RFC 3397, or SIP, RFC 3361 */
skipping to change at line 1329 skipping to change at line 1442
comma = split(arg); comma = split(arg);
while (arg && *arg) while (arg && *arg)
{ {
char *in, *dom = NULL; char *in, *dom = NULL;
size_t domlen = 1; size_t domlen = 1;
/* Allow "." as an empty domain */ /* Allow "." as an empty domain */
if (strcmp (arg, ".") != 0) if (strcmp (arg, ".") != 0)
{ {
if (!(dom = canonicalise_opt(arg))) if (!(dom = canonicalise_opt(arg)))
ret_err(_("bad domain in dhcp-option")); goto_err(_("bad domain in dhcp-option"));
domlen = strlen(dom) + 2; domlen = strlen(dom) + 2;
} }
newp = opt_malloc(len + domlen + header_size); newp = opt_malloc(len + domlen + header_size);
if (m) if (m)
{ {
memcpy(newp, m, header_size + len); memcpy(newp, m, header_size + len);
free(m); free(m);
} }
skipping to change at line 1376 skipping to change at line 1489
goto end; goto end;
} }
end: end:
len = newlen; len = newlen;
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
} }
/* RFC 3361, enc byte is zero for names */ /* RFC 3361, enc byte is zero for names */
if (new->opt == OPTION_SIP_SERVER) if (new->opt == OPTION_SIP_SERVER && m)
m[0] = 0; m[0] = 0;
new->len = (int) len + header_size; new->len = (int) len + header_size;
new->val = m; new->val = m;
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else if (comma && (opt_len & OT_CSTRING)) else if (comma && (opt_len & OT_CSTRING))
{ {
/* length fields are two bytes so need 16 bits for each string */ /* length fields are two bytes so need 16 bits for each string */
int i, commas = 1; int i, commas = 1;
unsigned char *p, *newp; unsigned char *p, *newp;
skipping to change at line 1414 skipping to change at line 1527
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
} }
new->val = newp; new->val = newp;
new->len = p - newp; new->len = p - newp;
} }
else if (comma && (opt_len & OT_RFC1035_NAME)) else if (comma && (opt_len & OT_RFC1035_NAME))
{ {
unsigned char *p = NULL, *newp, *end; unsigned char *p = NULL, *q, *newp, *end;
int len = 0; int len = 0;
int header_size = (is6 && new->opt == OPTION6_NTP_SERVER) ? 4 : 0;
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
while (arg && *arg) while (arg && *arg)
{ {
char *dom = canonicalise_opt(arg); char *dom = canonicalise_opt(arg);
if (!dom) if (!dom)
ret_err(_("bad domain in dhcp-option")); goto_err(_("bad domain in dhcp-option"));
newp = opt_malloc(len + strlen(dom) + 2); newp = opt_malloc(len + header_size + strlen(dom) + 2);
if (p) if (p)
{ {
memcpy(newp, p, len); memcpy(newp, p, len);
free(p); free(p);
} }
p = newp; p = newp;
end = do_rfc1035_name(p + len, dom, NULL); q = p + len;
end = do_rfc1035_name(q + header_size, dom, NULL);
*end++ = 0; *end++ = 0;
if (is6 && new->opt == OPTION6_NTP_SERVER)
{
PUTSHORT(NTP_SUBOPTION_SRV_FQDN, q);
PUTSHORT(end - q - 2, q);
}
len = end - p; len = end - p;
free(dom); free(dom);
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
} }
new->val = p; new->val = p;
new->len = len; new->len = len;
} }
skipping to change at line 1461 skipping to change at line 1581
new->val = (unsigned char *)opt_string_alloc(comma); new->val = (unsigned char *)opt_string_alloc(comma);
new->flags |= DHOPT_STRING; new->flags |= DHOPT_STRING;
} }
} }
} }
if (!is6 && if (!is6 &&
((new->len > 255) || ((new->len > 255) ||
(new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) || (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
(new->len > 250 && (new->flags & DHOPT_RFC3925)))) (new->len > 250 && (new->flags & DHOPT_RFC3925))))
ret_err(_("dhcp-option too long")); goto_err(_("dhcp-option too long"));
if (flags == DHOPT_MATCH) if (flags == DHOPT_MATCH)
{ {
if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) || if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
!new->netid || !new->netid ||
new->netid->next) new->netid->next)
ret_err(_("illegal dhcp-match")); goto_err(_("illegal dhcp-match"));
if (is6) if (is6)
{ {
new->next = daemon->dhcp_match6; new->next = daemon->dhcp_match6;
daemon->dhcp_match6 = new; daemon->dhcp_match6 = new;
} }
else else
{ {
new->next = daemon->dhcp_match; new->next = daemon->dhcp_match;
daemon->dhcp_match = new; daemon->dhcp_match = new;
skipping to change at line 1493 skipping to change at line 1613
new->next = daemon->dhcp_opts6; new->next = daemon->dhcp_opts6;
daemon->dhcp_opts6 = new; daemon->dhcp_opts6 = new;
} }
else else
{ {
new->next = daemon->dhcp_opts; new->next = daemon->dhcp_opts;
daemon->dhcp_opts = new; daemon->dhcp_opts = new;
} }
return 1; return 1;
on_error:
dhcp_opt_free(new);
return 0;
} }
#endif #endif
void set_option_bool(unsigned int opt) void set_option_bool(unsigned int opt)
{ {
if (opt < 32) option_var(opt) |= option_val(opt);
daemon->options |= 1u << opt;
else
daemon->options2 |= 1u << (opt - 32);
} }
void reset_option_bool(unsigned int opt) void reset_option_bool(unsigned int opt)
{ {
if (opt < 32) option_var(opt) &= ~(option_val(opt));
daemon->options &= ~(1u << opt); }
else
daemon->options2 &= ~(1u << (opt - 32)); static void server_list_free(struct server *list)
{
while (list)
{
struct server *tmp = list;
list = list->next;
free(tmp);
}
} }
static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma nd_line, int servers_only) static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma nd_line, int servers_only)
{ {
int i; int i;
char *comma; char *comma;
if (option == '?') if (option == '?')
ret_err(gen_err); ret_err(gen_err);
skipping to change at line 1571 skipping to change at line 1698
} }
break; break;
} }
case '7': /* --conf-dir */ case '7': /* --conf-dir */
{ {
DIR *dir_stream; DIR *dir_stream;
struct dirent *ent; struct dirent *ent;
char *directory, *path; char *directory, *path;
struct list { struct list {
char *suffix; char *name;
struct list *next; struct list *next;
} *ignore_suffix = NULL, *match_suffix = NULL, *li; } *ignore_suffix = NULL, *match_suffix = NULL, *files = NULL, *li;
comma = split(arg); comma = split(arg);
if (!(directory = opt_string_alloc(arg))) if (!(directory = opt_string_alloc(arg)))
break; break;
for (arg = comma; arg; arg = comma) for (arg = comma; arg; arg = comma)
{ {
comma = split(arg); comma = split(arg);
if (strlen(arg) != 0) if (strlen(arg) != 0)
{ {
skipping to change at line 1595 skipping to change at line 1722
if (*arg == '*') if (*arg == '*')
{ {
/* "*" with no suffix is a no-op */ /* "*" with no suffix is a no-op */
if (arg[1] == 0) if (arg[1] == 0)
free(li); free(li);
else else
{ {
li->next = match_suffix; li->next = match_suffix;
match_suffix = li; match_suffix = li;
/* Have to copy: buffer is overwritten */ /* Have to copy: buffer is overwritten */
li->suffix = opt_string_alloc(arg+1); li->name = opt_string_alloc(arg+1);
} }
} }
else else
{ {
li->next = ignore_suffix; li->next = ignore_suffix;
ignore_suffix = li; ignore_suffix = li;
/* Have to copy: buffer is overwritten */ /* Have to copy: buffer is overwritten */
li->suffix = opt_string_alloc(arg); li->name = opt_string_alloc(arg);
} }
} }
} }
if (!(dir_stream = opendir(directory))) if (!(dir_stream = opendir(directory)))
die(_("cannot access directory %s: %s"), directory, EC_FILE); die(_("cannot access directory %s: %s"), directory, EC_FILE);
while ((ent = readdir(dir_stream))) while ((ent = readdir(dir_stream)))
{ {
size_t len = strlen(ent->d_name); size_t len = strlen(ent->d_name);
skipping to change at line 1628 skipping to change at line 1755
ent->d_name[len - 1] == '~' || ent->d_name[len - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') || (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
ent->d_name[0] == '.') ent->d_name[0] == '.')
continue; continue;
if (match_suffix) if (match_suffix)
{ {
for (li = match_suffix; li; li = li->next) for (li = match_suffix; li; li = li->next)
{ {
/* check for required suffices */ /* check for required suffices */
size_t ls = strlen(li->suffix); size_t ls = strlen(li->name);
if (len > ls && if (len > ls &&
strcmp(li->suffix, &ent->d_name[len - ls]) == 0) strcmp(li->name, &ent->d_name[len - ls]) == 0)
break; break;
} }
if (!li) if (!li)
continue; continue;
} }
for (li = ignore_suffix; li; li = li->next) for (li = ignore_suffix; li; li = li->next)
{ {
/* check for proscribed suffices */ /* check for proscribed suffices */
size_t ls = strlen(li->suffix); size_t ls = strlen(li->name);
if (len > ls && if (len > ls &&
strcmp(li->suffix, &ent->d_name[len - ls]) == 0) strcmp(li->name, &ent->d_name[len - ls]) == 0)
break; break;
} }
if (li) if (li)
continue; continue;
path = opt_malloc(strlen(directory) + len + 2); path = opt_malloc(strlen(directory) + len + 2);
strcpy(path, directory); strcpy(path, directory);
strcat(path, "/"); strcat(path, "/");
strcat(path, ent->d_name); strcat(path, ent->d_name);
/* files must be readable */ /* files must be readable */
if (stat(path, &buf) == -1) if (stat(path, &buf) == -1)
die(_("cannot access %s: %s"), path, EC_FILE); die(_("cannot access %s: %s"), path, EC_FILE);
/* only reg files allowed. */ /* only reg files allowed. */
if (S_ISREG(buf.st_mode)) if (S_ISREG(buf.st_mode))
one_file(path, 0); {
/* sort files into order. */
struct list **up, *new = opt_malloc(sizeof(struct list));
new->name = path;
for (up = &files, li = files; li; up = &li->next, li = li->next)
if (strcmp(li->name, path) >=0)
break;
new->next = li;
*up = new;
}
free(path);
} }
for (li = files; li; li = li->next)
one_file(li->name, 0);
closedir(dir_stream); closedir(dir_stream);
free(directory); free(directory);
for(; ignore_suffix; ignore_suffix = li) for(; ignore_suffix; ignore_suffix = li)
{ {
li = ignore_suffix->next; li = ignore_suffix->next;
free(ignore_suffix->suffix); free(ignore_suffix->name);
free(ignore_suffix); free(ignore_suffix);
} }
for(; match_suffix; match_suffix = li) for(; match_suffix; match_suffix = li)
{ {
li = match_suffix->next; li = match_suffix->next;
free(match_suffix->suffix); free(match_suffix->name);
free(match_suffix); free(match_suffix);
} }
for(; files; files = li)
{
li = files->next;
free(files->name);
free(files);
}
break; break;
} }
case LOPT_ADD_SBNET: /* --add-subnet */ case LOPT_ADD_SBNET: /* --add-subnet */
set_option_bool(OPT_CLIENT_SUBNET); set_option_bool(OPT_CLIENT_SUBNET);
if (arg) if (arg)
{ {
char *err, *end; char *err, *end;
comma = split(arg); comma = split(arg);
struct mysubnet* new = opt_malloc(sizeof(struct mysubnet)); struct mysubnet* new = opt_malloc(sizeof(struct mysubnet));
if ((end = split_chr(arg, '/'))) if ((end = split_chr(arg, '/')))
{ {
/* has subnet+len */ /* has subnet+len */
err = parse_mysockaddr(arg, &new->addr); err = parse_mysockaddr(arg, &new->addr);
if (err) if (err)
ret_err(err); ret_err_free(err, new);
if (!atoi_check(end, &new->mask)) if (!atoi_check(end, &new->mask))
ret_err(gen_err); ret_err_free(gen_err, new);
new->addr_used = 1; new->addr_used = 1;
} }
else if (!atoi_check(arg, &new->mask)) else if (!atoi_check(arg, &new->mask))
ret_err(gen_err); ret_err_free(gen_err, new);
daemon->add_subnet4 = new; daemon->add_subnet4 = new;
if (comma) if (comma)
{ {
new = opt_malloc(sizeof(struct mysubnet)); new = opt_malloc(sizeof(struct mysubnet));
if ((end = split_chr(comma, '/'))) if ((end = split_chr(comma, '/')))
{ {
/* has subnet+len */ /* has subnet+len */
err = parse_mysockaddr(comma, &new->addr); err = parse_mysockaddr(comma, &new->addr);
if (err) if (err)
ret_err(err); ret_err_free(err, new);
if (!atoi_check(end, &new->mask)) if (!atoi_check(end, &new->mask))
ret_err(gen_err); ret_err_free(gen_err, new);
new->addr_used = 1; new->addr_used = 1;
} }
else else
{ {
if (!atoi_check(comma, &new->mask)) if (!atoi_check(comma, &new->mask))
ret_err(gen_err); ret_err_free(gen_err, new);
} }
daemon->add_subnet6 = new; daemon->add_subnet6 = new;
} }
} }
break; break;
case '1': /* --enable-dbus */ case '1': /* --enable-dbus */
set_option_bool(OPT_DBUS); set_option_bool(OPT_DBUS);
if (arg) if (arg)
daemon->dbus_name = opt_string_alloc(arg); daemon->dbus_name = opt_string_alloc(arg);
else else
daemon->dbus_name = DNSMASQ_SERVICE; daemon->dbus_name = DNSMASQ_SERVICE;
break; break;
case LOPT_UBUS: /* --enable-ubus */
set_option_bool(OPT_UBUS);
if (arg)
daemon->ubus_name = opt_string_alloc(arg);
else
daemon->ubus_name = DNSMASQ_UBUS_NAME;
break;
case '8': /* --log-facility */ case '8': /* --log-facility */
/* may be a filename */ /* may be a filename */
if (strchr(arg, '/') || strcmp (arg, "-") == 0) if (strchr(arg, '/') || strcmp (arg, "-") == 0)
daemon->log_file = opt_string_alloc(arg); daemon->log_file = opt_string_alloc(arg);
else else
{ {
#ifdef __ANDROID__ #ifdef __ANDROID__
ret_err(_("setting log facility is not possible under Android")); ret_err(_("setting log facility is not possible under Android"));
#else #else
for (i = 0; facilitynames[i].c_name; i++) for (i = 0; facilitynames[i].c_name; i++)
skipping to change at line 1843 skipping to change at line 1997
break; break;
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
case 'l': /* --dhcp-leasefile */ case 'l': /* --dhcp-leasefile */
daemon->lease_file = opt_string_alloc(arg); daemon->lease_file = opt_string_alloc(arg);
break; break;
/* Sorry about the gross pre-processor abuse */ /* Sorry about the gross pre-processor abuse */
case '6': /* --dhcp-script */ case '6': /* --dhcp-script */
case LOPT_LUASCRIPT: /* --dhcp-luascript */ case LOPT_LUASCRIPT: /* --dhcp-luascript */
# if defined(NO_FORK) # if !defined(HAVE_SCRIPT)
ret_err(_("cannot run scripts under uClinux"));
# elif !defined(HAVE_SCRIPT)
ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scrip ts")); ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scrip ts"));
# else # else
if (option == LOPT_LUASCRIPT) if (option == LOPT_LUASCRIPT)
# if !defined(HAVE_LUASCRIPT) # if !defined(HAVE_LUASCRIPT)
ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts")) ; ret_err(_("recompile with HAVE_LUASCRIPT defined to enable Lua scripts")) ;
# else # else
daemon->luascript = opt_string_alloc(arg); daemon->luascript = opt_string_alloc(arg);
# endif # endif
else else
daemon->lease_change_command = opt_string_alloc(arg); daemon->lease_change_command = opt_string_alloc(arg);
skipping to change at line 1915 skipping to change at line 2067
daemon->authserver = opt_string_alloc(arg); daemon->authserver = opt_string_alloc(arg);
while ((arg = comma)) while ((arg = comma))
{ {
struct iname *new = opt_malloc(sizeof(struct iname)); struct iname *new = opt_malloc(sizeof(struct iname));
comma = split(arg); comma = split(arg);
new->name = NULL; new->name = NULL;
unhide_metas(arg); unhide_metas(arg);
if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0) if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
new->addr.sa.sa_family = AF_INET; new->addr.sa.sa_family = AF_INET;
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
new->addr.sa.sa_family = AF_INET6; new->addr.sa.sa_family = AF_INET6;
#endif
else else
{ {
char *fam = split_chr(arg, '/'); char *fam = split_chr(arg, '/');
new->name = opt_string_alloc(arg); new->name = opt_string_alloc(arg);
new->addr.sa.sa_family = 0; new->addr.sa.sa_family = 0;
if (fam) if (fam)
{ {
if (strcmp(fam, "4") == 0) if (strcmp(fam, "4") == 0)
new->addr.sa.sa_family = AF_INET; new->addr.sa.sa_family = AF_INET;
#ifdef HAVE_IPV6
else if (strcmp(fam, "6") == 0) else if (strcmp(fam, "6") == 0)
new->addr.sa.sa_family = AF_INET6; new->addr.sa.sa_family = AF_INET6;
#endif
else else
ret_err(gen_err); {
free(new->name);
ret_err_free(gen_err, new);
}
} }
} }
new->next = daemon->authinterface; new->next = daemon->authinterface;
daemon->authinterface = new; daemon->authinterface = new;
}; };
break; break;
case LOPT_AUTHSFS: /* --auth-sec-servers */ case LOPT_AUTHSFS: /* --auth-sec-servers */
{ {
skipping to change at line 1977 skipping to change at line 2128
new->interface_names = NULL; new->interface_names = NULL;
new->next = daemon->auth_zones; new->next = daemon->auth_zones;
daemon->auth_zones = new; daemon->auth_zones = new;
while ((arg = comma)) while ((arg = comma))
{ {
int prefixlen = 0; int prefixlen = 0;
int is_exclude = 0; int is_exclude = 0;
char *prefix; char *prefix;
struct addrlist *subnet = NULL; struct addrlist *subnet = NULL;
struct all_addr addr; union all_addr addr;
comma = split(arg); comma = split(arg);
prefix = split_chr(arg, '/'); prefix = split_chr(arg, '/');
if (prefix && !atoi_check(prefix, &prefixlen)) if (prefix && !atoi_check(prefix, &prefixlen))
ret_err(gen_err); ret_err(gen_err);
if (strstr(arg, "exclude:") == arg) if (strstr(arg, "exclude:") == arg)
{ {
is_exclude = 1; is_exclude = 1;
arg = arg+8; arg = arg+8;
} }
if (inet_pton(AF_INET, arg, &addr.addr.addr4)) if (inet_pton(AF_INET, arg, &addr.addr4))
{ {
subnet = opt_malloc(sizeof(struct addrlist)); subnet = opt_malloc(sizeof(struct addrlist));
subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen; subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
subnet->flags = ADDRLIST_LITERAL; subnet->flags = ADDRLIST_LITERAL;
} }
#ifdef HAVE_IPV6 else if (inet_pton(AF_INET6, arg, &addr.addr6))
else if (inet_pton(AF_INET6, arg, &addr.addr.addr6))
{ {
subnet = opt_malloc(sizeof(struct addrlist)); subnet = opt_malloc(sizeof(struct addrlist));
subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen; subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6; subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
} }
#endif
else else
{ {
struct auth_name_list *name = opt_malloc(sizeof(struct auth_name _list)); struct auth_name_list *name = opt_malloc(sizeof(struct auth_name _list));
name->name = opt_string_alloc(arg); name->name = opt_string_alloc(arg);
name->flags = AUTH4 | AUTH6; name->flags = AUTH4 | AUTH6;
name->next = new->interface_names; name->next = new->interface_names;
new->interface_names = name; new->interface_names = name;
if (prefix) if (prefix)
{ {
if (prefixlen == 4) if (prefixlen == 4)
name->flags &= ~AUTH6; name->flags &= ~AUTH6;
#ifdef HAVE_IPV6
else if (prefixlen == 6) else if (prefixlen == 6)
name->flags &= ~AUTH4; name->flags &= ~AUTH4;
#endif
else else
ret_err(gen_err); ret_err(gen_err);
} }
} }
if (subnet) if (subnet)
{ {
subnet->addr = addr; subnet->addr = addr;
if (is_exclude) if (is_exclude)
skipping to change at line 2102 skipping to change at line 2249
new->prefix = NULL; new->prefix = NULL;
new->indexed = 0; new->indexed = 0;
unhide_metas(comma); unhide_metas(comma);
if ((netpart = split_chr(comma, '/'))) if ((netpart = split_chr(comma, '/')))
{ {
int msize; int msize;
arg = split(netpart); arg = split(netpart);
if (!atoi_check(netpart, &msize)) if (!atoi_check(netpart, &msize))
ret_err(gen_err); ret_err_free(gen_err, new);
else if (inet_pton(AF_INET, comma, &new->start)) else if (inet_pton(AF_INET, comma, &new->start))
{ {
int mask = (1 << (32 - msize)) - 1; int mask = (1 << (32 - msize)) - 1;
new->is6 = 0; new->is6 = 0;
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~m ask); new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~m ask);
new->end.s_addr = new->start.s_addr | htonl(mask); new->end.s_addr = new->start.s_addr | htonl(mask);
if (arg) if (arg)
{ {
if (option != 's') if (option != 's')
{ {
if (!(new->prefix = canonicalise_opt(arg)) || if (!(new->prefix = canonicalise_opt(arg)) ||
strlen(new->prefix) > MAXLABEL - INET_ADDRS TRLEN) strlen(new->prefix) > MAXLABEL - INET_ADDRS TRLEN)
ret_err(_("bad prefix")); ret_err_free(_("bad prefix"), new);
} }
else if (strcmp(arg, "local") != 0 || else if (strcmp(arg, "local") != 0 ||
(msize != 8 && msize != 16 && msize != 24) ) (msize != 8 && msize != 16 && msize != 24) )
ret_err(gen_err); ret_err_free(gen_err, new);
else else
{ {
/* generate the equivalent of /* generate the equivalent of
local=/xxx.yyy.zzz.in-addr.arpa/ */ local=/xxx.yyy.zzz.in-addr.arpa/ */
struct server *serv = add_rev4(new->start, msiz e); struct server *serv = add_rev4(new->start, msiz e);
if (!serv) if (!serv)
ret_err(_("bad prefix")); ret_err_free(_("bad prefix"), new);
serv->flags |= SERV_NO_ADDR; serv->flags |= SERV_NO_ADDR;
/* local=/<domain>/ */ /* local=/<domain>/ */
serv = opt_malloc(sizeof(struct server)); serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server)); memset(serv, 0, sizeof(struct server));
serv->domain = d; serv->domain = d;
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
serv->next = daemon->servers; serv->next = daemon->servers;
daemon->servers = serv; daemon->servers = serv;
} }
} }
} }
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, comma, &new->start6)) else if (inet_pton(AF_INET6, comma, &new->start6))
{ {
u64 mask = (1LLU << (128 - msize)) - 1LLU; u64 mask = (1LLU << (128 - msize)) - 1LLU;
u64 addrpart = addr6part(&new->start6); u64 addrpart = addr6part(&new->start6);
new->is6 = 1; new->is6 = 1;
/* prefix==64 overflows the mask calculation above */ /* prefix==64 overflows the mask calculation above */
if (msize == 64) if (msize == 64)
mask = (u64)-1LL; mask = (u64)-1LL;
new->end6 = new->start6; new->end6 = new->start6;
setaddr6part(&new->start6, addrpart & ~mask); setaddr6part(&new->start6, addrpart & ~mask);
setaddr6part(&new->end6, addrpart | mask); setaddr6part(&new->end6, addrpart | mask);
if (msize < 64) if (msize < 64)
ret_err(gen_err); ret_err_free(gen_err, new);
else if (arg) else if (arg)
{ {
if (option != 's') if (option != 's')
{ {
if (!(new->prefix = canonicalise_opt(arg)) || if (!(new->prefix = canonicalise_opt(arg)) ||
strlen(new->prefix) > MAXLABEL - INET6_ADDR STRLEN) strlen(new->prefix) > MAXLABEL - INET6_ADDR STRLEN)
ret_err(_("bad prefix")); ret_err_free(_("bad prefix"), new);
} }
else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0)) else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
ret_err(gen_err); ret_err_free(gen_err, new);
else else
{ {
/* generate the equivalent of /* generate the equivalent of
local=/xxx.yyy.zzz.ip6.arpa/ */ local=/xxx.yyy.zzz.ip6.arpa/ */
struct server *serv = add_rev6(&new->start6, ms ize); struct server *serv = add_rev6(&new->start6, ms ize);
serv->flags |= SERV_NO_ADDR; serv->flags |= SERV_NO_ADDR;
/* local=/<domain>/ */ /* local=/<domain>/ */
serv = opt_malloc(sizeof(struct server)); serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server)); memset(serv, 0, sizeof(struct server));
serv->domain = d; serv->domain = d;
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
serv->next = daemon->servers; serv->next = daemon->servers;
daemon->servers = serv; daemon->servers = serv;
} }
} }
} }
#endif
else else
ret_err(gen_err); ret_err_free(gen_err, new);
} }
else else
{ {
char *prefstr; char *prefstr;
arg = split(comma); arg = split(comma);
prefstr = split(arg); prefstr = split(arg);
if (inet_pton(AF_INET, comma, &new->start)) if (inet_pton(AF_INET, comma, &new->start))
{ {
new->is6 = 0; new->is6 = 0;
if (!arg) if (!arg)
new->end.s_addr = new->start.s_addr; new->end.s_addr = new->start.s_addr;
else if (!inet_pton(AF_INET, arg, &new->end)) else if (!inet_pton(AF_INET, arg, &new->end))
ret_err(gen_err); ret_err_free(gen_err, new);
} }
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, comma, &new->start6)) else if (inet_pton(AF_INET6, comma, &new->start6))
{ {
new->is6 = 1; new->is6 = 1;
if (!arg) if (!arg)
memcpy(&new->end6, &new->start6, IN6ADDRSZ); memcpy(&new->end6, &new->start6, IN6ADDRSZ);
else if (!inet_pton(AF_INET6, arg, &new->end6)) else if (!inet_pton(AF_INET6, arg, &new->end6))
ret_err(gen_err); ret_err_free(gen_err, new);
} }
#endif
else else
ret_err(gen_err); ret_err_free(gen_err, new);
if (option != 's' && prefstr) if (option != 's' && prefstr)
{ {
if (!(new->prefix = canonicalise_opt(prefstr)) || if (!(new->prefix = canonicalise_opt(prefstr)) ||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN) strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
ret_err(_("bad prefix")); ret_err_free(_("bad prefix"), new);
} }
} }
new->domain = d; new->domain = d;
if (option == 's') if (option == 's')
{ {
new->next = daemon->cond_domain; new->next = daemon->cond_domain;
daemon->cond_domain = new; daemon->cond_domain = new;
} }
else else
skipping to change at line 2370 skipping to change at line 2513
comma = split(arg); comma = split(arg);
unhide_metas(arg); unhide_metas(arg);
if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)) if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
{ {
new->addr.sa.sa_family = AF_INET; new->addr.sa.sa_family = AF_INET;
new->addr.in.sin_port = 0; new->addr.in.sin_port = 0;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
new->addr.in.sin_len = sizeof(new->addr.in); new->addr.in.sin_len = sizeof(new->addr.in);
#endif #endif
} }
#ifdef HAVE_IPV6
else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
{ {
new->addr.sa.sa_family = AF_INET6; new->addr.sa.sa_family = AF_INET6;
new->addr.in6.sin6_flowinfo = 0; new->addr.in6.sin6_flowinfo = 0;
new->addr.in6.sin6_scope_id = 0; new->addr.in6.sin6_scope_id = 0;
new->addr.in6.sin6_port = 0; new->addr.in6.sin6_port = 0;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
new->addr.in6.sin6_len = sizeof(new->addr.in6); new->addr.in6.sin6_len = sizeof(new->addr.in6);
#endif #endif
} }
#endif
else else
ret_err(gen_err); ret_err_free(gen_err, new);
new->used = 0; new->used = 0;
if (option == 'a') if (option == 'a')
{ {
new->next = daemon->if_addrs; new->next = daemon->if_addrs;
daemon->if_addrs = new; daemon->if_addrs = new;
} }
else else
{ {
new->next = daemon->auth_peers; new->next = daemon->auth_peers;
skipping to change at line 2454 skipping to change at line 2595
#endif #endif
} }
if (servers_only && option == 'S') if (servers_only && option == 'S')
newlist->flags |= SERV_FROM_FILE; newlist->flags |= SERV_FROM_FILE;
if (option == 'A') if (option == 'A')
{ {
newlist->flags |= SERV_LITERAL_ADDRESS; newlist->flags |= SERV_LITERAL_ADDRESS;
if (!(newlist->flags & SERV_TYPE)) if (!(newlist->flags & SERV_TYPE))
ret_err(gen_err); {
server_list_free(newlist);
ret_err(gen_err);
}
} }
else if (option == LOPT_NO_REBIND) else if (option == LOPT_NO_REBIND)
newlist->flags |= SERV_NO_REBIND; newlist->flags |= SERV_NO_REBIND;
if (!arg || !*arg) if (!arg || !*arg)
{ {
if (!(newlist->flags & SERV_NO_REBIND)) if (!(newlist->flags & SERV_NO_REBIND))
newlist->flags |= SERV_NO_ADDR; /* no server */ newlist->flags |= SERV_NO_ADDR; /* no server */
} }
else if (strcmp(arg, "#") == 0) else if (strcmp(arg, "#") == 0)
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */ newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
else else
{ {
char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags); char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
if (err) if (err)
ret_err(err); {
server_list_free(newlist);
ret_err(err);
}
} }
serv = newlist; serv = newlist;
while (serv->next) while (serv->next)
{ {
serv->next->flags = serv->flags; serv->next->flags |= serv->flags & ~(SERV_HAS_DOMAIN | SERV_FOR_NODOT S);
serv->next->addr = serv->addr; serv->next->addr = serv->addr;
serv->next->source_addr = serv->source_addr; serv->next->source_addr = serv->source_addr;
strcpy(serv->next->interface, serv->interface); strcpy(serv->next->interface, serv->interface);
serv = serv->next; serv = serv->next;
} }
serv->next = daemon->servers; serv->next = daemon->servers;
daemon->servers = newlist; daemon->servers = newlist;
break; break;
} }
case LOPT_REV_SERV: /* --rev-server */ case LOPT_REV_SERV: /* --rev-server */
{ {
char *string; char *string;
int size; int size;
struct server *serv; struct server *serv;
struct in_addr addr4; struct in_addr addr4;
#ifdef HAVE_IPV6
struct in6_addr addr6; struct in6_addr addr6;
#endif
unhide_metas(arg); unhide_metas(arg);
if (!arg || !(comma=split(arg)) || !(string = split_chr(arg, '/')) || !at if (!arg)
oi_check(string, &size)) ret_err(gen_err);
comma=split(arg);
if (!(string = split_chr(arg, '/')) || !atoi_check(string, &size))
ret_err(gen_err); ret_err(gen_err);
if (inet_pton(AF_INET, arg, &addr4)) if (inet_pton(AF_INET, arg, &addr4))
{ {
serv = add_rev4(addr4, size); serv = add_rev4(addr4, size);
if (!serv) if (!serv)
ret_err(_("bad prefix")); ret_err(_("bad prefix"));
} }
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &addr6)) else if (inet_pton(AF_INET6, arg, &addr6))
serv = add_rev6(&addr6, size); serv = add_rev6(&addr6, size);
#endif
else else
ret_err(gen_err); ret_err(gen_err);
string = parse_server(comma, &serv->addr, &serv->source_addr, serv->inter face, &serv->flags); string = parse_server(comma, &serv->addr, &serv->source_addr, serv->inter face, &serv->flags);
if (string) if (string)
ret_err(string); ret_err(string);
if (servers_only) if (servers_only)
serv->flags |= SERV_FROM_FILE; serv->flags |= SERV_FROM_FILE;
skipping to change at line 2605 skipping to change at line 2753
if (!atoi_check(arg, &size)) if (!atoi_check(arg, &size))
ret_err(gen_err); ret_err(gen_err);
else else
{ {
/* zero is OK, and means no caching. */ /* zero is OK, and means no caching. */
if (size < 0) if (size < 0)
size = 0; size = 0;
/* Note that for very large cache sizes, the malloc()
will overflow. For the size of the cache record
at the time this was noted, the value of "very large"
was 46684428. Limit to an order of magnitude less than
that to be safe from changes to the cache record. */
if (size > 5000000)
size = 5000000;
daemon->cachesize = size; daemon->cachesize = size;
} }
break; break;
} }
case 'p': /* --port */ case 'p': /* --port */
if (!atoi_check16(arg, &daemon->port)) if (!atoi_check16(arg, &daemon->port))
ret_err(gen_err); ret_err(gen_err);
break; break;
skipping to change at line 2790 skipping to change at line 2946
b->next = new->alias; b->next = new->alias;
new->alias = b; new->alias = b;
strcpy(b->iface, arg); strcpy(b->iface, arg);
} }
} while (comma); } while (comma);
break; break;
} }
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
case LOPT_SHARED_NET: /* --shared-network */
{
struct shared_network *new = opt_malloc(sizeof(struct shared_network));
#ifdef HAVE_DHCP6
new->shared_addr.s_addr = 0;
#endif
new->if_index = 0;
if (!(comma = split(arg)))
{
snerr:
free(new);
ret_err(_("bad shared-network"));
}
if (inet_pton(AF_INET, comma, &new->shared_addr))
{
if (!inet_pton(AF_INET, arg, &new->match_addr) &&
!(new->if_index = if_nametoindex(arg)))
goto snerr;
}
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, comma, &new->shared_addr6))
{
if (!inet_pton(AF_INET6, arg, &new->match_addr6) &&
!(new->if_index = if_nametoindex(arg)))
goto snerr;
}
#endif
else
goto snerr;
new->next = daemon->shared_networks;
daemon->shared_networks = new;
break;
}
case 'F': /* --dhcp-range */ case 'F': /* --dhcp-range */
{ {
int k, leasepos = 2; int k, leasepos = 2;
char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context)); struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
memset (new, 0, sizeof(*new)); memset (new, 0, sizeof(*new));
new->lease_time = DEFLEASE; new->lease_time = DEFLEASE;
while(1) while(1)
skipping to change at line 2811 skipping to change at line 3005
for (cp = arg; *cp; cp++) for (cp = arg; *cp; cp++)
if (!(*cp == ' ' || *cp == '.' || *cp == ':' || if (!(*cp == ' ' || *cp == '.' || *cp == ':' ||
(*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') || (*cp >= 'a' && *cp <= 'f') || (*cp >= 'A' && *cp <= 'F') ||
(*cp >='0' && *cp <= '9'))) (*cp >='0' && *cp <= '9')))
break; break;
if (*cp != ',' && (comma = split(arg))) if (*cp != ',' && (comma = split(arg)))
{ {
if (is_tag_prefix(arg)) if (is_tag_prefix(arg))
{ {
struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid)
);
tt->net = opt_string_alloc(arg+4);
tt->next = new->filter;
/* ignore empty tag */ /* ignore empty tag */
if (tt->net) if (arg[4])
new->filter = tt; new->filter = dhcp_netid_create(arg+4, new->filter);
} }
else else
{ {
if (new->netid.net) if (new->netid.net)
ret_err(_("only one tag allowed")); {
else if (strstr(arg, "set:") == arg) dhcp_context_free(new);
new->netid.net = opt_string_alloc(arg+4); ret_err(_("only one tag allowed"));
}
else else
new->netid.net = opt_string_alloc(arg); new->netid.net = opt_string_alloc(set_prefix(arg));
} }
arg = comma; arg = comma;
} }
else else
{ {
a[0] = arg; a[0] = arg;
break; break;
} }
} }
for (k = 1; k < 8; k++) for (k = 1; k < 8; k++)
if (!(a[k] = split(a[k-1]))) if (!(a[k] = split(a[k-1])))
break; break;
if (k < 2) if (k < 2)
ret_err(_("bad dhcp-range")); {
dhcp_context_free(new);
ret_err(_("bad dhcp-range"));
}
if (inet_pton(AF_INET, a[0], &new->start)) if (inet_pton(AF_INET, a[0], &new->start))
{ {
new->next = daemon->dhcp; new->next = daemon->dhcp;
daemon->dhcp = new; daemon->dhcp = new;
new->end = new->start; new->end = new->start;
if (strcmp(a[1], "static") == 0) if (strcmp(a[1], "static") == 0)
new->flags |= CONTEXT_STATIC; new->flags |= CONTEXT_STATIC;
else if (strcmp(a[1], "proxy") == 0) else if (strcmp(a[1], "proxy") == 0)
new->flags |= CONTEXT_PROXY; new->flags |= CONTEXT_PROXY;
else if (!inet_pton(AF_INET, a[1], &new->end)) else if (!inet_pton(AF_INET, a[1], &new->end))
ret_err(_("bad dhcp-range")); {
dhcp_context_free(new);
ret_err(_("bad dhcp-range"));
}
if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
{ {
struct in_addr tmp = new->start; struct in_addr tmp = new->start;
new->start = new->end; new->start = new->end;
new->end = tmp; new->end = tmp;
} }
if (k >= 3 && strchr(a[2], '.') && if (k >= 3 && strchr(a[2], '.') &&
(inet_pton(AF_INET, a[2], &new->netmask) > 0)) (inet_pton(AF_INET, a[2], &new->netmask) > 0))
{ {
new->flags |= CONTEXT_NETMASK; new->flags |= CONTEXT_NETMASK;
leasepos = 3; leasepos = 3;
if (!is_same_net(new->start, new->end, new->netmask)) if (!is_same_net(new->start, new->end, new->netmask))
ret_err(_("inconsistent DHCP range")); {
dhcp_context_free(new);
ret_err(_("inconsistent DHCP range"));
}
if (k >= 4 && strchr(a[3], '.') && if (k >= 4 && strchr(a[3], '.') &&
(inet_pton(AF_INET, a[3], &new->broadcast) > 0)) (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
{ {
new->flags |= CONTEXT_BRDCAST; new->flags |= CONTEXT_BRDCAST;
leasepos = 4; leasepos = 4;
} }
} }
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, a[0], &new->start6)) else if (inet_pton(AF_INET6, a[0], &new->start6))
{ {
const char *err = NULL;
new->flags |= CONTEXT_V6; new->flags |= CONTEXT_V6;
new->prefix = 64; /* default */ new->prefix = 64; /* default */
new->end6 = new->start6; new->end6 = new->start6;
new->next = daemon->dhcp6; new->next = daemon->dhcp6;
daemon->dhcp6 = new; daemon->dhcp6 = new;
for (leasepos = 1; leasepos < k; leasepos++) for (leasepos = 1; leasepos < k; leasepos++)
{ {
if (strcmp(a[leasepos], "static") == 0) if (strcmp(a[leasepos], "static") == 0)
new->flags |= CONTEXT_STATIC | CONTEXT_DHCP; new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
skipping to change at line 2926 skipping to change at line 3129
for (cp = a[leasepos]; *cp; cp++) for (cp = a[leasepos]; *cp; cp++)
if (!(*cp >= '0' && *cp <= '9')) if (!(*cp >= '0' && *cp <= '9'))
break; break;
if (!*cp && (pref = atoi(a[leasepos])) <= 128) if (!*cp && (pref = atoi(a[leasepos])) <= 128)
{ {
new->prefix = pref; new->prefix = pref;
leasepos++; leasepos++;
} }
} }
if (new->prefix != 64) if (new->prefix > 64)
{ {
if (new->flags & CONTEXT_RA) if (new->flags & CONTEXT_RA)
ret_err(_("prefix length must be exactly 64 for RA subnets")); err=(_("prefix length must be exactly 64 for RA subnets"));
else if (new->flags & CONTEXT_TEMPLATE) else if (new->flags & CONTEXT_TEMPLATE)
ret_err(_("prefix length must be exactly 64 for subnet construc tors")); err=(_("prefix length must be exactly 64 for subnet constructor s"));
} }
else if (new->prefix < 64)
err=(_("prefix length must be at least 64"));
if (new->prefix < 64) if (!err && !is_same_net6(&new->start6, &new->end6, new->prefix))
ret_err(_("prefix length must be at least 64")); err=(_("inconsistent DHCPv6 range"));
if (!is_same_net6(&new->start6, &new->end6, new->prefix)) if (err)
ret_err(_("inconsistent DHCPv6 range")); {
dhcp_context_free(new);
ret_err(err);
}
/* dhcp-range=:: enables DHCP stateless on any interface */ /* dhcp-range=:: enables DHCP stateless on any interface */
if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_T EMPLATE)) if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_T EMPLATE))
new->prefix = 0; new->prefix = 0;
if (new->flags & CONTEXT_TEMPLATE) if (new->flags & CONTEXT_TEMPLATE)
{ {
struct in6_addr zero; struct in6_addr zero;
memset(&zero, 0, sizeof(zero)); memset(&zero, 0, sizeof(zero));
if (!is_same_net6(&zero, &new->start6, new->prefix)) if (!is_same_net6(&zero, &new->start6, new->prefix))
ret_err(_("prefix must be zero with \"constructor:\" argument") {
); dhcp_context_free(new);
ret_err(_("prefix must be zero with \"constructor:\" argument
"));
}
} }
if (addr6part(&new->start6) > addr6part(&new->end6)) if (addr6part(&new->start6) > addr6part(&new->end6))
{ {
struct in6_addr tmp = new->start6; struct in6_addr tmp = new->start6;
new->start6 = new->end6; new->start6 = new->end6;
new->end6 = tmp; new->end6 = tmp;
} }
} }
#endif #endif
else else
ret_err(_("bad dhcp-range")); {
dhcp_context_free(new);
ret_err(_("bad dhcp-range"));
}
if (leasepos < k) if (leasepos < k)
{ {
if (leasepos != k-1) if (leasepos != k-1)
ret_err(_("bad dhcp-range")); {
dhcp_context_free(new);
ret_err(_("bad dhcp-range"));
}
if (strcmp(a[leasepos], "infinite") == 0) if (strcmp(a[leasepos], "infinite") == 0)
new->lease_time = 0xffffffff; new->lease_time = 0xffffffff;
else if (strcmp(a[leasepos], "deprecated") == 0) else if (strcmp(a[leasepos], "deprecated") == 0)
new->flags |= CONTEXT_DEPRECATE; new->flags |= CONTEXT_DEPRECATE;
else else
{ {
int fac = 1; int fac = 1;
if (strlen(a[leasepos]) > 0) if (strlen(a[leasepos]) > 0)
{ {
skipping to change at line 3005 skipping to change at line 3222
case 's': case 's':
case 'S': case 'S':
a[leasepos][strlen(a[leasepos]) - 1] = 0; a[leasepos][strlen(a[leasepos]) - 1] = 0;
} }
for (cp = a[leasepos]; *cp; cp++) for (cp = a[leasepos]; *cp; cp++)
if (!(*cp >= '0' && *cp <= '9')) if (!(*cp >= '0' && *cp <= '9'))
break; break;
if (*cp || (leasepos+1 < k)) if (*cp || (leasepos+1 < k))
ret_err(_("bad dhcp-range")); ret_err_free(_("bad dhcp-range"), new);
new->lease_time = atoi(a[leasepos]) * fac; new->lease_time = atoi(a[leasepos]) * fac;
/* Leases of a minute or less confuse /* Leases of a minute or less confuse
some clients, notably Apple's */ some clients, notably Apple's */
if (new->lease_time < 120) if (new->lease_time < 120)
new->lease_time = 120; new->lease_time = 120;
} }
} }
} }
break; break;
} }
case LOPT_BANK: case LOPT_BANK:
case 'G': /* --dhcp-host */ case 'G': /* --dhcp-host */
{ {
int j, k = 0;
char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
struct dhcp_config *new; struct dhcp_config *new;
struct in_addr in; struct in_addr in;
new = opt_malloc(sizeof(struct dhcp_config)); new = opt_malloc(sizeof(struct dhcp_config));
new->next = daemon->dhcp_conf; new->next = daemon->dhcp_conf;
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0; new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
new->hwaddr = NULL; new->hwaddr = NULL;
new->netid = NULL; new->netid = NULL;
new->filter = NULL;
new->clid = NULL;
#ifdef HAVE_DHCP6
new->addr6 = NULL;
#endif
if ((a[0] = arg)) while (arg)
for (k = 1; k < 7; k++) {
if (!(a[k] = split(a[k-1]))) comma = split(arg);
break; if (strchr(arg, ':')) /* ethernet address, netid or binary CLID */
{
for (j = 0; j < k; j++) if ((arg[0] == 'i' || arg[0] == 'I') &&
if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */ (arg[1] == 'd' || arg[1] == 'D') &&
{ arg[2] == ':')
char *arg = a[j]; {
if (arg[3] == '*')
new->flags |= CONFIG_NOCLID;
else
{
int len;
arg += 3; /* dump id: */
if (strchr(arg, ':'))
len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NU
LL);
else
{
unhide_metas(arg);
len = (int) strlen(arg);
}
if ((arg[0] == 'i' || arg[0] == 'I') && if (len == -1)
(arg[1] == 'd' || arg[1] == 'D') && {
arg[2] == ':') dhcp_config_free(new);
{ ret_err(_("bad hex constant"));
if (arg[3] == '*') }
new->flags |= CONFIG_NOCLID; else if ((new->clid = opt_malloc(len)))
else {
{ new->flags |= CONFIG_CLID;
int len; new->clid_len = len;
arg += 3; /* dump id: */ memcpy(new->clid, arg, len);
if (strchr(arg, ':')) }
len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL }
); }
else /* dhcp-host has strange backwards-compat needs. */
{ else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg
unhide_metas(arg); )
len = (int) strlen(arg); {
} struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dh
cp_netid_list));
newlist->next = new->netid;
new->netid = newlist;
newlist->list = dhcp_netid_create(arg+4, NULL);
}
else if (strstr(arg, "tag:") == arg)
new->filter = dhcp_netid_create(arg+4, new->filter);
if (len == -1)
ret_err(_("bad hex constant"));
else if ((new->clid = opt_malloc(len)))
{
new->flags |= CONFIG_CLID;
new->clid_len = len;
memcpy(new->clid, arg, len);
}
}
}
/* dhcp-host has strange backwards-compat needs. */
else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
{
struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid
));
struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp
_netid_list));
newtag->net = opt_malloc(strlen(arg + 4) + 1);
newlist->next = new->netid;
new->netid = newlist;
newlist->list = newtag;
strcpy(newtag->net, arg+4);
unhide_metas(newtag->net);
}
else if (strstr(arg, "tag:") == arg)
ret_err(_("cannot match tags in --dhcp-host"));
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else if (arg[0] == '[' && arg[strlen(arg)-1] == ']') else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
{ {
arg[strlen(arg)-1] = 0; char *pref;
arg++; struct in6_addr in6;
struct addrlist *new_addr;
arg[strlen(arg)-1] = 0;
arg++;
pref = split_chr(arg, '/');
if (!inet_pton(AF_INET6, arg, &new->addr6)) if (!inet_pton(AF_INET6, arg, &in6))
ret_err(_("bad IPv6 address")); {
dhcp_config_free(new);
ret_err(_("bad IPv6 address"));
}
for (i= 0; i < 8; i++) new_addr = opt_malloc(sizeof(struct addrlist));
if (new->addr6.s6_addr[i] != 0) new_addr->next = new->addr6;
break; new_addr->flags = 0;
new_addr->addr.addr6 = in6;
new->addr6 = new_addr;
/* set WILDCARD if network part all zeros */ if (pref)
if (i == 8) {
new->flags |= CONFIG_WILDCARD; u64 addrpart = addr6part(&in6);
new->flags |= CONFIG_ADDR6; if (!atoi_check(pref, &new_addr->prefixlen) ||
} new_addr->prefixlen > 128 ||
#endif ((((u64)1<<(128-new_addr->prefixlen))-1) & addrpart)
else != 0)
{ {
struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_c dhcp_config_free(new);
onfig)); ret_err(_("bad IPv6 prefix"));
if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CH }
ADDR_MAX,
&newhw->wildcard_mask, &newh
w->hwaddr_type)) == -1)
ret_err(_("bad hex constant"));
else
{
newhw->next = new->hwaddr; new_addr->flags |= ADDRLIST_PREFIX;
new->hwaddr = newhw; }
}
} for (i= 0; i < 8; i++)
} if (in6.s6_addr[i] != 0)
else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0)) break;
{
struct dhcp_config *configs;
new->addr = in; /* set WILDCARD if network part all zeros */
new->flags |= CONFIG_ADDR; if (i == 8)
new_addr->flags |= ADDRLIST_WILDCARD;
/* If the same IP appears in more than one host config, then DISCOV new->flags |= CONFIG_ADDR6;
ER }
for one of the hosts will get the address, but REQUEST will be N #endif
AKed, else
since the address is reserved by the other one -> protocol loop.
*/
for (configs = daemon->dhcp_conf; configs; configs = configs->next)
if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.
s_addr)
{ {
sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr
_ntoa(in)); _config));
return 0; if ((newhw->hwaddr_len = parse_hex(arg, newhw->hwaddr, DHCP_C
HADDR_MAX,
&newhw->wildcard_mask, &ne
whw->hwaddr_type)) == -1)
{
free(newhw);
dhcp_config_free(new);
ret_err(_("bad hex constant"));
}
else
{
newhw->next = new->hwaddr;
new->hwaddr = newhw;
}
} }
} }
else else if (strchr(arg, '.') && (inet_pton(AF_INET, arg, &in) > 0))
{ {
char *cp, *lastp = NULL, last = 0; struct dhcp_config *configs;
int fac = 1, isdig = 0;
if (strlen(a[j]) > 1) new->addr = in;
{ new->flags |= CONFIG_ADDR;
lastp = a[j] + strlen(a[j]) - 1;
last = *lastp; /* If the same IP appears in more than one host config, then DISC
switch (last) OVER
for one of the hosts will get the address, but REQUEST will be
NAKed,
since the address is reserved by the other one -> protocol loo
p. */
for (configs = daemon->dhcp_conf; configs; configs = configs->nex
t)
if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == i
n.s_addr)
{ {
case 'w': sprintf(errstr, _("duplicate dhcp-host IP address %s"), in
case 'W': et_ntoa(in));
fac *= 7; return 0;
/* fall through */
case 'd':
case 'D':
fac *= 24;
/* fall through */
case 'h':
case 'H':
fac *= 60;
/* fall through */
case 'm':
case 'M':
fac *= 60;
/* fall through */
case 's':
case 'S':
*lastp = 0;
} }
} }
else
{
char *cp, *lastp = NULL, last = 0;
int fac = 1, isdig = 0;
for (cp = a[j]; *cp; cp++) if (strlen(arg) > 1)
if (isdigit((unsigned char)*cp)) {
isdig = 1; lastp = arg + strlen(arg) - 1;
else if (*cp != ' ') last = *lastp;
break; switch (last)
{
case 'w':
case 'W':
fac *= 7;
/* fall through */
case 'd':
case 'D':
fac *= 24;
/* fall through */
case 'h':
case 'H':
fac *= 60;
/* fall through */
case 'm':
case 'M':
fac *= 60;
/* fall through */
case 's':
case 'S':
*lastp = 0;
}
}
if (*cp) for (cp = arg; *cp; cp++)
{ if (isdigit((unsigned char)*cp))
if (lastp) isdig = 1;
*lastp = last; else if (*cp != ' ')
if (strcmp(a[j], "infinite") == 0) break;
{
new->lease_time = 0xffffffff;
new->flags |= CONFIG_TIME;
}
else if (strcmp(a[j], "ignore") == 0)
new->flags |= CONFIG_DISABLE;
else
{
if (!(new->hostname = canonicalise_opt(a[j])) ||
!legal_hostname(new->hostname))
ret_err(_("bad DHCP host name"));
new->flags |= CONFIG_NAME; if (*cp)
new->domain = strip_hostname(new->hostname); {
} if (lastp)
} *lastp = last;
else if (isdig) if (strcmp(arg, "infinite") == 0)
{ {
new->lease_time = atoi(a[j]) * fac; new->lease_time = 0xffffffff;
/* Leases of a minute or less confuse new->flags |= CONFIG_TIME;
some clients, notably Apple's */ }
if (new->lease_time < 120) else if (strcmp(arg, "ignore") == 0)
new->lease_time = 120; new->flags |= CONFIG_DISABLE;
new->flags |= CONFIG_TIME; else
} {
} if (!(new->hostname = canonicalise_opt(arg)) ||
!legal_hostname(new->hostname))
{
dhcp_config_free(new);
ret_err(_("bad DHCP host name"));
}
new->flags |= CONFIG_NAME;
new->domain = strip_hostname(new->hostname);
}
}
else if (isdig)
{
new->lease_time = atoi(arg) * fac;
/* Leases of a minute or less confuse
some clients, notably Apple's */
if (new->lease_time < 120)
new->lease_time = 120;
new->flags |= CONFIG_TIME;
}
}
arg = comma;
}
daemon->dhcp_conf = new; daemon->dhcp_conf = new;
break; break;
} }
case LOPT_TAG_IF: /* --tag-if */ case LOPT_TAG_IF: /* --tag-if */
{ {
struct tag_if *new = opt_malloc(sizeof(struct tag_if)); struct tag_if *new = opt_malloc(sizeof(struct tag_if));
new->tag = NULL; new->tag = NULL;
skipping to change at line 3243 skipping to change at line 3496
comma = split(arg); comma = split(arg);
len = strlen(arg); len = strlen(arg);
if (len < 5) if (len < 5)
{ {
new->set = NULL; new->set = NULL;
break; break;
} }
else else
{ {
struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)) struct dhcp_netid *newtag = dhcp_netid_create(arg+4, NULL);
;
newtag->net = opt_malloc(len - 3);
strcpy(newtag->net, arg+4);
unhide_metas(newtag->net);
if (strstr(arg, "set:") == arg) if (strstr(arg, "set:") == arg)
{ {
struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dh cp_netid_list)); struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dh cp_netid_list));
newlist->next = new->set; newlist->next = new->set;
new->set = newlist; new->set = newlist;
newlist->list = newtag; newlist->list = newtag;
} }
else if (strstr(arg, "tag:") == arg) else if (strstr(arg, "tag:") == arg)
{ {
newtag->next = new->tag; newtag->next = new->tag;
new->tag = newtag; new->tag = newtag;
} }
else else
{ {
new->set = NULL; new->set = NULL;
free(newtag); dhcp_netid_free(newtag);
break; break;
} }
} }
arg = comma; arg = comma;
} }
if (!new->set) if (!new->set)
ret_err(_("bad tag-if")); {
dhcp_netid_free(new->tag);
dhcp_netid_list_free(new->set);
ret_err_free(_("bad tag-if"), new);
}
break; break;
} }
case 'O': /* --dhcp-option */ case 'O': /* --dhcp-option */
case LOPT_FORCE: /* --dhcp-option-force */ case LOPT_FORCE: /* --dhcp-option-force */
case LOPT_OPTS: case LOPT_OPTS:
case LOPT_MATCH: /* --dhcp-match */ case LOPT_MATCH: /* --dhcp-match */
return parse_dhcp_opt(errstr, arg, return parse_dhcp_opt(errstr, arg,
option == LOPT_FORCE ? DHOPT_FORCE : option == LOPT_FORCE ? DHOPT_FORCE :
skipping to change at line 3314 skipping to change at line 3568
new->name = opt_string_alloc(comma); new->name = opt_string_alloc(comma);
new->next = daemon->dhcp_name_match; new->next = daemon->dhcp_name_match;
daemon->dhcp_name_match = new; daemon->dhcp_name_match = new;
break; break;
} }
case 'M': /* --dhcp-boot */ case 'M': /* --dhcp-boot */
{ {
struct dhcp_netid *id = NULL; struct dhcp_netid *id = dhcp_tags(&arg);
while (is_tag_prefix(arg))
{
struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
newid->next = id;
id = newid;
comma = split(arg);
newid->net = opt_string_alloc(arg+4);
arg = comma;
};
if (!arg) if (!arg)
ret_err(gen_err); {
ret_err(gen_err);
}
else else
{ {
char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL; char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
struct in_addr dhcp_next_server; struct in_addr dhcp_next_server;
struct dhcp_boot *new; struct dhcp_boot *new;
comma = split(arg); comma = split(arg);
dhcp_file = opt_string_alloc(arg); dhcp_file = opt_string_alloc(arg);
dhcp_next_server.s_addr = 0; dhcp_next_server.s_addr = 0;
if (comma) if (comma)
{ {
skipping to change at line 3372 skipping to change at line 3619
new->netid = id; new->netid = id;
new->next = daemon->boot_config; new->next = daemon->boot_config;
daemon->boot_config = new; daemon->boot_config = new;
} }
break; break;
} }
case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */ case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */
{ {
struct dhcp_netid *id = NULL; struct dhcp_netid *id = dhcp_tags(&arg);
while (is_tag_prefix(arg))
{
struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
newid->next = id;
id = newid;
comma = split(arg);
newid->net = opt_string_alloc(arg+4);
arg = comma;
};
if (!arg) if (!arg)
ret_err(gen_err); {
ret_err(gen_err);
}
else else
{ {
struct delay_config *new; struct delay_config *new;
int delay; int delay;
if (!atoi_check(arg, &delay)) if (!atoi_check(arg, &delay))
ret_err(gen_err); ret_err(gen_err);
new = opt_malloc(sizeof(struct delay_config)); new = opt_malloc(sizeof(struct delay_config));
new->delay = delay; new->delay = delay;
new->netid = id; new->netid = id;
skipping to change at line 3409 skipping to change at line 3649
break; break;
} }
case LOPT_PXE_PROMT: /* --pxe-prompt */ case LOPT_PXE_PROMT: /* --pxe-prompt */
{ {
struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt)); struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
int timeout; int timeout;
new->netid = NULL; new->netid = NULL;
new->opt = 10; /* PXE_MENU_PROMPT */ new->opt = 10; /* PXE_MENU_PROMPT */
new->netid = dhcp_tags(&arg);
while (is_tag_prefix(arg))
{
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
comma = split(arg);
nn->next = new->netid;
new->netid = nn;
nn->net = opt_string_alloc(arg+4);
arg = comma;
}
if (!arg) if (!arg)
ret_err(gen_err); {
dhcp_opt_free(new);
ret_err(gen_err);
}
else else
{ {
comma = split(arg); comma = split(arg);
unhide_metas(arg); unhide_metas(arg);
new->len = strlen(arg) + 1; new->len = strlen(arg) + 1;
new->val = opt_malloc(new->len); new->val = opt_malloc(new->len);
memcpy(new->val + 1, arg, new->len - 1); memcpy(new->val + 1, arg, new->len - 1);
new->u.vendor_class = (unsigned char *)"PXEClient"; new->u.vendor_class = (unsigned char *)"PXEClient";
new->flags = DHOPT_VENDOR; new->flags = DHOPT_VENDOR;
skipping to change at line 3457 skipping to change at line 3691
{ {
struct pxe_service *new = opt_malloc(sizeof(struct pxe_service)); struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_ Lean_Client", char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_ Lean_Client",
"IA32_EFI", "x86-64_EFI", "Xscale_EFI", "BC_EFI", "IA32_EFI", "x86-64_EFI", "Xscale_EFI", "BC_EFI",
"ARM32_EFI", "ARM64_EFI", NULL }; "ARM32_EFI", "ARM64_EFI", NULL };
static int boottype = 32768; static int boottype = 32768;
new->netid = NULL; new->netid = NULL;
new->sname = NULL; new->sname = NULL;
new->server.s_addr = 0; new->server.s_addr = 0;
new->netid = dhcp_tags(&arg);
while (is_tag_prefix(arg))
{
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
comma = split(arg);
nn->next = new->netid;
new->netid = nn;
nn->net = opt_string_alloc(arg+4);
arg = comma;
}
if (arg && (comma = split(arg))) if (arg && (comma = split(arg)))
{ {
for (i = 0; CSA[i]; i++) for (i = 0; CSA[i]; i++)
if (strcasecmp(CSA[i], arg) == 0) if (strcasecmp(CSA[i], arg) == 0)
break; break;
if (CSA[i] || atoi_check(arg, &i)) if (CSA[i] || atoi_check(arg, &i))
{ {
arg = comma; arg = comma;
skipping to change at line 3544 skipping to change at line 3769
{ {
if (!(comma = split(arg))) if (!(comma = split(arg)))
ret_err(gen_err); ret_err(gen_err);
else else
{ {
struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac)); struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
new->netid.net = opt_string_alloc(set_prefix(arg)); new->netid.net = opt_string_alloc(set_prefix(arg));
unhide_metas(comma); unhide_metas(comma);
new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new ->mask, &new->hwaddr_type); new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new ->mask, &new->hwaddr_type);
if (new->hwaddr_len == -1) if (new->hwaddr_len == -1)
ret_err(gen_err); {
free(new->netid.net);
ret_err_free(gen_err, new);
}
else else
{ {
new->next = daemon->dhcp_macs; new->next = daemon->dhcp_macs;
daemon->dhcp_macs = new; daemon->dhcp_macs = new;
} }
} }
} }
break; break;
#ifdef OPTION6_PREFIX_CLASS
case LOPT_PREF_CLSS: /* --dhcp-prefix-class */
{
struct prefix_class *new = opt_malloc(sizeof(struct prefix_class));
if (!(comma = split(arg)) ||
!atoi_check16(comma, &new->class))
ret_err(gen_err);
new->tag.net = opt_string_alloc(set_prefix(arg));
new->next = daemon->prefix_classes;
daemon->prefix_classes = new;
break;
}
#endif
case 'U': /* --dhcp-vendorclass */ case 'U': /* --dhcp-vendorclass */
case 'j': /* --dhcp-userclass */ case 'j': /* --dhcp-userclass */
case LOPT_CIRCUIT: /* --dhcp-circuitid */ case LOPT_CIRCUIT: /* --dhcp-circuitid */
case LOPT_REMOTE: /* --dhcp-remoteid */ case LOPT_REMOTE: /* --dhcp-remoteid */
case LOPT_SUBSCR: /* --dhcp-subscrid */ case LOPT_SUBSCR: /* --dhcp-subscrid */
{ {
unsigned char *p; unsigned char *p;
int dig = 0; int dig = 0;
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor)); struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
if (!(comma = split(arg))) if (!(comma = split(arg)))
ret_err(gen_err); ret_err_free(gen_err, new);
new->netid.net = opt_string_alloc(set_prefix(arg)); new->netid.net = opt_string_alloc(set_prefix(arg));
/* check for hex string - must digits may include : must not have nothin g else, /* check for hex string - must digits may include : must not have nothin g else,
only allowed for agent-options. */ only allowed for agent-options. */
arg = comma; arg = comma;
if ((comma = split(arg))) if ((comma = split(arg)))
{ {
if (option != 'U' || strstr(arg, "enterprise:") != arg) if (option != 'U' || strstr(arg, "enterprise:") != arg)
ret_err(gen_err); {
free(new->netid.net);
ret_err_free(gen_err, new);
}
else else
new->enterprise = atoi(arg+11); new->enterprise = atoi(arg+11);
} }
else else
comma = arg; comma = arg;
for (p = (unsigned char *)comma; *p; p++) for (p = (unsigned char *)comma; *p; p++)
if (isxdigit(*p)) if (isxdigit(*p))
dig = 1; dig = 1;
else if (*p != ':') else if (*p != ':')
skipping to change at line 3694 skipping to change at line 3908
new->next = daemon->dhcp_gen_names; new->next = daemon->dhcp_gen_names;
daemon->dhcp_gen_names = new; daemon->dhcp_gen_names = new;
} }
else else
{ {
new->next = daemon->dhcp_ignore_names; new->next = daemon->dhcp_ignore_names;
daemon->dhcp_ignore_names = new; daemon->dhcp_ignore_names = new;
} }
while (arg) { while (arg) {
struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
comma = split(arg); comma = split(arg);
member->next = list; list = dhcp_netid_create(is_tag_prefix(arg) ? arg+4 :arg, list);
list = member;
if (is_tag_prefix(arg))
member->net = opt_string_alloc(arg+4);
else
member->net = opt_string_alloc(arg);
arg = comma; arg = comma;
} }
new->list = list; new->list = list;
break; break;
} }
case LOPT_PROXY: /* --dhcp-proxy */ case LOPT_PROXY: /* --dhcp-proxy */
daemon->override = 1; daemon->override = 1;
while (arg) { while (arg) {
struct addr_list *new = opt_malloc(sizeof(struct addr_list)); struct addr_list *new = opt_malloc(sizeof(struct addr_list));
comma = split(arg); comma = split(arg);
if (!(inet_pton(AF_INET, arg, &new->addr) > 0)) if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
ret_err(_("bad dhcp-proxy address")); ret_err_free(_("bad dhcp-proxy address"), new);
new->next = daemon->override_relays; new->next = daemon->override_relays;
daemon->override_relays = new; daemon->override_relays = new;
arg = comma; arg = comma;
} }
break; break;
case LOPT_RELAY: /* --dhcp-relay */ case LOPT_RELAY: /* --dhcp-relay */
{ {
struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay)); struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
comma = split(arg); comma = split(arg);
skipping to change at line 3741 skipping to change at line 3949
daemon->relay4 = new; daemon->relay4 = new;
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, com ma, &new->server)) else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, com ma, &new->server))
{ {
new->next = daemon->relay6; new->next = daemon->relay6;
daemon->relay6 = new; daemon->relay6 = new;
} }
#endif #endif
else else
ret_err(_("Bad dhcp-relay")); {
free(new->interface);
ret_err_free(_("Bad dhcp-relay"), new);
}
break; break;
} }
#endif #endif
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
case LOPT_RA_PARAM: /* --ra-param */ case LOPT_RA_PARAM: /* --ra-param */
if ((comma = split(arg))) if ((comma = split(arg)))
{ {
skipping to change at line 3781 skipping to change at line 3992
{ {
if (*comma == 'l' || *comma == 'L') if (*comma == 'l' || *comma == 'L')
new->prio = 0x18; new->prio = 0x18;
else else
new->prio = 0x08; new->prio = 0x08;
comma = split(comma); comma = split(comma);
} }
arg = split(comma); arg = split(comma);
if (!atoi_check(comma, &new->interval) || if (!atoi_check(comma, &new->interval) ||
(arg && !atoi_check(arg, &new->lifetime))) (arg && !atoi_check(arg, &new->lifetime)))
{
err: err:
ret_err(_("bad RA-params")); free(new->name);
ret_err_free(_("bad RA-params"), new);
}
new->next = daemon->ra_interfaces; new->next = daemon->ra_interfaces;
daemon->ra_interfaces = new; daemon->ra_interfaces = new;
} }
break; break;
case LOPT_DUID: /* --dhcp-duid */ case LOPT_DUID: /* --dhcp-duid */
if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterpr ise)) if (!(comma = split(arg)) || !atoi_check(arg, (int *)&daemon->duid_enterpr ise))
ret_err(_("bad DUID")); ret_err(_("bad DUID"));
else else
skipping to change at line 3831 skipping to change at line 4045
if ((k < 2) || if ((k < 2) ||
(!(inet_pton(AF_INET, a[0], &new->in) > 0)) || (!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
(!(inet_pton(AF_INET, a[1], &new->out) > 0)) || (!(inet_pton(AF_INET, a[1], &new->out) > 0)) ||
(k == 3 && !inet_pton(AF_INET, a[2], &new->mask))) (k == 3 && !inet_pton(AF_INET, a[2], &new->mask)))
ret_err(_("missing address in alias")); ret_err(_("missing address in alias"));
if (dash && if (dash &&
(!(inet_pton(AF_INET, dash, &new->end) > 0) || (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
!is_same_net(new->in, new->end, new->mask) || !is_same_net(new->in, new->end, new->mask) ||
ntohl(new->in.s_addr) > ntohl(new->end.s_addr))) ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
ret_err(_("invalid alias range")); ret_err_free(_("invalid alias range"), new);
break; break;
} }
case LOPT_INTNAME: /* --interface-name */ case LOPT_INTNAME: /* --interface-name */
{ {
struct interface_name *new, **up; struct interface_name *new, **up;
char *domain = NULL; char *domain = NULL;
comma = split(arg); comma = split(arg);
skipping to change at line 3861 skipping to change at line 4075
of an interface is used for PTR lookups. */ of an interface is used for PTR lookups. */
for (up = &daemon->int_names; *up; up = &((*up)->next)); for (up = &daemon->int_names; *up; up = &((*up)->next));
*up = new; *up = new;
new->name = domain; new->name = domain;
new->family = 0; new->family = 0;
arg = split_chr(comma, '/'); arg = split_chr(comma, '/');
if (arg) if (arg)
{ {
if (strcmp(arg, "4") == 0) if (strcmp(arg, "4") == 0)
new->family = AF_INET; new->family = AF_INET;
#ifdef HAVE_IPV6
else if (strcmp(arg, "6") == 0) else if (strcmp(arg, "6") == 0)
new->family = AF_INET6; new->family = AF_INET6;
#endif
else else
ret_err(gen_err); ret_err_free(gen_err, new);
} }
new->intr = opt_string_alloc(comma); new->intr = opt_string_alloc(comma);
break; break;
} }
case LOPT_CNAME: /* --cname */ case LOPT_CNAME: /* --cname */
{ {
struct cname *new; struct cname *new;
char *alias, *target, *last, *pen; char *alias, *target, *last, *pen;
int ttl = -1; int ttl = -1;
skipping to change at line 3898 skipping to change at line 4110
last = pen; last = pen;
target = canonicalise_opt(last); target = canonicalise_opt(last);
while (arg != last) while (arg != last)
{ {
int arglen = strlen(arg); int arglen = strlen(arg);
alias = canonicalise_opt(arg); alias = canonicalise_opt(arg);
if (!alias || !target) if (!alias || !target)
ret_err(_("bad CNAME")); {
free(target);
free(alias);
ret_err(_("bad CNAME"));
}
for (new = daemon->cnames; new; new = new->next) for (new = daemon->cnames; new; new = new->next)
if (hostname_isequal(new->alias, alias)) if (hostname_isequal(new->alias, alias))
ret_err(_("duplicate CNAME")); {
free(target);
free(alias);
ret_err(_("duplicate CNAME"));
}
new = opt_malloc(sizeof(struct cname)); new = opt_malloc(sizeof(struct cname));
new->next = daemon->cnames; new->next = daemon->cnames;
daemon->cnames = new; daemon->cnames = new;
new->alias = alias; new->alias = alias;
new->target = target; new->target = target;
new->ttl = ttl; new->ttl = ttl;
for (arg += arglen+1; *arg && isspace(*arg); arg++); for (arg += arglen+1; *arg && isspace(*arg); arg++);
} }
skipping to change at line 3925 skipping to change at line 4145
case LOPT_PTR: /* --ptr-record */ case LOPT_PTR: /* --ptr-record */
{ {
struct ptr_record *new; struct ptr_record *new;
char *dom, *target = NULL; char *dom, *target = NULL;
comma = split(arg); comma = split(arg);
if (!(dom = canonicalise_opt(arg)) || if (!(dom = canonicalise_opt(arg)) ||
(comma && !(target = canonicalise_opt(comma)))) (comma && !(target = canonicalise_opt(comma))))
ret_err(_("bad PTR record")); {
free(dom);
free(target);
ret_err(_("bad PTR record"));
}
else else
{ {
new = opt_malloc(sizeof(struct ptr_record)); new = opt_malloc(sizeof(struct ptr_record));
new->next = daemon->ptr; new->next = daemon->ptr;
daemon->ptr = new; daemon->ptr = new;
new->name = dom; new->name = dom;
new->ptr = target; new->ptr = target;
} }
break; break;
} }
case LOPT_NAPTR: /* --naptr-record */ case LOPT_NAPTR: /* --naptr-record */
{ {
char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
int k = 0; int k = 0;
struct naptr *new; struct naptr *new;
int order, pref; int order, pref;
char *name, *replace = NULL; char *name=NULL, *replace = NULL;
if ((a[0] = arg)) if ((a[0] = arg))
for (k = 1; k < 7; k++) for (k = 1; k < 7; k++)
if (!(a[k] = split(a[k-1]))) if (!(a[k] = split(a[k-1])))
break; break;
if (k < 6 || if (k < 6 ||
!(name = canonicalise_opt(a[0])) || !(name = canonicalise_opt(a[0])) ||
!atoi_check16(a[1], &order) || !atoi_check16(a[1], &order) ||
!atoi_check16(a[2], &pref) || !atoi_check16(a[2], &pref) ||
(k == 7 && !(replace = canonicalise_opt(a[6])))) (k == 7 && !(replace = canonicalise_opt(a[6]))))
ret_err(_("bad NAPTR record")); {
free(name);
free(replace);
ret_err(_("bad NAPTR record"));
}
else else
{ {
new = opt_malloc(sizeof(struct naptr)); new = opt_malloc(sizeof(struct naptr));
new->next = daemon->naptr; new->next = daemon->naptr;
daemon->naptr = new; daemon->naptr = new;
new->name = name; new->name = name;
new->flags = opt_string_alloc(a[3]); new->flags = opt_string_alloc(a[3]);
new->services = opt_string_alloc(a[4]); new->services = opt_string_alloc(a[4]);
new->regexp = opt_string_alloc(a[5]); new->regexp = opt_string_alloc(a[5]);
new->replace = replace; new->replace = replace;
skipping to change at line 3977 skipping to change at line 4205
new->pref = pref; new->pref = pref;
} }
break; break;
} }
case LOPT_RR: /* dns-rr */ case LOPT_RR: /* dns-rr */
{ {
struct txt_record *new; struct txt_record *new;
size_t len = 0; size_t len = 0;
char *data; char *data;
int val; int class;
comma = split(arg); comma = split(arg);
data = split(comma); data = split(comma);
new = opt_malloc(sizeof(struct txt_record)); new = opt_malloc(sizeof(struct txt_record));
new->next = daemon->rr; new->name = NULL;
daemon->rr = new;
if (!atoi_check(comma, &val) || if (!atoi_check(comma, &class) ||
!(new->name = canonicalise_opt(arg)) || !(new->name = canonicalise_opt(arg)) ||
(data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL )) == -1U)) (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL )) == -1U))
ret_err(_("bad RR record")); {
free(new->name);
ret_err_free(_("bad RR record"), new);
}
new->class = val;
new->len = 0; new->len = 0;
new->class = class;
new->next = daemon->rr;
daemon->rr = new;
if (data) if (data)
{ {
new->txt = opt_malloc(len); new->txt = opt_malloc(len);
new->len = len; new->len = len;
memcpy(new->txt, data, len); memcpy(new->txt, data, len);
} }
break; break;
} }
skipping to change at line 4044 skipping to change at line 4276
case 'Y': /* --txt-record */ case 'Y': /* --txt-record */
{ {
struct txt_record *new; struct txt_record *new;
unsigned char *p, *cnt; unsigned char *p, *cnt;
size_t len; size_t len;
comma = split(arg); comma = split(arg);
new = opt_malloc(sizeof(struct txt_record)); new = opt_malloc(sizeof(struct txt_record));
new->next = daemon->txt;
daemon->txt = new;
new->class = C_IN; new->class = C_IN;
new->stat = 0; new->stat = 0;
if (!(new->name = canonicalise_opt(arg))) if (!(new->name = canonicalise_opt(arg)))
ret_err(_("bad TXT record")); ret_err_free(_("bad TXT record"), new);
new->next = daemon->txt;
daemon->txt = new;
len = comma ? strlen(comma) : 0; len = comma ? strlen(comma) : 0;
len += (len/255) + 1; /* room for extra counts */ len += (len/255) + 1; /* room for extra counts */
new->txt = p = opt_malloc(len); new->txt = p = opt_malloc(len);
cnt = p++; cnt = p++;
*cnt = 0; *cnt = 0;
while (comma && *comma) while (comma && *comma)
{ {
unsigned char c = (unsigned char)*comma++; unsigned char c = (unsigned char)*comma++;
skipping to change at line 4098 skipping to change at line 4330
comma = split(arg); comma = split(arg);
if (!(name = canonicalise_opt(arg))) if (!(name = canonicalise_opt(arg)))
ret_err(_("bad SRV record")); ret_err(_("bad SRV record"));
if (comma) if (comma)
{ {
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
if (!(target = canonicalise_opt(arg))) if (!(target = canonicalise_opt(arg)))
ret_err(_("bad SRV target")); ret_err_free(_("bad SRV target"), name);
if (comma) if (comma)
{ {
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
if (!atoi_check16(arg, &port)) if (!atoi_check16(arg, &port))
ret_err(_("invalid port number")); {
free(name);
ret_err_free(_("invalid port number"), target);
}
if (comma) if (comma)
{ {
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
if (!atoi_check16(arg, &priority)) if (!atoi_check16(arg, &priority))
ret_err(_("invalid priority")); {
free(name);
ret_err_free(_("invalid priority"), target);
}
if (comma && !atoi_check16(comma, &weight)) if (comma && !atoi_check16(comma, &weight))
ret_err(_("invalid weight")); {
free(name);
ret_err_free(_("invalid weight"), target);
}
} }
} }
} }
new = opt_malloc(sizeof(struct mx_srv_record)); new = opt_malloc(sizeof(struct mx_srv_record));
new->next = daemon->mxnames; new->next = daemon->mxnames;
daemon->mxnames = new; daemon->mxnames = new;
new->issrv = 1; new->issrv = 1;
new->name = name; new->name = name;
new->target = target; new->target = target;
new->srvport = port; new->srvport = port;
new->priority = priority; new->priority = priority;
new->weight = weight; new->weight = weight;
break; break;
} }
case LOPT_HOST_REC: /* --host-record */ case LOPT_HOST_REC: /* --host-record */
{ {
struct host_record *new = opt_malloc(sizeof(struct host_record)); struct host_record *new;
memset(new, 0, sizeof(struct host_record));
new->ttl = -1;
if (!arg || !(comma = split(arg))) if (!arg || !(comma = split(arg)))
ret_err(_("Bad host-record")); ret_err(_("Bad host-record"));
new = opt_malloc(sizeof(struct host_record));
memset(new, 0, sizeof(struct host_record));
new->ttl = -1;
new->flags = 0;
while (arg) while (arg)
{ {
struct all_addr addr; union all_addr addr;
char *dig; char *dig;
for (dig = arg; *dig != 0; dig++) for (dig = arg; *dig != 0; dig++)
if (*dig < '0' || *dig > '9') if (*dig < '0' || *dig > '9')
break; break;
if (*dig == 0) if (*dig == 0)
new->ttl = atoi(arg); new->ttl = atoi(arg);
else if (inet_pton(AF_INET, arg, &addr)) else if (inet_pton(AF_INET, arg, &addr.addr4))
new->addr = addr.addr.addr4; {
#ifdef HAVE_IPV6 new->addr = addr.addr4;
else if (inet_pton(AF_INET6, arg, &addr)) new->flags |= HR_4;
new->addr6 = addr.addr.addr6; }
#endif else if (inet_pton(AF_INET6, arg, &addr.addr6))
{
new->addr6 = addr.addr6;
new->flags |= HR_6;
}
else else
{ {
int nomem; int nomem;
char *canon = canonicalise(arg, &nomem); char *canon = canonicalise(arg, &nomem);
struct name_list *nl = opt_malloc(sizeof(struct name_list)); struct name_list *nl;
if (!canon) if (!canon)
ret_err(_("Bad name in host-record")); {
struct name_list *tmp = new->names, *next;
for (tmp = new->names; tmp; tmp = next)
{
next = tmp->next;
free(tmp);
}
ret_err_free(_("Bad name in host-record"), new);
}
nl = opt_malloc(sizeof(struct name_list));
nl->name = canon; nl->name = canon;
/* keep order, so that PTR record goes to first name */ /* keep order, so that PTR record goes to first name */
nl->next = NULL; nl->next = NULL;
if (!new->names) if (!new->names)
new->names = nl; new->names = nl;
else else
{ {
struct name_list *tmp; struct name_list *tmp;
for (tmp = new->names; tmp->next; tmp = tmp->next); for (tmp = new->names; tmp->next; tmp = tmp->next);
tmp->next = nl; tmp->next = nl;
skipping to change at line 4214 skipping to change at line 4470
} }
break; break;
case LOPT_TRUST_ANCHOR: /* --trust-anchor */ case LOPT_TRUST_ANCHOR: /* --trust-anchor */
{ {
struct ds_config *new = opt_malloc(sizeof(struct ds_config)); struct ds_config *new = opt_malloc(sizeof(struct ds_config));
char *cp, *cp1, *keyhex, *digest, *algo = NULL; char *cp, *cp1, *keyhex, *digest, *algo = NULL;
int len; int len;
new->class = C_IN; new->class = C_IN;
new->name = NULL;
if ((comma = split(arg)) && (algo = split(comma))) if ((comma = split(arg)) && (algo = split(comma)))
{ {
int class = 0; int class = 0;
if (strcmp(comma, "IN") == 0) if (strcmp(comma, "IN") == 0)
class = C_IN; class = C_IN;
else if (strcmp(comma, "CH") == 0) else if (strcmp(comma, "CH") == 0)
class = C_CHAOS; class = C_CHAOS;
else if (strcmp(comma, "HS") == 0) else if (strcmp(comma, "HS") == 0)
class = C_HESIOD; class = C_HESIOD;
skipping to change at line 4238 skipping to change at line 4495
comma = algo; comma = algo;
algo = split(comma); algo = split(comma);
} }
} }
if (!comma || !algo || !(digest = split(algo)) || !(keyhex = spli t(digest)) || if (!comma || !algo || !(digest = split(algo)) || !(keyhex = spli t(digest)) ||
!atoi_check16(comma, &new->keytag) || !atoi_check16(comma, &new->keytag) ||
!atoi_check8(algo, &new->algo) || !atoi_check8(algo, &new->algo) ||
!atoi_check8(digest, &new->digest_type) || !atoi_check8(digest, &new->digest_type) ||
!(new->name = canonicalise_opt(arg))) !(new->name = canonicalise_opt(arg)))
ret_err(_("bad trust anchor")); ret_err_free(_("bad trust anchor"), new);
/* Upper bound on length */ /* Upper bound on length */
len = (2*strlen(keyhex))+1; len = (2*strlen(keyhex))+1;
new->digest = opt_malloc(len); new->digest = opt_malloc(len);
unhide_metas(keyhex); unhide_metas(keyhex);
/* 4034: "Whitespace is allowed within digits" */ /* 4034: "Whitespace is allowed within digits" */
for (cp = keyhex; *cp; ) for (cp = keyhex; *cp; )
if (isspace(*cp)) if (isspace(*cp))
for (cp1 = cp; *cp1; cp1++) for (cp1 = cp; *cp1; cp1++)
*cp1 = *(cp1+1); *cp1 = *(cp1+1);
else else
cp++; cp++;
if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len , NULL, NULL)) == -1) if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len , NULL, NULL)) == -1)
ret_err(_("bad HEX in trust anchor")); {
free(new->name);
ret_err_free(_("bad HEX in trust anchor"), new);
}
new->next = daemon->ds; new->next = daemon->ds;
daemon->ds = new; daemon->ds = new;
break; break;
} }
#endif #endif
default: default:
ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/T FTP/DNSSEC/DBus support)")); ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/T FTP/DNSSEC/DBus support)"));
skipping to change at line 4719 skipping to change at line 4979
set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0); set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
# endif # endif
} }
#endif #endif
void read_opts(int argc, char **argv, char *compile_opts) void read_opts(int argc, char **argv, char *compile_opts)
{ {
size_t argbuf_size = MAXDNAME; size_t argbuf_size = MAXDNAME;
char *argbuf = opt_malloc(argbuf_size); char *argbuf = opt_malloc(argbuf_size);
char *buff = opt_malloc(MAXDNAME); char *buff = opt_malloc(MAXDNAME);
int option, conffile_opt = '7', testmode = 0; int option, testmode = 0;
char *arg, *conffile = CONFFILE; char *arg, *conffile = NULL;
opterr = 0; opterr = 0;
daemon = opt_malloc(sizeof(struct daemon)); daemon = opt_malloc(sizeof(struct daemon));
memset(daemon, 0, sizeof(struct daemon)); memset(daemon, 0, sizeof(struct daemon));
daemon->namebuff = buff; daemon->namebuff = buff;
/* Set defaults - everything else is zero or NULL */ /* Set defaults - everything else is zero or NULL */
daemon->cachesize = CACHESIZ; daemon->cachesize = CACHESIZ;
daemon->ftabsize = FTABSIZ; daemon->ftabsize = FTABSIZ;
skipping to change at line 4829 skipping to change at line 5089
{ {
printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT); printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT);
printf(_("Compile time options: %s\n\n"), compile_opts); printf(_("Compile time options: %s\n\n"), compile_opts);
printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n")); printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n")); printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
printf(_("under the terms of the GNU General Public License, version 2 or 3.\n")); printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
exit(0); exit(0);
} }
else if (option == 'C') else if (option == 'C')
{ {
conffile_opt = 0; /* file must exist */ if (!conffile)
conffile = opt_string_alloc(arg); conffile = opt_string_alloc(arg);
else
{
char *extra = opt_string_alloc(arg);
one_file(extra, 0);
free(extra);
}
} }
else else
{ {
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1, 0)) if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1, 0))
#else #else
if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0)) if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0))
#endif #endif
die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF); die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
} }
} }
free(argbuf); free(argbuf);
if (conffile) if (conffile)
{ {
one_file(conffile, conffile_opt); one_file(conffile, 0);
if (conffile_opt == 0) free(conffile);
free(conffile);
} }
else
one_file(CONFFILE, '7');
/* port might not be known when the address is parsed - fill in here */ /* port might not be known when the address is parsed - fill in here */
if (daemon->servers) if (daemon->servers)
{ {
struct server *tmp; struct server *tmp;
for (tmp = daemon->servers; tmp; tmp = tmp->next) for (tmp = daemon->servers; tmp; tmp = tmp->next)
if (!(tmp->flags & SERV_HAS_SOURCE)) if (!(tmp->flags & SERV_HAS_SOURCE))
{ {
if (tmp->source_addr.sa.sa_family == AF_INET) if (tmp->source_addr.sa.sa_family == AF_INET)
tmp->source_addr.in.sin_port = htons(daemon->query_port); tmp->source_addr.in.sin_port = htons(daemon->query_port);
#ifdef HAVE_IPV6
else if (tmp->source_addr.sa.sa_family == AF_INET6) else if (tmp->source_addr.sa.sa_family == AF_INET6)
tmp->source_addr.in6.sin6_port = htons(daemon->query_port); tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
#endif
} }
} }
if (daemon->host_records) if (daemon->host_records)
{ {
struct host_record *hr; struct host_record *hr;
for (hr = daemon->host_records; hr; hr = hr->next) for (hr = daemon->host_records; hr; hr = hr->next)
if (hr->ttl == -1) if (hr->ttl == -1)
hr->ttl = daemon->local_ttl; hr->ttl = daemon->local_ttl;
} }
if (daemon->cnames) if (daemon->cnames)
{ {
struct cname *cn, *cn2, *cn3; struct cname *cn, *cn2, *cn3;
#define NOLOOP 1 #define NOLOOP 1
#define TESTLOOP 2 #define TESTLOOP 2
/* Fill in TTL for CNAMES noe we have local_ttl. /* Fill in TTL for CNAMES now we have local_ttl.
Also prepare to do loop detection. */ Also prepare to do loop detection. */
for (cn = daemon->cnames; cn; cn = cn->next) for (cn = daemon->cnames; cn; cn = cn->next)
{ {
if (cn->ttl == -1) if (cn->ttl == -1)
cn->ttl = daemon->local_ttl; cn->ttl = daemon->local_ttl;
cn->flag = 0; cn->flag = 0;
cn->targetp = NULL; cn->targetp = NULL;
for (cn2 = daemon->cnames; cn2; cn2 = cn2->next) for (cn2 = daemon->cnames; cn2; cn2 = cn2->next)
if (hostname_isequal(cn->target, cn2->alias)) if (hostname_isequal(cn->target, cn2->alias))
{ {
skipping to change at line 4925 skipping to change at line 5190
cn3->flag = NOLOOP; cn3->flag = NOLOOP;
} }
} }
if (daemon->if_addrs) if (daemon->if_addrs)
{ {
struct iname *tmp; struct iname *tmp;
for(tmp = daemon->if_addrs; tmp; tmp = tmp->next) for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (tmp->addr.sa.sa_family == AF_INET) if (tmp->addr.sa.sa_family == AF_INET)
tmp->addr.in.sin_port = htons(daemon->port); tmp->addr.in.sin_port = htons(daemon->port);
#ifdef HAVE_IPV6
else if (tmp->addr.sa.sa_family == AF_INET6) else if (tmp->addr.sa.sa_family == AF_INET6)
tmp->addr.in6.sin6_port = htons(daemon->port); tmp->addr.in6.sin6_port = htons(daemon->port);
#endif /* IPv6 */
} }
/* create default, if not specified */ /* create default, if not specified */
if (daemon->authserver && !daemon->hostmaster) if (daemon->authserver && !daemon->hostmaster)
{ {
strcpy(buff, "hostmaster."); strcpy(buff, "hostmaster.");
strcat(buff, daemon->authserver); strcat(buff, daemon->authserver);
daemon->hostmaster = opt_string_alloc(buff); daemon->hostmaster = opt_string_alloc(buff);
} }
 End of changes. 217 change blocks. 
439 lines changed or deleted 702 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)