2 * Acess2 IFCONFIG command
12 #define FILENAME_MAX 255
13 #define IPSTACK_ROOT "/Devices/ip"
15 // TODO: Move this to a header
16 #define ntohs(v) (((v&0xFF)<<8)|((v>>8)&0xFF))
19 void PrintUsage(const char *ProgName);
20 void DumpInterfaces(void);
21 void DumpRoutes(void);
22 void DumpInterface(const char *Name);
23 void DumpRoute(const char *Name);
24 int AddInterface(const char *Device);
25 void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop);
26 int DoAutoConfig(const char *Device);
27 int SetAddress(int IFNum, const char *Address);
28 int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits);
32 * \brief Program entrypoint
34 int main(int argc, char *argv[])
38 // No args, dump interfaces
44 if( strcmp(argv[1], "routes") == 0 ) {
49 // Add a new interface
50 if( strcmp(argv[1], "add") == 0 ) {
52 fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2);
56 // TODO: Also set the IP address as the usage says it does
57 ret = AddInterface( argv[2] );
58 if(ret < 0) return ret;
59 ret = SetAddress( ret, argv[3] );
63 // Delete an interface
64 if( strcmp(argv[1], "del") == 0 ) {
66 fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]);
73 // Autoconfigure an interface
74 // NOTE: Debugging hack (see the function for more details)
75 if( strcmp(argv[1], "autoconf") == 0 ) {
76 DoAutoConfig(argv[2]);
80 // Print usage instructions
87 * \brief Print usage instructions
89 void PrintUsage(const char *ProgName)
91 fprintf(stderr, "Usage:\n");
92 fprintf(stderr, " %s add <device> <ip>/<prefix>\n", ProgName);
93 fprintf(stderr, " Add a new interface listening on <device> with the specified\n");
94 fprintf(stderr, " address.\n");
95 fprintf(stderr, " %s del <interface>\n", ProgName);
96 fprintf(stderr, " %s set <interface> <option> <value>\n", ProgName);
97 fprintf(stderr, " Set an option on an interface, a list of valid options follows\n");
98 fprintf(stderr, " gw IPv4 default gateway\n");
99 fprintf(stderr, " %s [<interface>]\n", ProgName);
100 fprintf(stderr, " Print the current interfaces (or only <interface> if passed)\n");
101 fprintf(stderr, "\n");
102 fprintf(stderr, "A note on Acess's IP Stack:\n");
103 fprintf(stderr, " Each interface corresponds to only one IP address (either IPv4\n");
104 fprintf(stderr, " or IPv6). A network device can have multiple interfaces bound\n");
105 fprintf(stderr, " to it, allowing multiple addresses for one network connection\n");
106 fprintf(stderr, "\n");
110 * \brief Dump all interfaces
112 void DumpInterfaces(void)
115 char filename[FILENAME_MAX+1];
117 dp = open(IPSTACK_ROOT, OPENFLAG_READ);
119 while( readdir(dp, filename) )
121 if(filename[0] == '.') continue;
122 DumpInterface(filename);
129 * \brief Dump all interfaces
131 void DumpRoutes(void)
134 char filename[FILENAME_MAX+1];
136 dp = open(IPSTACK_ROOT"/routes", OPENFLAG_READ);
138 while( readdir(dp, filename) )
140 if(filename[0] == '.') continue;
148 * \brief Dump an interface
150 void DumpInterface(const char *Name)
154 char path[sizeof(IPSTACK_ROOT)+1+FILENAME_MAX+1] = IPSTACK_ROOT"/";
158 fd = open(path, OPENFLAG_READ);
160 printf("%s:\tUnable to open ('%s')\n", Name, path);
164 type = ioctl(fd, 4, NULL);
171 printf("%s:\t", Name);
173 int call_num = ioctl(fd, 3, "get_device");
174 int len = ioctl(fd, call_num, NULL);
175 char *buf = malloc(len+1);
176 ioctl(fd, call_num, buf);
177 printf("'%s'\t", buf);
180 // Get the address type
183 case 0: // Disabled/Unset
184 printf("DISABLED\n");
191 ioctl(fd, 5, ip); // Get IP Address
192 subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
193 printf("\tAddress: %i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet);
201 ioctl(fd, 5, ip); // Get IP Address
202 subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
203 printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
204 ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
205 ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]),
210 printf("UNKNOWN (%i)\n", type);
220 * \brief Dump a route
222 void DumpRoute(const char *Name)
226 char path[sizeof(IPSTACK_ROOT)+8+FILENAME_MAX+1] = IPSTACK_ROOT"/routes/";
230 fd = open(path, OPENFLAG_READ);
232 printf("%s:\tUnable to open ('%s')\n", Name, path);
236 type = ioctl(fd, 4, NULL);
243 printf("%s:\t", Name);
245 int call_num = ioctl(fd, 3, "get_interface");
246 int len = ioctl(fd, call_num, NULL);
247 char *buf = malloc(len+1);
248 ioctl(fd, call_num, buf);
249 printf("'%s'\t", buf);
253 // Get the address type
256 case 0: // Disabled/Unset
257 printf("DISABLED\n");
261 uint8_t net[4], addr[4];
264 ioctl(fd, ioctl(fd, 3, "get_network"), net); // Get Network
265 ioctl(fd, ioctl(fd, 3, "get_nexthop"), addr); // Get Gateway/NextHop
266 subnet = ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), NULL); // Get Subnet Bits
267 metric = ioctl(fd, ioctl(fd, 3, "getset_metric"), NULL); // Get Subnet Bits
268 printf("\tNetwork: %s/%i\n", Net_PrintAddress(4, net), subnet);
269 printf("\tGateway: %s\n", Net_PrintAddress(4, addr));
270 printf("\tMetric: %i\n", metric);
275 uint16_t net[8], addr[8];
278 ioctl(fd, ioctl(fd, 3, "get_network"), net); // Get Network
279 ioctl(fd, ioctl(fd, 3, "get_nexthop"), addr); // Get Gateway/NextHop
280 subnet = ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), NULL); // Get Subnet Bits
281 metric = ioctl(fd, ioctl(fd, 3, "getset_metric"), NULL); // Get Subnet Bits
282 printf("\tNetwork: %s/%i\n", Net_PrintAddress(6, net), subnet);
283 printf("\tGateway: %s\n", Net_PrintAddress(6, addr));
284 printf("\tMetric: %i\n", metric);
288 printf("UNKNOWN (%i)\n", type);
297 * \brief Create a new interface using the passed device
298 * \param Device Network device to bind to
300 int AddInterface(const char *Device)
304 dp = open(IPSTACK_ROOT, OPENFLAG_READ);
305 ret = ioctl(dp, 4, (void*)Device);
309 fprintf(stderr, "Unable to add '%s' as a network interface\n", Device);
313 printf("-- Added '"IPSTACK_ROOT"/%i' using device %s\n", ret, Device);
318 void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop)
322 char tmp[sizeof(IPSTACK_ROOT"/routes/") + 5]; // enough for 4 digits
325 fd = open(IPSTACK_ROOT"/routes", 0);
326 num = ioctl(fd, ioctl(fd, 3, "add_route"), (char*)Interface);
330 sprintf(tmp, IPSTACK_ROOT"/routes/%i", num);
333 ioctl(fd, ioctl(fd, 3, "set_network"), Dest);
334 ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
335 ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), &MaskBits);
342 * \note Debugging HACK!
343 * \brief Autoconfigure the specified device to 10.0.2.55/8 using
344 * 10.0.2.1 as the gateway.
346 int DoAutoConfig(const char *Device)
349 char path[sizeof(IPSTACK_ROOT)+1+4+1]; // /0000
350 uint8_t addr[4] = {10,0,2,55};
351 uint8_t gw[4] = {10,0,2,1};
354 tmp = AddInterface(Device);
355 if( tmp < 0 ) return tmp;
357 sprintf(path, IPSTACK_ROOT"/%i", tmp);
359 fd = open(path, OPENFLAG_READ);
361 fprintf(stderr, "Unable to open '%s'\n", path);
366 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
368 fprintf(stderr, "Error in setting address type (got %i, expected 4)\n", tmp);
372 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
374 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
378 uint8_t net[4] = {0,0,0,0};
379 AddRoute(path + sizeof(IPSTACK_ROOT), addr, 8, net); // This interface
380 AddRoute(path + sizeof(IPSTACK_ROOT), net, 0, gw); // Gateway
385 printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n",
386 addr[0], addr[1], addr[2], addr[3],
388 gw[0], gw[1], gw[2], gw[3]);
394 * \brief Set the address on an interface from a textual IP address
396 int SetAddress(int IFNum, const char *Address)
400 char path[sizeof(IPSTACK_ROOT)+1+5+1]; // ip000
404 type = ParseIPAddres(Address, addr, &subnet);
406 fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
411 sprintf(path, IPSTACK_ROOT"/%i", IFNum);
412 fd = open(path, OPENFLAG_READ);
414 fprintf(stderr, "Unable to open '%s'\n", path);
419 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
421 fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
426 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
429 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
434 //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
440 * \brief Parse an IP Address
441 * \return 0 for unknown, 4 for IPv4 and 6 for IPv6
443 int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
445 const char *p = Address;
448 while(*p && *p >= '0' && *p <= '9') p ++;
456 for( j = 0; Address[i] && j < 4; j ++ )
459 for( ; '0' <= Address[i] && Address[i] <= '9'; i++ )
461 val = val*10 + Address[i] - '0';
464 //printf("val > 255 (%i)\n", val);
469 if(Address[i] == '.')
473 //printf("4 parts expected, %i found\n", j);
477 if(Address[i] == '/') {
480 while('0' <= Address[i] && Address[i] <= '9') {
482 val += Address[i] - '0';
486 printf("Notice: Subnet size >32 (%i)\n", val);
490 if(Address[i] != '\0') {
491 //printf("EOS != '\\0', '%c'\n", Address[i]);
498 if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F'))
502 int val, split = -1, end;
503 uint16_t hi[8], low[8];
505 for( j = 0; Address[i] && j < 8; j ++ )
507 if(Address[i] == '/')
510 if(Address[i] == ':') {
512 printf("Two '::'s\n");
521 for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ )
524 if('0' <= Address[i] && Address[i] <= '9')
525 val += Address[i] - '0';
526 else if('A' <= Address[i] && Address[i] <= 'F')
527 val += Address[i] - 'A' + 10;
528 else if('a' <= Address[i] && Address[i] <= 'f')
529 val += Address[i] - 'a' + 10;
531 printf("%c unexpected\n", Address[i]);
537 printf("val (0x%x) > 0xFFFF\n", val);
546 if( Address[i] == ':' ) {
553 if(Address[i] == '/') {
555 while('0' <= Address[i] && Address[i] <= '9') {
557 val += Address[i] - '0';
561 printf("Notice: Subnet size >128 (%i)\n", val);
566 for( j = 0; j < split; j ++ )
568 //printf("%04x:", hi[j]);
569 Dest[j*2] = hi[j]>>8;
570 Dest[j*2+1] = hi[j]&0xFF;
572 for( ; j < 8 - (end - split); j++ )
574 //printf("0000:", hi[j]);
578 for( k = 0; j < 8; j ++, k++)
580 //printf("%04x:", low[k]);
581 Dest[j*2] = low[k]>>8;
582 Dest[j*2+1] = low[k]&0xFF;