diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2017-08-29 13:21:31 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2017-08-29 13:21:31 +0000 |
commit | cff65d09c3e41406403a4cedc09efca2e8e36e95 (patch) | |
tree | 2decd868f28f18dc603edbd401e6743500ab2405 | |
parent | bad77b9140c3ecca0786c6b902d2c9212f424a7c (diff) |
Add a utility function extract_classless_route() and
use it to simplify logic at both places that process
RFC 3442 data.
-rw-r--r-- | sbin/dhclient/dhcpd.h | 4 | ||||
-rw-r--r-- | sbin/dhclient/kroute.c | 55 | ||||
-rw-r--r-- | sbin/dhclient/options.c | 47 |
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); } |