IPStack - Firewall cleanups and speedups (now shoudl at least work)
[tpg/acess2.git] / Modules / IPStack / firewall.c
1 /*
2  * Acess2 IP Stack
3  * - Firewall Rules
4  */
5 #include "ipstack.h"
6 #include "firewall.h"
7
8 #define MAX_ADDRTYPE    9
9
10 // === IMPORTS ===
11
12 // === TYPES ===
13 typedef struct sKeyValue        tKeyValue;
14 typedef struct sFirewallMod     tFirewallMod;
15 typedef struct sModuleRule      tModuleRule;
16 typedef struct sRule    tRule;
17 typedef struct sChain   tChain;
18
19 // === STRUCTURES ===
20 struct sKeyValue
21 {
22         const char      *Key;
23         const char      *Value;
24 };
25
26 struct sFirewallMod
27 {
28         const char      *Name;
29         
30          int    (*Match)(tModuleRule *Rule, int AddrType,
31                                 const void *Src, const void *Dest,
32                                 Uint8 Type, Uint32 Flags,
33                                 size_t Length, const void *Data);
34         
35         tModuleRule     *(*Create)(tKeyValue *Params);
36 };
37
38 struct sModuleRule
39 {
40         tModuleRule     *Next;
41         
42         tFirewallMod    *Mod;
43         
44         char    Data[];
45 };
46
47 struct sRule
48 {
49         tRule   *Next;
50         
51          int    PacketCount;    // Number of packets seen
52          int    ByteCount;              // Number of bytes seen (IP Payload bytes)
53         
54          int    bInvertSource;  // Boolean NOT flag on source
55         void    *Source;        // Source address bytes
56          int    SourceMask;     // Source address mask bits
57          
58          int    bInvertDest;    // Boolean NOT flag on destination
59         void    *Dest;  // Destination address bytes
60          int    DestMask;       // Destination address mask bits
61         
62         tModuleRule     *Modules;       // Modules loaded for this rule
63         
64         char    Target[];       // Target rule name
65 };
66
67 struct sChain
68 {
69         tChain  *Next;
70         
71         tRule   *FirstRule;
72         tRule   *LastRule;
73         
74         char    Name[];
75 };
76
77 // === PROTOTYPES ===
78  int    IPTables_TestChain(
79         const char *RuleName,
80         const int AddressType,
81         const void *Src, const void *Dest,
82         Uint8 Type, Uint32 Flags,
83         size_t Length, const void *Data
84         );
85
86 // === GLOBALS ===
87 tChain  *gapFirewall_Chains[MAX_ADDRTYPE+1];
88 tChain  gFirewall_DROP = {.Name="DROP"};
89 tChain  gFirewall_ACCEPT = {.Name="ACCEPT"};
90 tChain  gFirewall_RETURN = {.Name="RETURN"};
91
92 // === CODE ===
93 /**
94  * \brief Apply a rule to a packet
95  * \return -1 for no match, -2 for RETURN, eFirewallAction otherwise
96  */
97 int IPTables_DoRule(
98         tRule *Rule, int AddrType,
99         const void *Src, const void *Dest,
100         Uint8 Type, Uint32 Flags,
101         size_t Length, const void *Data)
102 {
103          int    rv;
104         // Check if source doesn't match
105         if( !IPStack_CompareAddress(AddrType, Src, Rule->Source, Rule->SourceMask) == !Rule->bInvertSource )
106                 return -1;
107         // Check if destination doesn't match
108         if( !IPStack_CompareAddress(AddrType, Dest, Rule->Dest, Rule->DestMask) == !Rule->bInvertDest )
109                 return -1;
110         
111         // TODO: Handle modules (UDP/TCP/etc)
112         tModuleRule *modrule;
113         for( modrule = Rule->Modules; modrule; modrule = modrule->Next )
114         {
115                 if( !modrule->Mod->Match )      continue;
116                 rv = modrule->Mod->Match(modrule, AddrType, Src, Dest, Type, Flags, Length, Data);
117                 if(rv == -1)    return -1;      // no match
118                 // TODO: If != 0 maybe, allowing it to ask for a drop?
119         }
120         
121         // Update statistics
122         Rule->PacketCount ++;
123         Rule->ByteCount += Length;
124         
125         return IPTables_TestChain(Rule->Target, AddrType, Src, Dest, Type, Flags, Length, Data);
126 }
127
128 /**
129  * \brief Tests an IPv4 chain on a packet
130  * \return Boolean Disallow (0: Packet Allowed, 1: Drop, 2: Reject, 3: Continue)
131  */
132 int IPTables_TestChain(
133         const char *RuleName,
134         const int AddressType,
135         const void *Src, const void *Dest,
136         Uint8 Type, Uint32 Flags,
137         size_t Length, const void *Data
138         )
139 {
140          int    rv;
141         tChain  *chain;
142         tRule   *rule;
143         
144         if( AddressType >= MAX_ADDRTYPE )       return -1;      // Bad address type
145         
146         // Catch builtin targets
147         if(strcmp(RuleName, "") == 0)   return -1;      // No action
148         if(strcmp(RuleName, "ACCEPT") == 0)     return 0;       // Accept packet
149         if(strcmp(RuleName, "DROP") == 0)       return 1;       // Drop packet
150         if(strcmp(RuleName, "RETURN") == 0)     return -2;      // Return from rule
151         
152         // Find the rule
153         for( chain = gapFirewall_Chains[AddressType]; chain; chain = chain->Next )
154         {
155                 if( strcmp(chain->Name, RuleName) == 0 )
156                         break;
157         }
158         if( !chain )    return -1;      // Bad rule name
159         
160         // Check the rules
161         for( rule = chain->FirstRule; rule; rule = rule->Next )
162         {
163                 rv = IPTables_DoRule(rule, AddressType, Src, Dest, Type, Flags, Length, Data);
164                 if( rv == -1 )
165                         continue ;
166                 if( rv == -2 )  // -2 = Return from a chain/table, pretend no match
167                         return -1;
168                 
169                 return rv;
170         }
171         
172         
173         return 0;       // Accept all for now
174 }

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