Compare commits

...

13 Commits

Author SHA1 Message Date
Marek Kwaczynski
fa355af9a2 add mem_monitor.sh script to monitor memomory usage
Signed-off-by: Marek Kwaczynski <marek@shasta.cloud>
2025-10-29 10:12:43 +01:00
Marek Kwaczynski
de43044eb4 ipq807x_v5.4: Enable SLUB_DEBUG
Signed-off-by: Marek Kwaczynski <marek@shasta.cloud>
2025-10-29 09:45:38 +01:00
Marek Kwaczynski
c09c4c9d60 ipq807x_v5.4: Enable kmemleak
Enable KMEMLEAK to find memory leak issue.

Signed-off-by: Marek Kwaczynski <marek@shasta.cloud>
2025-10-29 09:45:08 +01:00
jaspreetsachdev
a15703c413 Merge pull request #936 from Telecominfraproject/for-4.0
ucentral-tools: the git repo is gone, move the code into the package
2025-09-12 11:59:21 -04:00
John Crispin
d218ba64e3 ucentral-tools: the git repo is gone, move the code into the package
Signed-off-by: John Crispin <john@phrozen.org>
2025-09-12 08:17:51 +02:00
jaspreetsachdev
dab5ebd31f Merge pull request #832 from Telecominfraproject/release-4
Release 4
2025-05-02 04:47:18 -07:00
Jaspreet Sachdev
f4d2d3d12a Merge branch 'main' into release-4 2025-05-02 07:42:57 -04:00
John Crispin
adac3818a4 ucentral-schema: update to latest HEAD
52afdf8 fix wifi-scan on wifi-7 devices

Fixes: WIFI-14541
Fixes: WIFI-14537
Signed-off-by: John Crispin <john@phrozen.org>
2025-04-30 08:03:26 +02:00
Ken
a516b035ab qca-wifi-7: WF189 10G PHY code optimization
* add "limit_rtlphy_10g_ablity" in DTS , no side effect on other product.
* disable 10G capability if DTS defined limit_rtlphy_10g_ablity , no side effect on other product.
* revert the last 0006-qca-ssdk-Fix-10G-rtl-phy-driver-for-c45-mdio-read-wr.patch and based on 0005 patch.

Fixes: WIFI-14567
Signed-off-by: Ken Shi <xshi@actiontec.com>
2025-04-29 08:25:22 +02:00
Ken
29b088ef21 qca-wifi-7: fix WF189 WAN port link issues
Fixes: WIFI-14546
Signed-off-by: Ken <xshi@actiontec.com>
2025-04-28 17:06:48 +02:00
John Crispin
10b875d42c ucentral-schema: update to latest HEAD
3b88fc1 dhcp_inject: Multiple ssids sometime didn't display dhcp option 82 rules

Fixes: WIFI-14564
Signed-off-by: John Crispin <john@phrozen.org>
2025-04-28 12:35:34 +02:00
alex18_huang
1f0a24a941 udhcpinject: Multiple ssids sometime didn't display dhcp option 82 rules
Added check when parsing ssid info retrieved from iwinfo.
Program will exit if expected interface count and iwinfo entry count mismatch.

Fixes: WIFI-14564
Signed-off-by: alex18_huang <alex18_huang@accton.com>
2025-04-28 12:33:00 +02:00
jaspreetsachdev
4c9b22f999 Merge pull request #815 from Telecominfraproject/release-4
Release 4
2025-04-11 10:58:12 -04:00
18 changed files with 2805 additions and 27 deletions

View File

@@ -341,7 +341,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_EFI is not set
CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
# CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN is not set
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=n
CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000
CONFIG_DEBUG_KMEMLEAK_TEST=m
CONFIG_SLUB_DEBUG=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
# CONFIG_DEBUG_MISC is not set
# CONFIG_DEBUG_PLIST is not set

View File

@@ -342,7 +342,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_EFI is not set
CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
# CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN is not set
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=n
CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000
CONFIG_DEBUG_KMEMLEAK_TEST=m
CONFIG_SLUB_DEBUG=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
# CONFIG_DEBUG_MISC is not set
# CONFIG_DEBUG_PLIST is not set

View File

@@ -342,7 +342,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_EFI is not set
CONFIG_DEBUG_GPIO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
# CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN is not set
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=n
CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000
CONFIG_DEBUG_KMEMLEAK_TEST=m
CONFIG_SLUB_DEBUG=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
# CONFIG_DEBUG_MISC is not set
# CONFIG_DEBUG_PLIST is not set

View File

@@ -44,9 +44,11 @@
uniphyaddr_fixup = <0xC90F014>;
mdio_clk_fixup; /* MDIO clock sequence fix up flag */
tip,clk_div = <0xff>; /* MDIO Frequency reduction*/
limit_rtlphy_10g_ablity;
phy0: ethernet-phy@0 {
reg = <8>;
compatible ="ethernet-phy-ieee802.3-c45";
};
phy1: ethernet-phy@1 {

View File

@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/delay.h>
#include <linux/of.h>
#include "phy_rtl826xb_patch.h"
#include "phy_rtl8251b_patch.h"
@@ -30,6 +31,7 @@ static int rtl8251_match_phy_device(struct phy_device *phydev)
static int rtl826xb_get_features(struct phy_device *phydev)
{
int ret;
struct device_node *np;
ret = genphy_c45_pma_read_abilities(phydev);
if (ret)
return ret;
@@ -48,6 +50,14 @@ static int rtl826xb_get_features(struct phy_device *phydev)
linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
phydev->supported);
np = of_find_node_by_name(NULL, "mdio");
if (np)
if (of_property_read_bool(np, "limit_rtlphy_10g_ablity"))
{
linkmode_clear_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, phydev->supported);
}
return 0;
}
@@ -80,7 +90,6 @@ static int rtkphy_config_init(struct phy_device *phydev)
case REALTEK_PHY_ID_RTL8261N:
case REALTEK_PHY_ID_RTL8264B:
phydev_info(phydev, "%s:%u [RTL8261N/RTL826XB] phy_id: 0x%X PHYAD:%d\n", __FUNCTION__, __LINE__, phydev->drv->phy_id, phydev->mdio.addr);
phy_modify_mmd_changed(phydev, 7, 0x20, BIT(12), 0);
#if 1 /* toggle reset */
phy_modify_mmd_changed(phydev, 30, 0x145, BIT(0) , 1);
@@ -213,7 +222,6 @@ static int rtkphy_c45_aneg_done(struct phy_device *phydev)
static int rtkphy_c45_read_status(struct phy_device *phydev)
{
int ret = 0, status = 0;
uint16_t local;
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
@@ -232,9 +240,6 @@ static int rtkphy_c45_read_status(struct phy_device *phydev)
if (ret)
return ret;
phy_write_mmd(phydev, 7, 0x20, 0x181);
local = phy_read_mmd(phydev, 7, 0x20);
status = phy_read_mmd(phydev, 31, 0xA414);
if (status < 0)
return status;
@@ -242,11 +247,6 @@ static int rtkphy_c45_read_status(struct phy_device *phydev)
phydev->lp_advertising, status & BIT(11));
phy_resolve_aneg_linkmode(phydev);
if((phydev->speed == 10000) && (local == 0x181))
{
phydev->speed = 5000;
phydev->duplex = DUPLEX_FULL;
}
}
else
{

View File

@@ -0,0 +1,116 @@
From 85a7c62d4e3385de1a379959dd45148cfdc95b3b Mon Sep 17 00:00:00 2001
From: huangyunxiang <huangyunxiang@cigtech.com>
Date: Tue, 29 Apr 2025 09:56:28 +0800
Subject: [PATCH] qca-ssdk modify rtl826x phy mdio read/write as c45 mode and
clear 10G ablity
---
src/hsl/phy/rtl826xb_phy.c | 55 ++++++-------------
1 file changed, 17 insertions(+), 38 deletions(-)
diff --git a/src/hsl/phy/rtl826xb_phy.c b/src/hsl/phy/rtl826xb_phy.c
index a336348aa9..9a67b45948 100644
--- a/src/hsl/phy/rtl826xb_phy.c
+++ b/src/hsl/phy/rtl826xb_phy.c
@@ -48,46 +48,39 @@ void rtl826xb_phy_lock_init(void)
static a_uint16_t rtl826x_phy_mmd_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_mmd, a_uint16_t reg_id)
{
- a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(reg_mmd, reg_id);
-
- return __hsl_phy_mii_reg_read(dev_id, phy_id, reg_id_c45);
+ return hsl_phy_mmd_reg_read(dev_id, phy_id, A_TRUE, reg_mmd, reg_id);
}
static sw_error_t rtl826x_phy_mmd_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_mmd, a_uint16_t reg_id, a_uint16_t reg_val)
{
- a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(reg_mmd, reg_id);
-
- return __hsl_phy_mii_reg_write(dev_id, phy_id, reg_id_c45, reg_val);
+ return hsl_phy_mmd_reg_write(dev_id, phy_id, A_TRUE, reg_mmd, reg_id, reg_val);
}
static a_uint16_t rtl826x_phy_reg_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg)
{
- return __hsl_phy_mii_reg_read(dev_id, phy_id, reg);
+ return hsl_phy_mii_reg_read(dev_id, phy_id, reg);
}
static sw_error_t rtl826x_phy_reg_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg, a_uint16_t reg_val)
{
- return __hsl_phy_mii_reg_write(dev_id, phy_id, reg, reg_val);
+
+ return hsl_phy_mii_reg_write(dev_id, phy_id, reg, reg_val);
}
static a_int16_t hal_miim_mmd_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t mmdAddr, a_uint16_t mmdReg)
{
- a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(mmdAddr, mmdReg);
-
- return __hsl_phy_mii_reg_read(dev_id, phy_id, reg_id_c45);
+ return hsl_phy_mmd_reg_read(dev_id, phy_id, A_TRUE, mmdAddr, mmdReg);
}
static a_int32_t hal_miim_mmd_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t mmdAddr, a_uint16_t mmdReg, a_uint16_t phy_data)
{
- a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(mmdAddr, mmdReg);
-
- return __hsl_phy_mii_reg_write(dev_id, phy_id, reg_id_c45, phy_data);
+ return hsl_phy_mmd_reg_write(dev_id, phy_id, A_TRUE, mmdAddr, mmdReg, phy_data);
}
@@ -1281,34 +1274,20 @@ phy_826xb_autoNegoAbility_set(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t a
hsl_phy_phydev_autoneg_update(dev_id, phy_id, A_TRUE, autoneg);
phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 16);
+ phyData &= (~(0x0020 | 0x0040 | FAL_PHY_ADV_100TX_HD | FAL_PHY_ADV_100TX_FD | FAL_PHY_ADV_PAUSE | FAL_PHY_ADV_ASY_PAUSE));
+ phyData |= (autoneg & FAL_PHY_ADV_100TX_HD) ? (FAL_PHY_ADV_100TX_HD) : (0);
+ phyData |= ((autoneg & FAL_PHY_ADV_100TX_FD)) ? (FAL_PHY_ADV_100TX_FD) : (0);
- phyData &= (~(0x0020 | 0x0040 | 0x0080 | 0x0100 | 0x0400 | 0x0800));
- phyData |= ((autoneg & 1 << 1)) ? (0x0040) : (0);
- phyData |= ((autoneg & 1 << 2)) ? (0x0080) : (0);
- phyData |= ((autoneg & 1 << 3)) ? (0x0100) : (0);
- phyData |= ((autoneg & 1 << 4)) ? (0x0400) : (0);
- phyData |= ((autoneg & 1 << 5)) ? (0x0800) : (0);
-// phyData |= ((autoneg & 1 << 9)) ? (0x0400) : (0);
-// phyData |= ((autoneg & 1 << 10)) ? (0x0800) : (0);
-
- phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 16, phyData);
-
+ phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 16, phyData);
phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 32);
+ phyData &= (~(FAL_PHY_ADV_2500T_FD | FAL_PHY_ADV_5000T_FD | FAL_PHY_ADV_10000T_FD));
+ phyData |= (autoneg & FAL_PHY_ADV_2500T_FD) ? (FAL_PHY_ADV_2500T_FD) : (0);
+ phyData |= (autoneg & FAL_PHY_ADV_5000T_FD) ? (FAL_PHY_ADV_5000T_FD) : (0);
- phyData &= (~(0x4000 | 0x2000 | 0x1000));
- phyData |= (autoneg & 1 << 12) ? (0x0080) : (0);
- phyData |= (autoneg & 1 << 13) ? (0x0100) : (0);
- phyData |= (autoneg & 1 << 14) ? (0x1000) : (0);
-
- phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 32, phyData);
-
-
+ phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 32, phyData);
phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_VEND2, 0xA412);
-
-
- phyData &= (~(0x0100 | 0x0200));
- phyData |= (autoneg & 1 << 9) ? (0x0200) : (0);
-// phyData |= (autoneg & 1 << 5) ? (0x0200) : (0);
+ phyData &= (~(0x0100 | FAL_PHY_ADV_1000T_FD));
+ phyData |= (autoneg & FAL_PHY_ADV_1000T_FD) ? (FAL_PHY_ADV_1000T_FD) : (0);
phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_VEND2, 0xA412, phyData);
--
2.34.1

View File

@@ -0,0 +1,324 @@
#!/bin/sh
PRIMARY_DIR="/root/mem_usage"
PRIMARY_FALLBACK_DIR="/tmp/mem_usage_live"
ARCHIVE_DIR="/tmp/mem_usage"
ARCHIVE_TMP_DIR="/tmp/mem_usage_tmp"
# thresholds
PRIMARY_MAX_BYTES=$((3 * 1024 * 1024)) # 3 MB
ARCHIVE_MAX_BYTES=$((15 * 1024 * 1024)) # 15 MB
RETENTION_DAYS=7 # remove archives older than this
SLEEP_INTERVAL=10 # 15 minutes between collections
KMEMLEAK_IFACE="/sys/kernel/debug/kmemleak"
# Ensure primary dir writable, otherwise fallback
if [ ! -d "$PRIMARY_DIR" ] || [ ! -w "$PRIMARY_DIR" ]; then
mkdir -p "$PRIMARY_DIR" 2>/dev/null || true
fi
if [ ! -d "$PRIMARY_DIR" ] || [ ! -w "$PRIMARY_DIR" ]; then
PRIMARY_DIR="$PRIMARY_FALLBACK_DIR"
mkdir -p "$PRIMARY_DIR" 2>/dev/null || true
fi
# Ensure archive dir exists
mkdir -p "$ARCHIVE_DIR" 2>/dev/null || true
mkdir -p "$ARCHIVE_TMP_DIR" 2>/dev/null || true
mkdir -p "$PRIMARY_DIR" 2>/dev/null || true
# Host identity
MAC="$(uci get system.@system[0].hostname)"
MAC="${MAC:-}"
log() { printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >&2; }
dir_size_bytes() {
t="$1"
if [ ! -d "$t" ]; then echo 0; return 0; fi
kb=$(du -s "$t" 2>/dev/null | awk '{print $1}')
if [ -z "$kb" ]; then echo 0; else echo $((kb * 1024)); fi
}
# Ensure archive total size <= ARCHIVE_MAX_BYTES by deleting oldest tar.gz
enforce_archive_size_limit() {
[ -d "$ARCHIVE_DIR" ] || return 0
total=$(dir_size_bytes "$ARCHIVE_DIR")
if [ "$total" -le "$ARCHIVE_MAX_BYTES" ]; then return 0; fi
ls -1tr -- "$ARCHIVE_DIR"/*.tar.gz 2>/dev/null | while IFS= read -r af; do
if [ -z "$af" ]; then break; fi
rm -f -- "$af" && log "INFO: removed oldest archive $af to free space"
total=$(dir_size_bytes "$ARCHIVE_DIR")
if [ "$total" -le "$ARCHIVE_MAX_BYTES" ]; then break; fi
done
}
# Create a single tarball containing ALL files from PRIMARY_DIR and move to ARCHIVE_DIR.
tar_all_primary_now() {
ts=$(date +%Y%m%d_%H%M%S)
tar_name="memtracker_all_${ts}.tar.gz"
tmp_tar="${ARCHIVE_TMP_DIR}/${tar_name}.partial.$$"
tar_err="${ARCHIVE_TMP_DIR}/tar_err_all.$$"
if [ ! -d "$PRIMARY_DIR" ]; then
echo "ERROR: PRIMARY_DIR '$PRIMARY_DIR' missing" >&2
return 1
fi
set -- "$PRIMARY_DIR"/*
if [ ! -e "$1" ]; then
echo "DEBUG: no files in $PRIMARY_DIR to archive" >&2
return 2
fi
(
cd "$PRIMARY_DIR" || { echo "ERROR: cannot cd $PRIMARY_DIR" >&2; exit 3; }
if ! tar -czf "$tmp_tar" . 2>"$tar_err"; then
echo "ERROR: tar failed (see $tar_err)" >&2
[ -f "$tmp_tar" ] && rm -f "$tmp_tar"
exit 4
fi
exit 0
)
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
if [ ! -d "$ARCHIVE_DIR" ]; then
mkdir -p "$ARCHIVE_DIR" 2>/dev/null || {
echo "WARN: cannot create ARCHIVE_DIR $ARCHIVE_DIR; leaving tar in $ARCHIVE_TMP_DIR" >&2
mv -f "$tmp_tar" "${ARCHIVE_TMP_DIR}/${tar_name}" 2>/dev/null || true
return 5
}
fi
if mv -f "$tmp_tar" "$ARCHIVE_DIR/$tar_name" 2>/dev/null; then
sync || true
find "$PRIMARY_DIR" -maxdepth 1 -type f -print0 2>/dev/null |
while IFS= read -r -d '' src; do rm -f -- "$src"; done
echo "INFO: archived all -> $ARCHIVE_DIR/$tar_name" >&2
return 0
fi
if cp -f "$tmp_tar" "$ARCHIVE_DIR/$tar_name" 2>/dev/null; then
sync || true
rm -f "$tmp_tar"
find "$PRIMARY_DIR" -maxdepth 1 -type f -print0 2>/dev/null |
while IFS= read -r -d '' src; do rm -f -- "$src"; done
echo "INFO: copied archive -> $ARCHIVE_DIR/$tar_name (fallback)" >&2
return 0
fi
mv -f "$tmp_tar" "${ARCHIVE_TMP_DIR}/${tar_name}" 2>/dev/null || true
echo "WARN: failed to move/copy $tar_name to $ARCHIVE_DIR; kept ${ARCHIVE_TMP_DIR}/${tar_name}" >&2
return 6
}
collect_meminfo() {
ts=$(date +%Y%m%d_%H%M%S)
out="$PRIMARY_DIR/meminfo_${ts}.csv"
if [ ! -r /proc/meminfo ]; then
echo "ERROR: Cannot read /proc/meminfo" >&2
return 1
fi
{
# header
printf "timestamp,mac"
awk '{gsub(":", "", $1); printf ",%s", $1}' /proc/meminfo
printf "\n"
# row of values
printf "%s,%s" "$ts" "$MAC"
awk '{printf ",%s", $2}' /proc/meminfo
printf "\n"
} > "$out"
echo "Collected meminfo -> $out"
}
collect_slabinfo() {
ts=$(date +%Y%m%d_%H%M%S)
out="$PRIMARY_DIR/slabinfo_${ts}.csv"
[ -r /proc/slabinfo ] || { echo "ERROR: Cannot read /proc/slabinfo" >&2; return 1; }
awk -v ts="$ts" -v mac="$MAC" '
BEGIN {
OFS = ","
ncount = 0
}
/^slabinfo/ { next }
/^#/ { next }
{
line = $0
# split into up to 3 parts by ":" (some lines contain two ":" separators)
parts_count = split(line, parts, ":")
# trim leading/trailing whitespace from parts[1]
gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[1])
# parse first segment tokens (name + first numeric columns)
toks0_count = split(parts[1], t0, /[[:space:]]+/)
name_raw = (toks0_count >= 1 ? t0[1] : "")
# sanitize name to be CSV-safe
name = name_raw
gsub(/[^A-Za-z0-9_]/, "_", name)
active = (toks0_count >= 2 ? t0[2] : 0)
num_objs = (toks0_count >= 3 ? t0[3] : 0)
objsize = (toks0_count >= 4 ? t0[4] : 0)
objperslab = (toks0_count >= 5 ? t0[5] : 0)
#pagesperslab= (toks0_count >= 6 ? t0[6] : 0)
# tunables: parse parts[2] if present
tun_limit = tun_batch = tun_shared = 0
if (parts_count >= 2) {
# trim whitespace
gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[2])
ni = split(parts[2], t1, /[[:space:]]+/)
# pick last 3 numeric tokens (limit, batchcount, sharedfactor)
cnt = 0
for (i = ni; i >= 1 && cnt < 3; i--) {
if (t1[i] ~ /^[0-9]+$/) {
if (cnt == 0) tun_shared = t1[i]
else if (cnt == 1) tun_batch = t1[i]
else if (cnt == 2) tun_limit = t1[i]
cnt++
}
}
}
# slabdata: usually parts[3]; if missing, it may be in parts[2] - we try parts[3] first
active_slabs = num_slabs = sharedavail = 0
if (parts_count >= 3) {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[3])
ni2 = split(parts[3], t2, /[[:space:]]+/)
cnt2 = 0
for (i = ni2; i >= 1 && cnt2 < 3; i--) {
if (t2[i] ~ /^[0-9]+$/) {
if (cnt2 == 0) sharedavail = t2[i]
else if (cnt2 == 1) num_slabs = t2[i]
else if (cnt2 == 2) active_slabs = t2[i]
cnt2++
}
}
} else if (parts_count == 2) {
# fallback: try to extract slabdata numeric suffix from parts[2]
ni2 = split(parts[2], t2, /[[:space:]]+/)
cnt2 = 0
for (i = ni2; i >= 1 && cnt2 < 3; i--) {
if (t2[i] ~ /^[0-9]+$/) {
if (cnt2 == 0) sharedavail = t2[i]
else if (cnt2 == 1) num_slabs = t2[i]
else if (cnt2 == 2) active_slabs = t2[i]
cnt2++
}
}
}
# store values
names[++ncount] = name
vals[name, "active"] = active
vals[name, "num_objs"] = num_objs
vals[name, "objsize"] = objsize
#vals[name, "objperslab"] = objperslab
#vals[name, "pagesperslab"] = pagesperslab
#vals[name, "tun_limit"] = tun_limit
#vals[name, "tun_batch"] = tun_batch
#vals[name, "tun_shared"] = tun_shared
#vals[name, "active_slabs"] = active_slabs
#vals[name, "num_slabs"] = num_slabs
#vals[name, "sharedavail"] = sharedavail
}
END {
# Header
printf "timestamp%smac", OFS
for (i = 1; i <= ncount; i++) {
nm = names[i]
printf "%s%s_active", OFS, nm
printf "%s%s_num_objs", OFS, nm
printf "%s%s_objsize", OFS, nm
#printf "%s%s_objperslab", OFS, nm
#printf "%s%s_pagesperslab", OFS, nm
#printf "%s%s_tun_limit", OFS, nm
#printf "%s%s_tun_batch", OFS, nm
#printf "%s%s_tun_shared", OFS, nm
#printf "%s%s_active_slabs", OFS, nm
#printf "%s%s_num_slabs", OFS, nm
#printf "%s%s_sharedavail", OFS, nm
}
printf "\n"
# Values row
printf "%s%s%s", ts, OFS, mac
for (i = 1; i <= ncount; i++) {
nm = names[i]
printf "%s%s", OFS, (vals[nm, "active"] != "" ? vals[nm, "active"] : 0)
printf "%s%s", OFS, (vals[nm, "num_objs"] != "" ? vals[nm, "num_objs"] : 0)
printf "%s%s", OFS, (vals[nm, "objsize"] != "" ? vals[nm, "objsize"] : 0)
#printf "%s%s", OFS, (vals[nm, "objperslab"] != "" ? vals[nm, "objperslab"] : 0)
#printf "%s%s", OFS, (vals[nm, "pagesperslab"] != "" ? vals[nm, "pagesperslab"] : 0)
#printf "%s%s", OFS, (vals[nm, "tun_limit"] != "" ? vals[nm, "tun_limit"] : 0)
#printf "%s%s", OFS, (vals[nm, "tun_batch"] != "" ? vals[nm, "tun_batch"] : 0)
#printf "%s%s", OFS, (vals[nm, "tun_shared"] != "" ? vals[nm, "tun_shared"] : 0)
#printf "%s%s", OFS, (vals[nm, "active_slabs"] != "" ? vals[nm, "active_slabs"] : 0)
#printf "%s%s", OFS, (vals[nm, "num_slabs"] != "" ? vals[nm, "num_slabs"] : 0)
#printf "%s%s", OFS, (vals[nm, "sharedavail"] != "" ? vals[nm, "sharedavail"] : 0)
}
printf "\n"
}' /proc/slabinfo > "$out" 2>/dev/null || { echo "ERROR: slabinfo parsing failed" >&2; return 2; }
echo "Collected slabinfo -> $out"
return 0
}
collect_kmemleak() {
ts=$(date +%Y%m%d_%H%M%S)
out="$PRIMARY_DIR/kmemleak_${ts}.txt"
if [ ! -d "$(dirname "$KMEMLEAK_IFACE")" ] || [ ! -e "$KMEMLEAK_IFACE" ]; then
echo "WARN: kmemleak interface not present at $KMEMLEAK_IFACE" >&2
return 1
fi
# Trigger kernel scan (best-effort; may require root)
if [ -w "$KMEMLEAK_IFACE" ]; then
# echo "scan" returns nothing; do it in a safe way
echo scan > "$KMEMLEAK_IFACE" 2>/dev/null || true
# small pause to let kernel produce a report (optional)
sleep 1
fi
# Save the current kmemleak output (read-only)
if [ -r "$KMEMLEAK_IFACE" ]; then
# prefix with timestamp for clarity
printf 'kmemleak snapshot: %s\n\n' "$ts" > "$out"
cat "$KMEMLEAK_IFACE" >> "$out" 2>/dev/null || true
sync || true
echo "Collected kmemleak -> $out"
return 0
else
echo "ERROR: cannot read $KMEMLEAK_IFACE" >&2
return 2
fi
}
log "Starting mem_monitor. PRIMARY_DIR=$PRIMARY_DIR ARCHIVE_DIR=$ARCHIVE_DIR"
while true; do
collect_meminfo
collect_slabinfo
collect_kmemleak
prim_size=$(du -s "$PRIMARY_DIR" 2>/dev/null | awk '{print $1}')
prim_size=$(( prim_size * 1024 )) # convert KB to bytes
if [ "$prim_size" -ge "$PRIMARY_MAX_BYTES" ]; then
echo "DEBUG: PRIMARY threshold reached: ${prim_size} bytes >= ${PRIMARY_MAX_BYTES}" >&2
tar_all_primary_now || echo "WARN: tar_all_primary_now returned $?" >&2
fi
enforce_archive_size_limit
sleep "$SLEEP_INTERVAL"
done

View File

@@ -4,10 +4,10 @@ PKG_NAME:=ucentral-schema
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-schema.git
PKG_MIRROR_HASH:=cd070141672c85e72001e2e36616aa7159c6dc8ca4bbacca1b61a41c145cde2f
PKG_MIRROR_HASH:=280d87658fa36c1d5d6852dcb8203042eba6bbc9101ac317a2088e2dd68249da
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2025-01-27
PKG_SOURCE_VERSION:=048a53d4a6cf3ef570dab9e2d10989844ae7c355
PKG_SOURCE_VERSION:=52afdf8f1d1cb8445b6b56eba3768d0edffa63e1
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -3,12 +3,6 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=ucentral-tools
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-tools.git
PKG_MIRROR_HASH:=9ae6a0cd431595871c233550427c4043c2ba7ddb3c5d87e46ab74a03b2b5a947
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2021-01-28
PKG_SOURCE_VERSION:=b013fc636e48d407870a46aaa68a09ed74de8d6f
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 2.6)
PROJECT(openwifi-tools C)
INCLUDE(GNUInstallDirs)
ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
ADD_EXECUTABLE(firstcontact firstcontact.c)
TARGET_LINK_LIBRARIES(firstcontact curl crypto ssl ubox)
INSTALL(TARGETS firstcontact
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)
ADD_EXECUTABLE(dhcpdiscover dhcpdiscover.c)
INSTALL(TARGETS dhcpdiscover
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)
ADD_EXECUTABLE(dnsprobe dnsprobe.c)
TARGET_LINK_LIBRARIES(dnsprobe ubox resolv)
INSTALL(TARGETS dnsprobe
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)
ADD_EXECUTABLE(radiusprobe radiusprobe.c)
TARGET_LINK_LIBRARIES(radiusprobe radcli)
INSTALL(TARGETS radiusprobe
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)
ADD_EXECUTABLE(ip-collide ip-collide.c)
TARGET_LINK_LIBRARIES(ip-collide ubox)
INSTALL(TARGETS ip-collide
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,690 @@
/*
* nslookup_lede - musl compatible replacement for busybox nslookup
*
* Copyright (C) 2017 Jo-Philipp Wich <jo@mein.io>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//config:config NSLOOKUP_OPENWRT
//config: bool "nslookup_openwrt"
//config: depends on !NSLOOKUP
//config: default y
//config: help
//config: nslookup is a tool to query Internet name servers (LEDE flavor).
//config:
//config:config FEATURE_NSLOOKUP_OPENWRT_LONG_OPTIONS
//config: bool "Enable long options"
//config: default y
//config: depends on NSLOOKUP_OPENWRT && LONG_OPTS
//config: help
//config: Support long options for the nslookup applet.
//applet:IF_NSLOOKUP_OPENWRT(APPLET(nslookup, BB_DIR_USR_BIN, BB_SUID_DROP))
//kbuild:lib-$(CONFIG_NSLOOKUP_OPENWRT) += nslookup_lede.o
//usage:#define nslookup_lede_trivial_usage
//usage: "[HOST] [SERVER]"
//usage:#define nslookup_lede_full_usage "\n\n"
//usage: "Query the nameserver for the IP address of the given HOST\n"
//usage: "optionally using a specified DNS server"
//usage:
//usage:#define nslookup_lede_example_usage
//usage: "$ nslookup localhost\n"
//usage: "Server: default\n"
//usage: "Address: default\n"
//usage: "\n"
//usage: "Name: debian\n"
//usage: "Address: 127.0.0.1\n"
#include <stdio.h>
#include <resolv.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <poll.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#include <libubox/ulog.h>
#define ENABLE_FEATURE_IPV6 1
typedef struct len_and_sockaddr {
socklen_t len;
union {
struct sockaddr sa;
struct sockaddr_in sin;
#if ENABLE_FEATURE_IPV6
struct sockaddr_in6 sin6;
#endif
} u;
} len_and_sockaddr;
struct ns {
const char *name;
len_and_sockaddr addr;
int failures;
int replies;
};
struct query {
const char *name;
size_t qlen, rlen;
unsigned char query[512], reply[512];
unsigned long latency;
int rcode, n_ns;
};
static const char *rcodes[] = {
"NOERROR",
"FORMERR",
"SERVFAIL",
"NXDOMAIN",
"NOTIMP",
"REFUSED",
"YXDOMAIN",
"YXRRSET",
"NXRRSET",
"NOTAUTH",
"NOTZONE",
"RESERVED11",
"RESERVED12",
"RESERVED13",
"RESERVED14",
"RESERVED15",
"BADVERS"
};
static unsigned int default_port = 53;
static unsigned int default_retry = 1;
static unsigned int default_timeout = 2;
static int parse_reply(const unsigned char *msg, size_t len, int *bb_style_counter)
{
ns_msg handle;
ns_rr rr;
int i, n, rdlen;
const char *format = NULL;
char astr[INET6_ADDRSTRLEN], dname[MAXDNAME];
const unsigned char *cp;
if (ns_initparse(msg, len, &handle) != 0) {
//fprintf(stderr, "Unable to parse reply: %s\n", strerror(errno));
return -1;
}
for (i = 0; i < ns_msg_count(handle, ns_s_an); i++) {
if (ns_parserr(&handle, ns_s_an, i, &rr) != 0) {
//fprintf(stderr, "Unable to parse resource record: %s\n", strerror(errno));
return -1;
}
rdlen = ns_rr_rdlen(rr);
switch (ns_rr_type(rr))
{
case ns_t_a:
if (rdlen != 4) {
//fprintf(stderr, "Unexpected A record length\n");
return -1;
}
inet_ntop(AF_INET, ns_rr_rdata(rr), astr, sizeof(astr));
printf("Name:\t%s\nAddress: %s\n", ns_rr_name(rr), astr);
break;
#if ENABLE_FEATURE_IPV6
case ns_t_aaaa:
if (rdlen != 16) {
//fprintf(stderr, "Unexpected AAAA record length\n");
return -1;
}
inet_ntop(AF_INET6, ns_rr_rdata(rr), astr, sizeof(astr));
printf("%s\thas AAAA address %s\n", ns_rr_name(rr), astr);
break;
#endif
case ns_t_ns:
if (!format)
format = "%s\tnameserver = %s\n";
/* fall through */
case ns_t_cname:
if (!format)
format = "%s\tcanonical name = %s\n";
/* fall through */
case ns_t_ptr:
if (!format)
format = "%s\tname = %s\n";
if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
ns_rr_rdata(rr), dname, sizeof(dname)) < 0) {
//fprintf(stderr, "Unable to uncompress domain: %s\n", strerror(errno));
return -1;
}
printf(format, ns_rr_name(rr), dname);
break;
case ns_t_mx:
if (rdlen < 2) {
fprintf(stderr, "MX record too short\n");
return -1;
}
n = ns_get16(ns_rr_rdata(rr));
if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
ns_rr_rdata(rr) + 2, dname, sizeof(dname)) < 0) {
//fprintf(stderr, "Cannot uncompress MX domain: %s\n", strerror(errno));
return -1;
}
printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, dname);
break;
case ns_t_txt:
if (rdlen < 1) {
//fprintf(stderr, "TXT record too short\n");
return -1;
}
n = *(unsigned char *)ns_rr_rdata(rr);
if (n > 0) {
memset(dname, 0, sizeof(dname));
memcpy(dname, ns_rr_rdata(rr) + 1, n);
printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), dname);
}
break;
case ns_t_soa:
if (rdlen < 20) {
//fprintf(stderr, "SOA record too short\n");
return -1;
}
printf("%s\n", ns_rr_name(rr));
cp = ns_rr_rdata(rr);
n = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
cp, dname, sizeof(dname));
if (n < 0) {
//fprintf(stderr, "Unable to uncompress domain: %s\n", strerror(errno));
return -1;
}
printf("\torigin = %s\n", dname);
cp += n;
n = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
cp, dname, sizeof(dname));
if (n < 0) {
//fprintf(stderr, "Unable to uncompress domain: %s\n", strerror(errno));
return -1;
}
printf("\tmail addr = %s\n", dname);
cp += n;
printf("\tserial = %lu\n", ns_get32(cp));
cp += 4;
printf("\trefresh = %lu\n", ns_get32(cp));
cp += 4;
printf("\tretry = %lu\n", ns_get32(cp));
cp += 4;
printf("\texpire = %lu\n", ns_get32(cp));
cp += 4;
printf("\tminimum = %lu\n", ns_get32(cp));
break;
default:
break;
}
}
return i;
}
static int parse_nsaddr(const char *addrstr, len_and_sockaddr *lsa)
{
char *eptr, *hash, ifname[IFNAMSIZ];
unsigned int port = default_port;
unsigned int scope = 0;
hash = strchr(addrstr, '#');
if (hash) {
*hash++ = '\0';
port = strtoul(hash, &eptr, 10);
if (eptr == hash || *eptr != '\0' || port > 65535) {
errno = EINVAL;
return -1;
}
}
hash = strchr(addrstr, '%');
if (hash) {
for (eptr = ++hash; *eptr != '\0' && *eptr != '#'; eptr++) {
if ((eptr - hash) >= IFNAMSIZ) {
errno = ENODEV;
return -1;
}
ifname[eptr - hash] = *eptr;
}
ifname[eptr - hash] = '\0';
scope = if_nametoindex(ifname);
if (scope == 0) {
errno = ENODEV;
return -1;
}
}
#if ENABLE_FEATURE_IPV6
if (inet_pton(AF_INET6, addrstr, &lsa->u.sin6.sin6_addr)) {
lsa->u.sin6.sin6_family = AF_INET6;
lsa->u.sin6.sin6_port = htons(port);
lsa->u.sin6.sin6_scope_id = scope;
lsa->len = sizeof(lsa->u.sin6);
return 0;
}
#endif
if (!scope && inet_pton(AF_INET, addrstr, &lsa->u.sin.sin_addr)) {
lsa->u.sin.sin_family = AF_INET;
lsa->u.sin.sin_port = htons(port);
lsa->len = sizeof(lsa->u.sin);
return 0;
}
errno = EINVAL;
return -1;
}
static unsigned long mtime(void)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (unsigned long)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}
#if ENABLE_FEATURE_IPV6
static void to_v4_mapped(len_and_sockaddr *a)
{
if (a->u.sa.sa_family != AF_INET)
return;
memcpy(a->u.sin6.sin6_addr.s6_addr + 12,
&a->u.sin.sin_addr, 4);
memcpy(a->u.sin6.sin6_addr.s6_addr,
"\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
a->u.sin6.sin6_family = AF_INET6;
a->u.sin6.sin6_flowinfo = 0;
a->u.sin6.sin6_scope_id = 0;
a->len = sizeof(a->u.sin6);
}
#endif
/*
* Function logic borrowed & modified from musl libc, res_msend.c
*/
static int send_queries(struct ns *ns, int n_ns, struct query *queries, int n_queries)
{
int fd;
int timeout = default_timeout * 1000, retry_interval, servfail_retry = 0;
len_and_sockaddr from = { };
#if ENABLE_FEATURE_IPV6
int one = 1;
#endif
int recvlen = 0;
int n_replies = 0;
struct pollfd pfd;
unsigned long t0, t1, t2;
int nn, qn, next_query = 0;
from.u.sa.sa_family = AF_INET;
from.len = sizeof(from.u.sin);
#if ENABLE_FEATURE_IPV6
for (nn = 0; nn < n_ns; nn++) {
if (ns[nn].addr.u.sa.sa_family == AF_INET6) {
from.u.sa.sa_family = AF_INET6;
from.len = sizeof(from.u.sin6);
break;
}
}
#endif
/* Get local address and open/bind a socket */
fd = socket(from.u.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
#if ENABLE_FEATURE_IPV6
/* Handle case where system lacks IPv6 support */
if (fd < 0 && from.u.sa.sa_family == AF_INET6 && errno == EAFNOSUPPORT) {
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
from.u.sa.sa_family = AF_INET;
}
#endif
if (fd < 0)
return -1;
if (bind(fd, &from.u.sa, from.len) < 0) {
close(fd);
return -1;
}
#if ENABLE_FEATURE_IPV6
/* Convert any IPv4 addresses in a mixed environment to v4-mapped */
if (from.u.sa.sa_family == AF_INET6) {
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
for (nn = 0; nn < n_ns; nn++)
to_v4_mapped(&ns[nn].addr);
}
#endif
pfd.fd = fd;
pfd.events = POLLIN;
retry_interval = timeout / default_retry;
t0 = t2 = mtime();
t1 = t2 - retry_interval;
for (; t2 - t0 < timeout; t2 = mtime()) {
if (t2 - t1 >= retry_interval) {
for (qn = 0; qn < n_queries; qn++) {
if (queries[qn].rlen)
continue;
for (nn = 0; nn < n_ns; nn++) {
sendto(fd, queries[qn].query, queries[qn].qlen,
MSG_NOSIGNAL, &ns[nn].addr.u.sa, ns[nn].addr.len);
}
}
t1 = t2;
servfail_retry = 2 * n_queries;
}
/* Wait for a response, or until time to retry */
if (poll(&pfd, 1, t1+retry_interval-t2) <= 0)
continue;
while (1) {
recvlen = recvfrom(fd, queries[next_query].reply,
sizeof(queries[next_query].reply), 0,
&from.u.sa, &from.len);
/* read error */
if (recvlen < 0)
break;
/* Ignore non-identifiable packets */
if (recvlen < 4)
continue;
/* Ignore replies from addresses we didn't send to */
for (nn = 0; nn < n_ns; nn++)
if (memcmp(&from.u.sa, &ns[nn].addr.u.sa, from.len) == 0)
break;
if (nn >= n_ns)
continue;
/* Find which query this answer goes with, if any */
for (qn = next_query; qn < n_queries; qn++)
if (!memcmp(queries[next_query].reply, queries[qn].query, 2))
break;
if (qn >= n_queries || queries[qn].rlen)
continue;
queries[qn].rcode = queries[next_query].reply[3] & 15;
queries[qn].latency = mtime() - t0;
queries[qn].n_ns = nn;
ns[nn].replies++;
/* Only accept positive or negative responses;
* retry immediately on server failure, and ignore
* all other codes such as refusal. */
switch (queries[qn].rcode) {
case 0:
case 3:
break;
case 2:
if (servfail_retry && servfail_retry--) {
ns[nn].failures++;
sendto(fd, queries[qn].query, queries[qn].qlen,
MSG_NOSIGNAL, &ns[nn].addr.u.sa, ns[nn].addr.len);
}
/* fall through */
default:
continue;
}
/* Store answer */
n_replies++;
queries[qn].rlen = recvlen;
if (qn == next_query) {
while (next_query < n_queries) {
if (!queries[next_query].rlen)
break;
next_query++;
}
}
else {
memcpy(queries[qn].reply, queries[next_query].reply, recvlen);
}
if (next_query >= n_queries)
return n_replies;
}
}
return n_replies;
}
static struct ns *add_ns(struct ns **ns, int *n_ns, const char *addr)
{
char portstr[sizeof("65535")], *p;
len_and_sockaddr a = { };
struct ns *tmp;
struct addrinfo *ai, *aip, hints = {
.ai_flags = AI_NUMERICSERV,
.ai_socktype = SOCK_DGRAM
};
if (parse_nsaddr(addr, &a)) {
/* Maybe we got a domain name, attempt to resolve it using the standard
* resolver routines */
p = strchr(addr, '#');
snprintf(portstr, sizeof(portstr), "%hu",
(unsigned short)(p ? strtoul(p, NULL, 10) : default_port));
if (!getaddrinfo(addr, portstr, &hints, &ai)) {
for (aip = ai; aip; aip = aip->ai_next) {
if (aip->ai_addr->sa_family != AF_INET &&
aip->ai_addr->sa_family != AF_INET6)
continue;
#if ! ENABLE_FEATURE_IPV6
if (aip->ai_addr->sa_family != AF_INET)
continue;
#endif
tmp = realloc(*ns, sizeof(**ns) * (*n_ns + 1));
if (!tmp)
return NULL;
*ns = tmp;
(*ns)[*n_ns].name = addr;
(*ns)[*n_ns].replies = 0;
(*ns)[*n_ns].failures = 0;
(*ns)[*n_ns].addr.len = aip->ai_addrlen;
memcpy(&(*ns)[*n_ns].addr.u.sa, aip->ai_addr, aip->ai_addrlen);
(*n_ns)++;
}
freeaddrinfo(ai);
return &(*ns)[*n_ns];
}
return NULL;
}
tmp = realloc(*ns, sizeof(**ns) * (*n_ns + 1));
if (!tmp)
return NULL;
*ns = tmp;
(*ns)[*n_ns].addr = a;
(*ns)[*n_ns].name = addr;
(*ns)[*n_ns].replies = 0;
(*ns)[*n_ns].failures = 0;
return &(*ns)[(*n_ns)++];
}
static struct query *add_query(struct query **queries, int *n_queries,
int type, const char *dname)
{
struct query *tmp;
ssize_t qlen;
tmp = realloc(*queries, sizeof(**queries) * (*n_queries + 1));
if (!tmp)
return NULL;
memset(&tmp[*n_queries], 0, sizeof(*tmp));
qlen = res_mkquery(QUERY, dname, C_IN, type, NULL, 0, NULL,
tmp[*n_queries].query, sizeof(tmp[*n_queries].query));
tmp[*n_queries].qlen = qlen;
tmp[*n_queries].name = dname;
*queries = tmp;
return &tmp[(*n_queries)++];
}
int main(int argc, char **argv)
{
int rc = 1;
struct ns *ns = NULL;
struct query *queries = NULL;
int n_ns = 0, n_queries = 0;
int c = 0;
char *url = "telecominfraproject.com";
char *server = "127.0.0.1";
int v6 = 0;
while (1) {
int option = getopt(argc, argv, "u:s:i:6");
if (option == -1)
break;
switch (option) {
case '6':
v6 = 1;
break;
case 'u':
url = optarg;
break;
case 's':
server = optarg;
break;
default:
case 'h':
printf("Usage: dnsprobe OPTIONS\n"
" -6 - use ipv6\n"
" -u <url>\n"
" -s <server>\n");
return -1;
}
}
ulog_open(ULOG_SYSLOG | ULOG_STDIO, LOG_DAEMON, "dnsprobe");
ULOG_INFO("attempting to probe dns - %s %s %s\n",
url, server, v6 ? "ipv6" : "");
add_query(&queries, &n_queries, v6 ? T_AAAA : T_A, url);
add_ns(&ns, &n_ns, server);
rc = send_queries(&ns[0], 1, queries, n_queries);
if (rc <= 0) {
fprintf(stderr, "Failed to send queries: %s\n", strerror(errno));
rc = -1;
goto out;
}
if (queries[0].rcode != 0) {
printf("** server can't find %s: %s\n", queries[0].name,
rcodes[queries[0].rcode]);
goto out;
}
if (queries[0].rlen) {
c = parse_reply(queries[0].reply, queries[0].rlen, NULL);
}
if (c == 0)
printf("*** Can't find %s: No answer\n", queries[0].name);
else if (c < 0)
printf("*** Can't find %s: Parse error\n", queries[0].name);
else
rc = 0;
out:
if (n_ns)
free(ns);
if (n_queries)
free(queries);
return rc;
}

View File

@@ -0,0 +1,100 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <getopt.h>
#include <curl/curl.h>
#include <libubox/ulog.h>
static const char *file_cert = "/etc/open-wifi/client.pem";
static const char *file_key = "/etc/open-wifi/client_dec.key";
static const char *file_json = "/etc/open-wifi/redirector.json";
static const char *file_dbg = "/tmp/firstcontact.hdr";
int main(int argc, char **argv)
{
FILE *fp_json;
FILE *fp_dbg;
CURLcode res;
CURL *curl;
char *devid = NULL;
char *url;
while (1) {
int option = getopt(argc, argv, "k:c:o:hi:");
if (option == -1)
break;
switch (option) {
case 'k':
file_key = optarg;
break;
case 'c':
file_cert = optarg;
break;
case 'o':
file_json = optarg;
break;
case 'i':
devid = optarg;
break;
default:
case 'h':
printf("Usage: firstcontact OPTIONS\n"
" -k <keyfile>\n"
" -c <certfile>\n"
" -o <outfile>\n"
" -i <devid>\n");
return -1;
}
}
if (!devid) {
fprintf(stderr, "missing devid\n");
return -1;
}
ulog_open(ULOG_SYSLOG | ULOG_STDIO, LOG_DAEMON, "firstcontact");
ULOG_INFO("attempting first contact\n");
fp_dbg = fopen(file_dbg, "wb");
fp_json = fopen(file_json, "wb");
if (!fp_json) {
ULOG_ERR("failed to create %s\n", file_json);
return -1;
}
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (!curl) {
ULOG_ERR("curl_easy_init failed\n");
return -1;
}
if (asprintf(&url, "https://clientauth.demo.one.digicert.com/iot/api/v2/device/%s", devid) < 0) {
ULOG_ERR("failed to assemble url\n");
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp_json);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp_dbg);
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, file_cert);
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLKEY, file_key);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
ULOG_ERR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
else
ULOG_INFO("downloaded first contact data\n");
curl_easy_cleanup(curl);
curl_global_cleanup();
ulog_close();
return (res != CURLE_OK);
}

View File

@@ -0,0 +1,86 @@
#include <arpa/inet.h>
#include <net/if.h>
#include <libubox/list.h>
#include <libubox/ulog.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct route {
struct list_head list;
char devname[64];
uint32_t domain;
uint32_t mask;
};
static struct list_head routes = LIST_HEAD_INIT(routes);
static int parse_routes(void)
{
FILE *fp = fopen("/proc/net/route", "r");
int flgs, ref, use, metric, mtu, win, ir;
struct route *route;
unsigned long g;
int r;
r = fscanf(fp, "%*[^\n]\n");
if (r < 0) {
fprintf(stderr, "failed to parse routes\n");
return -1;
}
while (1) {
route = malloc(sizeof(*route));
if (!route)
break;
memset(route, 0, sizeof(*route));
r = fscanf(fp, "%63s%x%lx%X%d%d%d%x%d%d%d\n",
route->devname, &route->domain, &g, &flgs, &ref, &use, &metric, &route->mask,
&mtu, &win, &ir);
if (r != 11 && (r < 0) && feof(fp))
break;
list_add(&route->list, &routes);
printf("1 %s %x %x\n", route->devname, ntohl(route->domain), ntohl(route->mask));
}
fclose(fp);
return 0;
}
static int find_collisions(void)
{
struct route *route;
list_for_each_entry(route, &routes, list) {
struct route *compare;
if (!route->domain || !route->mask)
continue;
list_for_each_entry(compare, &routes, list) {
if (!compare->domain || !compare->mask)
continue;
if (compare == route)
continue;
if (((route->domain & route->mask) == (compare->domain & route->mask)) ||
((route->domain & compare->mask) == (compare->domain & compare->mask))) {
ULOG_ERR("collision detected\n");
return 1;
}
}
}
ULOG_INFO("no collision detected\n");
return 0;
}
int main(int argc, char **argv)
{
ulog_open(ULOG_SYSLOG | ULOG_STDIO, LOG_DAEMON, "ip-collide");
parse_routes();
if (!list_empty(&routes))
return find_collisions();
return 0;
}

View File

@@ -0,0 +1,47 @@
#include <stdio.h>
#include <string.h>
#include <radcli/radcli.h>
int
main(int argc, char **argv)
{
int result;
char username[128];
char passwd[AUTH_PASS_LEN + 1];
VALUE_PAIR *send, *received;
uint32_t service;
rc_handle *rh;
/* Not needed if you already used openlog() */
rc_openlog("radiusprobe");
if ((rh = rc_read_config("/tmp/radius.conf")) == NULL)
return ERROR_RC;
strcpy(username, "healthcheck");
strcpy(passwd, "uCentral");
send = NULL;
if (rc_avpair_add(rh, &send, PW_USER_NAME, username, -1, 0) == NULL)
return ERROR_RC;
if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, passwd, -1, 0) == NULL)
return ERROR_RC;
service = PW_AUTHENTICATE_ONLY;
if (rc_avpair_add(rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL)
return ERROR_RC;
result = rc_auth(rh, 0, send, &received, NULL);
if (result == OK_RC || result == REJECT_RC) {
fprintf(stderr, "RADIUS server OK\n");
result = 0;
} else {
fprintf(stderr, "RADIUS server failure\n");
result = -1;
}
return result;
}

View File

@@ -5,3 +5,6 @@
# list ssid 'EAP101-ERICHI'
# list ssid 'EAP101-AKIHO'
# list ssid 'EAP101-DAMAYU'
#
# config dhcpinject 'dhcpinject'
# option iface_count '6'

View File

@@ -9,9 +9,9 @@ SERVICE_NAME="dhcpinject"
PROG=/usr/bin/udhcpinject
start_service() {
local ssid_list=""
local ssids=""
local ports=""
local ifaces=""
# Function to process each ssid
append_ssid() {
@@ -40,6 +40,9 @@ start_service() {
# 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
@@ -47,11 +50,11 @@ start_service() {
fi
# Optional: Log or echo for debugging
logger -t dhcp_inject "Generated SSIDs=$ssids, Uplink=$ports"
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"
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

View File

@@ -26,6 +26,7 @@ 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;
@@ -192,6 +193,11 @@ int parse_ssids(const char *ssids) {
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;
}
@@ -310,7 +316,6 @@ void signal_handler(int sig) {
exit(0);
} else if (sig == SIGHUP) {
syslog(LOG_INFO, "Received reload signal, reconfiguring...\n");
sleep(5);
// Clean up existing resources
cleanup_tc();
@@ -561,7 +566,19 @@ int main(int argc, char *argv[]) {
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
sleep(5);
// 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;
}
provided_ssids = getenv("SSIDs");
syslog(LOG_INFO, "Provided SSIDs: %s\n", provided_ssids);
@@ -618,4 +635,4 @@ int main(int argc, char *argv[]) {
cleanup();
return 0;
}
}