mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-30 18:07:52 +00:00
udhcpinject: Support multiple upstream
Support multiple ssid <-> upstream bindings Fixes: WIFI-15125 Signed-off-by: Kumiko18 <alex18_huang@accton.com>
This commit is contained in:
@@ -12,7 +12,7 @@ define Package/udhcpinject
|
|||||||
SECTION:=net
|
SECTION:=net
|
||||||
CATEGORY:=Network
|
CATEGORY:=Network
|
||||||
TITLE:=An agent to inject DHCP option
|
TITLE:=An agent to inject DHCP option
|
||||||
DEPENDS:=+libpcap +kmod-ifb +tc
|
DEPENDS:=+libpcap +kmod-ifb +tc +libuci
|
||||||
MAINTAINER:=kmk <alex18_huang@accton.com>
|
MAINTAINER:=kmk <alex18_huang@accton.com>
|
||||||
endef
|
endef
|
||||||
|
|
||||||
@@ -41,4 +41,4 @@ define Package/udhcpinject/install
|
|||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call BuildPackage,udhcpinject))
|
$(eval $(call BuildPackage,udhcpinject))
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
# config device 'uplink'
|
#config network 'wan0'
|
||||||
# list port 'eth0'
|
# option upstream 'up0v0'
|
||||||
#
|
# list ssid5G '18-KMK-YAYA'
|
||||||
# config ssids 'ssids'
|
# list ssid5G '18-KMK-AKIHO'
|
||||||
# list ssid 'EAP101-ERICHI'
|
# list ssid2G '18-KMK-YAYA'
|
||||||
# list ssid 'EAP101-AKIHO'
|
# list ssid2G '18-KMK-AKIHO'
|
||||||
# list ssid 'EAP101-DAMAYU'
|
# option count '4'
|
||||||
#
|
|
||||||
# config dhcpinject 'dhcpinject'
|
#config network 'wan284'
|
||||||
# option iface_count '6'
|
# option upstream 'up1v284'
|
||||||
|
# list ssid5G '18-KMK-SARAN'
|
||||||
|
# list ssid2G '18-KMK-SARAN'
|
||||||
|
# option count '2'
|
||||||
|
|
||||||
|
#config network 'wan283'
|
||||||
|
# option upstream 'up2v283'
|
||||||
|
# list ssid5G '18-KMK-ERICHI'
|
||||||
|
# list ssid2G '18-KMK-ERICHI'
|
||||||
|
# option count '2'
|
||||||
|
|||||||
@@ -9,55 +9,18 @@ SERVICE_NAME="dhcpinject"
|
|||||||
PROG=/usr/bin/udhcpinject
|
PROG=/usr/bin/udhcpinject
|
||||||
|
|
||||||
start_service() {
|
start_service() {
|
||||||
local ssids=""
|
# check if config file has contents by executing `uci get dhcpinject.@network[0]`
|
||||||
local ports=""
|
if [ -z "$(uci get dhcpinject.@network[0] 2>/dev/null)" ]; then
|
||||||
local ifaces=""
|
echo "No upstreams specified, exiting $SERVICE_NAME"
|
||||||
|
return 0
|
||||||
# Function to process each ssid
|
|
||||||
append_ssid() {
|
|
||||||
local value="$1"
|
|
||||||
if [ -n "$ssids" ]; then
|
|
||||||
ssids="$ssids,$value"
|
|
||||||
else
|
|
||||||
ssids="$value"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
append_port() {
|
|
||||||
local value="$1"
|
|
||||||
if [ -n "$ports" ]; then
|
|
||||||
ports="$ports,$value"
|
|
||||||
else
|
|
||||||
ports="$value"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Load the dhcpinject config
|
|
||||||
config_load dhcpinject
|
|
||||||
|
|
||||||
# Get the list of SSIDs
|
|
||||||
config_list_foreach ssids ssid append_ssid
|
|
||||||
|
|
||||||
# Get the list of ports
|
|
||||||
config_list_foreach uplink port append_port
|
|
||||||
|
|
||||||
# Get the iface_count
|
|
||||||
config_get ifaces dhcpinject iface_count
|
|
||||||
|
|
||||||
# Fallback to eth0 if no ports are specified
|
|
||||||
if [ -z "$ports" ]; then
|
|
||||||
ports="eth0"
|
|
||||||
fi
|
fi
|
||||||
|
# Wait for wifi to be up
|
||||||
# Optional: Log or echo for debugging
|
ubus -t 90 wait_for network.wireless
|
||||||
logger -t dhcp_inject "Generated SSIDs=$ssids, Uplink=$ports, IFACEs=$ifaces"
|
|
||||||
|
|
||||||
procd_open_instance "$SERVICE_NAME"
|
procd_open_instance "$SERVICE_NAME"
|
||||||
procd_set_param command $PROG
|
procd_set_param command $PROG
|
||||||
procd_set_param env SSIDs="$ssids" PORTs="$ports" IFACEs="$ifaces"
|
|
||||||
procd_set_param respawn 3600 10 10
|
procd_set_param respawn 3600 10 10
|
||||||
procd_set_param file /etc/config/dhcpinject
|
procd_set_param file /etc/config/dhcpinject
|
||||||
procd_set_param reload_signal SIGHUP
|
|
||||||
procd_close_instance
|
procd_close_instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ obj-y := udhcpinject.o
|
|||||||
all: udhcpinject
|
all: udhcpinject
|
||||||
|
|
||||||
udhcpinject: $(obj-y)
|
udhcpinject: $(obj-y)
|
||||||
$(CC) $(LDFLAGS) -lpcap -o $@ $(obj-y)
|
$(CC) $(LDFLAGS) -lpcap -luci -o $@ $(obj-y)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) $(TARGET_CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) $(TARGET_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o udhcpinject
|
rm -f *.o udhcpinject
|
||||||
|
|||||||
@@ -6,286 +6,81 @@
|
|||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <uci.h>
|
||||||
|
|
||||||
#include "udhcpinject.h"
|
#include "udhcpinject.h"
|
||||||
|
|
||||||
#define MAX_INTERFACES 48
|
|
||||||
#define MAX_PORTS 8
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
struct iface_info *iface_map = NULL;
|
|
||||||
static struct port_info *ports = NULL;
|
|
||||||
int iface_count = 0;
|
|
||||||
int port_count = 0;
|
|
||||||
int total_iface = 0;
|
|
||||||
static pcap_t *handle = NULL;
|
|
||||||
static char *provided_ssids = NULL;
|
|
||||||
static char *provided_ports = NULL;
|
|
||||||
|
|
||||||
// Function to cleanup tc rules
|
|
||||||
void cleanup_tc() {
|
|
||||||
char cmd[1024];
|
|
||||||
for (int i = 0; i < iface_count; i++) {
|
|
||||||
snprintf(cmd, sizeof(cmd), "tc filter del dev %s ingress pref 32 2>/dev/null",
|
|
||||||
iface_map[i].iface);
|
|
||||||
system(cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup function
|
// Cleanup function
|
||||||
void cleanup() {
|
void cleanup()
|
||||||
|
{
|
||||||
syslog(LOG_INFO, "Cleaning up resources...\n");
|
syslog(LOG_INFO, "Cleaning up resources...\n");
|
||||||
cleanup_tc();
|
|
||||||
|
|
||||||
if (handle) {
|
if (handle)
|
||||||
|
{
|
||||||
pcap_close(handle);
|
pcap_close(handle);
|
||||||
handle = NULL;
|
handle = NULL;
|
||||||
}
|
}
|
||||||
if (ports) {
|
|
||||||
for (int i = 0; i < port_count; i++) {
|
if (iface_map)
|
||||||
if (ports[i].sock >= 0) {
|
{
|
||||||
close(ports[i].sock);
|
char cmd[1024];
|
||||||
}
|
for (int i = 0; i < iface_map_size; i++)
|
||||||
|
{
|
||||||
|
snprintf(cmd, sizeof(cmd), "tc filter del dev %s ingress pref 32 2>/dev/null",
|
||||||
|
iface_map[i].iface);
|
||||||
|
system(cmd);
|
||||||
}
|
}
|
||||||
free(ports);
|
|
||||||
ports = NULL;
|
|
||||||
port_count = 0;
|
|
||||||
}
|
|
||||||
if (iface_map) {
|
|
||||||
free(iface_map);
|
free(iface_map);
|
||||||
iface_map = NULL;
|
|
||||||
iface_count = 0;
|
|
||||||
}
|
}
|
||||||
if (provided_ssids) {
|
|
||||||
free(provided_ssids);
|
if (port_map)
|
||||||
provided_ssids = NULL;
|
{
|
||||||
}
|
for (int i = 0; i < port_map_size; i++)
|
||||||
if (provided_ports) {
|
{
|
||||||
free(provided_ports);
|
close(port_map[i].sock);
|
||||||
provided_ports = NULL;
|
}
|
||||||
|
free(port_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_INFO, "Cleanup complete.\n");
|
syslog(LOG_INFO, "Cleanup complete.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to parse SSIDs and populate iface_map
|
int setup_tc()
|
||||||
int parse_ssids(const char *ssids) {
|
{
|
||||||
if (iface_map) {
|
char cmd[512];
|
||||||
free(iface_map);
|
|
||||||
iface_map = NULL;
|
|
||||||
iface_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a set of provided SSIDs for efficient lookup
|
|
||||||
char ssids_copy[256];
|
|
||||||
strncpy(ssids_copy, ssids, sizeof(ssids_copy) - 1);
|
|
||||||
ssids_copy[sizeof(ssids_copy) - 1] = '\0';
|
|
||||||
|
|
||||||
// Count number of SSIDs for allocation
|
|
||||||
int ssid_count = 1; // Start at 1 for first SSID
|
|
||||||
for (int i = 0; ssids_copy[i]; i++) {
|
|
||||||
if (ssids_copy[i] == ',')
|
|
||||||
ssid_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char **ssid_set = malloc(ssid_count * sizeof(char *));
|
|
||||||
if (!ssid_set) {
|
|
||||||
syslog(LOG_ERR, "Failed to allocate memory for SSID set\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ssid_idx = 0;
|
|
||||||
char *token = strtok(ssids_copy, ",");
|
|
||||||
while (token) {
|
|
||||||
ssid_set[ssid_idx++] = token;
|
|
||||||
token = strtok(NULL, ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute iwinfo command and capture output
|
|
||||||
FILE *pipe = popen("iwinfo | grep wlan -A1 | grep -v \"^--\" | tr -d '\"' "
|
|
||||||
"| awk '/wlan/ {name=$1; essid=$3} /Access Point/ "
|
|
||||||
"{print name \"=\" essid \",\" $3}' | tr -d ':'",
|
|
||||||
"r");
|
|
||||||
if (!pipe) {
|
|
||||||
syslog(LOG_ERR, "Failed to execute iwinfo command\n");
|
|
||||||
free(ssid_set);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char line[256];
|
|
||||||
while (fgets(line, sizeof(line), pipe) != NULL) {
|
|
||||||
// Remove trailing newline
|
|
||||||
line[strcspn(line, "\n")] = 0;
|
|
||||||
|
|
||||||
// Parse line format: wlanX=SSID,BSSID
|
|
||||||
char *iface = strtok(line, "=");
|
|
||||||
char *rest = strtok(NULL, "=");
|
|
||||||
if (!iface || !rest)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char *essid = strtok(rest, ",");
|
|
||||||
char *bssid = strtok(NULL, ",");
|
|
||||||
if (!essid || !bssid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check if this SSID is in our provided set
|
|
||||||
int match = 0;
|
|
||||||
for (int i = 0; i < ssid_idx; i++) {
|
|
||||||
if (strcmp(essid, ssid_set[i]) == 0) {
|
|
||||||
match = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!match)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Add matching interface to iface_map
|
|
||||||
if (iface_count >= MAX_INTERFACES) {
|
|
||||||
syslog(LOG_ERR, "Too many matching interfaces, max is %d\n",
|
|
||||||
MAX_INTERFACES);
|
|
||||||
pclose(pipe);
|
|
||||||
free(ssid_set);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
iface_map =
|
|
||||||
realloc(iface_map, (iface_count + 1) * sizeof(struct iface_info));
|
|
||||||
if (!iface_map) {
|
|
||||||
syslog(LOG_ERR, "Failed to reallocate iface_map\n");
|
|
||||||
pclose(pipe);
|
|
||||||
free(ssid_set);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iface_info *info = &iface_map[iface_count];
|
|
||||||
info->serial = iface_count + 1;
|
|
||||||
|
|
||||||
strncpy(info->iface, iface, LEN_IFACE);
|
|
||||||
info->iface[LEN_IFACE] = '\0';
|
|
||||||
|
|
||||||
strncpy(info->essid, essid, LEN_ESSID);
|
|
||||||
info->essid[LEN_ESSID] = '\0';
|
|
||||||
|
|
||||||
strncpy(info->bssid, bssid, LEN_BSSID);
|
|
||||||
info->bssid[LEN_BSSID] = '\0';
|
|
||||||
|
|
||||||
iface_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pipe_status = pclose(pipe);
|
|
||||||
if (pipe_status == -1) {
|
|
||||||
syslog(LOG_ERR, "Error closing iwinfo pipe: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ssid_set);
|
|
||||||
|
|
||||||
if (iface_count == 0) {
|
|
||||||
syslog(LOG_ERR, "No matching interfaces found for provided SSIDs\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iface_count != total_iface) {
|
|
||||||
syslog(LOG_ERR, "Expect %d but only %d interfaces were found.\n", total_iface, iface_count);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
syslog(LOG_INFO, "Found %d matching interfaces\n", iface_count);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_ports(const char *port_list) {
|
|
||||||
if (ports) {
|
|
||||||
for (int i = 0; i < port_count; i++) {
|
|
||||||
if (ports[i].sock >= 0) {
|
|
||||||
close(ports[i].sock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ports);
|
|
||||||
ports = NULL;
|
|
||||||
port_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char ports_copy[256];
|
|
||||||
strncpy(ports_copy, port_list, sizeof(ports_copy) - 1);
|
|
||||||
ports_copy[sizeof(ports_copy) - 1] = '\0';
|
|
||||||
|
|
||||||
port_count = 1;
|
|
||||||
for (int i = 0; ports_copy[i]; i++) {
|
|
||||||
if (ports_copy[i] == ',') {
|
|
||||||
port_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port_count > MAX_PORTS) {
|
|
||||||
syslog(LOG_ERR, "Too many ports specified, maximum is %d\n", MAX_PORTS);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ports = calloc(port_count, sizeof(struct port_info));
|
|
||||||
if (!ports) {
|
|
||||||
syslog(LOG_ERR, "Failed to allocate memory for ports\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *token = strtok(ports_copy, ",");
|
|
||||||
int idx = 0;
|
|
||||||
while (token && idx < port_count) {
|
|
||||||
strncpy(ports[idx].name, token, LEN_IFACE);
|
|
||||||
ports[idx].name[LEN_IFACE] = '\0';
|
|
||||||
|
|
||||||
ports[idx].sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
|
||||||
if (ports[idx].sock < 0) {
|
|
||||||
syslog(LOG_ERR, "Socket creation failed for %s: %s\n",
|
|
||||||
ports[idx].name, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ports[idx].ifindex = if_nametoindex(ports[idx].name);
|
|
||||||
if (ports[idx].ifindex == 0) {
|
|
||||||
syslog(LOG_ERR, "Failed to get interface index for %s: %s\n",
|
|
||||||
ports[idx].name, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
token = strtok(NULL, ",");
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
syslog(LOG_INFO, "Configured %d ports for forwarding\n", port_count);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int setup_tc() {
|
|
||||||
char cmd[1024];
|
|
||||||
|
|
||||||
|
// check if ifb-inject exists, if not create it
|
||||||
snprintf(cmd, sizeof(cmd), "ip link show ifb-inject >/dev/null 2>&1");
|
snprintf(cmd, sizeof(cmd), "ip link show ifb-inject >/dev/null 2>&1");
|
||||||
if (system(cmd) != 0) {
|
if (system(cmd) != 0)
|
||||||
|
{
|
||||||
snprintf(cmd, sizeof(cmd),
|
snprintf(cmd, sizeof(cmd),
|
||||||
"ip link add name ifb-inject type ifb && ip link set "
|
"ip link add name ifb-inject type ifb && ip link set "
|
||||||
"ifb-inject up");
|
"ifb-inject up");
|
||||||
if (system(cmd) != 0) {
|
if (system(cmd) != 0)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Failed to setup ifb-inject\n");
|
syslog(LOG_ERR, "Failed to setup ifb-inject\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < iface_count; i++) {
|
for (int i = 0; i < iface_map_size; i++)
|
||||||
snprintf(cmd, sizeof(cmd), "tc qdisc add dev %s ingress 2>/dev/null 1>2",
|
{
|
||||||
iface_map[i].iface);
|
snprintf(cmd, sizeof(cmd), "tc qdisc add dev %s ingress 2>/dev/null 1>2",
|
||||||
|
iface_map[i].iface);
|
||||||
int result = system(cmd);
|
int result = system(cmd);
|
||||||
if (result == 2) {
|
if (result == 2)
|
||||||
|
{
|
||||||
syslog(LOG_INFO, "Ingress qdisc already exists for %s\n", iface_map[i].iface);
|
syslog(LOG_INFO, "Ingress qdisc already exists for %s\n", iface_map[i].iface);
|
||||||
}
|
}
|
||||||
else if (result == 1) {
|
else if (result == 1)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Failed to add qdisc for %s\n", iface_map[i].iface);
|
syslog(LOG_ERR, "Failed to add qdisc for %s\n", iface_map[i].iface);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -300,7 +95,8 @@ int setup_tc() {
|
|||||||
"action mirred egress mirror dev ifb-inject pipe "
|
"action mirred egress mirror dev ifb-inject pipe "
|
||||||
"action drop",
|
"action drop",
|
||||||
iface_map[i].iface, iface_map[i].serial);
|
iface_map[i].iface, iface_map[i].serial);
|
||||||
if (system(cmd) != 0) {
|
if (system(cmd) != 0)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Failed to setup tc for %s\n", iface_map[i].iface);
|
syslog(LOG_ERR, "Failed to setup tc for %s\n", iface_map[i].iface);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -308,82 +104,172 @@ int setup_tc() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal handler
|
int parse_iwinfo_by_essid(struct iface_info *iface)
|
||||||
void signal_handler(int sig) {
|
{
|
||||||
if (sig == SIGTERM) {
|
char cmd[256];
|
||||||
syslog(LOG_INFO, "Received SIGTERM, cleaning up...\n");
|
FILE *fp;
|
||||||
cleanup();
|
char output[128];
|
||||||
exit(0);
|
char *line;
|
||||||
} else if (sig == SIGHUP) {
|
|
||||||
syslog(LOG_INFO, "Received reload signal, reconfiguring...\n");
|
snprintf(cmd, sizeof(cmd), IWINFO_CMD, iface->essid, iface->frequency);
|
||||||
// Clean up existing resources
|
|
||||||
cleanup_tc();
|
fp = popen(cmd, "r");
|
||||||
|
if (fp == NULL)
|
||||||
// Free old SSIDs and get new ones
|
{
|
||||||
if (provided_ssids) {
|
syslog(LOG_ERR, "Failed to execute command: %s\n", cmd);
|
||||||
free(provided_ssids);
|
return 1;
|
||||||
}
|
}
|
||||||
provided_ssids = getenv("SSIDs");
|
|
||||||
if (!provided_ssids) {
|
// Read the first line (interface name)
|
||||||
syslog(LOG_ERR, "No SSIDs provided on reload\n");
|
line = fgets(output, sizeof(output), fp);
|
||||||
return;
|
if (line)
|
||||||
}
|
{
|
||||||
|
output[strcspn(output, "\n")] = '\0'; // Remove trailing newline
|
||||||
// Reload SSIDs
|
snprintf(iface->iface, LEN_IFACE + 1, output);
|
||||||
if (parse_ssids(provided_ssids) != 0) {
|
}
|
||||||
syslog(LOG_ERR, "Failed to reload SSIDs configuration\n");
|
else
|
||||||
return;
|
{
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
// Free old ports and get new ones
|
|
||||||
if (provided_ports) {
|
// Read the second line (BSSID)
|
||||||
free(provided_ports);
|
line = fgets(output, sizeof(output), fp);
|
||||||
}
|
if (line)
|
||||||
provided_ports = getenv("PORTs");
|
{
|
||||||
if (!provided_ports) {
|
output[strcspn(output, "\n")] = '\0'; // Remove trailing newline
|
||||||
syslog(LOG_ERR, "No PORTs provided on reload\n");
|
snprintf(iface->bssid, LEN_BSSID + 1, output);
|
||||||
return;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
// Close existing sockets and reopen with new config
|
return 1;
|
||||||
if (ports) {
|
}
|
||||||
for (int i = 0; i < port_count; i++) {
|
|
||||||
if (ports[i].sock >= 0) {
|
// Close the pipe
|
||||||
close(ports[i].sock);
|
pclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_iface_info(const char *essid, const char *upstream, const char *freq, int serial)
|
||||||
|
{
|
||||||
|
iface_map = realloc(iface_map, (iface_map_size + 1) * sizeof(struct iface_info));
|
||||||
|
if (!iface_map)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Memory allocation failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
struct iface_info *info = &iface_map[iface_map_size];
|
||||||
|
memset(info, 0, sizeof(struct iface_info));
|
||||||
|
// use snprintf to copy essid to info->essid
|
||||||
|
snprintf(info->essid, LEN_ESSID + 1, essid);
|
||||||
|
snprintf(info->upstream, LEN_IFACE + 1, upstream);
|
||||||
|
snprintf(info->frequency, 2, freq);
|
||||||
|
info->serial = serial;
|
||||||
|
iface_map_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_uci_config()
|
||||||
|
{
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
if (!ctx)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Failed to allocate UCI context\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct uci_package *pkg = NULL;
|
||||||
|
if (uci_load(ctx, CONFIG_PATH, &pkg) != UCI_OK)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Failed to load UCI config\n");
|
||||||
|
uci_free_context(ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serial = 1;
|
||||||
|
struct uci_element *e;
|
||||||
|
uci_foreach_element(&pkg->sections, e)
|
||||||
|
{
|
||||||
|
struct uci_section *s = uci_to_section(e);
|
||||||
|
if (!strcmp(s->type, "network"))
|
||||||
|
{
|
||||||
|
const char *upstream = uci_lookup_option_string(ctx, s, "upstream");
|
||||||
|
if (!upstream)
|
||||||
|
continue;
|
||||||
|
syslog(LOG_INFO, "Processing ssids with upstream %s", upstream);
|
||||||
|
struct uci_option *opt, *opt2;
|
||||||
|
|
||||||
|
opt = uci_lookup_option(ctx, s, "freq");
|
||||||
|
if (opt && opt->type == UCI_TYPE_LIST)
|
||||||
|
{
|
||||||
|
struct uci_element *i;
|
||||||
|
char *freq_type = NULL;
|
||||||
|
uci_foreach_element(&opt->v.list, i)
|
||||||
|
{
|
||||||
|
// parse 6G ifaces
|
||||||
|
if (!strcmp(i->name, "6G"))
|
||||||
|
{
|
||||||
|
opt2 = uci_lookup_option(ctx, s, "ssid6G");
|
||||||
|
freq_type = "6";
|
||||||
|
}
|
||||||
|
// parse 5G ifaces
|
||||||
|
else if (!strcmp(i->name, "5G"))
|
||||||
|
{
|
||||||
|
opt2 = uci_lookup_option(ctx, s, "ssid5G");
|
||||||
|
freq_type = "5";
|
||||||
|
}
|
||||||
|
// parse 2G ifaces
|
||||||
|
else if (!strcmp(i->name, "2G"))
|
||||||
|
{
|
||||||
|
opt2 = uci_lookup_option(ctx, s, "ssid2G");
|
||||||
|
freq_type = "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt2 && opt2->type == UCI_TYPE_LIST)
|
||||||
|
{
|
||||||
|
struct uci_element *i;
|
||||||
|
uci_foreach_element(&opt2->v.list, i)
|
||||||
|
{
|
||||||
|
add_iface_info(i->name, upstream, freq_type, serial++);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(ports);
|
|
||||||
ports = NULL;
|
// initialize socket to upstream interface, say "up0v0"
|
||||||
port_count = 0;
|
port_map = realloc(port_map, (port_map_size + 1) * sizeof(struct port_info));
|
||||||
}
|
int sock = socket(AF_PACKET, SOCK_RAW, 0);
|
||||||
|
if (sock < 0)
|
||||||
// Reload ports
|
{
|
||||||
if (parse_ports(provided_ports) != 0) {
|
syslog(LOG_ERR, "Failed to create socket for %s\n", upstream);
|
||||||
syslog(LOG_ERR, "Failed to reload ports configuration\n");
|
continue;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
// Get interface index
|
||||||
// Reapply tc rules
|
int ifindex = if_nametoindex(upstream);
|
||||||
if (setup_tc() == 0) {
|
if (ifindex == 0)
|
||||||
syslog(LOG_INFO, "Reloaded with SSIDs: %s and Ports: %s\n",
|
{
|
||||||
provided_ssids, provided_ports);
|
syslog(LOG_ERR, "Failed to get ifindex for %s\n", upstream);
|
||||||
} else {
|
close(sock);
|
||||||
syslog(LOG_ERR, "Failed to reload tc configuration\n");
|
}
|
||||||
|
|
||||||
|
// Store in port_map
|
||||||
|
snprintf(port_map[port_map_size].name, LEN_IFACE + 1, upstream);
|
||||||
|
port_map[port_map_size].sock = sock;
|
||||||
|
port_map[port_map_size].ifindex = ifindex;
|
||||||
|
port_map_size++;
|
||||||
|
syslog(LOG_INFO, "Initialized socket for upstream interface %s", upstream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uci_free_context(ctx);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_hostname() {
|
struct iface_info *find_iface_info_by_vlan(int vlan_id)
|
||||||
static char hostname[256];
|
{
|
||||||
if (gethostname(hostname, sizeof(hostname)) != 0) {
|
for (int i = 0; i < iface_map_size; i++)
|
||||||
strcpy(hostname, "unknown");
|
{
|
||||||
}
|
if (iface_map[i].serial == vlan_id)
|
||||||
return hostname;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
struct iface_info *find_iface_info_by_vlan(int vlan_id) {
|
|
||||||
for (int i = 0; i < iface_count; i++) {
|
|
||||||
if (iface_map[i].serial == vlan_id) {
|
|
||||||
return &iface_map[i];
|
return &iface_map[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -391,13 +277,15 @@ struct iface_info *find_iface_info_by_vlan(int vlan_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
||||||
const unsigned char *packet) {
|
const unsigned char *packet)
|
||||||
|
{
|
||||||
int orig_len = header->len;
|
int orig_len = header->len;
|
||||||
struct ethhdr *eth = (struct ethhdr *)packet;
|
struct ethhdr *eth = (struct ethhdr *)packet;
|
||||||
int vlan_id = -1;
|
int vlan_id = -1;
|
||||||
int eth_offset = sizeof(struct ethhdr);
|
int eth_offset = sizeof(struct ethhdr);
|
||||||
|
|
||||||
if (ntohs(eth->h_proto) != ETH_P_8021Q) {
|
if (ntohs(eth->h_proto) != ETH_P_8021Q)
|
||||||
|
{
|
||||||
syslog(LOG_DEBUG,
|
syslog(LOG_DEBUG,
|
||||||
"No VLAN header found in packet (EtherType: 0x%04x)\n",
|
"No VLAN header found in packet (EtherType: 0x%04x)\n",
|
||||||
ntohs(eth->h_proto));
|
ntohs(eth->h_proto));
|
||||||
@@ -409,11 +297,14 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
|||||||
eth_offset += sizeof(struct vlan_hdr);
|
eth_offset += sizeof(struct vlan_hdr);
|
||||||
|
|
||||||
struct iface_info *info = find_iface_info_by_vlan(vlan_id);
|
struct iface_info *info = find_iface_info_by_vlan(vlan_id);
|
||||||
if (!info) {
|
if (!info)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "No interface info found for VLAN ID %d\n", vlan_id);
|
syslog(LOG_ERR, "No interface info found for VLAN ID %d\n", vlan_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "Received dhcp packet with vlan id %d from iface %s of length: %d", vlan_id, info->iface, header->len);
|
||||||
|
|
||||||
char *hostname = get_hostname();
|
char *hostname = get_hostname();
|
||||||
int circuit_id_len = strlen(info->bssid) + 1 + strlen(info->essid);
|
int circuit_id_len = strlen(info->bssid) + 1 + strlen(info->essid);
|
||||||
int remote_id_len = strlen(hostname);
|
int remote_id_len = strlen(hostname);
|
||||||
@@ -429,13 +320,16 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
|||||||
int dhcp_len = ntohs(udp->len) - sizeof(struct udphdr);
|
int dhcp_len = ntohs(udp->len) - sizeof(struct udphdr);
|
||||||
|
|
||||||
int options_end = -1;
|
int options_end = -1;
|
||||||
for (int i = dhcp_len - 1; i >= 0; i--) {
|
for (int i = dhcp_len - 1; i >= 0; i--)
|
||||||
if (dhcp_start[i] == 0xFF) { // End option
|
{
|
||||||
|
if (dhcp_start[i] == 0xFF)
|
||||||
|
{ // End option
|
||||||
options_end = i;
|
options_end = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options_end == -1) {
|
if (options_end == -1)
|
||||||
|
{
|
||||||
syslog(LOG_DEBUG, "Could not find DHCP options end tag\n");
|
syslog(LOG_DEBUG, "Could not find DHCP options end tag\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -445,7 +339,8 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
|||||||
int orig_options_len = options_end;
|
int orig_options_len = options_end;
|
||||||
int new_len = orig_len - 4 - 1 + opt82_len + 1;
|
int new_len = orig_len - 4 - 1 + opt82_len + 1;
|
||||||
unsigned char *new_packet = malloc(new_len);
|
unsigned char *new_packet = malloc(new_len);
|
||||||
if (!new_packet) {
|
if (!new_packet)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Failed to allocate memory for new packet\n");
|
syslog(LOG_ERR, "Failed to allocate memory for new packet\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -501,10 +396,12 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
|||||||
new_ip->check = 0;
|
new_ip->check = 0;
|
||||||
unsigned int sum = 0;
|
unsigned int sum = 0;
|
||||||
unsigned short *ip_ptr = (unsigned short *)new_ip;
|
unsigned short *ip_ptr = (unsigned short *)new_ip;
|
||||||
for (int i = 0; i < ip->ihl * 2; i++) {
|
for (int i = 0; i < ip->ihl * 2; i++)
|
||||||
|
{
|
||||||
sum += *ip_ptr++;
|
sum += *ip_ptr++;
|
||||||
}
|
}
|
||||||
while (sum >> 16) {
|
while (sum >> 16)
|
||||||
|
{
|
||||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
}
|
}
|
||||||
new_ip->check = ~sum;
|
new_ip->check = ~sum;
|
||||||
@@ -524,13 +421,16 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
|||||||
unsigned char *udp_start = (unsigned char *)new_udp;
|
unsigned char *udp_start = (unsigned char *)new_udp;
|
||||||
int udp_total_len = ntohs(new_udp->len);
|
int udp_total_len = ntohs(new_udp->len);
|
||||||
unsigned short *udp_ptr = (unsigned short *)udp_start;
|
unsigned short *udp_ptr = (unsigned short *)udp_start;
|
||||||
for (int i = 0; i < udp_total_len / 2; i++) {
|
for (int i = 0; i < udp_total_len / 2; i++)
|
||||||
|
{
|
||||||
sum += *udp_ptr++;
|
sum += *udp_ptr++;
|
||||||
}
|
}
|
||||||
if (udp_total_len % 2) {
|
if (udp_total_len % 2)
|
||||||
|
{
|
||||||
sum += *(unsigned char *)udp_ptr;
|
sum += *(unsigned char *)udp_ptr;
|
||||||
}
|
}
|
||||||
while (sum >> 16) {
|
while (sum >> 16)
|
||||||
|
{
|
||||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
}
|
}
|
||||||
new_udp->check = ~sum;
|
new_udp->check = ~sum;
|
||||||
@@ -542,92 +442,91 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
|
|||||||
socket_address.sll_family = AF_PACKET;
|
socket_address.sll_family = AF_PACKET;
|
||||||
socket_address.sll_protocol = htons(ETH_P_ALL);
|
socket_address.sll_protocol = htons(ETH_P_ALL);
|
||||||
|
|
||||||
for (int i = 0; i < port_count; i++) {
|
for (int i = 0; i < port_map_size; i++)
|
||||||
socket_address.sll_ifindex = ports[i].ifindex;
|
{
|
||||||
|
if (!strcmp(info->upstream, port_map[i].name))
|
||||||
if (sendto(ports[i].sock, new_packet, new_len, 0,
|
{
|
||||||
(struct sockaddr *)&socket_address,
|
socket_address.sll_ifindex = port_map[i].ifindex;
|
||||||
sizeof(socket_address)) < 0) {
|
if (sendto(port_map[i].sock, new_packet, new_len, 0, (struct sockaddr *)&socket_address,
|
||||||
syslog(LOG_ERR, "Failed to send packet to %s: %s\n",
|
sizeof(socket_address)) < 0)
|
||||||
ports[i].name, strerror(errno));
|
{
|
||||||
} else {
|
syslog(LOG_ERR, "Failed to send packet to %s: %s\n",
|
||||||
syslog(LOG_DEBUG,
|
info->upstream, strerror(errno));
|
||||||
"Successfully forwarded packet to %s (new length: %d)\n",
|
}
|
||||||
ports[i].name, new_len);
|
else
|
||||||
|
{
|
||||||
|
syslog(LOG_INFO,
|
||||||
|
"Successfully forwarded packet to %s (new length: %d)\n",
|
||||||
|
info->upstream, new_len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(new_packet);
|
free(new_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
void signal_handler(int sig)
|
||||||
|
{
|
||||||
|
switch (sig)
|
||||||
|
{
|
||||||
|
case SIGTERM:
|
||||||
|
case SIGHUP:
|
||||||
|
cleanup();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
openlog("dhcp_inject:", LOG_PID | LOG_CONS, LOG_DAEMON);
|
openlog("dhcp_inject:", LOG_PID | LOG_CONS, LOG_DAEMON);
|
||||||
|
|
||||||
signal(SIGTERM, signal_handler);
|
signal(SIGTERM, signal_handler);
|
||||||
signal(SIGHUP, signal_handler);
|
signal(SIGHUP, signal_handler);
|
||||||
|
|
||||||
// Read IFACEs from environment variable
|
if (parse_uci_config() != 0)
|
||||||
char *iface_env = getenv("IFACEs");
|
{
|
||||||
if (!iface_env) {
|
syslog(LOG_ERR, "Failed to parse UCI configuration\n");
|
||||||
syslog(LOG_ERR, "No IFACEs provided. Exiting...\n");
|
|
||||||
cleanup();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
total_iface = atoi(iface_env);
|
|
||||||
if (total_iface <= 0) {
|
|
||||||
syslog(LOG_ERR, "Invalid IFACEs value: %s. Exiting...\n", iface_env);
|
|
||||||
cleanup();
|
cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
provided_ssids = getenv("SSIDs");
|
for (int i = 0; i < iface_map_size; i++)
|
||||||
syslog(LOG_INFO, "Provided SSIDs: %s\n", provided_ssids);
|
{
|
||||||
if (!provided_ssids && argc > 1) {
|
if (parse_iwinfo_by_essid(&iface_map[i]) != 0)
|
||||||
provided_ssids = strdup(argv[1]);
|
{
|
||||||
}
|
syslog(LOG_ERR, "Failed to get iface info for ESSID: %s\n", iface_map[i].essid);
|
||||||
if (!provided_ssids) {
|
cleanup();
|
||||||
syslog(LOG_ERR, "No SSIDs provided. Exiting...\n");
|
return 1;
|
||||||
return 1;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syslog(LOG_INFO, "iface_info[%d]: iface='%s', freq='%s', essid='%s', bssid='%s', upstream='%s', serial=%d\n",
|
||||||
|
i, iface_map[i].iface, iface_map[i].frequency, iface_map[i].essid, iface_map[i].bssid,
|
||||||
|
iface_map[i].upstream, iface_map[i].serial);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provided_ports = getenv("PORTs");
|
if (setup_tc() != 0)
|
||||||
syslog(LOG_INFO, "Provided PORTs: %s\n", provided_ports);
|
{
|
||||||
if (!provided_ports) {
|
|
||||||
syslog(LOG_ERR, "No PORTs provided. Exiting...\n");
|
|
||||||
cleanup();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_ssids(provided_ssids) != 0) {
|
|
||||||
syslog(LOG_ERR, "Failed to parse SSIDs\n");
|
|
||||||
cleanup();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_ports(provided_ports) != 0) {
|
|
||||||
syslog(LOG_ERR, "Failed to parse ports\n");
|
|
||||||
cleanup();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setup_tc() != 0) {
|
|
||||||
syslog(LOG_ERR, "Setup failed\n");
|
syslog(LOG_ERR, "Setup failed\n");
|
||||||
cleanup();
|
cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_INFO, "Setup complete for SSIDs: %s and Ports: %s\n",
|
|
||||||
provided_ssids, provided_ports);
|
|
||||||
|
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
handle = pcap_open_live("ifb-inject", BUFSIZ, 1, 1000, errbuf);
|
handle = pcap_open_live("ifb-inject", BUFSIZ, 1, 1000, errbuf);
|
||||||
if (handle == NULL) {
|
if (handle == NULL)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Couldn't open device ifb-inject: %s\n", errbuf);
|
syslog(LOG_ERR, "Couldn't open device ifb-inject: %s\n", errbuf);
|
||||||
cleanup();
|
cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcap_loop(handle, -1, process_packet, NULL) < 0) {
|
if (pcap_loop(handle, -1, process_packet, NULL) < 0)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "pcap_loop failed: %s\n", pcap_geterr(handle));
|
syslog(LOG_ERR, "pcap_loop failed: %s\n", pcap_geterr(handle));
|
||||||
cleanup();
|
cleanup();
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -1,9 +1,27 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#define LEN_ESSID 32
|
#define LEN_ESSID 32
|
||||||
#define LEN_BSSID 12
|
#define LEN_BSSID 12
|
||||||
#define LEN_IFACE 15
|
#define LEN_IFACE 15
|
||||||
|
#define LEN_FREQ 3
|
||||||
|
|
||||||
|
#define MAX_INTERFACES 48
|
||||||
|
#define MAX_PORTS 8
|
||||||
|
|
||||||
|
#define CONFIG_PATH "/etc/config/dhcpinject"
|
||||||
|
|
||||||
|
#define IWINFO_CMD "iwinfo | grep %s -A2 | grep '.*Channel:.*\\(%s\\..*\\) GHz' -B2 | awk '/ESSID/{print $1} /Access Point/{gsub(/:/, \"\", $3); print $3}'"
|
||||||
|
|
||||||
|
static pcap_t *handle = NULL;
|
||||||
|
|
||||||
|
static int iface_map_size = 0;
|
||||||
|
struct iface_info *iface_map = NULL;
|
||||||
|
static int port_map_size = 0;
|
||||||
|
struct port_info *port_map = NULL;
|
||||||
|
|
||||||
// DHCP header structure
|
// DHCP header structure
|
||||||
struct dhcp_packet {
|
struct dhcp_packet {
|
||||||
@@ -25,11 +43,15 @@ struct dhcp_packet {
|
|||||||
uint8_t options[];
|
uint8_t options[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// up4094v4094
|
||||||
|
|
||||||
// Structure to hold interface info
|
// Structure to hold interface info
|
||||||
struct iface_info {
|
struct iface_info {
|
||||||
char iface[LEN_IFACE + 1];
|
char iface[LEN_IFACE + 1];
|
||||||
char essid[LEN_ESSID + 1];
|
char essid[LEN_ESSID + 1];
|
||||||
char bssid[LEN_BSSID + 1];
|
char bssid[LEN_BSSID + 1];
|
||||||
|
char upstream[LEN_IFACE + 1];
|
||||||
|
char frequency[4];
|
||||||
int serial;
|
int serial;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,6 +63,14 @@ struct port_info {
|
|||||||
|
|
||||||
// VLAN header structure
|
// VLAN header structure
|
||||||
struct vlan_hdr {
|
struct vlan_hdr {
|
||||||
__be16 h_vlan_TCI; // VLAN Tag Control Information
|
__be16 h_vlan_TCI; // VLAN Tag Control Information
|
||||||
__be16 h_vlan_encapsulated_proto; // Encapsulated protocol
|
__be16 h_vlan_encapsulated_proto; // Encapsulated protocol
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *get_hostname() {
|
||||||
|
static char hostname[256];
|
||||||
|
if (gethostname(hostname, sizeof(hostname)) != 0) {
|
||||||
|
strcpy(hostname, "unknown");
|
||||||
|
}
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user