1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2018-05-18 ChenYong First version
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <sal_ipaddr.h>
12*10465441SEvalZero #include <rtthread.h>
13*10465441SEvalZero
14*10465441SEvalZero /* Here for now until needed in other places in lwIP */
15*10465441SEvalZero #ifndef isprint
16*10465441SEvalZero #define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
17*10465441SEvalZero #define isprint(c) in_range(c, 0x20, 0x7f)
18*10465441SEvalZero #define isdigit(c) in_range(c, '0', '9')
19*10465441SEvalZero #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
20*10465441SEvalZero #define islower(c) in_range(c, 'a', 'z')
21*10465441SEvalZero #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
22*10465441SEvalZero #endif
23*10465441SEvalZero
24*10465441SEvalZero
25*10465441SEvalZero /**
26*10465441SEvalZero * Check whether "cp" is a valid ascii representation
27*10465441SEvalZero * of an Internet address and convert to a binary address.
28*10465441SEvalZero * Returns 1 if the address is valid, 0 if not.
29*10465441SEvalZero * This replaces inet_addr, the return value from which
30*10465441SEvalZero * cannot distinguish between failure and a local broadcast address.
31*10465441SEvalZero *
32*10465441SEvalZero * @param cp IP address in ascii representation (e.g. "127.0.0.1")
33*10465441SEvalZero * @param addr pointer to which to save the ip address in network order
34*10465441SEvalZero * @return 1 if cp could be converted to addr, 0 on failure
35*10465441SEvalZero */
sal_ip4addr_aton(const char * cp,ip4_addr_t * addr)36*10465441SEvalZero int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr)
37*10465441SEvalZero {
38*10465441SEvalZero u32_t val;
39*10465441SEvalZero u8_t base;
40*10465441SEvalZero char c;
41*10465441SEvalZero u32_t parts[4];
42*10465441SEvalZero u32_t *pp = parts;
43*10465441SEvalZero
44*10465441SEvalZero c = *cp;
45*10465441SEvalZero for (;;)
46*10465441SEvalZero {
47*10465441SEvalZero /*
48*10465441SEvalZero * Collect number up to ``.''.
49*10465441SEvalZero * Values are specified as for C:
50*10465441SEvalZero * 0x=hex, 0=octal, 1-9=decimal.
51*10465441SEvalZero */
52*10465441SEvalZero if (!isdigit(c))
53*10465441SEvalZero {
54*10465441SEvalZero return 0;
55*10465441SEvalZero }
56*10465441SEvalZero val = 0;
57*10465441SEvalZero base = 10;
58*10465441SEvalZero if (c == '0')
59*10465441SEvalZero {
60*10465441SEvalZero c = *++cp;
61*10465441SEvalZero if (c == 'x' || c == 'X')
62*10465441SEvalZero {
63*10465441SEvalZero base = 16;
64*10465441SEvalZero c = *++cp;
65*10465441SEvalZero }
66*10465441SEvalZero else
67*10465441SEvalZero {
68*10465441SEvalZero base = 8;
69*10465441SEvalZero }
70*10465441SEvalZero }
71*10465441SEvalZero for (;;)
72*10465441SEvalZero {
73*10465441SEvalZero if (isdigit(c))
74*10465441SEvalZero {
75*10465441SEvalZero val = (val * base) + (u32_t) (c - '0');
76*10465441SEvalZero c = *++cp;
77*10465441SEvalZero }
78*10465441SEvalZero else if (base == 16 && isxdigit(c))
79*10465441SEvalZero {
80*10465441SEvalZero val = (val << 4) | (u32_t) (c + 10 - (islower(c) ? 'a' : 'A'));
81*10465441SEvalZero c = *++cp;
82*10465441SEvalZero }
83*10465441SEvalZero else
84*10465441SEvalZero {
85*10465441SEvalZero break;
86*10465441SEvalZero }
87*10465441SEvalZero }
88*10465441SEvalZero if (c == '.')
89*10465441SEvalZero {
90*10465441SEvalZero /*
91*10465441SEvalZero * Internet format:
92*10465441SEvalZero * a.b.c.d
93*10465441SEvalZero * a.b.c (with c treated as 16 bits)
94*10465441SEvalZero * a.b (with b treated as 24 bits)
95*10465441SEvalZero */
96*10465441SEvalZero if (pp >= parts + 3)
97*10465441SEvalZero {
98*10465441SEvalZero return 0;
99*10465441SEvalZero }
100*10465441SEvalZero *pp++ = val;
101*10465441SEvalZero c = *++cp;
102*10465441SEvalZero }
103*10465441SEvalZero else
104*10465441SEvalZero {
105*10465441SEvalZero break;
106*10465441SEvalZero }
107*10465441SEvalZero }
108*10465441SEvalZero /*
109*10465441SEvalZero * Check for trailing characters.
110*10465441SEvalZero */
111*10465441SEvalZero if (c != '\0' && !isspace(c))
112*10465441SEvalZero {
113*10465441SEvalZero return 0;
114*10465441SEvalZero }
115*10465441SEvalZero /*
116*10465441SEvalZero * Concoct the address according to
117*10465441SEvalZero * the number of parts specified.
118*10465441SEvalZero */
119*10465441SEvalZero switch (pp - parts + 1)
120*10465441SEvalZero {
121*10465441SEvalZero
122*10465441SEvalZero case 0:
123*10465441SEvalZero return 0; /* initial nondigit */
124*10465441SEvalZero
125*10465441SEvalZero case 1: /* a -- 32 bits */
126*10465441SEvalZero break;
127*10465441SEvalZero
128*10465441SEvalZero case 2: /* a.b -- 8.24 bits */
129*10465441SEvalZero if (val > 0xffffffUL)
130*10465441SEvalZero {
131*10465441SEvalZero return 0;
132*10465441SEvalZero }
133*10465441SEvalZero if (parts[0] > 0xff)
134*10465441SEvalZero {
135*10465441SEvalZero return 0;
136*10465441SEvalZero }
137*10465441SEvalZero val |= parts[0] << 24;
138*10465441SEvalZero break;
139*10465441SEvalZero
140*10465441SEvalZero case 3: /* a.b.c -- 8.8.16 bits */
141*10465441SEvalZero if (val > 0xffff)
142*10465441SEvalZero {
143*10465441SEvalZero return 0;
144*10465441SEvalZero }
145*10465441SEvalZero if ((parts[0] > 0xff) || (parts[1] > 0xff))
146*10465441SEvalZero {
147*10465441SEvalZero return 0;
148*10465441SEvalZero }
149*10465441SEvalZero val |= (parts[0] << 24) | (parts[1] << 16);
150*10465441SEvalZero break;
151*10465441SEvalZero
152*10465441SEvalZero case 4: /* a.b.c.d -- 8.8.8.8 bits */
153*10465441SEvalZero if (val > 0xff)
154*10465441SEvalZero {
155*10465441SEvalZero return 0;
156*10465441SEvalZero }
157*10465441SEvalZero if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
158*10465441SEvalZero {
159*10465441SEvalZero return 0;
160*10465441SEvalZero }
161*10465441SEvalZero val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
162*10465441SEvalZero break;
163*10465441SEvalZero default:
164*10465441SEvalZero RT_ASSERT(0);
165*10465441SEvalZero break;
166*10465441SEvalZero }
167*10465441SEvalZero if (addr)
168*10465441SEvalZero {
169*10465441SEvalZero ip4_addr_set_u32(addr, htonl(val));
170*10465441SEvalZero }
171*10465441SEvalZero return 1;
172*10465441SEvalZero }
173*10465441SEvalZero
174*10465441SEvalZero /**
175*10465441SEvalZero * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
176*10465441SEvalZero *
177*10465441SEvalZero * @param addr ip address in network order to convert
178*10465441SEvalZero * @param buf target buffer where the string is stored
179*10465441SEvalZero * @param buflen length of buf
180*10465441SEvalZero * @return either pointer to buf which now holds the ASCII
181*10465441SEvalZero * representation of addr or NULL if buf was too small
182*10465441SEvalZero */
sal_ip4addr_ntoa_r(const ip4_addr_t * addr,char * buf,int buflen)183*10465441SEvalZero char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
184*10465441SEvalZero {
185*10465441SEvalZero u32_t s_addr;
186*10465441SEvalZero char inv[3];
187*10465441SEvalZero char *rp;
188*10465441SEvalZero u8_t *ap;
189*10465441SEvalZero u8_t rem;
190*10465441SEvalZero u8_t n;
191*10465441SEvalZero u8_t i;
192*10465441SEvalZero int len = 0;
193*10465441SEvalZero
194*10465441SEvalZero s_addr = ip4_addr_get_u32(addr);
195*10465441SEvalZero
196*10465441SEvalZero rp = buf;
197*10465441SEvalZero ap = (u8_t *) &s_addr;
198*10465441SEvalZero for (n = 0; n < 4; n++)
199*10465441SEvalZero {
200*10465441SEvalZero i = 0;
201*10465441SEvalZero do
202*10465441SEvalZero {
203*10465441SEvalZero rem = *ap % (u8_t) 10;
204*10465441SEvalZero *ap /= (u8_t) 10;
205*10465441SEvalZero inv[i++] = (char) ('0' + rem);
206*10465441SEvalZero } while (*ap);
207*10465441SEvalZero while (i--)
208*10465441SEvalZero {
209*10465441SEvalZero if (len++ >= buflen)
210*10465441SEvalZero {
211*10465441SEvalZero return NULL;
212*10465441SEvalZero }
213*10465441SEvalZero *rp++ = inv[i];
214*10465441SEvalZero }
215*10465441SEvalZero if (len++ >= buflen)
216*10465441SEvalZero {
217*10465441SEvalZero return NULL;
218*10465441SEvalZero }
219*10465441SEvalZero *rp++ = '.';
220*10465441SEvalZero ap++;
221*10465441SEvalZero }
222*10465441SEvalZero *--rp = 0;
223*10465441SEvalZero return buf;
224*10465441SEvalZero }
225*10465441SEvalZero
226*10465441SEvalZero
227*10465441SEvalZero /**
228*10465441SEvalZero * Convert numeric IP address into decimal dotted ASCII representation.
229*10465441SEvalZero * returns ptr to static buffer; not reentrant!
230*10465441SEvalZero *
231*10465441SEvalZero * @param addr ip address in network order to convert
232*10465441SEvalZero * @return pointer to a global static (!) buffer that holds the ASCII
233*10465441SEvalZero * representation of addr
234*10465441SEvalZero */
sal_ip4addr_ntoa(const ip4_addr_t * addr)235*10465441SEvalZero char *sal_ip4addr_ntoa(const ip4_addr_t *addr)
236*10465441SEvalZero {
237*10465441SEvalZero static char str[IP4ADDR_STRLEN_MAX];
238*10465441SEvalZero return sal_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
239*10465441SEvalZero }
240*10465441SEvalZero
241*10465441SEvalZero
242*10465441SEvalZero /**
243*10465441SEvalZero * Ascii internet address interpretation routine.
244*10465441SEvalZero * The value returned is in network order.
245*10465441SEvalZero *
246*10465441SEvalZero * @param cp IP address in ascii representation (e.g. "127.0.0.1")
247*10465441SEvalZero * @return ip address in network order
248*10465441SEvalZero */
sal_ipaddr_addr(const char * cp)249*10465441SEvalZero in_addr_t sal_ipaddr_addr(const char *cp)
250*10465441SEvalZero {
251*10465441SEvalZero ip4_addr_t val;
252*10465441SEvalZero
253*10465441SEvalZero if (sal_ip4addr_aton(cp, &val)) {
254*10465441SEvalZero return ip4_addr_get_u32(&val);
255*10465441SEvalZero }
256*10465441SEvalZero return (IPADDR_NONE);
257*10465441SEvalZero }
258