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