From 94ecc5441605ad5151e625457531e7f90470db31 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 14 Nov 2010 18:27:23 +0800 Subject: [PATCH] Reworked the IPStack tInterface structure - Now no longer explicitly mentions IPv4/IPv6 - Also allowed the cleaning up of a nice chunk of the interface code --- Modules/IPStack/arp.c | 9 +- Modules/IPStack/interface.c | 175 +++++++++++------------------------- Modules/IPStack/ipstack.h | 53 ++++++----- Modules/IPStack/ipv4.c | 10 +-- Modules/IPStack/ipv6.c | 18 ++-- Modules/IPStack/main.c | 8 +- Modules/IPStack/routing.c | 14 --- Modules/IPStack/tcp.c | 2 +- 8 files changed, 113 insertions(+), 176 deletions(-) diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c index d84b9187..fda1b2f9 100644 --- a/Modules/IPStack/arp.c +++ b/Modules/IPStack/arp.c @@ -75,6 +75,9 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) ENTER("pInterface xAddress", Interface, Address); + // Check routing tables + // Replace address with gateway if needed + Mutex_Acquire( &glARP_Cache4 ); for( i = 0; i < giARP_Cache4Space; i++ ) { @@ -106,7 +109,7 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) req.SWSize = 4; req.Request = htons(1); req.SourceMac = Interface->Adapter->MacAddr; - req.SourceIP = Interface->IP4.Address; + req.SourceIP = *(tIPv4*)Interface->Address; req.DestMac = cMAC_BROADCAST; req.DestIP = Address; @@ -276,7 +279,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe req4->DestIP = req4->SourceIP; req4->DestMac = req4->SourceMac; - req4->SourceIP = iface->IP4.Address; + req4->SourceIP = *(tIPv4*)iface->Address;; req4->SourceMac = Adapter->MacAddr; req4->Request = htons(2); Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)", @@ -301,7 +304,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe { req6->DestIP = req6->SourceIP; req6->DestMac = req6->SourceMac; - req6->SourceIP = iface->IP6.Address; + req6->SourceIP = *(tIPv6*)iface->Address; req6->SourceMac = Adapter->MacAddr; req6->Request = htons(2); Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)", diff --git a/Modules/IPStack/interface.c b/Modules/IPStack/interface.c index 9b11e5f3..445e5892 100644 --- a/Modules/IPStack/interface.c +++ b/Modules/IPStack/interface.c @@ -230,12 +230,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 + } + + nameLen = sprintf(NULL, "%i", giIP_NextIfaceId); - iface = malloc(sizeof(tInterface) + sprintf(NULL, "%i", giIP_NextIfaceId) + 1); + iface = malloc( + sizeof(tInterface) + + nameLen + 1 + + IPStack_GetAddressSize(-1) + ); if(!iface) { LEAVE('i', -2); return -2; // Return ERR_MYBAD @@ -243,6 +254,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; @@ -348,7 +360,6 @@ static const char *casIOCtls_Iface[] = { "getset_type", "get_address", "set_address", "getset_subnet", - "get_gateway", "set_gateway", "get_device", "ping", NULL @@ -358,7 +369,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); @@ -402,24 +413,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 +435,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 +496,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: diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h index 885e048d..db93328d 100644 --- a/Modules/IPStack/ipstack.h +++ b/Modules/IPStack/ipstack.h @@ -39,41 +39,48 @@ struct sMacAddr { } __attribute__((packed)); struct sInterface { - struct sInterface *Next; - tVFS_Node Node; - tAdapter *Adapter; - int TimeoutDelay; // Time in miliseconds before a packet times out - int Type; // 0 for disabled, 4 for IPv4 and 6 for IPv6 + struct sInterface *Next; //!< Next interface in list - //TODO: Remove explicit mentions of IPv4/IPv6 and make more general - union { - struct { - tIPv6 Address; - int SubnetBits; //Should this be outside the union? - } IP6; - - struct { - tIPv4 Address; - tIPv4 Gateway; - int SubnetBits; - } IP4; - }; + tVFS_Node Node; //!< Node to use the interface + + tAdapter *Adapter; //!< Adapter the interface is associated with + int TimeoutDelay; //!< Time in miliseconds before a packet times out + int Type; //!< Interface type, see ::eInterfaceTypes + + void *Address; //!< IP address (stored after the Name) + int SubnetBits; //!< Number of bits that denote the address network char Name[]; }; +/** + * \brief Route definition structure + */ +typedef struct sRoute { + struct sRoute *Next; + + tVFS_Node Node; //!< Node for route manipulation + + tInterface *Interface; //!< Interface for this route + int AddressType; //!< 0: Invalid, 4: IPv4, 6: IPv4 + void *Network; //!< Network - Pointer to tIPv4/tIPv6/... at end of structure + int SubnetBits; //!< Number of bits in \a Network that are valid + void *NextHop; //!< Next Hop address - Pointer to tIPv4/tIPv6/... at end of structure + int Metric; //!< Route priority +} tRoute; + /** * \brief Represents a network adapter */ struct sAdapter { struct sAdapter *Next; - int DeviceFD; - int NRef; + int DeviceFD; //!< File descriptor of the device + int NRef; //!< Number of times it's been referenced - tMacAddr MacAddr; - int DeviceLen; - char Device[]; + tMacAddr MacAddr; //!< Physical address of the adapter + int DeviceLen; //!< Device name length + char Device[]; //!< Device name }; /** diff --git a/Modules/IPStack/ipv4.c b/Modules/IPStack/ipv4.c index e2f18f8b..e37085bf 100644 --- a/Modules/IPStack/ipv4.c +++ b/Modules/IPStack/ipv4.c @@ -71,7 +71,7 @@ int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, int // OUTPUT Firewall rule go here ret = IPTablesV4_TestChain("OUTPUT", - &Iface->IP4.Address, &Address, + (tIPv4*)Iface->Address, &Address, Protocol, 0, Length, Data); if(ret != 0) { @@ -95,7 +95,7 @@ int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, int hdr->TTL = DEFAULT_TTL; hdr->Protocol = Protocol; hdr->HeaderChecksum = 0; // Will be set later - hdr->Source = Iface->IP4.Address; + hdr->Source = *(tIPv4*)Iface->Address; hdr->Destination = Address; hdr->HeaderChecksum = IPv4_Checksum(hdr, sizeof(tIPv4Header)); @@ -236,15 +236,15 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast) { if( iface->Adapter != Adapter ) continue; if( iface->Type != 4 ) continue; - if( IP4_EQU(Address, iface->IP4.Address) ) + if( IP4_EQU(Address, *(tIPv4*)iface->Address) ) return iface; if( !Broadcast ) continue; - this = ntohl( iface->IP4.Address.L ); + this = ntohl( ((tIPv4*)iface->Address)->L ); // Check for broadcast - netmask = IPv4_Netmask(iface->IP4.SubnetBits); + netmask = IPv4_Netmask(iface->SubnetBits); if( (addr & netmask) == (this & netmask) && (addr & ~netmask) == (0xFFFFFFFF & ~netmask) ) diff --git a/Modules/IPStack/ipv6.c b/Modules/IPStack/ipv6.c index aac33dea..561297db 100644 --- a/Modules/IPStack/ipv6.c +++ b/Modules/IPStack/ipv6.c @@ -75,32 +75,34 @@ tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast) for( iface = gIP_Interfaces; iface; iface = iface->Next) { + tIPv6 *thisAddr; // Check for this adapter if( iface->Adapter != Adapter ) continue; // Skip non-IPv6 Interfaces if( iface->Type != 6 ) continue; + thisAddr = (tIPv6*)iface->Address; // If the address is a perfect match, return this interface - if( IP6_EQU(Address, iface->IP6.Address) ) return iface; + if( IP6_EQU(Address, *thisAddr) ) return iface; // Check if we want to match broadcast addresses if( !Broadcast ) continue; // Check for broadcast - if( iface->IP6.SubnetBits > 32 && Address.L[0] != iface->IP6.Address.L[0] ) + if( iface->SubnetBits > 32 && Address.L[0] != thisAddr->L[0] ) continue; - if( iface->IP6.SubnetBits > 64 && Address.L[1] != iface->IP6.Address.L[1] ) + if( iface->SubnetBits > 64 && Address.L[1] != thisAddr->L[1] ) continue; - if( iface->IP6.SubnetBits > 96 && Address.L[2] != iface->IP6.Address.L[2] ) + if( iface->SubnetBits > 96 && Address.L[2] != thisAddr->L[2] ) continue; - j = iface->IP6.SubnetBits / 32; - i = iface->IP6.SubnetBits % 32; - netmask = IPv4_Netmask( iface->IP6.SubnetBits % 32 ); + j = iface->SubnetBits / 32; + i = iface->SubnetBits % 32; + netmask = IPv4_Netmask( iface->SubnetBits % 32 ); // Check the last bit of the netmask - if( (Address.L[j] >> i) != (iface->IP6.Address.L[j] >> i) ) continue; + if( (Address.L[j] >> i) != (thisAddr->L[j] >> i) ) continue; // Check that the host portion is one if( (Address.L[j] & ~netmask) != (0xFFFFFFFF & ~netmask) ) continue; diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 577cd38a..585f8c3e 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -88,13 +88,19 @@ int IPStack_GetAddressSize(int AddressType) { switch(AddressType) { - default: + case -1: // -1 = maximum + return sizeof(tIPv6); + case AF_NULL: return 0; + case AF_INET4: return sizeof(tIPv4); case AF_INET6: return sizeof(tIPv6); + + default: + return 0; } } diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c index 643de1ee..51eb6db5 100644 --- a/Modules/IPStack/routing.c +++ b/Modules/IPStack/routing.c @@ -12,20 +12,6 @@ // === IMPORTS === tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Filename); -// === TYPES === -typedef struct sRoute { - struct sRoute *Next; - - tVFS_Node Node; - - tInterface *Interface; // Interface for this route - int AddressType; // 0: Invalid, 4: IPv4, 6: IPv4 - void *Network; // Network - Pointer to tIPv4/tIPv6/... at end of structure - int SubnetBits; // Number of bits in \a Network that are valid - void *NextHop; // Next Hop address - Pointer to tIPv4/tIPv6/... at end of structure - int Metric; // Route priority -} tRoute; - // === PROTOTYPES === // - Routes directory char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos); diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c index 99e6719f..37415036 100644 --- a/Modules/IPStack/tcp.c +++ b/Modules/IPStack/tcp.c @@ -79,7 +79,7 @@ void TCP_SendPacket( tTCPConnection *Conn, size_t Length, tTCPHeader *Data ) case 4: // Append IPv4 Pseudo Header buflen = 4 + 4 + 4 + ((Length+1)&~1); buf = malloc( buflen ); - buf[0] = Conn->Interface->IP4.Address.L; + buf[0] = ((tIPv4*)Conn->Interface->Address)->L; buf[1] = Conn->RemoteIP.v4.L; buf[2] = (htons(Length)<<16) | (6<<8) | 0; Data->Checksum = 0; -- 2.20.1