upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/main/firewall.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/firewall.c')
-rw-r--r--main/firewall.c93
1 files changed, 83 insertions, 10 deletions
diff --git a/main/firewall.c b/main/firewall.c
index 8087b54..f349ab1 100644
--- a/main/firewall.c
+++ b/main/firewall.c
@@ -1,7 +1,11 @@
1#include "firewall.h" 1#include "firewall.h"
2#include "dns_server.h" 2#include "dns_server.h"
3#include "esp_log.h" 3#include "esp_log.h"
4#include "esp_wifi.h"
5#include "esp_wifi_ap_get_sta_list.h"
4#include "lwip/lwip_napt.h" 6#include "lwip/lwip_napt.h"
7#include "lwip/etharp.h"
8#include "lwip/netif.h"
5#include <string.h> 9#include <string.h>
6 10
7#define MAX_CLIENTS 10 11#define MAX_CLIENTS 10
@@ -12,11 +16,51 @@ static bool s_nat_enabled = false;
12 16
13typedef struct { 17typedef struct {
14 uint32_t ip; 18 uint32_t ip;
19 char mac[FW_MAX_MAC_LEN];
15} fw_client_t; 20} fw_client_t;
16 21
17static fw_client_t s_clients[MAX_CLIENTS]; 22static fw_client_t s_clients[MAX_CLIENTS];
18static int s_client_count = 0; 23static int s_client_count = 0;
19 24
25static struct netif *get_ap_netif(void)
26{
27 return netif_get_by_index(NETIF_NO_INDEX);
28}
29
30esp_err_t firewall_get_mac_for_ip(uint32_t client_ip, char *mac_out, size_t mac_out_size)
31{
32 wifi_sta_list_t sta_list;
33 if (esp_wifi_ap_get_sta_list(&sta_list) == ESP_OK) {
34 wifi_sta_mac_ip_list_t ip_mac_list;
35 if (esp_wifi_ap_get_sta_list_with_ip(&sta_list, &ip_mac_list) == ESP_OK) {
36 for (int i = 0; i < ip_mac_list.num; i++) {
37 if (ip_mac_list.sta[i].ip.addr == client_ip) {
38 snprintf(mac_out, mac_out_size, "%02x:%02x:%02x:%02x:%02x:%02x",
39 ip_mac_list.sta[i].mac[0], ip_mac_list.sta[i].mac[1],
40 ip_mac_list.sta[i].mac[2], ip_mac_list.sta[i].mac[3],
41 ip_mac_list.sta[i].mac[4], ip_mac_list.sta[i].mac[5]);
42 return ESP_OK;
43 }
44 }
45 }
46 }
47
48 ip4_addr_t *entry_ip = NULL;
49 struct netif *entry_netif = NULL;
50 struct eth_addr *entry_eth = NULL;
51 ssize_t i = 0;
52 while (etharp_get_entry(i, &entry_ip, &entry_netif, &entry_eth) == ERR_OK) {
53 if (entry_ip && entry_ip->addr == client_ip && entry_eth) {
54 snprintf(mac_out, mac_out_size, "%02x:%02x:%02x:%02x:%02x:%02x",
55 entry_eth->addr[0], entry_eth->addr[1], entry_eth->addr[2],
56 entry_eth->addr[3], entry_eth->addr[4], entry_eth->addr[5]);
57 return ESP_OK;
58 }
59 i++;
60 }
61 return ESP_FAIL;
62}
63
20esp_err_t firewall_init(esp_ip4_addr_t ap_ip) 64esp_err_t firewall_init(esp_ip4_addr_t ap_ip)
21{ 65{
22 s_ap_ip = ap_ip; 66 s_ap_ip = ap_ip;
@@ -56,34 +100,61 @@ void firewall_disable_nat(void)
56 ESP_LOGI(TAG, "NAT disabled"); 100 ESP_LOGI(TAG, "NAT disabled");
57} 101}
58 102
59void firewall_grant_access(uint32_t client_ip) 103static fw_client_t *find_client_by_ip(uint32_t client_ip)
60{ 104{
61 for (int i = 0; i < s_client_count; i++) { 105 for (int i = 0; i < s_client_count; i++) {
62 if (s_clients[i].ip == client_ip) return; 106 if (s_clients[i].ip == client_ip) return &s_clients[i];
107 }
108 return NULL;
109}
110
111static fw_client_t *find_client_by_mac(const char *mac)
112{
113 for (int i = 0; i < s_client_count; i++) {
114 if (s_clients[i].mac[0] != '\0' && strcmp(s_clients[i].mac, mac) == 0) {
115 return &s_clients[i];
116 }
117 }
118 return NULL;
119}
120
121void firewall_grant_access(uint32_t client_ip)
122{
123 fw_client_t *existing = find_client_by_ip(client_ip);
124 if (existing) {
125 existing->ip = client_ip;
126 return;
63 } 127 }
64 if (s_client_count >= MAX_CLIENTS) { 128 if (s_client_count >= MAX_CLIENTS) {
65 ESP_LOGW(TAG, "Max clients reached, cannot grant access"); 129 ESP_LOGW(TAG, "Max clients reached, cannot grant access");
66 return; 130 return;
67 } 131 }
68 s_clients[s_client_count].ip = client_ip; 132
133 fw_client_t *client = &s_clients[s_client_count];
134 client->ip = client_ip;
135 client->mac[0] = '\0';
136 firewall_get_mac_for_ip(client_ip, client->mac, sizeof(client->mac));
69 s_client_count++; 137 s_client_count++;
138
70 dns_server_set_client_authenticated(client_ip, true); 139 dns_server_set_client_authenticated(client_ip, true);
71 update_nat(); 140 update_nat();
72 141
73 esp_ip4_addr_t ip_addr = { .addr = client_ip }; 142 esp_ip4_addr_t ip_addr = { .addr = client_ip };
74 ESP_LOGI(TAG, "Access granted to " IPSTR, IP2STR(&ip_addr)); 143 ESP_LOGI(TAG, "Access granted to " IPSTR " mac=%s", IP2STR(&ip_addr),
144 client->mac[0] ? client->mac : "unknown");
75} 145}
76 146
77void firewall_revoke_access(uint32_t client_ip) 147void firewall_revoke_access(uint32_t client_ip)
78{ 148{
79 for (int i = 0; i < s_client_count; i++) { 149 for (int i = 0; i < s_client_count; i++) {
80 if (s_clients[i].ip == client_ip) { 150 if (s_clients[i].ip == client_ip) {
151 esp_ip4_addr_t ip_addr = { .addr = client_ip };
152 ESP_LOGI(TAG, "Access revoked for " IPSTR " mac=%s", IP2STR(&ip_addr),
153 s_clients[i].mac[0] ? s_clients[i].mac : "unknown");
81 s_clients[i] = s_clients[s_client_count - 1]; 154 s_clients[i] = s_clients[s_client_count - 1];
82 s_client_count--; 155 s_client_count--;
83 dns_server_set_client_authenticated(client_ip, false); 156 dns_server_set_client_authenticated(client_ip, false);
84 update_nat(); 157 update_nat();
85 esp_ip4_addr_t ip_addr = { .addr = client_ip };
86 ESP_LOGI(TAG, "Access revoked for " IPSTR, IP2STR(&ip_addr));
87 return; 158 return;
88 } 159 }
89 } 160 }
@@ -101,10 +172,12 @@ void firewall_revoke_all(void)
101 172
102bool firewall_is_client_allowed(uint32_t client_ip) 173bool firewall_is_client_allowed(uint32_t client_ip)
103{ 174{
104 for (int i = 0; i < s_client_count; i++) { 175 return find_client_by_ip(client_ip) != NULL;
105 if (s_clients[i].ip == client_ip) return true; 176}
106 } 177
107 return false; 178bool firewall_is_mac_allowed(const char *mac)
179{
180 return find_client_by_mac(mac) != NULL;
108} 181}
109 182
110int firewall_client_count(void) 183int firewall_client_count(void)