8887362d69a52a765023e5228e5162d019713642
[tpg/acess2.git] / Usermode / Libraries / libnet.so_src / address.c
1 /*
2  * Acess2 Networking Toolkit
3  * By John Hodge (thePowersGang)
4  * 
5  * address.c
6  * - Address Parsing
7  */
8 #include <net.h>
9 #include <stdint.h>
10 //#include <stdio.h>
11 #include <stdlib.h>
12 #define DEBUG   0
13
14 static inline uint32_t htonl(uint32_t v)
15 {
16         return    (((v >> 24) & 0xFF) <<  0)
17                 | (((v >> 16) & 0xFF) <<  8)
18                 | (((v >>  8) & 0xFF) << 16)
19                 | (((v >>  0) & 0xFF) << 24);
20 }
21 static inline uint16_t htons(uint16_t v)
22 {
23         return    (((v >> 8) & 0xFF) <<  0)
24                 | (((v >> 0) & 0xFF) <<  8);
25 }
26 #define htonb(v)        v
27 #define ntohl(v)        htonl(v)
28 #define ntohs(v)        htons(v)
29 #define ntohb(v)        v
30
31 #define __thread                // Disable TLS
32
33 /**
34  * \brief Read an IPv4 Address
35  * \param String        IPv4 dotted decimal address
36  * \param Addr  Output 32-bit representation of IP address
37  * \return Boolean success
38  */
39 static int Net_ParseIPv4Addr(const char *String, uint8_t *Addr)
40 {
41          int    j;
42         const char *pos = String;
43         
44         for( j = 0; *pos && j < 4; j ++ )
45         {
46                 char    *end;
47                 unsigned long val = strtoul(pos, &end, 10);
48                 if( *end && *end != '.' ) {
49                         #if DEBUG
50                         _SysDebug("%s: Unexpected character, '%c' found", __func__, *end);
51                         #endif
52                         return 0;
53                 }
54                 if( *pos == '.' ) {
55                         #if DEBUG
56                         _SysDebug("%s: Two dots in a row", __func__);
57                         #endif
58                         return 0;
59                 }
60                 if(val > 255) {
61                         #if DEBUG
62                         _SysDebug("%s: val > 255 (%i)", __func__, val);
63                         #endif
64                         return 0;
65                 }
66                 #if DEBUG
67                 _SysDebug("%s: Comp '%.*s' = %lu", __func__, end - pos, pos, val);
68                 #endif
69                 Addr[j] = val;
70                 
71                 pos = end;
72                 
73                 if(*pos == '.')
74                         pos ++;
75         }
76         if( j != 4 ) {
77                 #if DEBUG
78                 _SysDebug("%s: 4 parts expected, %i found", __func__, j);
79                 #endif
80                 return 0;
81         }
82         if(*pos != '\0') {
83                 #if DEBUG
84                 _SysDebug("%s: EOS != '\\0', '%c'", __func__, *pos);
85                 #endif
86                 return 0;
87         }
88         return 1;
89 }
90
91 /**
92  * \brief Read an IPv6 Address
93  * \param String        IPv6 colon-hex representation
94  * \param Addr  Output 128-bit representation of IP address
95  * \return Boolean success
96  */
97 static int Net_ParseIPv6Addr(const char *String, uint8_t *Addr)
98 {
99          int    i = 0;
100          int    j, k;
101          int    val, split = -1, end;
102         uint16_t        hi[8], low[8];
103         
104         for( j = 0; String[i] && j < 8; j ++ )
105         {
106                 if(String[i] == ':') {
107                         if(split != -1) {
108                                 #if DEBUG
109                                 printf("Two '::'s\n");
110                                 #endif
111                                 return 0;
112                         }
113                         split = j;
114                         i ++;
115                         continue;
116                 }
117                 
118                 val = 0;
119                 for( k = 0; String[i] && String[i] != ':'; i++, k++ )
120                 {
121                         val *= 16;
122                         if('0' <= String[i] && String[i] <= '9')
123                                 val += String[i] - '0';
124                         else if('A' <= String[i] && String[i] <= 'F')
125                                 val += String[i] - 'A' + 10;
126                         else if('a' <= String[i] && String[i] <= 'f')
127                                 val += String[i] - 'a' + 10;
128                         else {
129                                 #if DEBUG
130                                 printf("%c unexpected\n", String[i]);
131                                 #endif
132                                 return 0;
133                         }
134                 }
135                 
136                 if(val > 0xFFFF) {
137                         #if DEBUG
138                         printf("val (0x%x) > 0xFFFF\n", val);
139                         #endif
140                         return 0;
141                 }
142                 
143                 if(split == -1)
144                         hi[j] = val;
145                 else
146                         low[j-split] = val;
147                 
148                 if( String[i] == ':' ) {
149                         i ++;
150                 }
151         }
152         end = j;
153         
154         // Create final address
155         // - First section
156         for( j = 0; j < split; j ++ )
157         {
158                 Addr[j*2] = hi[j]>>8;
159                 Addr[j*2+1] = hi[j]&0xFF;
160         }
161         // - Zero region
162         for( ; j < 8 - (end - split); j++ )
163         {
164                 Addr[j*2] = 0;
165                 Addr[j*2+1] = 0;
166         }
167         // - Tail section
168         k = 0;
169         for( ; j < 8; j ++, k++)
170         {
171                 Addr[j*2] = low[k]>>8;
172                 Addr[j*2+1] = low[k]&0xFF;
173         }
174         
175         return 1;
176 }
177
178 /**
179  * \brief Parse an address from a string
180  * \param String        String containing an IPv4/IPv6 address
181  * \param Addr  Buffer for the address (must be >= 16 bytes)
182  * \return Address type
183  * \retval 0    Unknown address type
184  * \retval 4    IPv4 Address
185  * \retval 6    IPv6 Address
186  */
187 int Net_ParseAddress(const char *String, void *Addr)
188 {
189         if( Net_ParseIPv4Addr(String, Addr) )
190                 return 4;
191         
192         if( Net_ParseIPv6Addr(String, Addr) )
193                 return 6;
194         
195         return 0;
196 }
197
198 static const char *Net_PrintIPv4Address(const uint8_t *Address)
199 {
200         static __thread char    ret[4*3+3+1];   // '255.255.255.255\0'
201         
202         sprintf(ret, "%i.%i.%i.%i", Address[0], Address[1], Address[2], Address[3]);
203         
204         return ret;
205 }
206
207 static const char *Net_PrintIPv6Address(const uint16_t *Address)
208 {
209         static __thread char    ret[8*4+7+1];   // 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF\0'
210         #if 0
211         // TODO: Zero compression
212          int    zeroStart = 0, zeroEnd = 8;
213         for( i = 0; i < 8; i ++ ) {
214                 if( 
215         }
216         #endif
217         
218         sprintf(ret, "%x:%x:%x:%x:%x:%x:%x:%x",
219                 ntohs(Address[0]), ntohs(Address[1]), ntohs(Address[2]), ntohs(Address[3]),
220                 ntohs(Address[4]), ntohs(Address[5]), ntohs(Address[6]), ntohs(Address[7])
221                 );
222         
223         return ret;
224 }
225
226 const char *Net_PrintAddress(int AddressType, const void *Address)
227 {
228         switch( AddressType )
229         {
230         case 0: return "";
231         
232         case 4:
233                 return Net_PrintIPv4Address(Address);
234         
235         case 6:
236                 return Net_PrintIPv6Address(Address);
237                 
238         default:
239                 return "BAD";
240         }
241 }

UCC git Repository :: git.ucc.asn.au