X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Frouting.c;h=fd234da7754abb126c84bb29961cda12d4d16d88;hb=fe2794b4f932c0755674493b6a6da4b60a5c2433;hp=643de1ee4a914bd07695c5ce6c906acced0337b7;hpb=8025b7daeb599847864cc3d8e3c2a41e63e3789d;p=tpg%2Facess2.git diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c index 643de1ee..fd234da7 100644 --- a/Modules/IPStack/routing.c +++ b/Modules/IPStack/routing.c @@ -9,30 +9,21 @@ #include "ipstack.h" #include "link.h" -// === IMPORTS === -tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Filename); +#define DEFAUTL_METRIC 30 -// === TYPES === -typedef struct sRoute { - struct sRoute *Next; - - tVFS_Node Node; - - tInterface *Interface; // Interface for this route - int AddressType; // 0: Invalid, 4: IPv4, 6: IPv4 - void *Network; // Network - Pointer to tIPv4/tIPv6/... at end of structure - int SubnetBits; // Number of bits in \a Network that are valid - void *NextHop; // Next Hop address - Pointer to tIPv4/tIPv6/... at end of structure - int Metric; // Route priority -} tRoute; +// === IMPORTS === +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); -tRoute *IPStack_FindRoute(int AddressType, void *Address); +// - 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); @@ -108,53 +99,48 @@ 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; + BASE_IOCTLS(DRV_TYPE_MISC, STR(IDENT), VERSION, casIOCtls_RouteDir) - case DRV_IOCTL_VERSION: - LEAVE('x', VERSION); - return VERSION; - - case DRV_IOCTL_LOOKUP: - tmp = ModUtil_LookupString( (char**)casIOCtls_RouteDir, (char*)Data ); + case 4: // Add Route + if( !CheckString(Data) ) LEAVE_RET('i', -1); + rt = IPStack_Route_Create(Data); + if( !rt ) + tmp = -1; + else + tmp = rt->Node.Inode; LEAVE('i', tmp); return tmp; - case 4: // Add Route - if( !CheckString(Data) ) return -1; - return IPStack_Route_Create(Data); - case 5: // Locate Route { struct { int Type; Uint8 Addr[]; } *data = Data; - tRoute *rt; if( !CheckMem(Data, sizeof(int)) ) - return -1; + LEAVE_RET('i', -1); if( !CheckMem(Data, sizeof(int) + IPStack_GetAddressSize(data->Type)) ) - return -1; + LEAVE_RET('i', -1); - rt = IPStack_FindRoute(data->Type, data->Addr); + 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); if( !rt ) - return 0; + LEAVE_RET('i', 0); + LEAVE('i', rt->Node.Inode); return rt->Node.Inode; } break; } + LEAVE('i', 0); return 0; } @@ -162,7 +148,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; @@ -172,14 +158,18 @@ int IPStack_Route_Create(const char *InterfaceName) // Note: Oh man! This is such a hack { tVFS_Node *node = IPStack_Root_FindDir(NULL, InterfaceName); - if( !node ) return 0; + if( !node ) { + Log_Debug("IPStack", "IPStack_Route_Create - Unknown interface '%s'\n", InterfaceName); + 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 @@ -199,6 +189,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 ) { @@ -209,33 +202,135 @@ int IPStack_Route_Create(const char *InterfaceName) gIP_Routes = gIP_RoutesEnd = rt; } - return rt->Node.Inode; + Log_Log("IPStack", "Route entry for '%s' created", InterfaceName); + + return rt; } /** + * \brief Add and fill a route */ -tRoute *IPStack_FindRoute(int AddressType, void *Address) +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; +} + +/** + */ +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)); + if( Interface && AddressType != Interface->Type ) { + LOG("Interface->Type (%i) != AddressType", Interface->Type); + LEAVE('n'); + return NULL; + } + + // Get address size + addrSize = IPStack_GetAddressSize(AddressType); + + // Check against explicit routes for( rt = gIP_Routes; rt; rt = rt->Next ) { + // Check interface + if( Interface && rt->Interface != Interface ) continue; + // Check address type if( rt->AddressType != AddressType ) continue; + LOG("Checking network %s/%i", IPStack_PrintAddress(AddressType, rt->Network), rt->SubnetBits); + + // Check if the address matches if( !IPStack_CompareAddress(AddressType, rt->Network, Address, rt->SubnetBits) ) continue; if( best ) { // More direct routes are preferred - if( best->SubnetBits > rt->SubnetBits ) continue; + 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 ) continue; + if( best->SubnetBits == rt->SubnetBits && best->Metric < rt->Metric ) { + LOG("Skipped - higher metric (%i > %i)", rt->Metric, best->Metric); + continue; + } } 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; } @@ -244,6 +339,7 @@ tRoute *IPStack_FindRoute(int AddressType, void *Address) */ static const char *casIOCtls_Route[] = { DRV_IOCTLNAMES, + "get_type", // Get address type - (void), returns integer type "get_network", // Get network - (void *Data), returns boolean success "set_network", // Set network - (void *Data), returns boolean success "get_nexthop", // Get next hop - (void *Data), returns boolean success @@ -259,7 +355,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); @@ -267,48 +362,36 @@ 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; + BASE_IOCTLS(DRV_TYPE_MISC, STR(IDENT), VERSION, casIOCtls_Route) - case DRV_IOCTL_LOOKUP: - tmp = ModUtil_LookupString( (char**)casIOCtls_Route, (char*)Data ); - LEAVE('i', tmp); - return tmp; + // Get address type + case 4: + return rt->AddressType; // Get Network - case 4: + case 5: if( !CheckMem(Data, addrSize) ) return -1; memcpy(Data, rt->Network, addrSize); return 1; // Set Network - case 5: + case 6: if( !CheckMem(Data, addrSize) ) return -1; memcpy(rt->Network, Data, addrSize); return 1; // Get Next Hop - case 6: + case 7: if( !CheckMem(Data, addrSize) ) return -1; memcpy(Data, rt->NextHop, addrSize); return 1; // Set Next Hop - case 7: + case 8: if( !CheckMem(Data, addrSize) ) return -1; memcpy(rt->NextHop, Data, addrSize); return 1; // Get/Set Subnet Bits - case 8: + case 9: if( Data ) { if( !CheckMem(Data, sizeof(int)) ) return -1; if( *iData < 0 || *iData > addrSize*8 ) @@ -318,7 +401,7 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) return rt->SubnetBits; // Get/Set Metric - case 9: + case 10: if( Data ) { if( !CheckMem(Data, sizeof(int)) ) return -1; if( *iData < 0 ) return -1; @@ -327,7 +410,7 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) return rt->Metric; // Get interface name - case 10: + case 11: if( Data ) { if( !CheckMem(Data, strlen(rt->Interface->Name) + 1) ) return -1; @@ -336,6 +419,6 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) return strlen(rt->Interface->Name); default: - return 0; + return -1; } }