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++ )
{
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;
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)",
{
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)",
{
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
iface->Next = NULL;
iface->Type = 0; // Unset type
+ iface->Address = iface->Name + nameLen + 1; // Address
// Create Node
iface->Node.ImplPtr = iface;
"getset_type",
"get_address", "set_address",
"getset_subnet",
- "get_gateway", "set_gateway",
"get_device",
"ping",
NULL
*/
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);
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;
* - 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 ) )
* ping
* - Send an ICMP Echo
*/
- case 11:
+ case 9:
switch(iface->Type)
{
case 0:
} __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
};
/**
// OUTPUT Firewall rule go here
ret = IPTablesV4_TestChain("OUTPUT",
- &Iface->IP4.Address, &Address,
+ (tIPv4*)Iface->Address, &Address,
Protocol, 0,
Length, Data);
if(ret != 0) {
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));
{
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) )
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;
{
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;
}
}
// === 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);
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;