Renamed tpl_drv_* to api_drv_* (a more fitting name)
[tpg/acess2.git] / Modules / IPStack / interface.c
index 9b11e5f..e08d650 100644 (file)
@@ -6,8 +6,8 @@
 #define VERSION        VER2(0,10)
 #include "ipstack.h"
 #include "link.h"
-#include <tpl_drv_common.h>
-#include <tpl_drv_network.h>
+#include <api_drv_common.h>
+#include <api_drv_network.h>
 
 // === CONSTANTS ===
 //! Default timeout value, 30 seconds
@@ -23,8 +23,8 @@ char  *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
  int   IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
 
- int   IPStack_AddInterface(const char *Device, const char *Name);
  int   IPStack_AddFile(tSocketFile *File);
+tInterface     *IPStack_AddInterface(const char *Device, const char *Name);
 tAdapter       *IPStack_GetAdapter(const char *Path);
 
 char   *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos);
@@ -34,24 +34,29 @@ tVFS_Node   *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name);
 // === GLOBALS ===
 //! Loopback (127.0.0.0/8, ::1) Pseudo-Interface
 tInterface     gIP_LoopInterface = {
-       Node: {
-               ImplPtr: &gIP_LoopInterface,
-               Flags: VFS_FFLAG_DIRECTORY,
-               Size: -1,
-               NumACLs: 1,
-               ACLs: &gVFS_ACL_EveryoneRX,
-               ReadDir: IPStack_Iface_ReadDir,
-               FindDir: IPStack_Iface_FindDir,
-               IOCtl: IPStack_Iface_IOCtl
+       .Node = {
+               .ImplPtr = &gIP_LoopInterface,
+               .Flags = VFS_FFLAG_DIRECTORY,
+               .Size = -1,
+               .NumACLs = 1,
+               .ACLs = &gVFS_ACL_EveryoneRX,
+               .ReadDir = IPStack_Iface_ReadDir,
+               .FindDir = IPStack_Iface_FindDir,
+               .IOCtl = IPStack_Iface_IOCtl
        },
-       Adapter: NULL,
-       Type: 0
+       .Adapter = NULL,
+       .Type = 0
 };
 tShortSpinlock glIP_Interfaces;
 tInterface     *gIP_Interfaces = NULL;
 tInterface     *gIP_Interfaces_Last = NULL;
 
 tSocketFile    *gIP_FileTemplates;
+
+tAdapter       gIP_LoopAdapter = {
+       .DeviceLen = 8,
+       .Device = "LOOPBACK"
+       };
 tMutex glIP_Adapters;
 tAdapter       *gIP_Adapters = NULL;
  int   giIP_NextIfaceId = 1;
@@ -139,28 +144,6 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
                return &gIP_LoopInterface.Node;
        }
        
-       #if 0
-       i = 0;  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; iface = iface->Next )
-       {
-               if( (int)iface->Node.ImplInt == num )
-               {
-                       LEAVE('p', &iface->Node);
-                       return &iface->Node;
-               }
-       }
-       #else
        for( iface = gIP_Interfaces; iface; iface = iface->Next )
        {
                if( strcmp(iface->Name, Name) == 0 )
@@ -169,7 +152,6 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
                        return &iface->Node;
                }
        }
-       #endif
        
        LEAVE('p', NULL);
        return NULL;
@@ -187,34 +169,20 @@ int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *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;
+       BASE_IOCTLS(DRV_TYPE_MISC, "IPStack", VERSION, casIOCtls_Root)
                
-               /*
-                * add_interface
-                * - Adds a new IP interface and binds it to a device
-                */
+       /*
+        * 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);
                {
                        char    name[4] = "";
-                       tmp = IPStack_AddInterface(Data, name);
+                       tInterface      *iface = IPStack_AddInterface(Data, name);
+                       if(iface == NULL)       LEAVE_RET('i', -1);
+                       tmp = iface->Node.ImplInt;
                }
                LEAVE_RET('i', tmp);
        }
@@ -223,26 +191,42 @@ int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data)
 }
 
 /**
- * \fn int IPStack_AddInterface(char *Device)
+ * \fn tInterface *IPStack_AddInterface(char *Device)
  * \brief Adds an interface to the list
  */
-int IPStack_AddInterface(const char *Device, const char *Name)
+tInterface *IPStack_AddInterface(const char *Device, const char *Name)
 {
        tInterface      *iface;
        tAdapter        *card;
+        int    nameLen;
        
        ENTER("sDevice", Device);
        
        card = IPStack_GetAdapter(Device);
+       if( !card ) {
+               Log_Debug("IPStack", "Unable to open card '%s'", Device);
+               LEAVE('n');
+               return NULL;    // ERR_YOURBAD
+       }
        
-       iface = malloc(sizeof(tInterface) + sprintf(NULL, "%i", giIP_NextIfaceId) + 1);
+       nameLen = sprintf(NULL, "%i", giIP_NextIfaceId);
+       
+       iface = malloc(
+               sizeof(tInterface)
+               + nameLen + 1
+               + IPStack_GetAddressSize(-1)*3  // Address, Route->Network, Route->NextHop
+               );
        if(!iface) {
-               LEAVE('i', -2);
-               return -2;      // Return ERR_MYBAD
+               Log_Warning("IPStack", "AddInterface - malloc() failed");
+               LEAVE('n');
+               return NULL;    // Return ERR_MYBAD
        }
        
        iface->Next = NULL;
        iface->Type = 0;        // 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);
        
        // Create Node
        iface->Node.ImplPtr = iface;
@@ -262,12 +246,7 @@ int IPStack_AddInterface(const char *Device, const char *Name)
        iface->TimeoutDelay = DEFAULT_TIMEOUT;
        
        // Get adapter handle
-       iface->Adapter = IPStack_GetAdapter(Device);
-       if( !iface->Adapter ) {
-               free( iface );
-               LEAVE('i', -1);
-               return -1;      // Return ERR_YOUFAIL
-       }
+       iface->Adapter = card;
        
        // Delay setting ImplInt until after the adapter is opened
        // Keeps things simple
@@ -289,8 +268,8 @@ int IPStack_AddInterface(const char *Device, const char *Name)
 //     gIP_DriverInfo.RootNode.Size ++;
        
        // Success!
-       LEAVE('i', iface->Node.ImplInt);
-       return iface->Node.ImplInt;
+       LEAVE('p', iface);
+       return iface;
 }
 
 /**
@@ -348,7 +327,6 @@ static const char *casIOCtls_Iface[] = {
        "getset_type",
        "get_address", "set_address",
        "getset_subnet",
-       "get_gateway", "set_gateway",
        "get_device",
        "ping",
        NULL
@@ -358,30 +336,14 @@ static const char *casIOCtls_Iface[] = {
  */
 int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
 {
-        int    tmp;
+        int    tmp, size;
        tInterface      *iface = (tInterface*)Node->ImplPtr;
        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, 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_Iface, (char*)Data );
-               LEAVE('i', tmp);
-               return tmp;
+       BASE_IOCTLS(DRV_TYPE_MISC, "IPStack", VERSION, casIOCtls_Iface)
        
        /*
         * getset_type
@@ -402,24 +364,19 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
                                LEAVE('i', -1);
                                return -1;
                        }
-                       switch( *(int*)Data )
-                       {
-                       case 0: // Disable
+                       
+                       // Set type
+                       iface->Type = *(int*)Data;
+                       size = IPStack_GetAddressSize(iface->Type);
+                       // Check it's actually valid
+                       if( iface->Type != 0 && size == 0 ) {
                                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;
                        }
+                       
+                       // Clear address
+                       memset(iface->Address, 0, size);
                }
                LEAVE('i', iface->Type);
                return iface->Type;
@@ -429,129 +386,56 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
         * - 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);
+               size = IPStack_GetAddressSize(iface->Type);
+               if( !CheckMem( Data, size ) )   LEAVE_RET('i', -1);
+               memcpy( Data, iface->Address, size );
+               LEAVE('i', 1);
+               return 1;
        
        /*
         * set_address
-        * - Get the interface's address
+        * - Set the interface's address
         */
        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);
+               
+               size = IPStack_GetAddressSize(iface->Type);
+               if( !CheckMem( Data, size ) )   LEAVE_RET('i', -1);
+               // TODO: Protect against trashing
+               memcpy( iface->Address, Data, size );
+               LEAVE('i', 1);
+               return 1;
        
        /*
         * 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;
-               
-       /*
-        * 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)
+               // Do we want to set the value?
+               if( Data )
                {
-               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);
+                       // Are we root? (TODO: Check Owner/Group)
+                       if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
+                       // Is the memory valid
+                       if( !CheckMem(Data, sizeof(int)) )      LEAVE_RET('i', -1);
                        
-               case 6:
-                       LEAVE_RET('i', 1);
+                       // Is the mask sane?
+                       if( *(int*)Data < 0 || *(int*)Data > IPStack_GetAddressSize(iface->Type)*8-1 )
+                               LEAVE_RET('i', -1);
+                       
+                       // Ok, set it
+                       iface->SubnetBits = *(int*)Data;
                }
-               break;
+               LEAVE('i', iface->SubnetBits);
+               return iface->SubnetBits;
        
        /*
         * get_device
         * - Gets the name of the attached device
         */
-       case 10:
+       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 ) )
@@ -563,7 +447,7 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
         * ping
         * - Send an ICMP Echo
         */
-       case 11:
+       case 9:
                switch(iface->Type)
                {
                case 0:
@@ -598,6 +482,37 @@ tAdapter *IPStack_GetAdapter(const char *Path)
        
        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
@@ -614,6 +529,7 @@ tAdapter *IPStack_GetAdapter(const char *Path)
        // 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;
@@ -637,7 +553,7 @@ tAdapter *IPStack_GetAdapter(const char *Path)
        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);
+               Log_Warning("IPStack", "IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
                VFS_Close( dev->DeviceFD );
                free( dev );
                Mutex_Release( &glIP_Adapters );

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