summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2017-08-29 13:21:31 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2017-08-29 13:21:31 +0000
commitcff65d09c3e41406403a4cedc09efca2e8e36e95 (patch)
tree2decd868f28f18dc603edbd401e6743500ab2405 /sbin
parentbad77b9140c3ecca0786c6b902d2c9212f424a7c (diff)
Add a utility function extract_classless_route() and
use it to simplify logic at both places that process RFC 3442 data.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/dhclient/dhcpd.h4
-rw-r--r--sbin/dhclient/kroute.c55
-rw-r--r--sbin/dhclient/options.c47
3 files changed, 55 insertions, 51 deletions
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index 1bfa93ac545..8543adae8c3 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.224 2017/08/28 17:33:42 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.225 2017/08/29 13:21:30 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -233,6 +233,8 @@ void read_client_conf(char *);
void read_client_leases(char *, struct client_lease_tq *);
/* kroute.c */
+int extract_classless_route(uint8_t *, unsigned int,
+ in_addr_t *, in_addr_t *, in_addr_t *);
void delete_address(struct in_addr);
void set_resolv_conf(char *, uint8_t *, unsigned int,
uint8_t *, unsigned int);
diff --git a/sbin/dhclient/kroute.c b/sbin/dhclient/kroute.c
index 4af542eedcf..0f90ff5a14e 100644
--- a/sbin/dhclient/kroute.c
+++ b/sbin/dhclient/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.142 2017/08/26 18:52:56 krw Exp $ */
+/* $OpenBSD: kroute.c,v 1.143 2017/08/29 13:21:30 krw Exp $ */
/*
* Copyright 2012 Kenneth R Westerback <krw@openbsd.org>
@@ -163,40 +163,51 @@ priv_flush_routes(int index, int routefd, int rdomain)
free(buf);
}
+int
+extract_classless_route(uint8_t *rtstatic, unsigned int rtstatic_len,
+ in_addr_t *dest, in_addr_t *netmask, in_addr_t *gateway)
+{
+ unsigned int bits, bytes, len;
+
+ if (rtstatic[0] > 32)
+ return -1;
+
+ bits = rtstatic[0];
+ bytes = (bits + 7) / 8;
+ len = 1 + bytes + sizeof(*gateway);
+ if (len > rtstatic_len)
+ return -1;
+
+ memcpy(dest, &rtstatic[1], bytes);
+ if (bits == 0)
+ *netmask = INADDR_ANY;
+ else
+ *netmask = htonl(0xffffffff << (32 - bits));
+ *dest &= *netmask;
+ memcpy(gateway, &rtstatic[1 + bytes], sizeof(*gateway));
+
+ return len;
+}
+
void
set_routes(struct in_addr addr, struct in_addr addrmask, uint8_t *rtstatic,
unsigned int rtstatic_len)
{
const struct in_addr any = { INADDR_ANY };
struct in_addr dest, gateway, netmask;
- unsigned int i, bits, bytes;
+ unsigned int i;
+ int len;
flush_routes();
/* Add classless static routes. */
i = 0;
while (i < rtstatic_len) {
- bits = rtstatic[i++];
- bytes = (bits + 7) / 8;
-
- if (bytes > sizeof(netmask.s_addr))
- return;
- else if (i + bytes > rtstatic_len)
- return;
-
- if (bits != 0)
- netmask.s_addr = htonl(0xffffffff << (32 - bits));
- else
- netmask.s_addr = INADDR_ANY;
-
- memcpy(&dest, &rtstatic[i], bytes);
- dest.s_addr = dest.s_addr & netmask.s_addr;
- i += bytes;
-
- if (i + sizeof(gateway) > rtstatic_len)
+ len = extract_classless_route(&rtstatic[i], rtstatic_len - i,
+ &dest.s_addr, &netmask.s_addr, &gateway.s_addr);
+ if (len <= 0)
return;
- memcpy(&gateway.s_addr, &rtstatic[i], sizeof(gateway.s_addr));
- i += sizeof(gateway.s_addr);
+ i += len;
if (gateway.s_addr == INADDR_ANY) {
/*
diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c
index 9f84615b3e0..24ac6d64ce0 100644
--- a/sbin/dhclient/options.c
+++ b/sbin/dhclient/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.102 2017/08/28 17:33:42 krw Exp $ */
+/* $OpenBSD: options.c,v 1.103 2017/08/29 13:21:30 krw Exp $ */
/* DHCP options parsing and reassembly. */
@@ -588,43 +588,34 @@ pretty_print_classless_routes(unsigned char *src, size_t srclen,
unsigned char *buf, size_t buflen)
{
char bitsbuf[5]; /* to hold "/nn " */
- struct in_addr net, gateway;
- unsigned int bytes;
- int bits, rslt;
-
- while (srclen) {
- bits = *src;
- src++;
- srclen--;
-
- bytes = (bits + 7) / 8;
- if (srclen < (bytes + sizeof(gateway.s_addr)) ||
- bytes > sizeof(net.s_addr))
- goto toobig;
- rslt = snprintf(bitsbuf, sizeof(bitsbuf), "/%d ", bits);
+ struct in_addr dest, netmask, gateway;
+ unsigned int i;
+ int len, rslt;
+
+ i = 0;
+ while (i < srclen) {
+ len = extract_classless_route(&src[i], srclen - i,
+ &dest.s_addr, &netmask.s_addr, &gateway.s_addr);
+ if (len <= 0)
+ goto bad;
+ i += len;
+
+ rslt = snprintf(bitsbuf, sizeof(bitsbuf), "/%d ",
+ 33 - ffs(netmask.s_addr));
if (rslt == -1 || (unsigned int)rslt >= sizeof(bitsbuf))
- goto toobig;
-
- memset(&net, 0, sizeof(net));
- memcpy(&net.s_addr, src, bytes);
- src += bytes;
- srclen -= bytes;
-
- memcpy(&gateway.s_addr, src, sizeof(gateway.s_addr));
- src += sizeof(gateway.s_addr);
- srclen -= sizeof(gateway.s_addr);
+ goto bad;
if (strlen(buf) > 0)
strlcat(buf, ", ", buflen);
- strlcat(buf, inet_ntoa(net), buflen);
+ strlcat(buf, inet_ntoa(dest), buflen);
strlcat(buf, bitsbuf, buflen);
if (strlcat(buf, inet_ntoa(gateway), buflen) >= buflen)
- goto toobig;
+ goto bad;
}
return;
-toobig:
+bad:
memset(buf, 0, buflen);
}