]> git.saurik.com Git - apple/xnu.git/blob - bsd/libkern/inet_ntop.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / bsd / libkern / inet_ntop.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30
31 /*
32 * Copyright 1994, 1995 Massachusetts Institute of Technology
33 *
34 * Permission to use, copy, modify, and distribute this software and
35 * its documentation for any purpose and without fee is hereby
36 * granted, provided that both the above copyright notice and this
37 * permission notice appear in all copies, that both the above
38 * copyright notice and this permission notice appear in all
39 * supporting documentation, and that the name of M.I.T. not be used
40 * in advertising or publicity pertaining to distribution of the
41 * software without specific, written prior permission. M.I.T. makes
42 * no representations about the suitability of this software for any
43 * purpose. It is provided "as is" without express or implied
44 * warranty.
45 *
46 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
47 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
48 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
49 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
50 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
53 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59
60 #include <sys/param.h>
61 #include <sys/systm.h>
62
63 #include <netinet/in.h>
64
65 static const char *hexchars = "0123456789abcdef";
66
67 static const char *
68 inet_ntop4(const struct in_addr *addr, char *buf, size_t len)
69 {
70 const u_int8_t *ap = (const u_int8_t *)&addr->s_addr;
71 char tmp[MAX_IPv4_STR_LEN]; /* max length of ipv4 addr string */
72 int fulllen;
73
74 /*
75 * snprintf returns number of bytes printed (not including NULL) or
76 * number of bytes that would have been printed if more than would
77 * fit
78 */
79 fulllen = snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
80 ap[0], ap[1], ap[2], ap[3]);
81 if (fulllen >= (int)len) {
82 return NULL;
83 }
84
85 bcopy(tmp, buf, fulllen + 1);
86
87 return buf;
88 }
89
90 static const char *
91 inet_ntop6(const struct in6_addr *addr, char *dst, size_t size)
92 {
93 char hexa[8][5], tmp[MAX_IPv6_STR_LEN];
94 int zr[8];
95 size_t len;
96 int32_t i, j, k, skip;
97 uint8_t x8, hx8;
98 uint16_t x16;
99 struct in_addr a4;
100
101 if (addr == NULL) return NULL;
102
103 bzero(tmp, sizeof(tmp));
104
105 /* check for mapped or compat addresses */
106 i = IN6_IS_ADDR_V4MAPPED(addr);
107 j = IN6_IS_ADDR_V4COMPAT(addr);
108 if ((i != 0) || (j != 0))
109 {
110 char tmp2[16]; /* max length of ipv4 addr string */
111 a4.s_addr = addr->__u6_addr.__u6_addr32[3];
112 len = snprintf(tmp, sizeof(tmp), "::%s%s", (i != 0) ? "ffff:" : "",
113 inet_ntop4(&a4, tmp2, sizeof(tmp2)));
114 if (len >= size) return NULL;
115 bcopy(tmp, dst, len + 1);
116 return dst;
117 }
118
119 k = 0;
120 for (i = 0; i < 16; i += 2)
121 {
122 j = 0;
123 skip = 1;
124
125 bzero(hexa[k], 5);
126
127 x8 = addr->__u6_addr.__u6_addr8[i];
128
129 hx8 = x8 >> 4;
130 if (hx8 != 0)
131 {
132 skip = 0;
133 hexa[k][j++] = hexchars[hx8];
134 }
135
136 hx8 = x8 & 0x0f;
137 if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
138 {
139 skip = 0;
140 hexa[k][j++] = hexchars[hx8];
141 }
142
143 x8 = addr->__u6_addr.__u6_addr8[i + 1];
144
145 hx8 = x8 >> 4;
146 if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
147 {
148 hexa[k][j++] = hexchars[hx8];
149 }
150
151 hx8 = x8 & 0x0f;
152 hexa[k][j++] = hexchars[hx8];
153
154 k++;
155 }
156
157 /* find runs of zeros for :: convention */
158 j = 0;
159 for (i = 7; i >= 0; i--)
160 {
161 zr[i] = j;
162 x16 = addr->__u6_addr.__u6_addr16[i];
163 if (x16 == 0) j++;
164 else j = 0;
165 zr[i] = j;
166 }
167
168 /* find longest run of zeros */
169 k = -1;
170 j = 0;
171 for(i = 0; i < 8; i++)
172 {
173 if (zr[i] > j)
174 {
175 k = i;
176 j = zr[i];
177 }
178 }
179
180 for(i = 0; i < 8; i++)
181 {
182 if (i != k) zr[i] = 0;
183 }
184
185 len = 0;
186 for (i = 0; i < 8; i++)
187 {
188 if (zr[i] != 0)
189 {
190 /* check for leading zero */
191 if (i == 0) tmp[len++] = ':';
192 tmp[len++] = ':';
193 i += (zr[i] - 1);
194 continue;
195 }
196 for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j];
197 if (i != 7) tmp[len++] = ':';
198 }
199
200 /* trailing NULL */
201 len++;
202
203 if (len > size) return NULL;
204 bcopy(tmp, dst, len);
205 return dst;
206 }
207
208 const char *
209 inet_ntop(int af, const void *addr, char *buf, size_t len)
210 {
211 if(af==AF_INET6)
212 return inet_ntop6(addr, buf, len);
213 if(af==AF_INET)
214 return inet_ntop4(addr, buf, len);
215 return NULL;
216 }