diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2020-05-14 13:57:14 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2020-05-14 13:57:14 +0000 |
commit | 0c700953f06ebf1d9769f8861cdaba7541906bf2 (patch) | |
tree | 95dc344ecf76752df35e8717e71acff7e7165c7c | |
parent | b857c663aeebfdf6245335135509ac3cbc5a0586 (diff) |
Massage merge_option_data() to be more careful when dealing with 'D'
(domain search) and 't' (text) options. Enables append/prepend for the
domain-search option by inserting blanks between the domains and
ensures the presence of a terminating NUL when merging text.
-rw-r--r-- | sbin/dhclient/dhclient.c | 17 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 4 | ||||
-rw-r--r-- | sbin/dhclient/options.c | 39 |
3 files changed, 43 insertions, 17 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index cb2e5fb5df5..61e02a32b3c 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.667 2020/05/13 20:28:10 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.668 2020/05/14 13:57:13 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -2405,6 +2405,7 @@ apply_defaults(struct client_lease *lease) { struct option_data emptyopt = {0, NULL}; struct client_lease *newlease; + char *fmt; int i; newlease = clone_lease(lease); @@ -2425,31 +2426,31 @@ apply_defaults(struct client_lease *lease) newlease->next_server.s_addr = config->next_server.s_addr; for (i = 0; i < DHO_COUNT; i++) { + fmt = code_to_format(i); switch (config->default_actions[i]) { case ACTION_IGNORE: - free(newlease->options[i].data); - newlease->options[i].data = NULL; - newlease->options[i].len = 0; + merge_option_data(fmt, &emptyopt, &emptyopt, + &newlease->options[i]); break; case ACTION_SUPERSEDE: - merge_option_data(&config->defaults[i], &emptyopt, + merge_option_data(fmt, &config->defaults[i], &emptyopt, &newlease->options[i]); break; case ACTION_PREPEND: - merge_option_data(&config->defaults[i], + merge_option_data(fmt, &config->defaults[i], &lease->options[i], &newlease->options[i]); break; case ACTION_APPEND: - merge_option_data(&lease->options[i], + merge_option_data(fmt, &lease->options[i], &config->defaults[i], &newlease->options[i]); break; case ACTION_DEFAULT: if (newlease->options[i].len == 0) - merge_option_data(&config->defaults[i], + merge_option_data(fmt, &config->defaults[i], &emptyopt, &newlease->options[i]); break; diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index d98b12de0c3..ceba6388e4f 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.285 2020/01/23 22:39:35 krw Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.286 2020/05/14 13:57:13 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> @@ -167,7 +167,7 @@ char *code_to_name(int); char *code_to_format(int); int code_to_action(int, int); int name_to_code(char *); -void merge_option_data(struct option_data *, +void merge_option_data(char *, struct option_data *, struct option_data *, struct option_data *); /* conflex.c */ diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c index 0a8b3fdb1d9..6dca740ca80 100644 --- a/sbin/dhclient/options.c +++ b/sbin/dhclient/options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options.c,v 1.120 2019/07/03 03:24:01 deraadt Exp $ */ +/* $OpenBSD: options.c,v 1.121 2020/05/14 13:57:13 krw Exp $ */ /* DHCP options parsing and reassembly. */ @@ -963,15 +963,40 @@ unpack_options(struct dhcp_packet *packet) } void -merge_option_data(struct option_data *first, +merge_option_data(char *fmt, struct option_data *first, struct option_data *second, struct option_data *dest) { + int rslt; + free(dest->data); + dest->data = NULL; dest->len = first->len + second->len; - dest->data = calloc(1, dest->len); - if (dest->data == NULL) - fatal("merged option data"); + if (dest->len == 0) + return; - memcpy(dest->data, first->data, first->len); - memcpy(dest->data + first->len, second->data, second->len); + switch (fmt[0]) { + case 'D': + rslt = asprintf((char **)&dest->data, "%s%s%s", + (first->len > 0) ? (char *)first->data : "", + (first->len > 0 && second->len > 0) ? " " : "", + (second->len > 0) ? (char *)second->data : ""); + if (rslt == -1) + fatal("merged 'D'"); + dest->len = strlen(dest->data); + break; + case 't': + rslt = asprintf((char **)&dest->data, "%s%s", + (first->len > 0) ? (char *)first->data : "", + (second->len > 0) ? (char *)second->data : ""); + if (rslt == -1) + fatal("merged 't'"); + break; + default: + dest->data = calloc(1, dest->len); + if (dest->data == NULL) + fatal("merged option data"); + memcpy(dest->data, first->data, first->len); + memcpy(dest->data + first->len, second->data, second->len); + break; + } } |