dnsmasq: backport latest pre2.81 patches
[openwrt/openwrt.git] / package / network / services / dnsmasq / patches / 0011-Free-config-file-values-on-parsing-errors.patch
1 From 59e470381f84f2fdf0640c7bc67827f3f0c64784 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
3 Date: Fri, 2 Nov 2018 22:39:39 +0000
4 Subject: [PATCH 11/30] Free config file values on parsing errors.
5
6 This time I have a little bit more controversal patches. But I think
7 still useful. They fixes memory leaks that might occur in some cases.
8 Most dnsmasq errors is fatal, so it does not matter. But some are not.
9 Some parts are reloaded on SIGHUP signal, so it might leak more than once.
10
11 Some example when it changes the failures. Use dhcp-options file with
12 this content:
13
14 tag:error,vendor:redhat
15 option:ntp-server,1.2.3.4.5
16 option6:ntp-server,[:::]
17
18 Is not fatal and dnsmasq will start. On each reload command, it would
19 leak some memory. I validated it using valgrind --leak-check=full
20 dnsmasq -d. This patch fixes it. It introduces something that might be
21 considered constructor and destructor of selected structures.
22
23 Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
24 ---
25 src/option.c | 533 ++++++++++++++++++++++++++++++++++-----------------
26 1 file changed, 352 insertions(+), 181 deletions(-)
27
28 --- a/src/option.c
29 +++ b/src/option.c
30 @@ -577,14 +577,15 @@ static void *opt_malloc(size_t size)
31 return ret;
32 }
33
34 -static char *opt_string_alloc(char *cp)
35 +static char *opt_string_alloc(const char *cp)
36 {
37 char *ret = NULL;
38 + size_t len;
39
40 - if (cp && strlen(cp) != 0)
41 + if (cp && (len = strlen(cp)) != 0)
42 {
43 - ret = opt_malloc(strlen(cp)+1);
44 - strcpy(ret, cp);
45 + ret = opt_malloc(len+1);
46 + memcpy(ret, cp, len+1);
47
48 /* restore hidden metachars */
49 unhide_metas(ret);
50 @@ -759,6 +760,8 @@ static void do_usage(void)
51 }
52
53 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
54 +#define ret_err_free(x,m) do { strcpy(errstr, (x)); free((m)); return 0; } while (0)
55 +#define goto_err(x) do { strcpy(errstr, (x)); goto on_error; } while (0)
56
57 static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
58 {
59 @@ -904,6 +907,8 @@ static struct server *add_rev4(struct in
60 p += sprintf(p, "%d.", (a >> 24) & 0xff);
61 break;
62 default:
63 + free(serv->domain);
64 + free(serv);
65 return NULL;
66 }
67
68 @@ -958,6 +963,97 @@ static char *set_prefix(char *arg)
69 return arg;
70 }
71
72 +static struct dhcp_netid *
73 +dhcp_netid_create(const char *net, struct dhcp_netid *next)
74 +{
75 + struct dhcp_netid *tt;
76 + tt = opt_malloc(sizeof (struct dhcp_netid));
77 + tt->net = opt_string_alloc(net);
78 + tt->next = next;
79 + return tt;
80 +}
81 +
82 +static void dhcp_netid_free(struct dhcp_netid *nid)
83 +{
84 + while (nid)
85 + {
86 + struct dhcp_netid *tmp = nid;
87 + nid = nid->next;
88 + free(tmp->net);
89 + free(tmp);
90 + }
91 +}
92 +
93 +/* Parse one or more tag:s before parameters.
94 + * Moves arg to the end of tags. */
95 +static struct dhcp_netid * dhcp_tags(char **arg)
96 +{
97 + struct dhcp_netid *id = NULL;
98 +
99 + while (is_tag_prefix(*arg))
100 + {
101 + char *comma = split(*arg);
102 + id = dhcp_netid_create((*arg)+4, id);
103 + *arg = comma;
104 + };
105 + if (!*arg)
106 + {
107 + dhcp_netid_free(id);
108 + id = NULL;
109 + }
110 + return id;
111 +}
112 +
113 +static void dhcp_netid_list_free(struct dhcp_netid_list *netid)
114 +{
115 + while (netid)
116 + {
117 + struct dhcp_netid_list *tmplist = netid;
118 + netid = netid->next;
119 + dhcp_netid_free(tmplist->list);
120 + free(tmplist);
121 + }
122 +}
123 +
124 +static void dhcp_config_free(struct dhcp_config *config)
125 +{
126 + if (config)
127 + {
128 + struct hwaddr_config *hwaddr = config->hwaddr;
129 + while (hwaddr)
130 + {
131 + struct hwaddr_config *tmp = hwaddr;
132 + hwaddr = hwaddr->next;
133 + free(tmp);
134 + }
135 + dhcp_netid_list_free(config->netid);
136 + if (config->flags & CONFIG_CLID)
137 + free(config->clid);
138 + free(config);
139 + }
140 +}
141 +
142 +static void dhcp_context_free(struct dhcp_context *ctx)
143 +{
144 + if (ctx)
145 + {
146 + dhcp_netid_free(ctx->filter);
147 + free(ctx->netid.net);
148 + free(ctx->template_interface);
149 + free(ctx);
150 + }
151 +}
152 +
153 +static void dhcp_opt_free(struct dhcp_opt *opt)
154 +{
155 + if (opt->flags & DHOPT_VENDOR)
156 + free(opt->u.vendor_class);
157 + dhcp_netid_free(opt->netid);
158 + free(opt->val);
159 + free(opt);
160 +}
161 +
162 +
163 /* This is too insanely large to keep in-line in the switch */
164 static int parse_dhcp_opt(char *errstr, char *arg, int flags)
165 {
166 @@ -965,7 +1061,6 @@ static int parse_dhcp_opt(char *errstr,
167 char lenchar = 0, *cp;
168 int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
169 char *comma = NULL;
170 - struct dhcp_netid *np = NULL;
171 u16 opt_len = 0;
172 int is6 = 0;
173 int option_ok = 0;
174 @@ -1052,14 +1147,9 @@ static int parse_dhcp_opt(char *errstr,
175 }
176 else
177 {
178 - new->netid = opt_malloc(sizeof (struct dhcp_netid));
179 /* allow optional "net:" or "tag:" for consistency */
180 - if (is_tag_prefix(arg))
181 - new->netid->net = opt_string_alloc(arg+4);
182 - else
183 - new->netid->net = opt_string_alloc(set_prefix(arg));
184 - new->netid->next = np;
185 - np = new->netid;
186 + const char *name = (is_tag_prefix(arg)) ? arg+4 : set_prefix(arg);
187 + new->netid = dhcp_netid_create(name, new->netid);
188 }
189
190 arg = comma;
191 @@ -1069,7 +1159,7 @@ static int parse_dhcp_opt(char *errstr,
192 if (is6)
193 {
194 if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
195 - ret_err(_("unsupported encapsulation for IPv6 option"));
196 + goto_err(_("unsupported encapsulation for IPv6 option"));
197
198 if (opt_len == 0 &&
199 !(new->flags & DHOPT_RFC3925))
200 @@ -1083,7 +1173,7 @@ static int parse_dhcp_opt(char *errstr,
201
202 /* option may be missing with rfc3925 match */
203 if (!option_ok)
204 - ret_err(_("bad dhcp-option"));
205 + goto_err(_("bad dhcp-option"));
206
207 if (comma)
208 {
209 @@ -1151,10 +1241,10 @@ static int parse_dhcp_opt(char *errstr,
210 is_string = is_dec = is_hex = 0;
211
212 if (!is6 && (!is_addr || dots == 0))
213 - ret_err(_("bad IP address"));
214 + goto_err(_("bad IP address"));
215
216 if (is6 && !is_addr6)
217 - ret_err(_("bad IPv6 address"));
218 + goto_err(_("bad IPv6 address"));
219 }
220 /* or names */
221 else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
222 @@ -1247,7 +1337,7 @@ static int parse_dhcp_opt(char *errstr,
223 comma = split(cp);
224 slash = split_chr(cp, '/');
225 if (!inet_pton(AF_INET, cp, &in))
226 - ret_err(_("bad IPv4 address"));
227 + goto_err(_("bad IPv4 address"));
228 if (!slash)
229 {
230 memcpy(op, &in, INADDRSZ);
231 @@ -1292,8 +1382,8 @@ static int parse_dhcp_opt(char *errstr,
232 op += IN6ADDRSZ;
233 continue;
234 }
235 -
236 - ret_err(_("bad IPv6 address"));
237 +
238 + goto_err(_("bad IPv6 address"));
239 }
240 new->len = op - new->val;
241 }
242 @@ -1320,7 +1410,7 @@ static int parse_dhcp_opt(char *errstr,
243 if (strcmp (arg, ".") != 0)
244 {
245 if (!(dom = canonicalise_opt(arg)))
246 - ret_err(_("bad domain in dhcp-option"));
247 + goto_err(_("bad domain in dhcp-option"));
248
249 domlen = strlen(dom) + 2;
250 }
251 @@ -1414,7 +1504,7 @@ static int parse_dhcp_opt(char *errstr,
252 {
253 char *dom = canonicalise_opt(arg);
254 if (!dom)
255 - ret_err(_("bad domain in dhcp-option"));
256 + goto_err(_("bad domain in dhcp-option"));
257
258 newp = opt_malloc(len + strlen(dom) + 2);
259
260 @@ -1452,14 +1542,14 @@ static int parse_dhcp_opt(char *errstr,
261 ((new->len > 255) ||
262 (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
263 (new->len > 250 && (new->flags & DHOPT_RFC3925))))
264 - ret_err(_("dhcp-option too long"));
265 + goto_err(_("dhcp-option too long"));
266
267 if (flags == DHOPT_MATCH)
268 {
269 if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
270 !new->netid ||
271 new->netid->next)
272 - ret_err(_("illegal dhcp-match"));
273 + goto_err(_("illegal dhcp-match"));
274
275 if (is6)
276 {
277 @@ -1484,6 +1574,9 @@ static int parse_dhcp_opt(char *errstr,
278 }
279
280 return 1;
281 +on_error:
282 + dhcp_opt_free(new);
283 + return 0;
284 }
285
286 #endif
287 @@ -1498,6 +1591,16 @@ void reset_option_bool(unsigned int opt)
288 option_var(opt) &= ~(option_val(opt));
289 }
290
291 +static void server_list_free(struct server *list)
292 +{
293 + while (list)
294 + {
295 + struct server *tmp = list;
296 + list = list->next;
297 + free(tmp);
298 + }
299 +}
300 +
301 static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only)
302 {
303 int i;
304 @@ -1679,13 +1782,13 @@ static int one_opt(int option, char *arg
305 /* has subnet+len */
306 err = parse_mysockaddr(arg, &new->addr);
307 if (err)
308 - ret_err(err);
309 + ret_err_free(err, new);
310 if (!atoi_check(end, &new->mask))
311 - ret_err(gen_err);
312 + ret_err_free(gen_err, new);
313 new->addr_used = 1;
314 }
315 else if (!atoi_check(arg, &new->mask))
316 - ret_err(gen_err);
317 + ret_err_free(gen_err, new);
318
319 daemon->add_subnet4 = new;
320
321 @@ -1697,15 +1800,15 @@ static int one_opt(int option, char *arg
322 /* has subnet+len */
323 err = parse_mysockaddr(comma, &new->addr);
324 if (err)
325 - ret_err(err);
326 + ret_err_free(err, new);
327 if (!atoi_check(end, &new->mask))
328 - ret_err(gen_err);
329 + ret_err_free(gen_err, new);
330 new->addr_used = 1;
331 }
332 else
333 {
334 if (!atoi_check(comma, &new->mask))
335 - ret_err(gen_err);
336 + ret_err_free(gen_err, new);
337 }
338
339 daemon->add_subnet6 = new;
340 @@ -1912,7 +2015,10 @@ static int one_opt(int option, char *arg
341 else if (strcmp(fam, "6") == 0)
342 new->addr.sa.sa_family = AF_INET6;
343 else
344 - ret_err(gen_err);
345 + {
346 + free(new->name);
347 + ret_err_free(gen_err, new);
348 + }
349 }
350 }
351 new->next = daemon->authinterface;
352 @@ -2077,7 +2183,7 @@ static int one_opt(int option, char *arg
353
354 arg = split(netpart);
355 if (!atoi_check(netpart, &msize))
356 - ret_err(gen_err);
357 + ret_err_free(gen_err, new);
358 else if (inet_pton(AF_INET, comma, &new->start))
359 {
360 int mask = (1 << (32 - msize)) - 1;
361 @@ -2090,18 +2196,18 @@ static int one_opt(int option, char *arg
362 {
363 if (!(new->prefix = canonicalise_opt(arg)) ||
364 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
365 - ret_err(_("bad prefix"));
366 + ret_err_free(_("bad prefix"), new);
367 }
368 else if (strcmp(arg, "local") != 0 ||
369 (msize != 8 && msize != 16 && msize != 24))
370 - ret_err(gen_err);
371 + ret_err_free(gen_err, new);
372 else
373 {
374 /* generate the equivalent of
375 local=/xxx.yyy.zzz.in-addr.arpa/ */
376 struct server *serv = add_rev4(new->start, msize);
377 if (!serv)
378 - ret_err(_("bad prefix"));
379 + ret_err_free(_("bad prefix"), new);
380
381 serv->flags |= SERV_NO_ADDR;
382
383 @@ -2130,17 +2236,17 @@ static int one_opt(int option, char *arg
384 setaddr6part(&new->end6, addrpart | mask);
385
386 if (msize < 64)
387 - ret_err(gen_err);
388 + ret_err_free(gen_err, new);
389 else if (arg)
390 {
391 if (option != 's')
392 {
393 if (!(new->prefix = canonicalise_opt(arg)) ||
394 strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
395 - ret_err(_("bad prefix"));
396 + ret_err_free(_("bad prefix"), new);
397 }
398 else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
399 - ret_err(gen_err);
400 + ret_err_free(gen_err, new);
401 else
402 {
403 /* generate the equivalent of
404 @@ -2159,7 +2265,7 @@ static int one_opt(int option, char *arg
405 }
406 }
407 else
408 - ret_err(gen_err);
409 + ret_err_free(gen_err, new);
410 }
411 else
412 {
413 @@ -2173,7 +2279,7 @@ static int one_opt(int option, char *arg
414 if (!arg)
415 new->end.s_addr = new->start.s_addr;
416 else if (!inet_pton(AF_INET, arg, &new->end))
417 - ret_err(gen_err);
418 + ret_err_free(gen_err, new);
419 }
420 else if (inet_pton(AF_INET6, comma, &new->start6))
421 {
422 @@ -2181,16 +2287,16 @@ static int one_opt(int option, char *arg
423 if (!arg)
424 memcpy(&new->end6, &new->start6, IN6ADDRSZ);
425 else if (!inet_pton(AF_INET6, arg, &new->end6))
426 - ret_err(gen_err);
427 + ret_err_free(gen_err, new);
428 }
429 else
430 - ret_err(gen_err);
431 + ret_err_free(gen_err, new);
432
433 if (option != 's' && prefstr)
434 {
435 if (!(new->prefix = canonicalise_opt(prefstr)) ||
436 strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
437 - ret_err(_("bad prefix"));
438 + ret_err_free(_("bad prefix"), new);
439 }
440 }
441
442 @@ -2352,7 +2458,7 @@ static int one_opt(int option, char *arg
443 #endif
444 }
445 else
446 - ret_err(gen_err);
447 + ret_err_free(gen_err, new);
448
449 new->used = 0;
450 if (option == 'a')
451 @@ -2423,7 +2529,10 @@ static int one_opt(int option, char *arg
452 {
453 newlist->flags |= SERV_LITERAL_ADDRESS;
454 if (!(newlist->flags & SERV_TYPE))
455 - ret_err(gen_err);
456 + {
457 + server_list_free(newlist);
458 + ret_err(gen_err);
459 + }
460 }
461 else if (option == LOPT_NO_REBIND)
462 newlist->flags |= SERV_NO_REBIND;
463 @@ -2440,7 +2549,10 @@ static int one_opt(int option, char *arg
464 {
465 char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
466 if (err)
467 - ret_err(err);
468 + {
469 + server_list_free(newlist);
470 + ret_err(err);
471 + }
472 }
473
474 serv = newlist;
475 @@ -2776,21 +2888,19 @@ static int one_opt(int option, char *arg
476 {
477 if (is_tag_prefix(arg))
478 {
479 - struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
480 - tt->net = opt_string_alloc(arg+4);
481 - tt->next = new->filter;
482 /* ignore empty tag */
483 - if (tt->net)
484 - new->filter = tt;
485 + if (arg[4])
486 + new->filter = dhcp_netid_create(arg+4, new->filter);
487 }
488 else
489 {
490 if (new->netid.net)
491 - ret_err(_("only one tag allowed"));
492 - else if (strstr(arg, "set:") == arg)
493 - new->netid.net = opt_string_alloc(arg+4);
494 + {
495 + dhcp_context_free(new);
496 + ret_err(_("only one tag allowed"));
497 + }
498 else
499 - new->netid.net = opt_string_alloc(arg);
500 + new->netid.net = opt_string_alloc(set_prefix(arg));
501 }
502 arg = comma;
503 }
504 @@ -2806,7 +2916,10 @@ static int one_opt(int option, char *arg
505 break;
506
507 if (k < 2)
508 - ret_err(_("bad dhcp-range"));
509 + {
510 + dhcp_context_free(new);
511 + ret_err(_("bad dhcp-range"));
512 + }
513
514 if (inet_pton(AF_INET, a[0], &new->start))
515 {
516 @@ -2818,7 +2931,10 @@ static int one_opt(int option, char *arg
517 else if (strcmp(a[1], "proxy") == 0)
518 new->flags |= CONTEXT_PROXY;
519 else if (!inet_pton(AF_INET, a[1], &new->end))
520 - ret_err(_("bad dhcp-range"));
521 + {
522 + dhcp_context_free(new);
523 + ret_err(_("bad dhcp-range"));
524 + }
525
526 if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
527 {
528 @@ -2833,7 +2949,10 @@ static int one_opt(int option, char *arg
529 new->flags |= CONTEXT_NETMASK;
530 leasepos = 3;
531 if (!is_same_net(new->start, new->end, new->netmask))
532 - ret_err(_("inconsistent DHCP range"));
533 + {
534 + dhcp_context_free(new);
535 + ret_err(_("inconsistent DHCP range"));
536 + }
537
538
539 if (k >= 4 && strchr(a[3], '.') &&
540 @@ -2847,6 +2966,8 @@ static int one_opt(int option, char *arg
541 #ifdef HAVE_DHCP6
542 else if (inet_pton(AF_INET6, a[0], &new->start6))
543 {
544 + const char *err = NULL;
545 +
546 new->flags |= CONTEXT_V6;
547 new->prefix = 64; /* default */
548 new->end6 = new->start6;
549 @@ -2892,19 +3013,24 @@ static int one_opt(int option, char *arg
550 }
551 }
552
553 - if (new->prefix != 64)
554 + if (new->prefix > 64)
555 {
556 if (new->flags & CONTEXT_RA)
557 - ret_err(_("prefix length must be exactly 64 for RA subnets"));
558 + err=(_("prefix length must be exactly 64 for RA subnets"));
559 else if (new->flags & CONTEXT_TEMPLATE)
560 - ret_err(_("prefix length must be exactly 64 for subnet constructors"));
561 + err=(_("prefix length must be exactly 64 for subnet constructors"));
562 }
563 -
564 - if (new->prefix < 64)
565 - ret_err(_("prefix length must be at least 64"));
566 + else if (new->prefix < 64)
567 + err=(_("prefix length must be at least 64"));
568
569 - if (!is_same_net6(&new->start6, &new->end6, new->prefix))
570 - ret_err(_("inconsistent DHCPv6 range"));
571 + if (!err && !is_same_net6(&new->start6, &new->end6, new->prefix))
572 + err=(_("inconsistent DHCPv6 range"));
573 +
574 + if (err)
575 + {
576 + dhcp_context_free(new);
577 + ret_err(err);
578 + }
579
580 /* dhcp-range=:: enables DHCP stateless on any interface */
581 if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
582 @@ -2915,7 +3041,10 @@ static int one_opt(int option, char *arg
583 struct in6_addr zero;
584 memset(&zero, 0, sizeof(zero));
585 if (!is_same_net6(&zero, &new->start6, new->prefix))
586 - ret_err(_("prefix must be zero with \"constructor:\" argument"));
587 + {
588 + dhcp_context_free(new);
589 + ret_err(_("prefix must be zero with \"constructor:\" argument"));
590 + }
591 }
592
593 if (addr6part(&new->start6) > addr6part(&new->end6))
594 @@ -2927,12 +3056,18 @@ static int one_opt(int option, char *arg
595 }
596 #endif
597 else
598 - ret_err(_("bad dhcp-range"));
599 + {
600 + dhcp_context_free(new);
601 + ret_err(_("bad dhcp-range"));
602 + }
603
604 if (leasepos < k)
605 {
606 if (leasepos != k-1)
607 - ret_err(_("bad dhcp-range"));
608 + {
609 + dhcp_context_free(new);
610 + ret_err(_("bad dhcp-range"));
611 + }
612
613 if (strcmp(a[leasepos], "infinite") == 0)
614 new->lease_time = 0xffffffff;
615 @@ -2971,7 +3106,7 @@ static int one_opt(int option, char *arg
616 break;
617
618 if (*cp || (leasepos+1 < k))
619 - ret_err(_("bad dhcp-range"));
620 + ret_err_free(_("bad dhcp-range"), new);
621
622 new->lease_time = atoi(a[leasepos]) * fac;
623 /* Leases of a minute or less confuse
624 @@ -2998,6 +3133,7 @@ static int one_opt(int option, char *arg
625 new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
626 new->hwaddr = NULL;
627 new->netid = NULL;
628 + new->clid = NULL;
629
630 if ((a[0] = arg))
631 for (k = 1; k < 7; k++)
632 @@ -3028,7 +3164,10 @@ static int one_opt(int option, char *arg
633 }
634
635 if (len == -1)
636 - ret_err(_("bad hex constant"));
637 + {
638 + dhcp_config_free(new);
639 + ret_err(_("bad hex constant"));
640 + }
641 else if ((new->clid = opt_malloc(len)))
642 {
643 new->flags |= CONFIG_CLID;
644 @@ -3040,17 +3179,17 @@ static int one_opt(int option, char *arg
645 /* dhcp-host has strange backwards-compat needs. */
646 else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
647 {
648 - struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
649 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
650 - newtag->net = opt_malloc(strlen(arg + 4) + 1);
651 newlist->next = new->netid;
652 new->netid = newlist;
653 - newlist->list = newtag;
654 - strcpy(newtag->net, arg+4);
655 - unhide_metas(newtag->net);
656 + newlist->list = dhcp_netid_create(arg+4, NULL);
657 }
658 else if (strstr(arg, "tag:") == arg)
659 - ret_err(_("cannot match tags in --dhcp-host"));
660 + {
661 +
662 + dhcp_config_free(new);
663 + ret_err(_("cannot match tags in --dhcp-host"));
664 + }
665 #ifdef HAVE_DHCP6
666 else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
667 {
668 @@ -3058,7 +3197,10 @@ static int one_opt(int option, char *arg
669 arg++;
670
671 if (!inet_pton(AF_INET6, arg, &new->addr6))
672 - ret_err(_("bad IPv6 address"));
673 + {
674 + dhcp_config_free(new);
675 + ret_err(_("bad IPv6 address"));
676 + }
677
678 for (i= 0; i < 8; i++)
679 if (new->addr6.s6_addr[i] != 0)
680 @@ -3076,10 +3218,13 @@ static int one_opt(int option, char *arg
681 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
682 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
683 &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
684 - ret_err(_("bad hex constant"));
685 + {
686 + free(newhw);
687 + dhcp_config_free(new);
688 + ret_err(_("bad hex constant"));
689 + }
690 else
691 {
692 -
693 newhw->next = new->hwaddr;
694 new->hwaddr = newhw;
695 }
696 @@ -3156,7 +3301,10 @@ static int one_opt(int option, char *arg
697 {
698 if (!(new->hostname = canonicalise_opt(a[j])) ||
699 !legal_hostname(new->hostname))
700 - ret_err(_("bad DHCP host name"));
701 + {
702 + dhcp_config_free(new);
703 + ret_err(_("bad DHCP host name"));
704 + }
705
706 new->flags |= CONFIG_NAME;
707 new->domain = strip_hostname(new->hostname);
708 @@ -3209,10 +3357,7 @@ static int one_opt(int option, char *arg
709 }
710 else
711 {
712 - struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
713 - newtag->net = opt_malloc(len - 3);
714 - strcpy(newtag->net, arg+4);
715 - unhide_metas(newtag->net);
716 + struct dhcp_netid *newtag = dhcp_netid_create(arg+4, NULL);
717
718 if (strstr(arg, "set:") == arg)
719 {
720 @@ -3229,7 +3374,7 @@ static int one_opt(int option, char *arg
721 else
722 {
723 new->set = NULL;
724 - free(newtag);
725 + dhcp_netid_free(newtag);
726 break;
727 }
728 }
729 @@ -3238,7 +3383,11 @@ static int one_opt(int option, char *arg
730 }
731
732 if (!new->set)
733 - ret_err(_("bad tag-if"));
734 + {
735 + dhcp_netid_free(new->tag);
736 + dhcp_netid_list_free(new->set);
737 + ret_err_free(_("bad tag-if"), new);
738 + }
739
740 break;
741 }
742 @@ -3281,19 +3430,12 @@ static int one_opt(int option, char *arg
743
744 case 'M': /* --dhcp-boot */
745 {
746 - struct dhcp_netid *id = NULL;
747 - while (is_tag_prefix(arg))
748 - {
749 - struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
750 - newid->next = id;
751 - id = newid;
752 - comma = split(arg);
753 - newid->net = opt_string_alloc(arg+4);
754 - arg = comma;
755 - };
756 + struct dhcp_netid *id = dhcp_tags(&arg);
757
758 - if (!arg)
759 - ret_err(gen_err);
760 + if (!id)
761 + {
762 + ret_err(gen_err);
763 + }
764 else
765 {
766 char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
767 @@ -3339,19 +3481,12 @@ static int one_opt(int option, char *arg
768
769 case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */
770 {
771 - struct dhcp_netid *id = NULL;
772 - while (is_tag_prefix(arg))
773 - {
774 - struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
775 - newid->next = id;
776 - id = newid;
777 - comma = split(arg);
778 - newid->net = opt_string_alloc(arg+4);
779 - arg = comma;
780 - };
781 + struct dhcp_netid *id = dhcp_tags(&arg);
782
783 - if (!arg)
784 - ret_err(gen_err);
785 + if (!id)
786 + {
787 + ret_err(gen_err);
788 + }
789 else
790 {
791 struct delay_config *new;
792 @@ -3376,19 +3511,13 @@ static int one_opt(int option, char *arg
793
794 new->netid = NULL;
795 new->opt = 10; /* PXE_MENU_PROMPT */
796 -
797 - while (is_tag_prefix(arg))
798 - {
799 - struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
800 - comma = split(arg);
801 - nn->next = new->netid;
802 - new->netid = nn;
803 - nn->net = opt_string_alloc(arg+4);
804 - arg = comma;
805 - }
806 + new->netid = dhcp_tags(&arg);
807
808 - if (!arg)
809 - ret_err(gen_err);
810 + if (!new->netid)
811 + {
812 + dhcp_opt_free(new);
813 + ret_err(gen_err);
814 + }
815 else
816 {
817 comma = split(arg);
818 @@ -3424,17 +3553,8 @@ static int one_opt(int option, char *arg
819 new->netid = NULL;
820 new->sname = NULL;
821 new->server.s_addr = 0;
822 + new->netid = dhcp_tags(&arg);
823
824 - while (is_tag_prefix(arg))
825 - {
826 - struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
827 - comma = split(arg);
828 - nn->next = new->netid;
829 - new->netid = nn;
830 - nn->net = opt_string_alloc(arg+4);
831 - arg = comma;
832 - }
833 -
834 if (arg && (comma = split(arg)))
835 {
836 for (i = 0; CSA[i]; i++)
837 @@ -3511,7 +3631,10 @@ static int one_opt(int option, char *arg
838 unhide_metas(comma);
839 new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
840 if (new->hwaddr_len == -1)
841 - ret_err(gen_err);
842 + {
843 + free(new->netid.net);
844 + ret_err_free(gen_err, new);
845 + }
846 else
847 {
848 new->next = daemon->dhcp_macs;
849 @@ -3528,7 +3651,7 @@ static int one_opt(int option, char *arg
850
851 if (!(comma = split(arg)) ||
852 !atoi_check16(comma, &new->class))
853 - ret_err(gen_err);
854 + ret_err_free(gen_err, new);
855
856 new->tag.net = opt_string_alloc(set_prefix(arg));
857 new->next = daemon->prefix_classes;
858 @@ -3550,7 +3673,7 @@ static int one_opt(int option, char *arg
859 struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
860
861 if (!(comma = split(arg)))
862 - ret_err(gen_err);
863 + ret_err_free(gen_err, new);
864
865 new->netid.net = opt_string_alloc(set_prefix(arg));
866 /* check for hex string - must digits may include : must not have nothing else,
867 @@ -3560,7 +3683,10 @@ static int one_opt(int option, char *arg
868 if ((comma = split(arg)))
869 {
870 if (option != 'U' || strstr(arg, "enterprise:") != arg)
871 - ret_err(gen_err);
872 + {
873 + free(new->netid.net);
874 + ret_err_free(gen_err, new);
875 + }
876 else
877 new->enterprise = atoi(arg+11);
878 }
879 @@ -3662,14 +3788,8 @@ static int one_opt(int option, char *arg
880 }
881
882 while (arg) {
883 - struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
884 comma = split(arg);
885 - member->next = list;
886 - list = member;
887 - if (is_tag_prefix(arg))
888 - member->net = opt_string_alloc(arg+4);
889 - else
890 - member->net = opt_string_alloc(arg);
891 + list = dhcp_netid_create(is_tag_prefix(arg) ? arg+4 :arg, list);
892 arg = comma;
893 }
894
895 @@ -3683,7 +3803,7 @@ static int one_opt(int option, char *arg
896 struct addr_list *new = opt_malloc(sizeof(struct addr_list));
897 comma = split(arg);
898 if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
899 - ret_err(_("bad dhcp-proxy address"));
900 + ret_err_free(_("bad dhcp-proxy address"), new);
901 new->next = daemon->override_relays;
902 daemon->override_relays = new;
903 arg = comma;
904 @@ -3709,7 +3829,10 @@ static int one_opt(int option, char *arg
905 }
906 #endif
907 else
908 - ret_err(_("Bad dhcp-relay"));
909 + {
910 + free(new->interface);
911 + ret_err_free(_("Bad dhcp-relay"), new);
912 + }
913
914 break;
915 }
916 @@ -3749,8 +3872,11 @@ static int one_opt(int option, char *arg
917 arg = split(comma);
918 if (!atoi_check(comma, &new->interval) ||
919 (arg && !atoi_check(arg, &new->lifetime)))
920 + {
921 err:
922 - ret_err(_("bad RA-params"));
923 + free(new->name);
924 + ret_err_free(_("bad RA-params"), new);
925 + }
926
927 new->next = daemon->ra_interfaces;
928 daemon->ra_interfaces = new;
929 @@ -3799,7 +3925,7 @@ err:
930 (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
931 !is_same_net(new->in, new->end, new->mask) ||
932 ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
933 - ret_err(_("invalid alias range"));
934 + ret_err_free(_("invalid alias range"), new);
935
936 break;
937 }
938 @@ -3832,7 +3958,7 @@ err:
939 else if (strcmp(arg, "6") == 0)
940 new->family = AF_INET6;
941 else
942 - ret_err(gen_err);
943 + ret_err_free(gen_err, new);
944 }
945 new->intr = opt_string_alloc(comma);
946 break;
947 @@ -3864,11 +3990,19 @@ err:
948 alias = canonicalise_opt(arg);
949
950 if (!alias || !target)
951 - ret_err(_("bad CNAME"));
952 + {
953 + free(target);
954 + free(alias);
955 + ret_err(_("bad CNAME"));
956 + }
957
958 for (new = daemon->cnames; new; new = new->next)
959 if (hostname_isequal(new->alias, alias))
960 - ret_err(_("duplicate CNAME"));
961 + {
962 + free(target);
963 + free(alias);
964 + ret_err(_("duplicate CNAME"));
965 + }
966 new = opt_malloc(sizeof(struct cname));
967 new->next = daemon->cnames;
968 daemon->cnames = new;
969 @@ -3891,7 +4025,11 @@ err:
970
971 if (!(dom = canonicalise_opt(arg)) ||
972 (comma && !(target = canonicalise_opt(comma))))
973 - ret_err(_("bad PTR record"));
974 + {
975 + free(dom);
976 + free(target);
977 + ret_err(_("bad PTR record"));
978 + }
979 else
980 {
981 new = opt_malloc(sizeof(struct ptr_record));
982 @@ -3909,7 +4047,7 @@ err:
983 int k = 0;
984 struct naptr *new;
985 int order, pref;
986 - char *name, *replace = NULL;
987 + char *name=NULL, *replace = NULL;
988
989 if ((a[0] = arg))
990 for (k = 1; k < 7; k++)
991 @@ -3922,7 +4060,11 @@ err:
992 !atoi_check16(a[1], &order) ||
993 !atoi_check16(a[2], &pref) ||
994 (k == 7 && !(replace = canonicalise_opt(a[6]))))
995 - ret_err(_("bad NAPTR record"));
996 + {
997 + free(name);
998 + free(replace);
999 + ret_err(_("bad NAPTR record"));
1000 + }
1001 else
1002 {
1003 new = opt_malloc(sizeof(struct naptr));
1004 @@ -3944,22 +4086,26 @@ err:
1005 struct txt_record *new;
1006 size_t len = 0;
1007 char *data;
1008 - int val;
1009 + int class;
1010
1011 comma = split(arg);
1012 data = split(comma);
1013
1014 new = opt_malloc(sizeof(struct txt_record));
1015 - new->next = daemon->rr;
1016 - daemon->rr = new;
1017 + new->name = NULL;
1018
1019 - if (!atoi_check(comma, &val) ||
1020 + if (!atoi_check(comma, &class) ||
1021 !(new->name = canonicalise_opt(arg)) ||
1022 (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
1023 - ret_err(_("bad RR record"));
1024 -
1025 - new->class = val;
1026 + {
1027 + free(new->name);
1028 + ret_err_free(_("bad RR record"), new);
1029 + }
1030 +
1031 new->len = 0;
1032 + new->class = class;
1033 + new->next = daemon->rr;
1034 + daemon->rr = new;
1035
1036 if (data)
1037 {
1038 @@ -4011,14 +4157,14 @@ err:
1039 comma = split(arg);
1040
1041 new = opt_malloc(sizeof(struct txt_record));
1042 - new->next = daemon->txt;
1043 - daemon->txt = new;
1044 new->class = C_IN;
1045 new->stat = 0;
1046
1047 if (!(new->name = canonicalise_opt(arg)))
1048 - ret_err(_("bad TXT record"));
1049 + ret_err_free(_("bad TXT record"), new);
1050
1051 + new->next = daemon->txt;
1052 + daemon->txt = new;
1053 len = comma ? strlen(comma) : 0;
1054 len += (len/255) + 1; /* room for extra counts */
1055 new->txt = p = opt_malloc(len);
1056 @@ -4065,24 +4211,32 @@ err:
1057 arg = comma;
1058 comma = split(arg);
1059 if (!(target = canonicalise_opt(arg)))
1060 - ret_err(_("bad SRV target"));
1061 + ret_err_free(_("bad SRV target"), name);
1062
1063 if (comma)
1064 {
1065 arg = comma;
1066 comma = split(arg);
1067 if (!atoi_check16(arg, &port))
1068 - ret_err(_("invalid port number"));
1069 + {
1070 + free(name);
1071 + ret_err_free(_("invalid port number"), target);
1072 + }
1073
1074 if (comma)
1075 {
1076 arg = comma;
1077 comma = split(arg);
1078 if (!atoi_check16(arg, &priority))
1079 - ret_err(_("invalid priority"));
1080 -
1081 + {
1082 + free(name);
1083 + ret_err_free(_("invalid priority"), target);
1084 + }
1085 if (comma && !atoi_check16(comma, &weight))
1086 - ret_err(_("invalid weight"));
1087 + {
1088 + free(name);
1089 + ret_err_free(_("invalid weight"), target);
1090 + }
1091 }
1092 }
1093 }
1094 @@ -4101,13 +4255,15 @@ err:
1095
1096 case LOPT_HOST_REC: /* --host-record */
1097 {
1098 - struct host_record *new = opt_malloc(sizeof(struct host_record));
1099 - memset(new, 0, sizeof(struct host_record));
1100 - new->ttl = -1;
1101 + struct host_record *new;
1102
1103 if (!arg || !(comma = split(arg)))
1104 ret_err(_("Bad host-record"));
1105
1106 + new = opt_malloc(sizeof(struct host_record));
1107 + memset(new, 0, sizeof(struct host_record));
1108 + new->ttl = -1;
1109 +
1110 while (arg)
1111 {
1112 struct all_addr addr;
1113 @@ -4126,10 +4282,19 @@ err:
1114 {
1115 int nomem;
1116 char *canon = canonicalise(arg, &nomem);
1117 - struct name_list *nl = opt_malloc(sizeof(struct name_list));
1118 + struct name_list *nl;
1119 if (!canon)
1120 - ret_err(_("Bad name in host-record"));
1121 + {
1122 + struct name_list *tmp = new->names, *next;
1123 + for (tmp = new->names; tmp; tmp = next)
1124 + {
1125 + next = tmp->next;
1126 + free(tmp);
1127 + }
1128 + ret_err_free(_("Bad name in host-record"), new);
1129 + }
1130
1131 + nl = opt_malloc(sizeof(struct name_list));
1132 nl->name = canon;
1133 /* keep order, so that PTR record goes to first name */
1134 nl->next = NULL;
1135 @@ -4179,6 +4344,7 @@ err:
1136 int len;
1137
1138 new->class = C_IN;
1139 + new->name = NULL;
1140
1141 if ((comma = split(arg)) && (algo = split(comma)))
1142 {
1143 @@ -4203,7 +4369,7 @@ err:
1144 !atoi_check8(algo, &new->algo) ||
1145 !atoi_check8(digest, &new->digest_type) ||
1146 !(new->name = canonicalise_opt(arg)))
1147 - ret_err(_("bad trust anchor"));
1148 + ret_err_free(_("bad trust anchor"), new);
1149
1150 /* Upper bound on length */
1151 len = (2*strlen(keyhex))+1;
1152 @@ -4217,7 +4383,10 @@ err:
1153 else
1154 cp++;
1155 if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1)
1156 - ret_err(_("bad HEX in trust anchor"));
1157 + {
1158 + free(new->name);
1159 + ret_err_free(_("bad HEX in trust anchor"), new);
1160 + }
1161
1162 new->next = daemon->ds;
1163 daemon->ds = new;
1164 @@ -4686,8 +4855,8 @@ void read_opts(int argc, char **argv, ch
1165 size_t argbuf_size = MAXDNAME;
1166 char *argbuf = opt_malloc(argbuf_size);
1167 char *buff = opt_malloc(MAXDNAME);
1168 - int option, conffile_opt = '7', testmode = 0;
1169 - char *arg, *conffile = CONFFILE;
1170 + int option, testmode = 0;
1171 + char *arg, *conffile = NULL;
1172
1173 opterr = 0;
1174
1175 @@ -4796,7 +4965,8 @@ void read_opts(int argc, char **argv, ch
1176 }
1177 else if (option == 'C')
1178 {
1179 - conffile_opt = 0; /* file must exist */
1180 + if (conffile)
1181 + free(conffile);
1182 conffile = opt_string_alloc(arg);
1183 }
1184 else
1185 @@ -4814,10 +4984,11 @@ void read_opts(int argc, char **argv, ch
1186
1187 if (conffile)
1188 {
1189 - one_file(conffile, conffile_opt);
1190 - if (conffile_opt == 0)
1191 - free(conffile);
1192 + one_file(conffile, 0);
1193 + free(conffile);
1194 }
1195 + else
1196 + one_file(CONFFILE, '7');
1197
1198 /* port might not be known when the address is parsed - fill in here */
1199 if (daemon->servers)