1 2#include <sys/types.h> 3#include <netinet/in.h> 4#include <arpa/inet.h> 5#include <stdio.h> 6#include <stdint.h> 7#include <string.h> 8#include <errno.h> 9#include <sys/socket.h> 10 11#define MAX_V4_ADDR_LEN 16 12#define MAX_V6_ADDR_LEN 64 13 14static const char *hexchars = "0123456789abcdef"; 15 16const char * 17inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) 18{ 19 char hexa[8][5], tmp[MAX_V6_ADDR_LEN]; 20 int zr[8]; 21 socklen_t len; 22 int32_t i, j, k, skip; 23 uint8_t x8, hx8; 24 uint16_t x16; 25 struct in_addr a4; 26 27 if (addr == NULL) 28 { 29 errno = EAFNOSUPPORT; 30 return NULL; 31 } 32 33 if (dst == NULL) 34 { 35 errno = ENOSPC; 36 return NULL; 37 } 38 39 memset(tmp, 0, MAX_V6_ADDR_LEN); 40 41 /* check for mapped or compat addresses */ 42 i = IN6_IS_ADDR_V4MAPPED(addr); 43 j = IN6_IS_ADDR_V4COMPAT(addr); 44 if ((i != 0) || (j != 0)) 45 { 46 a4.s_addr = addr->__u6_addr.__u6_addr32[3]; 47 sprintf(tmp, "::%s%s", (i != 0) ? "ffff:" : "", inet_ntoa(a4)); 48 len = strlen(tmp) + 1; 49 if (len > size) 50 { 51 errno = ENOSPC; 52 return NULL; 53 } 54 55 memcpy(dst, tmp, len); 56 return dst; 57 } 58 59 k = 0; 60 for (i = 0; i < 16; i += 2) 61 { 62 j = 0; 63 skip = 1; 64 65 memset(hexa[k], 0, 5); 66 67 x8 = addr->__u6_addr.__u6_addr8[i]; 68 69 hx8 = x8 >> 4; 70 if (hx8 != 0) 71 { 72 skip = 0; 73 hexa[k][j++] = hexchars[hx8]; 74 } 75 76 hx8 = x8 & 0x0f; 77 if ((skip == 0) || ((skip == 1) && (hx8 != 0))) 78 { 79 skip = 0; 80 hexa[k][j++] = hexchars[hx8]; 81 } 82 83 x8 = addr->__u6_addr.__u6_addr8[i + 1]; 84 85 hx8 = x8 >> 4; 86 if ((skip == 0) || ((skip == 1) && (hx8 != 0))) 87 { 88 hexa[k][j++] = hexchars[hx8]; 89 } 90 91 hx8 = x8 & 0x0f; 92 hexa[k][j++] = hexchars[hx8]; 93 94 k++; 95 } 96 97 /* find runs of zeros for :: convention */ 98 j = 0; 99 for (i = 7; i >= 0; i--) 100 { 101 zr[i] = j; 102 x16 = addr->__u6_addr.__u6_addr16[i]; 103 if (x16 == 0) j++; 104 else j = 0; 105 zr[i] = j; 106 } 107 108 /* find longest run of zeros */ 109 k = -1; 110 j = 0; 111 for(i = 0; i < 8; i++) 112 { 113 if (zr[i] > j) 114 { 115 k = i; 116 j = zr[i]; 117 } 118 } 119 120 for(i = 0; i < 8; i++) 121 { 122 if (i != k) zr[i] = 0; 123 } 124 125 len = 0; 126 for (i = 0; i < 8; i++) 127 { 128 if (zr[i] != 0) 129 { 130 /* check for leading zero */ 131 if (i == 0) tmp[len++] = ':'; 132 tmp[len++] = ':'; 133 i += (zr[i] - 1); 134 continue; 135 } 136 for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j]; 137 if (i != 7) tmp[len++] = ':'; 138 } 139 140 /* trailing NULL */ 141 len++; 142 143 if (len > size) 144 { 145 errno = ENOSPC; 146 return NULL; 147 } 148 149 memcpy(dst, tmp, len); 150 return dst; 151} 152 153const char * 154inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) 155{ 156 char tmp[MAX_V4_ADDR_LEN], *p; 157 const u_int8_t *ap = (u_int8_t *)&addr->s_addr; 158 int i, ql, len; 159 160 if (addr == NULL) 161 { 162 errno = EAFNOSUPPORT; 163 return NULL; 164 } 165 166 if (dst == NULL) 167 { 168 errno = ENOSPC; 169 return NULL; 170 } 171 172 memset(tmp, 0, MAX_V4_ADDR_LEN); 173 174 /* 3 dots, trailing nul */ 175 len = 4; 176 177 p = tmp; 178 179 for (i = 0; i < 4; i++, ap++) 180 { 181 snprintf(p, 4, "%d", *ap); 182 ql = strlen(p); 183 len += ql; 184 p += ql; 185 if (i < 3) *p++ = '.'; 186 } 187 188 if (len > size) 189 { 190 errno = ENOSPC; 191 return NULL; 192 } 193 194 memcpy(dst, tmp, len); 195 return dst; 196} 197 198const char * 199inet_ntop(int af, const void *addr, char *buf, socklen_t len) 200{ 201 if (af == AF_INET6) return inet_ntop6(addr, buf, len); 202 if (af == AF_INET) return inet_ntop4(addr, buf, len); 203 204 errno = EAFNOSUPPORT; 205 return NULL; 206} 207