1*3340d773SGleb Smirnoff /* 2*3340d773SGleb Smirnoff * Copyright (c) 1999 Kungliga Tekniska Högskolan 3*3340d773SGleb Smirnoff * (Royal Institute of Technology, Stockholm, Sweden). 4*3340d773SGleb Smirnoff * All rights reserved. 5*3340d773SGleb Smirnoff * 6*3340d773SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 7*3340d773SGleb Smirnoff * modification, are permitted provided that the following conditions 8*3340d773SGleb Smirnoff * are met: 9*3340d773SGleb Smirnoff * 10*3340d773SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 11*3340d773SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 12*3340d773SGleb Smirnoff * 13*3340d773SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 14*3340d773SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 15*3340d773SGleb Smirnoff * documentation and/or other materials provided with the distribution. 16*3340d773SGleb Smirnoff * 17*3340d773SGleb Smirnoff * 3. All advertising materials mentioning features or use of this software 18*3340d773SGleb Smirnoff * must display the following acknowledgement: 19*3340d773SGleb Smirnoff * This product includes software developed by the Kungliga Tekniska 20*3340d773SGleb Smirnoff * Högskolan and its contributors. 21*3340d773SGleb Smirnoff * 22*3340d773SGleb Smirnoff * 4. Neither the name of the Institute nor the names of its contributors 23*3340d773SGleb Smirnoff * may be used to endorse or promote products derived from this software 24*3340d773SGleb Smirnoff * without specific prior written permission. 25*3340d773SGleb Smirnoff * 26*3340d773SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 27*3340d773SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28*3340d773SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29*3340d773SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 30*3340d773SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31*3340d773SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32*3340d773SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33*3340d773SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34*3340d773SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35*3340d773SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36*3340d773SGleb Smirnoff * SUCH DAMAGE. 37*3340d773SGleb Smirnoff */ 38*3340d773SGleb Smirnoff 39*3340d773SGleb Smirnoff #ifdef HAVE_CONFIG_H 40*3340d773SGleb Smirnoff #include "config.h" 41*3340d773SGleb Smirnoff #endif 42*3340d773SGleb Smirnoff 43*3340d773SGleb Smirnoff #include <netdissect-stdinc.h> 44*3340d773SGleb Smirnoff #include "addrtostr.h" 45*3340d773SGleb Smirnoff 46*3340d773SGleb Smirnoff #include <stdio.h> 47*3340d773SGleb Smirnoff #include <string.h> 48*3340d773SGleb Smirnoff 49*3340d773SGleb Smirnoff /* 50*3340d773SGleb Smirnoff * 51*3340d773SGleb Smirnoff */ 52*3340d773SGleb Smirnoff 53*3340d773SGleb Smirnoff #ifndef IN6ADDRSZ 54*3340d773SGleb Smirnoff #define IN6ADDRSZ 16 /* IPv6 T_AAAA */ 55*3340d773SGleb Smirnoff #endif 56*3340d773SGleb Smirnoff 57*3340d773SGleb Smirnoff #ifndef INT16SZ 58*3340d773SGleb Smirnoff #define INT16SZ 2 /* word size */ 59*3340d773SGleb Smirnoff #endif 60*3340d773SGleb Smirnoff 61*3340d773SGleb Smirnoff const char * 62*3340d773SGleb Smirnoff addrtostr (const void *src, char *dst, size_t size) 63*3340d773SGleb Smirnoff { 64*3340d773SGleb Smirnoff const u_char *srcaddr = (const u_char *)src; 65*3340d773SGleb Smirnoff const char digits[] = "0123456789"; 66*3340d773SGleb Smirnoff int i; 67*3340d773SGleb Smirnoff const char *orig_dst = dst; 68*3340d773SGleb Smirnoff 69*3340d773SGleb Smirnoff if (size < INET_ADDRSTRLEN) { 70*3340d773SGleb Smirnoff errno = ENOSPC; 71*3340d773SGleb Smirnoff return NULL; 72*3340d773SGleb Smirnoff } 73*3340d773SGleb Smirnoff for (i = 0; i < 4; ++i) { 74*3340d773SGleb Smirnoff int n = *srcaddr++; 75*3340d773SGleb Smirnoff int non_zerop = 0; 76*3340d773SGleb Smirnoff 77*3340d773SGleb Smirnoff if (non_zerop || n / 100 > 0) { 78*3340d773SGleb Smirnoff *dst++ = digits[n / 100]; 79*3340d773SGleb Smirnoff n %= 100; 80*3340d773SGleb Smirnoff non_zerop = 1; 81*3340d773SGleb Smirnoff } 82*3340d773SGleb Smirnoff if (non_zerop || n / 10 > 0) { 83*3340d773SGleb Smirnoff *dst++ = digits[n / 10]; 84*3340d773SGleb Smirnoff n %= 10; 85*3340d773SGleb Smirnoff non_zerop = 1; 86*3340d773SGleb Smirnoff } 87*3340d773SGleb Smirnoff *dst++ = digits[n]; 88*3340d773SGleb Smirnoff if (i != 3) 89*3340d773SGleb Smirnoff *dst++ = '.'; 90*3340d773SGleb Smirnoff } 91*3340d773SGleb Smirnoff *dst++ = '\0'; 92*3340d773SGleb Smirnoff return orig_dst; 93*3340d773SGleb Smirnoff } 94*3340d773SGleb Smirnoff 95*3340d773SGleb Smirnoff /* 96*3340d773SGleb Smirnoff * Convert IPv6 binary address into presentation (printable) format. 97*3340d773SGleb Smirnoff */ 98*3340d773SGleb Smirnoff const char * 99*3340d773SGleb Smirnoff addrtostr6 (const void *src, char *dst, size_t size) 100*3340d773SGleb Smirnoff { 101*3340d773SGleb Smirnoff /* 102*3340d773SGleb Smirnoff * Note that int32_t and int16_t need only be "at least" large enough 103*3340d773SGleb Smirnoff * to contain a value of the specified size. On some systems, like 104*3340d773SGleb Smirnoff * Crays, there is no such thing as an integer variable with 16 bits. 105*3340d773SGleb Smirnoff * Keep this in mind if you think this function should have been coded 106*3340d773SGleb Smirnoff * to use pointer overlays. All the world's not a VAX. 107*3340d773SGleb Smirnoff */ 108*3340d773SGleb Smirnoff const u_char *srcaddr = (const u_char *)src; 109*3340d773SGleb Smirnoff char *dp; 110*3340d773SGleb Smirnoff size_t space_left, added_space; 111*3340d773SGleb Smirnoff int snprintfed; 112*3340d773SGleb Smirnoff struct { 113*3340d773SGleb Smirnoff long base; 114*3340d773SGleb Smirnoff long len; 115*3340d773SGleb Smirnoff } best, cur; 116*3340d773SGleb Smirnoff u_long words [IN6ADDRSZ / INT16SZ]; 117*3340d773SGleb Smirnoff int i; 118*3340d773SGleb Smirnoff 119*3340d773SGleb Smirnoff /* Preprocess: 120*3340d773SGleb Smirnoff * Copy the input (bytewise) array into a wordwise array. 121*3340d773SGleb Smirnoff * Find the longest run of 0x00's in src[] for :: shorthanding. 122*3340d773SGleb Smirnoff */ 123*3340d773SGleb Smirnoff memset (words, 0, sizeof(words)); 124*3340d773SGleb Smirnoff for (i = 0; i < IN6ADDRSZ; i++) 125*3340d773SGleb Smirnoff words[i/2] |= (srcaddr[i] << ((1 - (i % 2)) << 3)); 126*3340d773SGleb Smirnoff 127*3340d773SGleb Smirnoff best.len = 0; 128*3340d773SGleb Smirnoff best.base = -1; 129*3340d773SGleb Smirnoff cur.len = 0; 130*3340d773SGleb Smirnoff cur.base = -1; 131*3340d773SGleb Smirnoff for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) 132*3340d773SGleb Smirnoff { 133*3340d773SGleb Smirnoff if (words[i] == 0) 134*3340d773SGleb Smirnoff { 135*3340d773SGleb Smirnoff if (cur.base == -1) 136*3340d773SGleb Smirnoff cur.base = i, cur.len = 1; 137*3340d773SGleb Smirnoff else cur.len++; 138*3340d773SGleb Smirnoff } 139*3340d773SGleb Smirnoff else if (cur.base != -1) 140*3340d773SGleb Smirnoff { 141*3340d773SGleb Smirnoff if (best.base == -1 || cur.len > best.len) 142*3340d773SGleb Smirnoff best = cur; 143*3340d773SGleb Smirnoff cur.base = -1; 144*3340d773SGleb Smirnoff } 145*3340d773SGleb Smirnoff } 146*3340d773SGleb Smirnoff if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) 147*3340d773SGleb Smirnoff best = cur; 148*3340d773SGleb Smirnoff if (best.base != -1 && best.len < 2) 149*3340d773SGleb Smirnoff best.base = -1; 150*3340d773SGleb Smirnoff 151*3340d773SGleb Smirnoff /* Format the result. 152*3340d773SGleb Smirnoff */ 153*3340d773SGleb Smirnoff dp = dst; 154*3340d773SGleb Smirnoff space_left = size; 155*3340d773SGleb Smirnoff #define APPEND_CHAR(c) \ 156*3340d773SGleb Smirnoff { \ 157*3340d773SGleb Smirnoff if (space_left == 0) { \ 158*3340d773SGleb Smirnoff errno = ENOSPC; \ 159*3340d773SGleb Smirnoff return (NULL); \ 160*3340d773SGleb Smirnoff } \ 161*3340d773SGleb Smirnoff *dp++ = c; \ 162*3340d773SGleb Smirnoff space_left--; \ 163*3340d773SGleb Smirnoff } 164*3340d773SGleb Smirnoff for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) 165*3340d773SGleb Smirnoff { 166*3340d773SGleb Smirnoff /* Are we inside the best run of 0x00's? 167*3340d773SGleb Smirnoff */ 168*3340d773SGleb Smirnoff if (best.base != -1 && i >= best.base && i < (best.base + best.len)) 169*3340d773SGleb Smirnoff { 170*3340d773SGleb Smirnoff if (i == best.base) 171*3340d773SGleb Smirnoff APPEND_CHAR(':'); 172*3340d773SGleb Smirnoff continue; 173*3340d773SGleb Smirnoff } 174*3340d773SGleb Smirnoff 175*3340d773SGleb Smirnoff /* Are we following an initial run of 0x00s or any real hex? 176*3340d773SGleb Smirnoff */ 177*3340d773SGleb Smirnoff if (i != 0) 178*3340d773SGleb Smirnoff APPEND_CHAR(':'); 179*3340d773SGleb Smirnoff 180*3340d773SGleb Smirnoff /* Is this address an encapsulated IPv4? 181*3340d773SGleb Smirnoff */ 182*3340d773SGleb Smirnoff if (i == 6 && best.base == 0 && 183*3340d773SGleb Smirnoff (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) 184*3340d773SGleb Smirnoff { 185*3340d773SGleb Smirnoff if (!addrtostr(srcaddr+12, dp, space_left)) 186*3340d773SGleb Smirnoff { 187*3340d773SGleb Smirnoff errno = ENOSPC; 188*3340d773SGleb Smirnoff return (NULL); 189*3340d773SGleb Smirnoff } 190*3340d773SGleb Smirnoff added_space = strlen(dp); 191*3340d773SGleb Smirnoff dp += added_space; 192*3340d773SGleb Smirnoff space_left -= added_space; 193*3340d773SGleb Smirnoff break; 194*3340d773SGleb Smirnoff } 195*3340d773SGleb Smirnoff snprintfed = snprintf (dp, space_left, "%lx", words[i]); 196*3340d773SGleb Smirnoff if (snprintfed < 0) 197*3340d773SGleb Smirnoff return (NULL); 198*3340d773SGleb Smirnoff if ((size_t) snprintfed >= space_left) 199*3340d773SGleb Smirnoff { 200*3340d773SGleb Smirnoff errno = ENOSPC; 201*3340d773SGleb Smirnoff return (NULL); 202*3340d773SGleb Smirnoff } 203*3340d773SGleb Smirnoff dp += snprintfed; 204*3340d773SGleb Smirnoff space_left -= snprintfed; 205*3340d773SGleb Smirnoff } 206*3340d773SGleb Smirnoff 207*3340d773SGleb Smirnoff /* Was it a trailing run of 0x00's? 208*3340d773SGleb Smirnoff */ 209*3340d773SGleb Smirnoff if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) 210*3340d773SGleb Smirnoff APPEND_CHAR(':'); 211*3340d773SGleb Smirnoff APPEND_CHAR('\0'); 212*3340d773SGleb Smirnoff 213*3340d773SGleb Smirnoff return (dst); 214*3340d773SGleb Smirnoff } 215