source: rtems-libbsd/freebsd/lib/libc/inet/inet_cidr_ntop.c @ e599318

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since e599318 was e599318, checked in by Sebastian Huber <sebastian.huber@…>, on 10/09/13 at 20:52:54

Update files to match FreeBSD layout

Add compatibility with Newlib header files. Some FreeBSD header files
are mapped by the translation script:

o rtems/bsd/sys/_types.h
o rtems/bsd/sys/errno.h
o rtems/bsd/sys/lock.h
o rtems/bsd/sys/param.h
o rtems/bsd/sys/resource.h
o rtems/bsd/sys/time.h
o rtems/bsd/sys/timespec.h
o rtems/bsd/sys/types.h
o rtems/bsd/sys/unistd.h

It is now possible to include <sys/socket.h> directly for example.

Generate one Makefile which builds everything including tests.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1998,1999 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#if defined(LIBC_SCCS) && !defined(lint)
19static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 1.4.18.3 2006/10/11 02:32:47 marka Exp $";
20#endif
21
22#include "port_before.h"
23
24#include <rtems/bsd/sys/types.h>
25#include <sys/socket.h>
26#include <netinet/in.h>
27#include <arpa/nameser.h>
28#include <arpa/inet.h>
29
30#include <errno.h>
31#include <stdio.h>
32#include <string.h>
33#include <stdlib.h>
34
35#include "port_after.h"
36
37#ifdef SPRINTF_CHAR
38# define SPRINTF(x) strlen(sprintf/**/x)
39#else
40# define SPRINTF(x) ((size_t)sprintf x)
41#endif
42
43static char *
44inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size);
45static char *
46inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size);
47
48/*%
49 * char *
50 * inet_cidr_ntop(af, src, bits, dst, size)
51 *      convert network address from network to presentation format.
52 *      "src"'s size is determined from its "af".
53 * return:
54 *      pointer to dst, or NULL if an error occurred (check errno).
55 * note:
56 *      192.5.5.1/28 has a nonzero host part, which means it isn't a network
57 *      as called for by inet_net_ntop() but it can be a host address with
58 *      an included netmask.
59 * author:
60 *      Paul Vixie (ISC), October 1998
61 */
62char *
63inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) {
64        switch (af) {
65        case AF_INET:
66                return (inet_cidr_ntop_ipv4(src, bits, dst, size));
67        case AF_INET6:
68                return (inet_cidr_ntop_ipv6(src, bits, dst, size));
69        default:
70                errno = EAFNOSUPPORT;
71                return (NULL);
72        }
73}
74
75static int
76decoct(const u_char *src, int bytes, char *dst, size_t size) {
77        char *odst = dst;
78        char *t;
79        int b;
80
81        for (b = 1; b <= bytes; b++) {
82                if (size < sizeof "255.")
83                        return (0);
84                t = dst;
85                dst += SPRINTF((dst, "%u", *src++));
86                if (b != bytes) {
87                        *dst++ = '.';
88                        *dst = '\0';
89                }
90                size -= (size_t)(dst - t);
91        }
92        return (dst - odst);
93}
94
95/*%
96 * static char *
97 * inet_cidr_ntop_ipv4(src, bits, dst, size)
98 *      convert IPv4 network address from network to presentation format.
99 *      "src"'s size is determined from its "af".
100 * return:
101 *      pointer to dst, or NULL if an error occurred (check errno).
102 * note:
103 *      network byte order assumed.  this means 192.5.5.240/28 has
104 *      0b11110000 in its fourth octet.
105 * author:
106 *      Paul Vixie (ISC), October 1998
107 */
108static char *
109inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) {
110        char *odst = dst;
111        size_t len = 4;
112        size_t b;
113        size_t bytes;
114
115        if ((bits < -1) || (bits > 32)) {
116                errno = EINVAL;
117                return (NULL);
118        }
119
120        /* Find number of significant bytes in address. */
121        if (bits == -1)
122                len = 4;
123        else
124                for (len = 1, b = 1 ; b < 4U; b++)
125                        if (*(src + b))
126                                len = b + 1;
127
128        /* Format whole octets plus nonzero trailing octets. */
129        bytes = (((bits <= 0) ? 1 : bits) + 7) / 8;
130        if (len > bytes)
131                bytes = len;
132        b = decoct(src, bytes, dst, size);
133        if (b == 0U)
134                goto emsgsize;
135        dst += b;
136        size -= b;
137
138        if (bits != -1) {
139                /* Format CIDR /width. */
140                if (size < sizeof "/32")
141                        goto emsgsize;
142                dst += SPRINTF((dst, "/%u", bits));
143        }
144
145        return (odst);
146
147 emsgsize:
148        errno = EMSGSIZE;
149        return (NULL);
150}
151 
152static char *
153inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
154        /*
155         * Note that int32_t and int16_t need only be "at least" large enough
156         * to contain a value of the specified size.  On some systems, like
157         * Crays, there is no such thing as an integer variable with 16 bits.
158         * Keep this in mind if you think this function should have been coded
159         * to use pointer overlays.  All the world's not a VAX.
160         */
161        char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
162        char *tp;
163        struct { int base, len; } best, cur;
164        u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
165        int i;
166
167        if ((bits < -1) || (bits > 128)) {
168                errno = EINVAL;
169                return (NULL);
170        }
171
172        /*
173         * Preprocess:
174         *      Copy the input (bytewise) array into a wordwise array.
175         *      Find the longest run of 0x00's in src[] for :: shorthanding.
176         */
177        memset(words, '\0', sizeof words);
178        for (i = 0; i < NS_IN6ADDRSZ; i++)
179                words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
180        best.base = -1;
181        best.len = 0;
182        cur.base = -1;
183        cur.len = 0;
184        for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
185                if (words[i] == 0) {
186                        if (cur.base == -1)
187                                cur.base = i, cur.len = 1;
188                        else
189                                cur.len++;
190                } else {
191                        if (cur.base != -1) {
192                                if (best.base == -1 || cur.len > best.len)
193                                        best = cur;
194                                cur.base = -1;
195                        }
196                }
197        }
198        if (cur.base != -1) {
199                if (best.base == -1 || cur.len > best.len)
200                        best = cur;
201        }
202        if (best.base != -1 && best.len < 2)
203                best.base = -1;
204
205        /*
206         * Format the result.
207         */
208        tp = tmp;
209        for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
210                /* Are we inside the best run of 0x00's? */
211                if (best.base != -1 && i >= best.base &&
212                    i < (best.base + best.len)) {
213                        if (i == best.base)
214                                *tp++ = ':';
215                        continue;
216                }
217                /* Are we following an initial run of 0x00s or any real hex? */
218                if (i != 0)
219                        *tp++ = ':';
220                /* Is this address an encapsulated IPv4? */
221                if (i == 6 && best.base == 0 && (best.len == 6 ||
222                    (best.len == 7 && words[7] != 0x0001) ||
223                    (best.len == 5 && words[5] == 0xffff))) {
224                        int n;
225
226                        if (src[15] || bits == -1 || bits > 120)
227                                n = 4;
228                        else if (src[14] || bits > 112)
229                                n = 3;
230                        else
231                                n = 2;
232                        n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp));
233                        if (n == 0) {
234                                errno = EMSGSIZE;
235                                return (NULL);
236                        }
237                        tp += strlen(tp);
238                        break;
239                }
240                tp += SPRINTF((tp, "%x", words[i]));
241        }
242
243        /* Was it a trailing run of 0x00's? */
244        if (best.base != -1 && (best.base + best.len) ==
245            (NS_IN6ADDRSZ / NS_INT16SZ))
246                *tp++ = ':';
247        *tp = '\0';
248
249        if (bits != -1)
250                tp += SPRINTF((tp, "/%u", bits));
251
252        /*
253         * Check for overflow, copy, and we're done.
254         */
255        if ((size_t)(tp - tmp) > size) {
256                errno = EMSGSIZE;
257                return (NULL);
258        }
259        strcpy(dst, tmp);
260        return (dst);
261}
262
263/*! \file */
Note: See TracBrowser for help on using the repository browser.