1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18: #if defined(LIBC_SCCS) && !defined(lint)
19: static const char rcsid[] = "$BINDId: inet_ntop.c,v 1.8 1999/10/13 16:39:28 vixie Exp $";
20: #endif
21:
22: #include <sys/param.h>
23: #include <sys/types.h>
24: #include <sys/socket.h>
25:
26: #include <netinet/in.h>
27: #include <arpa/inet.h>
28: #include <arpa/nameser.h>
29:
30: #include <errno.h>
31: #include <stdio.h>
32: #include <string.h>
33:
34: #ifdef SPRINTF_CHAR
35: # define SPRINTF(x) strlen(sprintfx)
36: #else
37: # define SPRINTF(x) ((size_t)sprintf x)
38: #endif
39:
40:
41:
42:
43:
44:
45: static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size)
46: internal_function;
47: static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size)
48: internal_function;
49:
50:
51:
52:
53:
54:
55:
56:
57:
58: const char *
59: inet_ntop(af, src, dst, size)
60: int af;
61: const void *src;
62: char *dst;
63: socklen_t size;
64: {
65: switch (af) {
66: case AF_INET:
67: return (inet_ntop4(src, dst, size));
68: case AF_INET6:
69: return (inet_ntop6(src, dst, size));
70: default:
71: __set_errno (EAFNOSUPPORT);
72: return (NULL);
73: }
74:
75: }
76: libc_hidden_def (inet_ntop)
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89: static const char *
90: internal_function
91: inet_ntop4(src, dst, size)
92: const u_char *src;
93: char *dst;
94: socklen_t size;
95: {
96: static const char fmt[] = "%u.%u.%u.%u";
97: char tmp[sizeof "255.255.255.255"];
98:
99: if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) {
100: __set_errno (ENOSPC);
101: return (NULL);
102: }
103: return strcpy(dst, tmp);
104: }
105:
106:
107:
108:
109:
110:
111:
112: static const char *
113: internal_function
114: inet_ntop6(src, dst, size)
115: const u_char *src;
116: char *dst;
117: socklen_t size;
118: {
119:
120:
121:
122:
123:
124:
125:
126: char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
127: struct { int base, len; } best, cur;
128: u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
129: int i;
130:
131:
132:
133:
134:
135:
136: memset(words, '\0', sizeof words);
137: for (i = 0; i < NS_IN6ADDRSZ; i += 2)
138: words[i / 2] = (src[i] << 8) | src[i + 1];
139: best.base = -1;
140: cur.base = -1;
141: best.len = 0;
142: cur.len = 0;
143: for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
144: if (words[i] == 0) {
145: if (cur.base == -1)
146: cur.base = i, cur.len = 1;
147: else
148: cur.len++;
149: } else {
150: if (cur.base != -1) {
151: if (best.base == -1 || cur.len > best.len)
152: best = cur;
153: cur.base = -1;
154: }
155: }
156: }
157: if (cur.base != -1) {
158: if (best.base == -1 || cur.len > best.len)
159: best = cur;
160: }
161: if (best.base != -1 && best.len < 2)
162: best.base = -1;
163:
164:
165:
166:
167: tp = tmp;
168: for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
169:
170: if (best.base != -1 && i >= best.base &&
171: i < (best.base + best.len)) {
172: if (i == best.base)
173: *tp++ = ':';
174: continue;
175: }
176:
177: if (i != 0)
178: *tp++ = ':';
179:
180: if (i == 6 && best.base == 0 &&
181: (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
182: if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
183: return (NULL);
184: tp += strlen(tp);
185: break;
186: }
187: tp += SPRINTF((tp, "%x", words[i]));
188: }
189:
190: if (best.base != -1 && (best.base + best.len) ==
191: (NS_IN6ADDRSZ / NS_INT16SZ))
192: *tp++ = ':';
193: *tp++ = '\0';
194:
195:
196:
197:
198: if ((socklen_t)(tp - tmp) > size) {
199: __set_errno (ENOSPC);
200: return (NULL);
201: }
202: return strcpy(dst, tmp);
203: }