Home | History | Annotate | Download | only in src
      1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
      2 
      3    This program is free software; you can redistribute it and/or modify
      4    it under the terms of the GNU General Public License as published by
      5    the Free Software Foundation; version 2 dated June, 1991, or
      6    (at your option) version 3 dated 29 June, 2007.
      7 
      8    This program is distributed in the hope that it will be useful,
      9    but WITHOUT ANY WARRANTY; without even the implied warranty of
     10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11    GNU General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License
     14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15 */
     16 
     17 /* define this to get facilitynames */
     18 #define SYSLOG_NAMES
     19 #include <setjmp.h>
     20 #include "dnsmasq.h"
     21 
     22 static volatile int mem_recover = 0;
     23 static jmp_buf mem_jmp;
     24 static void one_file(char* file, int nest, int hard_opt);
     25 
     26 #ifndef HAVE_GETOPT_LONG
     27 struct myoption {
     28     const char* name;
     29     int has_arg;
     30     int* flag;
     31     int val;
     32 };
     33 #endif
     34 
     35 #define OPTSTRING                                                                                 \
     36     "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:" \
     37     "6:7:8:0:3:"
     38 
     39 /* options which don't have a one-char version */
     40 #define LOPT_RELOAD 256
     41 #define LOPT_NO_NAMES 257
     42 #define LOPT_TFTP 258
     43 #define LOPT_SECURE 259
     44 #define LOPT_PREFIX 260
     45 #define LOPT_PTR 261
     46 #define LOPT_BRIDGE 262
     47 #define LOPT_TFTP_MAX 263
     48 #define LOPT_FORCE 264
     49 #define LOPT_NOBLOCK 265
     50 #define LOPT_LOG_OPTS 266
     51 #define LOPT_MAX_LOGS 267
     52 #define LOPT_CIRCUIT 268
     53 #define LOPT_REMOTE 269
     54 #define LOPT_SUBSCR 270
     55 #define LOPT_INTNAME 271
     56 #define LOPT_BANK 272
     57 #define LOPT_DHCP_HOST 273
     58 #define LOPT_APREF 274
     59 #define LOPT_OVERRIDE 275
     60 #define LOPT_TFTPPORTS 276
     61 #define LOPT_REBIND 277
     62 #define LOPT_NOLAST 278
     63 #define LOPT_OPTS 279
     64 #define LOPT_DHCP_OPTS 280
     65 #define LOPT_MATCH 281
     66 #define LOPT_BROADCAST 282
     67 #define LOPT_NEGTTL 283
     68 #define LOPT_ALTPORT 284
     69 #define LOPT_SCRIPTUSR 285
     70 #define LOPT_LOCAL 286
     71 #define LOPT_NAPTR 287
     72 #define LOPT_MINPORT 288
     73 #define LOPT_DHCP_FQDN 289
     74 #define LOPT_CNAME 290
     75 #define LOPT_PXE_PROMT 291
     76 #define LOPT_PXE_SERV 292
     77 #define LOPT_TEST 293
     78 #define LOPT_LISTNMARK 294
     79 
     80 #ifdef HAVE_GETOPT_LONG
     81 static const struct option opts[] =
     82 #else
     83 static const struct myoption opts[] =
     84 #endif
     85     {{"version", 0, 0, 'v'},
     86      {"no-hosts", 0, 0, 'h'},
     87      {"no-poll", 0, 0, 'n'},
     88      {"help", 0, 0, 'w'},
     89      {"no-daemon", 0, 0, 'd'},
     90      {"log-queries", 0, 0, 'q'},
     91      {"user", 1, 0, 'u'},
     92      {"group", 2, 0, 'g'},
     93      {"resolv-file", 2, 0, 'r'},
     94      {"mx-host", 1, 0, 'm'},
     95      {"mx-target", 1, 0, 't'},
     96      {"cache-size", 2, 0, 'c'},
     97      {"port", 1, 0, 'p'},
     98      {"dhcp-leasefile", 2, 0, 'l'},
     99      {"dhcp-lease", 1, 0, 'l'},
    100      {"dhcp-host", 1, 0, 'G'},
    101      {"dhcp-range", 1, 0, 'F'},
    102      {"dhcp-option", 1, 0, 'O'},
    103      {"dhcp-boot", 1, 0, 'M'},
    104      {"domain", 1, 0, 's'},
    105      {"domain-suffix", 1, 0, 's'},
    106      {"interface", 1, 0, 'i'},
    107      {"listen-address", 1, 0, 'a'},
    108      {"bogus-priv", 0, 0, 'b'},
    109      {"bogus-nxdomain", 1, 0, 'B'},
    110      {"selfmx", 0, 0, 'e'},
    111      {"filterwin2k", 0, 0, 'f'},
    112      {"pid-file", 2, 0, 'x'},
    113      {"strict-order", 0, 0, 'o'},
    114      {"server", 1, 0, 'S'},
    115      {"local", 1, 0, LOPT_LOCAL},
    116      {"address", 1, 0, 'A'},
    117      {"conf-file", 2, 0, 'C'},
    118      {"no-resolv", 0, 0, 'R'},
    119      {"expand-hosts", 0, 0, 'E'},
    120      {"localmx", 0, 0, 'L'},
    121      {"local-ttl", 1, 0, 'T'},
    122      {"no-negcache", 0, 0, 'N'},
    123      {"addn-hosts", 1, 0, 'H'},
    124      {"query-port", 1, 0, 'Q'},
    125      {"except-interface", 1, 0, 'I'},
    126      {"no-dhcp-interface", 1, 0, '2'},
    127      {"domain-needed", 0, 0, 'D'},
    128      {"dhcp-lease-max", 1, 0, 'X'},
    129      {"bind-interfaces", 0, 0, 'z'},
    130      {"alias", 1, 0, 'V'},
    131      {"dhcp-vendorclass", 1, 0, 'U'},
    132      {"dhcp-userclass", 1, 0, 'j'},
    133      {"dhcp-ignore", 1, 0, 'J'},
    134      {"edns-packet-max", 1, 0, 'P'},
    135      {"keep-in-foreground", 0, 0, 'k'},
    136      {"dhcp-authoritative", 0, 0, 'K'},
    137      {"srv-host", 1, 0, 'W'},
    138      {"localise-queries", 0, 0, 'y'},
    139      {"txt-record", 1, 0, 'Y'},
    140      {"enable-dbus", 0, 0, '1'},
    141      {"bootp-dynamic", 2, 0, '3'},
    142      {"dhcp-mac", 1, 0, '4'},
    143      {"no-ping", 0, 0, '5'},
    144      {"dhcp-script", 1, 0, '6'},
    145      {"conf-dir", 1, 0, '7'},
    146      {"log-facility", 1, 0, '8'},
    147      {"leasefile-ro", 0, 0, '9'},
    148      {"dns-forward-max", 1, 0, '0'},
    149      {"clear-on-reload", 0, 0, LOPT_RELOAD},
    150      {"dhcp-ignore-names", 2, 0, LOPT_NO_NAMES},
    151      {"enable-tftp", 0, 0, LOPT_TFTP},
    152      {"tftp-secure", 0, 0, LOPT_SECURE},
    153      {"tftp-unique-root", 0, 0, LOPT_APREF},
    154      {"tftp-root", 1, 0, LOPT_PREFIX},
    155      {"tftp-max", 1, 0, LOPT_TFTP_MAX},
    156      {"ptr-record", 1, 0, LOPT_PTR},
    157      {"naptr-record", 1, 0, LOPT_NAPTR},
    158      {"bridge-interface", 1, 0, LOPT_BRIDGE},
    159      {"dhcp-option-force", 1, 0, LOPT_FORCE},
    160      {"tftp-no-blocksize", 0, 0, LOPT_NOBLOCK},
    161      {"log-dhcp", 0, 0, LOPT_LOG_OPTS},
    162      {"log-async", 2, 0, LOPT_MAX_LOGS},
    163      {"dhcp-circuitid", 1, 0, LOPT_CIRCUIT},
    164      {"dhcp-remoteid", 1, 0, LOPT_REMOTE},
    165      {"dhcp-subscrid", 1, 0, LOPT_SUBSCR},
    166      {"interface-name", 1, 0, LOPT_INTNAME},
    167      {"dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST},
    168      {"dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS},
    169      {"dhcp-no-override", 0, 0, LOPT_OVERRIDE},
    170      {"tftp-port-range", 1, 0, LOPT_TFTPPORTS},
    171      {"stop-dns-rebind", 0, 0, LOPT_REBIND},
    172      {"all-servers", 0, 0, LOPT_NOLAST},
    173      {"dhcp-match", 1, 0, LOPT_MATCH},
    174      {"dhcp-broadcast", 1, 0, LOPT_BROADCAST},
    175      {"neg-ttl", 1, 0, LOPT_NEGTTL},
    176      {"dhcp-alternate-port", 2, 0, LOPT_ALTPORT},
    177      {"dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR},
    178      {"min-port", 1, 0, LOPT_MINPORT},
    179      {"dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN},
    180      {"cname", 1, 0, LOPT_CNAME},
    181      {"pxe-prompt", 1, 0, LOPT_PXE_PROMT},
    182      {"pxe-service", 1, 0, LOPT_PXE_SERV},
    183 #ifdef __ANDROID__
    184      {"listen-mark", 1, 0, LOPT_LISTNMARK},
    185 #endif /* __ANDROID__ */
    186      {"test", 0, 0, LOPT_TEST},
    187      {NULL, 0, 0, 0}};
    188 
    189 /* These must have more the one '1' bit */
    190 #define ARG_DUP 3
    191 #define ARG_ONE 5
    192 #define ARG_USED_CL 7
    193 #define ARG_USED_FILE 9
    194 
    195 static struct {
    196     int opt;
    197     unsigned int rept;
    198     char* const flagdesc;
    199     char* const desc;
    200     char* const arg;
    201 } usage[] = {
    202     {'a', ARG_DUP, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL},
    203     {'A', ARG_DUP, "/domain/ipaddr",
    204      gettext_noop("Return ipaddr for all hosts in specified domains."), NULL},
    205     {'b', OPT_BOGUSPRIV, NULL,
    206      gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL},
    207     {'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."),
    208      NULL},
    209     {'c', ARG_ONE, "cachesize",
    210      gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$"},
    211     {'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE},
    212     {'d', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."),
    213      NULL},
    214     {'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL},
    215     {'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL},
    216     {'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."),
    217      NULL},
    218     {'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."),
    219      NULL},
    220     {'F', ARG_DUP, "ipaddr,ipaddr,time",
    221      gettext_noop("Enable DHCP in the range given with lease duration."), NULL},
    222     {'g', ARG_ONE, "groupname",
    223      gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP},
    224     {'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."),
    225      NULL},
    226     {LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL},
    227     {LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL},
    228     {'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE},
    229     {'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."),
    230      HOSTSFILE},
    231     {'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL},
    232     {'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on."), NULL},
    233     {'j', ARG_DUP, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL},
    234     {LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL},
    235     {LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL},
    236     {LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."),
    237      NULL},
    238     {'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL},
    239     {LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]",
    240      gettext_noop("Force broadcast replies for hosts with tag set."), NULL},
    241     {'k', OPT_NO_FORK, NULL,
    242      gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL},
    243     {'K', OPT_AUTHORITATIVE, NULL,
    244      gettext_noop("Assume we are the only DHCP server on the local network."), NULL},
    245     {'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."),
    246      LEASEFILE},
    247     {'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL},
    248     {'m', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL},
    249     {'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL},
    250     {'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."),
    251      RESOLVFILE},
    252     {'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL},
    253     {'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."),
    254      RESOLVFILE},
    255     {'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL},
    256     {LOPT_FORCE, ARG_DUP, "<optspec>",
    257      gettext_noop("DHCP option sent even if the client does not request it."), NULL},
    258     {'p', ARG_ONE, "number",
    259      gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL},
    260     {'P', ARG_ONE, "<size>",
    261      gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*"},
    262     {'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL},
    263     {'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."),
    264      NULL},
    265     {'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL},
    266     {'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."),
    267      RESOLVFILE},
    268     {'S', ARG_DUP, "/domain/ipaddr",
    269      gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL},
    270     {LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."),
    271      NULL},
    272     {'s', ARG_DUP, "<domain>[,<range>]",
    273      gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL},
    274     {'t', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL},
    275     {'T', ARG_ONE, "time",
    276      gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL},
    277     {LOPT_NEGTTL, ARG_ONE, "time",
    278      gettext_noop("Specify time-to-live in seconds for negative caching."), NULL},
    279     {'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."),
    280      CHUSER},
    281     {'U', ARG_DUP, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL},
    282     {'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL},
    283     {'V', ARG_DUP, "addr,addr,mask",
    284      gettext_noop("Translate IPv4 addresses from upstream servers."), NULL},
    285     {'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL},
    286     {'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."),
    287      NULL},
    288     {'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE},
    289     {'X', ARG_ONE, "number",
    290      gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&"},
    291     {'y', OPT_LOCALISE, NULL,
    292      gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL},
    293     {'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL},
    294     {LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL},
    295     {LOPT_INTNAME, ARG_DUP, "name,interface",
    296      gettext_noop("Give DNS name to IPv4 address of interface."), NULL},
    297     {'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL},
    298     {'1', OPT_DBUS, NULL,
    299      gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL},
    300     {'2', ARG_DUP, "interface",
    301      gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL},
    302     {'3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."),
    303      NULL},
    304     {'4', ARG_DUP, "<id>,<mac address>",
    305      gettext_noop("Map MAC address (with wildcards) to option set."), NULL},
    306     {LOPT_BRIDGE, ARG_DUP, "iface,alias,..",
    307      gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL},
    308     {'5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."),
    309      NULL},
    310     {'6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."),
    311      NULL},
    312     {'7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."),
    313      NULL},
    314     {'8', ARG_ONE, "<facilty>|<file>",
    315      gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL},
    316     {'9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL},
    317     {'0', ARG_ONE, "<queries>",
    318      gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!"},
    319     {LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE},
    320     {LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]",
    321      gettext_noop("Ignore hostnames provided by DHCP clients."), NULL},
    322     {LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL,
    323      gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL},
    324     {LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL},
    325     {LOPT_PREFIX, ARG_ONE, "<directory>",
    326      gettext_noop("Export files by TFTP only from the specified subtree."), NULL},
    327     {LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL},
    328     {LOPT_SECURE, OPT_TFTP_SECURE, NULL,
    329      gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL},
    330     {LOPT_TFTP_MAX, ARG_ONE, "<connections>",
    331      gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#"},
    332     {LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."),
    333      NULL},
    334     {LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>",
    335      gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL},
    336     {LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL},
    337     {LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]",
    338      gettext_noop("Enable async. logging; optionally set queue length."), NULL},
    339     {LOPT_REBIND, OPT_NO_REBIND, NULL,
    340      gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL},
    341     {LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."),
    342      NULL},
    343     {LOPT_MATCH, ARG_DUP, "<netid>,<optspec>",
    344      gettext_noop("Set tag if client includes matching option in request."), NULL},
    345     {LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL},
    346     {LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."),
    347      NULL},
    348     {LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL},
    349     {LOPT_MINPORT, ARG_ONE, "<port>",
    350      gettext_noop("Specify lowest port available for DNS query transmission."), NULL},
    351     {LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL,
    352      gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL},
    353     {LOPT_CNAME, ARG_DUP, "<alias>,<target>",
    354      gettext_noop("Specify alias name for LOCAL DNS name."), NULL},
    355     {LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]",
    356      gettext_noop("Prompt to send to PXE clients."), NULL},
    357     {LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL},
    358     {LOPT_LISTNMARK, ARG_ONE, NULL, gettext_noop("Socket mark to use for listen sockets."), NULL},
    359     {LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL},
    360     {0, 0, NULL, NULL, NULL}};
    361 
    362 #ifdef HAVE_DHCP
    363 /* makes options which take a list of addresses */
    364 #define OT_ADDR_LIST 0x80
    365 /* DHCP-internal options, for logging. not valid in config file */
    366 #define OT_INTERNAL 0x40
    367 #define OT_NAME 0x20
    368 
    369 static const struct {
    370     char* name;
    371     unsigned char val, size;
    372 } opttab[] = {{"netmask", 1, OT_ADDR_LIST},
    373               {"time-offset", 2, 4},
    374               {"router", 3, OT_ADDR_LIST},
    375               {"dns-server", 6, OT_ADDR_LIST},
    376               {"log-server", 7, OT_ADDR_LIST},
    377               {"lpr-server", 9, OT_ADDR_LIST},
    378               {"hostname", 12, OT_INTERNAL | OT_NAME},
    379               {"boot-file-size", 13, 2},
    380               {"domain-name", 15, OT_NAME},
    381               {"swap-server", 16, OT_ADDR_LIST},
    382               {"root-path", 17, 0},
    383               {"extension-path", 18, 0},
    384               {"ip-forward-enable", 19, 1},
    385               {"non-local-source-routing", 20, 1},
    386               {"policy-filter", 21, OT_ADDR_LIST},
    387               {"max-datagram-reassembly", 22, 2},
    388               {"default-ttl", 23, 1},
    389               {"mtu", 26, 2},
    390               {"all-subnets-local", 27, 1},
    391               {"broadcast", 28, OT_INTERNAL | OT_ADDR_LIST},
    392               {"router-discovery", 31, 1},
    393               {"router-solicitation", 32, OT_ADDR_LIST},
    394               {"static-route", 33, OT_ADDR_LIST},
    395               {"trailer-encapsulation", 34, 1},
    396               {"arp-timeout", 35, 4},
    397               {"ethernet-encap", 36, 1},
    398               {"tcp-ttl", 37, 1},
    399               {"tcp-keepalive", 38, 4},
    400               {"nis-domain", 40, 0},
    401               {"nis-server", 41, OT_ADDR_LIST},
    402               {"ntp-server", 42, OT_ADDR_LIST},
    403               {"vendor-encap", 43, OT_INTERNAL},
    404               {"netbios-ns", 44, OT_ADDR_LIST},
    405               {"netbios-dd", 45, OT_ADDR_LIST},
    406               {"netbios-nodetype", 46, 1},
    407               {"netbios-scope", 47, 0},
    408               {"x-windows-fs", 48, OT_ADDR_LIST},
    409               {"x-windows-dm", 49, OT_ADDR_LIST},
    410               {"requested-address", 50, OT_INTERNAL | OT_ADDR_LIST},
    411               {"lease-time", 51, OT_INTERNAL},
    412               {"option-overload", 52, OT_INTERNAL},
    413               {
    414                   "message-type",
    415                   53,
    416                   OT_INTERNAL,
    417               },
    418               {"server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST},
    419               {"parameter-request", 55, OT_INTERNAL},
    420               {"message", 56, OT_INTERNAL},
    421               {"max-message-size", 57, OT_INTERNAL},
    422               {"T1", 58, OT_INTERNAL},
    423               {"T2", 59, OT_INTERNAL},
    424               {"vendor-class", 60, 0},
    425               {"client-id", 61, OT_INTERNAL},
    426               {"nis+-domain", 64, 0},
    427               {"nis+-server", 65, OT_ADDR_LIST},
    428               {"tftp-server", 66, 0},
    429               {"bootfile-name", 67, 0},
    430               {"mobile-ip-home", 68, OT_ADDR_LIST},
    431               {"smtp-server", 69, OT_ADDR_LIST},
    432               {"pop3-server", 70, OT_ADDR_LIST},
    433               {"nntp-server", 71, OT_ADDR_LIST},
    434               {"irc-server", 74, OT_ADDR_LIST},
    435               {"user-class", 77, 0},
    436               {"FQDN", 81, OT_INTERNAL},
    437               {"agent-id", 82, OT_INTERNAL},
    438               {"client-arch", 93, 2},
    439               {"client-interface-id", 94, 0},
    440               {"client-machine-id", 97, 0},
    441               {"subnet-select", 118, OT_INTERNAL},
    442               {"domain-search", 119, 0},
    443               {"sip-server", 120, 0},
    444               {"classless-static-route", 121, 0},
    445               {"server-ip-address", 255, OT_ADDR_LIST}, /* special, internal only, sets siaddr */
    446               {NULL, 0, 0}};
    447 
    448 char* option_string(unsigned char opt, int* is_ip, int* is_name) {
    449     int i;
    450 
    451     for (i = 0; opttab[i].name; i++)
    452         if (opttab[i].val == opt) {
    453             if (is_ip) *is_ip = !!(opttab[i].size & OT_ADDR_LIST);
    454             if (is_name) *is_name = !!(opttab[i].size & OT_NAME);
    455             return opttab[i].name;
    456         }
    457 
    458     return NULL;
    459 }
    460 
    461 #endif
    462 
    463 /* We hide metacharaters in quoted strings by mapping them into the ASCII control
    464    character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
    465    following sequence so that they map to themselves: it is therefore possible to call
    466    unhide_metas repeatedly on string without breaking things.
    467    The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a
    468    couple of other places.
    469    Note that space is included here so that
    470    --dhcp-option=3, string
    471    has five characters, whilst
    472    --dhcp-option=3," string"
    473    has six.
    474 */
    475 
    476 static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
    477 
    478 static char hide_meta(char c) {
    479     unsigned int i;
    480 
    481     for (i = 0; i < (sizeof(meta) - 1); i++)
    482         if (c == meta[i]) return (char) i;
    483 
    484     return c;
    485 }
    486 
    487 static char unhide_meta(char cr) {
    488     unsigned int c = cr;
    489 
    490     if (c < (sizeof(meta) - 1)) cr = meta[c];
    491 
    492     return cr;
    493 }
    494 
    495 static void unhide_metas(char* cp) {
    496     if (cp)
    497         for (; *cp; cp++) *cp = unhide_meta(*cp);
    498 }
    499 
    500 static void* opt_malloc(size_t size) {
    501     void* ret;
    502 
    503     if (mem_recover) {
    504         ret = whine_malloc(size);
    505         if (!ret) longjmp(mem_jmp, 1);
    506     } else
    507         ret = safe_malloc(size);
    508 
    509     return ret;
    510 }
    511 
    512 static char* opt_string_alloc(char* cp) {
    513     char* ret = NULL;
    514 
    515     if (cp && strlen(cp) != 0) {
    516         ret = opt_malloc(strlen(cp) + 1);
    517         strcpy(ret, cp);
    518 
    519         /* restore hidden metachars */
    520         unhide_metas(ret);
    521     }
    522 
    523     return ret;
    524 }
    525 
    526 /* find next comma, split string with zero and eliminate spaces.
    527    return start of string following comma */
    528 
    529 static char* split_chr(char* s, char c) {
    530     char *comma, *p;
    531 
    532     if (!s || !(comma = strchr(s, c))) return NULL;
    533 
    534     p = comma;
    535     *comma = ' ';
    536 
    537     for (; isspace((int) *comma); comma++)
    538         ;
    539 
    540     for (; (p >= s) && isspace((int) *p); p--) *p = 0;
    541 
    542     return comma;
    543 }
    544 
    545 static char* split(char* s) {
    546     return split_chr(s, ',');
    547 }
    548 
    549 static char* canonicalise_opt(char* s) {
    550     char* ret;
    551     int nomem;
    552 
    553     if (!s) return 0;
    554 
    555     unhide_metas(s);
    556     if (!(ret = canonicalise(s, &nomem)) && nomem) {
    557         if (mem_recover)
    558             longjmp(mem_jmp, 1);
    559         else
    560             die(_("could not get memory"), NULL, EC_NOMEM);
    561     }
    562 
    563     return ret;
    564 }
    565 
    566 static int atoi_check(char* a, int* res) {
    567     char* p;
    568 
    569     if (!a) return 0;
    570 
    571     unhide_metas(a);
    572 
    573     for (p = a; *p; p++)
    574         if (*p < '0' || *p > '9') return 0;
    575 
    576     *res = atoi(a);
    577     return 1;
    578 }
    579 
    580 static int atoi_check16(char* a, int* res) {
    581     if (!(atoi_check(a, res)) || *res < 0 || *res > 0xffff) return 0;
    582 
    583     return 1;
    584 }
    585 
    586 static void add_txt(char* name, char* txt) {
    587     size_t len = strlen(txt);
    588     struct txt_record* r = opt_malloc(sizeof(struct txt_record));
    589 
    590     r->name = opt_string_alloc(name);
    591     r->next = daemon->txt;
    592     daemon->txt = r;
    593     r->class = C_CHAOS;
    594     r->txt = opt_malloc(len + 1);
    595     r->len = len + 1;
    596     *(r->txt) = len;
    597     memcpy((r->txt) + 1, txt, len);
    598 }
    599 
    600 static void do_usage(void) {
    601     char buff[100];
    602     int i, j;
    603 
    604     struct {
    605         char handle;
    606         int val;
    607     } tab[] = {{'$', CACHESIZ}, {'*', EDNS_PKTSZ}, {'&', MAXLEASES}, {'!', FTABSIZ}, {'\0', 0}};
    608 
    609     printf(_("Usage: dnsmasq [options]\n\n"));
    610 #ifndef HAVE_GETOPT_LONG
    611     printf(_("Use short options only on the command line.\n"));
    612 #endif
    613     printf(_("Valid options are:\n"));
    614 
    615     for (i = 0; usage[i].opt != 0; i++) {
    616         char* desc = usage[i].flagdesc;
    617         char* eq = "=";
    618 
    619         if (!desc || *desc == '[') eq = "";
    620 
    621         if (!desc) desc = "";
    622 
    623         for (j = 0; opts[j].name; j++)
    624             if (opts[j].val == usage[i].opt) break;
    625         if (usage[i].opt < 256)
    626             sprintf(buff, "-%c, ", usage[i].opt);
    627         else
    628             sprintf(buff, "    ");
    629 
    630         sprintf(buff + 4, "--%s%s%s", opts[j].name, eq, desc);
    631         printf("%-36.36s", buff);
    632 
    633         if (usage[i].arg) {
    634             strcpy(buff, usage[i].arg);
    635             for (j = 0; tab[j].handle; j++)
    636                 if (tab[j].handle == *(usage[i].arg)) sprintf(buff, "%d", tab[j].val);
    637         }
    638         printf(_(usage[i].desc), buff);
    639         printf("\n");
    640     }
    641 }
    642 
    643 #ifdef HAVE_DHCP
    644 static void display_opts(void) {
    645     int i;
    646 
    647     printf(_("Known DHCP options:\n"));
    648 
    649     for (i = 0; opttab[i].name; i++)
    650         if (!(opttab[i].size & OT_INTERNAL)) printf("%3d %s\n", opttab[i].val, opttab[i].name);
    651 }
    652 
    653 /* This is too insanely large to keep in-line in the switch */
    654 static char* parse_dhcp_opt(char* arg, int flags) {
    655     struct dhcp_opt* new = opt_malloc(sizeof(struct dhcp_opt));
    656     char lenchar = 0, *cp;
    657     int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
    658     char *comma = NULL, *problem = NULL;
    659     struct dhcp_netid* np = NULL;
    660     unsigned char opt_len = 0;
    661 
    662     new->len = 0;
    663     new->flags = flags;
    664     new->netid = NULL;
    665     new->val = NULL;
    666     new->opt = 0;
    667 
    668     while (arg) {
    669         comma = split(arg);
    670 
    671         for (cp = arg; *cp; cp++)
    672             if (*cp < '0' || *cp > '9') break;
    673 
    674         if (!*cp) {
    675             new->opt = atoi(arg);
    676             opt_len = 0;
    677             break;
    678         }
    679 
    680         if (strstr(arg, "option:") == arg) {
    681             for (i = 0; opttab[i].name; i++)
    682                 if (!(opttab[i].size & OT_INTERNAL) && strcasecmp(opttab[i].name, arg + 7) == 0) {
    683                     new->opt = opttab[i].val;
    684                     opt_len = opttab[i].size;
    685                     break;
    686                 }
    687             /* option:<optname> must follow tag and vendor string. */
    688             break;
    689         } else if (strstr(arg, "vendor:") == arg) {
    690             new->u.vendor_class = (unsigned char*) opt_string_alloc(arg + 7);
    691             new->flags |= DHOPT_VENDOR;
    692         } else if (strstr(arg, "encap:") == arg) {
    693             new->u.encap = atoi(arg + 6);
    694             new->flags |= DHOPT_ENCAPSULATE;
    695         } else {
    696             new->netid = opt_malloc(sizeof(struct dhcp_netid));
    697             /* allow optional "net:" for consistency */
    698             if (strstr(arg, "net:") == arg)
    699                 new->netid->net = opt_string_alloc(arg + 4);
    700             else
    701                 new->netid->net = opt_string_alloc(arg);
    702             new->netid->next = np;
    703             np = new->netid;
    704         }
    705 
    706         arg = comma;
    707     }
    708 
    709     if (new->opt == 0)
    710         problem = _("bad dhcp-option");
    711     else if (comma) {
    712         /* characterise the value */
    713         char c;
    714         is_addr = is_hex = is_dec = is_string = 1;
    715         addrs = digs = 1;
    716         dots = 0;
    717         for (cp = comma; (c = *cp); cp++)
    718             if (c == ',') {
    719                 addrs++;
    720                 is_dec = is_hex = 0;
    721             } else if (c == ':') {
    722                 digs++;
    723                 is_dec = is_addr = 0;
    724             } else if (c == '/') {
    725                 is_dec = is_hex = 0;
    726                 if (cp == comma) /* leading / means a pathname */
    727                     is_addr = 0;
    728             } else if (c == '.') {
    729                 is_dec = is_hex = 0;
    730                 dots++;
    731             } else if (c == '-')
    732                 is_hex = is_addr = 0;
    733             else if (c == ' ')
    734                 is_dec = is_hex = 0;
    735             else if (!(c >= '0' && c <= '9')) {
    736                 is_addr = 0;
    737                 if (cp[1] == 0 && is_dec && (c == 'b' || c == 's' || c == 'i')) {
    738                     lenchar = c;
    739                     *cp = 0;
    740                 } else
    741                     is_dec = 0;
    742                 if (!((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') ||
    743                       (c == '*' && (flags & DHOPT_MATCH))))
    744                     is_hex = 0;
    745             }
    746 
    747         /* We know that some options take addresses */
    748 
    749         if (opt_len & OT_ADDR_LIST) {
    750             is_string = is_dec = is_hex = 0;
    751             if (!is_addr || dots == 0) problem = _("bad IP address");
    752         }
    753 
    754         if (is_hex && digs > 1) {
    755             new->len = digs;
    756             new->val = opt_malloc(new->len);
    757             parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL,
    758                       NULL);
    759             new->flags |= DHOPT_HEX;
    760         } else if (is_dec) {
    761             int i, val = atoi(comma);
    762             /* assume numeric arg is 1 byte except for
    763                options where it is known otherwise.
    764                For vendor class option, we have to hack. */
    765             if (opt_len != 0)
    766                 new->len = opt_len;
    767             else if (val & 0xffff0000)
    768                 new->len = 4;
    769             else if (val & 0xff00)
    770                 new->len = 2;
    771             else
    772                 new->len = 1;
    773 
    774             if (lenchar == 'b')
    775                 new->len = 1;
    776             else if (lenchar == 's')
    777                 new->len = 2;
    778             else if (lenchar == 'i')
    779                 new->len = 4;
    780 
    781             new->val = opt_malloc(new->len);
    782             for (i = 0; i < new->len; i++) new->val[i] = val >> ((new->len - i - 1) * 8);
    783         } else if (is_addr) {
    784             struct in_addr in;
    785             unsigned char* op;
    786             char* slash;
    787             /* max length of address/subnet descriptor is five bytes,
    788                add one for the option 120 enc byte too */
    789             new->val = op = opt_malloc((5 * addrs) + 1);
    790             new->flags |= DHOPT_ADDR;
    791 
    792             if (!(new->flags& DHOPT_ENCAPSULATE) && new->opt == 120) {
    793                 *(op++) = 1; /* RFC 3361 "enc byte" */
    794                 new->flags &= ~DHOPT_ADDR;
    795             }
    796             while (addrs--) {
    797                 cp = comma;
    798                 comma = split(cp);
    799                 slash = split_chr(cp, '/');
    800                 in.s_addr = inet_addr(cp);
    801                 if (!slash) {
    802                     memcpy(op, &in, INADDRSZ);
    803                     op += INADDRSZ;
    804                 } else {
    805                     unsigned char* p = (unsigned char*) &in;
    806                     int netsize = atoi(slash);
    807                     *op++ = netsize;
    808                     if (netsize > 0) *op++ = *p++;
    809                     if (netsize > 8) *op++ = *p++;
    810                     if (netsize > 16) *op++ = *p++;
    811                     if (netsize > 24) *op++ = *p++;
    812                     new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
    813                 }
    814             }
    815             new->len = op - new->val;
    816         } else if (is_string) {
    817             /* text arg */
    818             if ((new->opt == 119 || new->opt == 120) && !(new->flags& DHOPT_ENCAPSULATE)) {
    819                 /* dns search, RFC 3397, or SIP, RFC 3361 */
    820                 unsigned char *q, *r, *tail;
    821                 unsigned char *p, *m = NULL, *newp;
    822                 size_t newlen, len = 0;
    823                 int header_size = (new->opt == 119) ? 0 : 1;
    824 
    825                 arg = comma;
    826                 comma = split(arg);
    827 
    828                 while (arg && *arg) {
    829                     char* dom;
    830                     if (!(dom = arg = canonicalise_opt(arg))) {
    831                         problem = _("bad domain in dhcp-option");
    832                         break;
    833                     }
    834 
    835                     newp = opt_malloc(len + strlen(arg) + 2 + header_size);
    836                     if (m) memcpy(newp, m, header_size + len);
    837                     m = newp;
    838                     p = m + header_size;
    839                     q = p + len;
    840 
    841                     /* add string on the end in RFC1035 format */
    842                     while (*arg) {
    843                         unsigned char* cp = q++;
    844                         int j;
    845                         for (j = 0; *arg && (*arg != '.'); arg++, j++) *q++ = *arg;
    846                         *cp = j;
    847                         if (*arg) arg++;
    848                     }
    849                     *q++ = 0;
    850                     free(dom);
    851 
    852                     /* Now tail-compress using earlier names. */
    853                     newlen = q - p;
    854                     for (tail = p + len; *tail; tail += (*tail) + 1)
    855                         for (r = p; r - p < (int) len; r += (*r) + 1)
    856                             if (strcmp((char*) r, (char*) tail) == 0) {
    857                                 PUTSHORT((r - p) | 0xc000, tail);
    858                                 newlen = tail - p;
    859                                 goto end;
    860                             }
    861                 end:
    862                     len = newlen;
    863 
    864                     arg = comma;
    865                     comma = split(arg);
    866                 }
    867 
    868                 /* RFC 3361, enc byte is zero for names */
    869                 if (new->opt == 120) m[0] = 0;
    870                 new->len = (int) len + header_size;
    871                 new->val = m;
    872             } else {
    873                 new->len = strlen(comma);
    874                 /* keep terminating zero on string */
    875                 new->val = (unsigned char*) opt_string_alloc(comma);
    876                 new->flags |= DHOPT_STRING;
    877             }
    878         }
    879     }
    880 
    881     if ((new->len > 255) || (new->len > 253 && (new->flags&(DHOPT_VENDOR | DHOPT_ENCAPSULATE))))
    882         problem = _("dhcp-option too long");
    883 
    884     if (!problem) {
    885         if (flags == DHOPT_MATCH) {
    886             if ((new->flags&(DHOPT_ENCAPSULATE | DHOPT_VENDOR)) || !new->netid || new->netid->next)
    887                 problem = _("illegal dhcp-match");
    888             else {
    889                 new->next = daemon->dhcp_match;
    890                 daemon->dhcp_match = new;
    891             }
    892         } else {
    893             new->next = daemon->dhcp_opts;
    894             daemon->dhcp_opts = new;
    895         }
    896     }
    897 
    898     return problem;
    899 }
    900 
    901 #endif
    902 
    903 static char* one_opt(int option, char* arg, char* gen_prob, int nest) {
    904     int i;
    905     char *comma, *problem = NULL;
    906     ;
    907 
    908     if (option == '?') return gen_prob;
    909 
    910     for (i = 0; usage[i].opt != 0; i++)
    911         if (usage[i].opt == option) {
    912             int rept = usage[i].rept;
    913 
    914             if (nest == 0) {
    915                 /* command line */
    916                 if (rept == ARG_USED_CL) return _("illegal repeated flag");
    917                 if (rept == ARG_ONE) usage[i].rept = ARG_USED_CL;
    918             } else {
    919                 /* allow file to override command line */
    920                 if (rept == ARG_USED_FILE) return _("illegal repeated keyword");
    921                 if (rept == ARG_USED_CL || rept == ARG_ONE) usage[i].rept = ARG_USED_FILE;
    922             }
    923 
    924             if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL) {
    925                 daemon->options |= rept;
    926                 return NULL;
    927             }
    928 
    929             break;
    930         }
    931 
    932     switch (option) {
    933         case 'C': /* --conf-file */
    934         {
    935             char* file = opt_string_alloc(arg);
    936             if (file) {
    937                 one_file(file, nest, 0);
    938                 free(file);
    939             }
    940             break;
    941         }
    942 
    943         case '7': /* --conf-dir */
    944         {
    945             DIR* dir_stream;
    946             struct dirent* ent;
    947             char *directory, *path;
    948             struct list {
    949                 char* suffix;
    950                 struct list* next;
    951             }* ignore_suffix = NULL, *li;
    952 
    953             comma = split(arg);
    954             if (!(directory = opt_string_alloc(arg))) break;
    955 
    956             for (arg = comma; arg; arg = comma) {
    957                 comma = split(arg);
    958                 li = opt_malloc(sizeof(struct list));
    959                 li->next = ignore_suffix;
    960                 ignore_suffix = li;
    961                 /* Have to copy: buffer is overwritten */
    962                 li->suffix = opt_string_alloc(arg);
    963             };
    964 
    965             if (!(dir_stream = opendir(directory)))
    966                 die(_("cannot access directory %s: %s"), directory, EC_FILE);
    967 
    968             while ((ent = readdir(dir_stream))) {
    969                 size_t len = strlen(ent->d_name);
    970                 struct stat buf;
    971 
    972                 /* ignore emacs backups and dotfiles */
    973                 if (len == 0 || ent->d_name[len - 1] == '~' ||
    974                     (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') || ent->d_name[0] == '.')
    975                     continue;
    976 
    977                 for (li = ignore_suffix; li; li = li->next) {
    978                     /* check for proscribed suffices */
    979                     size_t ls = strlen(li->suffix);
    980                     if (len > ls && strcmp(li->suffix, &ent->d_name[len - ls]) == 0) break;
    981                 }
    982                 if (li) continue;
    983 
    984                 path = opt_malloc(strlen(directory) + len + 2);
    985                 strcpy(path, directory);
    986                 strcat(path, "/");
    987                 strcat(path, ent->d_name);
    988 
    989                 if (stat(path, &buf) == -1) die(_("cannot access %s: %s"), path, EC_FILE);
    990                 /* only reg files allowed. */
    991                 if (!S_ISREG(buf.st_mode)) continue;
    992 
    993                 /* dir is one level, so files must be readable */
    994                 one_file(path, nest + 1, 0);
    995                 free(path);
    996             }
    997 
    998             closedir(dir_stream);
    999             free(directory);
   1000             for (; ignore_suffix; ignore_suffix = li) {
   1001                 li = ignore_suffix->next;
   1002                 free(ignore_suffix->suffix);
   1003                 free(ignore_suffix);
   1004             }
   1005 
   1006             break;
   1007         }
   1008 
   1009         case '8': /* --log-facility */
   1010             /* may be a filename */
   1011             if (strchr(arg, '/'))
   1012                 daemon->log_file = opt_string_alloc(arg);
   1013             else {
   1014 #ifdef __ANDROID__
   1015                 problem = "Android does not support log facilities";
   1016 #else
   1017                 for (i = 0; facilitynames[i].c_name; i++)
   1018                     if (hostname_isequal((char*) facilitynames[i].c_name, arg)) break;
   1019 
   1020                 if (facilitynames[i].c_name)
   1021                     daemon->log_fac = facilitynames[i].c_val;
   1022                 else
   1023                     problem = "bad log facility";
   1024 #endif
   1025             }
   1026             break;
   1027 
   1028         case 'x': /* --pid-file */
   1029             daemon->runfile = opt_string_alloc(arg);
   1030             break;
   1031 
   1032         case LOPT_DHCP_HOST: /* --dhcp-hostfile */
   1033             if (daemon->dhcp_hosts_file)
   1034                 problem = _("only one dhcp-hostsfile allowed");
   1035             else
   1036                 daemon->dhcp_hosts_file = opt_string_alloc(arg);
   1037             break;
   1038 
   1039         case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
   1040             if (daemon->dhcp_opts_file)
   1041                 problem = _("only one dhcp-optsfile allowed");
   1042             else
   1043                 daemon->dhcp_opts_file = opt_string_alloc(arg);
   1044             break;
   1045 
   1046         case 'r': /* --resolv-file */
   1047         {
   1048             char* name = opt_string_alloc(arg);
   1049             struct resolvc* new, *list = daemon->resolv_files;
   1050 
   1051             if (list && list->is_default) {
   1052                 /* replace default resolv file - possibly with nothing */
   1053                 if (name) {
   1054                     list->is_default = 0;
   1055                     list->name = name;
   1056                 } else
   1057                     list = NULL;
   1058             } else if (name) {
   1059                 new = opt_malloc(sizeof(struct resolvc));
   1060                 new->next = list;
   1061                 new->name = name;
   1062                 new->is_default = 0;
   1063                 new->mtime = 0;
   1064                 new->logged = 0;
   1065                 list = new;
   1066             }
   1067             daemon->resolv_files = list;
   1068             break;
   1069         }
   1070 
   1071         case 'm': /* --mx-host */
   1072         {
   1073             int pref = 1;
   1074             struct mx_srv_record* new;
   1075             char *name, *target = NULL;
   1076 
   1077             if ((comma = split(arg))) {
   1078                 char* prefstr;
   1079                 if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
   1080                     problem = _("bad MX preference");
   1081             }
   1082 
   1083             if (!(name = canonicalise_opt(arg)) || (comma && !(target = canonicalise_opt(comma))))
   1084                 problem = _("bad MX name");
   1085 
   1086             new = opt_malloc(sizeof(struct mx_srv_record));
   1087             new->next = daemon->mxnames;
   1088             daemon->mxnames = new;
   1089             new->issrv = 0;
   1090             new->name = name;
   1091             new->target = target; /* may be NULL */
   1092             new->weight = pref;
   1093             break;
   1094         }
   1095 
   1096         case 't': /*  --mx-target */
   1097             if (!(daemon->mxtarget = canonicalise_opt(arg))) problem = _("bad MX target");
   1098             break;
   1099 
   1100 #ifdef HAVE_DHCP
   1101         case 'l': /* --dhcp-leasefile */
   1102             daemon->lease_file = opt_string_alloc(arg);
   1103             break;
   1104 
   1105         case '6': /* --dhcp-script */
   1106 #if defined(NO_FORK)
   1107             problem = _("cannot run scripts under uClinux");
   1108 #elif !defined(HAVE_SCRIPT)
   1109             problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
   1110 #else
   1111             daemon->lease_change_command = opt_string_alloc(arg);
   1112 #endif
   1113             break;
   1114 #endif
   1115 
   1116         case 'H': /* --addn-hosts */
   1117         {
   1118             struct hostsfile* new = opt_malloc(sizeof(struct hostsfile));
   1119             static int hosts_index = 1;
   1120             new->fname = opt_string_alloc(arg);
   1121             new->index = hosts_index++;
   1122             new->flags = 0;
   1123             new->next = daemon->addn_hosts;
   1124             daemon->addn_hosts = new;
   1125             break;
   1126         }
   1127 
   1128         case 's': /* --domain */
   1129             if (strcmp(arg, "#") == 0)
   1130                 daemon->options |= OPT_RESOLV_DOMAIN;
   1131             else {
   1132                 char* d;
   1133                 comma = split(arg);
   1134                 if (!(d = canonicalise_opt(arg)))
   1135                     option = '?';
   1136                 else {
   1137                     if (comma) {
   1138                         struct cond_domain* new = safe_malloc(sizeof(struct cond_domain));
   1139                         unhide_metas(comma);
   1140                         if ((arg = split_chr(comma, '/'))) {
   1141                             int mask;
   1142                             if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t) -1 ||
   1143                                 !atoi_check(arg, &mask))
   1144                                 option = '?';
   1145                             else {
   1146                                 mask = (1 << (32 - mask)) - 1;
   1147                                 new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
   1148                                 new->end.s_addr = new->start.s_addr | htonl(mask);
   1149                             }
   1150                         } else if ((arg = split(comma))) {
   1151                             if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t) -1 ||
   1152                                 (new->end.s_addr = inet_addr(arg)) == (in_addr_t) -1)
   1153                                 option = '?';
   1154                         } else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) ==
   1155                                    (in_addr_t) -1)
   1156                             option = '?';
   1157 
   1158                         new->domain = d;
   1159                         new->next = daemon->cond_domain;
   1160                         daemon->cond_domain = new;
   1161                     } else
   1162                         daemon->domain_suffix = d;
   1163                 }
   1164             }
   1165             break;
   1166 
   1167         case 'u': /* --user */
   1168             daemon->username = opt_string_alloc(arg);
   1169             break;
   1170 
   1171         case 'g': /* --group */
   1172             daemon->groupname = opt_string_alloc(arg);
   1173             daemon->group_set = 1;
   1174             break;
   1175 
   1176 #ifdef HAVE_DHCP
   1177         case LOPT_SCRIPTUSR: /* --scriptuser */
   1178             daemon->scriptuser = opt_string_alloc(arg);
   1179             break;
   1180 #endif
   1181 
   1182         case 'i': /* --interface */
   1183             do {
   1184                 struct iname* new = opt_malloc(sizeof(struct iname));
   1185                 comma = split(arg);
   1186                 new->next = daemon->if_names;
   1187                 daemon->if_names = new;
   1188                 /* new->name may be NULL if someone does
   1189                    "interface=" to disable all interfaces except loop. */
   1190                 new->name = opt_string_alloc(arg);
   1191                 new->isloop = new->used = 0;
   1192                 arg = comma;
   1193             } while (arg);
   1194             break;
   1195 
   1196         case 'I': /* --except-interface */
   1197         case '2': /* --no-dhcp-interface */
   1198             do {
   1199                 struct iname* new = opt_malloc(sizeof(struct iname));
   1200                 comma = split(arg);
   1201                 new->name = opt_string_alloc(arg);
   1202                 if (option == 'I') {
   1203                     new->next = daemon->if_except;
   1204                     daemon->if_except = new;
   1205                 } else {
   1206                     new->next = daemon->dhcp_except;
   1207                     daemon->dhcp_except = new;
   1208                 }
   1209                 arg = comma;
   1210             } while (arg);
   1211             break;
   1212 
   1213         case 'B': /* --bogus-nxdomain */
   1214         {
   1215             struct in_addr addr;
   1216             unhide_metas(arg);
   1217             if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t) -1) {
   1218                 struct bogus_addr* baddr = opt_malloc(sizeof(struct bogus_addr));
   1219                 baddr->next = daemon->bogus_addr;
   1220                 daemon->bogus_addr = baddr;
   1221                 baddr->addr = addr;
   1222             } else
   1223                 option = '?'; /* error */
   1224             break;
   1225         }
   1226 
   1227         case 'a': /* --listen-address */
   1228             do {
   1229                 struct iname* new = opt_malloc(sizeof(struct iname));
   1230                 comma = split(arg);
   1231                 unhide_metas(arg);
   1232                 new->next = daemon->if_addrs;
   1233                 if (arg && parse_addr(AF_INET, arg, &new->addr) != 0 &&
   1234                     parse_addr(AF_INET6, arg, &new->addr) != 0) {
   1235                     option = '?'; /* error */
   1236                     break;
   1237                 }
   1238 
   1239                 daemon->if_addrs = new;
   1240                 arg = comma;
   1241             } while (arg);
   1242             break;
   1243 
   1244         case 'S':        /*  --server */
   1245         case LOPT_LOCAL: /*  --local */
   1246         case 'A':        /*  --address */
   1247         {
   1248             struct server *serv, *newlist = NULL;
   1249 
   1250             unhide_metas(arg);
   1251 
   1252             if (arg && *arg == '/') {
   1253                 char* end;
   1254                 arg++;
   1255                 while ((end = split_chr(arg, '/'))) {
   1256                     char* domain = NULL;
   1257                     /* # matches everything and becomes a zero length domain string */
   1258                     if (strcmp(arg, "#") == 0)
   1259                         domain = "";
   1260                     else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
   1261                         option = '?';
   1262                     serv = opt_malloc(sizeof(struct server));
   1263                     memset(serv, 0, sizeof(struct server));
   1264                     serv->next = newlist;
   1265                     newlist = serv;
   1266                     serv->domain = domain;
   1267                     serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
   1268                     arg = end;
   1269                 }
   1270                 if (!newlist) {
   1271                     option = '?';
   1272                     break;
   1273                 }
   1274 
   1275             } else {
   1276                 newlist = opt_malloc(sizeof(struct server));
   1277                 memset(newlist, 0, sizeof(struct server));
   1278             }
   1279 
   1280             if (option == 'A') {
   1281                 newlist->flags |= SERV_LITERAL_ADDRESS;
   1282                 if (!(newlist->flags & SERV_TYPE)) option = '?';
   1283             }
   1284 
   1285             if (!arg || !*arg) {
   1286                 newlist->flags |= SERV_NO_ADDR; /* no server */
   1287                 if (newlist->flags & SERV_LITERAL_ADDRESS) option = '?';
   1288             } else {
   1289                 int source_port = 0, serv_port = NAMESERVER_PORT;
   1290                 char *portno, *source;
   1291 
   1292                 if ((source = split_chr(arg, '@')) && /* is there a source. */
   1293                     (portno = split_chr(source, '#')) && !atoi_check16(portno, &source_port))
   1294                     problem = _("bad port");
   1295 
   1296                 if ((portno = split_chr(arg, '#')) && /* is there a port no. */
   1297                     !atoi_check16(portno, &serv_port))
   1298                     problem = _("bad port");
   1299 
   1300                 if (parse_addr(AF_INET, arg, &newlist->addr) == 0) {
   1301                     newlist->addr.in.sin_port = htons(serv_port);
   1302                     if (source) {
   1303                         newlist->flags |= SERV_HAS_SOURCE;
   1304                         if (parse_addr(AF_INET, source, &newlist->addr) != 0) {
   1305 #if defined(SO_BINDTODEVICE)
   1306                             newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
   1307                             strncpy(newlist->interface, source, IF_NAMESIZE);
   1308 #else
   1309                             problem = _("interface binding not supported");
   1310 #endif
   1311                         }
   1312                     } else
   1313                         newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
   1314 
   1315                     newlist->source_addr.in.sin_port = htons(source_port);
   1316                     newlist->source_addr.sa.sa_family = AF_INET;
   1317                 }
   1318 #ifdef HAVE_IPV6
   1319                 else if (parse_addr(AF_INET6, arg, &newlist->addr) == 0) {
   1320                     newlist->addr.in6.sin6_port = htons(serv_port);
   1321                     if (source) {
   1322                         newlist->flags |= SERV_HAS_SOURCE;
   1323                         if (parse_addr(AF_INET6, source, &newlist->source_addr) != 0) {
   1324 #if defined(SO_BINDTODEVICE)
   1325                             newlist->source_addr.in6.sin6_addr = in6addr_any;
   1326                             strncpy(newlist->interface, source, IF_NAMESIZE);
   1327 #else
   1328                             problem = _("interface binding not supported");
   1329 #endif
   1330                         }
   1331                     } else
   1332                         newlist->source_addr.in6.sin6_addr = in6addr_any;
   1333 
   1334                     newlist->source_addr.in6.sin6_port = htons(source_port);
   1335                     newlist->source_addr.sa.sa_family = AF_INET6;
   1336                 }
   1337 #endif
   1338                 else
   1339                     option = '?'; /* error */
   1340             }
   1341 
   1342             serv = newlist;
   1343             while (serv->next) {
   1344                 serv->next->flags = serv->flags;
   1345                 serv->next->addr = serv->addr;
   1346                 serv->next->source_addr = serv->source_addr;
   1347                 serv = serv->next;
   1348             }
   1349             serv->next = daemon->servers;
   1350             daemon->servers = newlist;
   1351             break;
   1352         }
   1353 
   1354         case 'c': /* --cache-size */
   1355         {
   1356             int size;
   1357 
   1358             if (!atoi_check(arg, &size))
   1359                 option = '?';
   1360             else {
   1361                 /* zero is OK, and means no caching. */
   1362 
   1363                 if (size < 0)
   1364                     size = 0;
   1365                 else if (size > 10000)
   1366                     size = 10000;
   1367 
   1368                 daemon->cachesize = size;
   1369             }
   1370             break;
   1371         }
   1372 
   1373         case 'p': /* --port */
   1374             if (!atoi_check16(arg, &daemon->port)) option = '?';
   1375             break;
   1376 
   1377         case LOPT_MINPORT: /* --min-port */
   1378             if (!atoi_check16(arg, &daemon->min_port)) option = '?';
   1379             break;
   1380 
   1381         case '0': /* --dns-forward-max */
   1382             if (!atoi_check(arg, &daemon->ftabsize)) option = '?';
   1383             break;
   1384 
   1385         case LOPT_MAX_LOGS:             /* --log-async */
   1386             daemon->max_logs = LOG_MAX; /* default */
   1387             if (arg && !atoi_check(arg, &daemon->max_logs))
   1388                 option = '?';
   1389             else if (daemon->max_logs > 100)
   1390                 daemon->max_logs = 100;
   1391             break;
   1392 
   1393         case 'P': /* --edns-packet-max */
   1394         {
   1395             int i;
   1396             if (!atoi_check(arg, &i)) option = '?';
   1397             daemon->edns_pktsz = (unsigned short) i;
   1398             break;
   1399         }
   1400 
   1401         case 'Q': /* --query-port */
   1402             if (!atoi_check16(arg, &daemon->query_port)) option = '?';
   1403             /* if explicitly set to zero, use single OS ephemeral port
   1404            and disable random ports */
   1405             if (daemon->query_port == 0) daemon->osport = 1;
   1406             break;
   1407 
   1408         case 'T':         /* --local-ttl */
   1409         case LOPT_NEGTTL: /* --neg-ttl */
   1410         {
   1411             int ttl;
   1412             if (!atoi_check(arg, &ttl))
   1413                 option = '?';
   1414             else if (option == LOPT_NEGTTL)
   1415                 daemon->neg_ttl = (unsigned long) ttl;
   1416             else
   1417                 daemon->local_ttl = (unsigned long) ttl;
   1418             break;
   1419         }
   1420 
   1421 #ifdef HAVE_DHCP
   1422         case 'X': /* --dhcp-lease-max */
   1423             if (!atoi_check(arg, &daemon->dhcp_max)) option = '?';
   1424             break;
   1425 #endif
   1426 
   1427         case LOPT_BRIDGE: /* --bridge-interface */
   1428         {
   1429             struct dhcp_bridge* new = opt_malloc(sizeof(struct dhcp_bridge));
   1430             if (!(comma = split(arg))) {
   1431                 problem = _("bad bridge-interface");
   1432                 break;
   1433             }
   1434 
   1435             strncpy(new->iface, arg, IF_NAMESIZE);
   1436             new->alias = NULL;
   1437             new->next = daemon->bridges;
   1438             daemon->bridges = new;
   1439 
   1440             do {
   1441                 arg = comma;
   1442                 comma = split(arg);
   1443                 if (strlen(arg) != 0) {
   1444                     struct dhcp_bridge* b = opt_malloc(sizeof(struct dhcp_bridge));
   1445                     b->next = new->alias;
   1446                     new->alias = b;
   1447                     strncpy(b->iface, arg, IF_NAMESIZE);
   1448                 }
   1449             } while (comma);
   1450 
   1451             break;
   1452         }
   1453 
   1454 #ifdef HAVE_DHCP
   1455         case 'F': /* --dhcp-range */
   1456         {
   1457             int k, leasepos = 2;
   1458             char *cp, *a[5] = {NULL, NULL, NULL, NULL, NULL};
   1459             struct dhcp_context* new = opt_malloc(sizeof(struct dhcp_context));
   1460 
   1461             new->next = daemon->dhcp;
   1462             new->lease_time = DEFLEASE;
   1463             new->addr_epoch = 0;
   1464             new->netmask.s_addr = 0;
   1465             new->broadcast.s_addr = 0;
   1466             new->router.s_addr = 0;
   1467             new->netid.net = NULL;
   1468             new->filter = NULL;
   1469             new->flags = 0;
   1470 
   1471             gen_prob = _("bad dhcp-range");
   1472 
   1473             if (!arg) {
   1474                 option = '?';
   1475                 break;
   1476             }
   1477 
   1478             while (1) {
   1479                 for (cp = arg; *cp; cp++)
   1480                     if (!(*cp == ' ' || *cp == '.' || (*cp >= '0' && *cp <= '9'))) break;
   1481 
   1482                 if (*cp != ',' && (comma = split(arg))) {
   1483                     if (strstr(arg, "net:") == arg) {
   1484                         struct dhcp_netid* tt = opt_malloc(sizeof(struct dhcp_netid));
   1485                         tt->net = opt_string_alloc(arg + 4);
   1486                         tt->next = new->filter;
   1487                         new->filter = tt;
   1488                     } else {
   1489                         if (new->netid.net)
   1490                             problem = _("only one netid tag allowed");
   1491                         else
   1492                             new->netid.net = opt_string_alloc(arg);
   1493                     }
   1494                     arg = comma;
   1495                 } else {
   1496                     a[0] = arg;
   1497                     break;
   1498                 }
   1499             }
   1500 
   1501             for (k = 1; k < 5; k++)
   1502                 if (!(a[k] = split(a[k - 1]))) break;
   1503 
   1504             if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t) -1))
   1505                 option = '?';
   1506             else if (strcmp(a[1], "static") == 0) {
   1507                 new->end = new->start;
   1508                 new->flags |= CONTEXT_STATIC;
   1509             } else if (strcmp(a[1], "proxy") == 0) {
   1510                 new->end = new->start;
   1511                 new->flags |= CONTEXT_PROXY;
   1512             } else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t) -1)
   1513                 option = '?';
   1514 
   1515             if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) {
   1516                 struct in_addr tmp = new->start;
   1517                 new->start = new->end;
   1518                 new->end = tmp;
   1519             }
   1520 
   1521             if (option != '?' && k >= 3 && strchr(a[2], '.') &&
   1522                 ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t) -1)) {
   1523                 new->flags |= CONTEXT_NETMASK;
   1524                 leasepos = 3;
   1525                 if (!is_same_net(new->start, new->end, new->netmask))
   1526                     problem = _("inconsistent DHCP range");
   1527             }
   1528             daemon->dhcp = new;
   1529 
   1530             if (k >= 4 && strchr(a[3], '.') &&
   1531                 ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t) -1)) {
   1532                 new->flags |= CONTEXT_BRDCAST;
   1533                 leasepos = 4;
   1534             }
   1535 
   1536             if (k >= leasepos + 1) {
   1537                 if (strcmp(a[leasepos], "infinite") == 0)
   1538                     new->lease_time = 0xffffffff;
   1539                 else {
   1540                     int fac = 1;
   1541                     if (strlen(a[leasepos]) > 0) {
   1542                         switch (a[leasepos][strlen(a[leasepos]) - 1]) {
   1543                             case 'd':
   1544                             case 'D':
   1545                                 fac *= 24;
   1546                                 /* fall though */
   1547                             case 'h':
   1548                             case 'H':
   1549                                 fac *= 60;
   1550                                 /* fall through */
   1551                             case 'm':
   1552                             case 'M':
   1553                                 fac *= 60;
   1554                                 /* fall through */
   1555                             case 's':
   1556                             case 'S':
   1557                                 a[leasepos][strlen(a[leasepos]) - 1] = 0;
   1558                         }
   1559 
   1560                         new->lease_time = atoi(a[leasepos]) * fac;
   1561                         /* Leases of a minute or less confuse
   1562                            some clients, notably Apple's */
   1563                         if (new->lease_time < 120) new->lease_time = 120;
   1564                     }
   1565                 }
   1566             }
   1567             break;
   1568         }
   1569 
   1570         case LOPT_BANK:
   1571         case 'G': /* --dhcp-host */
   1572         {
   1573             int j, k = 0;
   1574             char* a[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
   1575             struct dhcp_config* new;
   1576             struct in_addr in;
   1577 
   1578             new = opt_malloc(sizeof(struct dhcp_config));
   1579 
   1580             new->next = daemon->dhcp_conf;
   1581             new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
   1582             new->hwaddr = NULL;
   1583 
   1584             if ((a[0] = arg))
   1585                 for (k = 1; k < 6; k++)
   1586                     if (!(a[k] = split(a[k - 1]))) break;
   1587 
   1588             for (j = 0; j < k; j++)
   1589                 if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
   1590                 {
   1591                     char* arg = a[j];
   1592 
   1593                     if ((arg[0] == 'i' || arg[0] == 'I') && (arg[1] == 'd' || arg[1] == 'D') &&
   1594                         arg[2] == ':') {
   1595                         if (arg[3] == '*')
   1596                             new->flags |= CONFIG_NOCLID;
   1597                         else {
   1598                             int len;
   1599                             arg += 3; /* dump id: */
   1600                             if (strchr(arg, ':'))
   1601                                 len = parse_hex(arg, (unsigned char*) arg, -1, NULL, NULL);
   1602                             else {
   1603                                 unhide_metas(arg);
   1604                                 len = (int) strlen(arg);
   1605                             }
   1606 
   1607                             if ((new->clid = opt_malloc(len))) {
   1608                                 new->flags |= CONFIG_CLID;
   1609                                 new->clid_len = len;
   1610                                 memcpy(new->clid, arg, len);
   1611                             }
   1612                         }
   1613                     } else if (strstr(arg, "net:") == arg) {
   1614                         int len = strlen(arg + 4) + 1;
   1615                         if ((new->netid.net = opt_malloc(len))) {
   1616                             new->flags |= CONFIG_NETID;
   1617                             strcpy(new->netid.net, arg + 4);
   1618                             unhide_metas(new->netid.net);
   1619                         }
   1620                     } else {
   1621                         struct hwaddr_config* newhw = opt_malloc(sizeof(struct hwaddr_config));
   1622                         newhw->next = new->hwaddr;
   1623                         new->hwaddr = newhw;
   1624                         newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
   1625                                                       &newhw->wildcard_mask, &newhw->hwaddr_type);
   1626                     }
   1627                 } else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t) -1) {
   1628                     new->addr = in;
   1629                     new->flags |= CONFIG_ADDR;
   1630                 } else {
   1631                     char *cp, *lastp = NULL, last = 0;
   1632                     int fac = 1;
   1633 
   1634                     if (strlen(a[j]) > 1) {
   1635                         lastp = a[j] + strlen(a[j]) - 1;
   1636                         last = *lastp;
   1637                         switch (last) {
   1638                             case 'd':
   1639                             case 'D':
   1640                                 fac *= 24;
   1641                                 /* fall through */
   1642                             case 'h':
   1643                             case 'H':
   1644                                 fac *= 60;
   1645                                 /* fall through */
   1646                             case 'm':
   1647                             case 'M':
   1648                                 fac *= 60;
   1649                                 /* fall through */
   1650                             case 's':
   1651                             case 'S':
   1652                                 *lastp = 0;
   1653                         }
   1654                     }
   1655 
   1656                     for (cp = a[j]; *cp; cp++)
   1657                         if (!isdigit((int) *cp) && *cp != ' ') break;
   1658 
   1659                     if (*cp) {
   1660                         if (lastp) *lastp = last;
   1661                         if (strcmp(a[j], "infinite") == 0) {
   1662                             new->lease_time = 0xffffffff;
   1663                             new->flags |= CONFIG_TIME;
   1664                         } else if (strcmp(a[j], "ignore") == 0)
   1665                             new->flags |= CONFIG_DISABLE;
   1666                         else {
   1667                             if (!(new->hostname = canonicalise_opt(a[j])) ||
   1668                                 !legal_hostname(new->hostname))
   1669                                 problem = _("bad DHCP host name");
   1670                             else
   1671                                 new->flags |= CONFIG_NAME;
   1672                             new->domain = NULL;
   1673                         }
   1674                     } else {
   1675                         new->lease_time = atoi(a[j]) * fac;
   1676                         /* Leases of a minute or less confuse
   1677                            some clients, notably Apple's */
   1678                         if (new->lease_time < 120) new->lease_time = 120;
   1679                         new->flags |= CONFIG_TIME;
   1680                     }
   1681                 }
   1682 
   1683             daemon->dhcp_conf = new;
   1684             break;
   1685         }
   1686 
   1687         case 'O':        /* --dhcp-option */
   1688         case LOPT_FORCE: /* --dhcp-option-force */
   1689         case LOPT_OPTS:
   1690         case LOPT_MATCH: /* --dhcp-match */
   1691             problem = parse_dhcp_opt(
   1692                 arg, option == LOPT_FORCE
   1693                          ? DHOPT_FORCE
   1694                          : (option == LOPT_MATCH ? DHOPT_MATCH
   1695                                                  : (option == LOPT_OPTS ? DHOPT_BANK : 0)));
   1696             break;
   1697 
   1698         case 'M': /* --dhcp-boot */
   1699         {
   1700             struct dhcp_netid* id = NULL;
   1701             while (arg && strstr(arg, "net:") == arg) {
   1702                 struct dhcp_netid* newid = opt_malloc(sizeof(struct dhcp_netid));
   1703                 newid->next = id;
   1704                 id = newid;
   1705                 comma = split(arg);
   1706                 newid->net = opt_string_alloc(arg + 4);
   1707                 arg = comma;
   1708             };
   1709 
   1710             if (!arg)
   1711                 option = '?';
   1712             else {
   1713                 char *dhcp_file, *dhcp_sname = NULL;
   1714                 struct in_addr dhcp_next_server;
   1715                 comma = split(arg);
   1716                 dhcp_file = opt_string_alloc(arg);
   1717                 dhcp_next_server.s_addr = 0;
   1718                 if (comma) {
   1719                     arg = comma;
   1720                     comma = split(arg);
   1721                     dhcp_sname = opt_string_alloc(arg);
   1722                     if (comma) {
   1723                         unhide_metas(comma);
   1724                         if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t) -1)
   1725                             option = '?';
   1726                     }
   1727                 }
   1728                 if (option != '?') {
   1729                     struct dhcp_boot* new = opt_malloc(sizeof(struct dhcp_boot));
   1730                     new->file = dhcp_file;
   1731                     new->sname = dhcp_sname;
   1732                     new->next_server = dhcp_next_server;
   1733                     new->netid = id;
   1734                     new->next = daemon->boot_config;
   1735                     daemon->boot_config = new;
   1736                 }
   1737             }
   1738 
   1739             break;
   1740         }
   1741 
   1742         case LOPT_PXE_PROMT: /* --pxe-prompt */
   1743         {
   1744             struct dhcp_opt* new = opt_malloc(sizeof(struct dhcp_opt));
   1745             int timeout;
   1746 
   1747             new->netid = NULL;
   1748             new->opt = 10; /* PXE_MENU_PROMPT */
   1749 
   1750             while (arg && strstr(arg, "net:") == arg) {
   1751                 struct dhcp_netid* nn = opt_malloc(sizeof(struct dhcp_netid));
   1752                 comma = split(arg);
   1753                 nn->next = new->netid;
   1754                 new->netid = nn;
   1755                 nn->net = opt_string_alloc(arg + 4);
   1756                 arg = comma;
   1757             }
   1758 
   1759             if (!arg)
   1760                 option = '?';
   1761             else {
   1762                 comma = split(arg);
   1763                 unhide_metas(arg);
   1764                 new->len = strlen(arg) + 1;
   1765                 new->val = opt_malloc(new->len);
   1766                 memcpy(new->val + 1, arg, new->len - 1);
   1767 
   1768                 new->u.vendor_class = (unsigned char*) "PXEClient";
   1769                 new->flags = DHOPT_VENDOR;
   1770 
   1771                 if (comma && atoi_check(comma, &timeout))
   1772                     *(new->val) = timeout;
   1773                 else
   1774                     *(new->val) = 255;
   1775 
   1776                 new->next = daemon->dhcp_opts;
   1777                 daemon->dhcp_opts = new;
   1778                 daemon->enable_pxe = 1;
   1779             }
   1780 
   1781             break;
   1782         }
   1783 
   1784         case LOPT_PXE_SERV: /* --pxe-service */
   1785         {
   1786             struct pxe_service* new = opt_malloc(sizeof(struct pxe_service));
   1787             char* CSA[] = {
   1788                 "x86PC",    "PC98",   "IA64_EFI",   "Alpha",      "Arc_x86", "Intel_Lean_Client",
   1789                 "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL};
   1790             static int boottype = 32768;
   1791 
   1792             new->netid = NULL;
   1793             new->server.s_addr = 0;
   1794 
   1795             while (arg && strstr(arg, "net:") == arg) {
   1796                 struct dhcp_netid* nn = opt_malloc(sizeof(struct dhcp_netid));
   1797                 comma = split(arg);
   1798                 nn->next = new->netid;
   1799                 new->netid = nn;
   1800                 nn->net = opt_string_alloc(arg + 4);
   1801                 arg = comma;
   1802             }
   1803 
   1804             if (arg && (comma = split(arg))) {
   1805                 for (i = 0; CSA[i]; i++)
   1806                     if (strcasecmp(CSA[i], arg) == 0) break;
   1807 
   1808                 if (CSA[i] || atoi_check(arg, &i)) {
   1809                     arg = comma;
   1810                     comma = split(arg);
   1811 
   1812                     new->CSA = i;
   1813                     new->menu = opt_string_alloc(arg);
   1814 
   1815                     if (comma) {
   1816                         arg = comma;
   1817                         comma = split(arg);
   1818                         if (atoi_check(arg, &i)) {
   1819                             new->type = i;
   1820                             new->basename = NULL;
   1821                         } else {
   1822                             new->type = boottype++;
   1823                             new->basename = opt_string_alloc(arg);
   1824                         }
   1825 
   1826                         if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t) -1)
   1827                             option = '?';
   1828 
   1829                         /* Order matters */
   1830                         new->next = NULL;
   1831                         if (!daemon->pxe_services)
   1832                             daemon->pxe_services = new;
   1833                         else {
   1834                             struct pxe_service* s;
   1835                             for (s = daemon->pxe_services; s->next; s = s->next)
   1836                                 ;
   1837                             s->next = new;
   1838                         }
   1839 
   1840                         daemon->enable_pxe = 1;
   1841                         break;
   1842                     }
   1843                 }
   1844             }
   1845 
   1846             option = '?';
   1847             break;
   1848         }
   1849 
   1850         case '4': /* --dhcp-mac */
   1851         {
   1852             if (!(comma = split(arg)))
   1853                 option = '?';
   1854             else {
   1855                 struct dhcp_mac* new = opt_malloc(sizeof(struct dhcp_mac));
   1856                 if (strstr(arg, "net:") == arg)
   1857                     new->netid.net = opt_string_alloc(arg + 4);
   1858                 else
   1859                     new->netid.net = opt_string_alloc(arg);
   1860                 unhide_metas(comma);
   1861                 new->hwaddr_len =
   1862                     parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
   1863                 new->next = daemon->dhcp_macs;
   1864                 daemon->dhcp_macs = new;
   1865             }
   1866         } break;
   1867 
   1868         case 'U':          /* --dhcp-vendorclass */
   1869         case 'j':          /* --dhcp-userclass */
   1870         case LOPT_CIRCUIT: /* --dhcp-circuitid */
   1871         case LOPT_REMOTE:  /* --dhcp-remoteid */
   1872         case LOPT_SUBSCR:  /* --dhcp-subscrid */
   1873         {
   1874             if (!(comma = split(arg)))
   1875                 option = '?';
   1876             else {
   1877                 char* p;
   1878                 int dig = 0;
   1879                 struct dhcp_vendor* new = opt_malloc(sizeof(struct dhcp_vendor));
   1880                 if (strstr(arg, "net:") == arg)
   1881                     new->netid.net = opt_string_alloc(arg + 4);
   1882                 else
   1883                     new->netid.net = opt_string_alloc(arg);
   1884                 /* check for hex string - must digits may include : must not have nothing else,
   1885                    only allowed for agent-options. */
   1886                 for (p = comma; *p; p++)
   1887                     if (isxdigit((int) *p))
   1888                         dig = 1;
   1889                     else if (*p != ':')
   1890                         break;
   1891                 unhide_metas(comma);
   1892                 if (option == 'U' || option == 'j' || *p || !dig) {
   1893                     new->len = strlen(comma);
   1894                     new->data = opt_malloc(new->len);
   1895                     memcpy(new->data, comma, new->len);
   1896                 } else {
   1897                     new->len = parse_hex(comma, (unsigned char*) comma, strlen(comma), NULL, NULL);
   1898                     new->data = opt_malloc(new->len);
   1899                     memcpy(new->data, comma, new->len);
   1900                 }
   1901 
   1902                 switch (option) {
   1903                     case 'j':
   1904                         new->match_type = MATCH_USER;
   1905                         break;
   1906                     case 'U':
   1907                         new->match_type = MATCH_VENDOR;
   1908                         break;
   1909                     case LOPT_CIRCUIT:
   1910                         new->match_type = MATCH_CIRCUIT;
   1911                         break;
   1912                     case LOPT_REMOTE:
   1913                         new->match_type = MATCH_REMOTE;
   1914                         break;
   1915                     case LOPT_SUBSCR:
   1916                         new->match_type = MATCH_SUBSCRIBER;
   1917                         break;
   1918                 }
   1919                 new->next = daemon->dhcp_vendors;
   1920                 daemon->dhcp_vendors = new;
   1921             }
   1922             break;
   1923         }
   1924 
   1925         case LOPT_ALTPORT: /* --dhcp-alternate-port */
   1926             if (!arg) {
   1927                 daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
   1928                 daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
   1929             } else {
   1930                 comma = split(arg);
   1931                 if (!atoi_check16(arg, &daemon->dhcp_server_port) ||
   1932                     (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
   1933                     problem = _("invalid port number");
   1934                 if (!comma) daemon->dhcp_client_port = daemon->dhcp_server_port + 1;
   1935             }
   1936             break;
   1937 
   1938         case 'J':            /* --dhcp-ignore */
   1939         case LOPT_NO_NAMES:  /* --dhcp-ignore-names */
   1940         case LOPT_BROADCAST: /* --dhcp-broadcast */
   1941         case '3':            /* --bootp-dynamic */
   1942         {
   1943             struct dhcp_netid_list* new = opt_malloc(sizeof(struct dhcp_netid_list));
   1944             struct dhcp_netid* list = NULL;
   1945             if (option == 'J') {
   1946                 new->next = daemon->dhcp_ignore;
   1947                 daemon->dhcp_ignore = new;
   1948             } else if (option == LOPT_BROADCAST) {
   1949                 new->next = daemon->force_broadcast;
   1950                 daemon->force_broadcast = new;
   1951             } else if (option == '3') {
   1952                 new->next = daemon->bootp_dynamic;
   1953                 daemon->bootp_dynamic = new;
   1954             } else {
   1955                 new->next = daemon->dhcp_ignore_names;
   1956                 daemon->dhcp_ignore_names = new;
   1957             }
   1958 
   1959             while (arg) {
   1960                 struct dhcp_netid* member = opt_malloc(sizeof(struct dhcp_netid));
   1961                 comma = split(arg);
   1962                 member->next = list;
   1963                 list = member;
   1964                 if (strstr(arg, "net:") == arg)
   1965                     member->net = opt_string_alloc(arg + 4);
   1966                 else
   1967                     member->net = opt_string_alloc(arg);
   1968                 arg = comma;
   1969             }
   1970 
   1971             new->list = list;
   1972             break;
   1973         }
   1974 #endif
   1975 
   1976         case 'V': /* --alias */
   1977         {
   1978             char *dash, *a[3] = {NULL, NULL, NULL};
   1979             int k = 0;
   1980             struct doctor* new = opt_malloc(sizeof(struct doctor));
   1981             new->next = daemon->doctors;
   1982             daemon->doctors = new;
   1983             new->mask.s_addr = 0xffffffff;
   1984             new->end.s_addr = 0;
   1985 
   1986             if ((a[0] = arg))
   1987                 for (k = 1; k < 3; k++) {
   1988                     if (!(a[k] = split(a[k - 1]))) break;
   1989                     unhide_metas(a[k]);
   1990                 }
   1991 
   1992             dash = split_chr(a[0], '-');
   1993 
   1994             if ((k < 2) || ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t) -1) ||
   1995                 ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t) -1))
   1996                 option = '?';
   1997 
   1998             if (k == 3) new->mask.s_addr = inet_addr(a[2]);
   1999 
   2000             if (dash && ((new->end.s_addr = inet_addr(dash)) == (in_addr_t) -1 ||
   2001                          !is_same_net(new->in, new->end, new->mask) ||
   2002                          ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
   2003                 problem = _("invalid alias range");
   2004 
   2005             break;
   2006         }
   2007 
   2008         case LOPT_INTNAME: /* --interface-name */
   2009         {
   2010             struct interface_name* new, **up;
   2011             char* domain = NULL;
   2012 
   2013             comma = split(arg);
   2014 
   2015             if (!comma || !(domain = canonicalise_opt(arg))) problem = _("bad interface name");
   2016 
   2017             new = opt_malloc(sizeof(struct interface_name));
   2018             new->next = NULL;
   2019             /* Add to the end of the list, so that first name
   2020                of an interface is used for PTR lookups. */
   2021             for (up = &daemon->int_names; *up; up = &((*up)->next))
   2022                 ;
   2023             *up = new;
   2024             new->name = domain;
   2025             new->intr = opt_string_alloc(comma);
   2026             break;
   2027         }
   2028 
   2029         case LOPT_CNAME: /* --cname */
   2030         {
   2031             struct cname* new;
   2032 
   2033             if (!(comma = split(arg)))
   2034                 option = '?';
   2035             else {
   2036                 char* alias = canonicalise_opt(arg);
   2037                 char* target = canonicalise_opt(comma);
   2038 
   2039                 if (!alias || !target)
   2040                     problem = _("bad CNAME");
   2041                 else {
   2042                     for (new = daemon->cnames; new; new = new->next)
   2043                         if (hostname_isequal(new->alias, arg)) problem = _("duplicate CNAME");
   2044                     new = opt_malloc(sizeof(struct cname));
   2045                     new->next = daemon->cnames;
   2046                     daemon->cnames = new;
   2047                     new->alias = alias;
   2048                     new->target = target;
   2049                 }
   2050             }
   2051             break;
   2052         }
   2053 
   2054         case LOPT_PTR: /* --ptr-record */
   2055         {
   2056             struct ptr_record* new;
   2057             char *dom, *target = NULL;
   2058 
   2059             comma = split(arg);
   2060 
   2061             if (!(dom = canonicalise_opt(arg)) || (comma && !(target = canonicalise_opt(comma))))
   2062                 problem = _("bad PTR record");
   2063             else {
   2064                 new = opt_malloc(sizeof(struct ptr_record));
   2065                 new->next = daemon->ptr;
   2066                 daemon->ptr = new;
   2067                 new->name = dom;
   2068                 new->ptr = target;
   2069             }
   2070             break;
   2071         }
   2072 
   2073         case LOPT_NAPTR: /* --naptr-record */
   2074         {
   2075             char* a[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
   2076             int k = 0;
   2077             struct naptr* new;
   2078             int order, pref;
   2079             char *name, *replace = NULL;
   2080 
   2081             if ((a[0] = arg))
   2082                 for (k = 1; k < 7; k++)
   2083                     if (!(a[k] = split(a[k - 1]))) break;
   2084 
   2085             if (k < 6 || !(name = canonicalise_opt(a[0])) || !atoi_check16(a[1], &order) ||
   2086                 !atoi_check16(a[2], &pref) || (k == 7 && !(replace = canonicalise_opt(a[6]))))
   2087                 problem = _("bad NAPTR record");
   2088             else {
   2089                 new = opt_malloc(sizeof(struct naptr));
   2090                 new->next = daemon->naptr;
   2091                 daemon->naptr = new;
   2092                 new->name = name;
   2093                 new->flags = opt_string_alloc(a[3]);
   2094                 new->services = opt_string_alloc(a[4]);
   2095                 new->regexp = opt_string_alloc(a[5]);
   2096                 new->replace = replace;
   2097                 new->order = order;
   2098                 new->pref = pref;
   2099             }
   2100             break;
   2101         }
   2102 
   2103         case 'Y': /* --txt-record */
   2104         {
   2105             struct txt_record* new;
   2106             unsigned char *p, *q;
   2107 
   2108             if ((comma = split(arg))) comma--;
   2109 
   2110             gen_prob = _("TXT record string too long");
   2111 
   2112             if ((q = (unsigned char*) comma))
   2113                 while (1) {
   2114                     size_t len;
   2115                     if ((p = (unsigned char*) strchr((char*) q + 1, ','))) {
   2116                         if ((len = p - q - 1) > 255) option = '?';
   2117                         *q = len;
   2118                         for (q = q + 1; q < p; q++) *q = unhide_meta(*q);
   2119                     } else {
   2120                         if ((len = strlen((char*) q + 1)) > 255) option = '?';
   2121                         *q = len;
   2122                         for (q = q + 1; *q; q++) *q = unhide_meta(*q);
   2123                         break;
   2124                     }
   2125                 }
   2126 
   2127             new = opt_malloc(sizeof(struct txt_record));
   2128             new->next = daemon->txt;
   2129             daemon->txt = new;
   2130             new->class = C_IN;
   2131             if (comma) {
   2132                 new->len = q - ((unsigned char*) comma);
   2133                 new->txt = opt_malloc(new->len);
   2134                 memcpy(new->txt, comma, new->len);
   2135             } else {
   2136                 static char empty[] = "";
   2137                 new->len = 1;
   2138                 new->txt = empty;
   2139             }
   2140 
   2141             /* ensure arg is terminated */
   2142             if (comma) *comma = 0;
   2143 
   2144             if (!(new->name = canonicalise_opt(arg))) {
   2145                 problem = _("bad TXT record");
   2146                 break;
   2147             }
   2148 
   2149             break;
   2150         }
   2151 
   2152         case 'W': /* --srv-host */
   2153         {
   2154             int port = 1, priority = 0, weight = 0;
   2155             char *name, *target = NULL;
   2156             struct mx_srv_record* new;
   2157 
   2158             comma = split(arg);
   2159 
   2160             if (!(name = canonicalise_opt(arg))) problem = _("bad SRV record");
   2161 
   2162             if (comma) {
   2163                 arg = comma;
   2164                 comma = split(arg);
   2165                 if (!(target = canonicalise_opt(arg))) problem = _("bad SRV target");
   2166 
   2167                 if (comma) {
   2168                     arg = comma;
   2169                     comma = split(arg);
   2170                     if (!atoi_check16(arg, &port)) problem = _("invalid port number");
   2171 
   2172                     if (comma) {
   2173                         arg = comma;
   2174                         comma = split(arg);
   2175                         if (!atoi_check16(arg, &priority)) problem = _("invalid priority");
   2176 
   2177                         if (comma) {
   2178                             arg = comma;
   2179                             comma = split(arg);
   2180                             if (!atoi_check16(arg, &weight)) problem = _("invalid weight");
   2181                         }
   2182                     }
   2183                 }
   2184             }
   2185 
   2186             new = opt_malloc(sizeof(struct mx_srv_record));
   2187             new->next = daemon->mxnames;
   2188             daemon->mxnames = new;
   2189             new->issrv = 1;
   2190             new->name = name;
   2191             new->target = target;
   2192             new->srvport = port;
   2193             new->priority = priority;
   2194             new->weight = weight;
   2195             break;
   2196         }
   2197 
   2198         case LOPT_LISTNMARK: /* --listen-mark */
   2199         {
   2200             char* endptr;
   2201             uint32_t mark = strtoul(arg, &endptr, 0);
   2202             // my_syslog(LOG_WARNING, "passed-in mark: %s", arg);
   2203             if (!*endptr)
   2204                 daemon->listen_mark = mark;
   2205             else
   2206                 problem = _("invalid mark");
   2207             // my_syslog(LOG_WARNING, "daemon->listen_mark: 0x%x, *endptr=%d", daemon->listen_mark, *endptr);
   2208             break;
   2209         }
   2210 
   2211         default:
   2212             return _("unsupported option (check that dnsmasq was compiled with DHCP support)");
   2213     }
   2214 
   2215     if (problem) return problem;
   2216 
   2217     if (option == '?') return gen_prob;
   2218 
   2219     return NULL;
   2220 }
   2221 
   2222 static void one_file(char* file, int nest, int hard_opt) {
   2223     volatile int lineno = 0;
   2224     int i, option;
   2225     FILE* f;
   2226     char *p, *arg, *start, *buff = daemon->namebuff;
   2227     static struct fileread {
   2228         dev_t dev;
   2229         ino_t ino;
   2230         struct fileread* next;
   2231     }* filesread = NULL;
   2232     struct stat statbuf;
   2233 
   2234     /* ignore repeated files. */
   2235     if (hard_opt == 0 && stat(file, &statbuf) == 0) {
   2236         struct fileread* r;
   2237 
   2238         for (r = filesread; r; r = r->next)
   2239             if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino) return;
   2240 
   2241         r = safe_malloc(sizeof(struct fileread));
   2242         r->next = filesread;
   2243         filesread = r;
   2244         r->dev = statbuf.st_dev;
   2245         r->ino = statbuf.st_ino;
   2246     }
   2247 
   2248     if (nest > 20) die(_("files nested too deep in %s"), file, EC_BADCONF);
   2249 
   2250     if (!(f = fopen(file, "r"))) {
   2251         if (errno == ENOENT && nest == 0)
   2252             return; /* No conffile, all done. */
   2253         else {
   2254             char* str = _("cannot read %s: %s");
   2255             if (hard_opt != 0) {
   2256                 my_syslog(LOG_ERR, str, file, strerror(errno));
   2257                 return;
   2258             } else
   2259                 die(str, file, EC_FILE);
   2260         }
   2261     }
   2262 
   2263     while (fgets(buff, MAXDNAME, f)) {
   2264         int white;
   2265         unsigned int lastquote;
   2266         char* errmess;
   2267 
   2268         /* Memory allocation failure longjmps here if mem_recover == 1 */
   2269         if (hard_opt) {
   2270             if (setjmp(mem_jmp)) continue;
   2271             mem_recover = 1;
   2272         }
   2273 
   2274         lineno++;
   2275         errmess = NULL;
   2276 
   2277         /* Implement quotes, inside quotes we allow \\ \" \n and \t
   2278        metacharacters get hidden also strip comments */
   2279 
   2280         for (white = 1, lastquote = 0, p = buff; *p; p++) {
   2281             if (*p == '"') {
   2282                 memmove(p, p + 1, strlen(p + 1) + 1);
   2283                 for (; *p && *p != '"'; p++) {
   2284                     if (*p == '\\' && strchr("\"tnebr\\", p[1])) {
   2285                         if (p[1] == 't')
   2286                             p[1] = '\t';
   2287                         else if (p[1] == 'n')
   2288                             p[1] = '\n';
   2289                         else if (p[1] == 'b')
   2290                             p[1] = '\b';
   2291                         else if (p[1] == 'r')
   2292                             p[1] = '\r';
   2293                         else if (p[1] == 'e') /* escape */
   2294                             p[1] = '\033';
   2295                         memmove(p, p + 1, strlen(p + 1) + 1);
   2296                     }
   2297                     *p = hide_meta(*p);
   2298                 }
   2299                 if (*p == '"') {
   2300                     memmove(p, p + 1, strlen(p + 1) + 1);
   2301                     lastquote = p - buff;
   2302                 } else {
   2303                     errmess = _("missing \"");
   2304                     goto oops;
   2305                 }
   2306             }
   2307 
   2308             if (white && *p == '#') {
   2309                 *p = 0;
   2310                 break;
   2311             }
   2312             white = isspace((int) unhide_meta(*p));
   2313         }
   2314 
   2315         /* fgets gets end of line char too. */
   2316         while (strlen(buff) > lastquote && isspace((int) unhide_meta(buff[strlen(buff) - 1])))
   2317             buff[strlen(buff) - 1] = 0;
   2318 
   2319         if (*buff == 0) continue;
   2320 
   2321         if (hard_opt != 0)
   2322             arg = buff;
   2323         else if ((p = strchr(buff, '='))) {
   2324             /* allow spaces around "=" */
   2325             arg = p + 1;
   2326             for (; p >= buff && (isspace((int) *p) || *p == '='); p--) *p = 0;
   2327         } else
   2328             arg = NULL;
   2329 
   2330         if (hard_opt != 0)
   2331             option = hard_opt;
   2332         else {
   2333             /* skip leading space */
   2334             for (start = buff; *start && isspace((int) *start); start++)
   2335                 ;
   2336 
   2337             for (option = 0, i = 0; opts[i].name; i++)
   2338                 if (strcmp(opts[i].name, start) == 0) {
   2339                     option = opts[i].val;
   2340                     break;
   2341                 }
   2342 
   2343             if (!option)
   2344                 errmess = _("bad option");
   2345             else if (opts[i].has_arg == 0 && arg)
   2346                 errmess = _("extraneous parameter");
   2347             else if (opts[i].has_arg == 1 && !arg)
   2348                 errmess = _("missing parameter");
   2349         }
   2350 
   2351         if (!errmess) {
   2352             if (arg)
   2353                 for (; isspace((int) *arg); arg++)
   2354                     ;
   2355 
   2356             errmess = one_opt(option, arg, _("error"), nest + 1);
   2357         }
   2358 
   2359         if (errmess) {
   2360         oops:
   2361             sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
   2362             if (hard_opt != 0)
   2363                 my_syslog(LOG_ERR, buff, file);
   2364             else
   2365                 die(buff, file, EC_BADCONF);
   2366         }
   2367     }
   2368 
   2369     mem_recover = 1;
   2370     fclose(f);
   2371 }
   2372 
   2373 #ifdef HAVE_DHCP
   2374 void reread_dhcp(void) {
   2375     if (daemon->dhcp_hosts_file) {
   2376         struct dhcp_config *configs, *cp, **up;
   2377 
   2378         /* remove existing... */
   2379         for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp) {
   2380             cp = configs->next;
   2381 
   2382             if (configs->flags & CONFIG_BANK) {
   2383                 struct hwaddr_config *mac, *tmp;
   2384 
   2385                 for (mac = configs->hwaddr; mac; mac = tmp) {
   2386                     tmp = mac->next;
   2387                     free(mac);
   2388                 }
   2389                 if (configs->flags & CONFIG_CLID) free(configs->clid);
   2390                 if (configs->flags & CONFIG_NETID) free(configs->netid.net);
   2391                 if (configs->flags & CONFIG_NAME) free(configs->hostname);
   2392 
   2393                 *up = configs->next;
   2394                 free(configs);
   2395             } else
   2396                 up = &configs->next;
   2397         }
   2398 
   2399         one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
   2400         my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
   2401     }
   2402 
   2403     if (daemon->dhcp_opts_file) {
   2404         struct dhcp_opt *opts, *cp, **up;
   2405         struct dhcp_netid *id, *next;
   2406 
   2407         for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp) {
   2408             cp = opts->next;
   2409 
   2410             if (opts->flags & DHOPT_BANK) {
   2411                 if ((opts->flags & DHOPT_VENDOR)) free(opts->u.vendor_class);
   2412                 free(opts->val);
   2413                 for (id = opts->netid; id; id = next) {
   2414                     next = id->next;
   2415                     free(id->net);
   2416                     free(id);
   2417                 }
   2418                 *up = opts->next;
   2419                 free(opts);
   2420             } else
   2421                 up = &opts->next;
   2422         }
   2423 
   2424         one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
   2425         my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
   2426     }
   2427 }
   2428 #endif
   2429 
   2430 void read_opts(int argc, char** argv, char* compile_opts) {
   2431     char* buff = opt_malloc(MAXDNAME);
   2432     int option, nest = 0, testmode = 0;
   2433     char *errmess, *arg, *conffile = CONFFILE;
   2434 
   2435     opterr = 0;
   2436 
   2437     daemon = opt_malloc(sizeof(struct daemon));
   2438     memset(daemon, 0, sizeof(struct daemon));
   2439     daemon->namebuff = buff;
   2440 
   2441     /* Set defaults - everything else is zero or NULL */
   2442     daemon->cachesize = CACHESIZ;
   2443     daemon->ftabsize = FTABSIZ;
   2444     daemon->port = NAMESERVER_PORT;
   2445     daemon->dhcp_client_port = DHCP_CLIENT_PORT;
   2446     daemon->dhcp_server_port = DHCP_SERVER_PORT;
   2447     daemon->default_resolv.is_default = 1;
   2448     daemon->default_resolv.name = RESOLVFILE;
   2449     daemon->resolv_files = &daemon->default_resolv;
   2450     daemon->username = CHUSER;
   2451     daemon->runfile = RUNFILE;
   2452     daemon->dhcp_max = MAXLEASES;
   2453     daemon->edns_pktsz = EDNS_PKTSZ;
   2454     daemon->log_fac = -1;
   2455     add_txt("version.bind", "dnsmasq-" VERSION);
   2456     add_txt("authors.bind", "Simon Kelley");
   2457     add_txt("copyright.bind", COPYRIGHT);
   2458 
   2459     while (1) {
   2460 #ifdef HAVE_GETOPT_LONG
   2461         option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
   2462 #else
   2463         option = getopt(argc, argv, OPTSTRING);
   2464 #endif
   2465 
   2466         if (option == -1) break;
   2467 
   2468         /* Copy optarg so that argv doesn't get changed */
   2469         if (optarg) {
   2470             strncpy(buff, optarg, MAXDNAME);
   2471             buff[MAXDNAME - 1] = 0;
   2472             arg = buff;
   2473         } else
   2474             arg = NULL;
   2475 
   2476         /* command-line only stuff */
   2477         if (option == LOPT_TEST)
   2478             testmode = 1;
   2479         else if (option == 'w') {
   2480             if (argc != 3 || strcmp(argv[2], "dhcp") != 0) do_usage();
   2481 #ifdef HAVE_DHCP
   2482             else
   2483                 display_opts();
   2484 #endif
   2485             exit(0);
   2486         } else if (option == 'v') {
   2487             printf(_("Dnsmasq version %s  %s\n"), VERSION, COPYRIGHT);
   2488             printf(_("Compile time options %s\n\n"), compile_opts);
   2489             printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
   2490             printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
   2491             printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
   2492             exit(0);
   2493         } else if (option == 'C') {
   2494             conffile = opt_string_alloc(arg);
   2495             nest++;
   2496         } else {
   2497 #ifdef HAVE_GETOPT_LONG
   2498             errmess = one_opt(option, arg, _("try --help"), 0);
   2499 #else
   2500             errmess = one_opt(option, arg, _("try -w"), 0);
   2501 #endif
   2502             if (errmess) die(_("bad command line options: %s"), errmess, EC_BADCONF);
   2503         }
   2504     }
   2505 
   2506     if (conffile) one_file(conffile, nest, 0);
   2507 
   2508     /* port might not be known when the address is parsed - fill in here */
   2509     if (daemon->servers) {
   2510         struct server* tmp;
   2511         for (tmp = daemon->servers; tmp; tmp = tmp->next)
   2512             if (!(tmp->flags & SERV_HAS_SOURCE)) {
   2513                 if (tmp->source_addr.sa.sa_family == AF_INET)
   2514                     tmp->source_addr.in.sin_port = htons(daemon->query_port);
   2515 #ifdef HAVE_IPV6
   2516                 else if (tmp->source_addr.sa.sa_family == AF_INET6)
   2517                     tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
   2518 #endif
   2519             }
   2520     }
   2521 
   2522     if (daemon->if_addrs) {
   2523         struct iname* tmp;
   2524         for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
   2525             if (tmp->addr.sa.sa_family == AF_INET) tmp->addr.in.sin_port = htons(daemon->port);
   2526 #ifdef HAVE_IPV6
   2527             else if (tmp->addr.sa.sa_family == AF_INET6)
   2528                 tmp->addr.in6.sin6_port = htons(daemon->port);
   2529 #endif /* IPv6 */
   2530     }
   2531 
   2532     /* only one of these need be specified: the other defaults to the host-name */
   2533     if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget) {
   2534         struct mx_srv_record* mx;
   2535 
   2536         if (gethostname(buff, MAXDNAME) == -1) die(_("cannot get host-name: %s"), NULL, EC_MISC);
   2537 
   2538         for (mx = daemon->mxnames; mx; mx = mx->next)
   2539             if (!mx->issrv && hostname_isequal(mx->name, buff)) break;
   2540 
   2541         if ((daemon->mxtarget || (daemon->options & OPT_LOCALMX)) && !mx) {
   2542             mx = opt_malloc(sizeof(struct mx_srv_record));
   2543             mx->next = daemon->mxnames;
   2544             mx->issrv = 0;
   2545             mx->target = NULL;
   2546             mx->name = opt_string_alloc(buff);
   2547             daemon->mxnames = mx;
   2548         }
   2549 
   2550         if (!daemon->mxtarget) daemon->mxtarget = opt_string_alloc(buff);
   2551 
   2552         for (mx = daemon->mxnames; mx; mx = mx->next)
   2553             if (!mx->issrv && !mx->target) mx->target = daemon->mxtarget;
   2554     }
   2555 
   2556     if (!(daemon->options & OPT_NO_RESOLV) && daemon->resolv_files && daemon->resolv_files->next &&
   2557         (daemon->options & OPT_NO_POLL))
   2558         die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
   2559 
   2560     if (daemon->options & OPT_RESOLV_DOMAIN) {
   2561         char* line;
   2562         FILE* f;
   2563 
   2564         if ((daemon->options & OPT_NO_RESOLV) || !daemon->resolv_files ||
   2565             (daemon->resolv_files)->next)
   2566             die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
   2567 
   2568         if (!(f = fopen((daemon->resolv_files)->name, "r")))
   2569             die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
   2570 
   2571         while ((line = fgets(buff, MAXDNAME, f))) {
   2572             char* token = strtok(line, " \t\n\r");
   2573 
   2574             if (!token || strcmp(token, "search") != 0) continue;
   2575 
   2576             if ((token = strtok(NULL, " \t\n\r")) &&
   2577                 (daemon->domain_suffix = canonicalise_opt(token)))
   2578                 break;
   2579         }
   2580 
   2581         fclose(f);
   2582 
   2583         if (!daemon->domain_suffix)
   2584             die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
   2585     }
   2586 
   2587     if (daemon->domain_suffix) {
   2588         /* add domain for any srv record without one. */
   2589         struct mx_srv_record* srv;
   2590 
   2591         for (srv = daemon->mxnames; srv; srv = srv->next)
   2592             if (srv->issrv && strchr(srv->name, '.') &&
   2593                 strchr(srv->name, '.') == strrchr(srv->name, '.')) {
   2594                 strcpy(buff, srv->name);
   2595                 strcat(buff, ".");
   2596                 strcat(buff, daemon->domain_suffix);
   2597                 free(srv->name);
   2598                 srv->name = opt_string_alloc(buff);
   2599             }
   2600     } else if (daemon->options & OPT_DHCP_FQDN)
   2601         die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
   2602 
   2603     if (testmode) {
   2604         fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
   2605         exit(0);
   2606     }
   2607 }
   2608