13340d773SGleb Smirnoff /* 23340d773SGleb Smirnoff * Copyright (c) 1999 Kungliga Tekniska Högskolan 33340d773SGleb Smirnoff * (Royal Institute of Technology, Stockholm, Sweden). 43340d773SGleb Smirnoff * All rights reserved. 53340d773SGleb Smirnoff * 63340d773SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 73340d773SGleb Smirnoff * modification, are permitted provided that the following conditions 83340d773SGleb Smirnoff * are met: 93340d773SGleb Smirnoff * 103340d773SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 113340d773SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 123340d773SGleb Smirnoff * 133340d773SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 143340d773SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 153340d773SGleb Smirnoff * documentation and/or other materials provided with the distribution. 163340d773SGleb Smirnoff * 173340d773SGleb Smirnoff * 3. All advertising materials mentioning features or use of this software 183340d773SGleb Smirnoff * must display the following acknowledgement: 193340d773SGleb Smirnoff * This product includes software developed by the Kungliga Tekniska 203340d773SGleb Smirnoff * Högskolan and its contributors. 213340d773SGleb Smirnoff * 223340d773SGleb Smirnoff * 4. Neither the name of the Institute nor the names of its contributors 233340d773SGleb Smirnoff * may be used to endorse or promote products derived from this software 243340d773SGleb Smirnoff * without specific prior written permission. 253340d773SGleb Smirnoff * 263340d773SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 273340d773SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 283340d773SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 293340d773SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 303340d773SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 313340d773SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 323340d773SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 333340d773SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 343340d773SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 353340d773SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 363340d773SGleb Smirnoff * SUCH DAMAGE. 373340d773SGleb Smirnoff */ 383340d773SGleb Smirnoff 39ee67461eSJoseph Mingrone #include <config.h> 403340d773SGleb Smirnoff 41ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 423340d773SGleb Smirnoff #include "addrtostr.h" 433340d773SGleb Smirnoff 443340d773SGleb Smirnoff #include <stdio.h> 453340d773SGleb Smirnoff #include <string.h> 463340d773SGleb Smirnoff 473340d773SGleb Smirnoff /* 483340d773SGleb Smirnoff * 493340d773SGleb Smirnoff */ 503340d773SGleb Smirnoff 513340d773SGleb Smirnoff #ifndef IN6ADDRSZ 523340d773SGleb Smirnoff #define IN6ADDRSZ 16 /* IPv6 T_AAAA */ 533340d773SGleb Smirnoff #endif 543340d773SGleb Smirnoff 553340d773SGleb Smirnoff #ifndef INT16SZ 563340d773SGleb Smirnoff #define INT16SZ 2 /* word size */ 573340d773SGleb Smirnoff #endif 583340d773SGleb Smirnoff 593340d773SGleb Smirnoff const char * 603340d773SGleb Smirnoff addrtostr (const void *src, char *dst, size_t size) 613340d773SGleb Smirnoff { 623340d773SGleb Smirnoff const u_char *srcaddr = (const u_char *)src; 633340d773SGleb Smirnoff const char digits[] = "0123456789"; 643340d773SGleb Smirnoff int i; 653340d773SGleb Smirnoff const char *orig_dst = dst; 663340d773SGleb Smirnoff 673340d773SGleb Smirnoff if (size < INET_ADDRSTRLEN) { 683340d773SGleb Smirnoff errno = ENOSPC; 693340d773SGleb Smirnoff return NULL; 703340d773SGleb Smirnoff } 713340d773SGleb Smirnoff for (i = 0; i < 4; ++i) { 723340d773SGleb Smirnoff int n = *srcaddr++; 733340d773SGleb Smirnoff int non_zerop = 0; 743340d773SGleb Smirnoff 753340d773SGleb Smirnoff if (non_zerop || n / 100 > 0) { 763340d773SGleb Smirnoff *dst++ = digits[n / 100]; 773340d773SGleb Smirnoff n %= 100; 783340d773SGleb Smirnoff non_zerop = 1; 793340d773SGleb Smirnoff } 803340d773SGleb Smirnoff if (non_zerop || n / 10 > 0) { 813340d773SGleb Smirnoff *dst++ = digits[n / 10]; 823340d773SGleb Smirnoff n %= 10; 833340d773SGleb Smirnoff non_zerop = 1; 843340d773SGleb Smirnoff } 853340d773SGleb Smirnoff *dst++ = digits[n]; 863340d773SGleb Smirnoff if (i != 3) 873340d773SGleb Smirnoff *dst++ = '.'; 883340d773SGleb Smirnoff } 893340d773SGleb Smirnoff *dst++ = '\0'; 903340d773SGleb Smirnoff return orig_dst; 913340d773SGleb Smirnoff } 923340d773SGleb Smirnoff 933340d773SGleb Smirnoff /* 943340d773SGleb Smirnoff * Convert IPv6 binary address into presentation (printable) format. 953340d773SGleb Smirnoff */ 963340d773SGleb Smirnoff const char * 973340d773SGleb Smirnoff addrtostr6 (const void *src, char *dst, size_t size) 983340d773SGleb Smirnoff { 993340d773SGleb Smirnoff /* 1003340d773SGleb Smirnoff * Note that int32_t and int16_t need only be "at least" large enough 1013340d773SGleb Smirnoff * to contain a value of the specified size. On some systems, like 1023340d773SGleb Smirnoff * Crays, there is no such thing as an integer variable with 16 bits. 1033340d773SGleb Smirnoff * Keep this in mind if you think this function should have been coded 1043340d773SGleb Smirnoff * to use pointer overlays. All the world's not a VAX. 1053340d773SGleb Smirnoff */ 1063340d773SGleb Smirnoff const u_char *srcaddr = (const u_char *)src; 1073340d773SGleb Smirnoff char *dp; 1083340d773SGleb Smirnoff size_t space_left, added_space; 1093340d773SGleb Smirnoff int snprintfed; 1103340d773SGleb Smirnoff struct { 1110bff6a5aSEd Maste int base; 1120bff6a5aSEd Maste int len; 1133340d773SGleb Smirnoff } best, cur; 1140bff6a5aSEd Maste uint16_t words [IN6ADDRSZ / INT16SZ]; 1153340d773SGleb Smirnoff int i; 1163340d773SGleb Smirnoff 1173340d773SGleb Smirnoff /* Preprocess: 1183340d773SGleb Smirnoff * Copy the input (bytewise) array into a wordwise array. 1193340d773SGleb Smirnoff * Find the longest run of 0x00's in src[] for :: shorthanding. 1203340d773SGleb Smirnoff */ 1210bff6a5aSEd Maste for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) 1220bff6a5aSEd Maste words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1]; 1233340d773SGleb Smirnoff 1243340d773SGleb Smirnoff best.len = 0; 1253340d773SGleb Smirnoff best.base = -1; 1263340d773SGleb Smirnoff cur.len = 0; 1273340d773SGleb Smirnoff cur.base = -1; 128*0a7e5f1fSJoseph Mingrone for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { 129*0a7e5f1fSJoseph Mingrone if (words[i] == 0) { 1303340d773SGleb Smirnoff if (cur.base == -1) 1313340d773SGleb Smirnoff cur.base = i, cur.len = 1; 1323340d773SGleb Smirnoff else cur.len++; 133*0a7e5f1fSJoseph Mingrone } else if (cur.base != -1) { 1343340d773SGleb Smirnoff if (best.base == -1 || cur.len > best.len) 1353340d773SGleb Smirnoff best = cur; 1363340d773SGleb Smirnoff cur.base = -1; 1373340d773SGleb Smirnoff } 1383340d773SGleb Smirnoff } 1393340d773SGleb Smirnoff if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) 1403340d773SGleb Smirnoff best = cur; 1413340d773SGleb Smirnoff if (best.base != -1 && best.len < 2) 1423340d773SGleb Smirnoff best.base = -1; 1433340d773SGleb Smirnoff 1443340d773SGleb Smirnoff /* Format the result. 1453340d773SGleb Smirnoff */ 1463340d773SGleb Smirnoff dp = dst; 1473340d773SGleb Smirnoff space_left = size; 1483340d773SGleb Smirnoff #define APPEND_CHAR(c) \ 1493340d773SGleb Smirnoff { \ 1503340d773SGleb Smirnoff if (space_left == 0) { \ 1513340d773SGleb Smirnoff errno = ENOSPC; \ 1523340d773SGleb Smirnoff return (NULL); \ 1533340d773SGleb Smirnoff } \ 1543340d773SGleb Smirnoff *dp++ = c; \ 1553340d773SGleb Smirnoff space_left--; \ 1563340d773SGleb Smirnoff } 157*0a7e5f1fSJoseph Mingrone for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { 1583340d773SGleb Smirnoff /* Are we inside the best run of 0x00's? 1593340d773SGleb Smirnoff */ 160*0a7e5f1fSJoseph Mingrone if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { 1613340d773SGleb Smirnoff if (i == best.base) 1623340d773SGleb Smirnoff APPEND_CHAR(':'); 1633340d773SGleb Smirnoff continue; 1643340d773SGleb Smirnoff } 1653340d773SGleb Smirnoff 1663340d773SGleb Smirnoff /* Are we following an initial run of 0x00s or any real hex? 1673340d773SGleb Smirnoff */ 1683340d773SGleb Smirnoff if (i != 0) 1693340d773SGleb Smirnoff APPEND_CHAR(':'); 1703340d773SGleb Smirnoff 1713340d773SGleb Smirnoff /* Is this address an encapsulated IPv4? 1723340d773SGleb Smirnoff */ 1733340d773SGleb Smirnoff if (i == 6 && best.base == 0 && 1743340d773SGleb Smirnoff (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) 1753340d773SGleb Smirnoff { 176*0a7e5f1fSJoseph Mingrone if (!addrtostr(srcaddr+12, dp, space_left)) { 1773340d773SGleb Smirnoff errno = ENOSPC; 1783340d773SGleb Smirnoff return (NULL); 1793340d773SGleb Smirnoff } 1803340d773SGleb Smirnoff added_space = strlen(dp); 1813340d773SGleb Smirnoff dp += added_space; 1823340d773SGleb Smirnoff space_left -= added_space; 1833340d773SGleb Smirnoff break; 1843340d773SGleb Smirnoff } 1850bff6a5aSEd Maste snprintfed = snprintf (dp, space_left, "%x", words[i]); 1863340d773SGleb Smirnoff if (snprintfed < 0) 1873340d773SGleb Smirnoff return (NULL); 188*0a7e5f1fSJoseph Mingrone if ((size_t) snprintfed >= space_left) { 1893340d773SGleb Smirnoff errno = ENOSPC; 1903340d773SGleb Smirnoff return (NULL); 1913340d773SGleb Smirnoff } 1923340d773SGleb Smirnoff dp += snprintfed; 1933340d773SGleb Smirnoff space_left -= snprintfed; 1943340d773SGleb Smirnoff } 1953340d773SGleb Smirnoff 1963340d773SGleb Smirnoff /* Was it a trailing run of 0x00's? 1973340d773SGleb Smirnoff */ 1983340d773SGleb Smirnoff if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) 1993340d773SGleb Smirnoff APPEND_CHAR(':'); 2003340d773SGleb Smirnoff APPEND_CHAR('\0'); 2013340d773SGleb Smirnoff 2023340d773SGleb Smirnoff return (dst); 2033340d773SGleb Smirnoff } 204