X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Fifconfig_src%2Fmain.c;h=8d97d1b992886bab3722a7c50c1ab8cd0dca5049;hb=e6eafcb86732068e2094f04a2452098c13256336;hp=ca9b73be9087b00762498792b2799118874c9a4a;hpb=c0078bf13fa69e05235341a2863c873b7a76180a;p=tpg%2Facess2.git diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c index ca9b73be..8d97d1b9 100644 --- a/Usermode/Applications/ifconfig_src/main.c +++ b/Usermode/Applications/ifconfig_src/main.c @@ -3,19 +3,29 @@ */ #include #include +#include #include #include +#include // === CONSTANTS === #define FILENAME_MAX 255 #define IPSTACK_ROOT "/Devices/ip" +// TODO: Move this to a header +#define ntohs(v) (((v&0xFF)<<8)|((v>>8)&0xFF)) + // === PROTOTYPES === void PrintUsage(const char *ProgName); void DumpInterfaces(void); +void DumpRoutes(void); void DumpInterface(const char *Name); +void DumpRoute(const char *Name); int AddInterface(const char *Device); +void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop); int DoAutoConfig(const char *Device); + int SetAddress(int IFNum, const char *Address); + int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits); // === CODE === /** @@ -23,21 +33,41 @@ void DumpInterface(const char *Name); */ int main(int argc, char *argv[]) { + int ret; + // No args, dump interfaces if(argc == 1) { DumpInterfaces(); return 0; } + if( strcmp(argv[1], "routes") == 0 ) { + DumpRoutes(); + return 0; + } + // Add a new interface if( strcmp(argv[1], "add") == 0 ) { if( argc < 4 ) { - fprintf(stderr, "ERROR: %s add require two arguments, %i passed\n", argv[0], argc-2); + fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2); PrintUsage(argv[0]); - return 0; + return -1; } // TODO: Also set the IP address as the usage says it does - return AddInterface( argv[2] ); + ret = AddInterface( argv[2] ); + if(ret < 0) return ret; + ret = SetAddress( ret, argv[3] ); + return ret; + } + + // Delete an interface + if( strcmp(argv[1], "del") == 0 ) { + if( argc < 3 ) { + fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]); + PrintUsage(argv[0]); + return -1; + } + // TODO: } // Autoconfigure an interface @@ -95,6 +125,25 @@ void DumpInterfaces(void) close(dp); } +/** + * \brief Dump all interfaces + */ +void DumpRoutes(void) +{ + int dp; + char filename[FILENAME_MAX+1]; + + dp = open(IPSTACK_ROOT"/routes", OPENFLAG_READ); + + while( readdir(dp, filename) ) + { + if(filename[0] == '.') continue; + DumpRoute(filename); + } + + close(dp); +} + /** * \brief Dump an interface */ @@ -114,6 +163,11 @@ void DumpInterface(const char *Name) type = ioctl(fd, 4, NULL); + // Ignore -1 values + if( type == -1 ) { + return ; + } + printf("%s:\t", Name); { int call_num = ioctl(fd, 3, "get_device"); @@ -137,8 +191,6 @@ void DumpInterface(const char *Name) ioctl(fd, 5, ip); // Get IP Address subnet = ioctl(fd, 7, NULL); // Get Subnet Bits printf("\tAddress: %i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet); - ioctl(fd, 8, ip); // Get Gateway - printf("\tGateway: %i.%i.%i.%i\n", ip[0], ip[1], ip[2], ip[3]); } break; case 6: // IPv6 @@ -149,8 +201,8 @@ void DumpInterface(const char *Name) ioctl(fd, 5, ip); // Get IP Address subnet = ioctl(fd, 7, NULL); // Get Subnet Bits printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n", - ip[0], ip[1], ip[2], ip[3], - ip[4], ip[5], ip[6], ip[7], + ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]), + ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]), subnet); } break; @@ -163,6 +215,84 @@ void DumpInterface(const char *Name) close(fd); } + +/** + * \brief Dump a route + */ +void DumpRoute(const char *Name) +{ + int fd; + int type; + char path[sizeof(IPSTACK_ROOT)+8+FILENAME_MAX+1] = IPSTACK_ROOT"/routes/"; + + strcat(path, Name); + + fd = open(path, OPENFLAG_READ); + if(fd == -1) { + printf("%s:\tUnable to open ('%s')\n", Name, path); + return ; + } + + type = ioctl(fd, 4, NULL); + + // Ignore -1 values + if( type == -1 ) { + return ; + } + + printf("%s:\t", Name); + { + int call_num = ioctl(fd, 3, "get_interface"); + int len = ioctl(fd, call_num, NULL); + char *buf = malloc(len+1); + ioctl(fd, call_num, buf); + printf("'%s'\t", buf); + free(buf); + } + + // Get the address type + switch(type) + { + case 0: // Disabled/Unset + printf("DISABLED\n"); + break; + case 4: // IPv4 + { + uint8_t net[4], addr[4]; + int subnet, metric; + printf("IPv4\n"); + ioctl(fd, ioctl(fd, 3, "get_network"), net); // Get Network + ioctl(fd, ioctl(fd, 3, "get_nexthop"), addr); // Get Gateway/NextHop + subnet = ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), NULL); // Get Subnet Bits + metric = ioctl(fd, ioctl(fd, 3, "getset_metric"), NULL); // Get Subnet Bits + printf("\tNetwork: %s/%i\n", Net_PrintAddress(4, net), subnet); + printf("\tGateway: %s\n", Net_PrintAddress(4, addr)); + printf("\tMetric: %i\n", metric); + } + break; + case 6: // IPv6 + { + uint16_t net[8], addr[8]; + int subnet, metric; + printf("IPv6\n"); + ioctl(fd, ioctl(fd, 3, "get_network"), net); // Get Network + ioctl(fd, ioctl(fd, 3, "get_nexthop"), addr); // Get Gateway/NextHop + subnet = ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), NULL); // Get Subnet Bits + metric = ioctl(fd, ioctl(fd, 3, "getset_metric"), NULL); // Get Subnet Bits + printf("\tNetwork: %s/%i\n", Net_PrintAddress(6, net), subnet); + printf("\tGateway: %s\n", Net_PrintAddress(6, addr)); + printf("\tMetric: %i\n", metric); + } + break; + default: // Unknow + printf("UNKNOWN (%i)\n", type); + break; + } + printf("\n"); + + close(fd); +} + /** * \brief Create a new interface using the passed device * \param Device Network device to bind to @@ -173,7 +303,6 @@ int AddInterface(const char *Device) dp = open(IPSTACK_ROOT, OPENFLAG_READ); ret = ioctl(dp, 4, (void*)Device); - printf("AddInterface: ret = 0x%x = %i\n", ret, ret); close(dp); if( ret < 0 ) { @@ -186,6 +315,29 @@ int AddInterface(const char *Device) return ret; } +void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop) +{ + int fd; + int num; + char tmp[sizeof(IPSTACK_ROOT"/routes/") + 5]; // enough for 4 digits + + // Create route + fd = open(IPSTACK_ROOT"/routes", 0); + num = ioctl(fd, ioctl(fd, 3, "add_route"), (char*)Interface); + close(fd); + + // Open route + sprintf(tmp, IPSTACK_ROOT"/routes/%i", num); + fd = open(tmp, 0); + + ioctl(fd, ioctl(fd, 3, "set_network"), Dest); + ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop); + ioctl(fd, ioctl(fd, 3, "getset_subnetbits"), &MaskBits); + + close(fd); + +} + /** * \note Debugging HACK! * \brief Autoconfigure the specified device to 10.0.2.55/8 using @@ -194,10 +346,10 @@ int AddInterface(const char *Device) int DoAutoConfig(const char *Device) { int tmp, fd; - char path[sizeof(IPSTACK_ROOT)+5+1]; // ip000 + char path[sizeof(IPSTACK_ROOT)+1+4+1]; // /0000 uint8_t addr[4] = {10,0,2,55}; - uint8_t gw[4] = {10,0,2,1}; - int subnet = 8; + uint8_t gw[4] = {10,0,2,2}; + int subnet = 24; tmp = AddInterface(Device); if( tmp < 0 ) return tmp; @@ -220,8 +372,13 @@ int DoAutoConfig(const char *Device) ioctl(fd, ioctl(fd, 3, "set_address"), addr); // Set Subnet ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet); - // Set Gateway - ioctl(fd, ioctl(fd, 3, "set_gateway"), gw); + + // Set routes + { + uint8_t net[4] = {0,0,0,0}; + AddRoute(path + sizeof(IPSTACK_ROOT), addr, subnet, net); // This interface + AddRoute(path + sizeof(IPSTACK_ROOT), net, 0, gw); // Gateway + } close(fd); @@ -232,3 +389,200 @@ int DoAutoConfig(const char *Device) return 0; } + +/** + * \brief Set the address on an interface from a textual IP address + */ +int SetAddress(int IFNum, const char *Address) +{ + uint8_t addr[16]; + int type; + char path[sizeof(IPSTACK_ROOT)+1+5+1]; // ip000 + int tmp, fd, subnet; + + // Parse IP Address + type = ParseIPAddres(Address, addr, &subnet); + if(type == 0) { + fprintf(stderr, "'%s' cannot be parsed as an IP address\n", Address); + return -1; + } + + // Open file + sprintf(path, IPSTACK_ROOT"/%i", IFNum); + fd = open(path, OPENFLAG_READ); + if( fd == -1 ) { + fprintf(stderr, "Unable to open '%s'\n", path); + return -1; + } + + tmp = type; + tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp); + if( tmp != type ) { + fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type); + close(fd); + return -1; + } + // Set Address + ioctl(fd, ioctl(fd, 3, "set_address"), addr); + + // Set Subnet + ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet); + + close(fd); + + // Dump! + //DumpInterface( path+sizeof(IPSTACK_ROOT)+1 ); + + return 0; +} + +/** + * \brief Parse an IP Address + * \return 0 for unknown, 4 for IPv4 and 6 for IPv6 + */ +int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits) +{ + const char *p = Address; + + // Check first block + while(*p && *p >= '0' && *p <= '9') p ++; + + // IPv4? + if(*p == '.') + { + int i = 0, j; + int val; + + for( j = 0; Address[i] && j < 4; j ++ ) + { + val = 0; + for( ; '0' <= Address[i] && Address[i] <= '9'; i++ ) + { + val = val*10 + Address[i] - '0'; + } + if(val > 255) { + //printf("val > 255 (%i)\n", val); + return 0; + } + Dest[j] = val; + + if(Address[i] == '.') + i ++; + } + if( j != 4 ) { + //printf("4 parts expected, %i found\n", j); + return 0; + } + // Parse subnet size + if(Address[i] == '/') { + val = 0; + i ++; + while('0' <= Address[i] && Address[i] <= '9') { + val *= 10; + val += Address[i] - '0'; + i ++; + } + if(val > 32) { + printf("Notice: Subnet size >32 (%i)\n", val); + } + *SubnetBits = val; + } + if(Address[i] != '\0') { + //printf("EOS != '\\0', '%c'\n", Address[i]); + return 0; + } + return 4; + } + + // IPv6 + if(*p == ':' || ('a' <= *p && *p <= 'f') || ('A' <= *p && *p <= 'F')) + { + int i = 0; + int j, k; + int val, split = -1, end; + uint16_t hi[8], low[8]; + + for( j = 0; Address[i] && j < 8; j ++ ) + { + if(Address[i] == '/') + break; + + if(Address[i] == ':') { + if(split != -1) { + printf("Two '::'s\n"); + return 0; + } + split = j; + i ++; + continue; + } + + val = 0; + for( k = 0; Address[i] && Address[i] != ':' && Address[i] != '/'; i++, k++ ) + { + val *= 16; + if('0' <= Address[i] && Address[i] <= '9') + val += Address[i] - '0'; + else if('A' <= Address[i] && Address[i] <= 'F') + val += Address[i] - 'A' + 10; + else if('a' <= Address[i] && Address[i] <= 'f') + val += Address[i] - 'a' + 10; + else { + printf("%c unexpected\n", Address[i]); + return 0; + } + } + + if(val > 0xFFFF) { + printf("val (0x%x) > 0xFFFF\n", val); + return 0; + } + + if(split == -1) + hi[j] = val; + else + low[j-split] = val; + + if( Address[i] == ':' ) { + i ++; + } + } + end = j; + + // Parse subnet size + if(Address[i] == '/') { + val = 0; + while('0' <= Address[i] && Address[i] <= '9') { + val *= 10; + val += Address[i] - '0'; + i ++; + } + if(val > 128) { + printf("Notice: Subnet size >128 (%i)\n", val); + } + *SubnetBits = val; + } + + for( j = 0; j < split; j ++ ) + { + //printf("%04x:", hi[j]); + Dest[j*2] = hi[j]>>8; + Dest[j*2+1] = hi[j]&0xFF; + } + for( ; j < 8 - (end - split); j++ ) + { + //printf("0000:", hi[j]); + Dest[j*2] = 0; + Dest[j*2+1] = 0; + } + for( k = 0; j < 8; j ++, k++) + { + //printf("%04x:", low[k]); + Dest[j*2] = low[k]>>8; + Dest[j*2+1] = low[k]&0xFF; + } + return 6; + } + // Unknown type + return 0; +}