X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FIPStack%2Frouting.c;h=24bb8fa2e43ac4370ccf0e872324eedd22133c80;hb=8a3c7218fb65c46c0876b7033b732188be91ae03;hp=7173d1f32eba0dc0273806e21ebf55343530ef8b;hpb=51ab5f489bc356940c95cc936fd0508e8f07ea97;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/IPStack/routing.c b/KernelLand/Modules/IPStack/routing.c index 7173d1f3..24bb8fa2 100644 --- a/KernelLand/Modules/IPStack/routing.c +++ b/KernelLand/Modules/IPStack/routing.c @@ -17,17 +17,18 @@ 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_MkNod(tVFS_Node *Node, const char *Name, Uint Flags); - int IPStack_RouteDir_Relink(tVFS_Node *Node, const char *OldName, const char *NewName); + int IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]); +tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name, Uint Flags); +tVFS_Node *IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags); + int IPStack_RouteDir_Unlink(tVFS_Node *Node, const char *OldName); tRoute *_Route_FindExactRoute(int Type, void *Network, int Subnet, int Metric); int _Route_ParseRouteName(const char *Name, void *Addr, int *SubnetBits, int *Metric); int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data); // - Route Management tRoute *IPStack_Route_Create(int AddrType, void *Network, int SubnetBits, int Metric); tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, void *NextHop, int Metric); -tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address); +tRoute *_Route_FindInterfaceRoute(int AddressType, const void *Address); +tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, const void *Address); // - Individual Routes int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data); @@ -42,7 +43,7 @@ tVFS_NodeType gIP_RouteDirNodeType = { .ReadDir = IPStack_RouteDir_ReadDir, .FindDir = IPStack_RouteDir_FindDir, .MkNod = IPStack_RouteDir_MkNod, - .Relink = IPStack_RouteDir_Relink, + .Unlink = IPStack_RouteDir_Unlink, .IOCtl = IPStack_RouteDir_IOCtl }; tVFS_Node gIP_RouteNode = { @@ -57,29 +58,27 @@ tVFS_Node gIP_RouteNode = { /** * \brief ReadDir for the /Devices/ip/routes/ directory */ -char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos) +int IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]) { tRoute *rt; for(rt = gIP_Routes; rt && Pos --; rt = rt->Next); - if( !rt ) return NULL; + if( !rt ) return -EINVAL; { int addrlen = IPStack_GetAddressSize(rt->AddressType); - int len = sprintf(NULL, "%i::%i:%i", rt->AddressType, rt->SubnetBits, rt->Metric) + addrlen*2; - char buf[len+1]; int ofs; - ofs = sprintf(buf, "%i:", rt->AddressType); - ofs += Hex(buf+ofs, addrlen, rt->Network); - sprintf(buf+ofs, ":%i:%i", rt->SubnetBits, rt->Metric); - return strdup(buf); + ofs = sprintf(Dest, "%i:", rt->AddressType); + ofs += Hex(Dest+ofs, addrlen, rt->Network); + sprintf(Dest+ofs, ":%i:%i", rt->SubnetBits, rt->Metric); + return 0; } } /** * \brief FindDir for the /Devices/ip/routes/ directory */ -tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name) +tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name, Uint Flags) { // Interpret the name as :, returning the interface for // needed to access that address. @@ -112,17 +111,26 @@ tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name) rt = IPStack_FindRoute(type, NULL, addrData); if(!rt) return NULL; - if( rt->Interface ) + if( !rt->Interface ) { - // Return the interface node - // - Sure it's hijacking it from inteface.c's area, but it's - // simpler this way - return &rt->Interface->Node; + LOG("Why does this route not have a node? trying to find an iface for the next hop"); + + void *nextrt = _Route_FindInterfaceRoute(type, rt->NextHop); + if(!nextrt) { + Log_Notice("Cannot find route to next hop '%s'", + IPStack_PrintAddress(type, rt->NextHop)); + return NULL; + } + rt = nextrt; } - else - { + if( !rt->Interface ) { + Log_Notice("Routes", "No interface for route %p, what the?", 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; } else if( Name[0] == '#' ) { @@ -160,13 +168,22 @@ tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name) /** * \brief Create a new route node */ -int IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags) +tVFS_Node *IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags) { - if( Flags ) return -EINVAL; - if( Threads_GetUID() != 0 ) return -EACCES; + if( Flags ) { + errno = EINVAL; + return NULL; + } + if( Threads_GetUID() != 0 ) { + errno = EACCES; + return NULL; + } int type = _Route_ParseRouteName(Name, NULL, NULL, NULL); - if( type <= 0 ) return -EINVAL; + if( type <= 0 ) { + errno = EINVAL; + return NULL; + } int size = IPStack_GetAddressSize(type); Uint8 addrdata[size]; @@ -175,18 +192,21 @@ int IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags) _Route_ParseRouteName(Name, addrdata, &subnet, &metric); // Check for duplicates - if( _Route_FindExactRoute(type, addrdata, subnet, metric) ) - return -EEXIST; + if( _Route_FindExactRoute(type, addrdata, subnet, metric) ) { + errno = EEXIST; + return NULL; + } - IPStack_Route_Create(type, addrdata, subnet, metric); + tRoute *rt = IPStack_Route_Create(type, addrdata, subnet, metric); + rt->Node.ReferenceCount ++; - return 0; + return &rt->Node; } /** * \brief Rename / Delete a route */ -int IPStack_RouteDir_Relink(tVFS_Node *Node, const char *OldName, const char *NewName) +int IPStack_RouteDir_Unlink(tVFS_Node *Node, const char *OldName) { tRoute *rt; @@ -203,29 +223,15 @@ int IPStack_RouteDir_Relink(tVFS_Node *Node, const char *OldName, const char *Ne rt = _Route_FindExactRoute(type, addr, subnet, metric); } - if( NewName == NULL ) - { - // Delete the route - tRoute *prev = NULL; - for(tRoute *r = gIP_Routes; r && r != rt; prev = r, r = r->Next); - - if(prev) - prev->Next = rt->Next; - else - gIP_Routes = rt->Next; - free(rt); - } - else - { - // Change the route - int type = _Route_ParseRouteName(NewName, NULL, NULL, NULL); - if(type <= 0) return -EINVAL; - Uint8 addr[IPStack_GetAddressSize(type)]; - int subnet, metric; - _Route_ParseRouteName(NewName, addr, &subnet, &metric); + // Delete the route + tRoute *prev = NULL; + for(tRoute *r = gIP_Routes; r && r != rt; prev = r, r = r->Next); - return -ENOTIMPL; - } + if(prev) + prev->Next = rt->Next; + else + gIP_Routes = rt->Next; + free(rt); return 0; } @@ -435,13 +441,56 @@ tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, v return rt; } +/** + * \brief Locates what interface should be used to get directly to an address + */ +tRoute *_Route_FindInterfaceRoute(int AddressType, const void *Address) +{ + tRoute *best = NULL, *rt; + int addrSize = IPStack_GetAddressSize(AddressType); + for( tInterface *iface = gIP_Interfaces; iface; iface = iface->Next ) + { + if( iface->Type != AddressType ) continue; + + // Check if the address matches + if( !IPStack_CompareAddress(AddressType, iface->Address, Address, iface->SubnetBits) ) + continue; + + rt = &iface->Route; + if( !rt->Interface ) + { + memcpy(rt->Network, iface->Address, addrSize); + memset(rt->NextHop, 0, addrSize); + rt->Metric = DEFAUTL_METRIC; + rt->SubnetBits = iface->SubnetBits; + rt->Interface = iface; + } + + 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; + } + } + + best = rt; + } + + return best; +} + /** */ -tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) +tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, const void *Address) { tRoute *rt; tRoute *best = NULL; - tInterface *iface; int addrSize; ENTER("iAddressType pInterface sAddress", @@ -460,7 +509,7 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) for( rt = gIP_Routes; rt; rt = rt->Next ) { // Check interface - if( Interface && rt->Interface != Interface ) continue; + if( Interface && rt->Interface && rt->Interface != Interface ) continue; // Check address type if( rt->AddressType != AddressType ) continue; @@ -489,37 +538,7 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) // 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; - } + best = _Route_FindInterfaceRoute(AddressType, Address); } if( !best && Interface ) { @@ -559,6 +578,8 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) { tRoute *rt = Node->ImplPtr; int addrSize = IPStack_GetAddressSize(rt->AddressType); + + ENTER("pNode iID pData", Node, ID, Data); switch(ID) { @@ -567,57 +588,57 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data) // Get Next Hop case 4: - if( !CheckMem(Data, addrSize) ) return -1; + if( !CheckMem(Data, addrSize) ) LEAVE_RET('i', -1); memcpy(Data, rt->NextHop, addrSize); - return 1; + LEAVE_RET('i', 1); // Set Next Hop case 5: - if( Threads_GetUID() != 0 ) return -1; - if( !CheckMem(Data, addrSize) ) return -1; + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + if( !CheckMem(Data, addrSize) ) LEAVE_RET('i', -1); memcpy(rt->NextHop, Data, addrSize); - return 1; + LEAVE_RET('i', 1); // Get interface name case 6: if( !rt->Interface ) { if(Data && !CheckMem(Data, 1) ) - return -1; + LEAVE_RET('i', -1); if(Data) *(char*)Data = 0; - return 0; + LEAVE_RET('i', 0); } if( Data ) { if( !CheckMem(Data, strlen(rt->Interface->Name) + 1) ) - return -1; + LEAVE_RET('i', -1); strcpy(Data, rt->Interface->Name); } - return strlen(rt->Interface->Name); + LEAVE_RET('i', strlen(rt->Interface->Name)); // Set interface name case 7: if( Threads_GetUID() != 0 ) - return -1; + LEAVE_RET('i', -1); if( !CheckString(Data) ) - return -1; + LEAVE_RET('i', -1); else { tInterface *iface; tVFS_Node *tmp; tmp = IPStack_Root_FindDir(NULL, Data); if(!tmp) - return -1; + LEAVE_RET('i', -1); iface = tmp->ImplPtr; if(tmp->Type->Close) tmp->Type->Close(tmp); if( iface->Type != rt->AddressType ) - return -1; + LEAVE_RET('i', -1); // TODO: Other checks? rt->Interface = iface; } - return 0; + LEAVE_RET('i', 0); default: - return -1; + LEAVE_RET('i', -1); } }