]>
Commit | Line | Data |
---|---|---|
974e3884 A |
1 | /* |
2 | * Copyright (c) 2003,2005,2006,2011,2012 Apple, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
507116e3 A |
23 | /* |
24 | * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") | |
25 | * Copyright (c) 1996-1999 by Internet Software Consortium. | |
26 | * | |
27 | * Permission to use, copy, modify, and distribute this software for any | |
28 | * purpose with or without fee is hereby granted, provided that the above | |
29 | * copyright notice and this permission notice appear in all copies. | |
30 | * | |
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES | |
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR | |
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
37 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
38 | */ | |
6465356a | 39 | |
6465356a | 40 | #include <arpa/inet.h> |
507116e3 A |
41 | #include <arpa/nameser.h> |
42 | #include <errno.h> | |
43 | #include <netinet/in.h> | |
6465356a | 44 | #include <stdint.h> |
507116e3 | 45 | #include <stdio.h> |
6465356a | 46 | #include <string.h> |
6465356a | 47 | #include <sys/socket.h> |
507116e3 | 48 | #include <sys/types.h> |
70ad1dc8 | 49 | |
6465356a | 50 | #define MAX_V4_ADDR_LEN 16 |
6465356a | 51 | |
974e3884 A |
52 | const char * inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size); |
53 | const char * inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size); | |
54 | ||
55 | const char * | |
56 | inet_ntop(int af, const void *addr, char *buf, socklen_t len) | |
57 | { | |
507116e3 A |
58 | if (addr && af == AF_INET6) return inet_ntop6(addr, buf, len); |
59 | if (addr && af == AF_INET) return inet_ntop4(addr, buf, len); | |
974e3884 A |
60 | |
61 | errno = EAFNOSUPPORT; | |
62 | return NULL; | |
63 | } | |
64 | ||
507116e3 A |
65 | /* const char * |
66 | * inet_ntop6(src, dst, size) | |
67 | * convert IPv6 binary address into presentation (printable) format | |
68 | * author: | |
69 | * Paul Vixie, 1996. | |
70 | */ | |
6465356a A |
71 | const char * |
72 | inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) | |
73 | { | |
507116e3 A |
74 | const u_char *src = addr->__u6_addr.__u6_addr8; |
75 | /* | |
76 | * Note that int32_t and int16_t need only be "at least" large enough | |
77 | * to contain a value of the specified size. On some systems, like | |
78 | * Crays, there is no such thing as an integer variable with 16 bits. | |
79 | * Keep this in mind if you think this function should have been coded | |
80 | * to use pointer overlays. All the world's not a VAX. | |
81 | */ | |
82 | char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; | |
83 | struct { int base, len; } best, cur; | |
84 | u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; | |
85 | int i; | |
86 | ||
87 | /* | |
88 | * Preprocess: | |
89 | * Copy the input (bytewise) array into a wordwise array. | |
90 | * Find the longest run of 0x00's in src[] for :: shorthanding. | |
91 | */ | |
92 | memset(words, '\0', sizeof words); | |
93 | for (i = 0; i < NS_IN6ADDRSZ; i++) | |
94 | words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); | |
95 | best.base = -1; | |
96 | best.len = 0; | |
97 | cur.base = -1; | |
98 | cur.len = 0; | |
99 | for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { | |
100 | if (words[i] == 0) { | |
101 | if (cur.base == -1) { | |
102 | cur.base = i; | |
103 | cur.len = 1; | |
104 | } else { | |
105 | cur.len++; | |
106 | } | |
974e3884 | 107 | } else { |
507116e3 A |
108 | if (cur.base != -1) { |
109 | if (best.base == -1 || cur.len > best.len) | |
110 | best = cur; | |
111 | cur.base = -1; | |
112 | } | |
6465356a A |
113 | } |
114 | } | |
507116e3 A |
115 | if (cur.base != -1) { |
116 | if (best.base == -1 || cur.len > best.len) | |
117 | best = cur; | |
6465356a | 118 | } |
507116e3 A |
119 | if (best.base != -1 && best.len < 2) |
120 | best.base = -1; | |
121 | ||
122 | /* | |
123 | * Format the result. | |
124 | */ | |
125 | tp = tmp; | |
126 | for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { | |
127 | /* Are we inside the best run of 0x00's? */ | |
128 | if (best.base != -1 && i >= best.base && | |
129 | i < (best.base + best.len)) { | |
130 | if (i == best.base) | |
131 | *tp++ = ':'; | |
6465356a A |
132 | continue; |
133 | } | |
507116e3 A |
134 | /* Are we following an initial run of 0x00s or any real hex? */ |
135 | if (i != 0) | |
136 | *tp++ = ':'; | |
137 | /* Is this address an encapsulated IPv4? */ | |
138 | if (i == 6 && best.base == 0 && (best.len == 6 || | |
139 | (best.len == 7 && words[7] != 0x0001) || | |
140 | (best.len == 5 && words[5] == 0xffff))) { | |
141 | struct in_addr ipv4_addr; | |
142 | memcpy(&ipv4_addr, src+12, sizeof(ipv4_addr)); | |
143 | if (!inet_ntop4(&ipv4_addr, tp, (socklen_t)sizeof(tmp) - (socklen_t)(tp - tmp))) { | |
144 | errno = ENOSPC; | |
145 | return (NULL); | |
146 | } | |
147 | tp += strlen(tp); | |
148 | break; | |
149 | } | |
150 | tp += sprintf(tp, "%x", words[i]); | |
6465356a | 151 | } |
507116e3 A |
152 | /* Was it a trailing run of 0x00's? */ |
153 | if (best.base != -1 && (best.base + best.len) == | |
154 | (NS_IN6ADDRSZ / NS_INT16SZ)) | |
155 | *tp++ = ':'; | |
156 | *tp++ = '\0'; | |
157 | ||
158 | /* | |
159 | * Check for overflow, copy, and we're done. | |
160 | */ | |
161 | if ((socklen_t)(tp - tmp) > size) { | |
6465356a | 162 | errno = ENOSPC; |
507116e3 | 163 | return (NULL); |
6465356a | 164 | } |
507116e3 A |
165 | strcpy(dst, tmp); |
166 | return (dst); | |
6465356a A |
167 | } |
168 | ||
169 | const char * | |
170 | inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) | |
171 | { | |
172 | char tmp[MAX_V4_ADDR_LEN], *p; | |
173 | const u_int8_t *ap = (u_int8_t *)&addr->s_addr; | |
507116e3 A |
174 | int i; |
175 | size_t ql, len; | |
6465356a | 176 | |
507116e3 | 177 | if (addr == NULL) { |
6465356a A |
178 | errno = EAFNOSUPPORT; |
179 | return NULL; | |
180 | } | |
181 | ||
507116e3 | 182 | if (dst == NULL) { |
6465356a A |
183 | errno = ENOSPC; |
184 | return NULL; | |
185 | } | |
186 | ||
187 | memset(tmp, 0, MAX_V4_ADDR_LEN); | |
188 | ||
189 | /* 3 dots, trailing nul */ | |
190 | len = 4; | |
191 | ||
192 | p = tmp; | |
193 | ||
507116e3 | 194 | for (i = 0; i < 4; i++, ap++) { |
6465356a A |
195 | snprintf(p, 4, "%d", *ap); |
196 | ql = strlen(p); | |
197 | len += ql; | |
198 | p += ql; | |
199 | if (i < 3) *p++ = '.'; | |
200 | } | |
201 | ||
507116e3 | 202 | if (len > size) { |
6465356a A |
203 | errno = ENOSPC; |
204 | return NULL; | |
205 | } | |
206 | ||
207 | memcpy(dst, tmp, len); | |
208 | return dst; | |
209 | } |