-/* $OpenBSD: dhcpd.h,v 1.167 2017/04/08 17:00:10 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.168 2017/04/08 18:54:52 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
char *pretty_print_option(unsigned int, struct option_data *, int);
char *pretty_print_domain_search(unsigned char *, size_t);
char *pretty_print_string(unsigned char *, size_t, int);
-int pretty_print_classless_routes(unsigned char *, size_t, unsigned char *,
- size_t);
+char *pretty_print_classless_routes(unsigned char *, size_t);
void do_packet(struct interface_info *, unsigned int, struct in_addr,
struct ether_addr *);
-/* $OpenBSD: options.c,v 1.85 2017/04/08 17:00:10 krw Exp $ */
+/* $OpenBSD: options.c,v 1.86 2017/04/08 18:54:52 krw Exp $ */
/* DHCP options parsing and reassembly. */
* Must special case *_CLASSLESS_* route options due to the variable size
* of the CIDR element in its CIA format.
*/
-int
-pretty_print_classless_routes(unsigned char *dst, size_t dstlen,
- unsigned char *src, size_t srclen)
+char *
+pretty_print_classless_routes(unsigned char *src, size_t srclen)
{
- struct in_addr mask, gateway;
- int opcount = 0, total = 0, bits, bytes;
- char ntoabuf[INET_ADDRSTRLEN];
+ static char string[8196];
+ char bitsbuf[5]; /* to hold "/nn " */
+ struct in_addr net, gateway;
+ int bits, bytes, rslt;
+
+ memset(string, 0, sizeof(string));
- while (srclen && dstlen) {
+ while (srclen) {
bits = *src;
src++;
srclen--;
+
bytes = (bits + 7) / 8;
- if (srclen < bytes || bytes > sizeof(mask.s_addr))
- break;
- memset(&mask, 0, sizeof(mask));
- memcpy(&mask.s_addr, src, bytes);
+ if (srclen < (bytes + sizeof(gateway.s_addr)) ||
+ bytes > sizeof(net.s_addr))
+ return (NULL);
+ rslt = snprintf(bitsbuf, sizeof(bitsbuf), "/%d ", bits);
+ if (rslt == -1 || rslt >= sizeof(bitsbuf))
+ return (NULL);
+
+ memset(&net, 0, sizeof(net));
+ memcpy(&net.s_addr, src, bytes);
src += bytes;
srclen -= bytes;
- strlcpy(ntoabuf, inet_ntoa(mask), sizeof(ntoabuf));
- if (srclen < sizeof(gateway.s_addr))
- break;
+
memcpy(&gateway.s_addr, src, sizeof(gateway.s_addr));
src += sizeof(gateway.s_addr);
srclen -= sizeof(gateway.s_addr);
- opcount = snprintf(dst, dstlen, "%s%s/%u %s",
- total ? ", " : "", ntoabuf, bits,
- inet_ntoa(gateway));
- if (opcount == -1)
- return (-1);
- total += opcount;
- if (opcount >= dstlen)
- break;
- dst += opcount;
- dstlen -= opcount;
+
+ if (strlen(string) > 0)
+ strlcat(string, ", ", sizeof(string));
+ strlcat(string, inet_ntoa(net), sizeof(string));
+ strlcat(string, bitsbuf, sizeof(string));
+ rslt = strlcat(string, inet_ntoa(gateway), sizeof(string));
+ if (rslt >= sizeof(string))
+ return (NULL);
}
- return (total);
+ return (string);
}
int
switch (code) {
case DHO_CLASSLESS_STATIC_ROUTES:
case DHO_CLASSLESS_MS_STATIC_ROUTES:
- opcount = pretty_print_classless_routes(op, opleft, dp, len);
- if (opcount >= opleft || opcount == -1)
+ buf = pretty_print_classless_routes(dp, len);
+ if (buf == NULL)
goto toobig;
+ strlcat(optbuf, buf, sizeof(optbuf));
goto done;
default:
break;