X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Frouting.c;h=643de1ee4a914bd07695c5ce6c906acced0337b7;hb=0c1bf884877e4b89eb224e91627508d42ca70974;hp=9678adad50659b90262dc635ae64c54daadbad32;hpb=d5834686ad14b66420060192445f06bce85db389;p=tpg%2Facess2.git diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c index 9678adad..643de1ee 100644 --- a/Modules/IPStack/routing.c +++ b/Modules/IPStack/routing.c @@ -2,20 +2,28 @@ * Acess2 IP Stack * - Routing Tables */ +#define DEBUG 0 +#define VERSION VER2(0,10) +#include +#include #include "ipstack.h" #include "link.h" +// === IMPORTS === +tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Filename); // === 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; // Pointer to tIPv4/tIPv6/... at end of structure - int SubnetBits; - void *NextHop; // Pointer to tIPv4/tIPv6/... at end of structure - tInterface *Interface; + 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; // === PROTOTYPES === @@ -24,9 +32,9 @@ 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); // - Individual Routes -Uint64 IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data); - + int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data); // === GLOBALS === int giIP_NextRouteId = 1; @@ -57,7 +65,7 @@ char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos) } { - int len = snprintf(NULL, 12, "%i", rt->Node.Inode); + int len = sprintf(NULL, "%i", rt->Node.Inode); char buf[len+1]; sprintf(buf, "%i", rt->Node.Inode); return strdup(buf); @@ -70,6 +78,7 @@ char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos) tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name) { int num = atoi(Name); + tRoute *rt; // Zero is invalid, sorry :) if( !num ) return NULL; @@ -84,16 +93,21 @@ tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name) } /** - * \brief Names for interface IOCtl Calls + * \brief Names for the route list IOCtl Calls */ static const char *casIOCtls_RouteDir[] = { DRV_IOCTLNAMES, - "add_route" // Add a route - char *InterfaceName + "add_route", // Add a route - char *InterfaceName + "locate_route", // Find the best route for an address - struct {int Type, char Address[]} * NULL }; +/** + * \brief IOCtl for /Devices/ip/routes/ + */ int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data) { + int tmp; switch(ID) { // --- Standard IOCtls (0-3) --- @@ -118,12 +132,35 @@ int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data) 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; + if( !CheckMem(Data, sizeof(int) + IPStack_GetAddressSize(data->Type)) ) + return -1; + + rt = IPStack_FindRoute(data->Type, data->Addr); + + if( !rt ) + return 0; + + return rt->Node.Inode; + } + break; } return 0; } /** * \brief Create a new route entry + * \param InterfaceName Name of the interface using this route */ int IPStack_Route_Create(const char *InterfaceName) { @@ -140,7 +177,7 @@ int IPStack_Route_Create(const char *InterfaceName) } // Get the size of the specified address type - size = IPStack_GetAddressSize(iface->AddressType); + size = IPStack_GetAddressSize(iface->Type); if( size == 0 ) { return 0; } @@ -148,12 +185,157 @@ int IPStack_Route_Create(const char *InterfaceName) // Allocate space rt = calloc(1, sizeof(tRoute) + size*2 ); - rt->Next = NULL; - //rt->Node + // Set up node + rt->Node.ImplPtr = rt; + rt->Node.Inode = giIP_NextRouteId ++; + rt->Node.Size = 0; + rt->Node.NumACLs = 1, + rt->Node.ACLs = &gVFS_ACL_EveryoneRO; + rt->Node.IOCtl = IPStack_Route_IOCtl; - rt->AddressType = iface->AddressType; + // Set up state + rt->AddressType = iface->Type; rt->Network = (void *)( (tVAddr)rt + sizeof(tRoute) ); rt->SubnetBits = 0; rt->NextHop = (void *)( (tVAddr)rt + sizeof(tRoute) + size ); rt->Interface = iface; + + // Add to list + if( gIP_RoutesEnd ) { + gIP_RoutesEnd->Next = rt; + gIP_RoutesEnd = rt; + } + else { + gIP_Routes = gIP_RoutesEnd = rt; + } + + return rt->Node.Inode; +} + +/** + */ +tRoute *IPStack_FindRoute(int AddressType, void *Address) +{ + tRoute *rt; + tRoute *best = NULL; + + for( rt = gIP_Routes; rt; rt = rt->Next ) + { + if( rt->AddressType != AddressType ) continue; + + if( !IPStack_CompareAddress(AddressType, rt->Network, Address, rt->SubnetBits) ) + continue; + + if( best ) { + // More direct routes are preferred + if( best->SubnetBits > rt->SubnetBits ) continue; + // If equally direct, choose the best metric + if( best->SubnetBits == rt->SubnetBits && best->Metric < rt->Metric ) continue; + } + + best = rt; + } + + return best; +} + +/** + * \brief Names for route IOCtl Calls + */ +static const char *casIOCtls_Route[] = { + DRV_IOCTLNAMES, + "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 + "set_nexthop", // Set next hop - (void *Data), returns boolean success + "getset_subnetbits", // Get/Set subnet bits - (int *Bits), returns current value + "getset_metric", // Get/Set metric - (int *Metric), returns current value + "get_interface", // Get interface name - (char *Name), returns name length, NULL OK + NULL + }; + +/** + * \brief IOCtl for /Devices/ip/routes/# + */ +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); + + 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; + + // Get Network + case 4: + if( !CheckMem(Data, addrSize) ) return -1; + memcpy(Data, rt->Network, addrSize); + return 1; + // Set Network + case 5: + if( !CheckMem(Data, addrSize) ) return -1; + memcpy(rt->Network, Data, addrSize); + return 1; + + // Get Next Hop + case 6: + if( !CheckMem(Data, addrSize) ) return -1; + memcpy(Data, rt->NextHop, addrSize); + return 1; + // Set Next Hop + case 7: + if( !CheckMem(Data, addrSize) ) return -1; + memcpy(rt->NextHop, Data, addrSize); + return 1; + + // Get/Set Subnet Bits + case 8: + if( Data ) { + if( !CheckMem(Data, sizeof(int)) ) return -1; + if( *iData < 0 || *iData > addrSize*8 ) + return -1; + rt->SubnetBits = *iData; + } + return rt->SubnetBits; + + // Get/Set Metric + case 9: + if( Data ) { + if( !CheckMem(Data, sizeof(int)) ) return -1; + if( *iData < 0 ) return -1; + rt->Metric = *iData; + } + return rt->Metric; + + // Get interface name + case 10: + if( Data ) { + if( !CheckMem(Data, strlen(rt->Interface->Name) + 1) ) + return -1; + strcpy(Data, rt->Interface->Name); + } + return strlen(rt->Interface->Name); + + default: + return 0; + } }