source: rtems/cpukit/libnetworking/libc/inet_net_pton.c @ d8fce03

4.8
Last change on this file since d8fce03 was 09fdb5e8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/30/07 at 05:15:58

Eliminate SCCS, LINT. Add HAVE_CONFIG_H.

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/*
2 * Copyright (c) 1996 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#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26
27#include <assert.h>
28#include <ctype.h>
29#include <errno.h>
30#include <stdio.h>
31#include <string.h>
32#include <stdlib.h>
33
34#ifdef SPRINTF_CHAR
35# define SPRINTF(x) strlen(sprintf/**/x)
36#else
37# define SPRINTF(x) ((size_t)sprintf x)
38#endif
39
40static int      inet_net_pton_ipv4 __P((const char *src, u_char *dst,
41                                        size_t size));
42
43/*
44 * static int
45 * inet_net_pton(af, src, dst, size)
46 *      convert network number from presentation to network format.
47 *      accepts hex octets, hex strings, decimal octets, and /CIDR.
48 *      "size" is in bytes and describes "dst".
49 * return:
50 *      number of bits, either imputed classfully or specified with /CIDR,
51 *      or -1 if some failure occurred (check errno).  ENOENT means it was
52 *      not a valid network specification.
53 * author:
54 *      Paul Vixie (ISC), June 1996
55 */
56int
57inet_net_pton(af, src, dst, size)
58        int af;
59        const char *src;
60        void *dst;
61        size_t size;
62{
63        switch (af) {
64        case AF_INET:
65                return (inet_net_pton_ipv4(src, dst, size));
66        default:
67                errno = EAFNOSUPPORT;
68                return (-1);
69        }
70}
71
72/*
73 * static int
74 * inet_net_pton_ipv4(src, dst, size)
75 *      convert IPv4 network number from presentation to network format.
76 *      accepts hex octets, hex strings, decimal octets, and /CIDR.
77 *      "size" is in bytes and describes "dst".
78 * return:
79 *      number of bits, either imputed classfully or specified with /CIDR,
80 *      or -1 if some failure occurred (check errno).  ENOENT means it was
81 *      not an IPv4 network specification.
82 * note:
83 *      network byte order assumed.  this means 192.5.5.240/28 has
84 *      0x11110000 in its fourth octet.
85 * author:
86 *      Paul Vixie (ISC), June 1996
87 */
88static int
89inet_net_pton_ipv4(src, dst, size)
90        const char *src;
91        u_char *dst;
92        size_t size;
93{
94        static const char
95                xdigits[] = "0123456789abcdef",
96                digits[] = "0123456789";
97        int n, ch, tmp, dirty, bits;
98        const u_char *odst = dst;
99
100        ch = *src++;
101        if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
102            && isascii(src[1]) && isxdigit(src[1])) {
103                /* Hexadecimal: Eat nybble string. */
104                if (size <= 0)
105                        goto emsgsize;
106                *dst = 0, dirty = 0;
107                src++;  /* skip x or X. */
108                while ((ch = *src++) != '\0' &&
109                       isascii(ch) && isxdigit(ch)) {
110                        if (isupper(ch))
111                                ch = tolower(ch);
112                        n = strchr(xdigits, ch) - xdigits;
113                        assert(n >= 0 && n <= 15);
114                        *dst |= n;
115                        if (!dirty++)
116                                *dst <<= 4;
117                        else if (size-- > 0)
118                                *++dst = 0, dirty = 0;
119                        else
120                                goto emsgsize;
121                }
122                if (dirty)
123                        size--;
124        } else if (isascii(ch) && isdigit(ch)) {
125                /* Decimal: eat dotted digit string. */
126                for (;;) {
127                        tmp = 0;
128                        do {
129                                n = strchr(digits, ch) - digits;
130                                assert(n >= 0 && n <= 9);
131                                tmp *= 10;
132                                tmp += n;
133                                if (tmp > 255)
134                                        goto enoent;
135                        } while ((ch = *src++) != '\0' &&
136                                 isascii(ch) && isdigit(ch));
137                        if (size-- <= 0)
138                                goto emsgsize;
139                        *dst++ = (u_char) tmp;
140                        if (ch == '\0' || ch == '/')
141                                break;
142                        if (ch != '.')
143                                goto enoent;
144                        ch = *src++;
145                        if (!isascii(ch) || !isdigit(ch))
146                                goto enoent;
147                }
148        } else
149                goto enoent;
150
151        bits = -1;
152        if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
153                /* CIDR width specifier.  Nothing can follow it. */
154                ch = *src++;    /* Skip over the /. */
155                bits = 0;
156                do {
157                        n = strchr(digits, ch) - digits;
158                        assert(n >= 0 && n <= 9);
159                        bits *= 10;
160                        bits += n;
161                } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
162                if (ch != '\0')
163                        goto enoent;
164                if (bits > 32)
165                        goto emsgsize;
166        }
167
168        /* Firey death and destruction unless we prefetched EOS. */
169        if (ch != '\0')
170                goto enoent;
171
172        /* If nothing was written to the destination, we found no address. */
173        if (dst == odst)
174                goto enoent;
175        /* If no CIDR spec was given, infer width from net class. */
176        if (bits == -1) {
177                if (*odst >= 240)       /* Class E */
178                        bits = 32;
179                else if (*odst >= 224)  /* Class D */
180                        bits = 4;
181                else if (*odst >= 192)  /* Class C */
182                        bits = 24;
183                else if (*odst >= 128)  /* Class B */
184                        bits = 16;
185                else                    /* Class A */
186                        bits = 8;
187                /* If imputed mask is narrower than specified octets, widen. */
188                if (bits >= 8 && bits < ((dst - odst) * 8))
189                        bits = (dst - odst) * 8;
190        }
191        /* Extend network to cover the actual mask. */
192        while (bits > ((dst - odst) * 8)) {
193                if (size-- <= 0)
194                        goto emsgsize;
195                *dst++ = '\0';
196        }
197        return (bits);
198
199 enoent:
200        errno = ENOENT;
201        return (-1);
202
203 emsgsize:
204        errno = EMSGSIZE;
205        return (-1);
206}
Note: See TracBrowser for help on using the repository browser.