From e691d16a63ce40bc56ecbc970e8118686d4b0148 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 29 Dec 2015 17:12:47 +0100 Subject: [PATCH] Explicit ip4_addr / ip6_addr printf support --- conf/confbase.Y | 2 +- lib/net.c | 9 +++---- lib/printf.c | 58 ++++++++++++++++++++++++++---------------- sysdep/linux/netlink.c | 2 +- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/conf/confbase.Y b/conf/confbase.Y index 06698833..9b4f54e9 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -178,7 +178,7 @@ pxlen4: } | ':' IP4 { $$ = ip4_masklen($2); - if ($$ == 255) cf_error("Invalid netmask %I", $2); /* XXXX */ + if ($$ == 255) cf_error("Invalid netmask %I4", $2); } ; diff --git a/lib/net.c b/lib/net.c index 76ecd460..a78111ab 100644 --- a/lib/net.c +++ b/lib/net.c @@ -31,17 +31,16 @@ net_format(const net_addr *N, char *buf, int buflen) { net_addr_union *n = (void *) N; - /* XXXX fix %I vs %R */ switch (n->n.type) { case NET_IP4: - return bsnprintf(buf, buflen, "%R/%d", n->ip4.prefix, n->ip4.pxlen); + return bsnprintf(buf, buflen, "%I4/%d", n->ip4.prefix, n->ip4.pxlen); case NET_IP6: - return bsnprintf(buf, buflen, "%I/%d", n->ip6.prefix, n->ip6.pxlen); + return bsnprintf(buf, buflen, "%I6/%d", n->ip6.prefix, n->ip6.pxlen); case NET_VPN4: - return bsnprintf(buf, buflen, "%u:%u %R/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); + return bsnprintf(buf, buflen, "%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); case NET_VPN6: - return bsnprintf(buf, buflen, "%u:%u %I/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); + return bsnprintf(buf, buflen, "%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); } return 0; diff --git a/lib/printf.c b/lib/printf.c index 071fc953..ce12202c 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -118,15 +118,15 @@ static char * number(char * str, long num, int base, int size, int precision, * @fmt: format string * @args: a list of arguments to be formatted * - * This functions acts like ordinary sprintf() except that it checks - * available space to avoid buffer overflows and it allows some more - * format specifiers: |%I| for formatting of IP addresses (any non-zero - * width is automatically replaced by standard IP address width which - * depends on whether we use IPv4 or IPv6; |%#I| gives hexadecimal format), - * |%R| for Router / Network ID (u32 value printed as IPv4 address) - * and |%m| resp. |%M| for error messages (uses strerror() to translate @errno code to - * message text). On the other hand, it doesn't support floating - * point numbers. + * This functions acts like ordinary sprintf() except that it checks available + * space to avoid buffer overflows and it allows some more format specifiers: + * |%I| for formatting of IP addresses (width of 1 is automatically replaced by + * standard IP address width which depends on whether we use IPv4 or IPv6; |%I4| + * or |%I6| can be used for explicit ip4_addr / ip6_addr arguments, |%N| for + * generic network addresses (net_addr *), |%R| for Router / Network ID (u32 + * value printed as IPv4 address) and |%m| resp. |%M| for error messages (uses + * strerror() to translate @errno code to message text). On the other hand, it + * doesn't support floating point numbers. * * Result: number of characters of the output string or -1 if * the buffer space was insufficient. @@ -168,7 +168,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) case '#': flags |= SPECIAL; goto repeat; case '0': flags |= ZEROPAD; goto repeat; } - + /* get field width */ field_width = -1; if (is_digit(*fmt)) @@ -186,7 +186,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) /* get the precision */ precision = -1; if (*fmt == '.') { - ++fmt; + ++fmt; if (is_digit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { @@ -289,22 +289,36 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) continue; /* IP address */ - case 'I': { - ip_addr a = va_arg(args, ip_addr); - if (flags & SPECIAL) - ip6_ntox(ipa_to_ip6(a), ipbuf); - else { - // XXXX better IPv4 / IPv6 distinction - if (ipa_is_ip4(a)) + case 'I': + if (fmt[1] == '4') { + /* Explicit IPv4 address */ + ip4_addr a = va_arg(args, ip4_addr); + ip4_ntop(a, ipbuf); + i = IP4_MAX_TEXT_LENGTH; + } else if (fmt[1] == '6') { + /* Explicit IPv6 address */ + ip6_addr a = va_arg(args, ip6_addr); + ip6_ntop(a, ipbuf); + i = IP6_MAX_TEXT_LENGTH; + } else { + /* Just IP address */ + ip_addr a = va_arg(args, ip_addr); + + if (ipa_is_ip4(a)) { ip4_ntop(ipa_to_ip4(a), ipbuf); - else + i = IP4_MAX_TEXT_LENGTH; + } else { ip6_ntop(ipa_to_ip6(a), ipbuf); - if (field_width == 1) - field_width = (ipa_is_ip4(a) ? IP4_MAX_TEXT_LENGTH : IP6_MAX_TEXT_LENGTH); + i = IP6_MAX_TEXT_LENGTH; + } } + s = ipbuf; + if (field_width == 1) + field_width = i; + goto str; - } + /* Interface scope after link-local IP address */ case 'J': iface = va_arg(args, struct iface *); diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index be790c29..530cb240 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -691,7 +691,7 @@ nl_parse_addr4(struct ifaddrmsg *i, int scan, int new) ifa.brd = ipa_from_ip4(xbrd); else if (ifi->flags & IF_TMP_DOWN) /* Complain only during the first scan */ { - log(L_ERR "KIF: Invalid broadcast address %I for %s", xbrd, ifi->name); + log(L_ERR "KIF: Invalid broadcast address %I4 for %s", xbrd, ifi->name); ifa.brd = ipa_from_ip4(ybrd); } }