source: trunk/libs/newlib/src/newlib/libc/sys/phoenix/net/inet_ntop.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

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