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