1*632aef92SSepherosa Ziehau /*
2*632aef92SSepherosa Ziehau * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3*632aef92SSepherosa Ziehau * Copyright (c) 1996-1999 by Internet Software Consortium.
4*632aef92SSepherosa Ziehau *
5*632aef92SSepherosa Ziehau * Permission to use, copy, modify, and distribute this software for any
6*632aef92SSepherosa Ziehau * purpose with or without fee is hereby granted, provided that the above
7*632aef92SSepherosa Ziehau * copyright notice and this permission notice appear in all copies.
8*632aef92SSepherosa Ziehau *
9*632aef92SSepherosa Ziehau * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*632aef92SSepherosa Ziehau * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*632aef92SSepherosa Ziehau * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12*632aef92SSepherosa Ziehau * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*632aef92SSepherosa Ziehau * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*632aef92SSepherosa Ziehau * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*632aef92SSepherosa Ziehau * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*632aef92SSepherosa Ziehau *
17*632aef92SSepherosa Ziehau * $Id: inet_ntop.c,v 1.3.18.2 2005/11/03 23:02:22 marka Exp $
18*632aef92SSepherosa Ziehau * FreeBSD r213103
19*632aef92SSepherosa Ziehau */
20*632aef92SSepherosa Ziehau
21*632aef92SSepherosa Ziehau #include <sys/param.h>
22*632aef92SSepherosa Ziehau #include <sys/socket.h>
23*632aef92SSepherosa Ziehau #include <sys/systm.h>
24*632aef92SSepherosa Ziehau
25*632aef92SSepherosa Ziehau #include <netinet/in.h>
26*632aef92SSepherosa Ziehau
27*632aef92SSepherosa Ziehau /*%
28*632aef92SSepherosa Ziehau * WARNING: Don't even consider trying to compile this on a system where
29*632aef92SSepherosa Ziehau * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
30*632aef92SSepherosa Ziehau */
31*632aef92SSepherosa Ziehau
32*632aef92SSepherosa Ziehau static char *inet_ntop4(const u_char *src, char *dst, socklen_t size);
33*632aef92SSepherosa Ziehau static char *inet_ntop6(const u_char *src, char *dst, socklen_t size);
34*632aef92SSepherosa Ziehau
35*632aef92SSepherosa Ziehau /* char *
36*632aef92SSepherosa Ziehau * inet_ntop(af, src, dst, size)
37*632aef92SSepherosa Ziehau * convert a network format address to presentation format.
38*632aef92SSepherosa Ziehau * return:
39*632aef92SSepherosa Ziehau * pointer to presentation format address (`dst'), or NULL (see errno).
40*632aef92SSepherosa Ziehau * author:
41*632aef92SSepherosa Ziehau * Paul Vixie, 1996.
42*632aef92SSepherosa Ziehau */
43*632aef92SSepherosa Ziehau char *
inet_ntop(int af,const void * src,char * dst,socklen_t size)44*632aef92SSepherosa Ziehau inet_ntop(int af, const void *src, char *dst, socklen_t size)
45*632aef92SSepherosa Ziehau {
46*632aef92SSepherosa Ziehau switch (af) {
47*632aef92SSepherosa Ziehau case AF_INET:
48*632aef92SSepherosa Ziehau return (inet_ntop4(src, dst, size));
49*632aef92SSepherosa Ziehau case AF_INET6:
50*632aef92SSepherosa Ziehau return (inet_ntop6(src, dst, size));
51*632aef92SSepherosa Ziehau default:
52*632aef92SSepherosa Ziehau return (NULL);
53*632aef92SSepherosa Ziehau }
54*632aef92SSepherosa Ziehau /* NOTREACHED */
55*632aef92SSepherosa Ziehau }
56*632aef92SSepherosa Ziehau
57*632aef92SSepherosa Ziehau /* const char *
58*632aef92SSepherosa Ziehau * inet_ntop4(src, dst, size)
59*632aef92SSepherosa Ziehau * format an IPv4 address
60*632aef92SSepherosa Ziehau * return:
61*632aef92SSepherosa Ziehau * `dst' (as a const)
62*632aef92SSepherosa Ziehau * notes:
63*632aef92SSepherosa Ziehau * (1) uses no statics
64*632aef92SSepherosa Ziehau * (2) takes a u_char* not an in_addr as input
65*632aef92SSepherosa Ziehau * author:
66*632aef92SSepherosa Ziehau * Paul Vixie, 1996.
67*632aef92SSepherosa Ziehau */
68*632aef92SSepherosa Ziehau static char *
inet_ntop4(const u_char * src,char * dst,socklen_t size)69*632aef92SSepherosa Ziehau inet_ntop4(const u_char *src, char *dst, socklen_t size)
70*632aef92SSepherosa Ziehau {
71*632aef92SSepherosa Ziehau static const char fmt[] = "%u.%u.%u.%u";
72*632aef92SSepherosa Ziehau char tmp[sizeof "255.255.255.255"];
73*632aef92SSepherosa Ziehau int l;
74*632aef92SSepherosa Ziehau
75*632aef92SSepherosa Ziehau l = ksnprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
76*632aef92SSepherosa Ziehau if (l <= 0 || (socklen_t) l >= size) {
77*632aef92SSepherosa Ziehau return (NULL);
78*632aef92SSepherosa Ziehau }
79*632aef92SSepherosa Ziehau strlcpy(dst, tmp, size);
80*632aef92SSepherosa Ziehau return (dst);
81*632aef92SSepherosa Ziehau }
82*632aef92SSepherosa Ziehau
83*632aef92SSepherosa Ziehau /* const char *
84*632aef92SSepherosa Ziehau * inet_ntop6(src, dst, size)
85*632aef92SSepherosa Ziehau * convert IPv6 binary address into presentation (printable) format
86*632aef92SSepherosa Ziehau * author:
87*632aef92SSepherosa Ziehau * Paul Vixie, 1996.
88*632aef92SSepherosa Ziehau */
89*632aef92SSepherosa Ziehau static char *
inet_ntop6(const u_char * src,char * dst,socklen_t size)90*632aef92SSepherosa Ziehau inet_ntop6(const u_char *src, char *dst, socklen_t size)
91*632aef92SSepherosa Ziehau {
92*632aef92SSepherosa Ziehau /*
93*632aef92SSepherosa Ziehau * Note that int32_t and int16_t need only be "at least" large enough
94*632aef92SSepherosa Ziehau * to contain a value of the specified size. On some systems, like
95*632aef92SSepherosa Ziehau * Crays, there is no such thing as an integer variable with 16 bits.
96*632aef92SSepherosa Ziehau * Keep this in mind if you think this function should have been coded
97*632aef92SSepherosa Ziehau * to use pointer overlays. All the world's not a VAX.
98*632aef92SSepherosa Ziehau */
99*632aef92SSepherosa Ziehau char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
100*632aef92SSepherosa Ziehau struct { int base, len; } best, cur;
101*632aef92SSepherosa Ziehau #define NS_IN6ADDRSZ 16
102*632aef92SSepherosa Ziehau #define NS_INT16SZ 2
103*632aef92SSepherosa Ziehau u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
104*632aef92SSepherosa Ziehau int i;
105*632aef92SSepherosa Ziehau
106*632aef92SSepherosa Ziehau /*
107*632aef92SSepherosa Ziehau * Preprocess:
108*632aef92SSepherosa Ziehau * Copy the input (bytewise) array into a wordwise array.
109*632aef92SSepherosa Ziehau * Find the longest run of 0x00's in src[] for :: shorthanding.
110*632aef92SSepherosa Ziehau */
111*632aef92SSepherosa Ziehau memset(words, '\0', sizeof words);
112*632aef92SSepherosa Ziehau for (i = 0; i < NS_IN6ADDRSZ; i++)
113*632aef92SSepherosa Ziehau words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
114*632aef92SSepherosa Ziehau best.base = -1;
115*632aef92SSepherosa Ziehau best.len = 0;
116*632aef92SSepherosa Ziehau cur.base = -1;
117*632aef92SSepherosa Ziehau cur.len = 0;
118*632aef92SSepherosa Ziehau for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
119*632aef92SSepherosa Ziehau if (words[i] == 0) {
120*632aef92SSepherosa Ziehau if (cur.base == -1)
121*632aef92SSepherosa Ziehau cur.base = i, cur.len = 1;
122*632aef92SSepherosa Ziehau else
123*632aef92SSepherosa Ziehau cur.len++;
124*632aef92SSepherosa Ziehau } else {
125*632aef92SSepherosa Ziehau if (cur.base != -1) {
126*632aef92SSepherosa Ziehau if (best.base == -1 || cur.len > best.len)
127*632aef92SSepherosa Ziehau best = cur;
128*632aef92SSepherosa Ziehau cur.base = -1;
129*632aef92SSepherosa Ziehau }
130*632aef92SSepherosa Ziehau }
131*632aef92SSepherosa Ziehau }
132*632aef92SSepherosa Ziehau if (cur.base != -1) {
133*632aef92SSepherosa Ziehau if (best.base == -1 || cur.len > best.len)
134*632aef92SSepherosa Ziehau best = cur;
135*632aef92SSepherosa Ziehau }
136*632aef92SSepherosa Ziehau if (best.base != -1 && best.len < 2)
137*632aef92SSepherosa Ziehau best.base = -1;
138*632aef92SSepherosa Ziehau
139*632aef92SSepherosa Ziehau /*
140*632aef92SSepherosa Ziehau * Format the result.
141*632aef92SSepherosa Ziehau */
142*632aef92SSepherosa Ziehau tp = tmp;
143*632aef92SSepherosa Ziehau for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
144*632aef92SSepherosa Ziehau /* Are we inside the best run of 0x00's? */
145*632aef92SSepherosa Ziehau if (best.base != -1 && i >= best.base &&
146*632aef92SSepherosa Ziehau i < (best.base + best.len)) {
147*632aef92SSepherosa Ziehau if (i == best.base)
148*632aef92SSepherosa Ziehau *tp++ = ':';
149*632aef92SSepherosa Ziehau continue;
150*632aef92SSepherosa Ziehau }
151*632aef92SSepherosa Ziehau /* Are we following an initial run of 0x00s or any real hex? */
152*632aef92SSepherosa Ziehau if (i != 0)
153*632aef92SSepherosa Ziehau *tp++ = ':';
154*632aef92SSepherosa Ziehau /* Is this address an encapsulated IPv4? */
155*632aef92SSepherosa Ziehau if (i == 6 && best.base == 0 && (best.len == 6 ||
156*632aef92SSepherosa Ziehau (best.len == 7 && words[7] != 0x0001) ||
157*632aef92SSepherosa Ziehau (best.len == 5 && words[5] == 0xffff))) {
158*632aef92SSepherosa Ziehau if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
159*632aef92SSepherosa Ziehau return (NULL);
160*632aef92SSepherosa Ziehau tp += strlen(tp);
161*632aef92SSepherosa Ziehau break;
162*632aef92SSepherosa Ziehau }
163*632aef92SSepherosa Ziehau tp += ksprintf(tp, "%x", words[i]);
164*632aef92SSepherosa Ziehau }
165*632aef92SSepherosa Ziehau /* Was it a trailing run of 0x00's? */
166*632aef92SSepherosa Ziehau if (best.base != -1 && (best.base + best.len) ==
167*632aef92SSepherosa Ziehau (NS_IN6ADDRSZ / NS_INT16SZ))
168*632aef92SSepherosa Ziehau *tp++ = ':';
169*632aef92SSepherosa Ziehau *tp++ = '\0';
170*632aef92SSepherosa Ziehau
171*632aef92SSepherosa Ziehau /*
172*632aef92SSepherosa Ziehau * Check for overflow, copy, and we're done.
173*632aef92SSepherosa Ziehau */
174*632aef92SSepherosa Ziehau if ((socklen_t)(tp - tmp) > size) {
175*632aef92SSepherosa Ziehau return (NULL);
176*632aef92SSepherosa Ziehau }
177*632aef92SSepherosa Ziehau strcpy(dst, tmp);
178*632aef92SSepherosa Ziehau return (dst);
179*632aef92SSepherosa Ziehau }
180*632aef92SSepherosa Ziehau
181*632aef92SSepherosa Ziehau /*! \file */
182