X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Fmain.c;h=13bc56159effbf0cb28a9700a184b53038cc7bf4;hb=1529dadb6c2170bf9899fbde46d06a3d9a392b52;hp=5a250fb765b772bac504831530c68f645e3e47a7;hpb=f035491c949cb86d92a93fc3d9d033538704256b;p=tpg%2Facess2.git diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 5a250fb7..13bc5615 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -1,9 +1,9 @@ /* * Acess2 IP Stack - * - Address Resolution Protocol + * - Stack Initialisation */ #define DEBUG 0 -#define VERSION ((0<<8)|10) +#define VERSION VER2(0,10) #include "ipstack.h" #include "link.h" #include @@ -11,16 +11,30 @@ #include #include +// === CONSTANTS === +//! Default timeout value, 30 seconds +#define DEFAULT_TIMEOUT (30*1000) + // === IMPORTS === - int ARP_Initialise(); +extern int ARP_Initialise(); +extern void UDP_Initialise(); +extern void TCP_Initialise(); +extern int IPv4_Initialise(); +extern int IPv4_Ping(tInterface *Iface, tIPv4 Addr); +extern int IPv6_Initialise(); +//extern int IPv6_Ping(tInterface *Iface, tIPv6 Addr); // === PROTOTYPES === int IPStack_Install(char **Arguments); -char *IPStack_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name); - int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data); + int IPStack_IOCtlRoot(tVFS_Node *Node, int ID, void *Data); +char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, char *Name); + int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data); int IPStack_AddInterface(char *Device); tAdapter *IPStack_GetAdapter(char *Path); +char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, char *Name); + int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data); // === GLOBALS === MODULE_DEFINE(0, VERSION, IPStack, IPStack_Install, NULL, NULL); @@ -31,17 +45,18 @@ tDevFS_Driver gIP_DriverInfo = { .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX, .Flags = VFS_FFLAG_DIRECTORY, - .ReadDir = IPStack_ReadDir, - .FindDir = IPStack_FindDir, - .IOCtl = IPStack_IOCtl + .ReadDir = IPStack_Root_ReadDir, + .FindDir = IPStack_Root_FindDir, + .IOCtl = IPStack_Root_IOCtl } }; - int glIP_Interfaces = 0; +tSpinlock glIP_Interfaces = 0; tInterface *gIP_Interfaces = NULL; tInterface *gIP_Interfaces_Last = NULL; int giIP_NextIfaceId = 1; - int glIP_Adapters = 0; +tSpinlock glIP_Adapters = 0; tAdapter *gIP_Adapters = NULL; +tSocketFile *gIP_FileTemplates; // === CODE === /** @@ -52,8 +67,14 @@ int IPStack_Install(char **Arguments) { int i = 0; - // Install Handlers + // Layer 2 - Data Link Layer ARP_Initialise(); + // Layer 3 - Network Layer + IPv4_Initialise(); + IPv6_Initialise(); + // Layer 4 - Transport Layer + TCP_Initialise(); + UDP_Initialise(); if(Arguments) { @@ -68,16 +89,27 @@ int IPStack_Install(char **Arguments) DevFS_AddDevice( &gIP_DriverInfo ); - return 1; + return MODULE_ERR_OK; +} + +/** + * \brief Adds a file to the socket list + */ +int IPStack_AddFile(tSocketFile *File) +{ + Log_Log("IPStack", "Added file '%s'", File->Name); + File->Next = gIP_FileTemplates; + gIP_FileTemplates = File; + return 0; } /** * \brief Read from the IP Stack's Device Directory */ -char *IPStack_ReadDir(tVFS_Node *Node, int Pos) +char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos) { tInterface *iface; - char name[] = "ip0\0\0\0"; + char *name; ENTER("pNode iPos", Node, Pos); // Traverse the list @@ -89,41 +121,47 @@ char *IPStack_ReadDir(tVFS_Node *Node, int Pos) return NULL; } + name = malloc(4); + if(!name) { + Log_Warning("IPStack", "IPStack_Root_ReadDir - malloc error"); + LEAVE('n'); + return NULL; + } + // Create the name Pos = iface->Node.ImplInt; - if(Pos < 10) - name[2] = '0' + Pos; + if(Pos < 10) { + name[0] = '0' + Pos; + name[1] = '\0'; + } else if(Pos < 100) { - name[2] = '0' + Pos/10; - name[3] = '0' + Pos%10; + name[0] = '0' + Pos/10; + name[1] = '0' + Pos%10; + name[2] = '\0'; } else { - name[2] = '0' + Pos/100; - name[3] = '0' + (Pos/10)%10; - name[4] = '0' + Pos%10; + name[0] = '0' + Pos/100; + name[1] = '0' + (Pos/10)%10; + name[2] = '0' + Pos%10; + name[3] = '\0'; } LEAVE('s', name); // Return the pre-generated name - return strdup(name); + return name; } /** * \brief Get the node of an interface */ -tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name) +tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, char *Name) { int i, num; tInterface *iface; ENTER("pNode sName", Node, Name); - if(Name[0] != 'i' || Name[1] != 'p') { - LEAVE('n'); - return NULL; - } - - i = 2; num = 0; + i = 0; num = 0; while('0' <= Name[i] && Name[i] <= '9') { num *= 10; @@ -137,7 +175,7 @@ tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name) for( iface = gIP_Interfaces; iface; iface = iface->Next ) { - if( iface->Node.ImplInt == num ) + if( (int)iface->Node.ImplInt == num ) { LEAVE('p', &iface->Node); return &iface->Node; @@ -148,20 +186,102 @@ tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name) } static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL }; +/** + * \brief Handles IOCtls for the IPStack root + */ +int IPStack_Root_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: + tmp = ModUtil_SetIdent(Data, "IPStack"); + LEAVE('i', 1); + return 1; + + case DRV_IOCTL_VERSION: + LEAVE('x', VERSION); + return VERSION; + + case DRV_IOCTL_LOOKUP: + tmp = ModUtil_LookupString( (char**)casIOCtls_Root, (char*)Data ); + LEAVE('i', tmp); + return tmp; + + /* + * add_interface + * - Adds a new IP interface and binds it to a device + */ + case 4: + 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; +} + +/** + * \brief Read from an interface's directory + */ +char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos) +{ + tSocketFile *file = gIP_FileTemplates; + while(Pos-- && file) { + file = file->Next; + } + + if(!file) return NULL; + + return strdup(file->Name); +} + +/** + * \brief Gets a named node from an interface directory + */ +tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, char *Name) +{ + tSocketFile *file = gIP_FileTemplates; + + // Get file definition + for(;file;file = file->Next) + { + if( strcmp(file->Name, Name) == 0 ) break; + } + if(!file) return NULL; + + // Pass the buck! + return file->Init(Node->ImplPtr); +} + +/** + * \brief Names for interface IOCtl Calls + */ static const char *casIOCtls_Iface[] = { DRV_IOCTLNAMES, "getset_type", "get_address", "set_address", "getset_subnet", "get_gateway", "set_gateway", + "get_device", + "ping", NULL }; /** - * \brief Handles IOCtls for the IPStack root/interfaces + * \brief Handles IOCtls for the IPStack interfaces */ -int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) +int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data) { int tmp; + tInterface *iface = (tInterface*)Node->ImplPtr; ENTER("pNode iID pData", Node, ID, Data); switch(ID) @@ -172,8 +292,7 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) return DRV_TYPE_MISC; case DRV_IOCTL_IDENT: - if( !CheckMem( Data, 4 ) ) LEAVE_RET('i', -1); - memcpy(Data, "IP\0\0", 4); + tmp = ModUtil_SetIdent(Data, STR(IDENT)); LEAVE('i', 1); return 1; @@ -182,202 +301,207 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) return VERSION; case DRV_IOCTL_LOOKUP: - if( !CheckString( Data ) ) LEAVE_RET('i', -1); - LOG("Lookup '%s'", Data); - if( Node == &gIP_DriverInfo.RootNode ) - tmp = LookupString( (char**)casIOCtls_Root, (char*)Data ); - else - tmp = LookupString( (char**)casIOCtls_Iface, (char*)Data ); + tmp = ModUtil_LookupString( (char**)casIOCtls_Iface, (char*)Data ); LEAVE('i', tmp); return tmp; - } - if(Node == &gIP_DriverInfo.RootNode) - { - switch(ID) + /* + * getset_type + * - Get/Set the interface type + */ + case 4: + // Set Type? + if( Data ) { - /* - * add_interface - * - Adds a new IP interface and binds it to a device - */ + // 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; + } + } + LEAVE('i', iface->Type); + return iface->Type; + + /* + * get_address + * - Get the interface's address + */ + case 5: + switch(iface->Type) + { + case 0: LEAVE_RET('i', 1); case 4: - if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); - if( !CheckString( Data ) ) LEAVE_RET('i', -1); - tmp = IPStack_AddInterface(Data); - LEAVE_RET('i', tmp); + 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) ) ) LEAVE_RET('i', -1); + memcpy( Data, &iface->IP6.Address, sizeof(tIPv6) ); + LEAVE_RET('i', 1); } - LEAVE('i', 0); - return 0; - } - else - { - tInterface *iface = (tInterface*)Node->ImplPtr; - switch(ID) + LEAVE_RET('i', 0); + + /* + * set_address + * - Get the interface's address + */ + case 6: + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + switch(iface->Type) { - /* - * getset_type - * - Get/Set the interface type - */ + case 0: LEAVE_RET('i', 1); case 4: - // Set Type? - if( Data ) + if( !CheckMem( Data, sizeof(tIPv4) ) ) LEAVE_RET('i', -1); + iface->Type = 0; // One very hacky mutex/trash protector + memcpy( &iface->IP4.Address, Data, sizeof(tIPv4) ); + iface->Type = 4; + LEAVE_RET('i', 1); + case 6: + if( !CheckMem( Data, sizeof(tIPv6) ) ) LEAVE_RET('i', -1); + iface->Type = 0; + memcpy( &iface->IP6.Address, Data, sizeof(tIPv6) ); + iface->Type = 6; + LEAVE_RET('i', 1); + } + LEAVE_RET('i', 0); + + /* + * getset_subnet + * - Get/Set the bits in the address subnet + */ + case 7: + // Get? + if( Data == NULL ) + { + switch( iface->Type ) { - // 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; - } + case 4: LEAVE_RET('i', iface->IP4.SubnetBits); + case 6: LEAVE_RET('i', iface->IP6.SubnetBits); + default: LEAVE_RET('i', 0); } - LEAVE('i', iface->Type); - return iface->Type; + } - /* - * get_address - * - Get the interface's address - */ - case 5: - switch(iface->Type) - { - case 0: LEAVE_RET('i', 1); - case 4: - 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) ) ) LEAVE_RET('i', -1); - memcpy( Data, &iface->IP6.Address, sizeof(tIPv6) ); - LEAVE_RET('i', 1); - } - LEAVE_RET('i', 0); + // Ok, set. + if( Threads_GetUID() != 0 ) LEAVE_RET('i', -1); + if( !CheckMem(Data, sizeof(int)) ) LEAVE_RET('i', -1); - /* - * set_address - * - Get the interface's address - */ + // Check and set the subnet bits + switch( iface->Type ) + { + case 4: + if( *(int*)Data < 0 || *(int*)Data > 31 ) LEAVE_RET('i', -1); + iface->IP4.SubnetBits = *(int*)Data; + LEAVE_RET('i', iface->IP4.SubnetBits); case 6: - 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.Address, Data, sizeof(tIPv4) ); - iface->Type = 4; - LEAVE_RET('i', 1); - case 6: - if( !CheckMem( Data, sizeof(tIPv6) ) ) LEAVE_RET('i', -1); - iface->Type = 0; - memcpy( &iface->IP6.Address, Data, sizeof(tIPv6) ); - iface->Type = 6; - LEAVE_RET('i', 1); - } - LEAVE_RET('i', 0); + if( *(int*)Data < 0 || *(int*)Data > 127 ) LEAVE_RET('i', -1); + iface->IP6.SubnetBits = *(int*)Data; + LEAVE_RET('i', iface->IP6.SubnetBits); + default: + break; + } - /* - * getset_subnet - * - Get/Set the bits in the address subnet - */ - case 7: - // Get? - if( Data == NULL ) - { - switch( iface->Type ) - { - 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 ) 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 ) LEAVE_RET('i', -1); - iface->IP4.SubnetBits = *(int*)Data; - LEAVE_RET('i', iface->IP4.SubnetBits); - case 6: - if( *(int*)Data < 0 || *(int*)Data > 127 ) LEAVE_RET('i', -1); - iface->IP6.SubnetBits = *(int*)Data; - LEAVE_RET('i', iface->IP6.SubnetBits); - default: - break; - } - - LEAVE('i', 0); - return 0; + 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/Set 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); - /* - * 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; + case 6: + LEAVE_RET('i', 1); + } + break; + + /* + * get_device + * - Gets the name of the attached device + */ + case 10: + if( Data == NULL ) + LEAVE_RET('i', iface->Adapter->DeviceLen); + if( !CheckMem( Data, iface->Adapter->DeviceLen+1 ) ) + LEAVE_RET('i', -1); + strcpy( Data, iface->Adapter->Device ); + return iface->Adapter->DeviceLen; + + /* + * ping + * - Send an ICMP Echo + */ + case 11: + switch(iface->Type) + { + case 0: + LEAVE_RET('i', 1); - /* - * 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); + tmp = IPv4_Ping(iface, *(tIPv4*)Data); + LEAVE('i', tmp); + return tmp; - 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); + case 6: + LEAVE_RET('i', 1); } + break; + } LEAVE('i', 0); @@ -392,9 +516,12 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data) int IPStack_AddInterface(char *Device) { tInterface *iface; + tAdapter *card; ENTER("sDevice", Device); + card = IPStack_GetAdapter(Device); + iface = malloc(sizeof(tInterface)); if(!iface) { LEAVE('i', -2); @@ -406,14 +533,20 @@ int IPStack_AddInterface(char *Device) // Create Node iface->Node.ImplPtr = iface; - iface->Node.ImplInt = giIP_NextIfaceId++; iface->Node.Flags = VFS_FFLAG_DIRECTORY; - iface->Node.Size = 0; + iface->Node.Size = -1; iface->Node.NumACLs = 1; iface->Node.ACLs = &gVFS_ACL_EveryoneRX; - iface->Node.ReadDir = NULL; - iface->Node.FindDir = NULL; - iface->Node.IOCtl = IPStack_IOCtl; + iface->Node.ReadDir = IPStack_Iface_ReadDir; + iface->Node.FindDir = IPStack_Iface_FindDir; + iface->Node.IOCtl = IPStack_Iface_IOCtl; + iface->Node.MkNod = NULL; + iface->Node.Link = NULL; + iface->Node.Relink = NULL; + iface->Node.Close = NULL; + + // Set Defaults + iface->TimeoutDelay = DEFAULT_TIMEOUT; // Get adapter handle iface->Adapter = IPStack_GetAdapter(Device); @@ -423,6 +556,10 @@ int IPStack_AddInterface(char *Device) return -1; // Return ERR_YOUFAIL } + // Delay setting ImplInt until after the adapter is opened + // Keeps things simple + iface->Node.ImplInt = giIP_NextIfaceId++; + // Append to list LOCK( &glIP_Interfaces ); if( gIP_Interfaces ) { @@ -477,6 +614,7 @@ tAdapter *IPStack_GetAdapter(char *Path) // Fill Structure strcpy( dev->Device, Path ); dev->NRef = 1; + dev->DeviceLen = strlen(Path); // Open Device dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );