From 89d57929e1e4f83a55d32a1d0084e4ed0296f521 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 25 Jan 2011 21:41:13 +0800 Subject: [PATCH] IPStack / ifconfig - Routing changes - Implemented implicit routes in interface.c/routing.c > Implicit routes are routes that are constructed on the fly from an interface. - Vastly improved the route support in ifconfig - (Misc) Added some missing syscalls to Usermode/acess/sys.h --- Modules/IPStack/interface.c | 4 +- Modules/IPStack/ipstack.h | 32 ++-- Modules/IPStack/routing.c | 56 +++++++ Usermode/Applications/ifconfig_src/main.c | 185 +++++++++++++++++++--- Usermode/Libraries/libnet.so_src/net.h | 7 + Usermode/include/acess/sys.h | 3 + 6 files changed, 247 insertions(+), 40 deletions(-) diff --git a/Modules/IPStack/interface.c b/Modules/IPStack/interface.c index 50d4c229..fc79e9ef 100644 --- a/Modules/IPStack/interface.c +++ b/Modules/IPStack/interface.c @@ -251,7 +251,7 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name) iface = malloc( sizeof(tInterface) + nameLen + 1 - + IPStack_GetAddressSize(-1) + + IPStack_GetAddressSize(-1)*3 // Address, Route->Network, Route->NextHop ); if(!iface) { LEAVE('n'); @@ -261,6 +261,8 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name) iface->Next = NULL; iface->Type = 0; // Unset type iface->Address = iface->Name + nameLen + 1; // Address + iface->Route.Network = iface->Address + IPStack_GetAddressSize(-1); + iface->Route.NextHop = iface->Route.Network + IPStack_GetAddressSize(-1); // Create Node iface->Node.ImplPtr = iface; diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h index e6ded4b1..b0dff231 100644 --- a/Modules/IPStack/ipstack.h +++ b/Modules/IPStack/ipstack.h @@ -38,21 +38,6 @@ struct sMacAddr { Uint8 B[6]; } __attribute__((packed)); -struct sInterface { - struct sInterface *Next; //!< Next interface in list - - tVFS_Node Node; //!< Node to use the interface - - tAdapter *Adapter; //!< Adapter the interface is associated with - int TimeoutDelay; //!< Time in miliseconds before a packet times out - int Type; //!< Interface type, see ::eInterfaceTypes - - void *Address; //!< IP address (stored after the Name) - int SubnetBits; //!< Number of bits that denote the address network - - char Name[]; -}; - /** * \brief Route definition structure */ @@ -69,6 +54,23 @@ typedef struct sRoute { int Metric; //!< Route priority } tRoute; +struct sInterface { + struct sInterface *Next; //!< Next interface in list + + tVFS_Node Node; //!< Node to use the interface + + tAdapter *Adapter; //!< Adapter the interface is associated with + int TimeoutDelay; //!< Time in miliseconds before a packet times out + int Type; //!< Interface type, see ::eInterfaceTypes + + void *Address; //!< IP address (stored after the Name) + int SubnetBits; //!< Number of bits that denote the address network + + tRoute Route; //!< Interface route + + char Name[]; +}; + /** * \brief Represents a network adapter */ diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c index 53d5c885..26817b65 100644 --- a/Modules/IPStack/routing.c +++ b/Modules/IPStack/routing.c @@ -251,6 +251,8 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) { tRoute *rt; tRoute *best = NULL; + tInterface *iface; + int addrSize; ENTER("iAddressType pInterface sAddress", AddressType, Interface, IPStack_PrintAddress(AddressType, Address)); @@ -261,6 +263,10 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) return NULL; } + // Get address size + addrSize = IPStack_GetAddressSize(AddressType); + + // Check against explicit routes for( rt = gIP_Routes; rt; rt = rt->Next ) { // Check interface @@ -290,6 +296,56 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) best = rt; } + // Check against implicit routes + if( !best && !Interface ) + { + for( iface = gIP_Interfaces; iface; iface = iface->Next ) + { + if( Interface && iface != Interface ) continue; + if( iface->Type != AddressType ) continue; + + + // Check if the address matches + if( !IPStack_CompareAddress(AddressType, iface->Address, Address, iface->SubnetBits) ) + continue; + + if( best ) { + // More direct routes are preferred + if( best->SubnetBits > rt->SubnetBits ) { + LOG("Skipped - less direct (%i < %i)", rt->SubnetBits, best->SubnetBits); + continue; + } + // If equally direct, choose the best metric + if( best->SubnetBits == rt->SubnetBits && best->Metric < rt->Metric ) { + LOG("Skipped - higher metric (%i > %i)", rt->Metric, best->Metric); + continue; + } + } + + rt = &iface->Route; + memcpy(rt->Network, iface->Address, addrSize); + memset(rt->NextHop, 0, addrSize); + rt->Metric = DEFAUTL_METRIC; + rt->SubnetBits = iface->SubnetBits; + + best = rt; + } + } + if( !best && Interface ) + { + rt = &Interface->Route; + // Make sure route is up to date + memcpy(rt->Network, iface->Address, addrSize); + memset(rt->NextHop, 0, addrSize); + rt->Metric = DEFAUTL_METRIC; + rt->SubnetBits = iface->SubnetBits; + + if( IPStack_CompareAddress(AddressType, rt->Network, Address, rt->SubnetBits) ) + { + best = rt; + } + } + LEAVE('p', best); return best; } diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c index 3a455304..9aa9d722 100644 --- a/Usermode/Applications/ifconfig_src/main.c +++ b/Usermode/Applications/ifconfig_src/main.c @@ -11,6 +11,7 @@ // === CONSTANTS === #define FILENAME_MAX 255 #define IPSTACK_ROOT "/Devices/ip" +#define DEFAULT_METRIC 30 // TODO: Move this to a header #define ntohs(v) (((v&0xFF)<<8)|((v>>8)&0xFF)) @@ -22,10 +23,10 @@ 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); +void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop); int DoAutoConfig(const char *Device); int SetAddress(int IFNum, const char *Address); - int ParseIPAddres(const char *Address, uint8_t *Dest, int *SubnetBits); + int ParseIPAddress(const char *Address, uint8_t *Dest, int *SubnetBits); // === CODE === /** @@ -41,13 +42,93 @@ int main(int argc, char *argv[]) return 0; } - if( strcmp(argv[1], "routes") == 0 ) { - DumpRoutes(); + // Routes + if( strcmp(argv[1], "route") == 0 ) + { + // Add new route + if( strcmp(argv[2], "add") == 0 ) + { + uint8_t dest[16] = {0}; + uint8_t nextHop[16] = {0}; + int addrType, subnetBits = -1; + int nextHopType, nextHopBits=-1; + char *ifaceName; + int metric = DEFAULT_METRIC; + // Usage: + // ifconfig route add [/] [] + // ifconfig route add [/] [] + if( argc - 3 < 2 ) { + fprintf(stderr, "ERROR: '%s route add' takes at least two arguments, %i passed\n", + argv[0], argc-3); + PrintUsage(argv[0]); + return -1; + } + + if( argc - 3 > 3 ) { + fprintf(stderr, "ERROR: '%s route add' takes at most three arguments, %i passed\n", + argv[0], argc-3); + PrintUsage(argv[0]); + return -1; + } + + // Destination IP + addrType = ParseIPAddress(argv[3], dest, &subnetBits); + if( subnetBits == -1 ) { + subnetBits = Net_GetAddressSize(addrType)*8; + } + // Interface Name / Next Hop + if( (nextHopType = ParseIPAddress(argv[4], nextHop, &nextHopBits)) == 0 ) + { + // Interface name + ifaceName = argv[4]; + } + else + { + // Next Hop + // - Check if it's the same type as the network/destination + if( nextHopType != addrType ) { + fprintf(stderr, "ERROR: Address type mismatch\n"); + return -1; + } + // - Make sure there's no mask + if( nextHopBits != -1 ) { + fprintf(stderr, "Error: Next hop cannot be masked\n"); + return -1; + } + } + + // Metric + if( argc - 3 >= 3 ) + { + metric = atoi(argv[5]); + if( metric == 0 && argv[5][0] != '0' ) { + fprintf(stderr, "ERROR: Metric should be a number\n"); + return -1; + } + } + + // Make the route! + AddRoute(ifaceName, addrType, dest, subnetBits, metric, nextHop); + + return 0; + } + // Delete a route + else if( strcmp(argv[2], "del") == 0 ) + { + // Usage: + // ifconfig route del + // ifconfig route del [/] + } + else + { + // List routes + DumpRoutes(); + } return 0; } - // Add a new interface - if( strcmp(argv[1], "add") == 0 ) { + else if( strcmp(argv[1], "add") == 0 ) + { if( argc < 4 ) { fprintf(stderr, "ERROR: '%s add' requires two arguments, %i passed\n", argv[0], argc-2); PrintUsage(argv[0]); @@ -59,9 +140,9 @@ int main(int argc, char *argv[]) ret = SetAddress( ret, argv[3] ); return ret; } - // Delete an interface - if( strcmp(argv[1], "del") == 0 ) { + else if( strcmp(argv[1], "del") == 0 ) + { if( argc < 3 ) { fprintf(stderr, "ERROR: '%s del' requires an argument\n", argv[0]); PrintUsage(argv[0]); @@ -69,16 +150,21 @@ int main(int argc, char *argv[]) } // TODO: } - // Autoconfigure an interface // NOTE: Debugging hack (see the function for more details) - if( strcmp(argv[1], "autoconf") == 0 ) { + else if( strcmp(argv[1], "autoconf") == 0 ) + { DoAutoConfig(argv[2]); return 0; } + else if( strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 ) + { + PrintUsage(argv[0]); + return 0; + } - // Print usage instructions - PrintUsage(argv[0]); + // Dump a named interface + DumpInterface(argv[1]); return 0; } @@ -93,12 +179,18 @@ void PrintUsage(const char *ProgName) fprintf(stderr, " Add a new interface listening on with the specified\n"); fprintf(stderr, " address.\n"); fprintf(stderr, " %s del \n", ProgName); - fprintf(stderr, " %s set