Kernel/armv7 - Bugfixes
[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 != 0)     return rv;      // No match / action
118         }
119         
120         // Update statistics
121         Rule->PacketCount ++;
122         Rule->ByteCount += Length;
123         
124         return IPTables_TestChain(Rule->Target, AddrType, Src, Dest, Type, Flags, Length, Data);
125 }
126
127 /**
128  * \brief Tests an IPv4 chain on a packet
129  * \return Boolean Disallow (0: Packet Allowed, 1: Drop, 2: Reject, 3: Continue, -1 no match)
130  */
131 int IPTables_TestChain(
132         const char *RuleName,
133         const int AddressType,
134         const void *Src, const void *Dest,
135         Uint8 Type, Uint32 Flags,
136         size_t Length, const void *Data
137         )
138 {
139          int    rv;
140         tChain  *chain;
141         tRule   *rule;
142         
143         if( AddressType >= MAX_ADDRTYPE )       return -1;      // Bad address type
144         
145         // Catch builtin targets
146         if(strcmp(RuleName, "") == 0)   return -1;      // No action
147         if(strcmp(RuleName, "ACCEPT") == 0)     return 0;       // Accept packet
148         if(strcmp(RuleName, "DROP") == 0)       return 1;       // Drop packet
149         if(strcmp(RuleName, "RETURN") == 0)     return -2;      // Return from rule
150         
151         // Find the rule
152         for( chain = gapFirewall_Chains[AddressType]; chain; chain = chain->Next )
153         {
154                 if( strcmp(chain->Name, RuleName) == 0 )
155                         break;
156         }
157         if( !chain )    return -1;      // Bad rule name
158         
159         // Check the rules
160         for( rule = chain->FirstRule; rule; rule = rule->Next )
161         {
162                 rv = IPTables_DoRule(rule, AddressType, Src, Dest, Type, Flags, Length, Data);
163                 if( rv == -1 )
164                         continue ;
165                 if( rv == -2 )  // -2 = Return from a chain/table, pretend no match
166                         return -1;
167                 
168                 return rv;
169         }
170         
171         
172         return 0;       // Accept all for now
173 }

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