source: rtems-libbsd/freebsd-userspace/lib/libc/inet/inet_net_ntop.c @ 1b13f69

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 1b13f69 was 1b13f69, checked in by Joel Sherrill <joel.sherrill@…>, on 07/11/12 at 18:23:45

FreeBSD user space support - First additions

This requires a full checkout of the FreeBSD 8.2 source code.
The checkout we have been using is missing at least the libc,
include, and sys directories. The script to copy files in is
crude.

This eventually needs to separate the manually written .h files
out and add the RTEMS specific network initialization support
with functionality to program the IP addresses and gateways as
the old stack did.

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