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