source: trunk/libs/newlib/src/newlib/libc/sys/phoenix/net/inet_net_pton.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.0 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/* Author: Paul Vixie (ISC), June 1996 */
19/* Copied from Linux, modified for Phoenix-RTOS. */
20
21#include <arpa/inet.h>
22#include <assert.h>
23#include <ctype.h>
24#include <errno.h>
25#include <netinet/in.h>
26#include <string.h>
27#include <sys/socket.h>
28#include <sys/types.h>
29
30static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
31{
32        static const char xdigits[] = "0123456789abcdef";
33        static const char digits[] = "0123456789";
34        int n, ch, tmp, dirty, bits;
35        const u_char *odst = dst;
36        ch = *src++;
37
38        if (ch == '0' && (src[0] == 'x' || src[0] == 'X') && isascii(src[1]) && isxdigit(src[1])) {
39                /* Hexadecimal: Eat nybble string. */
40                if (size <= 0)
41                        goto emsgsize;
42
43                *dst = 0, dirty = 0;
44                src++;  /* skip x or X. */
45
46                while ((ch = *src++) != '\0' &&
47                        isascii(ch) && isxdigit(ch)) {
48                        if (isupper(ch))
49                                ch = tolower(ch);
50
51                        n = strchr(xdigits, ch) - xdigits;
52                        assert(n >= 0 && n <= 15);
53                        *dst |= n;
54
55                        if (!dirty++)
56                                *dst <<= 4;
57
58                        else
59                                if (size-- > 0)
60                                        *++dst = 0, dirty = 0;
61
62                                else
63                                        goto emsgsize;
64                }
65
66                if (dirty)
67                        size--;
68        }
69        else {
70                if (isascii(ch) && isdigit(ch)) {
71                        /* Decimal: eat dotted digit string. */
72                        for (;;) {
73                                tmp = 0;
74
75                                do {
76                                        n = strchr(digits, ch) - digits;
77                                        assert(n >= 0 && n <= 9);
78                                        tmp *= 10;
79                                        tmp += n;
80
81                                        if (tmp > 255)
82                                                goto enoent;
83                                }
84                                while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
85
86                                if (size-- <= 0)
87                                        goto emsgsize;
88
89                                *dst++ = (u_char) tmp;
90
91                                if (ch == '\0' || ch == '/')
92                                        break;
93
94                                if (ch != '.')
95                                        goto enoent;
96
97                                ch = *src++;
98
99                                if (!isascii(ch) || !isdigit(ch))
100                                        goto enoent;
101                        }
102                }
103                else
104                        goto enoent;
105        }
106
107        bits = -1;
108
109        if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
110                /* CIDR width specifier.  Nothing can follow it. */
111                ch = *src++;    /* Skip over the /. */
112                bits = 0;
113
114                do {
115                        n = strchr(digits, ch) - digits;
116                        assert(n >= 0 && n <= 9);
117                        bits *= 10;
118                        bits += n;
119                }
120                while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
121
122                if (ch != '\0')
123                        goto enoent;
124
125                if (bits > 32)
126                        goto emsgsize;
127        }
128
129        /* Firey death and destruction unless we prefetched EOS. */
130        if (ch != '\0')
131                goto enoent;
132
133        /* If nothing was written to the destination, we found no address. */
134        if (dst == odst)
135                goto enoent;
136
137        /* If no CIDR spec was given, infer width from net class. */
138        if (bits == -1) {
139                if (*odst >= 240)       /* Class E */
140                        bits = 32;
141
142                else
143                        if (*odst >= 224)       /* Class D */
144                                bits = 4;
145
146                        else
147                                if (*odst >= 192)       /* Class C */
148                                        bits = 24;
149
150                                else
151                                        if (*odst >= 128)       /* Class B */
152                                                bits = 16;
153
154                                        else                    /* Class A */
155                                                bits = 8;
156
157                /* If imputed mask is narrower than specified octets, widen. */
158                if (bits >= 8 && bits < ((dst - odst) * 8))
159                        bits = (dst - odst) * 8;
160        }
161
162        /* Extend network to cover the actual mask. */
163        while (bits > ((dst - odst) * 8)) {
164                if (size-- <= 0)
165                        goto emsgsize;
166
167                *dst++ = '\0';
168        }
169
170        return (bits);
171enoent:
172        errno = ENOENT;
173        return -1;
174
175emsgsize:
176        errno = EMSGSIZE;
177        return -1;
178}
179
180int inet_net_pton(int af, const char *pres, void *netp, size_t nsize)
181{
182        switch (af) {
183        case AF_INET:
184                return inet_net_pton_ipv4(pres, netp, nsize);
185
186        default:
187                errno = EAFNOSUPPORT;
188                return -1;
189        }
190}
Note: See TracBrowser for help on using the repository browser.