1687 lines
52 KiB
Diff
1687 lines
52 KiB
Diff
From 8e11d702921e51a5eb00b9ee12925cae69039c22 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
|
Date: Thu, 18 Jul 2019 18:49:30 +0200
|
|
Subject: [PATCH] Fix issues detected by Coverity
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Squashed commit of the following:
|
|
|
|
commit 6a5fa6c9207961a662f8debbe9172500c752e3ac
|
|
Author: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
|
|
Date: Mon Dec 10 10:34:35 2018 +0000
|
|
|
|
build failure on master with NO_DHCPv6 and fix....
|
|
|
|
Hi Simon,
|
|
|
|
master has a build error when building without HAVE_DHCPv6
|
|
|
|
option.c: In function 'dhcp_context_free':
|
|
option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface'
|
|
free(ctx->template_interface);
|
|
|
|
Sadly, need to put in a little conditional compilation ifdef'erey
|
|
|
|
Simplest patch in the world attached
|
|
|
|
Cheers,
|
|
|
|
Kevin D-B
|
|
|
|
012C ACB2 28C6 C53E 9775 9123 B3A2 389B 9DE2 334A
|
|
|
|
From 061eb8599636bb360e0b7fa5986935b86db39497 Mon Sep 17 00:00:00 2001
|
|
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
|
Date: Mon, 10 Dec 2018 10:07:33 +0000
|
|
Subject: [PATCH] option: fix non DHCPv6 build error
|
|
|
|
option.c: In function 'dhcp_context_free':
|
|
option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface'
|
|
free(ctx->template_interface);
|
|
^~
|
|
|
|
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
|
(cherry picked from commit b683cf37f9f3dd3dc5d95d621ee75850d559b2e4)
|
|
|
|
commit a4be120618a5d8517d23e687003cab53e7db11c9
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Sun Dec 16 21:25:29 2018 +0000
|
|
|
|
Fix option parsing errors introduced in 59e470381f84f2fdf0640c7bc67827f3f0c64784
|
|
|
|
Thanks to Kevin Darbyshire-Bryant for spotting this.
|
|
|
|
(cherry picked from commit 137e9f878fafb38369eab7d9dfe84e4228ff5f89)
|
|
|
|
commit 3e0752faa67ffd25893ebbcbe6a5788699a2e1c9
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Fri Nov 2 22:39:39 2018 +0000
|
|
|
|
Free config file values on parsing errors.
|
|
|
|
This time I have a little bit more controversal patches. But I think
|
|
still useful. They fixes memory leaks that might occur in some cases.
|
|
Most dnsmasq errors is fatal, so it does not matter. But some are not.
|
|
Some parts are reloaded on SIGHUP signal, so it might leak more than once.
|
|
|
|
Some example when it changes the failures. Use dhcp-options file with
|
|
this content:
|
|
|
|
tag:error,vendor:redhat
|
|
option:ntp-server,1.2.3.4.5
|
|
option6:ntp-server,[:::]
|
|
|
|
Is not fatal and dnsmasq will start. On each reload command, it would
|
|
leak some memory. I validated it using valgrind --leak-check=full
|
|
dnsmasq -d. This patch fixes it. It introduces something that might be
|
|
considered constructor and destructor of selected structures.
|
|
|
|
(cherry picked from commit 59e470381f84f2fdf0640c7bc67827f3f0c64784)
|
|
|
|
commit c2a44c21dddffff95346c931feda696704ea73ca
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Wed Oct 24 22:30:18 2018 +0100
|
|
|
|
Do not rely on dead code elimination, use array instead.
|
|
Make options bits derived from size and count. Use size of option bits
|
|
and last supported bit in computation. No new change would be required
|
|
when new options are added. Just change OPT_LAST constant.
|
|
|
|
(cherry picked from commit 24b87607c1353e94689e8a2190571ab3f3b36f31)
|
|
|
|
commit 5b9f199a1b16b7aa41cf544e9312c93e893206b3
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Fri Aug 17 10:20:05 2018 +0200
|
|
|
|
Minor improvements in lease-tools
|
|
|
|
Limit max interface name to fit into buffer.
|
|
Make sure pointer have to be always positive.
|
|
Close socket after received reply.
|
|
|
|
(cherry picked from commit 2b38e3823b12ab13f86c3a44648de436daadb1f6)
|
|
|
|
commit d30a8f4c46a1b446b7d9932d022a09f1ee6b4554
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Thu Aug 16 15:48:15 2018 +0200
|
|
|
|
Close socket after received reply
|
|
|
|
commit 6e5dedbb8aa3d27c9477558e66f9d260414340a3
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Wed Aug 15 19:41:07 2018 +0200
|
|
|
|
Mark die function as never returning
|
|
|
|
Improves static analysis output and reduces false positives.
|
|
|
|
commit 3d7e9ba115d3c229d678814103dbf3401738dcf5
|
|
Author: Petr Menšík <pemensik@redhat.com>
|
|
Date: Wed Aug 15 18:17:00 2018 +0200
|
|
|
|
Fix lengths of interface names
|
|
|
|
Use helper function similar to copy correctly limited names into
|
|
buffers.
|
|
---
|
|
contrib/lease-tools/dhcp_lease_time.c | 2 +-
|
|
contrib/lease-tools/dhcp_release.c | 3 +-
|
|
contrib/lease-tools/dhcp_release6.c | 5 +-
|
|
src/bpf.c | 2 +-
|
|
src/dhcp.c | 9 +-
|
|
src/dnsmasq.h | 20 +-
|
|
src/log.c | 2 +-
|
|
src/network.c | 12 +-
|
|
src/option.c | 548 +++++++++++++++++---------
|
|
src/rfc2131.c | 10 +-
|
|
src/tftp.c | 2 +-
|
|
src/util.c | 12 +-
|
|
12 files changed, 408 insertions(+), 219 deletions(-)
|
|
|
|
diff --git a/contrib/lease-tools/dhcp_lease_time.c b/contrib/lease-tools/dhcp_lease_time.c
|
|
index f9d7a85..697d627 100644
|
|
--- a/contrib/lease-tools/dhcp_lease_time.c
|
|
+++ b/contrib/lease-tools/dhcp_lease_time.c
|
|
@@ -83,7 +83,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
|
if (p >= end - 2)
|
|
return NULL; /* malformed packet */
|
|
opt_len = option_len(p);
|
|
- if (p >= end - (2 + opt_len))
|
|
+ if (end - p >= (2 + opt_len))
|
|
return NULL; /* malformed packet */
|
|
if (*p == opt && opt_len >= minsize)
|
|
return p;
|
|
diff --git a/contrib/lease-tools/dhcp_release.c b/contrib/lease-tools/dhcp_release.c
|
|
index 201fcd3..59883d4 100644
|
|
--- a/contrib/lease-tools/dhcp_release.c
|
|
+++ b/contrib/lease-tools/dhcp_release.c
|
|
@@ -270,7 +270,8 @@ int main(int argc, char **argv)
|
|
|
|
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
|
a DHCP server */
|
|
- strcpy(ifr.ifr_name, argv[1]);
|
|
+ strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
|
+ ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
|
{
|
|
perror("cannot setup interface");
|
|
diff --git a/contrib/lease-tools/dhcp_release6.c b/contrib/lease-tools/dhcp_release6.c
|
|
index 7f79fa7..d680222 100644
|
|
--- a/contrib/lease-tools/dhcp_release6.c
|
|
+++ b/contrib/lease-tools/dhcp_release6.c
|
|
@@ -376,9 +376,12 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
+
|
|
+ close(sock);
|
|
return result;
|
|
}
|
|
-
|
|
+
|
|
+ close(sock);
|
|
fprintf(stderr, "Response timed out\n");
|
|
return -1;
|
|
}
|
|
diff --git a/src/bpf.c b/src/bpf.c
|
|
index 49a11bf..ff66d6d 100644
|
|
--- a/src/bpf.c
|
|
+++ b/src/bpf.c
|
|
@@ -169,7 +169,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|
struct in6_ifreq ifr6;
|
|
|
|
memset(&ifr6, 0, sizeof(ifr6));
|
|
- strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
|
+ safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
|
|
|
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
|
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
|
diff --git a/src/dhcp.c b/src/dhcp.c
|
|
index 5a8daec..26f3287 100644
|
|
--- a/src/dhcp.c
|
|
+++ b/src/dhcp.c
|
|
@@ -232,7 +232,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|
|
|
#ifdef HAVE_LINUX_NETWORK
|
|
/* ARP fiddling uses original interface even if we pretend to use a different one. */
|
|
- strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
|
+ safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
|
|
#endif
|
|
|
|
/* If the interface on which the DHCP request was received is an
|
|
@@ -255,7 +255,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|
}
|
|
else
|
|
{
|
|
- strncpy(ifr.ifr_name, bridge->iface, IF_NAMESIZE);
|
|
+ safe_strncpy(ifr.ifr_name, bridge->iface, sizeof(ifr.ifr_name));
|
|
break;
|
|
}
|
|
}
|
|
@@ -279,7 +279,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|
is_relay_reply = 1;
|
|
iov.iov_len = sz;
|
|
#ifdef HAVE_LINUX_NETWORK
|
|
- strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
|
+ safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
|
|
#endif
|
|
}
|
|
else
|
|
@@ -988,8 +988,7 @@ char *host_from_dns(struct in_addr addr)
|
|
if (!legal_hostname(hostname))
|
|
return NULL;
|
|
|
|
- strncpy(daemon->dhcp_buff, hostname, 256);
|
|
- daemon->dhcp_buff[255] = 0;
|
|
+ safe_strncpy(daemon->dhcp_buff, hostname, 256);
|
|
strip_hostname(daemon->dhcp_buff);
|
|
|
|
return daemon->dhcp_buff;
|
|
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
|
index 6773b69..6b18bb7 100644
|
|
--- a/src/dnsmasq.h
|
|
+++ b/src/dnsmasq.h
|
|
@@ -42,6 +42,12 @@
|
|
# define __EXTENSIONS__
|
|
#endif
|
|
|
|
+#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__clang__)
|
|
+#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
|
|
+#else
|
|
+#define ATTRIBUTE_NORETURN
|
|
+#endif
|
|
+
|
|
/* get these before config.h for IPv6 stuff... */
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
@@ -190,9 +196,6 @@ struct event_desc {
|
|
#define EC_MISC 5
|
|
#define EC_INIT_OFFSET 10
|
|
|
|
-/* Trust the compiler dead-code eliminator.... */
|
|
-#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
|
|
-
|
|
#define OPT_BOGUSPRIV 0
|
|
#define OPT_FILTER 1
|
|
#define OPT_LOG 2
|
|
@@ -252,6 +255,12 @@ struct event_desc {
|
|
#define OPT_TFTP_APREF_MAC 56
|
|
#define OPT_LAST 57
|
|
|
|
+#define OPTION_BITS (sizeof(unsigned int)*8)
|
|
+#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
|
+#define option_var(x) (daemon->options[(x) / OPTION_BITS])
|
|
+#define option_val(x) ((1u) << ((x) % OPTION_BITS))
|
|
+#define option_bool(x) (option_var(x) & option_val(x))
|
|
+
|
|
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
|
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
|
#define MS_TFTP LOG_USER
|
|
@@ -947,7 +956,7 @@ extern struct daemon {
|
|
config file arguments. All set (including defaults)
|
|
in option.c */
|
|
|
|
- unsigned int options, options2;
|
|
+ unsigned int options[OPTION_SIZE];
|
|
struct resolvc default_resolv, *resolv_files;
|
|
time_t last_resolv;
|
|
char *servers_file;
|
|
@@ -1205,6 +1214,7 @@ int legal_hostname(char *name);
|
|
char *canonicalise(char *in, int *nomem);
|
|
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
|
void *safe_malloc(size_t size);
|
|
+void safe_strncpy(char *dest, const char *src, size_t size);
|
|
void safe_pipe(int *fd, int read_noblock);
|
|
void *whine_malloc(size_t size);
|
|
int sa_len(union mysockaddr *addr);
|
|
@@ -1233,7 +1243,7 @@ int wildcard_match(const char* wildcard, const char* match);
|
|
int wildcard_matchn(const char* wildcard, const char* match, int num);
|
|
|
|
/* log.c */
|
|
-void die(char *message, char *arg1, int exit_code);
|
|
+void die(char *message, char *arg1, int exit_code) ATTRIBUTE_NORETURN;
|
|
int log_start(struct passwd *ent_pw, int errfd);
|
|
int log_reopen(char *log_file);
|
|
|
|
diff --git a/src/log.c b/src/log.c
|
|
index dae8a75..d0d4780 100644
|
|
--- a/src/log.c
|
|
+++ b/src/log.c
|
|
@@ -232,7 +232,7 @@ static void log_write(void)
|
|
logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1;
|
|
#endif
|
|
logaddr.sun_family = AF_UNIX;
|
|
- strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
|
|
+ safe_strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
|
|
|
|
/* Got connection back? try again. */
|
|
if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1)
|
|
diff --git a/src/network.c b/src/network.c
|
|
index 0381513..efb7b03 100644
|
|
--- a/src/network.c
|
|
+++ b/src/network.c
|
|
@@ -29,7 +29,7 @@ int indextoname(int fd, int index, char *name)
|
|
if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
|
|
return 0;
|
|
|
|
- strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
|
+ safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
|
|
|
return 1;
|
|
}
|
|
@@ -82,12 +82,12 @@ int indextoname(int fd, int index, char *name)
|
|
for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
|
|
{
|
|
struct lifreq lifr;
|
|
- strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
|
|
+ safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
|
|
if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
|
|
return 0;
|
|
|
|
if (lifr.lifr_index == index) {
|
|
- strncpy(name, lifr.lifr_name, IF_NAMESIZE);
|
|
+ safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -188,7 +188,7 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
|
struct ifreq ifr;
|
|
struct irec *iface;
|
|
|
|
- strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
|
+ safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
|
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
|
|
ifr.ifr_flags & IFF_LOOPBACK)
|
|
{
|
|
@@ -1284,7 +1284,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|
return NULL;
|
|
}
|
|
|
|
- strcpy(sfd->interface, intname);
|
|
+ safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
|
|
sfd->source_addr = *addr;
|
|
sfd->next = daemon->sfds;
|
|
sfd->ifindex = ifindex;
|
|
@@ -1452,7 +1452,7 @@ void add_update_server(int flags,
|
|
serv->flags |= SERV_HAS_DOMAIN;
|
|
|
|
if (interface)
|
|
- strcpy(serv->interface, interface);
|
|
+ safe_strncpy(serv->interface, interface, sizeof(serv->interface));
|
|
if (addr)
|
|
serv->addr = *addr;
|
|
if (source_addr)
|
|
diff --git a/src/option.c b/src/option.c
|
|
index d358d99..9768efb 100644
|
|
--- a/src/option.c
|
|
+++ b/src/option.c
|
|
@@ -559,14 +559,15 @@ static void *opt_malloc(size_t size)
|
|
return ret;
|
|
}
|
|
|
|
-static char *opt_string_alloc(char *cp)
|
|
+static char *opt_string_alloc(const char *cp)
|
|
{
|
|
char *ret = NULL;
|
|
+ size_t len;
|
|
|
|
- if (cp && strlen(cp) != 0)
|
|
+ if (cp && (len = strlen(cp)) != 0)
|
|
{
|
|
- ret = opt_malloc(strlen(cp)+1);
|
|
- strcpy(ret, cp);
|
|
+ ret = opt_malloc(len+1);
|
|
+ memcpy(ret, cp, len+1);
|
|
|
|
/* restore hidden metachars */
|
|
unhide_metas(ret);
|
|
@@ -741,6 +742,8 @@ static void do_usage(void)
|
|
}
|
|
|
|
#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
|
|
+#define ret_err_free(x,m) do { strcpy(errstr, (x)); free((m)); return 0; } while (0)
|
|
+#define goto_err(x) do { strcpy(errstr, (x)); goto on_error; } while (0)
|
|
|
|
static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
|
|
{
|
|
@@ -792,7 +795,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|
if (interface_opt)
|
|
{
|
|
#if defined(SO_BINDTODEVICE)
|
|
- strncpy(interface, interface_opt, IF_NAMESIZE - 1);
|
|
+ safe_strncpy(interface, interface_opt, IF_NAMESIZE);
|
|
#else
|
|
return _("interface binding not supported");
|
|
#endif
|
|
@@ -821,7 +824,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|
return _("interface can only be specified once");
|
|
|
|
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
|
- strncpy(interface, source, IF_NAMESIZE - 1);
|
|
+ safe_strncpy(interface, source, IF_NAMESIZE);
|
|
#else
|
|
return _("interface binding not supported");
|
|
#endif
|
|
@@ -856,7 +859,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|
return _("interface can only be specified once");
|
|
|
|
source_addr->in6.sin6_addr = in6addr_any;
|
|
- strncpy(interface, source, IF_NAMESIZE - 1);
|
|
+ safe_strncpy(interface, source, IF_NAMESIZE);
|
|
#else
|
|
return _("interface binding not supported");
|
|
#endif
|
|
@@ -894,6 +897,8 @@ static struct server *add_rev4(struct in_addr addr, int msize)
|
|
p += sprintf(p, "%d.", (a >> 24) & 0xff);
|
|
break;
|
|
default:
|
|
+ free(serv->domain);
|
|
+ free(serv);
|
|
return NULL;
|
|
}
|
|
|
|
@@ -948,6 +953,99 @@ static char *set_prefix(char *arg)
|
|
return arg;
|
|
}
|
|
|
|
+static struct dhcp_netid *
|
|
+dhcp_netid_create(const char *net, struct dhcp_netid *next)
|
|
+{
|
|
+ struct dhcp_netid *tt;
|
|
+ tt = opt_malloc(sizeof (struct dhcp_netid));
|
|
+ tt->net = opt_string_alloc(net);
|
|
+ tt->next = next;
|
|
+ return tt;
|
|
+}
|
|
+
|
|
+static void dhcp_netid_free(struct dhcp_netid *nid)
|
|
+{
|
|
+ while (nid)
|
|
+ {
|
|
+ struct dhcp_netid *tmp = nid;
|
|
+ nid = nid->next;
|
|
+ free(tmp->net);
|
|
+ free(tmp);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Parse one or more tag:s before parameters.
|
|
+ * Moves arg to the end of tags. */
|
|
+static struct dhcp_netid * dhcp_tags(char **arg)
|
|
+{
|
|
+ struct dhcp_netid *id = NULL;
|
|
+
|
|
+ while (is_tag_prefix(*arg))
|
|
+ {
|
|
+ char *comma = split(*arg);
|
|
+ id = dhcp_netid_create((*arg)+4, id);
|
|
+ *arg = comma;
|
|
+ };
|
|
+ if (!*arg)
|
|
+ {
|
|
+ dhcp_netid_free(id);
|
|
+ id = NULL;
|
|
+ }
|
|
+ return id;
|
|
+}
|
|
+
|
|
+static void dhcp_netid_list_free(struct dhcp_netid_list *netid)
|
|
+{
|
|
+ while (netid)
|
|
+ {
|
|
+ struct dhcp_netid_list *tmplist = netid;
|
|
+ netid = netid->next;
|
|
+ dhcp_netid_free(tmplist->list);
|
|
+ free(tmplist);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void dhcp_config_free(struct dhcp_config *config)
|
|
+{
|
|
+ if (config)
|
|
+ {
|
|
+ struct hwaddr_config *hwaddr = config->hwaddr;
|
|
+ while (hwaddr)
|
|
+ {
|
|
+ struct hwaddr_config *tmp = hwaddr;
|
|
+ hwaddr = hwaddr->next;
|
|
+ free(tmp);
|
|
+ }
|
|
+ dhcp_netid_list_free(config->netid);
|
|
+ if (config->flags & CONFIG_CLID)
|
|
+ free(config->clid);
|
|
+ free(config);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void dhcp_context_free(struct dhcp_context *ctx)
|
|
+{
|
|
+ if (ctx)
|
|
+ {
|
|
+ dhcp_netid_free(ctx->filter);
|
|
+ free(ctx->netid.net);
|
|
+#ifdef HAVE_DHCP6
|
|
+ free(ctx->template_interface);
|
|
+#endif
|
|
+ free(ctx);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void dhcp_opt_free(struct dhcp_opt *opt)
|
|
+{
|
|
+ if (opt->flags & DHOPT_VENDOR)
|
|
+ free(opt->u.vendor_class);
|
|
+ dhcp_netid_free(opt->netid);
|
|
+ free(opt->val);
|
|
+ free(opt);
|
|
+}
|
|
+
|
|
+
|
|
/* This is too insanely large to keep in-line in the switch */
|
|
static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
{
|
|
@@ -955,7 +1053,6 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
char lenchar = 0, *cp;
|
|
int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots;
|
|
char *comma = NULL;
|
|
- struct dhcp_netid *np = NULL;
|
|
u16 opt_len = 0;
|
|
int is6 = 0;
|
|
int option_ok = 0;
|
|
@@ -1042,14 +1139,9 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
}
|
|
else
|
|
{
|
|
- new->netid = opt_malloc(sizeof (struct dhcp_netid));
|
|
/* allow optional "net:" or "tag:" for consistency */
|
|
- if (is_tag_prefix(arg))
|
|
- new->netid->net = opt_string_alloc(arg+4);
|
|
- else
|
|
- new->netid->net = opt_string_alloc(set_prefix(arg));
|
|
- new->netid->next = np;
|
|
- np = new->netid;
|
|
+ const char *name = (is_tag_prefix(arg)) ? arg+4 : set_prefix(arg);
|
|
+ new->netid = dhcp_netid_create(name, new->netid);
|
|
}
|
|
|
|
arg = comma;
|
|
@@ -1059,7 +1151,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
if (is6)
|
|
{
|
|
if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))
|
|
- ret_err(_("unsupported encapsulation for IPv6 option"));
|
|
+ goto_err(_("unsupported encapsulation for IPv6 option"));
|
|
|
|
if (opt_len == 0 &&
|
|
!(new->flags & DHOPT_RFC3925))
|
|
@@ -1073,7 +1165,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
|
|
/* option may be missing with rfc3925 match */
|
|
if (!option_ok)
|
|
- ret_err(_("bad dhcp-option"));
|
|
+ goto_err(_("bad dhcp-option"));
|
|
|
|
if (comma)
|
|
{
|
|
@@ -1141,10 +1233,10 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
is_string = is_dec = is_hex = 0;
|
|
|
|
if (!is6 && (!is_addr || dots == 0))
|
|
- ret_err(_("bad IP address"));
|
|
+ goto_err(_("bad IP address"));
|
|
|
|
if (is6 && !is_addr6)
|
|
- ret_err(_("bad IPv6 address"));
|
|
+ goto_err(_("bad IPv6 address"));
|
|
}
|
|
/* or names */
|
|
else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING))
|
|
@@ -1237,7 +1329,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
comma = split(cp);
|
|
slash = split_chr(cp, '/');
|
|
if (!inet_pton(AF_INET, cp, &in))
|
|
- ret_err(_("bad IPv4 address"));
|
|
+ goto_err(_("bad IPv4 address"));
|
|
if (!slash)
|
|
{
|
|
memcpy(op, &in, INADDRSZ);
|
|
@@ -1282,8 +1374,8 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
op += IN6ADDRSZ;
|
|
continue;
|
|
}
|
|
-
|
|
- ret_err(_("bad IPv6 address"));
|
|
+
|
|
+ goto_err(_("bad IPv6 address"));
|
|
}
|
|
new->len = op - new->val;
|
|
}
|
|
@@ -1310,7 +1402,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
if (strcmp (arg, ".") != 0)
|
|
{
|
|
if (!(dom = canonicalise_opt(arg)))
|
|
- ret_err(_("bad domain in dhcp-option"));
|
|
+ goto_err(_("bad domain in dhcp-option"));
|
|
|
|
domlen = strlen(dom) + 2;
|
|
}
|
|
@@ -1404,7 +1496,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
{
|
|
char *dom = canonicalise_opt(arg);
|
|
if (!dom)
|
|
- ret_err(_("bad domain in dhcp-option"));
|
|
+ goto_err(_("bad domain in dhcp-option"));
|
|
|
|
newp = opt_malloc(len + strlen(dom) + 2);
|
|
|
|
@@ -1442,14 +1534,14 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
((new->len > 255) ||
|
|
(new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
|
|
(new->len > 250 && (new->flags & DHOPT_RFC3925))))
|
|
- ret_err(_("dhcp-option too long"));
|
|
+ goto_err(_("dhcp-option too long"));
|
|
|
|
if (flags == DHOPT_MATCH)
|
|
{
|
|
if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
|
|
!new->netid ||
|
|
new->netid->next)
|
|
- ret_err(_("illegal dhcp-match"));
|
|
+ goto_err(_("illegal dhcp-match"));
|
|
|
|
if (is6)
|
|
{
|
|
@@ -1474,24 +1566,31 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|
}
|
|
|
|
return 1;
|
|
+on_error:
|
|
+ dhcp_opt_free(new);
|
|
+ return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
void set_option_bool(unsigned int opt)
|
|
{
|
|
- if (opt < 32)
|
|
- daemon->options |= 1u << opt;
|
|
- else
|
|
- daemon->options2 |= 1u << (opt - 32);
|
|
+ option_var(opt) |= option_val(opt);
|
|
}
|
|
|
|
void reset_option_bool(unsigned int opt)
|
|
{
|
|
- if (opt < 32)
|
|
- daemon->options &= ~(1u << opt);
|
|
- else
|
|
- daemon->options2 &= ~(1u << (opt - 32));
|
|
+ option_var(opt) &= ~(option_val(opt));
|
|
+}
|
|
+
|
|
+static void server_list_free(struct server *list)
|
|
+{
|
|
+ while (list)
|
|
+ {
|
|
+ struct server *tmp = list;
|
|
+ list = list->next;
|
|
+ free(tmp);
|
|
+ }
|
|
}
|
|
|
|
static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only)
|
|
@@ -1675,13 +1774,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
/* has subnet+len */
|
|
err = parse_mysockaddr(arg, &new->addr);
|
|
if (err)
|
|
- ret_err(err);
|
|
+ ret_err_free(err, new);
|
|
if (!atoi_check(end, &new->mask))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
new->addr_used = 1;
|
|
}
|
|
else if (!atoi_check(arg, &new->mask))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
|
|
daemon->add_subnet4 = new;
|
|
|
|
@@ -1693,15 +1792,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
/* has subnet+len */
|
|
err = parse_mysockaddr(comma, &new->addr);
|
|
if (err)
|
|
- ret_err(err);
|
|
+ ret_err_free(err, new);
|
|
if (!atoi_check(end, &new->mask))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
new->addr_used = 1;
|
|
}
|
|
else
|
|
{
|
|
if (!atoi_check(comma, &new->mask))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
}
|
|
|
|
daemon->add_subnet6 = new;
|
|
@@ -1908,7 +2007,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
new->addr.sa.sa_family = AF_INET6;
|
|
#endif
|
|
else
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ free(new->name);
|
|
+ ret_err_free(gen_err, new);
|
|
+ }
|
|
}
|
|
}
|
|
new->next = daemon->authinterface;
|
|
@@ -2080,7 +2182,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
|
|
arg = split(netpart);
|
|
if (!atoi_check(netpart, &msize))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
else if (inet_pton(AF_INET, comma, &new->start))
|
|
{
|
|
int mask = (1 << (32 - msize)) - 1;
|
|
@@ -2093,18 +2195,18 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
{
|
|
if (!(new->prefix = canonicalise_opt(arg)) ||
|
|
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
|
- ret_err(_("bad prefix"));
|
|
+ ret_err_free(_("bad prefix"), new);
|
|
}
|
|
else if (strcmp(arg, "local") != 0 ||
|
|
(msize != 8 && msize != 16 && msize != 24))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
else
|
|
{
|
|
/* generate the equivalent of
|
|
local=/xxx.yyy.zzz.in-addr.arpa/ */
|
|
struct server *serv = add_rev4(new->start, msize);
|
|
if (!serv)
|
|
- ret_err(_("bad prefix"));
|
|
+ ret_err_free(_("bad prefix"), new);
|
|
|
|
serv->flags |= SERV_NO_ADDR;
|
|
|
|
@@ -2134,17 +2236,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
setaddr6part(&new->end6, addrpart | mask);
|
|
|
|
if (msize < 64)
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
else if (arg)
|
|
{
|
|
if (option != 's')
|
|
{
|
|
if (!(new->prefix = canonicalise_opt(arg)) ||
|
|
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
|
|
- ret_err(_("bad prefix"));
|
|
+ ret_err_free(_("bad prefix"), new);
|
|
}
|
|
else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
else
|
|
{
|
|
/* generate the equivalent of
|
|
@@ -2164,7 +2266,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
#endif
|
|
else
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
}
|
|
else
|
|
{
|
|
@@ -2178,7 +2280,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
if (!arg)
|
|
new->end.s_addr = new->start.s_addr;
|
|
else if (!inet_pton(AF_INET, arg, &new->end))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
}
|
|
#ifdef HAVE_IPV6
|
|
else if (inet_pton(AF_INET6, comma, &new->start6))
|
|
@@ -2187,17 +2289,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
if (!arg)
|
|
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
|
|
else if (!inet_pton(AF_INET6, arg, &new->end6))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
}
|
|
#endif
|
|
else
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
|
|
if (option != 's' && prefstr)
|
|
{
|
|
if (!(new->prefix = canonicalise_opt(prefstr)) ||
|
|
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
|
- ret_err(_("bad prefix"));
|
|
+ ret_err_free(_("bad prefix"), new);
|
|
}
|
|
}
|
|
|
|
@@ -2359,7 +2461,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
#endif
|
|
else
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
|
|
new->used = 0;
|
|
if (option == 'a')
|
|
@@ -2430,7 +2532,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
{
|
|
newlist->flags |= SERV_LITERAL_ADDRESS;
|
|
if (!(newlist->flags & SERV_TYPE))
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ server_list_free(newlist);
|
|
+ ret_err(gen_err);
|
|
+ }
|
|
}
|
|
else if (option == LOPT_NO_REBIND)
|
|
newlist->flags |= SERV_NO_REBIND;
|
|
@@ -2451,7 +2556,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
{
|
|
char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
|
|
if (err)
|
|
- ret_err(err);
|
|
+ {
|
|
+ server_list_free(newlist);
|
|
+ ret_err(err);
|
|
+ }
|
|
}
|
|
|
|
serv = newlist;
|
|
@@ -2801,21 +2909,19 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
{
|
|
if (is_tag_prefix(arg))
|
|
{
|
|
- struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
|
|
- tt->net = opt_string_alloc(arg+4);
|
|
- tt->next = new->filter;
|
|
/* ignore empty tag */
|
|
- if (tt->net)
|
|
- new->filter = tt;
|
|
+ if (arg[4])
|
|
+ new->filter = dhcp_netid_create(arg+4, new->filter);
|
|
}
|
|
else
|
|
{
|
|
if (new->netid.net)
|
|
- ret_err(_("only one tag allowed"));
|
|
- else if (strstr(arg, "set:") == arg)
|
|
- new->netid.net = opt_string_alloc(arg+4);
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("only one tag allowed"));
|
|
+ }
|
|
else
|
|
- new->netid.net = opt_string_alloc(arg);
|
|
+ new->netid.net = opt_string_alloc(set_prefix(arg));
|
|
}
|
|
arg = comma;
|
|
}
|
|
@@ -2831,7 +2937,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
break;
|
|
|
|
if (k < 2)
|
|
- ret_err(_("bad dhcp-range"));
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("bad dhcp-range"));
|
|
+ }
|
|
|
|
if (inet_pton(AF_INET, a[0], &new->start))
|
|
{
|
|
@@ -2843,7 +2952,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
else if (strcmp(a[1], "proxy") == 0)
|
|
new->flags |= CONTEXT_PROXY;
|
|
else if (!inet_pton(AF_INET, a[1], &new->end))
|
|
- ret_err(_("bad dhcp-range"));
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("bad dhcp-range"));
|
|
+ }
|
|
|
|
if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
|
|
{
|
|
@@ -2858,7 +2970,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
new->flags |= CONTEXT_NETMASK;
|
|
leasepos = 3;
|
|
if (!is_same_net(new->start, new->end, new->netmask))
|
|
- ret_err(_("inconsistent DHCP range"));
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("inconsistent DHCP range"));
|
|
+ }
|
|
|
|
|
|
if (k >= 4 && strchr(a[3], '.') &&
|
|
@@ -2872,6 +2987,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
#ifdef HAVE_DHCP6
|
|
else if (inet_pton(AF_INET6, a[0], &new->start6))
|
|
{
|
|
+ const char *err = NULL;
|
|
+
|
|
new->flags |= CONTEXT_V6;
|
|
new->prefix = 64; /* default */
|
|
new->end6 = new->start6;
|
|
@@ -2917,19 +3034,24 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
}
|
|
|
|
- if (new->prefix != 64)
|
|
+ if (new->prefix > 64)
|
|
{
|
|
if (new->flags & CONTEXT_RA)
|
|
- ret_err(_("prefix length must be exactly 64 for RA subnets"));
|
|
+ err=(_("prefix length must be exactly 64 for RA subnets"));
|
|
else if (new->flags & CONTEXT_TEMPLATE)
|
|
- ret_err(_("prefix length must be exactly 64 for subnet constructors"));
|
|
+ err=(_("prefix length must be exactly 64 for subnet constructors"));
|
|
}
|
|
-
|
|
- if (new->prefix < 64)
|
|
- ret_err(_("prefix length must be at least 64"));
|
|
+ else if (new->prefix < 64)
|
|
+ err=(_("prefix length must be at least 64"));
|
|
|
|
- if (!is_same_net6(&new->start6, &new->end6, new->prefix))
|
|
- ret_err(_("inconsistent DHCPv6 range"));
|
|
+ if (!err && !is_same_net6(&new->start6, &new->end6, new->prefix))
|
|
+ err=(_("inconsistent DHCPv6 range"));
|
|
+
|
|
+ if (err)
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(err);
|
|
+ }
|
|
|
|
/* dhcp-range=:: enables DHCP stateless on any interface */
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE))
|
|
@@ -2940,7 +3062,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
struct in6_addr zero;
|
|
memset(&zero, 0, sizeof(zero));
|
|
if (!is_same_net6(&zero, &new->start6, new->prefix))
|
|
- ret_err(_("prefix must be zero with \"constructor:\" argument"));
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("prefix must be zero with \"constructor:\" argument"));
|
|
+ }
|
|
}
|
|
|
|
if (addr6part(&new->start6) > addr6part(&new->end6))
|
|
@@ -2952,12 +3077,18 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
#endif
|
|
else
|
|
- ret_err(_("bad dhcp-range"));
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("bad dhcp-range"));
|
|
+ }
|
|
|
|
if (leasepos < k)
|
|
{
|
|
if (leasepos != k-1)
|
|
- ret_err(_("bad dhcp-range"));
|
|
+ {
|
|
+ dhcp_context_free(new);
|
|
+ ret_err(_("bad dhcp-range"));
|
|
+ }
|
|
|
|
if (strcmp(a[leasepos], "infinite") == 0)
|
|
new->lease_time = 0xffffffff;
|
|
@@ -2996,7 +3127,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
break;
|
|
|
|
if (*cp || (leasepos+1 < k))
|
|
- ret_err(_("bad dhcp-range"));
|
|
+ ret_err_free(_("bad dhcp-range"), new);
|
|
|
|
new->lease_time = atoi(a[leasepos]) * fac;
|
|
/* Leases of a minute or less confuse
|
|
@@ -3023,6 +3154,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
|
|
new->hwaddr = NULL;
|
|
new->netid = NULL;
|
|
+ new->clid = NULL;
|
|
|
|
if ((a[0] = arg))
|
|
for (k = 1; k < 7; k++)
|
|
@@ -3053,7 +3185,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
|
|
if (len == -1)
|
|
- ret_err(_("bad hex constant"));
|
|
+ {
|
|
+ dhcp_config_free(new);
|
|
+ ret_err(_("bad hex constant"));
|
|
+ }
|
|
else if ((new->clid = opt_malloc(len)))
|
|
{
|
|
new->flags |= CONFIG_CLID;
|
|
@@ -3065,17 +3200,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
/* dhcp-host has strange backwards-compat needs. */
|
|
else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
|
|
{
|
|
- struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
|
|
struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
|
|
- newtag->net = opt_malloc(strlen(arg + 4) + 1);
|
|
newlist->next = new->netid;
|
|
new->netid = newlist;
|
|
- newlist->list = newtag;
|
|
- strcpy(newtag->net, arg+4);
|
|
- unhide_metas(newtag->net);
|
|
+ newlist->list = dhcp_netid_create(arg+4, NULL);
|
|
}
|
|
else if (strstr(arg, "tag:") == arg)
|
|
- ret_err(_("cannot match tags in --dhcp-host"));
|
|
+ {
|
|
+
|
|
+ dhcp_config_free(new);
|
|
+ ret_err(_("cannot match tags in --dhcp-host"));
|
|
+ }
|
|
#ifdef HAVE_DHCP6
|
|
else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
|
|
{
|
|
@@ -3083,7 +3218,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
arg++;
|
|
|
|
if (!inet_pton(AF_INET6, arg, &new->addr6))
|
|
- ret_err(_("bad IPv6 address"));
|
|
+ {
|
|
+ dhcp_config_free(new);
|
|
+ ret_err(_("bad IPv6 address"));
|
|
+ }
|
|
|
|
for (i= 0; i < 8; i++)
|
|
if (new->addr6.s6_addr[i] != 0)
|
|
@@ -3101,10 +3239,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
|
|
if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
|
|
&newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
|
|
- ret_err(_("bad hex constant"));
|
|
+ {
|
|
+ free(newhw);
|
|
+ dhcp_config_free(new);
|
|
+ ret_err(_("bad hex constant"));
|
|
+ }
|
|
else
|
|
{
|
|
-
|
|
newhw->next = new->hwaddr;
|
|
new->hwaddr = newhw;
|
|
}
|
|
@@ -3181,7 +3322,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
{
|
|
if (!(new->hostname = canonicalise_opt(a[j])) ||
|
|
!legal_hostname(new->hostname))
|
|
- ret_err(_("bad DHCP host name"));
|
|
+ {
|
|
+ dhcp_config_free(new);
|
|
+ ret_err(_("bad DHCP host name"));
|
|
+ }
|
|
|
|
new->flags |= CONFIG_NAME;
|
|
new->domain = strip_hostname(new->hostname);
|
|
@@ -3234,10 +3378,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
else
|
|
{
|
|
- struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
|
|
- newtag->net = opt_malloc(len - 3);
|
|
- strcpy(newtag->net, arg+4);
|
|
- unhide_metas(newtag->net);
|
|
+ struct dhcp_netid *newtag = dhcp_netid_create(arg+4, NULL);
|
|
|
|
if (strstr(arg, "set:") == arg)
|
|
{
|
|
@@ -3254,7 +3395,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
else
|
|
{
|
|
new->set = NULL;
|
|
- free(newtag);
|
|
+ dhcp_netid_free(newtag);
|
|
break;
|
|
}
|
|
}
|
|
@@ -3263,7 +3404,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
|
|
if (!new->set)
|
|
- ret_err(_("bad tag-if"));
|
|
+ {
|
|
+ dhcp_netid_free(new->tag);
|
|
+ dhcp_netid_list_free(new->set);
|
|
+ ret_err_free(_("bad tag-if"), new);
|
|
+ }
|
|
|
|
break;
|
|
}
|
|
@@ -3280,19 +3425,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
|
|
case 'M': /* --dhcp-boot */
|
|
{
|
|
- struct dhcp_netid *id = NULL;
|
|
- while (is_tag_prefix(arg))
|
|
- {
|
|
- struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
|
|
- newid->next = id;
|
|
- id = newid;
|
|
- comma = split(arg);
|
|
- newid->net = opt_string_alloc(arg+4);
|
|
- arg = comma;
|
|
- };
|
|
+ struct dhcp_netid *id = dhcp_tags(&arg);
|
|
|
|
if (!arg)
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ ret_err(gen_err);
|
|
+ }
|
|
else
|
|
{
|
|
char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL;
|
|
@@ -3338,19 +3476,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
|
|
case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */
|
|
{
|
|
- struct dhcp_netid *id = NULL;
|
|
- while (is_tag_prefix(arg))
|
|
- {
|
|
- struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
|
|
- newid->next = id;
|
|
- id = newid;
|
|
- comma = split(arg);
|
|
- newid->net = opt_string_alloc(arg+4);
|
|
- arg = comma;
|
|
- };
|
|
+ struct dhcp_netid *id = dhcp_tags(&arg);
|
|
|
|
if (!arg)
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ ret_err(gen_err);
|
|
+ }
|
|
else
|
|
{
|
|
struct delay_config *new;
|
|
@@ -3375,19 +3506,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
|
|
new->netid = NULL;
|
|
new->opt = 10; /* PXE_MENU_PROMPT */
|
|
-
|
|
- while (is_tag_prefix(arg))
|
|
- {
|
|
- struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
|
|
- comma = split(arg);
|
|
- nn->next = new->netid;
|
|
- new->netid = nn;
|
|
- nn->net = opt_string_alloc(arg+4);
|
|
- arg = comma;
|
|
- }
|
|
+ new->netid = dhcp_tags(&arg);
|
|
|
|
if (!arg)
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ dhcp_opt_free(new);
|
|
+ ret_err(gen_err);
|
|
+ }
|
|
else
|
|
{
|
|
comma = split(arg);
|
|
@@ -3423,17 +3548,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
new->netid = NULL;
|
|
new->sname = NULL;
|
|
new->server.s_addr = 0;
|
|
+ new->netid = dhcp_tags(&arg);
|
|
|
|
- while (is_tag_prefix(arg))
|
|
- {
|
|
- struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
|
|
- comma = split(arg);
|
|
- nn->next = new->netid;
|
|
- new->netid = nn;
|
|
- nn->net = opt_string_alloc(arg+4);
|
|
- arg = comma;
|
|
- }
|
|
-
|
|
if (arg && (comma = split(arg)))
|
|
{
|
|
for (i = 0; CSA[i]; i++)
|
|
@@ -3510,7 +3626,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
unhide_metas(comma);
|
|
new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
|
|
if (new->hwaddr_len == -1)
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ free(new->netid.net);
|
|
+ ret_err_free(gen_err, new);
|
|
+ }
|
|
else
|
|
{
|
|
new->next = daemon->dhcp_macs;
|
|
@@ -3527,7 +3646,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
|
|
if (!(comma = split(arg)) ||
|
|
!atoi_check16(comma, &new->class))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
|
|
new->tag.net = opt_string_alloc(set_prefix(arg));
|
|
new->next = daemon->prefix_classes;
|
|
@@ -3549,7 +3668,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
|
|
|
|
if (!(comma = split(arg)))
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
|
|
new->netid.net = opt_string_alloc(set_prefix(arg));
|
|
/* check for hex string - must digits may include : must not have nothing else,
|
|
@@ -3559,7 +3678,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
if ((comma = split(arg)))
|
|
{
|
|
if (option != 'U' || strstr(arg, "enterprise:") != arg)
|
|
- ret_err(gen_err);
|
|
+ {
|
|
+ free(new->netid.net);
|
|
+ ret_err_free(gen_err, new);
|
|
+ }
|
|
else
|
|
new->enterprise = atoi(arg+11);
|
|
}
|
|
@@ -3661,14 +3783,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
|
|
while (arg) {
|
|
- struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
|
|
comma = split(arg);
|
|
- member->next = list;
|
|
- list = member;
|
|
- if (is_tag_prefix(arg))
|
|
- member->net = opt_string_alloc(arg+4);
|
|
- else
|
|
- member->net = opt_string_alloc(arg);
|
|
+ list = dhcp_netid_create(is_tag_prefix(arg) ? arg+4 :arg, list);
|
|
arg = comma;
|
|
}
|
|
|
|
@@ -3682,7 +3798,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
struct addr_list *new = opt_malloc(sizeof(struct addr_list));
|
|
comma = split(arg);
|
|
if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
|
|
- ret_err(_("bad dhcp-proxy address"));
|
|
+ ret_err_free(_("bad dhcp-proxy address"), new);
|
|
new->next = daemon->override_relays;
|
|
daemon->override_relays = new;
|
|
arg = comma;
|
|
@@ -3708,7 +3824,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
}
|
|
#endif
|
|
else
|
|
- ret_err(_("Bad dhcp-relay"));
|
|
+ {
|
|
+ free(new->interface);
|
|
+ ret_err_free(_("Bad dhcp-relay"), new);
|
|
+ }
|
|
|
|
break;
|
|
}
|
|
@@ -3748,8 +3867,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|
arg = split(comma);
|
|
if (!atoi_check(comma, &new->interval) ||
|
|
(arg && !atoi_check(arg, &new->lifetime)))
|
|
+ {
|
|
err:
|
|
- ret_err(_("bad RA-params"));
|
|
+ free(new->name);
|
|
+ ret_err_free(_("bad RA-params"), new);
|
|
+ }
|
|
|
|
new->next = daemon->ra_interfaces;
|
|
daemon->ra_interfaces = new;
|
|
@@ -3800,7 +3922,7 @@ err:
|
|
(!(inet_pton(AF_INET, dash, &new->end) > 0) ||
|
|
!is_same_net(new->in, new->end, new->mask) ||
|
|
ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
|
|
- ret_err(_("invalid alias range"));
|
|
+ ret_err_free(_("invalid alias range"), new);
|
|
|
|
break;
|
|
}
|
|
@@ -3835,7 +3957,7 @@ err:
|
|
new->family = AF_INET6;
|
|
#endif
|
|
else
|
|
- ret_err(gen_err);
|
|
+ ret_err_free(gen_err, new);
|
|
}
|
|
new->intr = opt_string_alloc(comma);
|
|
break;
|
|
@@ -3867,11 +3989,19 @@ err:
|
|
alias = canonicalise_opt(arg);
|
|
|
|
if (!alias || !target)
|
|
- ret_err(_("bad CNAME"));
|
|
+ {
|
|
+ free(target);
|
|
+ free(alias);
|
|
+ ret_err(_("bad CNAME"));
|
|
+ }
|
|
|
|
for (new = daemon->cnames; new; new = new->next)
|
|
if (hostname_isequal(new->alias, alias))
|
|
- ret_err(_("duplicate CNAME"));
|
|
+ {
|
|
+ free(target);
|
|
+ free(alias);
|
|
+ ret_err(_("duplicate CNAME"));
|
|
+ }
|
|
new = opt_malloc(sizeof(struct cname));
|
|
new->next = daemon->cnames;
|
|
daemon->cnames = new;
|
|
@@ -3894,7 +4024,11 @@ err:
|
|
|
|
if (!(dom = canonicalise_opt(arg)) ||
|
|
(comma && !(target = canonicalise_opt(comma))))
|
|
- ret_err(_("bad PTR record"));
|
|
+ {
|
|
+ free(dom);
|
|
+ free(target);
|
|
+ ret_err(_("bad PTR record"));
|
|
+ }
|
|
else
|
|
{
|
|
new = opt_malloc(sizeof(struct ptr_record));
|
|
@@ -3912,7 +4046,7 @@ err:
|
|
int k = 0;
|
|
struct naptr *new;
|
|
int order, pref;
|
|
- char *name, *replace = NULL;
|
|
+ char *name=NULL, *replace = NULL;
|
|
|
|
if ((a[0] = arg))
|
|
for (k = 1; k < 7; k++)
|
|
@@ -3925,7 +4059,11 @@ err:
|
|
!atoi_check16(a[1], &order) ||
|
|
!atoi_check16(a[2], &pref) ||
|
|
(k == 7 && !(replace = canonicalise_opt(a[6]))))
|
|
- ret_err(_("bad NAPTR record"));
|
|
+ {
|
|
+ free(name);
|
|
+ free(replace);
|
|
+ ret_err(_("bad NAPTR record"));
|
|
+ }
|
|
else
|
|
{
|
|
new = opt_malloc(sizeof(struct naptr));
|
|
@@ -3947,22 +4085,26 @@ err:
|
|
struct txt_record *new;
|
|
size_t len = 0;
|
|
char *data;
|
|
- int val;
|
|
+ int class;
|
|
|
|
comma = split(arg);
|
|
data = split(comma);
|
|
|
|
new = opt_malloc(sizeof(struct txt_record));
|
|
- new->next = daemon->rr;
|
|
- daemon->rr = new;
|
|
+ new->name = NULL;
|
|
|
|
- if (!atoi_check(comma, &val) ||
|
|
+ if (!atoi_check(comma, &class) ||
|
|
!(new->name = canonicalise_opt(arg)) ||
|
|
(data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U))
|
|
- ret_err(_("bad RR record"));
|
|
-
|
|
- new->class = val;
|
|
+ {
|
|
+ free(new->name);
|
|
+ ret_err_free(_("bad RR record"), new);
|
|
+ }
|
|
+
|
|
new->len = 0;
|
|
+ new->class = class;
|
|
+ new->next = daemon->rr;
|
|
+ daemon->rr = new;
|
|
|
|
if (data)
|
|
{
|
|
@@ -3983,14 +4125,14 @@ err:
|
|
comma = split(arg);
|
|
|
|
new = opt_malloc(sizeof(struct txt_record));
|
|
- new->next = daemon->txt;
|
|
- daemon->txt = new;
|
|
new->class = C_IN;
|
|
new->stat = 0;
|
|
|
|
if (!(new->name = canonicalise_opt(arg)))
|
|
- ret_err(_("bad TXT record"));
|
|
+ ret_err_free(_("bad TXT record"), new);
|
|
|
|
+ new->next = daemon->txt;
|
|
+ daemon->txt = new;
|
|
len = comma ? strlen(comma) : 0;
|
|
len += (len/255) + 1; /* room for extra counts */
|
|
new->txt = p = opt_malloc(len);
|
|
@@ -4037,24 +4179,32 @@ err:
|
|
arg = comma;
|
|
comma = split(arg);
|
|
if (!(target = canonicalise_opt(arg)))
|
|
- ret_err(_("bad SRV target"));
|
|
+ ret_err_free(_("bad SRV target"), name);
|
|
|
|
if (comma)
|
|
{
|
|
arg = comma;
|
|
comma = split(arg);
|
|
if (!atoi_check16(arg, &port))
|
|
- ret_err(_("invalid port number"));
|
|
+ {
|
|
+ free(name);
|
|
+ ret_err_free(_("invalid port number"), target);
|
|
+ }
|
|
|
|
if (comma)
|
|
{
|
|
arg = comma;
|
|
comma = split(arg);
|
|
if (!atoi_check16(arg, &priority))
|
|
- ret_err(_("invalid priority"));
|
|
-
|
|
+ {
|
|
+ free(name);
|
|
+ ret_err_free(_("invalid priority"), target);
|
|
+ }
|
|
if (comma && !atoi_check16(comma, &weight))
|
|
- ret_err(_("invalid weight"));
|
|
+ {
|
|
+ free(name);
|
|
+ ret_err_free(_("invalid weight"), target);
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -4073,13 +4223,15 @@ err:
|
|
|
|
case LOPT_HOST_REC: /* --host-record */
|
|
{
|
|
- struct host_record *new = opt_malloc(sizeof(struct host_record));
|
|
- memset(new, 0, sizeof(struct host_record));
|
|
- new->ttl = -1;
|
|
+ struct host_record *new;
|
|
|
|
if (!arg || !(comma = split(arg)))
|
|
ret_err(_("Bad host-record"));
|
|
|
|
+ new = opt_malloc(sizeof(struct host_record));
|
|
+ memset(new, 0, sizeof(struct host_record));
|
|
+ new->ttl = -1;
|
|
+
|
|
while (arg)
|
|
{
|
|
struct all_addr addr;
|
|
@@ -4100,10 +4252,19 @@ err:
|
|
{
|
|
int nomem;
|
|
char *canon = canonicalise(arg, &nomem);
|
|
- struct name_list *nl = opt_malloc(sizeof(struct name_list));
|
|
+ struct name_list *nl;
|
|
if (!canon)
|
|
- ret_err(_("Bad name in host-record"));
|
|
+ {
|
|
+ struct name_list *tmp = new->names, *next;
|
|
+ for (tmp = new->names; tmp; tmp = next)
|
|
+ {
|
|
+ next = tmp->next;
|
|
+ free(tmp);
|
|
+ }
|
|
+ ret_err_free(_("Bad name in host-record"), new);
|
|
+ }
|
|
|
|
+ nl = opt_malloc(sizeof(struct name_list));
|
|
nl->name = canon;
|
|
/* keep order, so that PTR record goes to first name */
|
|
nl->next = NULL;
|
|
@@ -4143,6 +4304,7 @@ err:
|
|
int len;
|
|
|
|
new->class = C_IN;
|
|
+ new->name = NULL;
|
|
|
|
if ((comma = split(arg)) && (algo = split(comma)))
|
|
{
|
|
@@ -4167,7 +4329,7 @@ err:
|
|
!atoi_check8(algo, &new->algo) ||
|
|
!atoi_check8(digest, &new->digest_type) ||
|
|
!(new->name = canonicalise_opt(arg)))
|
|
- ret_err(_("bad trust anchor"));
|
|
+ ret_err_free(_("bad trust anchor"), new);
|
|
|
|
/* Upper bound on length */
|
|
len = (2*strlen(keyhex))+1;
|
|
@@ -4181,7 +4343,10 @@ err:
|
|
else
|
|
cp++;
|
|
if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1)
|
|
- ret_err(_("bad HEX in trust anchor"));
|
|
+ {
|
|
+ free(new->name);
|
|
+ ret_err_free(_("bad HEX in trust anchor"), new);
|
|
+ }
|
|
|
|
new->next = daemon->ds;
|
|
daemon->ds = new;
|
|
@@ -4650,8 +4815,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|
size_t argbuf_size = MAXDNAME;
|
|
char *argbuf = opt_malloc(argbuf_size);
|
|
char *buff = opt_malloc(MAXDNAME);
|
|
- int option, conffile_opt = '7', testmode = 0;
|
|
- char *arg, *conffile = CONFFILE;
|
|
+ int option, testmode = 0;
|
|
+ char *arg, *conffile = NULL;
|
|
|
|
opterr = 0;
|
|
|
|
@@ -4725,8 +4890,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|
argbuf_size = strlen(optarg) + 1;
|
|
argbuf = opt_malloc(argbuf_size);
|
|
}
|
|
- strncpy(argbuf, optarg, argbuf_size);
|
|
- argbuf[argbuf_size-1] = 0;
|
|
+ safe_strncpy(argbuf, optarg, argbuf_size);
|
|
arg = argbuf;
|
|
}
|
|
else
|
|
@@ -4761,7 +4925,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|
}
|
|
else if (option == 'C')
|
|
{
|
|
- conffile_opt = 0; /* file must exist */
|
|
+ if (conffile)
|
|
+ free(conffile);
|
|
conffile = opt_string_alloc(arg);
|
|
}
|
|
else
|
|
@@ -4779,10 +4944,11 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|
|
|
if (conffile)
|
|
{
|
|
- one_file(conffile, conffile_opt);
|
|
- if (conffile_opt == 0)
|
|
- free(conffile);
|
|
+ one_file(conffile, 0);
|
|
+ free(conffile);
|
|
}
|
|
+ else
|
|
+ one_file(CONFFILE, '7');
|
|
|
|
/* port might not be known when the address is parsed - fill in here */
|
|
if (daemon->servers)
|
|
diff --git a/src/rfc2131.c b/src/rfc2131.c
|
|
index c08a8ab..997575a 100644
|
|
--- a/src/rfc2131.c
|
|
+++ b/src/rfc2131.c
|
|
@@ -917,7 +917,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|
mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
|
|
|
|
if (boot->file)
|
|
- strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
|
|
+ safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
|
|
}
|
|
|
|
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
|
@@ -2296,7 +2296,7 @@ static void do_options(struct dhcp_context *context,
|
|
in_list(req_options, OPTION_SNAME))
|
|
option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
|
|
else
|
|
- strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
|
|
+ safe_strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname));
|
|
}
|
|
|
|
if (boot->file)
|
|
@@ -2306,7 +2306,7 @@ static void do_options(struct dhcp_context *context,
|
|
in_list(req_options, OPTION_FILENAME))
|
|
option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
|
|
else
|
|
- strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
|
|
+ safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
|
|
}
|
|
|
|
if (boot->next_server.s_addr)
|
|
@@ -2323,14 +2323,14 @@ static void do_options(struct dhcp_context *context,
|
|
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
|
|
(opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
|
|
{
|
|
- strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
|
|
+ safe_strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file));
|
|
done_file = 1;
|
|
}
|
|
|
|
if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
|
|
(opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
|
|
{
|
|
- strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
|
|
+ safe_strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname));
|
|
done_server = 1;
|
|
}
|
|
|
|
diff --git a/src/tftp.c b/src/tftp.c
|
|
index bccca69..f2eccbc 100644
|
|
--- a/src/tftp.c
|
|
+++ b/src/tftp.c
|
|
@@ -234,7 +234,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|
#endif
|
|
}
|
|
|
|
- strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
|
+ safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
|
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
|
{
|
|
mtu = ifr.ifr_mtu;
|
|
diff --git a/src/util.c b/src/util.c
|
|
index 532bc16..e003e3c 100644
|
|
--- a/src/util.c
|
|
+++ b/src/util.c
|
|
@@ -281,7 +281,17 @@ void *safe_malloc(size_t size)
|
|
die(_("could not get memory"), NULL, EC_NOMEM);
|
|
|
|
return ret;
|
|
-}
|
|
+}
|
|
+
|
|
+/* can be replaced by (void)strlcpy() on some platforms */
|
|
+void safe_strncpy(char *dest, const char *src, size_t size)
|
|
+{
|
|
+ if (size)
|
|
+ {
|
|
+ dest[size-1] = '\0';
|
|
+ strncpy(dest, src, size-1);
|
|
+ }
|
|
+}
|
|
|
|
void safe_pipe(int *fd, int read_noblock)
|
|
{
|
|
--
|
|
2.20.1
|
|
|