X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/938056a4b69c1bafaa663cd7336c28fbb66c6178..refs/heads/master:/addrtostr.c diff --git a/addrtostr.c b/addrtostr.c index e941d8e1..1fd2cf09 100644 --- a/addrtostr.c +++ b/addrtostr.c @@ -36,11 +36,9 @@ * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include -#include +#include "netdissect-stdinc.h" #include "addrtostr.h" #include @@ -71,7 +69,7 @@ addrtostr (const void *src, char *dst, size_t size) return NULL; } for (i = 0; i < 4; ++i) { - int n = *srcaddr++; + int n = *srcaddr++; int non_zerop = 0; if (non_zerop || n / 100 > 0) { @@ -106,37 +104,33 @@ addrtostr6 (const void *src, char *dst, size_t size) * to use pointer overlays. All the world's not a VAX. */ const u_char *srcaddr = (const u_char *)src; - char tmp [INET6_ADDRSTRLEN+1]; - char *tp; + char *dp; + size_t space_left, added_space; + int snprintfed; struct { - long base; - long len; + int base; + int len; } best, cur; - u_long words [IN6ADDRSZ / INT16SZ]; - int i; + uint16_t words [IN6ADDRSZ / INT16SZ]; + int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ - memset (words, 0, sizeof(words)); - for (i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= (srcaddr[i] << ((1 - (i % 2)) << 3)); + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) + words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1]; best.len = 0; best.base = -1; cur.len = 0; cur.base = -1; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - if (words[i] == 0) - { + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; - } - else if (cur.base != -1) - { + } else if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; @@ -149,51 +143,61 @@ addrtostr6 (const void *src, char *dst, size_t size) /* Format the result. */ - tp = tmp; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { + dp = dst; + space_left = size; +#define APPEND_CHAR(c) \ + { \ + if (space_left == 0) { \ + errno = ENOSPC; \ + return (NULL); \ + } \ + *dp++ = c; \ + space_left--; \ + } + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ - if (best.base != -1 && i >= best.base && i < (best.base + best.len)) - { + if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) - *tp++ = ':'; + APPEND_CHAR(':'); continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) - *tp++ = ':'; + APPEND_CHAR(':'); /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { - if (!addrtostr(srcaddr+12, tp, sizeof(tmp) - (tp - tmp))) - { + if (!addrtostr(srcaddr+12, dp, space_left)) { errno = ENOSPC; return (NULL); } - tp += strlen(tp); + added_space = strlen(dp); + dp += added_space; + space_left -= added_space; break; } - tp += sprintf (tp, "%lx", words[i]); + snprintfed = snprintf (dp, space_left, "%x", words[i]); + if (snprintfed < 0) + return (NULL); + if ((size_t) snprintfed >= space_left) { + errno = ENOSPC; + return (NULL); + } + dp += snprintfed; + space_left -= snprintfed; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; + APPEND_CHAR(':'); + APPEND_CHAR('\0'); - /* Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) - { - errno = ENOSPC; - return (NULL); - } - return strcpy (dst, tmp); + return (dst); }