0011-Free-config-file-values-on-parsing-errors.patch 33 KB

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