]> git.saurik.com Git - apple/libc.git/blob - net/inet_ntop.c
Libc-1082.50.1.tar.gz
[apple/libc.git] / net / inet_ntop.c
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
14 static const char *hexchars = "0123456789abcdef";
15
16 const char *
17 inet_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
153 const char *
154 inet_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
198 const char *
199 inet_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 }