IPStack - Firewall cleanups and speedups (now shoudl at least work)
authorJohn Hodge <[email protected]>
Sat, 7 May 2011 13:36:23 +0000 (21:36 +0800)
committerJohn Hodge <[email protected]>
Sat, 7 May 2011 13:36:23 +0000 (21:36 +0800)
Modules/IPStack/firewall.c

index d279bf3..9da14f6 100644 (file)
@@ -5,14 +5,36 @@
 #include "ipstack.h"
 #include "firewall.h"
 
+#define MAX_ADDRTYPE   9
+
 // === IMPORTS ===
 
 // === TYPES ===
+typedef struct sKeyValue       tKeyValue;
 typedef struct sFirewallMod    tFirewallMod;
 typedef struct sModuleRule     tModuleRule;
 typedef struct sRule   tRule;
 typedef struct sChain  tChain;
 
+// === STRUCTURES ===
+struct sKeyValue
+{
+       const char      *Key;
+       const char      *Value;
+};
+
+struct sFirewallMod
+{
+       const char      *Name;
+       
+        int    (*Match)(tModuleRule *Rule, int AddrType,
+                               const void *Src, const void *Dest,
+                               Uint8 Type, Uint32 Flags,
+                               size_t Length, const void *Data);
+       
+       tModuleRule     *(*Create)(tKeyValue *Params);
+};
+
 struct sModuleRule
 {
        tModuleRule     *Next;
@@ -29,17 +51,17 @@ struct sRule
         int    PacketCount;    // Number of packets seen
         int    ByteCount;              // Number of bytes seen (IP Payload bytes)
        
-        int    bInvertSource;
-       void    *Source;
-        int    SourceMask;
+        int    bInvertSource;  // Boolean NOT flag on source
+       void    *Source;        // Source address bytes
+        int    SourceMask;     // Source address mask bits
         
-        int    bInvertDest;
-       void    *Dest;
-        int    DestMask;
+        int    bInvertDest;    // Boolean NOT flag on destination
+       void    *Dest;  // Destination address bytes
+        int    DestMask;       // Destination address mask bits
        
-       tModuleRule     *Modules;
+       tModuleRule     *Modules;       // Modules loaded for this rule
        
-       char    Action[];       // Target rule name
+       char    Target[];       // Target rule name
 };
 
 struct sChain
@@ -62,19 +84,45 @@ struct sChain
        );
 
 // === GLOBALS ===
-tChain *gapFirewall_Chains[10];
+tChain *gapFirewall_Chains[MAX_ADDRTYPE+1];
 tChain gFirewall_DROP = {.Name="DROP"};
 tChain gFirewall_ACCEPT = {.Name="ACCEPT"};
 tChain gFirewall_RETURN = {.Name="RETURN"};
 
 // === CODE ===
+/**
+ * \brief Apply a rule to a packet
+ * \return -1 for no match, -2 for RETURN, eFirewallAction otherwise
+ */
 int IPTables_DoRule(
        tRule *Rule, int AddrType,
        const void *Src, const void *Dest,
        Uint8 Type, Uint32 Flags,
        size_t Length, const void *Data)
 {
-       return 0;
+        int    rv;
+       // Check if source doesn't match
+       if( !IPStack_CompareAddress(AddrType, Src, Rule->Source, Rule->SourceMask) == !Rule->bInvertSource )
+               return -1;
+       // Check if destination doesn't match
+       if( !IPStack_CompareAddress(AddrType, Dest, Rule->Dest, Rule->DestMask) == !Rule->bInvertDest )
+               return -1;
+       
+       // TODO: Handle modules (UDP/TCP/etc)
+       tModuleRule *modrule;
+       for( modrule = Rule->Modules; modrule; modrule = modrule->Next )
+       {
+               if( !modrule->Mod->Match )      continue;
+               rv = modrule->Mod->Match(modrule, AddrType, Src, Dest, Type, Flags, Length, Data);
+               if(rv == -1)    return -1;      // no match
+               // TODO: If != 0 maybe, allowing it to ask for a drop?
+       }
+       
+       // Update statistics
+       Rule->PacketCount ++;
+       Rule->ByteCount += Length;
+       
+       return IPTables_TestChain(Rule->Target, AddrType, Src, Dest, Type, Flags, Length, Data);
 }
 
 /**
@@ -93,6 +141,15 @@ int IPTables_TestChain(
        tChain  *chain;
        tRule   *rule;
        
+       if( AddressType >= MAX_ADDRTYPE )       return -1;      // Bad address type
+       
+       // Catch builtin targets
+       if(strcmp(RuleName, "") == 0)   return -1;      // No action
+       if(strcmp(RuleName, "ACCEPT") == 0)     return 0;       // Accept packet
+       if(strcmp(RuleName, "DROP") == 0)       return 1;       // Drop packet
+       if(strcmp(RuleName, "RETURN") == 0)     return -2;      // Return from rule
+       
+       // Find the rule
        for( chain = gapFirewall_Chains[AddressType]; chain; chain = chain->Next )
        {
                if( strcmp(chain->Name, RuleName) == 0 )
@@ -106,6 +163,8 @@ int IPTables_TestChain(
                rv = IPTables_DoRule(rule, AddressType, Src, Dest, Type, Flags, Length, Data);
                if( rv == -1 )
                        continue ;
+               if( rv == -2 )  // -2 = Return from a chain/table, pretend no match
+                       return -1;
                
                return rv;
        }

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