]>
Commit | Line | Data |
---|---|---|
2aa62f2b | 1 | /** @File\r |
2 | Convert a binary network address into a presentable (printable) format.\r | |
3 | \r | |
4 | Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r | |
5 | This program and the accompanying materials are licensed and made available under\r | |
6 | the terms and conditions of the BSD License that accompanies this distribution.\r | |
7 | The full text of the license may be found at\r | |
8 | http://opensource.org/licenses/bsd-license.\r | |
9 | \r | |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
12 | \r | |
13 | * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")\r | |
14 | * Copyright (c) 1996-1999 by Internet Software Consortium.\r | |
15 | *\r | |
16 | * Permission to use, copy, modify, and distribute this software for any\r | |
17 | * purpose with or without fee is hereby granted, provided that the above\r | |
18 | * copyright notice and this permission notice appear in all copies.\r | |
19 | *\r | |
20 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES\r | |
21 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\r | |
22 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR\r | |
23 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r | |
24 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r | |
25 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\r | |
26 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r | |
27 | \r | |
28 | NetBSD: inet_ntop.c,v 1.3.4.2 2007/05/17 21:25:14 jdc Exp\r | |
29 | inet_ntop.c,v 1.3.18.2 2005/11/03 23:02:22 marka Exp\r | |
30 | **/\r | |
31 | #include <LibConfig.h>\r | |
32 | \r | |
33 | //#include "port_before.h"\r | |
34 | \r | |
35 | #include "namespace.h"\r | |
36 | #include <sys/param.h>\r | |
37 | #include <sys/types.h>\r | |
38 | #include <sys/socket.h>\r | |
39 | \r | |
40 | #include <netinet/in.h>\r | |
41 | #include <arpa/inet.h>\r | |
42 | #include <arpa/nameser.h>\r | |
43 | \r | |
44 | #include <assert.h>\r | |
45 | #include <errno.h>\r | |
46 | #include <stdio.h>\r | |
47 | #include <stdlib.h>\r | |
48 | #include <string.h>\r | |
49 | \r | |
50 | //#include "port_after.h"\r | |
51 | \r | |
52 | #ifdef __weak_alias\r | |
53 | __weak_alias(inet_ntop,_inet_ntop)\r | |
54 | #endif\r | |
55 | \r | |
56 | /*%\r | |
57 | * WARNING: Don't even consider trying to compile this on a system where\r | |
58 | * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.\r | |
59 | */\r | |
60 | \r | |
61 | static const char *inet_ntop4(const u_char *src, char *dst, socklen_t size);\r | |
62 | static const char *inet_ntop6(const u_char *src, char *dst, socklen_t size);\r | |
63 | \r | |
64 | /* char *\r | |
65 | * inet_ntop(af, src, dst, size)\r | |
66 | * convert a network format address to presentation format.\r | |
67 | * return:\r | |
68 | * pointer to presentation format address (`dst'), or NULL (see errno).\r | |
69 | * author:\r | |
70 | * Paul Vixie, 1996.\r | |
71 | */\r | |
72 | const char *\r | |
73 | inet_ntop(int af, const void *src, char *dst, socklen_t size)\r | |
74 | {\r | |
75 | \r | |
76 | _DIAGASSERT(src != NULL);\r | |
77 | _DIAGASSERT(dst != NULL);\r | |
78 | \r | |
79 | switch (af) {\r | |
80 | case AF_INET:\r | |
81 | return (inet_ntop4(src, dst, size));\r | |
82 | case AF_INET6:\r | |
83 | return (inet_ntop6(src, dst, size));\r | |
84 | default:\r | |
85 | errno = EAFNOSUPPORT;\r | |
86 | return (NULL);\r | |
87 | }\r | |
88 | /* NOTREACHED */\r | |
89 | }\r | |
90 | \r | |
91 | /* const char *\r | |
92 | * inet_ntop4(src, dst, size)\r | |
93 | * format an IPv4 address, more or less like inet_ntoa()\r | |
94 | * return:\r | |
95 | * `dst' (as a const)\r | |
96 | * notes:\r | |
97 | * (1) uses no statics\r | |
98 | * (2) takes a u_char* not an in_addr as input\r | |
99 | * author:\r | |
100 | * Paul Vixie, 1996.\r | |
101 | */\r | |
102 | static const char *\r | |
103 | inet_ntop4(const u_char *src, char *dst, socklen_t size)\r | |
104 | {\r | |
105 | char tmp[sizeof "255.255.255.255"];\r | |
106 | int l;\r | |
107 | \r | |
108 | _DIAGASSERT(src != NULL);\r | |
109 | _DIAGASSERT(dst != NULL);\r | |
110 | \r | |
111 | l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",\r | |
112 | src[0], src[1], src[2], src[3]);\r | |
113 | if (l <= 0 || (socklen_t) l >= size) {\r | |
114 | errno = ENOSPC;\r | |
115 | return (NULL);\r | |
116 | }\r | |
117 | //strlcpy(dst, tmp, size);\r | |
118 | strncpyX(dst, tmp, (size_t)size);\r | |
119 | return (dst);\r | |
120 | }\r | |
121 | \r | |
122 | /* const char *\r | |
123 | * inet_ntop6(src, dst, size)\r | |
124 | * convert IPv6 binary address into presentation (printable) format\r | |
125 | * author:\r | |
126 | * Paul Vixie, 1996.\r | |
127 | */\r | |
128 | static const char *\r | |
129 | inet_ntop6(const u_char *src, char *dst, socklen_t size)\r | |
130 | {\r | |
131 | /*\r | |
132 | * Note that int32_t and int16_t need only be "at least" large enough\r | |
133 | * to contain a value of the specified size. On some systems, like\r | |
134 | * Crays, there is no such thing as an integer variable with 16 bits.\r | |
135 | * Keep this in mind if you think this function should have been coded\r | |
136 | * to use pointer overlays. All the world's not a VAX.\r | |
137 | */\r | |
138 | char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];\r | |
139 | char *tp, *ep;\r | |
140 | struct { int base, len; } best, cur;\r | |
141 | unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];\r | |
142 | int i;\r | |
143 | int advance;\r | |
144 | \r | |
145 | _DIAGASSERT(src != NULL);\r | |
146 | _DIAGASSERT(dst != NULL);\r | |
147 | \r | |
148 | /*\r | |
149 | * Preprocess:\r | |
150 | * Copy the input (bytewise) array into a wordwise array.\r | |
151 | * Find the longest run of 0x00's in src[] for :: shorthanding.\r | |
152 | */\r | |
153 | memset(words, '\0', sizeof words);\r | |
154 | for (i = 0; i < NS_IN6ADDRSZ; i++)\r | |
155 | words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));\r | |
156 | best.base = -1;\r | |
157 | best.len = 0;\r | |
158 | cur.base = -1;\r | |
159 | cur.len = 0;\r | |
160 | for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {\r | |
161 | if (words[i] == 0) {\r | |
162 | if (cur.base == -1)\r | |
163 | cur.base = i, cur.len = 1;\r | |
164 | else\r | |
165 | cur.len++;\r | |
166 | } else {\r | |
167 | if (cur.base != -1) {\r | |
168 | if (best.base == -1 || cur.len > best.len)\r | |
169 | best = cur;\r | |
170 | cur.base = -1;\r | |
171 | }\r | |
172 | }\r | |
173 | }\r | |
174 | if (cur.base != -1) {\r | |
175 | if (best.base == -1 || cur.len > best.len)\r | |
176 | best = cur;\r | |
177 | }\r | |
178 | if (best.base != -1 && best.len < 2)\r | |
179 | best.base = -1;\r | |
180 | \r | |
181 | /*\r | |
182 | * Format the result.\r | |
183 | */\r | |
184 | tp = tmp;\r | |
185 | ep = tmp + sizeof(tmp);\r | |
186 | for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {\r | |
187 | /* Are we inside the best run of 0x00's? */\r | |
188 | if (best.base != -1 && i >= best.base &&\r | |
189 | i < (best.base + best.len)) {\r | |
190 | if (i == best.base)\r | |
191 | *tp++ = ':';\r | |
192 | continue;\r | |
193 | }\r | |
194 | /* Are we following an initial run of 0x00s or any real hex? */\r | |
195 | if (i != 0) {\r | |
196 | if (tp + 1 >= ep)\r | |
197 | return (NULL);\r | |
198 | *tp++ = ':';\r | |
199 | }\r | |
200 | /* Is this address an encapsulated IPv4? */\r | |
201 | if (i == 6 && best.base == 0 &&\r | |
202 | (best.len == 6 ||\r | |
203 | (best.len == 7 && words[7] != 0x0001) ||\r | |
204 | (best.len == 5 && words[5] == 0xffff))) {\r | |
205 | if (!inet_ntop4(src+12, tp, (socklen_t)(ep - tp)))\r | |
206 | return (NULL);\r | |
207 | tp += strlen(tp);\r | |
208 | break;\r | |
209 | }\r | |
210 | advance = snprintf(tp, (size_t)(ep - tp), "%x", words[i]);\r | |
211 | if (advance <= 0 || advance >= ep - tp)\r | |
212 | return (NULL);\r | |
213 | tp += advance;\r | |
214 | }\r | |
215 | /* Was it a trailing run of 0x00's? */\r | |
216 | if (best.base != -1 && (best.base + best.len) ==\r | |
217 | (NS_IN6ADDRSZ / NS_INT16SZ)) {\r | |
218 | if (tp + 1 >= ep)\r | |
219 | return (NULL);\r | |
220 | *tp++ = ':';\r | |
221 | }\r | |
222 | if (tp + 1 >= ep)\r | |
223 | return (NULL);\r | |
224 | *tp++ = '\0';\r | |
225 | \r | |
226 | /*\r | |
227 | * Check for overflow, copy, and we're done.\r | |
228 | */\r | |
229 | if ((size_t)(tp - tmp) > size) {\r | |
230 | errno = ENOSPC;\r | |
231 | return (NULL);\r | |
232 | }\r | |
233 | //strlcpy(dst, tmp, size);\r | |
234 | strncpyX(dst, tmp, (size_t)size);\r | |
235 | return (dst);\r | |
236 | }\r | |
237 | \r | |
238 | /*! \file */\r |