1/* dnsmasq is Copyright (c) 2000 - 2004 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.
6
7   This program is distributed in the hope that it will be useful,
8   but WITHOUT ANY WARRANTY; without even the implied warranty of
9   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10   GNU General Public License for more details.
11*/
12
13/* Author's email: simon@thekelleys.org.uk */
14
15#include "dnsmasq.h"
16
17struct myoption {
18  const char *name;
19  int has_arg;
20  int *flag;
21  int val;
22};
23
24#define OPTSTRING "ZDNLERzowefnbvhdkqr: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:"
25#ifdef OPENDNS_PARENTAL_CONTROL
26#define LOPT_DEVICE_ID 289      /* Foxconn add, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */
27#endif
28static struct myoption opts[] = {
29  {"version", 0, 0, 'v'},
30  {"no-hosts", 0, 0, 'h'},
31  {"no-poll", 0, 0, 'n'},
32  {"help", 0, 0, 'w'},
33  {"no-daemon", 0, 0, 'd'},
34  {"log-queries", 0, 0, 'q'},
35  {"user", 1, 0, 'u'},
36  {"group", 1, 0, 'g'},
37  {"resolv-file", 1, 0, 'r'},
38  {"mx-host", 1, 0, 'm'},
39  {"mx-target", 1, 0, 't'},
40  {"cache-size", 1, 0, 'c'},
41  {"port", 1, 0, 'p'},
42  {"dhcp-leasefile", 1, 0, 'l'},
43  {"dhcp-lease", 1, 0, 'l' },
44  {"dhcp-host", 1, 0, 'G'},
45  {"dhcp-range", 1, 0, 'F'},
46  {"dhcp-option", 1, 0, 'O'},
47  {"dhcp-boot", 1, 0, 'M'},
48  {"domain", 1, 0, 's'},
49  {"domain-suffix", 1, 0, 's'},
50  {"interface", 1, 0, 'i'},
51  {"listen-address", 1, 0, 'a'},
52  {"bogus-priv", 0, 0, 'b'},
53  {"bogus-nxdomain", 1, 0, 'B'},
54  {"selfmx", 0, 0, 'e'},
55  {"filterwin2k", 0, 0, 'f'},
56  {"pid-file", 1, 0, 'x'},
57  {"strict-order", 0, 0, 'o'},
58  {"server", 1, 0, 'S'},
59  {"local", 1, 0, 'S' },
60  {"address", 1, 0, 'A' },
61  {"conf-file", 1, 0, 'C'},
62  {"no-resolv", 0, 0, 'R'},
63  {"expand-hosts", 0, 0, 'E'},
64  {"localmx", 0, 0, 'L'},
65  {"local-ttl", 1, 0, 'T'},
66  {"no-negcache", 0, 0, 'N'},
67  {"addn-hosts", 1, 0, 'H'},
68  {"query-port", 1, 0, 'Q'},
69  {"except-interface", 1, 0, 'I'},
70  {"domain-needed", 0, 0, 'D'},
71  {"dhcp-lease-max", 1, 0, 'X' },
72  {"bind-interfaces", 0, 0, 'z'},
73  {"read-ethers", 0, 0, 'Z' },
74  {"alias", 1, 0, 'V' },
75  {"dhcp-vendorclass", 1, 0, 'U'},
76  {"dhcp-userclass", 1, 0, 'j'},
77  {"edns-packet-max", 1, 0, 'P'},
78  {"keep-in-foreground", 0, 0, 'k'},
79#ifdef OPENDNS_PARENTAL_CONTROL
80  {"device-id", 1, 0, LOPT_DEVICE_ID },/* Foxconn add, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */
81#endif
82  {0, 0, 0, 0}
83};
84
85struct optflags {
86  char c;
87  unsigned int flag;
88};
89
90static struct optflags optmap[] = {
91  { 'b', OPT_BOGUSPRIV },
92  { 'f', OPT_FILTER },
93  { 'q', OPT_LOG },
94  { 'e', OPT_SELFMX },
95  { 'h', OPT_NO_HOSTS },
96  { 'n', OPT_NO_POLL },
97  { 'd', OPT_DEBUG },
98  { 'k', OPT_NO_FORK },
99  { 'o', OPT_ORDER },
100  { 'R', OPT_NO_RESOLV },
101  { 'E', OPT_EXPAND },
102  { 'L', OPT_LOCALMX },
103  { 'N', OPT_NO_NEG },
104  { 'D', OPT_NODOTS_LOCAL },
105  { 'z', OPT_NOWILD },
106  { 'Z', OPT_ETHERS },
107  { 'v', 0},
108  { 'w', 0},
109  { 0, 0 }
110};
111
112static char *usage =
113#ifndef MULTIPLE_PPPOE /* foxconn removed start, 08/31/2007, for downsize ram usage */
114"Usage: dnsmasq [options]\n"
115"\nValid options are :\n"
116"-a, --listen-address=ipaddr         Specify local address(es) to listen on.\n"
117"-A, --address=/domain/ipaddr        Return ipaddr for all hosts in specified domains.\n"
118"-b, --bogus-priv                    Fake reverse lookups for RFC1918 private address ranges.\n"
119"-B, --bogus-nxdomain=ipaddr         Treat ipaddr as NXDOMAIN (defeats Verisign wildcard).\n"
120"-c, --cache-size=cachesize          Specify the size of the cache in entries (defaults to %d).\n"
121"-C, --conf-file=path                Specify configuration file (defaults to " CONFFILE ").\n"
122"-d, --no-daemon                     Do NOT fork into the background: run in debug mode.\n"
123"-D, --domain-needed                 Do NOT forward queries with no domain part.\n"
124"-e, --selfmx                        Return self-pointing MX records for local hosts.\n"
125"-E, --expand-hosts                  Expand simple names in /etc/hosts with domain-suffix.\n"
126"-f, --filterwin2k                   Don't forward spurious DNS requests from Windows hosts.\n"
127"-F, --dhcp-range=ipaddr,ipaddr,time Enable DHCP in the range given with lease duration.\n"
128"-g, --group=groupname               Change to this group after startup (defaults to " CHGRP ").\n"
129"-G, --dhcp-host=<hostspec>          Set address or hostname for a specified machine.\n"
130"-h, --no-hosts                      Do NOT load " HOSTSFILE " file.\n"
131"-H, --addn-hosts=path               Specify a hosts file to be read in addition to " HOSTSFILE ".\n"
132"-i, --interface=interface           Specify interface(s) to listen on.\n"
133"-I, --except-interface=int          Specify interface(s) NOT to listen on.\n"
134"-j, --dhcp-userclass=<id>,<class>   Map DHCP user class to option set.\n"
135"-k, --keep-in-foreground            Do NOT fork into the background, do NOT run in debug mode.\n"
136"-l, --dhcp-leasefile=path           Specify where to store DHCP leases (defaults to " LEASEFILE ").\n"
137"-L, --localmx                       Return MX records for local hosts.\n"
138"-m, --mx-host=host_name             Specify the MX name to reply to.\n"
139"-M, --dhcp-boot=<bootp opts>        Specify BOOTP options to DHCP server.\n"
140"-n, --no-poll                       Do NOT poll " RESOLVFILE " file, reload only on SIGHUP.\n"
141"-N, --no-negcache                   Do NOT cache failed search results.\n"
142"-o, --strict-order                  Use nameservers strictly in the order given in " RESOLVFILE ".\n"
143"-O, --dhcp-option=<optspec>         Set extra options to be set to DHCP clients.\n"
144"-p, --port=number                   Specify port to listen for DNS requests on (defaults to 53).\n"
145"-P, --edns-packet-max=<size>        Maximum supported UDP packet size for EDNS.0 (defaults to %d).\n"
146"-q, --log-queries                   Log queries.\n"
147"-Q, --query-port=number             Force the originating port for upstream queries.\n"
148"-R, --no-resolv                     Do NOT read resolv.conf.\n"
149"-r, --resolv-file=path              Specify path to resolv.conf (defaults to " RESOLVFILE ").\n"
150"-S, --server=/domain/ipaddr         Specify address(es) of upstream servers with optional domains.\n"
151"    --local=/domain/                Never forward queries to specified domains.\n"
152"-s, --domain=domain                 Specify the domain to be assigned in DHCP leases.\n"
153"-t, --mx-target=host_name           Specify the host in an MX reply.\n"
154"-T, --local-ttl=time                Specify time-to-live in seconds for replies from /etc/hosts.\n"
155"-u, --user=username                 Change to this user after startup. (defaults to " CHUSER ").\n"
156"-U, --dhcp-vendorclass=<id>,<class> Map DHCP vendor class to option set.\n"
157"-v, --version                       Display dnsmasq version and copyright information.\n"
158"-V, --alias=addr,addr,mask          Translate IPv4 addresses from upstream servers.\n"
159"-w, --help                          Display this message.\n"
160"-x, --pid-file=path                 Specify path of PID file. (defaults to " RUNFILE ").\n"
161"-X, --dhcp-lease-max=number         Specify maximum number of DHCP leases (defaults to %d).\n"
162"-z, --bind-interfaces               Bind only to interfaces in use.\n"
163"-Z, --read-ethers                   Read DHCP static host information from " ETHERSFILE ".\n"
164#endif /* foxconn wklin removed end, 08/31/2007, for downsize ram usage */
165"\n";
166
167struct daemon *read_opts (int argc, char **argv)
168{
169  struct daemon *daemon = safe_malloc(sizeof(struct daemon));
170  char *problem = NULL, *buff = safe_malloc(MAXDNAME);
171  int option = 0, i;
172  FILE *file_save = NULL, *f = NULL;
173  char *file_name_save = NULL, *conffile = CONFFILE;
174  int conffile_set = 0;
175  int line_save = 0, lineno = 0;
176  opterr = 0;
177
178  memset(daemon, 0, sizeof(struct daemon));
179  daemon->namebuff = buff;
180
181  /* Set defaults - everything else is zero or NULL */
182  daemon->min_leasetime = UINT_MAX;
183  daemon->cachesize = CACHESIZ;
184  daemon->port = NAMESERVER_PORT;
185  daemon->default_resolv.is_default = 1;
186  daemon->default_resolv.name = RESOLVFILE;
187  daemon->resolv_files = &daemon->default_resolv;
188  daemon->username = CHUSER;
189  daemon->groupname = CHGRP;
190  daemon->runfile =  RUNFILE;
191  daemon->dhcp_max = MAXLEASES;
192  daemon->edns_pktsz = EDNS_PKTSZ;
193
194  while (1)
195    {
196      problem = NULL;
197
198      if (!f)
199#ifdef HAVE_GETOPT_LONG
200	option = getopt_long(argc, argv, OPTSTRING, (struct option *)opts, NULL);
201#else
202        option = getopt(argc, argv, OPTSTRING);
203#endif
204      else
205	{ /* f non-NULL, reading from conffile. */
206	reread:
207	  if (!fgets(buff, MAXDNAME, f))
208	    {
209	      /* At end of file, all done */
210	      fclose(f);
211	      if (file_save)
212		{
213		  /* may be nested */
214		  conffile = file_name_save;
215		  f = file_save;
216		  file_save = NULL;
217		  lineno = line_save;
218		  goto reread;
219		}
220	      break;
221	    }
222	  else
223	    {
224	      char *p;
225	      int white;
226	      lineno++;
227	      /* dump comments */
228	      for (white = 1, p = buff; *p; p++)
229		if (white && *p == '#')
230		  {
231		    *p = 0;
232		    break;
233		  }
234		else
235		  white = isspace(*p);
236	      /* fgets gets end of line char too. */
237	      while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
238		buff[strlen(buff)-1] = 0;
239	      if (*buff == 0)
240		continue;
241	      if ((p=strchr(buff, '=')))
242		{
243		  optarg = p+1;
244		  *p = 0;
245		}
246	      else
247		optarg = NULL;
248
249	      option = 0;
250	      for (i=0; opts[i].name; i++)
251		if (strcmp(opts[i].name, buff) == 0)
252		  option = opts[i].val;
253	      if (!option)
254		{
255		  sprintf(buff, "bad option at line %d of %s ", lineno, conffile);
256		  complain(buff, NULL);
257		  continue;
258		}
259	    }
260	}
261
262      if (option == -1)
263	{ /* end of command line args, start reading conffile. */
264	  if (!conffile)
265	    break; /* "confile=" option disables */
266	fileopen:
267	  option = 0;
268	  if (!(f = fopen(conffile, "r")))
269	    {
270	      if (errno == ENOENT && !conffile_set)
271		break; /* No conffile, all done. */
272	      else
273		die("cannot read %s: %s", conffile);
274	    }
275	}
276
277      if (!f && option == 'w')
278	{
279#if !defined(MULTIPLE_PPPOE) /* foxconn wklin modified, for multiple pppoe, 08/31/2007 */
280	  fprintf (stderr, usage,  CACHESIZ, EDNS_PKTSZ, MAXLEASES);
281	  exit(0);
282#else
283	  extern int mpoe;
284	  mpoe = 1;
285#endif /* foxconn wklin modified end, 08/31/2007 */
286	}
287
288      if (!f && option == 'v')
289        {
290          fprintf(stderr, "Dnsmasq version %s  %s\n\n", VERSION, COPYRIGHT);
291	  fprintf(stderr, "This software comes with ABSOLUTELY NO WARRANTY.\n");
292	  fprintf(stderr, "Dnsmasq is free software, and you are welcome to redistribute it\n");
293	  fprintf(stderr, "under the terms of the GNU General Public License, version 2.\n");
294          exit(0);
295        }
296
297      for (i=0; optmap[i].c; i++)
298	if (option == optmap[i].c)
299	  {
300	    daemon->options |= optmap[i].flag;
301	    option = 0;
302	    if (f && optarg)
303	      {
304		sprintf(buff, "extraneous parameter at line %d of %s ", lineno, conffile);
305		complain(buff, NULL);
306	      }
307	    break;
308	  }
309
310      if (option && option != '?')
311	{
312	  if (f && !optarg)
313	    {
314	      sprintf(buff, "missing parameter at line %d of %s ", lineno, conffile);
315	      complain(buff, NULL);
316	      continue;
317	    }
318
319	  switch (option)
320	    {
321	     case 'C':
322	       if (!f)
323		 {
324		   conffile = safe_string_alloc(optarg);
325		   conffile_set = 1;
326		   break;
327		 }
328
329	       /* nest conffiles one deep */
330	       if (file_save)
331		 {
332		   sprintf(buff, "nested includes not allowed at line %d of %s ", lineno, conffile);
333		   complain(buff, NULL);
334		   continue;
335		 }
336	       file_name_save = conffile;
337	       file_save = f;
338	       line_save = lineno;
339	       conffile = safe_string_alloc(optarg);
340	       conffile_set = 1;
341	       lineno = 0;
342	       goto fileopen;
343
344	    case 'x':
345	      daemon->runfile = safe_string_alloc(optarg);
346	      break;
347
348	    case 'r':
349	      {
350		char *name = safe_string_alloc(optarg);
351		struct resolvc *new, *list = daemon->resolv_files;
352		if (list && list->is_default)
353		  {
354		    /* replace default resolv file - possibly with nothing */
355		    if (name)
356		      {
357			list->is_default = 0;
358			list->name = name;
359		      }
360		    else
361		      list = NULL;
362		  }
363		else if (name)
364		  {
365		    new = safe_malloc(sizeof(struct resolvc));
366		    new->next = list;
367		    new->name = name;
368		    new->is_default = 0;
369		    new->logged = 0;
370		    list = new;
371		  }
372		daemon->resolv_files = list;
373		break;
374	      }
375
376	    case 'm':
377	      {
378		char *comma = strchr(optarg, ',');
379		if (comma)
380		  *(comma++) = 0;
381		if (!canonicalise(optarg) || (comma && !canonicalise(comma)))
382		  {
383		    option = '?';
384		    problem = "bad MX name";
385		  }
386		else
387		  {
388		    struct mx_record *new = safe_malloc(sizeof(struct mx_record));
389		    new->next = daemon->mxnames;
390		    daemon->mxnames = new;
391		    new->mxname = safe_string_alloc(optarg);
392		    new->mxtarget = safe_string_alloc(comma); /* may be NULL */
393		  }
394		break;
395	      }
396
397	    case 't':
398	      if (!canonicalise(optarg))
399		{
400		  option = '?';
401		  problem = "bad MX target";
402		}
403	      else
404		daemon->mxtarget = safe_string_alloc(optarg);
405	      break;
406
407	    case 'l':
408	      daemon->lease_file = safe_string_alloc(optarg);
409	      break;
410
411	    case 'H':
412	      if (daemon->addn_hosts)
413		{
414		  option = '?';
415		  problem = "only one addn hosts file allowed";
416		}
417	      else
418		daemon->addn_hosts = safe_string_alloc(optarg);
419	      break;
420
421	    case 's':
422	      if (strcmp (optarg, "#") == 0)
423		daemon->options |= OPT_RESOLV_DOMAIN;
424	      else if (!canonicalise(optarg))
425		option = '?';
426	      else
427		daemon->domain_suffix = safe_string_alloc(optarg);
428	      break;
429
430	    case 'u':
431	      daemon->username = safe_string_alloc(optarg);
432	      break;
433
434	    case 'g':
435	      daemon->groupname = safe_string_alloc(optarg);
436	      break;
437
438	    case 'i':
439	      {
440		struct iname *new = safe_malloc(sizeof(struct iname));
441		new->next = daemon->if_names;
442		daemon->if_names = new;
443		/* new->name may be NULL if someone does
444		   "interface=" to disable all interfaces except loop. */
445		new->name = safe_string_alloc(optarg);
446		new->isloop = new->used = 0;
447		if (strchr(optarg, ':'))
448		  daemon->options |= OPT_NOWILD;
449		break;
450	      }
451
452	    case 'I':
453	      {
454		struct iname *new = safe_malloc(sizeof(struct iname));
455		new->next = daemon->if_except;
456		daemon->if_except = new;
457		new->name = safe_string_alloc(optarg);
458		if (strchr(optarg, ':'))
459		   daemon->options |= OPT_NOWILD;
460		break;
461	      }
462
463	    case 'B':
464	      {
465		struct in_addr addr;
466		if ((addr.s_addr = inet_addr(optarg)) != (in_addr_t)-1)
467		  {
468		    struct bogus_addr *baddr = safe_malloc(sizeof(struct bogus_addr));
469		    baddr->next = daemon->bogus_addr;
470		    daemon->bogus_addr = baddr;
471		    baddr->addr = addr;
472		  }
473		else
474		  option = '?'; /* error */
475		break;
476	      }
477
478	    case 'a':
479	      {
480		struct iname *new = safe_malloc(sizeof(struct iname));
481		new->next = daemon->if_addrs;
482#ifdef HAVE_IPV6
483		if (inet_pton(AF_INET, optarg, &new->addr.in.sin_addr))
484		  {
485		    new->addr.sa.sa_family = AF_INET;
486#ifdef HAVE_SOCKADDR_SA_LEN
487		    new->addr.in.sin_len = sizeof(struct sockaddr_in);
488#endif
489		  }
490		else if (inet_pton(AF_INET6, optarg, &new->addr.in6.sin6_addr))
491		  {
492		    new->addr.sa.sa_family = AF_INET6;
493		    new->addr.in6.sin6_flowinfo = htonl(0);
494#ifdef HAVE_SOCKADDR_SA_LEN
495		    new->addr.in6.sin6_len = sizeof(struct sockaddr_in6);
496#endif
497		  }
498#else
499		if ((new->addr.in.sin_addr.s_addr = inet_addr(optarg)) != (in_addr_t)-1)
500		  {
501		    new->addr.sa.sa_family = AF_INET;
502#ifdef HAVE_SOCKADDR_SA_LEN
503		    new->addr.in.sin_len = sizeof(struct sockaddr_in);
504#endif
505		  }
506#endif
507		else
508		  {
509		    option = '?'; /* error */
510		    free(new);
511		    new = NULL;
512		  }
513
514		if (new)
515		  daemon->if_addrs = new;
516		break;
517	      }
518
519	    case 'S':
520	    case 'A':
521	      {
522		struct server *serv, *newlist = NULL;
523
524		if (*optarg == '/')
525		  {
526		    char *end;
527		    optarg++;
528		    while ((end = strchr(optarg, '/')))
529		      {
530			char *domain = NULL;
531			*end = 0;
532			/* # matches everything and becomes a zero length domain string */
533			if (strcmp(optarg, "#") == 0)
534			  domain = "";
535			else if (!canonicalise(optarg) && strlen(optarg) != 0)
536			  option = '?';
537			else
538			  domain = safe_string_alloc(optarg); /* NULL if strlen is zero */
539			serv = safe_malloc(sizeof(struct server));
540			serv->next = newlist;
541			newlist = serv;
542			serv->sfd = NULL;
543			serv->domain = domain;
544			serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
545			optarg = end+1;
546		      }
547		    if (!newlist)
548		      {
549			option = '?';
550			break;
551		      }
552
553		  }
554		else
555		  {
556		    newlist = safe_malloc(sizeof(struct server));
557		    newlist->next = NULL;
558		    newlist->flags = 0;
559		    newlist->sfd = NULL;
560		    newlist->domain = NULL;
561		  }
562
563		if (option == 'A')
564		  {
565		    newlist->flags |= SERV_LITERAL_ADDRESS;
566		    if (!(newlist->flags & SERV_TYPE))
567		      option = '?';
568		  }
569
570		if (!*optarg)
571		  {
572		    newlist->flags |= SERV_NO_ADDR; /* no server */
573		    if (newlist->flags & SERV_LITERAL_ADDRESS)
574		      option = '?';
575		  }
576		else
577		  {
578		    int source_port = 0, serv_port = NAMESERVER_PORT;
579		    char *portno, *source;
580
581		    if ((source = strchr(optarg, '@'))) /* is there a source. */
582		      {
583			*source = 0;
584			if ((portno = strchr(source+1, '#')))
585			  {
586			    *portno = 0;
587			    if (!atoi_check(portno+1, &source_port))
588			      {
589				option = '?';
590				problem = "bad port";
591			      }
592			  }
593		      }
594
595		    if ((portno = strchr(optarg, '#'))) /* is there a port no. */
596		      {
597			*portno = 0;
598			if (!atoi_check(portno+1, &serv_port))
599			  {
600			    option = '?';
601			    problem = "bad port";
602			  }
603		      }
604
605#ifdef HAVE_IPV6
606		    if (inet_pton(AF_INET, optarg, &newlist->addr.in.sin_addr))
607#else
608		    if ((newlist->addr.in.sin_addr.s_addr = inet_addr(optarg)) != (in_addr_t) -1)
609#endif
610		      {
611			newlist->addr.in.sin_port = htons(serv_port);
612			newlist->source_addr.in.sin_port = htons(source_port);
613			newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
614#ifdef HAVE_SOCKADDR_SA_LEN
615			newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
616#endif
617			if (source)
618			  {
619#ifdef HAVE_IPV6
620			    if (inet_pton(AF_INET, source+1, &newlist->source_addr.in.sin_addr))
621#else
622			    if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source+1)) != (in_addr_t) -1)
623#endif
624				newlist->flags |= SERV_HAS_SOURCE;
625			    else
626			      option = '?'; /* error */
627			  }
628			else
629			  newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
630		      }
631#ifdef HAVE_IPV6
632		    else if (inet_pton(AF_INET6, optarg, &newlist->addr.in6.sin6_addr))
633		      {
634			newlist->addr.in6.sin6_port = htons(serv_port);
635			newlist->source_addr.in6.sin6_port = htons(source_port);
636			newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
637			newlist->addr.in6.sin6_flowinfo = newlist->source_addr.in6.sin6_flowinfo = htonl(0);
638#ifdef HAVE_SOCKADDR_SA_LEN
639			newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(struct sockaddr_in6);
640#endif
641			if (source)
642			  {
643			    if (inet_pton(AF_INET6, source+1, &newlist->source_addr.in6.sin6_addr))
644			      newlist->flags |= SERV_HAS_SOURCE;
645			    else
646			      option = '?'; /* error */
647			  }
648			else
649			  newlist->source_addr.in6.sin6_addr = in6addr_any;
650		      }
651#endif
652		    else
653		      option = '?'; /* error */
654
655		  }
656
657		if (option == '?')
658		  while (newlist)
659		    {
660		      serv = newlist;
661		      newlist = newlist->next;
662		      free(serv);
663		    }
664		else
665		  {
666		    serv = newlist;
667		    while (serv->next)
668		      {
669			serv->next->flags = serv->flags;
670			serv->next->addr = serv->addr;
671			serv->next->source_addr = serv->source_addr;
672			serv = serv->next;
673		      }
674		    serv->next = daemon->servers;
675		    daemon->servers = newlist;
676		  }
677		break;
678	      }
679
680	    case 'c':
681	      {
682		int size;
683		if (!atoi_check(optarg, &size))
684		  option = '?';
685		else
686		  {
687		    /* zero is OK, and means no caching. */
688
689		    if (size < 0)
690		      size = 0;
691		    else if (size > 10000)
692		      size = 10000;
693
694		    daemon->cachesize = size;
695		  }
696		break;
697	      }
698
699	    case 'p':
700	      if (!atoi_check(optarg, &daemon->port))
701		option = '?';
702	      break;
703
704	    case 'P':
705	      {
706		int i;
707		if (!atoi_check(optarg, &i))
708		  option = '?';
709		daemon->edns_pktsz = (unsigned short)i;
710		break;
711	      }
712
713	    case 'Q':
714	      if (!atoi_check(optarg, &daemon->query_port))
715		option = '?';
716	      break;
717
718	    case 'T':
719	      {
720		int ttl;
721		if (!atoi_check(optarg, &ttl))
722		  option = '?';
723		else
724		  daemon->local_ttl = (unsigned long)ttl;
725		break;
726	      }
727
728	    case 'X':
729	      if (!atoi_check(optarg, &daemon->dhcp_max))
730		option = '?';
731	      break;
732
733	    case 'F':
734	      {
735		int k, leasepos = 2;
736		char *cp, *comma, *a[5] = { NULL, NULL, NULL, NULL, NULL };
737		struct dhcp_context *new = safe_malloc(sizeof(struct dhcp_context));
738
739		new->next = daemon->dhcp;
740		new->lease_time = DEFLEASE;
741		new->addr_epoch = 0;
742		new->netmask.s_addr = 0;
743		new->broadcast.s_addr = 0;
744		new->router.s_addr = 0;
745		new->netid.net = NULL;
746		new->static_only = 0;
747
748		problem = "bad dhcp-range";
749
750		for (cp = optarg; *cp; cp++)
751		  if (!(*cp == ' ' || *cp == '.' ||  (*cp >='0' && *cp <= '9')))
752		    break;
753
754		if (*cp != ',' && (comma = strchr(optarg, ',')))
755		  {
756		    *comma = 0;
757		    new->netid.net = safe_string_alloc(optarg);
758		    a[0] = comma + 1;
759		  }
760		else
761		  a[0] = optarg;
762
763
764		for (k = 1; k < 5; k++)
765		  {
766		    if (!(a[k] = strchr(a[k-1], ',')))
767		      break;
768		    *(a[k]++) = 0;
769		  }
770
771		if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
772		  option = '?';
773		else if (strcmp(a[1], "static") == 0)
774		  {
775		    new->end = new->start;
776		    new->static_only = 1;
777		  }
778		else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
779		  option = '?';
780
781		if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
782		  {
783		    struct in_addr tmp = new->start;
784		    new->start = new->end;
785		    new->end = tmp;
786		  }
787
788		if (option != '?' && k >= 3 && strchr(a[2], '.') &&
789		    ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
790		  {
791		    leasepos = 3;
792		    if (!is_same_net(new->start, new->end, new->netmask))
793		      {
794			problem = "inconsistent DHCP range";
795			option = '?';
796		      }
797		  }
798
799		if (option == '?')
800		  {
801		    free(new);
802		    break;
803		  }
804		else
805		  daemon->dhcp = new;
806
807		if (k >= 4 && strchr(a[3], '.') &&
808		    ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
809		  leasepos = 4;
810
811		if (k >= leasepos+1)
812		  {
813		    if (strcmp(a[leasepos], "infinite") == 0)
814		      new->lease_time = 0xffffffff;
815		    else
816		      {
817			int fac = 1;
818			if (strlen(a[leasepos]) > 0)
819			  {
820			    switch (a[leasepos][strlen(a[leasepos]) - 1])
821			      {
822			      case 'h':
823			      case 'H':
824				fac *= 60;
825				/* fall through */
826			      case 'm':
827			      case 'M':
828				fac *= 60;
829				/* fall through */
830			      case 's':
831			      case 'S':
832				a[leasepos][strlen(a[leasepos]) - 1] = 0;
833			      }
834
835			    new->lease_time = atoi(a[leasepos]) * fac;
836			  }
837		      }
838		  }
839
840		if (new->lease_time < daemon->min_leasetime)
841		  daemon->min_leasetime = new->lease_time;
842		break;
843	      }
844
845	    case 'G':
846	      {
847		int j, k;
848		char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
849		unsigned int e0, e1, e2, e3, e4, e5;
850		struct dhcp_config *new = safe_malloc(sizeof(struct dhcp_config));
851		struct in_addr in;
852
853		new->next = daemon->dhcp_conf;
854		new->flags = 0;
855
856
857		a[0] = optarg;
858		for (k = 1; k < 6; k++)
859		  {
860		    if (!(a[k] = strchr(a[k-1], ',')))
861		      break;
862		    *(a[k]++) = 0;
863		  }
864
865		for(j = 0; j < k; j++)
866		  if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
867		    {
868		      char *arg = a[j];
869		      if ((arg[0] == 'i' || arg[0] == 'I') &&
870			  (arg[1] == 'd' || arg[1] == 'D') &&
871			  arg[2] == ':')
872			{
873			  if (arg[3] == '*')
874			    new->flags |= CONFIG_NOCLID;
875			  else
876			    {
877			      int len;
878			      arg += 3; /* dump id: */
879			      if (strchr(arg, ':'))
880				{
881				  /* decode hex in place */
882				  char *p = arg, *q = arg, *r;
883				  while (*p)
884				    {
885				      for (r = p; *r && *r != ':'; r++);
886				      if (*r)
887					{
888					  if (r != p)
889					    {
890					      *r = 0;
891					      *(q++) = strtol(p, NULL, 16);
892					    }
893					  p = r+1;
894					}
895				      else
896					{
897					  if (*p)
898					    *(q++) = strtol(p, NULL, 16);
899					  break;
900					}
901				    }
902				  len = q - arg;
903				}
904			      else
905				len = strlen(arg);
906
907			      new->flags |= CONFIG_CLID;
908			      new->clid_len = len;
909			      new->clid = safe_malloc(len);
910			      memcpy(new->clid, arg, len);
911			    }
912			}
913		      else if ((arg[0] == 'n' || arg[0] == 'N') &&
914			       (arg[1] == 'e' || arg[1] == 'E') &&
915			       (arg[2] == 't' || arg[3] == 'T') &&
916			       arg[3] == ':')
917			{
918			  new->flags |= CONFIG_NETID;
919			  new->netid.net = safe_string_alloc(arg+4);
920			}
921		      else if (sscanf(a[j], "%x:%x:%x:%x:%x:%x",
922				      &e0, &e1, &e2, &e3, &e4, &e5) == 6)
923			{
924			  new->flags |= CONFIG_HWADDR;
925			  new->hwaddr[0] = e0;
926			  new->hwaddr[1] = e1;
927			  new->hwaddr[2] = e2;
928			  new->hwaddr[3] = e3;
929			  new->hwaddr[4] = e4;
930			  new->hwaddr[5] = e5;
931			}
932		      else
933			option = '?';
934		    }
935		  else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
936		    {
937		      new->addr = in;
938		      new->flags |= CONFIG_ADDR;
939		    }
940		  else
941		    {
942		      char *cp, *lastp = NULL, last = 0;
943		      int fac = 1;
944
945		      if (strlen(a[j]) > 1)
946			{
947			  lastp = a[j] + strlen(a[j]) - 1;
948			  last = *lastp;
949			  switch (last)
950			    {
951			    case 'h':
952			    case 'H':
953			      fac *= 60;
954			      /* fall through */
955			    case 'm':
956			    case 'M':
957			      fac *= 60;
958			      /* fall through */
959			    case 's':
960			    case 'S':
961			      *lastp = 0;
962			    }
963			}
964
965		      for (cp = a[j]; *cp; cp++)
966			if (!isdigit(*cp) && *cp != ' ')
967			  break;
968
969		      if (*cp)
970			{
971			  if (lastp)
972			    *lastp = last;
973			  if (strcmp(a[j], "infinite") == 0)
974			    {
975			      new->lease_time = 0xffffffff;
976			      new->flags |= CONFIG_TIME;
977			    }
978			  else if (strcmp(a[j], "ignore") == 0)
979			    new->flags |= CONFIG_DISABLE;
980			  else
981			    {
982			      new->hostname = safe_string_alloc(a[j]);
983			      new->flags |= CONFIG_NAME;
984			    }
985			}
986		      else
987			{
988			  new->lease_time = atoi(a[j]) * fac;
989			  new->flags |= CONFIG_TIME;
990			}
991		    }
992
993		if (option == '?')
994		  {
995		    problem = "bad dhcp-host";
996		    if (new->flags & CONFIG_NAME)
997		      free(new->hostname);
998		    if (new->flags & CONFIG_CLID)
999		      free(new->clid);
1000		    if (new->flags & CONFIG_NETID)
1001		      free(new->netid.net);
1002		    free(new);
1003		  }
1004		else
1005		  {
1006		    if ((new->flags & CONFIG_TIME) && new->lease_time < daemon->min_leasetime)
1007		      daemon->min_leasetime = new->lease_time;
1008		    daemon->dhcp_conf = new;
1009		  }
1010		break;
1011	      }
1012
1013	    case 'O':
1014	      {
1015		struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
1016		char *cp, *comma;
1017		int addrs, digs, is_addr, is_hex, is_dec;
1018
1019		new->next = daemon->dhcp_opts;
1020		new->len = 0;
1021		new->is_addr = 0;
1022		new->netid = NULL;
1023
1024		if ((comma = strchr(optarg, ',')))
1025		  {
1026		    *comma = 0;
1027
1028		    for (cp = optarg; *cp; cp++)
1029		      if (!(*cp == ' ' || (*cp >='0' && *cp <= '9')))
1030			break;
1031
1032		    if (*cp)
1033		      {
1034			new->netid = safe_string_alloc(optarg);
1035			optarg = comma + 1;
1036			if ((comma = strchr(optarg, ',')))
1037			  *comma = 0;
1038		      }
1039		  }
1040
1041		if ((new->opt = atoi(optarg)) == 0)
1042		  {
1043		    option = '?';
1044		    problem = "bad dhcp-opt";
1045		    if (new->netid)
1046		      free(new->netid);
1047		    free(new);
1048		    break;
1049		  }
1050
1051		daemon->dhcp_opts = new;
1052
1053		if (!comma)
1054		  break;
1055
1056		/* characterise the value */
1057		is_addr = is_hex = is_dec = 1;
1058		addrs = digs = 1;
1059		for (cp = comma+1; *cp; cp++)
1060		  if (*cp == ',')
1061		    {
1062		      addrs++;
1063		      is_dec = is_hex = 0;
1064		    }
1065		  else if (*cp == ':')
1066		    {
1067		      digs++;
1068		      is_dec = is_addr = 0;
1069		    }
1070		  else if (*cp == '.')
1071		    is_dec = is_hex = 0;
1072		  else if (!(*cp >='0' && *cp <= '9'))
1073		      {
1074			is_dec = is_addr = 0;
1075			if (!((*cp >='A' && *cp <= 'F') ||
1076			      (*cp >='a' && *cp <= 'f')))
1077			  is_hex = 0;
1078		      }
1079
1080		if (is_hex && digs > 1)
1081		  {
1082		    char *p = comma+1, *q, *r;
1083		    new->len = digs;
1084		    q = new->val = safe_malloc(new->len);
1085		    while (*p)
1086		      {
1087			for (r = p; *r && *r != ':'; r++);
1088			if (*r)
1089			  {
1090			    if (r != p)
1091			      {
1092				*r = 0;
1093				*(q++) = strtol(p, NULL, 16);
1094			      }
1095			    p = r+1;
1096			  }
1097			else
1098			  {
1099			    if (*p)
1100			      *(q++) = strtol(p, NULL, 16);
1101			    break;
1102			  }
1103		      }
1104		  }
1105		else if (is_dec)
1106		  {
1107		    /* Given that we don't know the length,
1108		       this appaling hack is the best available */
1109		    unsigned int val = atoi(comma+1);
1110		    if (val < 256)
1111		      {
1112			new->len = 1;
1113			new->val = safe_malloc(1);
1114			*(new->val) = val;
1115		      }
1116		    else if (val < 65536)
1117		      {
1118			new->len = 2;
1119			new->val = safe_malloc(2);
1120			*(new->val) = val>>8;
1121			*(new->val+1) = val;
1122		      }
1123		    else
1124		      {
1125			new->len = 4;
1126			new->val = safe_malloc(4);
1127			*(new->val) = val>>24;
1128			*(new->val+1) = val>>16;
1129			*(new->val+2) = val>>8;
1130			*(new->val+3) = val;
1131		      }
1132		  }
1133		else if (is_addr)
1134		  {
1135		    struct in_addr in;
1136		    unsigned char *op;
1137		    new->len = INADDRSZ * addrs;
1138		    new->val = op = safe_malloc(new->len);
1139		    new->is_addr = 1;
1140		    while (addrs--)
1141		      {
1142			cp = comma;
1143			if ((comma = strchr(cp+1, ',')))
1144			  *comma = 0;
1145			in.s_addr = inet_addr(cp+1);
1146			memcpy(op, &in, INADDRSZ);
1147			op += INADDRSZ;
1148		      }
1149		  }
1150		else
1151		  {
1152		    /* text arg */
1153		    new->len = strlen(comma+1);
1154		    new->val = safe_malloc(new->len);
1155		    memcpy(new->val, comma+1, new->len);
1156		  }
1157		break;
1158	      }
1159
1160	    case 'M':
1161	      {
1162		char *comma;
1163
1164		if ((comma = strchr(optarg, ',')))
1165		  *comma = 0;
1166		daemon->dhcp_file = safe_string_alloc(optarg);
1167		if (comma)
1168		  {
1169		    optarg = comma+1;
1170		    if ((comma = strchr(optarg, ',')))
1171		      *comma = 0;
1172		    daemon->dhcp_sname = safe_string_alloc(optarg);
1173		    if (comma && (daemon->dhcp_next_server.s_addr = inet_addr(comma+1)) == (in_addr_t)-1)
1174		      option = '?';
1175		  }
1176		break;
1177	      }
1178
1179	    case 'U':
1180	    case 'j':
1181	      {
1182		char *comma;
1183
1184		if (!(comma = strchr(optarg, ',')))
1185		  option = '?';
1186		else
1187		  {
1188		    struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
1189		    *comma = 0;
1190		    new->netid.net = safe_string_alloc(optarg);
1191		    new->len = strlen(comma+1);
1192		    new->data = safe_malloc(new->len);
1193		    memcpy(new->data, comma+1, new->len);
1194		    new->is_vendor = (option == 'U');
1195		    new->next = daemon->dhcp_vendors;
1196		    daemon->dhcp_vendors = new;
1197		  }
1198		break;
1199	      }
1200
1201	    case 'V':
1202	      {
1203		char *a[3] = { NULL, NULL, NULL };
1204		int k;
1205		struct in_addr in, out, mask;
1206		struct doctor *new;
1207
1208		mask.s_addr = 0xffffffff;
1209
1210		a[0] = optarg;
1211		for (k = 1; k < 4; k++)
1212		  {
1213		    if (!(a[k] = strchr(a[k-1], ',')))
1214		      break;
1215		    *(a[k]++) = 0;
1216		  }
1217
1218		if ((k < 2) ||
1219		    ((in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
1220		    ((out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
1221		  {
1222		    option = '?';
1223		    break;
1224		  }
1225
1226		if (k == 3)
1227		  mask.s_addr = inet_addr(a[2]);
1228
1229		new = safe_malloc(sizeof(struct doctor));
1230		new->in = in;
1231		new->out = out;
1232		new->mask = mask;
1233		new->next = daemon->doctors;
1234		daemon->doctors = new;
1235
1236		break;
1237	      }
1238	    /* Foxconn add start, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */
1239#ifdef OPENDNS_PARENTAL_CONTROL
1240	    case LOPT_DEVICE_ID:  /* --device-id */
1241        {
1242            char *endptr;
1243            unsigned long long device_id;
1244
1245            errno = 0;
1246            //device_id = strtoull(arg, &endptr, 16);
1247            device_id = strtoull(argv, &endptr, 16);
1248            if (errno != 0 || *endptr != 0)
1249            {
1250                problem = "invalid device ID";
1251                break;
1252            }
1253            daemon->have_device_id = 1;
1254            for (i = 7; i >= 0; i--)
1255            {
1256                daemon->device_id[i] = (unsigned char)device_id;
1257                device_id >>= 8;
1258            }
1259        }
1260#endif
1261	    /* Foxconn add end  , Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */
1262	    }
1263	}
1264
1265      if (option == '?')
1266	{
1267	  if (f)
1268	    {
1269	      sprintf(buff, "%s at line %d of %s ",
1270		      problem ? problem : "error", lineno, conffile);
1271	      complain(buff, NULL);
1272	    }
1273	  else
1274	    die("bad command line options: %s.", problem ? problem : "try --help");
1275	}
1276    }
1277
1278  /* port might no be known when the address is parsed - fill in here */
1279  if (daemon->servers)
1280    {
1281      struct server *tmp;
1282      for (tmp = daemon->servers; tmp; tmp = tmp->next)
1283	if (!(tmp->flags & SERV_HAS_SOURCE))
1284	  {
1285	    if (tmp->source_addr.sa.sa_family == AF_INET)
1286	      tmp->source_addr.in.sin_port = htons(daemon->query_port);
1287#ifdef HAVE_IPV6
1288	    else if (tmp->source_addr.sa.sa_family == AF_INET6)
1289	      tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
1290#endif
1291	  }
1292    }
1293
1294  if (daemon->if_addrs)
1295    {
1296      struct iname *tmp;
1297      for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
1298	if (tmp->addr.sa.sa_family == AF_INET)
1299	  tmp->addr.in.sin_port = htons(daemon->port);
1300#ifdef HAVE_IPV6
1301	else if (tmp->addr.sa.sa_family == AF_INET6)
1302	  tmp->addr.in6.sin6_port = htons(daemon->port);
1303#endif /* IPv6 */
1304    }
1305
1306  /* only one of these need be specified: the other defaults to the
1307     host-name */
1308  if ((daemon->options & OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
1309    {
1310      if (gethostname(buff, MAXDNAME) == -1)
1311	die("cannot get host-name: %s", NULL);
1312
1313      if (!daemon->mxnames)
1314	{
1315	  daemon->mxnames = safe_malloc(sizeof(struct mx_record));
1316	  daemon->mxnames->next = NULL;
1317	  daemon->mxnames->mxtarget = NULL;
1318	  daemon->mxnames->mxname = safe_string_alloc(buff);
1319}
1320
1321      if (!daemon->mxtarget)
1322	daemon->mxtarget = safe_string_alloc(buff);
1323    }
1324
1325  if (daemon->options & OPT_NO_RESOLV)
1326    daemon->resolv_files = 0;
1327  else if (daemon->resolv_files && (daemon->resolv_files)->next && (daemon->options & OPT_NO_POLL))
1328    die("only one resolv.conf file allowed in no-poll mode.", NULL);
1329
1330  if (daemon->options & OPT_RESOLV_DOMAIN)
1331    {
1332      char *line;
1333
1334      if (!daemon->resolv_files || (daemon->resolv_files)->next)
1335	die("must have exactly one resolv.conf to read domain from.", NULL);
1336
1337      if (!(f = fopen((daemon->resolv_files)->name, "r")))
1338	die("failed to read %s: %m", (daemon->resolv_files)->name);
1339
1340      while ((line = fgets(buff, MAXDNAME, f)))
1341	{
1342	  char *token = strtok(line, " \t\n\r");
1343
1344	  if (!token || strcmp(token, "search") != 0)
1345	    continue;
1346
1347	  if ((token = strtok(NULL, " \t\n\r")) &&
1348	      canonicalise(token) &&
1349	      (daemon->domain_suffix = safe_string_alloc(token)))
1350	    break;
1351	}
1352
1353      fclose(f);
1354
1355      if (!daemon->domain_suffix)
1356	die("no search directive found in %s", (daemon->resolv_files)->name);
1357    }
1358
1359  return daemon;
1360}
1361
1362
1363
1364