156893Sfenner/* 256893Sfenner * Copyright (c) 1999 Kungliga Tekniska H�gskolan 356893Sfenner * (Royal Institute of Technology, Stockholm, Sweden). 456893Sfenner * All rights reserved. 5127668Sbms * 656893Sfenner * Redistribution and use in source and binary forms, with or without 756893Sfenner * modification, are permitted provided that the following conditions 856893Sfenner * are met: 9127668Sbms * 1056893Sfenner * 1. Redistributions of source code must retain the above copyright 1156893Sfenner * notice, this list of conditions and the following disclaimer. 12127668Sbms * 1356893Sfenner * 2. Redistributions in binary form must reproduce the above copyright 1456893Sfenner * notice, this list of conditions and the following disclaimer in the 1556893Sfenner * documentation and/or other materials provided with the distribution. 16127668Sbms * 1756893Sfenner * 3. All advertising materials mentioning features or use of this software 1856893Sfenner * must display the following acknowledgement: 1956893Sfenner * This product includes software developed by the Kungliga Tekniska 2056893Sfenner * H�gskolan and its contributors. 21127668Sbms * 2256893Sfenner * 4. Neither the name of the Institute nor the names of its contributors 2356893Sfenner * may be used to endorse or promote products derived from this software 2456893Sfenner * without specific prior written permission. 25127668Sbms * 2656893Sfenner * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2756893Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2856893Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2956893Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 3056893Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3156893Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3256893Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3356893Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3456893Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3556893Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3656893Sfenner * SUCH DAMAGE. 3756893Sfenner */ 3856893Sfenner 39190207Srpaulo/* $Id: inet_ntop.c,v 1.8 2005-02-09 02:25:46 guy Exp $ */ 4056893Sfenner 4156893Sfenner#ifndef lint 42127668Sbmsstatic const char rcsid[] _U_ = 43190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_ntop.c,v 1.8 2005-02-09 02:25:46 guy Exp $"; 4456893Sfenner#endif 4556893Sfenner 46127668Sbms#include <tcpdump-stdinc.h> 47127668Sbms 4856893Sfenner#include <stdio.h> 4956893Sfenner#include <errno.h> 5056893Sfenner 5156893Sfenner/* 5256893Sfenner * 5356893Sfenner */ 5456893Sfenner 55146775Ssam#ifndef IN6ADDRSZ 56146775Ssam#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ 5756893Sfenner#endif 5856893Sfenner 59146775Ssam#ifndef INT16SZ 60146775Ssam#define INT16SZ 2 /* word size */ 61146775Ssam#endif 62146775Ssam 6356893Sfennerstatic const char * 6456893Sfennerinet_ntop_v4 (const void *src, char *dst, size_t size) 6556893Sfenner{ 6656893Sfenner const char digits[] = "0123456789"; 6756893Sfenner int i; 6856893Sfenner struct in_addr *addr = (struct in_addr *)src; 6956893Sfenner u_long a = ntohl(addr->s_addr); 7056893Sfenner const char *orig_dst = dst; 7156893Sfenner 7256893Sfenner if (size < INET_ADDRSTRLEN) { 7356893Sfenner errno = ENOSPC; 7456893Sfenner return NULL; 7556893Sfenner } 7656893Sfenner for (i = 0; i < 4; ++i) { 7756893Sfenner int n = (a >> (24 - i * 8)) & 0xFF; 7856893Sfenner int non_zerop = 0; 7956893Sfenner 8056893Sfenner if (non_zerop || n / 100 > 0) { 8156893Sfenner *dst++ = digits[n / 100]; 8256893Sfenner n %= 100; 8356893Sfenner non_zerop = 1; 8456893Sfenner } 8556893Sfenner if (non_zerop || n / 10 > 0) { 8656893Sfenner *dst++ = digits[n / 10]; 8756893Sfenner n %= 10; 8856893Sfenner non_zerop = 1; 8956893Sfenner } 9056893Sfenner *dst++ = digits[n]; 9156893Sfenner if (i != 3) 9256893Sfenner *dst++ = '.'; 9356893Sfenner } 9456893Sfenner *dst++ = '\0'; 9556893Sfenner return orig_dst; 9656893Sfenner} 9756893Sfenner 98146775Ssam#ifdef INET6 99146775Ssam/* 100146775Ssam * Convert IPv6 binary address into presentation (printable) format. 101146775Ssam */ 102146775Ssamstatic const char * 103146775Ssaminet_ntop_v6 (const u_char *src, char *dst, size_t size) 104146775Ssam{ 105146775Ssam /* 106146775Ssam * Note that int32_t and int16_t need only be "at least" large enough 107146775Ssam * to contain a value of the specified size. On some systems, like 108146775Ssam * Crays, there is no such thing as an integer variable with 16 bits. 109146775Ssam * Keep this in mind if you think this function should have been coded 110146775Ssam * to use pointer overlays. All the world's not a VAX. 111146775Ssam */ 112146775Ssam char tmp [INET6_ADDRSTRLEN+1]; 113146775Ssam char *tp; 114146775Ssam struct { 115146775Ssam long base; 116146775Ssam long len; 117146775Ssam } best, cur; 118146775Ssam u_long words [IN6ADDRSZ / INT16SZ]; 119146775Ssam int i; 120146775Ssam 121146775Ssam /* Preprocess: 122146775Ssam * Copy the input (bytewise) array into a wordwise array. 123146775Ssam * Find the longest run of 0x00's in src[] for :: shorthanding. 124146775Ssam */ 125146775Ssam memset (words, 0, sizeof(words)); 126146775Ssam for (i = 0; i < IN6ADDRSZ; i++) 127146775Ssam words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); 128146775Ssam 129146775Ssam best.base = -1; 130146775Ssam cur.base = -1; 131146775Ssam for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) 132146775Ssam { 133146775Ssam if (words[i] == 0) 134146775Ssam { 135146775Ssam if (cur.base == -1) 136146775Ssam cur.base = i, cur.len = 1; 137146775Ssam else cur.len++; 138146775Ssam } 139146775Ssam else if (cur.base != -1) 140146775Ssam { 141146775Ssam if (best.base == -1 || cur.len > best.len) 142146775Ssam best = cur; 143146775Ssam cur.base = -1; 144146775Ssam } 145146775Ssam } 146146775Ssam if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) 147146775Ssam best = cur; 148146775Ssam if (best.base != -1 && best.len < 2) 149146775Ssam best.base = -1; 150146775Ssam 151146775Ssam /* Format the result. 152146775Ssam */ 153146775Ssam tp = tmp; 154146775Ssam for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) 155146775Ssam { 156146775Ssam /* Are we inside the best run of 0x00's? 157146775Ssam */ 158146775Ssam if (best.base != -1 && i >= best.base && i < (best.base + best.len)) 159146775Ssam { 160146775Ssam if (i == best.base) 161146775Ssam *tp++ = ':'; 162146775Ssam continue; 163146775Ssam } 164146775Ssam 165146775Ssam /* Are we following an initial run of 0x00s or any real hex? 166146775Ssam */ 167146775Ssam if (i != 0) 168146775Ssam *tp++ = ':'; 169146775Ssam 170146775Ssam /* Is this address an encapsulated IPv4? 171146775Ssam */ 172146775Ssam if (i == 6 && best.base == 0 && 173146775Ssam (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) 174146775Ssam { 175146775Ssam if (!inet_ntop_v4(src+12, tp, sizeof(tmp) - (tp - tmp))) 176146775Ssam { 177146775Ssam errno = ENOSPC; 178146775Ssam return (NULL); 179146775Ssam } 180146775Ssam tp += strlen(tp); 181146775Ssam break; 182146775Ssam } 183146775Ssam tp += sprintf (tp, "%lX", words[i]); 184146775Ssam } 185146775Ssam 186146775Ssam /* Was it a trailing run of 0x00's? 187146775Ssam */ 188146775Ssam if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) 189146775Ssam *tp++ = ':'; 190146775Ssam *tp++ = '\0'; 191146775Ssam 192146775Ssam /* Check for overflow, copy, and we're done. 193146775Ssam */ 194146775Ssam if ((size_t)(tp - tmp) > size) 195146775Ssam { 196146775Ssam errno = ENOSPC; 197146775Ssam return (NULL); 198146775Ssam } 199146775Ssam return strcpy (dst, tmp); 200146775Ssam return (NULL); 201146775Ssam} 202146775Ssam#endif /* INET6 */ 203146775Ssam 204146775Ssam 20556893Sfennerconst char * 20656893Sfennerinet_ntop(int af, const void *src, char *dst, size_t size) 20756893Sfenner{ 20856893Sfenner switch (af) { 20956893Sfenner case AF_INET : 21056893Sfenner return inet_ntop_v4 (src, dst, size); 211146775Ssam#ifdef INET6 212146775Ssam case AF_INET6: 213146775Ssam return inet_ntop_v6 ((const u_char*)src, dst, size); 214146775Ssam#endif 21556893Sfenner default : 21656893Sfenner errno = EAFNOSUPPORT; 21756893Sfenner return NULL; 21856893Sfenner } 21956893Sfenner} 220