Modules/IPStack - Add structure for propagating ICMP errors
authorJohn Hodge <[email protected]>
Mon, 16 Feb 2015 07:23:37 +0000 (15:23 +0800)
committerJohn Hodge <[email protected]>
Mon, 16 Feb 2015 07:23:37 +0000 (15:23 +0800)
KernelLand/Modules/IPStack/icmp.c
KernelLand/Modules/IPStack/ipstack.h
KernelLand/Modules/IPStack/ipv4.c
KernelLand/Modules/IPStack/ipv4.h
KernelLand/Modules/IPStack/ipv6.c
KernelLand/Modules/IPStack/ipv6.h
KernelLand/Modules/IPStack/tcp.c
KernelLand/Modules/IPStack/udp.c

index fa9927e..f34d790 100644 (file)
@@ -26,7 +26,7 @@ struct {
  */
 void ICMP_Initialise()
 {
-       IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket);
+       IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket, NULL);
 }
 
 /**
@@ -64,12 +64,15 @@ void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buff
                {
                case 3: // Port Unreachable
                        Log_Debug("ICMPv4", "Destination Unreachable (Port Unreachable)");
+                       IPv4_HandleError( Interface, IPERR_PORT_UNREACHABLE,
+                               htons(Length)-sizeof(tICMPHeader), hdr->Data );
                        break;
                default:
                        Log_Debug("ICMPv4", "Destination Unreachable (Code %i)", hdr->Code);
+                       IPv4_HandleError( Interface, IPERR_MISC,
+                               htons(Length)-sizeof(tICMPHeader), hdr->Data );
                        break;
                }
-//             IPv4_Unreachable( Interface, hdr->Code, htons(hdr->Length)-sizeof(tICMPHeader), hdr->Data );
                break;
        
        // -- 8: Echo Request
index ddcdde9..3833ce7 100644 (file)
@@ -15,7 +15,16 @@ typedef struct sAdapter      tAdapter;
 typedef struct sInterface      tInterface;
 typedef struct sSocketFile     tSocketFile;
 
-typedef void   (*tIPCallback)(tInterface *Interface, void *Address, int Length, void *Buffer);
+typedef enum eIPErrorMode
+{
+       IPERR_MISC,
+       IPERR_HOST_UNREACHABLE,
+       IPERR_PORT_UNREACHABLE,
+} tIPErrorMode;
+
+// NOTE: Non-const to allow reuse of Rx buffer for prepping Tx
+typedef void   tIPRxCallback(tInterface *Interface, void *Address, int Length, void *Buffer);
+typedef void   tIPErrorCallback(tInterface *Interface, tIPErrorMode mode, const void *Address, int Length, const void *Buffer);
 
 enum eInterfaceTypes {
        AF_NULL,
index 000fe39..371fe40 100644 (file)
@@ -20,7 +20,7 @@ extern  int   ICMP_Ping(tInterface *Interface, tIPv4 Addr);
 
 // === PROTOTYPES ===
  int   IPv4_Initialise();
- int   IPv4_RegisterCallback(int ID, tIPCallback Callback);
+// int IPv4_RegisterCallback(int ID, tIPRxCallback Callback, );
 void   IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface     *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
 Uint32 IPv4_Netmask(int FixedBits);
@@ -28,7 +28,10 @@ Uint16       IPv4_Checksum(const void *Buf, size_t Length);
  int   IPv4_Ping(tInterface *Iface, tIPv4 Addr);
 
 // === GLOBALS ===
-tIPCallback    gaIPv4_Callbacks[256];
+struct {
+       tIPRxCallback*  rx_cb;
+       tIPErrorCallback*       err_cb;
+} gaIPv4_Callbacks[256];
 
 // === CODE ===
 /**
@@ -46,11 +49,12 @@ int IPv4_Initialise()
  * \param ID   8-bit packet type ID
  * \param Callback     Callback function
  */
-int IPv4_RegisterCallback(int ID, tIPCallback Callback)
+int IPv4_RegisterCallback(int ID, tIPRxCallback *RxCallback, tIPErrorCallback *ErrCallback)
 {
        if( ID < 0 || ID > 255 )        return 0;
-       if( gaIPv4_Callbacks[ID] )      return 0;
-       gaIPv4_Callbacks[ID] = Callback;
+       if( gaIPv4_Callbacks[ID].rx_cb )        return 0;
+       gaIPv4_Callbacks[ID].rx_cb = RxCallback;
+       gaIPv4_Callbacks[ID].err_cb = ErrCallback;
        return 1;
 }
 
@@ -66,14 +70,12 @@ int IPv4_RegisterCallback(int ID, tIPCallback Callback)
  */
 int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPStackBuffer *Buffer)
 {
-       tMacAddr        to;
        tIPv4Header     hdr;
-        int    length;
 
-       length = IPStack_Buffer_GetLength(Buffer);
+       int length = IPStack_Buffer_GetLength(Buffer);
        
        // --- Resolve destination MAC address
-       to = HWCache_Resolve(Iface, &Address);
+       tMacAddr to = HWCache_Resolve(Iface, &Address);
        if( MAC_EQU(to, cMAC_ZERO) ) {
                // No route to host
                Log_Notice("IPv4", "No route to host %i.%i.%i.%i",
@@ -134,7 +136,6 @@ int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPS
 void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
 {
        tIPv4Header     *hdr = Buffer;
-       tInterface      *iface;
        Uint8   *data;
         int    dataLength;
         int    ret;
@@ -197,7 +198,7 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
        data = &hdr->Options[0];
        
        // Get Interface (allowing broadcasts)
-       iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
+       tInterface *iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
        
        // Firewall rules
        if( iface ) {
@@ -255,12 +256,29 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
        }
        
        // Send it on
-       if( !gaIPv4_Callbacks[hdr->Protocol] ) {
+       if( !gaIPv4_Callbacks[hdr->Protocol].rx_cb ) {
                Log_Log("IPv4", "Unknown Protocol %i", hdr->Protocol);
                return ;
        }
        
-       gaIPv4_Callbacks[hdr->Protocol]( iface, &hdr->Source, dataLength, data );
+       gaIPv4_Callbacks[hdr->Protocol].rx_cb( iface, &hdr->Source, dataLength, data );
+}
+
+/*
+ * Handles an error from the ICMPv4 code, 'Buf' contains part of an IPv4 packet
+ */
+void IPv4_HandleError(tInterface *Iface, tIPErrorMode Mode, size_t Length, const void *Buf)
+{
+       if(Length < sizeof(tIPv4Header))        return;
+       const tIPv4Header*      hdr = Buf;
+       if(hdr->Version != 4)   return;
+       
+       // Get Data and Data Length
+       size_t dataLength = MIN(Length, ntohs(hdr->TotalLength)) - sizeof(tIPv4Header);
+       const void *data = &hdr->Options[0];
+       
+       if( gaIPv4_Callbacks[hdr->Protocol].err_cb )
+               gaIPv4_Callbacks[hdr->Protocol].err_cb(Iface, Mode, &hdr->Source, dataLength, data);
 }
 
 /**
@@ -272,16 +290,14 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
  */
 tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
 {
-       tInterface      *iface = NULL, *zero_iface = NULL;
-       Uint32  netmask;
-       Uint32  addr, this;
+       tInterface      *zero_iface = NULL;
 
        ENTER("pAdapter xAddress bBroadcast", Adapter, Address, Broadcast);     
 
-       addr = ntohl( Address.L );
+       Uint32 addr = ntohl( Address.L );
        LOG("addr = 0x%x", addr);
        
-       for( iface = gIP_Interfaces; iface; iface = iface->Next)
+       for( tInterface *iface = gIP_Interfaces; iface; iface = iface->Next)
        {
                if( iface->Adapter != Adapter ) continue;
                if( iface->Type != 4 )  continue;
@@ -307,8 +323,8 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
                if( !Broadcast )        continue;
                
                // Check for broadcast
-               this = ntohl( ((tIPv4*)iface->Address)->L );
-               netmask = IPv4_Netmask(iface->SubnetBits);
+               Uint32 this = ntohl( ((tIPv4*)iface->Address)->L );
+               Uint32 netmask = IPv4_Netmask(iface->SubnetBits);
                LOG("iface addr = 0x%x, netmask = 0x%x (bits = %i)", this, netmask, iface->SubnetBits);
 
                if( (addr & netmask) == (this & netmask) && (addr & ~netmask) == (0xFFFFFFFF & ~netmask) )
index dd78788..c31b751 100644 (file)
@@ -47,9 +47,11 @@ struct sIPv4Header
 #define IPV4_ETHERNET_ID       0x0800
 
 // === FUNCTIONS ===
-extern int     IPv4_RegisterCallback(int ID, tIPCallback Callback);
+extern int     IPv4_RegisterCallback(int ID, tIPRxCallback *RxCallback, tIPErrorCallback *ErrCallback);
 extern Uint16  IPv4_Checksum(const void *Buf, size_t Length);
 extern Uint32  IPv4_Netmask(int FixedBits);
 extern int     IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPStackBuffer *Buffer);
 
+extern void    IPv4_HandleError(tInterface *Iface, tIPErrorMode Mode, size_t Length, const void *Buf);
+
 #endif
index 2ac0574..0e6df53 100644 (file)
@@ -14,12 +14,12 @@ extern Uint32       IPv4_Netmask(int FixedBits);
 
 // === PROTOTYPES ===
  int   IPv6_Initialise();
- int   IPv6_RegisterCallback(int ID, tIPCallback Callback);
+// int IPv6_RegisterCallback(int ID, tIPCallback Callback);
 void   IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface     *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
 
 // === GLOBALS ===
-tIPCallback    gaIPv6_Callbacks[256];
+tIPRxCallback* gaIPv6_Callbacks[256];
 
 // === CODE ===
 /**
@@ -36,7 +36,7 @@ int IPv6_Initialise()
  * \param ID   8-bit packet type ID
  * \param Callback     Callback function
  */
-int IPv6_RegisterCallback(int ID, tIPCallback Callback)
+int IPv6_RegisterCallback(int ID, tIPRxCallback* Callback)
 {
        if( ID < 0 || ID > 255 )        return 0;
        if( gaIPv6_Callbacks[ID] )      return 0;
index fec00f7..086dfbb 100644 (file)
@@ -37,7 +37,7 @@ struct sIPv6Header
 
 #define IPV6_ETHERNET_ID       0x86DD
 
-extern int     IPv6_RegisterCallback(int ID, tIPCallback Callback);
+extern int     IPv6_RegisterCallback(int ID, tIPRxCallback* Callback);
 extern int     IPv6_SendPacket(tInterface *Iface, tIPv6 Destination, int Protocol, tIPStackBuffer *Buffer);
 
 #endif
index a8a059a..2854f30 100644 (file)
@@ -28,6 +28,7 @@ void  TCP_StartConnection(tTCPConnection *Conn);
 void   TCP_SendPacket(tTCPConnection *Conn, tTCPHeader *Header, size_t DataLen, const void *Data);
 void   TCP_int_SendPacket(tInterface *Interface, const void *Dest, tTCPHeader *Header, size_t Length, const void *Data);
 void   TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
+void   TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer);
  int   TCP_INT_HandleServerPacket(tInterface *Interface, tTCPListener *Server, const void *Address, tTCPHeader *Header, size_t Length);
  int   TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length);
 int    TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length);
@@ -94,7 +95,7 @@ void TCP_Initialise(void)
        giTCP_NextOutPort += rand()%128;
        IPStack_AddFile(&gTCP_ServerFile);
        IPStack_AddFile(&gTCP_ClientFile);
-       IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
+       IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket, TCP_IPError);
        IPv6_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
 }
 
@@ -304,6 +305,29 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
        }
 }
 
+void TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer)
+{
+       if( Length < sizeof(tTCPHeader) )       return ;
+       
+       const tTCPHeader        *hdr = Buffer;
+       
+       // TODO: Handle errors for server connections
+       
+       for( tTCPConnection *conn = gTCP_OutbountCons; conn; conn = conn->Next )
+       {
+               if(conn->Interface != Interface)
+                       continue;
+               if(conn->RemotePort != ntohs(hdr->SourcePort))
+                       continue;
+               if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
+                       continue ;
+               
+               // Mark an error on the interface
+               VFS_MarkError(&conn->Node, 1);
+               return ;
+       }
+}
+
 /*
  * Handle packets in LISTEN state
  */
index b9dd323..9037439 100644 (file)
@@ -15,7 +15,7 @@
 // === PROTOTYPES ===
 void   UDP_Initialise();
 void   UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
-void   UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer);
+void   UDP_IPError(tInterface *Interface, tIPErrorMode Code, const void *Address, int Length, const void *Buffer);
 void   UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, Uint16 Port, const void *Data, size_t Length);
 // --- Client Channels
 tVFS_Node      *UDP_Channel_Init(tInterface *Interface);
@@ -56,8 +56,7 @@ tSocketFile   gUDP_SocketFile = {NULL, "udp", UDP_Channel_Init};
 void UDP_Initialise()
 {
        IPStack_AddFile(&gUDP_SocketFile);
-       //IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_Unreachable);
-       IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
+       IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_IPError);
 }
 
 /**
@@ -146,7 +145,7 @@ void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
 /**
  * \brief Handle an ICMP Unrechable Error
  */
-void UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer)
+void UDP_IPError(tInterface *Interface, tIPErrorMode Code, const void *Address, int Length, const void *Buffer)
 {
        
 }

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