X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Fmain.c;h=05e2897495ab79de5181794a42667dc9bd918034;hb=243bdab4e7acc8516d9b1c138f45dc1195f97767;hp=051d064d18e861d1aa136b13e8173dfe21b9845d;hpb=47e9dfd89189fc6b150bd6b20229cb047c7e0858;p=tpg%2Facess2.git diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 051d064d..05e28974 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -5,6 +5,7 @@ #define DEBUG 0 #define VERSION ((0<<8)|10) #include "ipstack.h" +#include "link.h" #include #include #include @@ -31,13 +32,15 @@ tDevFS_Driver gIP_DriverInfo = { .ACLs = &gVFS_ACL_EveryoneRX, .Flags = VFS_FFLAG_DIRECTORY, .ReadDir = IPStack_ReadDir, - .FindDir = IPStack_FindDir + .FindDir = IPStack_FindDir, + .IOCtl = IPStack_IOCtl } }; - int glIP_Interfaces = 0; +tSpinlock glIP_Interfaces = 0; tInterface *gIP_Interfaces = NULL; tInterface *gIP_Interfaces_Last = NULL; - int glIP_Adapters = 0; + int giIP_NextIfaceId = 1; +tSpinlock glIP_Adapters = 0; tAdapter *gIP_Adapters = NULL; // === CODE === @@ -63,6 +66,8 @@ int IPStack_Install(char **Arguments) } } + DevFS_AddDevice( &gIP_DriverInfo ); + return 1; } @@ -72,22 +77,33 @@ int IPStack_Install(char **Arguments) char *IPStack_ReadDir(tVFS_Node *Node, int Pos) { tInterface *iface; - char name[5] = "ip0\0\0"; + char name[] = "ip0\0\0\0"; + ENTER("pNode iPos", Node, Pos); + + // Traverse the list + for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ; + + // Did we run off the end? + if(!iface) { + LEAVE('n'); + return NULL; + } // Create the name + Pos = iface->Node.ImplInt; if(Pos < 10) name[2] = '0' + Pos; - else { + else if(Pos < 100) { name[2] = '0' + Pos/10; name[3] = '0' + Pos%10; } + else { + name[2] = '0' + Pos/100; + name[3] = '0' + (Pos/10)%10; + name[4] = '0' + Pos%10; + } - // Traverse the list - for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ; - - // Did we run off the end? - if(!iface) return NULL; - + LEAVE('s', name); // Return the pre-generated name return strdup(name); } @@ -97,27 +113,38 @@ char *IPStack_ReadDir(tVFS_Node *Node, int Pos) */ tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name) { - int i; - tInterface *iface; + int i, num; + tInterface *iface; - if(Name[0] != 'i' || Name[1] != 'p') return NULL; - if(Name[2] < '0' || Name[2] > '9') return NULL; + ENTER("pNode sName", Node, Name); - if(Name[3] == '\0') { - i = Name[2] - '0'; - for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ; - if(!iface) return NULL; - return &iface->Node; + if(Name[0] != 'i' || Name[1] != 'p') { + LEAVE('n'); + return NULL; } - if(Name[3] < '0' || Name[3] > '9') return NULL; - - i = (Name[2] - '0')*10; - i += Name[3] - '0'; + i = 2; num = 0; + while('0' <= Name[i] && Name[i] <= '9') + { + num *= 10; + num += Name[i] - '0'; + i ++; + } + if(Name[i] != '\0') { + LEAVE('n'); + return NULL; + } - for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ; - if(!iface) return NULL; - return &iface->Node; + for( iface = gIP_Interfaces; iface; iface = iface->Next ) + { + if( iface->Node.ImplInt == num ) + { + LEAVE('p', &iface->Node); + return &iface->Node; + } + } + LEAVE('p', NULL); + return NULL; } static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL }; @@ -134,27 +161,35 @@ static const char *casIOCtls_Iface[] = { */ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) { + int tmp; + 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: - if( !CheckMem( Data, 4 ) ) return -1; + if( !CheckMem( Data, 4 ) ) LEAVE_RET('i', -1); memcpy(Data, "IP\0\0", 4); + LEAVE('i', 1); return 1; case DRV_IOCTL_VERSION: + LEAVE('x', VERSION); return VERSION; case DRV_IOCTL_LOOKUP: - if( !CheckString( Data ) ) return -1; - + if( !CheckString( Data ) ) LEAVE_RET('i', -1); + LOG("Lookup '%s'", Data); if( Node == &gIP_DriverInfo.RootNode ) - return LookupString( (char**)casIOCtls_Root, (char*)Data ); + tmp = LookupString( (char**)casIOCtls_Root, (char*)Data ); else - return LookupString( (char**)casIOCtls_Iface, (char*)Data ); + tmp = LookupString( (char**)casIOCtls_Iface, (char*)Data ); + LEAVE('i', tmp); + return tmp; } if(Node == &gIP_DriverInfo.RootNode) @@ -166,10 +201,12 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) * - Adds a new IP interface and binds it to a device */ case 4: - if( Threads_GetUID() != 0 ) return -1; - if( !CheckString( Data ) ) return -1; - return IPStack_AddInterface(Data); + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + if( !CheckString( Data ) ) LEAVE_RET('i', -1); + tmp = IPStack_AddInterface(Data); + LEAVE_RET('i', tmp); } + LEAVE('i', 0); return 0; } else @@ -182,29 +219,41 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) * - Get/Set the interface type */ case 4: - // Get Type? - if( !Data ) return iface->Type; - // Ok, it's set type - if( Threads_GetUID() != 0 ) return -1; - if( !CheckMem( Data, sizeof(int) ) ) return -1; - switch( *(int*)Data ) + // Set Type? + if( Data ) { - case 0: // Disable - iface->Type = 0; - memset(&iface->IP6, 0, sizeof(tIPv6)); // Clear address - break; - case 4: // IPv4 - iface->Type = 4; - memset(&iface->IP4, 0, sizeof(tIPv4)); - break; - case 6: // IPv6 - iface->Type = 6; - memset(&iface->IP6, 0, sizeof(tIPv6)); - break; - default: - return -1; + // Ok, it's set type + if( Threads_GetUID() != 0 ) { + LOG("Attempt by non-root to alter an interface (%i)", Threads_GetUID()); + LEAVE('i', -1); + return -1; + } + if( !CheckMem( Data, sizeof(int) ) ) { + LOG("Invalid pointer %p", Data); + LEAVE('i', -1); + return -1; + } + switch( *(int*)Data ) + { + case 0: // Disable + iface->Type = 0; + memset(&iface->IP6, 0, sizeof(tIPv6)); // Clear address + break; + case 4: // IPv4 + iface->Type = 4; + memset(&iface->IP4, 0, sizeof(tIPv4)); + break; + case 6: // IPv6 + iface->Type = 6; + memset(&iface->IP6, 0, sizeof(tIPv6)); + break; + default: + LEAVE('i', -1); + return -1; + } } - return 0; + LEAVE('i', iface->Type); + return iface->Type; /* * get_address @@ -213,41 +262,41 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) case 5: switch(iface->Type) { - case 0: return 1; + case 0: LEAVE_RET('i', 1); case 4: - if( !CheckMem( Data, sizeof(tIPv4) ) ) return -1; - memcpy( Data, &iface->IP4, sizeof(tIPv4) ); - return 1; + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP4.Address, sizeof(tIPv4) ); + LEAVE_RET('i', 1); case 6: - if( !CheckMem( Data, sizeof(tIPv6) ) ) return -1; - memcpy( Data, &iface->IP6, sizeof(tIPv6) ); - return 1; + if( !CheckMem( Data, sizeof(tIPv6) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP6.Address, sizeof(tIPv6) ); + LEAVE_RET('i', 1); } - return 0; + LEAVE_RET('i', 0); /* * set_address * - Get the interface's address */ case 6: - if( Threads_GetUID() != 0 ) return -1; + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); switch(iface->Type) { - case 0: return 1; + case 0: LEAVE_RET('i', 1); case 4: - if( !CheckMem( Data, sizeof(tIPv4) ) ) return -1; + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); iface->Type = 0; // One very hacky mutex/trash protector - memcpy( &iface->IP4, Data, sizeof(tIPv4) ); + memcpy( &iface->IP4.Address, Data, sizeof(tIPv4) ); iface->Type = 4; - return 1; + LEAVE_RET('i', 1); case 6: - if( !CheckMem( Data, sizeof(tIPv6) ) ) return -1; + if( !CheckMem( Data, sizeof(tIPv6) ) ) LEAVE_RET('i', -1); iface->Type = 0; - memcpy( &iface->IP6, Data, sizeof(tIPv6) ); + memcpy( &iface->IP6.Address, Data, sizeof(tIPv6) ); iface->Type = 6; - return 1; + LEAVE_RET('i', 1); } - return 0; + LEAVE_RET('i', 0); /* * getset_subnet @@ -259,35 +308,79 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) { switch( iface->Type ) { - case 4: return iface->IP4.SubnetBits; - case 6: return iface->IP6.SubnetBits; - default: return 0; + case 4: LEAVE_RET('i', iface->IP4.SubnetBits); + case 6: LEAVE_RET('i', iface->IP6.SubnetBits); + default: LEAVE_RET('i', 0); } } // Ok, set. - if( Threads_GetUID() != 0 ) return -1; - if( !CheckMem(Data, sizeof(int)) ) return -1; + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + if( !CheckMem(Data, sizeof(int)) ) LEAVE_RET('i', -1); // Check and set the subnet bits switch( iface->Type ) { case 4: - if( *(int*)Data < 0 || *(int*)Data > 31 ) return -1; + if( *(int*)Data < 0 || *(int*)Data > 31 ) LEAVE_RET('i', -1); iface->IP4.SubnetBits = *(int*)Data; - return iface->IP4.SubnetBits; + LEAVE_RET('i', iface->IP4.SubnetBits); case 6: - if( *(int*)Data < 0 || *(int*)Data > 127 ) return -1; + if( *(int*)Data < 0 || *(int*)Data > 127 ) LEAVE_RET('i', -1); iface->IP6.SubnetBits = *(int*)Data; - return iface->IP6.SubnetBits; + LEAVE_RET('i', iface->IP6.SubnetBits); default: break; } + LEAVE('i', 0); + return 0; + + /* + * get_gateway + * - Get the interface's IPv4 gateway + */ + case 8: + switch(iface->Type) + { + case 0: + LEAVE_RET('i', 1); + case 4: + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP4.Gateway, sizeof(tIPv4) ); + LEAVE_RET('i', 1); + case 6: + LEAVE_RET('i', 1); + } + LEAVE('i', 0); return 0; + + /* + * set_gateway + * - Get the interface's IPv4 gateway + */ + case 9: + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + switch(iface->Type) + { + case 0: + LEAVE_RET('i', 1); + + case 4: + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + iface->Type = 0; // One very hacky mutex/trash protector + memcpy( &iface->IP4.Gateway, Data, sizeof(tIPv4) ); + iface->Type = 4; + LEAVE_RET('i', 1); + + case 6: + LEAVE_RET('i', 1); + } + LEAVE_RET('i', 0); } } + LEAVE('i', 0); return 0; } @@ -300,24 +393,33 @@ int IPStack_AddInterface(char *Device) { tInterface *iface; + ENTER("sDevice", Device); + iface = malloc(sizeof(tInterface)); - if(!iface) return -2; // Return ERR_MYBAD + if(!iface) { + LEAVE('i', -2); + return -2; // Return ERR_MYBAD + } iface->Next = NULL; iface->Type = 0; // Unset type // Create Node + iface->Node.ImplPtr = iface; + iface->Node.ImplInt = giIP_NextIfaceId++; iface->Node.Flags = VFS_FFLAG_DIRECTORY; iface->Node.Size = 0; iface->Node.NumACLs = 1; iface->Node.ACLs = &gVFS_ACL_EveryoneRX; iface->Node.ReadDir = NULL; iface->Node.FindDir = NULL; + iface->Node.IOCtl = IPStack_IOCtl; // Get adapter handle iface->Adapter = IPStack_GetAdapter(Device); if( !iface->Adapter ) { free( iface ); + LEAVE('i', -1); return -1; // Return ERR_YOUFAIL } @@ -333,8 +435,11 @@ int IPStack_AddInterface(char *Device) } RELEASE( &glIP_Interfaces ); + gIP_DriverInfo.RootNode.Size ++; + // Success! - return 1; + LEAVE('i', iface->Node.ImplInt); + return iface->Node.ImplInt; } /** @@ -344,6 +449,9 @@ int IPStack_AddInterface(char *Device) tAdapter *IPStack_GetAdapter(char *Path) { tAdapter *dev; + int tmp; + + ENTER("sPath", Path); LOCK( &glIP_Adapters ); @@ -353,6 +461,7 @@ tAdapter *IPStack_GetAdapter(char *Path) if( strcmp(dev->Device, Path) == 0 ) { dev->NRef ++; RELEASE( &glIP_Adapters ); + LEAVE('p', dev); return dev; } } @@ -361,6 +470,7 @@ tAdapter *IPStack_GetAdapter(char *Path) dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 ); if(!dev) { RELEASE( &glIP_Adapters ); + LEAVE('n'); return NULL; } @@ -373,15 +483,19 @@ tAdapter *IPStack_GetAdapter(char *Path) if( dev->DeviceFD == -1 ) { free( dev ); RELEASE( &glIP_Adapters ); + LEAVE('n'); return NULL; } // Check that it is a network interface - if( VFS_IOCtl(dev->DeviceFD, 0, NULL) != DRV_TYPE_NETWORK ) { + tmp = VFS_IOCtl(dev->DeviceFD, 0, NULL); + LOG("Device type = %i", tmp); + if( tmp != DRV_TYPE_NETWORK ) { Warning("IPStack_GetAdapter: '%s' is not a network interface", dev->Device); VFS_Close( dev->DeviceFD ); free( dev ); RELEASE( &glIP_Adapters ); + LEAVE('n'); return NULL; } @@ -393,5 +507,10 @@ tAdapter *IPStack_GetAdapter(char *Path) gIP_Adapters = dev; RELEASE( &glIP_Adapters ); + + // Start watcher + Link_WatchDevice( dev ); + + LEAVE('p', dev); return dev; }