OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [inet/] [ntop.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*
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
#define __FORCE_GLIBC
19
#include <features.h>
20
#include <sys/param.h>
21
#include <sys/types.h>
22
#include <sys/socket.h>
23
 
24
#include <netinet/in.h>
25
#include <arpa/inet.h>
26
#include <arpa/nameser.h>
27
 
28
#include <errno.h>
29
#include <stdio.h>
30
#include <string.h>
31
#include <ctype.h>
32
 
33
 
34
/*
35
 * WARNING: Don't even consider trying to compile this on a system where
36
 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
37
 */
38
 
39
 
40
/* const char *
41
 * inet_ntop4(src, dst, size)
42
 *      format an IPv4 address
43
 * return:
44
 *      `dst' (as a const)
45
 * notes:
46
 *      (1) uses no statics
47
 *      (2) takes a u_char* not an in_addr as input
48
 * author:
49
 *      Paul Vixie, 1996.
50
 */
51
static const char *
52
inet_ntop4(const u_char *src, char *dst, size_t size)
53
{
54
        char tmp[sizeof ("255.255.255.255") + 1] = "\0";
55
        int octet;
56
        int i;
57
 
58
        i = 0;
59
        for (octet = 0; octet <= 3; octet++) {
60
 
61
                if (src[octet] > 255) {
62
                        __set_errno (ENOSPC);
63
                        return (NULL);
64
                }
65
                tmp[i++] = '0' + src[octet] / 100;
66
                if (tmp[i - 1] == '0') {
67
                        tmp[i - 1] = '0' + (src[octet] / 10 % 10);
68
                        if (tmp[i - 1] == '0') i--;
69
                } else {
70
                        tmp[i++] = '0' + (src[octet] / 10 % 10);
71
                }
72
                tmp[i++] = '0' + src[octet] % 10;
73
                tmp[i++] = '.';
74
        }
75
        tmp[i - 1] = '\0';
76
 
77
        if (strlen (tmp) > size) {
78
                __set_errno (ENOSPC);
79
                return (NULL);
80
        }
81
 
82
        return strcpy(dst, tmp);
83
}
84
 
85
 
86
/* const char *
87
 * inet_ntop6(src, dst, size)
88
 *      convert IPv6 binary address into presentation (printable) format
89
 * author:
90
 *      Paul Vixie, 1996.
91
 */
92
 
93
#ifdef __UCLIBC_HAS_IPV6__
94
 
95
static const char *
96
inet_ntop6(const u_char *src, char *dst, size_t size)
97
{
98
        /*
99
         * Note that int32_t and int16_t need only be "at least" large enough
100
         * to contain a value of the specified size.  On some systems, like
101
         * Crays, there is no such thing as an integer variable with 16 bits.
102
         * Keep this in mind if you think this function should have been coded
103
         * to use pointer overlays.  All the world's not a VAX.
104
         */
105
        char tmp[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
106
        struct { int base, len; } best, cur;
107
        u_int words[8];
108
        int i;
109
 
110
        /*
111
         * Preprocess:
112
         *      Copy the input (bytewise) array into a wordwise array.
113
         *      Find the longest run of 0x00's in src[] for :: shorthanding.
114
         */
115
        memset(words, '\0', sizeof words);
116
        for (i = 0; i < 16; i += 2)
117
                words[i / 2] = (src[i] << 8) | src[i + 1];
118
        best.base = -1;
119
        cur.base = -1;
120
        for (i = 0; i < 8; i++) {
121
                if (words[i] == 0) {
122
                        if (cur.base == -1)
123
                                cur.base = i, cur.len = 1;
124
                        else
125
                                cur.len++;
126
                } else {
127
                        if (cur.base != -1) {
128
                                if (best.base == -1 || cur.len > best.len)
129
                                        best = cur;
130
                                cur.base = -1;
131
                        }
132
                }
133
        }
134
        if (cur.base != -1) {
135
                if (best.base == -1 || cur.len > best.len)
136
                        best = cur;
137
        }
138
        if (best.base != -1 && best.len < 2)
139
                best.base = -1;
140
 
141
        /*
142
         * Format the result.
143
         */
144
        tp = tmp;
145
        for (i = 0; i < 8; i++) {
146
                /* Are we inside the best run of 0x00's? */
147
                if (best.base != -1 && i >= best.base &&
148
                    i < (best.base + best.len)) {
149
                        if (i == best.base)
150
                                *tp++ = ':';
151
                        continue;
152
                }
153
                /* Are we following an initial run of 0x00s or any real hex? */
154
                if (i != 0)
155
                        *tp++ = ':';
156
                /* Is this address an encapsulated IPv4? */
157
                if (i == 6 && best.base == 0 &&
158
                    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
159
                        if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
160
                                return (NULL);
161
                        tp += strlen(tp);
162
                        break;
163
                }
164
                tp += sprintf(tp, "%x", words[i]);
165
        }
166
        /* Was it a trailing run of 0x00's? */
167
        if (best.base != -1 && (best.base + best.len) == 8)
168
                *tp++ = ':';
169
        *tp++ = '\0';
170
 
171
        /*
172
         * Check for overflow, copy, and we're done.
173
         */
174
        if ((size_t)(tp - tmp) > size) {
175
                __set_errno (ENOSPC);
176
                return (NULL);
177
        }
178
        return strcpy(dst, tmp);
179
}
180
#endif /* __UCLIBC_HAS_IPV6__ */
181
 
182
 
183
/* int
184
 * inet_pton4(src, dst)
185
 *      like inet_aton() but without all the hexadecimal and shorthand.
186
 * return:
187
 *      1 if `src' is a valid dotted quad, else 0.
188
 * notice:
189
 *      does not touch `dst' unless it's returning 1.
190
 * author:
191
 *      Paul Vixie, 1996.
192
 */
193
static int
194
inet_pton4(const char *src, u_char *dst)
195
{
196
        int saw_digit, octets, ch;
197
        u_char tmp[4], *tp;
198
 
199
        saw_digit = 0;
200
        octets = 0;
201
        *(tp = tmp) = 0;
202
        while ((ch = *src++) != '\0') {
203
 
204
                if (ch >= '0' && ch <= '9') {
205
                        u_int new = *tp * 10 + (ch - '0');
206
 
207
                        if (new > 255)
208
                                return (0);
209
                        *tp = new;
210
                        if (! saw_digit) {
211
                                if (++octets > 4)
212
                                        return (0);
213
                                saw_digit = 1;
214
                        }
215
                } else if (ch == '.' && saw_digit) {
216
                        if (octets == 4)
217
                                return (0);
218
                        *++tp = 0;
219
                        saw_digit = 0;
220
                } else
221
                        return (0);
222
        }
223
        if (octets < 4)
224
                return (0);
225
        memcpy(dst, tmp, 4);
226
        return (1);
227
}
228
 
229
/* int
230
 * inet_pton6(src, dst)
231
 *      convert presentation level address to network order binary form.
232
 * return:
233
 *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
234
 * notice:
235
 *      (1) does not touch `dst' unless it's returning 1.
236
 *      (2) :: in a full address is silently ignored.
237
 * credit:
238
 *      inspired by Mark Andrews.
239
 * author:
240
 *      Paul Vixie, 1996.
241
 */
242
 
243
#ifdef __UCLIBC_HAS_IPV6__
244
 
245
/* We cannot use the macro version of tolower() or very bad
246
 * things happen when '*src++' gets evaluated multiple times.
247
 * So * undef it here so we get the function version of tolower
248
 * instead.
249
 */
250
#undef tolower
251
 
252
static int
253
inet_pton6(const char *src, u_char *dst)
254
{
255
        static const char xdigits[] = "0123456789abcdef";
256
        u_char tmp[16], *tp, *endp, *colonp;
257
        const char *curtok;
258
        int ch, saw_xdigit;
259
        u_int val;
260
 
261
 
262
        tp = memset(tmp, '\0', 16);
263
        endp = tp + 16;
264
        colonp = NULL;
265
        /* Leading :: requires some special handling. */
266
        if (*src == ':')
267
                if (*++src != ':')
268
                        return (0);
269
        curtok = src;
270
        saw_xdigit = 0;
271
        val = 0;
272
        while ((ch = tolower (*src++)) != '\0') {
273
                const char *pch;
274
 
275
                pch = strchr(xdigits, ch);
276
                if (pch != NULL) {
277
                        val <<= 4;
278
                        val |= (pch - xdigits);
279
                        if (val > 0xffff)
280
                                return (0);
281
                        saw_xdigit = 1;
282
                        continue;
283
                }
284
                if (ch == ':') {
285
                        curtok = src;
286
                        if (!saw_xdigit) {
287
                                if (colonp)
288
                                        return (0);
289
                                colonp = tp;
290
                                continue;
291
                        } else if (*src == '\0') {
292
                                return (0);
293
                        }
294
                        if (tp + 2 > endp)
295
                                return (0);
296
                        *tp++ = (u_char) (val >> 8) & 0xff;
297
                        *tp++ = (u_char) val & 0xff;
298
                        saw_xdigit = 0;
299
                        val = 0;
300
                        continue;
301
                }
302
                if (ch == '.' && ((tp + 4) <= endp) &&
303
                    inet_pton4(curtok, tp) > 0) {
304
                        tp += 4;
305
                        saw_xdigit = 0;
306
                        break;  /* '\0' was seen by inet_pton4(). */
307
                }
308
                return (0);
309
        }
310
        if (saw_xdigit) {
311
                if (tp + 2 > endp)
312
                        return (0);
313
                *tp++ = (u_char) (val >> 8) & 0xff;
314
                *tp++ = (u_char) val & 0xff;
315
        }
316
        if (colonp != NULL) {
317
                /*
318
                 * Since some memmove()'s erroneously fail to handle
319
                 * overlapping regions, we'll do the shift by hand.
320
                 */
321
                const int n = tp - colonp;
322
                int i;
323
 
324
                if (tp == endp)
325
                        return (0);
326
                for (i = 1; i <= n; i++) {
327
                        endp[- i] = colonp[n - i];
328
                        colonp[n - i] = 0;
329
                }
330
                tp = endp;
331
        }
332
        if (tp != endp)
333
                return (0);
334
        memcpy(dst, tmp, 16);
335
        return (1);
336
}
337
 
338
#endif /* __UCLIBC_HAS_IPV6__ */
339
 
340
 
341
 
342
/* char *
343
 * inet_ntop(af, src, dst, size)
344
 *      convert a network format address to presentation format.
345
 * return:
346
 *      pointer to presentation format address (`dst'), or NULL (see errno).
347
 * author:
348
 *      Paul Vixie, 1996.
349
 */
350
extern const char *
351
inet_ntop(af, src, dst, size)
352
        int af;
353
        const void *src;
354
        char *dst;
355
        socklen_t size;
356
{
357
        switch (af) {
358
        case AF_INET:
359
                return (inet_ntop4(src, dst, size));
360
#ifdef __UCLIBC_HAS_IPV6__
361
        case AF_INET6:
362
                return (inet_ntop6(src, dst, size));
363
#endif
364
        default:
365
                __set_errno (EAFNOSUPPORT);
366
                return (NULL);
367
        }
368
        /* NOTREACHED */
369
}
370
 
371
 
372
/* int
373
 * inet_pton(af, src, dst)
374
 *      convert from presentation format (which usually means ASCII printable)
375
 *      to network format (which is usually some kind of binary format).
376
 * return:
377
 *      1 if the address was valid for the specified address family
378
 *      0 if the address wasn't valid (`dst' is untouched in this case)
379
 *      -1 if some other error occurred (`dst' is untouched in this case, too)
380
 * author:
381
 *      Paul Vixie, 1996.
382
 */
383
extern int
384
inet_pton(af, src, dst)
385
        int af;
386
        const char *src;
387
        void *dst;
388
{
389
        switch (af) {
390
        case AF_INET:
391
                return (inet_pton4(src, dst));
392
#ifdef __UCLIBC_HAS_IPV6__
393
        case AF_INET6:
394
                return (inet_pton6(src, dst));
395
#endif
396
        default:
397
                __set_errno (EAFNOSUPPORT);
398
                return (-1);
399
        }
400
        /* NOTREACHED */
401
}
402
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.