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