X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Frouting.c;h=c37e744148bd299bba08532face17a3298e25a56;hb=82adac267bc089391397b36413bba210a8e7c68f;hp=c1060342f697a6bbebf2dda63647848464819f39;hpb=41769c02317835472d7678d3531ecfc23df8e17a;p=tpg%2Facess2.git diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c index c1060342..c37e7441 100644 --- a/Modules/IPStack/routing.c +++ b/Modules/IPStack/routing.c @@ -9,15 +9,20 @@ #include "ipstack.h" #include "link.h" +#define DEFAUTL_METRIC 30 + // === IMPORTS === -tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Filename); +extern tInterface *gIP_Interfaces; +extern tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Filename); // === PROTOTYPES === // - Routes directory char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos); tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name); int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data); - int IPStack_Route_Create(const char *InterfaceName); +// - Route Management +tRoute *IPStack_Route_Create(const char *InterfaceName); +tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, void *NextHop, int Metric); tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address); // - Individual Routes int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data); @@ -27,13 +32,13 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) tRoute *gIP_Routes; tRoute *gIP_RoutesEnd; tVFS_Node gIP_RouteNode = { - Flags: VFS_FFLAG_DIRECTORY, - Size: -1, - NumACLs: 1, - ACLs: &gVFS_ACL_EveryoneRX, - ReadDir: IPStack_RouteDir_ReadDir, - FindDir: IPStack_RouteDir_FindDir, - IOCtl: IPStack_RouteDir_IOCtl + .Flags = VFS_FFLAG_DIRECTORY, + .Size = -1, + .NumACLs = 1, + .ACLs = &gVFS_ACL_EveryoneRX, + .ReadDir = IPStack_RouteDir_ReadDir, + .FindDir = IPStack_RouteDir_FindDir, + .IOCtl = IPStack_RouteDir_IOCtl }; // === CODE === @@ -69,10 +74,39 @@ tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name) // Zero is invalid, sorry :) if( !num ) return NULL; + // Interpret the name as :, returning the interface for + // needed to access that address. + // E.g. '4:0A02000A' - 10.2.0.10 + // Hm... It could do with a way to have a better address type representation + if( Name[1] == ':' ) // TODO: Allow variable length type codes + { + int addrSize = IPStack_GetAddressSize(num); + Uint8 addrData[addrSize]; + + // Errof if the size is invalid + if( strlen(Name) != 2 + addrSize*2 ) + return NULL; + + // Parse the address + // - Error if the address data is not fully hex + if( UnHex(addrData, addrSize, Name + 2) != addrSize ) + return NULL; + + // Find the route + rt = IPStack_FindRoute(num, NULL, addrData); + if(!rt) return NULL; + + // Return the interface node + // - Sure it's hijacking it from inteface.c's area, but it's + // simpler this way + return &rt->Interface->Node; + } + // The list is inherently sorted, so we can do a quick search for(rt = gIP_Routes; rt && rt->Node.Inode < num; rt = rt->Next); - // Fast fail on larger number - if( rt->Node.Inode > num ) + + // Fast fail end of list / larger number + if( !rt || rt->Node.Inode > num ) return NULL; return &rt->Node; @@ -94,31 +128,20 @@ static const char *casIOCtls_RouteDir[] = { int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data) { int tmp; + tRoute *rt; ENTER("pNode iID pData", Node, ID, Data); switch(ID) { // --- Standard IOCtls (0-3) --- - case DRV_IOCTL_TYPE: - LEAVE('i', DRV_TYPE_MISC); - return DRV_TYPE_MISC; - - case DRV_IOCTL_IDENT: - tmp = ModUtil_SetIdent(Data, STR(IDENT)); - LEAVE('i', 1); - return 1; - - case DRV_IOCTL_VERSION: - LEAVE('x', VERSION); - return VERSION; - - case DRV_IOCTL_LOOKUP: - tmp = ModUtil_LookupString( (char**)casIOCtls_RouteDir, (char*)Data ); - LEAVE('i', tmp); - return tmp; + BASE_IOCTLS(DRV_TYPE_MISC, STR(IDENT), VERSION, casIOCtls_RouteDir) case 4: // Add Route if( !CheckString(Data) ) LEAVE_RET('i', -1); - tmp = IPStack_Route_Create(Data); + rt = IPStack_Route_Create(Data); + if( !rt ) + tmp = -1; + else + tmp = rt->Node.Inode; LEAVE('i', tmp); return tmp; @@ -128,14 +151,13 @@ int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data) int Type; Uint8 Addr[]; } *data = Data; - tRoute *rt; if( !CheckMem(Data, sizeof(int)) ) LEAVE_RET('i', -1); if( !CheckMem(Data, sizeof(int) + IPStack_GetAddressSize(data->Type)) ) LEAVE_RET('i', -1); - Log_Debug("IPStack", "Route_RouteDir_IOCtl - FindRoute %i, %s\n", + Log_Debug("IPStack", "Route_RouteDir_IOCtl - FindRoute %i, %s", data->Type, IPStack_PrintAddress(data->Type, data->Addr) ); rt = IPStack_FindRoute(data->Type, NULL, data->Addr); @@ -155,7 +177,7 @@ int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data) * \brief Create a new route entry * \param InterfaceName Name of the interface using this route */ -int IPStack_Route_Create(const char *InterfaceName) +tRoute *IPStack_Route_Create(const char *InterfaceName) { tRoute *rt; tInterface *iface; @@ -167,15 +189,16 @@ int IPStack_Route_Create(const char *InterfaceName) tVFS_Node *node = IPStack_Root_FindDir(NULL, InterfaceName); if( !node ) { Log_Debug("IPStack", "IPStack_Route_Create - Unknown interface '%s'\n", InterfaceName); - return 0; + return NULL; } iface = node->ImplPtr; + if(node->Close) node->Close(node); } // Get the size of the specified address type size = IPStack_GetAddressSize(iface->Type); if( size == 0 ) { - return 0; + return NULL; } // Allocate space @@ -195,6 +218,9 @@ int IPStack_Route_Create(const char *InterfaceName) rt->SubnetBits = 0; rt->NextHop = (void *)( (tVAddr)rt + sizeof(tRoute) + size ); rt->Interface = iface; + rt->Metric = DEFAUTL_METRIC; + memset(rt->Network, 0, size); + memset(rt->NextHop, 0, size); // Add to list if( gIP_RoutesEnd ) { @@ -205,17 +231,41 @@ int IPStack_Route_Create(const char *InterfaceName) gIP_Routes = gIP_RoutesEnd = rt; } - Log_Log("IPStack", "Route entry for '%s' created\n", InterfaceName); + Log_Log("IPStack", "Route entry for '%s' created", InterfaceName); + + return rt; +} + +/** + * \brief Add and fill a route + */ +tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, void *NextHop, int Metric) +{ + tRoute *rt = IPStack_Route_Create(Interface); + int addrSize; + + if( !rt ) return NULL; + + addrSize = IPStack_GetAddressSize(rt->Interface->Type); + + memcpy(rt->Network, Network, addrSize); + if( NextHop ) + memcpy(rt->NextHop, NextHop, addrSize); + rt->SubnetBits = SubnetBits; + if( Metric ) + rt->Metric = Metric; - return rt->Node.Inode; + return rt; } /** */ -tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) +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)); @@ -226,6 +276,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 @@ -255,6 +309,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; } @@ -280,7 +384,6 @@ static const char *casIOCtls_Route[] = { */ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) { - int tmp; int *iData = Data; tRoute *rt = Node->ImplPtr; int addrSize = IPStack_GetAddressSize(rt->AddressType); @@ -288,23 +391,7 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) switch(ID) { // --- Standard IOCtls (0-3) --- - case DRV_IOCTL_TYPE: - LEAVE('i', DRV_TYPE_MISC); - return DRV_TYPE_MISC; - - case DRV_IOCTL_IDENT: - tmp = ModUtil_SetIdent(Data, STR(IDENT)); - LEAVE('i', 1); - return 1; - - case DRV_IOCTL_VERSION: - LEAVE('x', VERSION); - return VERSION; - - case DRV_IOCTL_LOOKUP: - tmp = ModUtil_LookupString( (char**)casIOCtls_Route, (char*)Data ); - LEAVE('i', tmp); - return tmp; + BASE_IOCTLS(DRV_TYPE_MISC, STR(IDENT), VERSION, casIOCtls_Route) // Get address type case 4: