xref: /nrf52832-nimble/rt-thread/components/net/sal_socket/src/sal_ipaddr.c (revision 104654410c56c573564690304ae786df310c91fc)
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