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)+7+FILENAME_MAX+1] = IPSTACK_ROOT"/route/";
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)+5+1]; // ip000
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) + 1, net, 0, gw);
384 printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n",
385 addr[0], addr[1], addr[2], addr[3],
387 gw[0], gw[1], gw[2], gw[3]);
393 * \brief Set the address on an interface from a textual IP address
395 int SetAddress(int IFNum, const char *Address)
399 char path[sizeof(IPSTACK_ROOT)+1+5+1]; // ip000
403 type = ParseIPAddres(Address, addr, &subnet);
405 fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
410 sprintf(path, IPSTACK_ROOT"/%i", IFNum);
411 fd = open(path, OPENFLAG_READ);
413 fprintf(stderr, "Unable to open '%s'\n", path);
418 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
420 fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
425 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
428 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
433 //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
439 * \brief Parse an IP Address
440 * \return 0 for unknown, 4 for IPv4 and 6 for IPv6
442 int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
444 const char *p = Address;
447 while(*p && *p >= '0' && *p <= '9') p ++;
455 for( j = 0; Address[i] && j < 4; j ++ )
458 for( ; '0' <= Address[i] && Address[i] <= '9'; i++ )
460 val = val*10 + Address[i] - '0';
463 //printf("val > 255 (%i)\n", val);
468 if(Address[i] == '.')
472 //printf("4 parts expected, %i found\n", j);
476 if(Address[i] == '/') {
479 while('0' <= Address[i] && Address[i] <= '9') {
481 val += Address[i] - '0';
485 printf("Notice: Subnet size >32 (%i)\n", val);
489 if(Address[i] != '\0') {
490 //printf("EOS != '\\0', '%c'\n", Address[i]);
497 if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F'))
501 int val, split = -1, end;
502 uint16_t hi[8], low[8];
504 for( j = 0; Address[i] && j < 8; j ++ )
506 if(Address[i] == '/')
509 if(Address[i] == ':') {
511 printf("Two '::'s\n");
520 for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ )
523 if('0' <= Address[i] && Address[i] <= '9')
524 val += Address[i] - '0';
525 else if('A' <= Address[i] && Address[i] <= 'F')
526 val += Address[i] - 'A' + 10;
527 else if('a' <= Address[i] && Address[i] <= 'f')
528 val += Address[i] - 'a' + 10;
530 printf("%c unexpected\n", Address[i]);
536 printf("val (0x%x) > 0xFFFF\n", val);
545 if( Address[i] == ':' ) {
552 if(Address[i] == '/') {
554 while('0' <= Address[i] && Address[i] <= '9') {
556 val += Address[i] - '0';
560 printf("Notice: Subnet size >128 (%i)\n", val);
565 for( j = 0; j < split; j ++ )
567 //printf("%04x:", hi[j]);
568 Dest[j*2] = hi[j]>>8;
569 Dest[j*2+1] = hi[j]&0xFF;
571 for( ; j < 8 - (end - split); j++ )
573 //printf("0000:", hi[j]);
577 for( k = 0; j < 8; j ++, k++)
579 //printf("%04x:", low[k]);
580 Dest[j*2] = low[k]>>8;
581 Dest[j*2+1] = low[k]&0xFF;