]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/NetUtil/inet_ntop.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / StdLib / LibC / NetUtil / inet_ntop.c
CommitLineData
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
61static const char *inet_ntop4(const u_char *src, char *dst, socklen_t size);\r
62static 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
72const char *\r
73inet_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
102static const char *\r
103inet_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
128static const char *\r
129inet_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