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

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