You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.9 KiB
106 lines
2.9 KiB
#include <esp_wifi_types.h>
|
|
#include <esp_wifi.h>
|
|
#include <esp_log.h>
|
|
#include <fcntl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/param.h>
|
|
|
|
#include "httpd_utils/captive.h"
|
|
#include "httpd_utils/fd_to_ipv4.h"
|
|
#include "httpd_utils/redirect.h"
|
|
#include <common_utils/utils.h>
|
|
|
|
static const char *TAG="captive";
|
|
|
|
const char * __attribute__((weak))
|
|
httpd_captive_redirect_get_domain(void)
|
|
{
|
|
return "fb_node.captive";
|
|
}
|
|
|
|
esp_err_t __attribute__((weak))
|
|
httpd_captive_redirect_get_url(httpd_req_t *r, char *buf, size_t maxlen)
|
|
{
|
|
buf = append(buf, "http://", &maxlen);
|
|
buf = append(buf, httpd_captive_redirect_get_domain(), &maxlen);
|
|
append(buf, "/", &maxlen);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t httpd_captive_redirect(httpd_req_t *r)
|
|
{
|
|
// must be static to survive being used in the redirect header
|
|
static char s_buf[64];
|
|
|
|
wifi_mode_t mode = 0;
|
|
esp_wifi_get_mode(&mode);
|
|
|
|
// Check if we have an softap interface. No point checking IPs and hostnames if the client can't be on AP.
|
|
if (mode == WIFI_MODE_STA || mode == WIFI_MODE_NULL) {
|
|
goto no_redirect;
|
|
}
|
|
|
|
int fd = httpd_req_to_sockfd(r);
|
|
|
|
tcpip_adapter_ip_info_t apip;
|
|
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &apip);
|
|
|
|
u32_t client_addr;
|
|
if(ESP_OK != fd_to_ipv4(fd, &client_addr)) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
ESP_LOGD(TAG, "[captive] Client addr = 0x%08x, ap addr 0x%08x, ap nmask 0x%08x",
|
|
client_addr,
|
|
apip.ip.addr,
|
|
apip.netmask.addr
|
|
);
|
|
|
|
// Check if client IP looks like from our AP dhcps
|
|
if ((client_addr & apip.netmask.addr) != (apip.ip.addr & apip.netmask.addr)) {
|
|
ESP_LOGD(TAG, "[captive] Client not in AP IP range");
|
|
goto no_redirect;
|
|
}
|
|
|
|
// Get requested hostname from the header
|
|
esp_err_t rv = httpd_req_get_hdr_value_str(r, "Host", s_buf, 64);
|
|
if (rv != ESP_OK) {
|
|
ESP_LOGW(TAG, "[captive] No host in request?");
|
|
goto no_redirect;
|
|
}
|
|
|
|
ESP_LOGD(TAG, "[captive] Candidate for redirect: %s%s", s_buf, r->uri);
|
|
|
|
// Never redirect if host is an IP
|
|
if (strlen(s_buf)>7) {
|
|
bool isIP = 1;
|
|
for (int x = 0; x < strlen(s_buf); x++) {
|
|
if (s_buf[x] != '.' && (s_buf[x] < '0' || s_buf[x] > '9')) {
|
|
isIP = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isIP) {
|
|
ESP_LOGD(TAG, "[captive] Access via IP, no redirect needed");
|
|
goto no_redirect;
|
|
}
|
|
}
|
|
|
|
// Redirect if host differs
|
|
// - this can be e.g. connectivitycheck.gstatic.com or the equivalent for ios
|
|
|
|
if (0 != strcmp(s_buf, httpd_captive_redirect_get_domain())) {
|
|
ESP_LOGD(TAG, "[captive] Host differs, redirecting...");
|
|
|
|
httpd_captive_redirect_get_url(r, s_buf, 64);
|
|
return httpd_redirect_to(r, s_buf);
|
|
} else {
|
|
ESP_LOGD(TAG, "[captive] Host is OK");
|
|
goto no_redirect;
|
|
}
|
|
|
|
no_redirect:
|
|
return ESP_ERR_NOT_FOUND;
|
|
}
|
|
|