ESP32/ESP8266 Firewall 1.0.0
a software firewall for ESP23 or ESP8266
Firewall.cpp
1#include "Firewall.hpp"
2
3namespace fw
4{
5 Firewall::Firewall()
6 {
7 this->amount_of_rules = retrieve_amount_of_rules();
8 for (uint8_t i = 1; i <= this->amount_of_rules; i++)
9 {
10 firewall_rule_t *rule_ptr = retrieve_firewall_rule(i);
11 this->add_rule_to_firewall(rule_ptr, false);
12 }
13 }
14
15 Firewall::~Firewall()
16 {
17 }
18
19 firewall_rule_t *Firewall::get_rule_head()
20 {
21 return this->rule_head;
22 }
23
24 void Firewall::add_rule_to_firewall(firewall_rule_t *rule_ptr, const bool save_in_eeprom)
25 {
26 store_amount_of_rules(this->amount_of_rules);
27 if (save_in_eeprom)
28 Storage::store_firewall_rule(rule_ptr);
29 if (this->rule_head == NULL)
30 {
31 this->rule_head = rule_ptr;
32 rule_ptr->next = NULL;
33 return;
34 }
35 firewall_rule_t *current_rule;
36 current_rule = this->rule_head;
37 while (current_rule->next != NULL)
38 current_rule = current_rule->next;
39 current_rule->next = rule_ptr;
40 rule_ptr->next = NULL;
41 }
42
43 firewall_rule_t *Firewall::add_rule_to_firewall(String *args)
44 {
45 firewall_rule_t *rule_ptr = (firewall_rule_t *)malloc(sizeof(firewall_rule_t));
46 rule_ptr->key = ++this->amount_of_rules;
47
48 strncpy(rule_ptr->ip, args[IP].c_str(), sizeof(rule_ptr->ip));
49 rule_ptr->port_from = args[PORT_FROM].toInt();
50 rule_ptr->port_to = args[PORT_TO].toInt();
51 rule_ptr->protocol = string_to_protocol(args[PROTOCOL]);
52 rule_ptr->target = string_to_target(args[TARGET]);
53
54 add_rule_to_firewall(rule_ptr);
55 return rule_ptr;
56 }
57
58 firewall_rule_t *Firewall::update_rule_of_firewall(String *args, const uint8_t key)
59 {
60 firewall_rule_t *rule_ptr = get_rule_from_firewall(key);
61 if (rule_ptr == NULL)
62 return rule_ptr;
63 strncpy(rule_ptr->ip, args[IP].c_str(), sizeof(rule_ptr->ip));
64 rule_ptr->port_from = args[PORT_FROM].toInt();
65 rule_ptr->port_to = args[PORT_TO].toInt();
66 rule_ptr->protocol = string_to_protocol(args[PROTOCOL]);
67 rule_ptr->target = string_to_target(args[TARGET]);
68
69 Storage::store_firewall_rule(rule_ptr);
70 return rule_ptr;
71 }
72
73 firewall_rule_t *Firewall::get_rule_from_firewall(const uint8_t key)
74 {
75 firewall_rule_t *rule_ptr = this->rule_head;
76 if (this->rule_head == NULL)
77 return NULL;
78 while (rule_ptr->key != key)
79 {
80 if (rule_ptr->next == NULL)
81 return NULL;
82 else
83 rule_ptr = rule_ptr->next;
84 }
85 return rule_ptr;
86 }
87
88 ok_t Firewall::delete_rule_from_firewall(const uint8_t key)
89 {
90 if (this->rule_head == NULL)
91 return NO_ACTION;
92 firewall_rule_t *current_rule = this->rule_head;
93 firewall_rule_t *previous_rule = NULL;
94 firewall_rule_t *temp = NULL;
95 while (current_rule->key != key)
96 {
97 if (current_rule->next == NULL)
98 return NO_ACTION;
99 else
100 {
101 previous_rule = current_rule;
102 current_rule = current_rule->next;
103 }
104 }
105 if (current_rule == this->rule_head)
106 {
107 this->rule_head = rule_head->next;
108 temp = this->rule_head;
109 }
110 else
111 {
112 previous_rule->next = current_rule->next;
113 temp = previous_rule->next;
114 }
115 while (temp != NULL)
116 {
117 temp->key--;
118 temp = temp->next;
119 }
120 free(current_rule);
121 this->amount_of_rules--;
122 Storage::store_amount_of_rules(this->amount_of_rules);
123 if (this->amount_of_rules != 0)
124 Storage::store_all_firewall_rules(rule_head);
125 return SUCCESS;
126 }
127
128 my_packet_t *Firewall::get_packet_information(struct pbuf *pbuf)
129 {
130 my_packet_t *packet = (my_packet_t *)malloc(sizeof(my_packet_t));
131 const struct ip_hdr *iphdr = (struct ip_hdr *)pbuf->payload;
132 u16_t iphdr_hlen = IPH_HL_BYTES(iphdr);
133
134 packet->protocol = (firewall_protocol_t)IPH_PROTO(iphdr);
135 sprintf(packet->ip, "%d.%d.%d.%d", ip4_addr1_16_val(iphdr->src), ip4_addr2_16_val(iphdr->src), ip4_addr3_16_val(iphdr->src), ip4_addr4_16_val(iphdr->src));
136
137 if (packet->protocol == PROTOCOL_UDP)
138 {
139 const struct udp_hdr *udphdr = (const struct udp_hdr *)((const u8_t *)iphdr + iphdr_hlen);
140 packet->port = lwip_ntohs(udphdr->dest);
141 }
142 else if (packet->protocol == PROTOCOL_TCP)
143 {
144 const struct tcp_hdr *tcphdr = (const struct tcp_hdr *)((const u8_t *)iphdr + iphdr_hlen);
145 packet->port = lwip_ntohs(tcphdr->dest);
146 }
147
148 return packet;
149 }
150
151 bool Firewall::rule_allows_packet(firewall_rule_t *rule_ptr, my_packet_t *packet)
152 {
153 if (strncmp(rule_ptr->ip, packet->ip, IPV4ADDRESS_LENGTH) == 0)
154 {
155 if ((rule_ptr->protocol == PROTOCOL_ALL || packet->protocol == rule_ptr->protocol) &&
156 is_in_range(packet->port, rule_ptr->port_from, rule_ptr->port_to) &&
157 rule_ptr->target == TARGET_ACCEPT)
158 {
159 free(packet);
160 return true;
161 }
162 }
163 return false;
164 }
165
166 bool Firewall::is_packet_allowed(struct pbuf *pbuf)
167 {
168 // no rules -> no action
169 if (this->amount_of_rules == 0)
170 return true;
171
172 my_packet_t *packet = get_packet_information(pbuf);
173 firewall_rule_t *rule_ptr = this->rule_head;
174 while (rule_ptr != NULL)
175 {
176 if (rule_allows_packet(rule_ptr, packet))
177 return true;
178 rule_ptr = rule_ptr->next;
179 }
180 free(packet);
181 return false;
182 }
183}