Modules/IPStack - Fix assertion failure, dedup some ACK code
[tpg/acess2.git] / KernelLand / Modules / IPStack / interface.c
index b0b63b9..ea42954 100644 (file)
@@ -7,31 +7,37 @@
 #include "ipstack.h"
 #include "link.h"
 #include <api_drv_common.h>
-#include <api_drv_network.h>
+#include "include/adapters.h"
+#include "interface.h"
 
 // === CONSTANTS ===
-//! Default timeout value, 30 seconds
-#define DEFAULT_TIMEOUT        (30*1000)
+//! Default timeout value, 5 seconds
+#define DEFAULT_TIMEOUT        (5*1000)
 
 // === IMPORTS ===
 extern int     IPv4_Ping(tInterface *Iface, tIPv4 Addr);
 //extern int   IPv6_Ping(tInterface *Iface, tIPv6 Addr);
 extern tVFS_Node       gIP_RouteNode;
+extern tVFS_Node       gIP_AdaptersNode;
 
 // === PROTOTYPES ===
-char   *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
+ int   IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+tVFS_Node      *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
  int   IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
 
  int   IPStack_AddFile(tSocketFile *File);
-tInterface     *IPStack_AddInterface(const char *Device, const char *Name);
-tAdapter       *IPStack_GetAdapter(const char *Path);
+tInterface     *IPStack_AddInterface(const char *Device, int Type, const char *Name);
 
-char   *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name);
+ int   IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+tVFS_Node      *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags);
  int   IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data);
 
 // === GLOBALS ===
+tVFS_NodeType  gIP_RootNodeType = {
+       .ReadDir = IPStack_Root_ReadDir,
+       .FindDir = IPStack_Root_FindDir,
+       .IOCtl = IPStack_Root_IOCtl
+};
 tVFS_NodeType  gIP_InterfaceNodeType = {
                .ReadDir = IPStack_Iface_ReadDir,
                .FindDir = IPStack_Iface_FindDir,
@@ -53,88 +59,59 @@ tInterface  gIP_LoopInterface = {
 tShortSpinlock glIP_Interfaces;
 tInterface     *gIP_Interfaces = NULL;
 tInterface     *gIP_Interfaces_Last = NULL;
+ int   giIP_NextIfaceId = 1;
 
 tSocketFile    *gIP_FileTemplates;
 
-tAdapter       gIP_LoopAdapter = {
-       .DeviceLen = 8,
-       .Device = "LOOPBACK"
-       };
-tMutex glIP_Adapters;
-tAdapter       *gIP_Adapters = NULL;
- int   giIP_NextIfaceId = 1;
-
 // === CODE ===
 
 /**
  * \brief Read from the IP Stack's Device Directory
  */
-char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
 {
        tInterface      *iface;
-       char    *name;
        ENTER("pNode iPos", Node, Pos);
        
 
        // Routing Subdir
        if( Pos == 0 ) {
-               LEAVE('s', "routes");
-               return strdup("routes");
+               strcpy(Dest, "routes");
+               return 0;
        }
-       // Pseudo Interfaces
+       // Adapters
        if( Pos == 1 ) {
-               LEAVE('s', "lo");
-               return strdup("lo");
+               strcpy(Dest, "adapters");
+               return 0;
        }
-       Pos -= 2;
+       // Pseudo Interfaces
+       if( Pos == 2 ) {
+               strcpy(Dest, "lo");
+               return 0;
+       }
+       Pos -= 3;
        
        // Traverse the list
        for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
        
        // Did we run off the end?
        if(!iface) {
-               LEAVE('n');
-               return NULL;
-       }
-       
-       name = malloc(4);
-       if(!name) {
-               Log_Warning("IPStack", "IPStack_Root_ReadDir - malloc error");
-               LEAVE('n');
-               return NULL;
+               LEAVE('i', -EINTERNAL);
+               return -EINVAL;
        }
        
        // Create the name
-       Pos = iface->Node.ImplInt;
-       if(Pos < 10) {
-               name[0] = '0' + Pos;
-               name[1] = '\0';
-       }
-       else if(Pos < 100) {
-               name[0] = '0' + Pos/10;
-               name[1] = '0' + Pos%10;
-               name[2] = '\0';
-       }
-       else {
-               name[0] = '0' + Pos/100;
-               name[1] = '0' + (Pos/10)%10;
-               name[2] = '0' + Pos%10;
-               name[3] = '\0';
-       }
+       strncpy(Dest, iface->Name, FILENAME_MAX);
        
-       LEAVE('s', name);
-       // Return the pre-generated name
-       return name;
+       LEAVE('i', 0);
+       return 0;
 }
 
 /**
  * \brief Get the node of an interface
  */
-tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
 {
-       #if 0
-        int    i, num;
-       #endif
        tInterface      *iface;
        
        ENTER("pNode sName", Node, Name);
@@ -145,6 +122,12 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
                return &gIP_RouteNode;
        }
        
+       // Adapters subdir
+       if( strcmp(Name, "adapters") == 0 ) {
+               LEAVE('p', &gIP_AdaptersNode);
+               return &gIP_AdaptersNode;
+       }
+       
        // Loopback
        if( strcmp(Name, "lo") == 0 ) {
                LEAVE('p', &gIP_LoopInterface.Node);
@@ -180,19 +163,32 @@ int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data)
                
        /*
         * add_interface
-        * - Adds a new IP interface and binds it to a device
+        * - Adds a new interface and binds it to a device
         */
-       case 4:
-               if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
-               if( !CheckString( Data ) )      LEAVE_RET('i', -1);
-               LOG("New interface for '%s'", Data);
-               {
-                       char    name[4] = "";
-                       tInterface      *iface = IPStack_AddInterface(Data, name);
-                       if(iface == NULL)       LEAVE_RET('i', -1);
-                       tmp = iface->Node.ImplInt;
-               }
+       case 4: {
+               const struct {
+                       const char *Device;
+                       const char *Name;
+                        int    Type;
+               } *ifinfo = Data;
+               
+               if( Threads_GetUID() != 0 )
+                       LEAVE_RET('i', -1);
+               if( !CheckMem(ifinfo, sizeof(*ifinfo)) )
+                       LEAVE_RET('i', -1);
+               if( !MM_IsUser(ifinfo->Device) || !CheckString( ifinfo->Device ) )
+                       LEAVE_RET('i', -1);
+               if( !MM_IsUser(ifinfo->Name) || !CheckString( ifinfo->Name ) )
+                       LEAVE_RET('i', -1);
+
+               LOG("New interface of type %i for '%s' named '%s'",
+                       ifinfo->Type, ifinfo->Device, ifinfo->Name);
+               tInterface *iface = IPStack_AddInterface(ifinfo->Device, ifinfo->Type, ifinfo->Name);
+               if(iface == NULL)       LEAVE_RET('i', -1);
+
+               tmp = iface->Node.ImplInt;
                LEAVE_RET('i', tmp);
+               }
        }
        LEAVE('i', 0);
        return 0;
@@ -202,39 +198,60 @@ int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data)
  * \fn tInterface *IPStack_AddInterface(char *Device)
  * \brief Adds an interface to the list
  */
-tInterface *IPStack_AddInterface(const char *Device, const char *Name)
+tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name)
 {
        tInterface      *iface;
        tAdapter        *card;
-        int    nameLen;
+        int    nameLen, addrsize;
        
        ENTER("sDevice", Device);
        
-       card = IPStack_GetAdapter(Device);
+       // Check address type
+       addrsize = IPStack_GetAddressSize(Type);
+       if( addrsize == -1 ) {
+               Log_Debug("IPStack", "Bad address type %i", Type);
+               return NULL;
+       }
+
+       // Open card
+       card = Adapter_GetByName(Device);
        if( !card ) {
                Log_Debug("IPStack", "Unable to open card '%s'", Device);
                LEAVE('n');
                return NULL;    // ERR_YOURBAD
        }
-       
-       nameLen = sprintf(NULL, "%i", giIP_NextIfaceId);
-       
+
+       // Get name length      
+       if( Name[0] )
+       {
+               nameLen = strlen(Name);
+       }
+       else
+       {
+               nameLen = snprintf(NULL, 0, "%i", giIP_NextIfaceId);
+       }
+
        iface = malloc(
                sizeof(tInterface)
                + nameLen + 1
-               + IPStack_GetAddressSize(-1)*3  // Address, Route->Network, Route->NextHop
+               + addrsize*3    // Address, Route->Network, Route->NextHop
                );
        if(!iface) {
                Log_Warning("IPStack", "AddInterface - malloc() failed");
+               // TODO: Close card
                LEAVE('n');
                return NULL;    // Return ERR_MYBAD
        }
        
        iface->Next = NULL;
-       iface->Type = 0;        // Unset type
+       iface->Type = Type;     // Unset type
        iface->Address = iface->Name + nameLen + 1;     // Address
-       iface->Route.Network = iface->Address + IPStack_GetAddressSize(-1);
-       iface->Route.NextHop = iface->Route.Network + IPStack_GetAddressSize(-1);
+       memset(iface->Address, 0, addrsize);
+       memset(&iface->Route, 0, sizeof(iface->Route));
+       iface->Route.Network = iface->Address + addrsize;
+       memset(iface->Route.Network, 0, addrsize);
+       iface->Route.NextHop = iface->Route.Network + addrsize;
+       memset(iface->Route.NextHop, 0, addrsize);
        
        // Create Node
        iface->Node.ImplPtr = iface;
@@ -250,10 +267,19 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name)
        // Get adapter handle
        iface->Adapter = card;
        
-       // Delay setting ImplInt until after the adapter is opened
-       // Keeps things simple
-       iface->Node.ImplInt = giIP_NextIfaceId++;
-       sprintf(iface->Name, "%i", (int)iface->Node.ImplInt);
+       // Set name
+       if( Name[0] )
+       {
+               iface->Node.ImplInt = 0;
+               strcpy(iface->Name, Name);
+       }
+       else
+       {
+               iface->Node.ImplInt = giIP_NextIfaceId++;
+               sprintf(iface->Name, "%i", (int)iface->Node.ImplInt);
+       }
+       
+       LOG("Creating interface '%s'", iface->Name);
        
        // Append to list
        SHORTLOCK( &glIP_Interfaces );
@@ -267,8 +293,6 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name)
        }
        SHORTREL( &glIP_Interfaces );
 
-//     gIP_DriverInfo.RootNode.Size ++;
-       
        // Success!
        LEAVE('p', iface);
        return iface;
@@ -279,7 +303,7 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name)
  */
 int IPStack_AddFile(tSocketFile *File)
 {
-       Log_Log("IPStack", "Added file '%s'", File->Name);
+//     Log_Log("IPStack", "Added file '%s'", File->Name);
        File->Next = gIP_FileTemplates;
        gIP_FileTemplates = File;
        return 0;
@@ -291,22 +315,24 @@ int IPStack_AddFile(tSocketFile *File)
 /**
  * \brief Read from an interface's directory
  */
-char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
 {
        tSocketFile     *file = gIP_FileTemplates;
        while(Pos-- && file) {
                file = file->Next;
        }
        
-       if(!file)       return NULL;
+       if(!file)
+               return -EINVAL;
        
-       return strdup(file->Name);
+       strncpy(Dest, file->Name, FILENAME_MAX);
+       return 0;
 }
 
 /**
  * \brief Gets a named node from an interface directory
  */
-tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name)
+tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
 {
        tSocketFile     *file = gIP_FileTemplates;
        
@@ -315,9 +341,13 @@ tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name)
        {
                if( strcmp(file->Name, Name) == 0 )     break;
        }
-       if(!file)       return NULL;
+       if(!file) {
+               LOG("File '%s' unknown", Name);
+               return NULL;
+       }
        
        // Pass the buck!
+       LOG("File '%s' calling %p", file->Init);
        return file->Init(Node->ImplPtr);
 }
 
@@ -355,6 +385,7 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
                // Set Type?
                if( Data )
                {
+#if 0
                        // Ok, it's set type
                        if( Threads_GetUID() != 0 ) {
                                LOG("Attempt by non-root to alter an interface (%i)", Threads_GetUID());
@@ -380,6 +411,8 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
                        
                        // Clear address
                        memset(iface->Address, 0, size);
+#endif
+                       Log_Notice("IPStack", "Interface ioctl(settype) no longer usable");
                }
                LEAVE('i', iface->Type);
                return iface->Type;
@@ -438,12 +471,17 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
        case 8:
                if( iface->Adapter == NULL )
                        LEAVE_RET('i', 0);
-               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 );
-               LEAVE_RET('i', iface->Adapter->DeviceLen);
+               char *name = Adapter_GetName(iface->Adapter);
+                int len = strlen(name);
+               if( Data ) {
+                       if( !CheckMem( Data, len+1 ) ) {
+                               free(name);
+                               LEAVE_RET('i', -1);
+                       }
+                       strcpy( Data, name );
+               }
+               free(name);
+               LEAVE_RET('i', len);
        
        /*
         * ping
@@ -471,109 +509,3 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
        return 0;
 }
 
-// --- Internal ---
-/**
- * \fn tAdapter *IPStack_GetAdapter(const char *Path)
- * \brief Gets/opens an adapter given the path
- */
-tAdapter *IPStack_GetAdapter(const char *Path)
-{
-       tAdapter        *dev;
-        int    tmp;
-       
-       ENTER("sPath", Path);
-       
-       // Check for loopback
-       if( strcmp(Path, "LOOPBACK") == 0 )
-       {
-               // Initialise if required
-               if( gIP_LoopAdapter.DeviceFD == 0 )
-               {
-                       dev = &gIP_LoopAdapter;
-                       
-                       dev->NRef = 1;
-                       dev->DeviceLen = 8;
-                       
-                       dev->DeviceFD = VFS_Open( "/Devices/fifo/anon", VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
-                       if( dev->DeviceFD == -1 ) {
-                               Log_Warning("IPStack", "Unable to open FIFO '/Devices/fifo/anon' for loopback");
-                               return NULL;
-                       }
-                       
-                       dev->MacAddr.B[0] = 'A';
-                       dev->MacAddr.B[1] = 'c';
-                       dev->MacAddr.B[2] = 'e';
-                       dev->MacAddr.B[3] = 's';
-                       dev->MacAddr.B[4] = 's';
-                       dev->MacAddr.B[5] = '2';
-                       
-                       // Start watcher
-                       Link_WatchDevice( dev );
-               }
-               LEAVE('p', &gIP_LoopAdapter);
-               return &gIP_LoopAdapter;
-       }
-       
-       Mutex_Acquire( &glIP_Adapters );
-       
-       // Check if this adapter is already open
-       for( dev = gIP_Adapters; dev; dev = dev->Next )
-       {
-               if( strcmp(dev->Device, Path) == 0 ) {
-                       dev->NRef ++;
-                       Mutex_Release( &glIP_Adapters );
-                       LEAVE('p', dev);
-                       return dev;
-               }
-       }
-       
-       // Ok, so let's open it
-       dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
-       if(!dev) {
-               Log_Warning("IPStack", "GetAdapter - malloc() failed");
-               Mutex_Release( &glIP_Adapters );
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // 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 );
-       if( dev->DeviceFD == -1 ) {
-               free( dev );
-               Mutex_Release( &glIP_Adapters );
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Check that it is a network interface
-       tmp = VFS_IOCtl(dev->DeviceFD, 0, NULL);
-       LOG("Device type = %i", tmp);
-       if( tmp != DRV_TYPE_NETWORK ) {
-               Log_Warning("IPStack", "IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
-               VFS_Close( dev->DeviceFD );
-               free( dev );
-               Mutex_Release( &glIP_Adapters );
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Get MAC Address
-       VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
-       
-       // Add to list
-       dev->Next = gIP_Adapters;
-       gIP_Adapters = dev;
-       
-       Mutex_Release( &glIP_Adapters );
-       
-       // Start watcher
-       Link_WatchDevice( dev );
-       
-       LEAVE('p', dev);
-       return dev;
-}

UCC git Repository :: git.ucc.asn.au