OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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/32] 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) |