summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2020-05-14 13:57:14 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2020-05-14 13:57:14 +0000
commit0c700953f06ebf1d9769f8861cdaba7541906bf2 (patch)
tree95dc344ecf76752df35e8717e71acff7e7165c7c
parentb857c663aeebfdf6245335135509ac3cbc5a0586 (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.c17
-rw-r--r--sbin/dhclient/dhcpd.h4
-rw-r--r--sbin/dhclient/options.c39
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;
+ }
}