2 * Copyright (c) 2009 Intel Corp., Inc.
\r
4 * This software is available to you under a choice of one of two
\r
5 * licenses. You may choose to be licensed under the terms of the GNU
\r
6 * General Public License (GPL) Version 2, available from the file
\r
7 * COPYING in the main directory of this source tree, or the
\r
8 * OpenIB.org BSD license below:
\r
10 * Redistribution and use in source and binary forms, with or
\r
11 * without modification, are permitted provided that the following
\r
12 * conditions are met:
\r
14 * - Redistributions of source code must retain the above
\r
15 * copyright notice, this list of conditions and the following
\r
18 * - Redistributions in binary form must reproduce the above
\r
19 * copyright notice, this list of conditions and the following
\r
20 * disclaimer in the documentation and/or other materials
\r
21 * provided with the distribution.
\r
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
34 #include <arpa/inet.h>
\r
38 static int inet_pton4(const char *src, struct in_addr *addr)
\r
42 ip = inet_addr(src);
\r
43 if (ip == INADDR_NONE)
\r
46 addr->S_un.S_addr = ip;
\r
50 enum in6_addr_format_state
\r
58 static int inet_check_groups(const char *src)
\r
61 int digits = 0, groups = 0;
\r
62 enum in6_addr_format_state state;
\r
64 if (src[0] == ':') {
\r
65 if (src[1] == ':') {
\r
67 state = in6_fs_0_colon;
\r
76 for (; src[i] != '\0'; i++) {
\r
77 if (src[i] == ':') {
\r
81 state = in6_fs_colon;
\r
85 state = in6_fs_0_colon;
\r
92 } else if (isxdigit(src[i]) && digits++ < 4) {
\r
99 case in6_fs_0_colon:
\r
100 state = in6_fs_0_num;
\r
111 if (groups > 8 || state == in6_fs_colon)
\r
118 * We don't handle the format x:x:x:x:x:x:d.d.d.d
\r
120 static int inet_pton6(const char *src, struct in6_addr *addr)
\r
125 skip = 8 - inet_check_groups(src);
\r
129 memset(addr, 0, sizeof(*addr));
\r
130 if (src[0] == ':') {
\r
138 for (; i < 8; i++) {
\r
139 addr->u.Word[i] = htons((u_short) strtoul(pos, (char **) &pos, 16));
\r
151 int inet_pton(int af, const char *src, void *dst)
\r
155 return inet_pton4(src, (struct in_addr *) dst);
\r
157 return inet_pton6(src, (struct in6_addr *) dst);
\r
164 static const char *inet_ntop4(const void *src, char *dst, socklen_t cnt)
\r
166 struct sockaddr_in in;
\r
168 in.sin_family = AF_INET;
\r
169 memcpy(&in.sin_addr, src, 4);
\r
170 if (getnameinfo((struct sockaddr *) &in,
\r
171 (socklen_t) sizeof(struct sockaddr_in),
\r
172 dst, cnt, NULL, 0, NI_NUMERICHOST))
\r
178 static const char *inet_ntop6(const void *src, char *dst, socklen_t cnt)
\r
180 struct sockaddr_in6 in6;
\r
181 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
\r
184 memset(&in6, 0, sizeof in6);
\r
185 in6.sin6_family = AF_INET6;
\r
186 memcpy(&in6.sin6_addr, src, sizeof(struct in_addr6));
\r
189 * If no ipv6 support return simple IPv6 format rule:
\r
190 * A series of "0's in a 16bit block can be represented by "0"
\r
192 if (getnameinfo((struct sockaddr *) &in6, (socklen_t) (sizeof in6),
\r
193 dst, cnt, NULL, 0, NI_NUMERICHOST))
\r
196 if (cnt < sizeof(tmp))
\r
199 for (i = 0; i < 8; i++)
\r
200 n += sprintf(tmp+n, "%s%x", i ? ":" : "",
\r
201 ntohs(((unsigned short*) src)[i]));
\r
209 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
\r
213 return inet_ntop4(src, dst, cnt);
\r
215 return inet_ntop6(src, dst, cnt);
\r