Compare commits

..

1 Commits

Author SHA1 Message Date
wingate5678
0e29904461 WIFI-15138 sonicfi wifi7 thermal setting
Signed-off-by: wingate5678 <wingate.chi@cybertan.com.tw>
2025-09-19 06:00:46 +00:00
22 changed files with 479 additions and 944 deletions

View File

@@ -1,34 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=log-helper
PKG_VERSION:=1.0
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/log-helper
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Log backup helper
DEPENDS:=+libuci +libubus +libubox
endef
define Package/log-helper/description
This service that backs up files on boot.
endef
define Package/log-helper/install
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_BIN) ./files/log-helper.uci $(1)/etc/config/log-helper
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/log-helper.init $(1)/etc/init.d/log-helper
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/log-helper $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,log-helper))

View File

@@ -1,30 +0,0 @@
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=15
PROG=/usr/sbin/log-helper
#add directory that need to be preserved during OpenWRT sysupgrade
check_upgrade_conf() {
dir="$1"
grep -q ${dir} /etc/sysupgrade.conf
[ $? -ne 0 ] && {
echo "/${dir}/" >> /etc/sysupgrade.conf
}
}
start_service() {
local enabled
config_load log-helper
config_get_bool enabled global enabled 0
[ ${enabled} -eq 0 ] && return 1
config_get backup_dir global backup_dir "backup_storage"
check_upgrade_conf ${backup_dir}
procd_open_instance
procd_set_param command $PROG
procd_close_instance
}

View File

@@ -1,18 +0,0 @@
config log-helper 'global'
option enabled '1'
# Directory in overlay file system for backed up files.
option backup_dir 'backup_storage'
# Free space safety margin in KB.
# A backup will be skipped if available space of overlay is less than (file_size + threshold).
option space_threshold '2048'
# To specify the maximum number of rotations.
option max_rotations '3'
option backup_file 'backup.tgz'
list file_list '/sys/fs/pstore/dmesg-ramoops-0'
list file_list '/sys/fs/pstore/console-ramoops-0'
list file_list '/sys/fs/pstore/pmsg-ramoops-0'

View File

@@ -1,22 +0,0 @@
cmake_minimum_required(VERSION 2.6)
INCLUDE(CheckFunctionExists)
PROJECT(log-helper C)
ADD_DEFINITIONS(-Os -Wall -Werror)
ADD_DEFINITIONS(-std=gnu99 -g3 -Wmissing-declarations -Wno-unused-parameter)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
SET(SOURCES main.c)
FIND_LIBRARY(uci NAMES uci)
FIND_LIBRARY(ubus NAMES ubus)
FIND_LIBRARY(ubox NAMES ubox)
ADD_EXECUTABLE(log-helper ${SOURCES})
TARGET_LINK_LIBRARIES(log-helper ${uci} ${ubus} ${ubox})
INSTALL(TARGETS log-helper
RUNTIME DESTINATION sbin
)

View File

@@ -1,341 +0,0 @@
/*
* Copyright (c) 2025, CyberTAN Technology Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions, and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of CyberTAN Technology Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <libgen.h>
#include <limits.h>
#include <errno.h>
#include <stdbool.h>
#include <uci.h>
#include <libubus.h>
#define DEFAULT_BACKUP_DIRECTOR "backup_storage"
#define DEFAULT_BACKUP_FILE_NAME "backup.tgz"
#define DEFAULT_MAX_ROTATIONS 3
#define DEFAULT_SPACE_THRESH 2048
#define UCI_CONFIG_FILE "log-helper"
#define OVERLAYFS_ROOT "/overlay/upper"
static int rotate_logs(const char *base_log_path, int max_rotations);
static int move_file(const char *src_path, const char *dest_dir);
static void do_backup(void);
static char backup_dir[1024];
/**
* @brief Performs log rotation.
* @param base_log_path The path of the base log file, e.g., "app.log".
* @param max_rotations The maximum number of backup files to keep.
* @return 0 on success, -1 on failure.
*/
static int rotate_logs(const char *base_log_path, int max_rotations) {
struct stat info;
char log_name[NAME_MAX] = {0};
char log_path[1024] = {0};
char src_path[PATH_MAX] = {0};
char dest_path[PATH_MAX] ={0};
int len;
if (!strlen(backup_dir) || stat(backup_dir, &info) != 0) {
syslog(LOG_ERR, "Wrong backup directory: %s", backup_dir);
return -1;
}
if (max_rotations <= 1) {
syslog(LOG_ERR, "max_rotations must be greater than 1: %d", max_rotations);
return -1;
}
strncpy(log_name, basename((char *)base_log_path), sizeof(log_name));
len = snprintf(log_path, sizeof(log_path), "%s/%s", backup_dir, log_name);
if (len >= sizeof(log_path)) {
syslog(LOG_ERR, "Buffer too small, path was truncated.");
return -1;
}
if (access(log_path, F_OK) != 0) {
syslog(LOG_DEBUG, "File not found: %s", log_path);
return 0;
}
// Remove the oldest backup file (e.g., app.log.5).
snprintf(dest_path, sizeof(dest_path), "%s.%d", log_path, max_rotations);
if (remove(dest_path) == 0) {
syslog(LOG_DEBUG, "Deleted oldest backup: %s", dest_path);
}
// Rename files in reverse order, from the second to last backup.
for (int i = max_rotations - 1; i >= 0; --i) {
// Generate the source file path.
if (i) {
// the source is the .i backup file.
snprintf(src_path, sizeof(src_path) - 2, "%s.%d", log_path, i);
} else {
// the source is the original log file.
src_path[strlen(log_path)] = '\0'; // Ensure null-termination.
}
// Generate the destination file path (i+1).
snprintf(dest_path, sizeof(dest_path), "%s.%d", log_path, i + 1);
// Check if the source file exists before trying to rename it.
if (access(src_path, F_OK) == 0) {
if (!rename(src_path, dest_path)) {
syslog(LOG_DEBUG, "rename '%s' to '%s'.", src_path, dest_path);
} else {
syslog(LOG_ERR, "Could not rename '%s' to '%s'.", src_path, dest_path);
return -1;
}
}
}
return 0;
}
/**
* @brief Moves a file from a source path to a destination directory.
* * @param src_path Absolute path to the source file.
* @param dest_dir Absolute path to the destination directory.
* @return 0 on success, -1 on failure.
*/
static int move_file(const char *src_path, const char *dest_dir) {
size_t len;
FILE *fd_s, *fd_d;
char buffer[4096] = {0};
char dest_path[PATH_MAX] = {0};
snprintf(dest_path, sizeof(dest_path) - 1, "%s/%s", dest_dir, basename((char *)src_path));
fd_s = fopen(src_path, "rb");
if (!fd_s) {
syslog(LOG_ERR, "Failed to open source file %s: %s", src_path, strerror(errno));
return -1;
}
fd_d = fopen(dest_path, "wb+");
if (!fd_d) {
syslog(LOG_ERR, "Failed to open destination file %s: %s", dest_path, strerror(errno));
fclose(fd_s);
return -1;
}
while ((len = fread(buffer, 1, sizeof(buffer), fd_s)) > 0) {
if (fwrite(buffer, 1, len, fd_d) != len) {
syslog(LOG_ERR, "Error writing to destination file: %s", dest_path);
fclose(fd_s);
fclose(fd_d);
return -1;
}
}
unlink(src_path);
fclose(fd_s);
fclose(fd_d);
return 0;
}
static int build_file_list(char *file_list, size_t list_size, const char *path) {
size_t current_len = strlen(file_list);
size_t path_len = strlen(path);
struct stat st;
if (stat(path, &st) != 0) {
syslog(LOG_WARNING, "Backup source file not found: %s", path);
return 0;
}
if (current_len + path_len + 1 > list_size - 1) {
syslog(LOG_ERR, "Buffer too small.");
return -1;
}
if (strlen(file_list)) {
strcat(file_list, " ");
}
strcat(file_list, path);
return 0;
}
/**
* @brief Performs the backup task based on UCI configuration.
*/
static void do_backup(void) {
struct uci_context *ctx = uci_alloc_context();
struct uci_package *pkg = NULL;
struct uci_section *s = NULL;
struct uci_element *e = NULL;
struct uci_option *o = NULL;
struct statvfs vfs;
struct stat st;
long space_threshold_kb;
long available_kb;
long max_rotations;
long file_kb;
const char *str = NULL;
char file_list[1024] = {0};
char cmd[1024] = {0};
char backup_file[256] = {0};
char tmp_file[256] = {0};
int n, ret;
if (uci_load(ctx, UCI_CONFIG_FILE, &pkg) != UCI_OK) {
syslog(LOG_ERR, "Failed to load UCI config: %s", UCI_CONFIG_FILE);
return;
}
s = uci_lookup_section(ctx, pkg, "global");
if (!s) {
syslog(LOG_ERR, "UCI section 'global' not found in %s", UCI_CONFIG_FILE);
goto backup_exit;
}
// Iterate through the list of files to be backed up
uci_foreach_element(&s->options, e) {
struct uci_element *le;
o = uci_to_option(e);
if (o->type != UCI_TYPE_LIST || strcmp(o->e.name, "file_list") != 0)
continue;
list_for_each_entry(le, &o->v.list, list) {
const char *f = le->name;
if (build_file_list(file_list, sizeof(file_list), f) != 0) {
goto backup_exit;
}
}
}
if (!strlen(file_list)) {
goto backup_exit;
}
// Get the backup directory
str = uci_lookup_option_string(ctx, s, "backup_dir");
if (!str || strlen(str)==0)
str = DEFAULT_BACKUP_DIRECTOR;
snprintf(backup_dir, sizeof(backup_dir) - 1 , "/%s", str);
mkdir(backup_dir, 0755);
// Get the backup file name
str = uci_lookup_option_string(ctx, s, "backup_file");
if (!str || strlen(str)==0)
str = DEFAULT_BACKUP_FILE_NAME;
n = snprintf(backup_file, sizeof(backup_file) - 1, "%s/%s", backup_dir, str);
if (n >= sizeof(backup_file)) {
syslog(LOG_ERR, "File buffer is too small.\n");
goto backup_exit;
}
n = snprintf(tmp_file, sizeof(tmp_file) - 1, "/tmp/%s", str);
if (n >= sizeof(tmp_file)) {
syslog(LOG_ERR, "Tmp buffer is too small.\n");
goto backup_exit;
}
// Create the backup tgz file in /tmp/
n = snprintf(cmd, sizeof(cmd) - 1, "tar -czf %s %s", tmp_file, file_list);
if (n >= sizeof(cmd)) {
syslog(LOG_ERR, "Command buffer is too small.\n");
goto backup_exit;
}
ret = system(cmd);
if (ret){
syslog(LOG_ERR, "The tar command failed with return code: %d\n", ret);
goto backup_exit;
}
// Get available space on the overlay filesystem
if (statvfs(OVERLAYFS_ROOT, &vfs) != 0) {
syslog(LOG_ERR, "Failed to get overlay filesystem stats: %s", strerror(errno));
goto backup_exit;
}
available_kb = (vfs.f_bavail * vfs.f_bsize) / 1024;
str = uci_lookup_option_string(ctx, s, "space_threshold");
space_threshold_kb = str ? atol(str) : DEFAULT_SPACE_THRESH;
syslog(LOG_INFO, "Overlay available space: %ldKB", available_kb);
// Check if there is enough space
stat(tmp_file, &st);
file_kb = st.st_size / 1024;
if (available_kb < (file_kb + space_threshold_kb)) {
syslog(LOG_ERR, "Overlay space insufficient for %s. (Available: %ldKB, Required: %ldKB)",
tmp_file, available_kb, (file_kb + space_threshold_kb));
goto backup_exit;
}
// Get the maximum number of rotations
str = uci_lookup_option_string(ctx, s, "max_rotations");
max_rotations = str ? atol(str) : DEFAULT_MAX_ROTATIONS;
if (max_rotations > 1 && access(backup_file, F_OK)==0) {
rotate_logs(backup_file, max_rotations);
}
if (move_file(tmp_file, backup_dir) == 0) {
syslog(LOG_INFO, "Successfully backed up to '%s'.", backup_file);
} else {
syslog(LOG_ERR, "Failed to move '%s' to '%s': %s", tmp_file, backup_file, strerror(errno));
}
backup_exit:
uci_free_context(ctx);
}
/**
* @brief Main entry point of the application.
*/
int main(int argc, char **argv) {
// Set up syslog with the program name
openlog("log-helper", LOG_PID, LOG_DAEMON);
do_backup();
closelog();
return 0;
}

View File

@@ -1 +0,0 @@
../../feeds/ipq807x_v5.4/log-helper

View File

@@ -259,13 +259,8 @@ const phy_proto = {
addr[0] ^= idx << 2;
break;
case "b5":
if (mbssid) {
let b5 = addr[5];
addr[5] = addr[3];
addr[3] = b5;
addr[5] &= ~0xf;
if (mbssid)
addr[0] |= 2;
}
addr[5] ^= idx;
break;
default:

View File

@@ -1,33 +0,0 @@
From f7b27331b915477cd289c37b56efb0d28b2d6f38 Mon Sep 17 00:00:00 2001
From: Antonio Wu <antonio.wu@cybertan.com.tw>
Date: Tue, 5 Aug 2025 10:39:58 +0000
Subject: [PATCH] Add IPQ_MEM_PROFILE in arm64 kconfig
---
arch/arm64/Kconfig | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 702a289..7864e79 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2143,6 +2143,16 @@ config STACKPROTECTOR_PER_TASK
def_bool y
depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_SYSREG
+config IPQ_MEM_PROFILE
+ int "Select Memory Profile"
+ range 0 1024
+ default 0
+ help
+ This option select memory profile to be used, which defines
+ the reserved memory configuration used in device tree.
+
+ If unsure, say 0
+
# The GPIO number here must be sorted by descending number. In case of
# a multiplatform kernel, we just want the highest value required by the
# selected platforms.
--
2.17.1

View File

@@ -25,11 +25,6 @@ copy_certificates() {
}
boot() {
case "$(board_name)" in
sonicfi,rap6*)
touch /tmp/squashfs
;;
esac
[ -f /etc/ucentral/key.pem ] && return
/usr/bin/mount_certs
copy_certificates

View File

@@ -37,16 +37,13 @@ sonicfi,rap7*)
mtd=$(find_mtd_index certificates)
[ -n "$mtd" ] && mount -t ext4 /dev/mtdblock$mtd /certificates
fi
;;
sonicfi,rap6*)
mtd=$(find_mtd_index certificates)
if [ "$(head -c 4 /dev/mtd$mtd)" == "hsqs" ]; then
mount -t squashfs /dev/mtdblock$mtd /mnt
cp /mnt/* /certificates
umount /mnt
if [ ! -f /certificates/cert.pem ] || [ ! -f /certificates/key.pem ]; then
part=$(tar_part_lookup "0:BOOTCONFIG" "0:BOOTCONFIG1")
if [ -n "part" ]; then
mmc_dev=$(echo $(find_mmc_part "$part") | sed 's/^.\{5\}//')
[ -n "$mmc_dev" ] && tar xf /dev/$mmc_dev -C /certificates
fi
fi
mtd=$(find_mtd_index devinfo)
[ -n "$mtd" ] && tar xf /dev/mtdblock$mtd -C /certificates
;;
udaya,a5-id2|\
yuncore,ax820)
@@ -62,6 +59,19 @@ yuncore,ax820)
[ -n "$mtd" ] && tar xf /dev/mtdblock$mtd -C /certificates
fi
;;
sonicfi,rap6*)
mtd=$(find_mtd_index certificates)
if [ "$(head -c 4 /dev/mtd$mtd)" == "hsqs" ]; then
mount -t squashfs /dev/mtdblock$mtd /mnt
cp /mnt/* /certificates
umount /mnt
fi
part=$(tar_part_lookup "devinfo" "certificates")
if [ -n "$part" ]; then
mtd=$(find_mtd_index $part)
[ -n "$mtd" ] && tar xf /dev/mtdblock$mtd -C /certificates
fi
;;
*)
mtd=$(find_mtd_index certificates)

View File

@@ -14,6 +14,13 @@ tar_part_lookup() {
. /lib/functions.sh
case "$(board_name)" in
sonicfi,rap7110c-341x)
cd /certificates
tar cf /tmp/certs.tar .
part=$(tar_part_lookup "0:BOOTCONFIG" "0:BOOTCONFIG1")
mmc_dev=$(echo $(find_mmc_part $part) | sed 's/^.\{5\}//')
dd if=/tmp/certs.tar of=/dev/$mmc_dev
;;
udaya,a5-id2|\
yuncore,ax820)
cd /certificates
@@ -26,7 +33,8 @@ sonicfi,rap6*)
if [ "$(fw_printenv -n store_certs_disabled)" != "1" ]; then
cd /certificates
tar cf /tmp/certs.tar .
mtd=$(find_mtd_index devinfo)
part=$(tar_part_lookup "devinfo" "certificates")
mtd=$(find_mtd_index $part)
block_size=$(cat /sys/class/mtd/mtd$mtd/size)
dd if=/tmp/certs.tar of=/tmp/certs_pad.tar bs=$block_size conv=sync
mtd write /tmp/certs_pad.tar /dev/mtd$mtd

View File

@@ -5,8 +5,8 @@ import * as fs from 'fs';
let cmd = ARGV[0];
let ifname = getenv("interface");
let opt138 = fs.readfile('/tmp/dhcp-option-138');
let opt224 = fs.readfile('/tmp/dhcp-option-224');
let opt138 = getenv("opt138");
let opt224 = getenv("opt224");
if (cmd != 'bound' && cmd != 'renew')
exit(0);
@@ -23,14 +23,14 @@ let cloud = {
lease: true,
};
if (opt138) {
let dhcp = opt138;
let dhcp = hexdec(opt138);
dhcp = split(dhcp, ':');
cloud.dhcp_server = dhcp[0];
cloud.dhcp_port = dhcp[1] ?? 15002;
cloud.no_validation = true;
}
if (opt224) {
let dhcp = opt224;
let dhcp = hexdec(opt224);
dhcp = split(dhcp, ':');
cloud.dhcp_server = dhcp[0];
cloud.dhcp_port = dhcp[1] ?? 15002;

View File

@@ -12,7 +12,7 @@ define Package/udhcpinject
SECTION:=net
CATEGORY:=Network
TITLE:=An agent to inject DHCP option
DEPENDS:=+libpcap +kmod-ifb +tc +libuci
DEPENDS:=+libpcap +kmod-ifb +tc
MAINTAINER:=kmk <alex18_huang@accton.com>
endef
@@ -41,4 +41,4 @@ define Package/udhcpinject/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,udhcpinject))
$(eval $(call BuildPackage,udhcpinject))

View File

@@ -1,19 +1,10 @@
#config network 'wan0'
# option upstream 'up0v0'
# list ssid5G '18-KMK-YAYA'
# list ssid5G '18-KMK-AKIHO'
# list ssid2G '18-KMK-YAYA'
# list ssid2G '18-KMK-AKIHO'
# option count '4'
#config network 'wan284'
# 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'
# config device 'uplink'
# list port 'eth0'
#
# config ssids 'ssids'
# list ssid 'EAP101-ERICHI'
# list ssid 'EAP101-AKIHO'
# list ssid 'EAP101-DAMAYU'
#
# config dhcpinject 'dhcpinject'
# option iface_count '6'

View File

@@ -9,18 +9,55 @@ SERVICE_NAME="dhcpinject"
PROG=/usr/bin/udhcpinject
start_service() {
# check if config file has contents by executing `uci get dhcpinject.@network[0]`
if [ -z "$(uci get dhcpinject.@network[0] 2>/dev/null)" ]; then
echo "No upstreams specified, exiting $SERVICE_NAME"
return 0
local ssids=""
local ports=""
local ifaces=""
# 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
# Wait for wifi to be up
ubus -t 90 wait_for network.wireless
# Optional: Log or echo for debugging
logger -t dhcp_inject "Generated SSIDs=$ssids, Uplink=$ports, IFACEs=$ifaces"
procd_open_instance "$SERVICE_NAME"
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 file /etc/config/dhcpinject
procd_set_param reload_signal SIGHUP
procd_close_instance
}

View File

@@ -7,10 +7,10 @@ obj-y := udhcpinject.o
all: udhcpinject
udhcpinject: $(obj-y)
$(CC) $(LDFLAGS) -lpcap -luci -o $@ $(obj-y)
$(CC) $(LDFLAGS) -lpcap -o $@ $(obj-y)
%.o: %.c
$(CC) $(CFLAGS) $(TARGET_CFLAGS) -c $< -o $@
clean:
rm -f *.o udhcpinject
rm -f *.o udhcpinject

View File

@@ -6,81 +6,286 @@
#include <linux/ip.h>
#include <linux/udp.h>
#include <net/if.h>
#include <netinet/in.h>
#include <pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <syslog.h>
#include <unistd.h>
#include <uci.h>
#include "udhcpinject.h"
// Cleanup function
void cleanup()
{
syslog(LOG_INFO, "Cleaning up resources...\n");
#define MAX_INTERFACES 48
#define MAX_PORTS 8
if (handle)
{
// 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
void cleanup() {
syslog(LOG_INFO, "Cleaning up resources...\n");
cleanup_tc();
if (handle) {
pcap_close(handle);
handle = NULL;
}
if (iface_map)
{
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);
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;
}
if (iface_map) {
free(iface_map);
iface_map = NULL;
iface_count = 0;
}
if (port_map)
{
for (int i = 0; i < port_map_size; i++)
{
close(port_map[i].sock);
}
free(port_map);
if (provided_ssids) {
free(provided_ssids);
provided_ssids = NULL;
}
if (provided_ports) {
free(provided_ports);
provided_ports = NULL;
}
syslog(LOG_INFO, "Cleanup complete.\n");
}
int setup_tc()
{
char cmd[512];
// Function to parse SSIDs and populate iface_map
int parse_ssids(const char *ssids) {
if (iface_map) {
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");
if (system(cmd) != 0)
{
if (system(cmd) != 0) {
snprintf(cmd, sizeof(cmd),
"ip link add name ifb-inject type ifb && ip link set "
"ifb-inject up");
if (system(cmd) != 0)
{
if (system(cmd) != 0) {
syslog(LOG_ERR, "Failed to setup ifb-inject\n");
return -1;
}
}
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);
for (int i = 0; i < iface_count; i++) {
snprintf(cmd, sizeof(cmd), "tc qdisc add dev %s ingress 2>/dev/null 1>2",
iface_map[i].iface);
int result = system(cmd);
if (result == 2)
{
if (result == 2) {
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);
return -1;
}
@@ -95,8 +300,7 @@ int setup_tc()
"action mirred egress mirror dev ifb-inject pipe "
"action drop",
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);
return -1;
}
@@ -104,172 +308,82 @@ int setup_tc()
return 0;
}
int parse_iwinfo_by_essid(struct iface_info *iface)
{
char cmd[256];
FILE *fp;
char output[128];
char *line;
snprintf(cmd, sizeof(cmd), IWINFO_CMD, iface->essid, iface->frequency);
fp = popen(cmd, "r");
if (fp == NULL)
{
syslog(LOG_ERR, "Failed to execute command: %s\n", cmd);
return 1;
}
// Read the first line (interface name)
line = fgets(output, sizeof(output), fp);
if (line)
{
output[strcspn(output, "\n")] = '\0'; // Remove trailing newline
snprintf(iface->iface, LEN_IFACE + 1, output);
}
else
{
return 1;
}
// Read the second line (BSSID)
line = fgets(output, sizeof(output), fp);
if (line)
{
output[strcspn(output, "\n")] = '\0'; // Remove trailing newline
snprintf(iface->bssid, LEN_BSSID + 1, output);
}
else
{
return 1;
}
// Close the pipe
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++);
}
}
// Signal handler
void signal_handler(int sig) {
if (sig == SIGTERM) {
syslog(LOG_INFO, "Received SIGTERM, cleaning up...\n");
cleanup();
exit(0);
} else if (sig == SIGHUP) {
syslog(LOG_INFO, "Received reload signal, reconfiguring...\n");
// Clean up existing resources
cleanup_tc();
// Free old SSIDs and get new ones
if (provided_ssids) {
free(provided_ssids);
}
provided_ssids = getenv("SSIDs");
if (!provided_ssids) {
syslog(LOG_ERR, "No SSIDs provided on reload\n");
return;
}
// Reload SSIDs
if (parse_ssids(provided_ssids) != 0) {
syslog(LOG_ERR, "Failed to reload SSIDs configuration\n");
return;
}
// Free old ports and get new ones
if (provided_ports) {
free(provided_ports);
}
provided_ports = getenv("PORTs");
if (!provided_ports) {
syslog(LOG_ERR, "No PORTs provided on reload\n");
return;
}
// Close existing sockets and reopen with new config
if (ports) {
for (int i = 0; i < port_count; i++) {
if (ports[i].sock >= 0) {
close(ports[i].sock);
}
}
// initialize socket to upstream interface, say "up0v0"
port_map = realloc(port_map, (port_map_size + 1) * sizeof(struct port_info));
int sock = socket(AF_PACKET, SOCK_RAW, 0);
if (sock < 0)
{
syslog(LOG_ERR, "Failed to create socket for %s\n", upstream);
continue;
}
// Get interface index
int ifindex = if_nametoindex(upstream);
if (ifindex == 0)
{
syslog(LOG_ERR, "Failed to get ifindex for %s\n", upstream);
close(sock);
}
// 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);
free(ports);
ports = NULL;
port_count = 0;
}
// Reload ports
if (parse_ports(provided_ports) != 0) {
syslog(LOG_ERR, "Failed to reload ports configuration\n");
return;
}
// Reapply tc rules
if (setup_tc() == 0) {
syslog(LOG_INFO, "Reloaded with SSIDs: %s and Ports: %s\n",
provided_ssids, provided_ports);
} else {
syslog(LOG_ERR, "Failed to reload tc configuration\n");
}
}
uci_free_context(ctx);
return 0;
}
struct iface_info *find_iface_info_by_vlan(int vlan_id)
{
for (int i = 0; i < iface_map_size; i++)
{
if (iface_map[i].serial == vlan_id)
{
char *get_hostname() {
static char hostname[256];
if (gethostname(hostname, sizeof(hostname)) != 0) {
strcpy(hostname, "unknown");
}
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];
}
}
@@ -277,15 +391,13 @@ struct iface_info *find_iface_info_by_vlan(int vlan_id)
}
void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
const unsigned char *packet)
{
const unsigned char *packet) {
int orig_len = header->len;
struct ethhdr *eth = (struct ethhdr *)packet;
int vlan_id = -1;
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,
"No VLAN header found in packet (EtherType: 0x%04x)\n",
ntohs(eth->h_proto));
@@ -297,14 +409,11 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
eth_offset += sizeof(struct vlan_hdr);
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);
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();
int circuit_id_len = strlen(info->bssid) + 1 + strlen(info->essid);
int remote_id_len = strlen(hostname);
@@ -320,16 +429,13 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
int dhcp_len = ntohs(udp->len) - sizeof(struct udphdr);
int options_end = -1;
for (int i = dhcp_len - 1; i >= 0; i--)
{
if (dhcp_start[i] == 0xFF)
{ // End option
for (int i = dhcp_len - 1; i >= 0; i--) {
if (dhcp_start[i] == 0xFF) { // End option
options_end = i;
break;
}
}
if (options_end == -1)
{
if (options_end == -1) {
syslog(LOG_DEBUG, "Could not find DHCP options end tag\n");
return;
}
@@ -339,8 +445,7 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
int orig_options_len = options_end;
int new_len = orig_len - 4 - 1 + opt82_len + 1;
unsigned char *new_packet = malloc(new_len);
if (!new_packet)
{
if (!new_packet) {
syslog(LOG_ERR, "Failed to allocate memory for new packet\n");
return;
}
@@ -396,12 +501,10 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
new_ip->check = 0;
unsigned int sum = 0;
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++;
}
while (sum >> 16)
{
while (sum >> 16) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
new_ip->check = ~sum;
@@ -421,16 +524,13 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
unsigned char *udp_start = (unsigned char *)new_udp;
int udp_total_len = ntohs(new_udp->len);
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++;
}
if (udp_total_len % 2)
{
if (udp_total_len % 2) {
sum += *(unsigned char *)udp_ptr;
}
while (sum >> 16)
{
while (sum >> 16) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
new_udp->check = ~sum;
@@ -442,91 +542,92 @@ void process_packet(unsigned char *user, const struct pcap_pkthdr *header,
socket_address.sll_family = AF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ALL);
for (int i = 0; i < port_map_size; i++)
{
if (!strcmp(info->upstream, port_map[i].name))
{
socket_address.sll_ifindex = port_map[i].ifindex;
if (sendto(port_map[i].sock, new_packet, new_len, 0, (struct sockaddr *)&socket_address,
sizeof(socket_address)) < 0)
{
syslog(LOG_ERR, "Failed to send packet to %s: %s\n",
info->upstream, strerror(errno));
}
else
{
syslog(LOG_INFO,
"Successfully forwarded packet to %s (new length: %d)\n",
info->upstream, new_len);
}
break;
for (int i = 0; i < port_count; i++) {
socket_address.sll_ifindex = ports[i].ifindex;
if (sendto(ports[i].sock, new_packet, new_len, 0,
(struct sockaddr *)&socket_address,
sizeof(socket_address)) < 0) {
syslog(LOG_ERR, "Failed to send packet to %s: %s\n",
ports[i].name, strerror(errno));
} else {
syslog(LOG_DEBUG,
"Successfully forwarded packet to %s (new length: %d)\n",
ports[i].name, new_len);
}
}
free(new_packet);
}
void signal_handler(int sig)
{
switch (sig)
{
case SIGTERM:
case SIGHUP:
cleanup();
break;
default:
break;
}
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
openlog("dhcp_inject:", LOG_PID | LOG_CONS, LOG_DAEMON);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
if (parse_uci_config() != 0)
{
syslog(LOG_ERR, "Failed to parse UCI configuration\n");
// Read IFACEs from environment variable
char *iface_env = getenv("IFACEs");
if (!iface_env) {
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();
return 1;
}
for (int i = 0; i < iface_map_size; i++)
{
if (parse_iwinfo_by_essid(&iface_map[i]) != 0)
{
syslog(LOG_ERR, "Failed to get iface info for ESSID: %s\n", iface_map[i].essid);
cleanup();
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_ssids = getenv("SSIDs");
syslog(LOG_INFO, "Provided SSIDs: %s\n", provided_ssids);
if (!provided_ssids && argc > 1) {
provided_ssids = strdup(argv[1]);
}
if (!provided_ssids) {
syslog(LOG_ERR, "No SSIDs provided. Exiting...\n");
return 1;
}
if (setup_tc() != 0)
{
provided_ports = getenv("PORTs");
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");
cleanup();
return 1;
}
syslog(LOG_INFO, "Setup complete for SSIDs: %s and Ports: %s\n",
provided_ssids, provided_ports);
char errbuf[PCAP_ERRBUF_SIZE];
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);
cleanup();
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));
cleanup();
return 1;

View File

@@ -1,27 +1,9 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#define LEN_ESSID 32
#define LEN_BSSID 12
#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
struct dhcp_packet {
@@ -43,15 +25,11 @@ struct dhcp_packet {
uint8_t options[];
};
// up4094v4094
// Structure to hold interface info
struct iface_info {
char iface[LEN_IFACE + 1];
char essid[LEN_ESSID + 1];
char bssid[LEN_BSSID + 1];
char upstream[LEN_IFACE + 1];
char frequency[4];
int serial;
};
@@ -63,14 +41,6 @@ struct port_info {
// VLAN header structure
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
};
char *get_hostname() {
static char hostname[256];
if (gethostname(hostname, sizeof(hostname)) != 0) {
strcpy(hostname, "unknown");
}
return hostname;
}

View File

@@ -1,25 +0,0 @@
From 40894005e2c114664a44abb0ffadb1cb945a88e2 Mon Sep 17 00:00:00 2001
From: Antonio Wu <antonio.wu@cybertan.com.tw>
Date: Mon, 4 Aug 2025 05:10:41 +0000
Subject: [PATCH] add KERNEL_IPQ_MEM_PROFILE for IPQ53XX
---
config/Config-kernel.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/Config-kernel.in b/config/Config-kernel.in
index 3529696559..b7f13eccbe 100644
--- a/config/Config-kernel.in
+++ b/config/Config-kernel.in
@@ -6,7 +6,7 @@ config KERNEL_IPQ_MEM_PROFILE
int "Different memory profile "
range 0 1024
default 512
- depends on TARGET_ipq807x || TARGET_ipq60xx || TARGET_ipq50xx || TARGET_ipq95xx
+ depends on TARGET_ipq807x || TARGET_ipq60xx || TARGET_ipq50xx || TARGET_ipq95xx || TARGET_ipq53xx
help
This option select memory profile to be used,which defines
the reserved memory configuration used in device tree.
--
2.17.1

View File

@@ -1,68 +0,0 @@
From ba5c63cc0cbbacd952a5c2cfd873439bf5adc86a Mon Sep 17 00:00:00 2001
From: Tanya Singh <tanya_singh@accton.com>
Date: Thu, 18 Sep 2025 13:21:38 +0800
Subject: [PATCH] netifd: Support DHCP option 138 and DHCP option 224
---
.../netifd/files/lib/netifd/dhcp.script | 10 ++++++++++
.../patches/601-dhcp_opt138_opt224.patch | 20 +++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 package/utils/busybox/patches/601-dhcp_opt138_opt224.patch
diff --git a/package/network/config/netifd/files/lib/netifd/dhcp.script b/package/network/config/netifd/files/lib/netifd/dhcp.script
index 6fcf139beb..9c4366f48b 100755
--- a/package/network/config/netifd/files/lib/netifd/dhcp.script
+++ b/package/network/config/netifd/files/lib/netifd/dhcp.script
@@ -4,6 +4,8 @@
. /lib/functions.sh
. /lib/netifd/netifd-proto.sh
+rm -rf /tmp/dhcp-option-*
+
set_classless_routes() {
local max=128
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
@@ -111,6 +113,14 @@ case "$1" in
;;
esac
+if [ -n "${opt138}" ]; then
+ echo -n "${opt138}" > /tmp/dhcp-option-138
+fi
+
+if [ -n "${opt224}" ]; then
+ echo -n "${opt224}" > /tmp/dhcp-option-224
+fi
+
# user rules
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@"
for f in /etc/udhcpc.user.d/*; do
diff --git a/package/utils/busybox/patches/601-dhcp_opt138_opt224.patch b/package/utils/busybox/patches/601-dhcp_opt138_opt224.patch
new file mode 100644
index 0000000000..38e53be78c
--- /dev/null
+++ b/package/utils/busybox/patches/601-dhcp_opt138_opt224.patch
@@ -0,0 +1,20 @@
+--- a/networking/udhcp/common.c 2025-09-18 13:15:38.313248300 +0800
++++ b/networking/udhcp/common.c 2025-09-18 13:17:50.078418978 +0800
+@@ -55,6 +55,8 @@ const struct dhcp_optflag dhcp_optflags[
+ { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */
+ //TODO: not a string, but a set of LASCII strings:
+ // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */
++ { OPTION_IP , 0x8A }, /* DHCP_OPT138 */
++ { OPTION_STRING , 0xE0 }, /* DHCP_OPT224 */
+ { OPTION_STRING , 0x64 }, /* DHCP_PCODE */
+ { OPTION_STRING , 0x65 }, /* DHCP_TCODE */
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+@@ -124,6 +126,8 @@ const char dhcp_option_strings[] ALIGN1
+ "tftp" "\0" /* DHCP_TFTP_SERVER_NAME*/
+ "bootfile" "\0" /* DHCP_BOOT_FILE */
+ // "userclass" "\0" /* DHCP_USER_CLASS */
++ "opt138" "\0" /* DHCP_OPT138 */
++ "opt224" "\0" /* DHCP_OPT224 */
+ "tzstr" "\0" /* DHCP_PCODE */
+ "tzdbstr" "\0" /* DHCP_TCODE */
+ #if ENABLE_FEATURE_UDHCP_RFC3397
--
2.34.1