]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/common/v2_0/src/inet_ntop.c
Initial revision
[karo-tx-redboot.git] / packages / net / common / v2_0 / src / inet_ntop.c
1 //==========================================================================
2 //
3 //      src/inet_ntop.c
4 //
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
7 //
8 // -------------------------------------------
9 //
10 // Portions of this software may have been derived from OpenBSD, 
11 // FreeBSD or other sources, and are covered by the appropriate
12 // copyright disclaimers included herein.
13 //
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16 //
17 // -------------------------------------------
18 //
19 //####BSDCOPYRIGHTEND####
20 //==========================================================================
21
22 /*      $OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $    */
23
24 /* Copyright (c) 1996 by Internet Software Consortium.
25  *
26  * Permission to use, copy, modify, and distribute this software for any
27  * purpose with or without fee is hereby granted, provided that the above
28  * copyright notice and this permission notice appear in all copies.
29  *
30  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
31  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
32  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
33  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
34  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
35  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
36  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37  * SOFTWARE.
38  */
39
40 #include <sys/param.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <arpa/nameser.h>
46 #include <string.h>
47 #include <errno.h>
48 #ifndef CYGPKG_NET_FREEBSD_STACK
49 #include <stdio.h>
50 #endif
51
52 #ifndef IN6ADDRSZ
53 #define IN6ADDRSZ    16      /* IPv6 T_AAAA */
54 #endif
55 #ifndef INT16SZ
56 #define INT16SZ sizeof(u_int16_t)
57 #endif
58
59 /*
60  * WARNING: Don't even consider trying to compile this on a system where
61  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
62  */
63
64 static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
65 #ifdef CYGPKG_NET_INET6
66 static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
67 #endif
68
69 /* char *
70  * inet_ntop(af, src, dst, size)
71  *      convert a network format address to presentation format.
72  * return:
73  *      pointer to presentation format address (`dst'), or NULL (see errno).
74  * author:
75  *      Paul Vixie, 1996.
76  */
77 const char *
78 inet_ntop(int af, const void *src, char *dst, size_t size)
79 {
80         switch (af) {
81         case AF_INET:
82                 return (inet_ntop4(src, dst, size));
83 #ifdef CYGPKG_NET_INET6
84         case AF_INET6:
85                 return (inet_ntop6(src, dst, size));
86 #endif
87         default:
88                 errno = EAFNOSUPPORT;
89                 return (NULL);
90         }
91         /* NOTREACHED */
92 }
93
94 //
95 // A more useful conversion routine
96 // Convert a network [socket] address to presentation format
97 // This routine handles all of the mapping required and isolates
98 // the knowledge of the structure format.
99 //
100 const char *
101 _inet_ntop(struct sockaddr *sa, char *dst, size_t size)
102 {
103     switch (sa->sa_family) {
104     case AF_INET:
105         return (inet_ntop(AF_INET, (char *)&((struct sockaddr_in *)sa)->sin_addr, 
106                           dst, size));
107 #ifdef CYGPKG_NET_INET6
108     case AF_INET6:
109         return (inet_ntop(AF_INET6, (char *)&((struct sockaddr_in6 *)sa)->sin6_addr, 
110                           dst, size));
111 #endif
112     default:
113         errno = EAFNOSUPPORT;
114         return (NULL);
115     }
116 }
117
118 u_int16_t
119 _inet_port(struct sockaddr *sa)
120 {
121     switch (sa->sa_family) {
122     case AF_INET:
123         return (ntohs(((struct sockaddr_in *)sa)->sin_port)); 
124 #ifdef CYGPKG_NET_INET6
125     case AF_INET6:
126         return (ntohs(((struct sockaddr_in6 *)sa)->sin6_port)); 
127 #endif
128     default:
129         return 0;  // Unknown!
130     }
131 }
132
133 /* const char *
134  * inet_ntop4(src, dst, size)
135  *      format an IPv4 address, more or less like inet_ntoa()
136  * return:
137  *      `dst' (as a const)
138  * notes:
139  *      (1) uses no statics
140  *      (2) takes a u_char* not an in_addr as input
141  * author:
142  *      Paul Vixie, 1996.
143  */
144 static const char *
145 inet_ntop4(src, dst, size)
146         const u_char *src;
147         char *dst;
148         size_t size;
149 {
150         static const char fmt[] = "%u.%u.%u.%u";
151         char tmp[sizeof "255.255.255.255"];
152
153         if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) {
154                 errno = ENOSPC;
155                 return (NULL);
156         }
157         strcpy(dst, tmp);
158         return (dst);
159 }
160
161 #ifdef CYGPKG_NET_INET6
162 /* const char *
163  * inet_ntop6(src, dst, size)
164  *      convert IPv6 binary address into presentation (printable) format
165  * author:
166  *      Paul Vixie, 1996.
167  */
168 static const char *
169 inet_ntop6(const u_char *src, char *dst, size_t size)
170 {
171         /*
172          * Note that int32_t and int16_t need only be "at least" large enough
173          * to contain a value of the specified size.  On some systems, like
174          * Crays, there is no such thing as an integer variable with 16 bits.
175          * Keep this in mind if you think this function should have been coded
176          * to use pointer overlays.  All the world's not a VAX.
177          */
178 #if 0 // This is too optimistic
179         char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
180 #else
181         char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"], *tp;
182 #endif
183         struct { int base, len; } best, cur;
184         u_int words[IN6ADDRSZ / INT16SZ];
185         int i;
186
187         /*
188          * Preprocess:
189          *      Copy the input (bytewise) array into a wordwise array.
190          *      Find the longest run of 0x00's in src[] for :: shorthanding.
191          */
192         memset(words, '\0', sizeof words);
193         for (i = 0; i < IN6ADDRSZ; i++)
194                 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
195         best.base = -1;
196         cur.base = -1;
197         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
198                 if (words[i] == 0) {
199                         if (cur.base == -1)
200                                 cur.base = i, cur.len = 1;
201                         else
202                                 cur.len++;
203                 } else {
204                         if (cur.base != -1) {
205                                 if (best.base == -1 || cur.len > best.len)
206                                         best = cur;
207                                 cur.base = -1;
208                         }
209                 }
210         }
211         if (cur.base != -1) {
212                 if (best.base == -1 || cur.len > best.len)
213                         best = cur;
214         }
215         if (best.base != -1 && best.len < 2)
216                 best.base = -1;
217
218         /*
219          * Format the result.
220          */
221         tp = tmp;
222         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
223                 /* Are we inside the best run of 0x00's? */
224                 if (best.base != -1 && i >= best.base &&
225                     i < (best.base + best.len)) {
226                         if (i == best.base)
227                                 *tp++ = ':';
228                         continue;
229                 }
230                 /* Are we following an initial run of 0x00s or any real hex? */
231                 if (i != 0)
232                         *tp++ = ':';
233                 /* Is this address an encapsulated IPv4? */
234                 if (i == 6 && best.base == 0 &&
235                     (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
236                         if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
237                                 return (NULL);
238                         tp += strlen(tp);
239                         break;
240                 }
241                 tp += sprintf(tp, "%x", words[i]);
242         }
243         /* Was it a trailing run of 0x00's? */
244         if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
245                 *tp++ = ':';
246         *tp++ = '\0';
247
248         /*
249          * Check for overflow, copy, and we're done.
250          */
251         if ((size_t)(tp - tmp) > size) {
252                 errno = ENOSPC;
253                 return (NULL);
254         }
255         strcpy(dst, tmp);
256         return (dst);
257 }
258 #endif