TODO
[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(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[3], dest, &subnetBits);
54                 if( subnetBits == -1 ) {
55                         subnetBits = Net_GetAddressSize(addrType)*8;
56                 }
57                 // Interface Name / Next Hop
58                 if( (nextHopType = ParseIPAddress(argv[4], nextHop, &nextHopBits)) == 0 )
59                 {
60                         // Interface name
61                         ifaceName = argv[4];
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[5]);
82                         if( metric == 0 && argv[5][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 = open(IPSTACK_ROOT"/routes", OPENFLAG_READ);
118         
119         printf("Type\tNetwork \tGateway \tMetric\tIFace\n");
120         
121         while( readdir(dp, filename) )
122         {
123                 if(filename[0] == '.')  continue;
124                 DumpRoute(filename);
125         }
126         
127         close(dp);
128 }
129
130 /**
131  * \brief Dump a route
132  */
133 void DumpRoute(const char *Name)
134 {
135          int    fd;
136          int    type;
137         char    path[sizeof(IPSTACK_ROOT)+8+FILENAME_MAX+1] = IPSTACK_ROOT"/routes/";
138         
139         strcat(path, Name);
140         
141         fd = open(path, OPENFLAG_READ);
142         if(fd == -1) {
143                 printf("%s:\tUnable to open ('%s')\n", Name, path);
144                 return ;
145         }
146         
147          int    ofs = 2;
148         type = atoi(Name);
149         
150          int    i;
151          int    len = Net_GetAddressSize(type);
152         uint8_t net[len], gw[len];
153          int    subnet, metric;
154         for( i = 0; i < len; i ++ ) {
155                 char tmp[5] = "0x00";
156                 tmp[2] = Name[ofs++];
157                 tmp[3] = Name[ofs++];
158                 net[i] = atoi(tmp);
159         }
160         ofs ++;
161         subnet = atoi(Name+ofs);
162         ofs ++;
163         metric = atoi(Name+ofs);
164         ioctl(fd, ioctl(fd, 3, "get_nexthop"), gw);     // Get Gateway/NextHop
165         
166         // Get the address type
167         switch(type)
168         {
169         case 0: // Disabled/Unset
170                 printf("DISABLED\n");
171                 break;
172         case 4: // IPv4
173                 printf("IPv4\t");
174                 break;
175         case 6: // IPv6
176                 printf("IPv6\t");
177                 break;
178         default:        // Unknow
179                 printf("UNKNOWN (%i)\n", type);
180                 break;
181         }
182         printf("%s/%i\t", Net_PrintAddress(type, net), subnet);
183         printf("%s \t", Net_PrintAddress(type, gw));
184         printf("%i\t", metric);
185         
186         // Interface
187         {
188                  int    call_num = ioctl(fd, 3, "get_interface");
189                  int    len = ioctl(fd, call_num, NULL);
190                 char    *buf = malloc(len+1);
191                 ioctl(fd, call_num, buf);
192                 printf("'%s'\t", buf);
193                 free(buf);
194         }
195         
196         printf("\n");
197                         
198         close(fd);
199 }
200
201 void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop)
202 {
203          int    fd;
204          int    num;
205         char    *ifaceToFree = NULL;
206         
207         // Get interface name
208         if( !Interface )
209         {
210                 if( !NextHop ) {
211                         fprintf(stderr,
212                                 "BUG: AddRoute(Interface=NULL,...,NextHop=NULL)\n"
213                                 "Only one should be NULL\n"
214                                 );
215                         return ;
216                 }
217                 
218                 // Query for the interface name
219                 Interface = ifaceToFree = Net_GetInterface(AddressType, NextHop);
220         }
221         // Check address type (if the interface was passed)
222         // - If we got the interface name, then it should be correct
223         else
224         {
225                 char    ifacePath[sizeof(IPSTACK_ROOT"/")+strlen(Interface)+1];
226                 
227                 // Open interface
228                 strcpy(ifacePath, IPSTACK_ROOT"/");
229                 strcat(ifacePath, Interface);
230                 fd = open(ifacePath, 0);
231                 if( fd == -1 ) {
232                         fprintf(stderr, "Error: Interface '%s' does not exist\n", Interface);
233                         return ;
234                 }
235                 // Get and check type
236                 num = ioctl(fd, ioctl(fd, 3, "getset_type"), NULL);
237                 if( num != AddressType ) {
238                         fprintf(stderr, "Error: Passed type does not match interface type (%i != %i)\n",
239                                 AddressType, num);
240                         return ;
241                 }
242                 
243                 close(fd);
244         }
245         
246         // Create route
247          int    addrsize = Net_GetAddressSize(AddressType);
248          int    len = snprintf(NULL, 0, "/Devices/ip/routes/%i::%i:%i", AddressType, MaskBits, Metric) + addrsize*2;
249         char    path[len+1];
250         {
251                  int    i, ofs;
252                 ofs = sprintf(path, "/Devices/ip/routes/%i:", AddressType);
253                 for( i = 0; i < addrsize; i ++ )
254                         sprintf(path+ofs+i*2, "%02x", ((uint8_t*)Dest)[i]);
255                 ofs += addrsize*2;
256                 sprintf(path+ofs, ":%i:%i", MaskBits, Metric);
257         }
258
259         fd = open(path, 0);
260         if( fd != -1 ) {
261                 close(fd);
262                 fprintf(stderr, "Unable to create route '%s', already exists\n", path);
263                 return ;
264         }
265         fd = open(path, OPENFLAG_CREATE, 0);
266         if( fd == -1 ) {
267                 fprintf(stderr, "Unable to create '%s'\n", path);
268                 return ;
269         }
270         
271         if( NextHop )
272                 ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
273         ioctl(fd, ioctl(fd, 3, "set_interface"), (void*)Interface);
274         
275         close(fd);
276         
277         // Check if the interface name was allocated by us
278         if( ifaceToFree )
279                 free(ifaceToFree);
280 }
281

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