source: rtems-libbsd/freebsd/lib/libc/inet/inet_net_ntop.c @ 165dd8e

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 165dd8e was 165dd8e, checked in by Sebastian Huber <sebastian.huber@…>, on 04/08/15 at 13:37:49

Update to FreeBSD Stable/9 2015-04-08

  • Property mode set to 100644
File size: 6.6 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996,1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.5 2006/06/20 02:50:14 marka Exp $";
22#endif
23#include <sys/cdefs.h>
24__FBSDID("$FreeBSD$");
25
26#include "port_before.h"
27
28#include <rtems/bsd/sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37
38#include "port_after.h"
39
40#ifdef SPRINTF_CHAR
41# define SPRINTF(x) strlen(sprintf/**/x)
42#else
43# define SPRINTF(x) ((size_t)sprintf x)
44#endif
45
46static char *   inet_net_ntop_ipv4(const u_char *src, int bits, char *dst,
47                    size_t size);
48static char *   inet_net_ntop_ipv6(const u_char *src, int bits, char *dst,
49                    size_t size);
50
51/*%
52 * char *
53 * inet_net_ntop(af, src, bits, dst, size)
54 *      convert network number from network to presentation format.
55 *      generates CIDR style result always.
56 * return:
57 *      pointer to dst, or NULL if an error occurred (check errno).
58 * author:
59 *      Paul Vixie (ISC), July 1996
60 */
61char *
62inet_net_ntop(af, src, bits, dst, size)
63        int af;
64        const void *src;
65        int bits;
66        char *dst;
67        size_t size;
68{
69        switch (af) {
70        case AF_INET:
71                return (inet_net_ntop_ipv4(src, bits, dst, size));
72        case AF_INET6:
73                return (inet_net_ntop_ipv6(src, bits, dst, size));
74        default:
75                errno = EAFNOSUPPORT;
76                return (NULL);
77        }
78}
79
80/*%
81 * static char *
82 * inet_net_ntop_ipv4(src, bits, dst, size)
83 *      convert IPv4 network number from network to presentation format.
84 *      generates CIDR style result always.
85 * return:
86 *      pointer to dst, or NULL if an error occurred (check errno).
87 * note:
88 *      network byte order assumed.  this means 192.5.5.240/28 has
89 *      0b11110000 in its fourth octet.
90 * author:
91 *      Paul Vixie (ISC), July 1996
92 */
93static char *
94inet_net_ntop_ipv4(src, bits, dst, size)
95        const u_char *src;
96        int bits;
97        char *dst;
98        size_t size;
99{
100        char *odst = dst;
101        char *t;
102        u_int m;
103        int b;
104
105        if (bits < 0 || bits > 32) {
106                errno = EINVAL;
107                return (NULL);
108        }
109
110        if (bits == 0) {
111                if (size < sizeof "0")
112                        goto emsgsize;
113                *dst++ = '0';
114                size--;
115                *dst = '\0';
116        }
117
118        /* Format whole octets. */
119        for (b = bits / 8; b > 0; b--) {
120                if (size <= sizeof "255.")
121                        goto emsgsize;
122                t = dst;
123                dst += SPRINTF((dst, "%u", *src++));
124                if (b > 1) {
125                        *dst++ = '.';
126                        *dst = '\0';
127                }
128                size -= (size_t)(dst - t);
129        }
130
131        /* Format partial octet. */
132        b = bits % 8;
133        if (b > 0) {
134                if (size <= sizeof ".255")
135                        goto emsgsize;
136                t = dst;
137                if (dst != odst)
138                        *dst++ = '.';
139                m = ((1 << b) - 1) << (8 - b);
140                dst += SPRINTF((dst, "%u", *src & m));
141                size -= (size_t)(dst - t);
142        }
143
144        /* Format CIDR /width. */
145        if (size <= sizeof "/32")
146                goto emsgsize;
147        dst += SPRINTF((dst, "/%u", bits));
148        return (odst);
149
150 emsgsize:
151        errno = EMSGSIZE;
152        return (NULL);
153}
154
155/*%
156 * static char *
157 * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
158 *      convert IPv6 network number from network to presentation format.
159 *      generates CIDR style result always. Picks the shortest representation
160 *      unless the IP is really IPv4.
161 *      always prints specified number of bits (bits).
162 * return:
163 *      pointer to dst, or NULL if an error occurred (check errno).
164 * note:
165 *      network byte order assumed.  this means 192.5.5.240/28 has
166 *      0b11110000 in its fourth octet.
167 * author:
168 *      Vadim Kogan (UCB), June 2001
169 *  Original version (IPv4) by Paul Vixie (ISC), July 1996
170 */
171
172static char *
173inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
174        u_int   m;
175        int     b;
176        int     p;
177        int     zero_s, zero_l, tmp_zero_s, tmp_zero_l;
178        int     i;
179        int     is_ipv4 = 0;
180        unsigned char inbuf[16];
181        char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
182        char    *cp;
183        int     words;
184        u_char  *s;
185
186        if (bits < 0 || bits > 128) {
187                errno = EINVAL;
188                return (NULL);
189        }
190
191        cp = outbuf;
192
193        if (bits == 0) {
194                *cp++ = ':';
195                *cp++ = ':';
196                *cp = '\0';
197        } else {
198                /* Copy src to private buffer.  Zero host part. */
199                p = (bits + 7) / 8;
200                memcpy(inbuf, src, p);
201                memset(inbuf + p, 0, 16 - p);
202                b = bits % 8;
203                if (b != 0) {
204                        m = ~0 << (8 - b);
205                        inbuf[p-1] &= m;
206                }
207
208                s = inbuf;
209
210                /* how many words need to be displayed in output */
211                words = (bits + 15) / 16;
212                if (words == 1)
213                        words = 2;
214
215                /* Find the longest substring of zero's */
216                zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
217                for (i = 0; i < (words * 2); i += 2) {
218                        if ((s[i] | s[i+1]) == 0) {
219                                if (tmp_zero_l == 0)
220                                        tmp_zero_s = i / 2;
221                                tmp_zero_l++;
222                        } else {
223                                if (tmp_zero_l && zero_l < tmp_zero_l) {
224                                        zero_s = tmp_zero_s;
225                                        zero_l = tmp_zero_l;
226                                        tmp_zero_l = 0;
227                                }
228                        }
229                }
230
231                if (tmp_zero_l && zero_l < tmp_zero_l) {
232                        zero_s = tmp_zero_s;
233                        zero_l = tmp_zero_l;
234                }
235
236                if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
237                    ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
238                    ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
239                        is_ipv4 = 1;
240
241                /* Format whole words. */
242                for (p = 0; p < words; p++) {
243                        if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
244                                /* Time to skip some zeros */
245                                if (p == zero_s)
246                                        *cp++ = ':';
247                                if (p == words - 1)
248                                        *cp++ = ':';
249                                s++;
250                                s++;
251                                continue;
252                        }
253
254                        if (is_ipv4 && p > 5 ) {
255                                *cp++ = (p == 6) ? ':' : '.';
256                                cp += SPRINTF((cp, "%u", *s++));
257                                /* we can potentially drop the last octet */
258                                if (p != 7 || bits > 120) {
259                                        *cp++ = '.';
260                                        cp += SPRINTF((cp, "%u", *s++));
261                                }
262                        } else {
263                                if (cp != outbuf)
264                                        *cp++ = ':';
265                                cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
266                                s += 2;
267                        }
268                }
269        }
270        /* Format CIDR /width. */
271        sprintf(cp, "/%u", bits);
272        if (strlen(outbuf) + 1 > size)
273                goto emsgsize;
274        strcpy(dst, outbuf);
275
276        return (dst);
277
278emsgsize:
279        errno = EMSGSIZE;
280        return (NULL);
281}
282
283/*
284 * Weak aliases for applications that use certain private entry points,
285 * and fail to include <arpa/inet.h>.
286 */
287#undef inet_net_ntop
288__weak_reference(__inet_net_ntop, inet_net_ntop);
289
290/*! \file */
Note: See TracBrowser for help on using the repository browser.