Kernel - Imported userland strtoi file (and other minor changes)
[tpg/acess2.git] / Usermode / Applications / ip_src / routes.c
1 /*
2  * Acess2 ip command
3  * - By John Hodge (thePowersGang)
4  * 
5  * routes.c
6  * - `ip route` sub-command
7  */
8 #include "common.h"
9
10 #define DEFAULT_METRIC  30
11
12 // === PROTOTYPES ===
13  int    Routes_main(int argc, char *argv[]);
14 void    DumpRoutes(void);
15 void    DumpRoute(int PFD, const char *Name);
16 void    AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop);
17
18 // === CODE ===
19 int Routes_main(int argc, char *argv[])
20 {
21         if( argc <= 1 )
22         {
23                 // Show routes
24                 DumpRoutes();
25         }
26         // Add new route
27         else if( strcmp(argv[1], "add") == 0 )
28         {
29                 uint8_t dest[16] = {0};
30                 uint8_t nextHop[16] = {0};
31                  int    addrType, subnetBits = -1;
32                  int    nextHopType, nextHopBits=-1;
33                 char    *ifaceName = NULL;
34                  int    metric = DEFAULT_METRIC;
35                 // Usage:
36                 // ifconfig route add <host>[/<prefix>] <interface> [<metric>]
37                 // ifconfig route add <host>[/<prefix>] <next hop> [<metric>]
38                 if( argc - 2 < 2 ) {
39                         fprintf(stderr, "ERROR: '%s route add' takes at least two arguments, %i passed\n",
40                                 argv[0], argc-3);
41                         PrintUsage(argv[0]);
42                         return -1;
43                 }
44                 
45                 if( argc - 2 > 3 ) {
46                         fprintf(stderr, "ERROR: '%s route add' takes at most three arguments, %i passed\n",
47                                 argv[0], argc-3);
48                         PrintUsage(argv[0]);
49                         return -1;
50                 }
51                 
52                 // Destination IP
53                 addrType = ParseIPAddress(argv[2], dest, &subnetBits);
54                 if( subnetBits == -1 ) {
55                         subnetBits = Net_GetAddressSize(addrType)*8;
56                 }
57                 // Interface Name / Next Hop
58                 if( (nextHopType = ParseIPAddress(argv[3], nextHop, &nextHopBits)) == 0 )
59                 {
60                         // Interface name
61                         ifaceName = argv[3];
62                 }
63                 else
64                 {
65                         // Next Hop
66                         // - Check if it's the same type as the network/destination
67                         if( nextHopType != addrType ) {
68                                 fprintf(stderr, "ERROR: Address type mismatch\n");
69                                 return -1;
70                         }
71                         // - Make sure there's no mask
72                         if( nextHopBits != -1 ) {
73                                 fprintf(stderr, "Error: Next hop cannot be masked\n");
74                                 return -1;
75                         }
76                 }
77                 
78                 // Metric
79                 if( argc - 3 >= 3 )
80                 {
81                         metric = atoi(argv[4]);
82                         if( metric == 0 && argv[4][0] != '0' ) {
83                                 fprintf(stderr, "ERROR: Metric should be a number\n");
84                                 return -1;
85                         }
86                 }
87                 
88                 // Make the route!
89                 AddRoute(ifaceName, addrType, dest, subnetBits, metric, nextHop);
90                 
91                 return 0;
92         }
93         // Delete a route
94         else if( strcmp(argv[2], "del") == 0 )
95         {
96                 // Usage:
97                 // ifconfig route del <routenum>
98                 // ifconfig route del <host>[/<prefix>]
99         }
100         else
101         {
102                 // List routes
103                 DumpRoutes();
104         }
105         
106         return 0;
107 }
108
109 /**
110  * \brief Dump all interfaces
111  */
112 void DumpRoutes(void)
113 {
114          int    dp;
115         char    filename[FILENAME_MAX+1];
116         
117         dp = _SysOpen(IPSTACK_ROOT"/routes", OPENFLAG_READ);
118         
119         printf("Type\tNetwork \tGateway \tMetric\tIFace\n");
120         
121         while( _SysReadDir(dp, filename) )
122         {
123                 if(filename[0] == '.')  continue;
124                 DumpRoute(dp, filename);
125         }
126         
127         _SysClose(dp);
128 }
129
130 /**
131  * \brief Dump a route
132  */
133 void DumpRoute(int PFD, const char *Name)
134 {
135          int    fd;
136          int    type;
137         
138         fd = _SysOpenChild(PFD, Name, OPENFLAG_READ);
139         if(fd == -1) {
140                 printf("%s:\tUnable to open\n", Name);
141                 return ;
142         }
143         
144          int    ofs = 2;
145         type = atoi(Name);
146         
147          int    i;
148          int    len = Net_GetAddressSize(type);
149         uint8_t net[len], gw[len];
150          int    subnet, metric;
151         for( i = 0; i < len; i ++ ) {
152                 char tmp[5] = "0x00";
153                 tmp[2] = Name[ofs++];
154                 tmp[3] = Name[ofs++];
155                 net[i] = atoi(tmp);
156         }
157         ofs ++;
158         subnet = atoi(Name+ofs);
159         ofs ++;
160         metric = atoi(Name+ofs);
161         _SysIOCtl(fd, _SysIOCtl(fd, 3, "get_nexthop"), gw);     // Get Gateway/NextHop
162         
163         // Get the address type
164         switch(type)
165         {
166         case 0: // Disabled/Unset
167                 printf("DISABLED\n");
168                 break;
169         case 4: // IPv4
170                 printf("IPv4\t");
171                 break;
172         case 6: // IPv6
173                 printf("IPv6\t");
174                 break;
175         default:        // Unknow
176                 printf("UNKNOWN (%i)\n", type);
177                 break;
178         }
179         printf("%s/%i\t", Net_PrintAddress(type, net), subnet);
180         printf("%s \t", Net_PrintAddress(type, gw));
181         printf("%i\t", metric);
182         
183         // Interface
184         {
185                  int    call_num = _SysIOCtl(fd, 3, "get_interface");
186                  int    len = _SysIOCtl(fd, call_num, NULL);
187                 char    *buf = malloc(len+1);
188                 _SysIOCtl(fd, call_num, buf);
189                 printf("'%s'\t", buf);
190                 free(buf);
191         }
192         
193         printf("\n");
194                         
195         _SysClose(fd);
196 }
197
198 void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop)
199 {
200          int    fd;
201          int    num;
202         char    *ifaceToFree = NULL;
203         
204         // Get interface name
205         if( !Interface )
206         {
207                 if( !NextHop ) {
208                         fprintf(stderr,
209                                 "BUG: AddRoute(Interface=NULL,...,NextHop=NULL)\n"
210                                 "Only one should be NULL\n"
211                                 );
212                         return ;
213                 }
214                 
215                 // Query for the interface name
216                 Interface = ifaceToFree = Net_GetInterface(AddressType, NextHop);
217         }
218         // Check address type (if the interface was passed)
219         // - If we got the interface name, then it should be correct
220         else
221         {
222                 char    ifacePath[sizeof(IPSTACK_ROOT"/")+strlen(Interface)+1];
223                 
224                 // Open interface
225                 strcpy(ifacePath, IPSTACK_ROOT"/");
226                 strcat(ifacePath, Interface);
227                 fd = _SysOpen(ifacePath, 0);
228                 if( fd == -1 ) {
229                         fprintf(stderr, "Error: Interface '%s' does not exist\n", Interface);
230                         return ;
231                 }
232                 // Get and check type
233                 num = _SysIOCtl(fd, _SysIOCtl(fd, 3, "getset_type"), NULL);
234                 if( num != AddressType ) {
235                         fprintf(stderr, "Error: Passed type does not match interface type (%i != %i)\n",
236                                 AddressType, num);
237                         return ;
238                 }
239                 
240                 _SysClose(fd);
241         }
242         
243         // Create route
244          int    addrsize = Net_GetAddressSize(AddressType);
245          int    len = snprintf(NULL, 0, "/Devices/ip/routes/%i::%i:%i", AddressType, MaskBits, Metric) + addrsize*2;
246         char    path[len+1];
247         {
248                  int    i, ofs;
249                 ofs = sprintf(path, "/Devices/ip/routes/%i:", AddressType);
250                 for( i = 0; i < addrsize; i ++ )
251                         sprintf(path+ofs+i*2, "%02x", ((uint8_t*)Dest)[i]);
252                 ofs += addrsize*2;
253                 sprintf(path+ofs, ":%i:%i", MaskBits, Metric);
254         }
255
256         fd = _SysOpen(path, 0);
257         if( fd != -1 ) {
258                 _SysClose(fd);
259                 fprintf(stderr, "Unable to create route '%s', already exists\n", path);
260                 return ;
261         }
262         fd = _SysOpen(path, OPENFLAG_CREATE, 0);
263         if( fd == -1 ) {
264                 fprintf(stderr, "Unable to create '%s'\n", path);
265                 return ;
266         }
267         
268         if( NextHop )
269                 _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_nexthop"), NextHop);
270         _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_interface"), (void*)Interface);
271         
272         _SysClose(fd);
273         
274         // Check if the interface name was allocated by us
275         if( ifaceToFree )
276                 free(ifaceToFree);
277 }
278

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