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);
137 printf("%s:\t", Name);
139 int call_num = ioctl(fd, 3, "get_device");
140 int len = ioctl(fd, call_num, NULL);
141 char *buf = malloc(len+1);
142 ioctl(fd, call_num, buf);
143 printf("'%s'\t", buf);
146 // Get the address type
149 case 0: // Disabled/Unset
150 printf("DISABLED\n");
157 ioctl(fd, 5, ip); // Get IP Address
158 subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
159 printf("\tAddress: %i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet);
160 ioctl(fd, 8, ip); // Get Gateway
161 printf("\tGateway: %i.%i.%i.%i\n", ip[0], ip[1], ip[2], ip[3]);
169 ioctl(fd, 5, ip); // Get IP Address
170 subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
171 printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
172 ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
173 ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]),
178 printf("UNKNOWN (%i)\n", type);
187 * \brief Create a new interface using the passed device
188 * \param Device Network device to bind to
190 int AddInterface(const char *Device)
194 dp = open(IPSTACK_ROOT, OPENFLAG_READ);
195 ret = ioctl(dp, 4, (void*)Device);
199 fprintf(stderr, "Unable to add '%s' as a network interface\n", Device);
203 printf("-- Added '"IPSTACK_ROOT"/%i' using device %s\n", ret, Device);
209 * \note Debugging HACK!
210 * \brief Autoconfigure the specified device to 10.0.2.55/8 using
211 * 10.0.2.1 as the gateway.
213 int DoAutoConfig(const char *Device)
216 char path[sizeof(IPSTACK_ROOT)+5+1]; // ip000
217 uint8_t addr[4] = {10,0,2,55};
218 uint8_t gw[4] = {10,0,2,1};
221 tmp = AddInterface(Device);
222 if( tmp < 0 ) return tmp;
224 sprintf(path, IPSTACK_ROOT"/%i", tmp);
226 fd = open(path, OPENFLAG_READ);
228 fprintf(stderr, "Unable to open '%s'\n", path);
233 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
235 fprintf(stderr, "Error in setting address type (got %i, expected 4)\n", tmp);
239 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
241 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
243 ioctl(fd, ioctl(fd, 3, "set_gateway"), gw);
247 printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n",
248 addr[0], addr[1], addr[2], addr[3],
250 gw[0], gw[1], gw[2], gw[3]);
256 * \brief Set the address on an interface from a textual IP address
258 int SetAddress(int IFNum, const char *Address)
262 char path[sizeof(IPSTACK_ROOT)+1+5+1]; // ip000
266 type = ParseIPAddres(Address, addr, &subnet);
268 fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address);
273 sprintf(path, IPSTACK_ROOT"/%i", IFNum);
274 fd = open(path, OPENFLAG_READ);
276 fprintf(stderr, "Unable to open '%s'\n", path);
281 tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
283 fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
288 ioctl(fd, ioctl(fd, 3, "set_address"), addr);
291 ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
296 //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
302 * \brief Parse an IP Address
303 * \return 0 for unknown, 4 for IPv4 and 6 for IPv6
305 int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits)
307 const char *p = Address;
310 while(*p && *p >= '0' && *p <= '9') p ++;
318 for( j = 0; Address[i] && j < 4; j ++ )
321 for( ; '0' <= Address[i] && Address[i] <= '9'; i++ )
323 val = val*10 + Address[i] - '0';
326 //printf("val > 255 (%i)\n", val);
331 if(Address[i] == '.')
335 //printf("4 parts expected, %i found\n", j);
339 if(Address[i] == '/') {
342 while('0' <= Address[i] && Address[i] <= '9') {
344 val += Address[i] - '0';
348 printf("Notice: Subnet size >32 (%i)\n", val);
352 if(Address[i] != '\0') {
353 //printf("EOS != '\\0', '%c'\n", Address[i]);
360 if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F'))
364 int val, split = -1, end;
365 uint16_t hi[8], low[8];
367 for( j = 0; Address[i] && j < 8; j ++ )
369 if(Address[i] == '/')
372 if(Address[i] == ':') {
374 printf("Two '::'s\n");
383 for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ )
386 if('0' <= Address[i] && Address[i] <= '9')
387 val += Address[i] - '0';
388 else if('A' <= Address[i] && Address[i] <= 'F')
389 val += Address[i] - 'A' + 10;
390 else if('a' <= Address[i] && Address[i] <= 'f')
391 val += Address[i] - 'a' + 10;
393 printf("%c unexpected\n", Address[i]);
399 printf("val (0x%x) > 0xFFFF\n", val);
408 if( Address[i] == ':' ) {
415 if(Address[i] == '/') {
417 while('0' <= Address[i] && Address[i] <= '9') {
419 val += Address[i] - '0';
423 printf("Notice: Subnet size >128 (%i)\n", val);
428 for( j = 0; j < split; j ++ )
430 //printf("%04x:", hi[j]);
431 Dest[j*2] = hi[j]>>8;
432 Dest[j*2+1] = hi[j]&0xFF;
434 for( ; j < 8 - (end - split); j++ )
436 //printf("0000:", hi[j]);
440 for( k = 0; j < 8; j ++, k++)
442 //printf("%04x:", low[k]);
443 Dest[j*2] = low[k]>>8;
444 Dest[j*2+1] = low[k]&0xFF;