2 * Acess2 IFCONFIG command
11 #define FILENAME_MAX 255
12 #define IPSTACK_ROOT "/Devices/ip"
14 // TODO: Move this to a header
15 #define ntohs(v) (((v&0xFF)<<8)|((v>>8)&0xFF))
18 void PrintUsage(const char *ProgName);
19 void DumpInterfaces(void);
20 void DumpInterface(const char *Name);
21 int AddInterface(const char *Device);
22 int DoAutoConfig(const char *Device);
23 int SetAddress(int IFNum, const char *Address);
24 int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits);
28 * \brief Program entrypoint
30 int main(int argc, char *argv[])
33 // No args, dump interfaces
39 // Add a new interface
40 if( strcmp(argv[1], "add") == 0 ) {
42 fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2);
46 // TODO: Also set the IP address as the usage says it does
47 ret = AddInterface( argv[2] );
48 if(ret < 0) return ret;
49 ret = SetAddress( ret, argv[3] );
53 // Delete an interface
54 if( strcmp(argv[1], "del") == 0 ) {
56 fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]);
63 // Autoconfigure an interface
64 // NOTE: Debugging hack (see the function for more details)
65 if( strcmp(argv[1], "autoconf") == 0 ) {
66 DoAutoConfig(argv[2]);
70 // Print usage instructions
77 * \brief Print usage instructions
79 void PrintUsage(const char *ProgName)
81 fprintf(stderr, "Usage:\n");
82 fprintf(stderr, " %s add <device> <ip>/<prefix>\n", ProgName);
83 fprintf(stderr, " Add a new interface listening on <device> with the specified\n");
84 fprintf(stderr, " address.\n");
85 fprintf(stderr, " %s del <interface>\n", ProgName);
86 fprintf(stderr, " %s set <interface> <option> <value>\n", ProgName);
87 fprintf(stderr, " Set an option on an interface, a list of valid options follows\n");
88 fprintf(stderr, " gw IPv4 default gateway\n");
89 fprintf(stderr, " %s [<interface>]\n", ProgName);
90 fprintf(stderr, " Print the current interfaces (or only <interface> if passed)\n");
91 fprintf(stderr, "\n");
92 fprintf(stderr, "A note on Acess's IP Stack:\n");
93 fprintf(stderr, " Each interface corresponds to only one IP address (either IPv4\n");
94 fprintf(stderr, " or IPv6). A network device can have multiple interfaces bound\n");
95 fprintf(stderr, " to it, allowing multiple addresses for one network connection\n");
96 fprintf(stderr, "\n");
100 * \brief Dump all interfaces
102 void DumpInterfaces(void)
105 char filename[FILENAME_MAX+1];
107 dp = open(IPSTACK_ROOT, OPENFLAG_READ);
109 while( readdir(dp, filename) )
111 if(filename[0] == '.') continue;
112 DumpInterface(filename);
119 * \brief Dump an interface
121 void DumpInterface(const char *Name)
125 char path[sizeof(IPSTACK_ROOT)+1+FILENAME_MAX+1] = IPSTACK_ROOT"/";
129 fd = open(path, OPENFLAG_READ);
131 printf("%s:\tUnable to open ('%s')\n", Name, path);
135 type = ioctl(fd, 4, NULL);
142 printf("%s:\t", Name);
144 int call_num = ioctl(fd, 3, "get_device");
145 int len = ioctl(fd, call_num, NULL);
146 char *buf = malloc(len+1);
147 ioctl(fd, call_num, buf);
148 printf("'%s'\t", buf);
151 // Get the address type
154 case 0: // Disabled/Unset
155 printf("DISABLED\n");
162 ioctl(fd, 5, ip); // Get IP Address
163 subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
164 printf("\tAddress: %i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet);
165 ioctl(fd, 8, ip); // Get Gateway
166 printf("\tGateway: %i.%i.%i.%i\n", ip[0], ip[1], ip[2], ip[3]);
174 ioctl(fd, 5, ip); // Get IP Address
175 subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
176 printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
177 ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
178 ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]),
183 printf("UNKNOWN (%i)\n", type);
192 * \brief Create a new interface using the passed device
193 * \param Device Network device to bind to
195 int AddInterface(const char *Device)
199 dp = open(IPSTACK_ROOT, OPENFLAG_READ);
200 ret = ioctl(dp, 4, (void*)Device);
204 fprintf(stderr, "Unable to add '%s' as a network interface\n", Device);
208 printf("-- Added '"IPSTACK_ROOT"/%i' using device %s\n", ret, Device);
213 void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop)
217 char tmp[sizeof(IPSTACK_ROOT"/routes/") + 5]; // enough for 4 digits
220 fd = open(IPSTACK_ROOT"/routes", 0);
221 num = ioctl(fd, ioctl(fd, 3, "add_route"), (char*)Interface);
225 sprintf(tmp, IPSTACK_ROOT"/routes/%i", num);
228 ioctl(fd, ioctl(fd, 3, "set_network"), Dest);
229 ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
230 ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), &MaskBits);
237 * \note Debugging HACK!
238 * \brief Autoconfigure the specified device to 10.0.2.55/8 using
239 * 10.0.2.1 as the gateway.
241 int DoAutoConfig(const char *Device)
244 char path[sizeof(IPSTACK_ROOT)+5+1]; // ip000
245 uint8_t addr[4] = {10,0,2,55};
246 uint8_t gw[4] = {10,0,2,1};
249 tmp = AddInterface(Device);
250 if( tmp < 0 ) return tmp;
252 sprintf(path, IPSTACK_ROOT"/%i", tmp);
254 fd = open(path, OPENFLAG_READ);
256 fprintf(stderr, "Unable to open '%s'\n", path);
261 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
263 fprintf(stderr, "Error in setting address type (got %i, expected 4)\n", tmp);
267 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
269 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
271 ioctl(fd, ioctl(fd, 3, "set_gateway"), gw);
275 printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n",
276 addr[0], addr[1], addr[2], addr[3],
278 gw[0], gw[1], gw[2], gw[3]);
284 * \brief Set the address on an interface from a textual IP address
286 int SetAddress(int IFNum, const char *Address)
290 char path[sizeof(IPSTACK_ROOT)+1+5+1]; // ip000
294 type = ParseIPAddres(Address, addr, &subnet);
296 fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
301 sprintf(path, IPSTACK_ROOT"/%i", IFNum);
302 fd = open(path, OPENFLAG_READ);
304 fprintf(stderr, "Unable to open '%s'\n", path);
309 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
311 fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
316 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
319 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
324 //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
330 * \brief Parse an IP Address
331 * \return 0 for unknown, 4 for IPv4 and 6 for IPv6
333 int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
335 const char *p = Address;
338 while(*p && *p >= '0' && *p <= '9') p ++;
346 for( j = 0; Address[i] && j < 4; j ++ )
349 for( ; '0' <= Address[i] && Address[i] <= '9'; i++ )
351 val = val*10 + Address[i] - '0';
354 //printf("val > 255 (%i)\n", val);
359 if(Address[i] == '.')
363 //printf("4 parts expected, %i found\n", j);
367 if(Address[i] == '/') {
370 while('0' <= Address[i] && Address[i] <= '9') {
372 val += Address[i] - '0';
376 printf("Notice: Subnet size >32 (%i)\n", val);
380 if(Address[i] != '\0') {
381 //printf("EOS != '\\0', '%c'\n", Address[i]);
388 if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F'))
392 int val, split = -1, end;
393 uint16_t hi[8], low[8];
395 for( j = 0; Address[i] && j < 8; j ++ )
397 if(Address[i] == '/')
400 if(Address[i] == ':') {
402 printf("Two '::'s\n");
411 for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ )
414 if('0' <= Address[i] && Address[i] <= '9')
415 val += Address[i] - '0';
416 else if('A' <= Address[i] && Address[i] <= 'F')
417 val += Address[i] - 'A' + 10;
418 else if('a' <= Address[i] && Address[i] <= 'f')
419 val += Address[i] - 'a' + 10;
421 printf("%c unexpected\n", Address[i]);
427 printf("val (0x%x) > 0xFFFF\n", val);
436 if( Address[i] == ':' ) {
443 if(Address[i] == '/') {
445 while('0' <= Address[i] && Address[i] <= '9') {
447 val += Address[i] - '0';
451 printf("Notice: Subnet size >128 (%i)\n", val);
456 for( j = 0; j < split; j ++ )
458 //printf("%04x:", hi[j]);
459 Dest[j*2] = hi[j]>>8;
460 Dest[j*2+1] = hi[j]&0xFF;
462 for( ; j < 8 - (end - split); j++ )
464 //printf("0000:", hi[j]);
468 for( k = 0; j < 8; j ++, k++)
470 //printf("%04x:", low[k]);
471 Dest[j*2] = low[k]>>8;
472 Dest[j*2+1] = low[k]&0xFF;