X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Finterface.c;h=65380783712eb58da59a425a210d8cea370fc666;hb=4f1a9b430a3fa57bbe52a6a2fe546f6fe93c389d;hp=4958d7fca1a9ffc34540941e7e57a6e1410f0c48;hpb=8c721d1069e9c0c769b847e9903d83b99d1acdfe;p=tpg%2Facess2.git diff --git a/Modules/IPStack/interface.c b/Modules/IPStack/interface.c index 4958d7fc..65380783 100644 --- a/Modules/IPStack/interface.c +++ b/Modules/IPStack/interface.c @@ -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; @@ -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; } @@ -173,34 +192,19 @@ 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); + tmp = iface->Node.ImplInt; } LEAVE_RET('i', tmp); } @@ -209,26 +213,40 @@ 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 ) { + LEAVE('n'); + return NULL; // ERR_YOURBAD + } + + nameLen = sprintf(NULL, "%i", giIP_NextIfaceId); - iface = malloc(sizeof(tInterface) + strlen(Name)); + 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 + 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; @@ -251,13 +269,14 @@ int IPStack_AddInterface(const char *Device, const char *Name) iface->Adapter = IPStack_GetAdapter(Device); if( !iface->Adapter ) { free( iface ); - LEAVE('i', -1); - return -1; // Return ERR_YOUFAIL + LEAVE('n'); + return NULL; // Return ERR_YOUFAIL } // 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 ); @@ -274,8 +293,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; } /** @@ -333,7 +352,6 @@ static const char *casIOCtls_Iface[] = { "getset_type", "get_address", "set_address", "getset_subnet", - "get_gateway", "set_gateway", "get_device", "ping", NULL @@ -343,30 +361,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 @@ -387,24 +389,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 +411,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 +472,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 +507,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