Multiple IPStack Related changes (and other bugfixes)
[tpg/acess2.git] / Modules / IPStack / interface.c
index 4958d7f..c6f55ba 100644 (file)
@@ -52,6 +52,11 @@ 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;
@@ -122,7 +127,9 @@ char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos)
  */
 tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
 {
+       #if 0
         int    i, num;
+       #endif
        tInterface      *iface;
        
        ENTER("pNode sName", Node, Name);
@@ -137,6 +144,7 @@ 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')
        {
@@ -157,6 +165,17 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
                        return &iface->Node;
                }
        }
+       #else
+       for( iface = gIP_Interfaces; iface; iface = iface->Next )
+       {
+               if( strcmp(iface->Name, Name) == 0 )
+               {
+                       LEAVE('p', &iface->Node);
+                       return &iface->Node;
+               }
+       }
+       #endif
+       
        LEAVE('p', NULL);
        return NULL;
 }
@@ -216,12 +235,23 @@ int IPStack_AddInterface(const char *Device, const char *Name)
 {
        tInterface      *iface;
        tAdapter        *card;
+        int    nameLen;
        
        ENTER("sDevice", Device);
        
        card = IPStack_GetAdapter(Device);
+       if( !card ) {
+               LEAVE('i', -1);
+               return -1;      // ERR_YOURBAD
+       }
        
-       iface = malloc(sizeof(tInterface) + strlen(Name));
+       nameLen = sprintf(NULL, "%i", giIP_NextIfaceId);
+       
+       iface = malloc(
+               sizeof(tInterface)
+               + nameLen + 1
+               + IPStack_GetAddressSize(-1)
+               );
        if(!iface) {
                LEAVE('i', -2);
                return -2;      // Return ERR_MYBAD
@@ -229,6 +259,7 @@ int IPStack_AddInterface(const char *Device, const char *Name)
        
        iface->Next = NULL;
        iface->Type = 0;        // Unset type
+       iface->Address = iface->Name + nameLen + 1;     // Address
        
        // Create Node
        iface->Node.ImplPtr = iface;
@@ -258,6 +289,7 @@ int IPStack_AddInterface(const char *Device, const char *Name)
        // Delay setting ImplInt until after the adapter is opened
        // Keeps things simple
        iface->Node.ImplInt = giIP_NextIfaceId++;
+       sprintf(iface->Name, "%i", iface->Node.ImplInt);
        
        // Append to list
        SHORTLOCK( &glIP_Interfaces );
@@ -333,7 +365,6 @@ static const char *casIOCtls_Iface[] = {
        "getset_type",
        "get_address", "set_address",
        "getset_subnet",
-       "get_gateway", "set_gateway",
        "get_device",
        "ping",
        NULL
@@ -343,7 +374,7 @@ 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);
        
@@ -387,24 +418,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;
@@ -414,129 +440,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 ) )
@@ -548,7 +501,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:
@@ -583,6 +536,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

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