Compare commits

...

12 Commits

Author SHA1 Message Date
John Crispin
6132577aa5 .github/workflows/build-dev.yml: only build the udaya board
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 08:04:58 +01:00
John Crispin
5ed2e9d2fc patches: add patches
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 08:04:48 +01:00
John Crispin
0630f92cae ucentral-client: add cloud_discovery support
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:58:19 +01:00
John Crispin
6bfa602102 tip-defaults: add insta CA
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:58:19 +01:00
John Crispin
95bee2c43b ieee8021x: remove package
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:58:19 +01:00
John Crispin
4ea0c1f4ba certificates: update for insta certs
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:58:19 +01:00
John Crispin
711eaa8355 cloud_discovery: add new daemon
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:58:19 +01:00
John Crispin
ee8c869a8e firstcontact: remove tool
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:27:39 +01:00
John Crispin
70d6293458 ucentral-tools: move code into the tree
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:27:04 +01:00
John Crispin
5ba650cdb1 ucode: update to version used in v4.2
Signed-off-by: John Crispin <john@phrozen.org>
2025-12-11 07:26:39 +01:00
jaspreetsachdev
bb5d3ecd2d Merge pull request #583 from Telecominfraproject/main
merge main to release branch
2023-09-26 10:30:48 -04:00
jaspreetsachdev
dd41f15987 Merge pull request #581 from Telecominfraproject/main
Merge the latest changes from main
2023-09-20 08:58:21 -04:00
48 changed files with 4342 additions and 548 deletions

View File

@@ -21,7 +21,9 @@ jobs:
strategy:
fail-fast: false
matrix:
target: [ 'cig_wf186w', 'cig_wf188n-ca', 'cig_wf188n-ca-ath12', 'cig_wf188n-us', 'cig_wf196-us', 'cig_wf196-ca', 'cig_wf196-ca-ath12', 'cig_wf610d', 'cig_wf660a', 'cig_wf808', 'cybertan_eww622-a1', 'cybertan_eww631-a1', 'cybertan_eww631-b1', 'edgecore_eap101', 'edgecore_eap101-ath12', 'edgecore_eap102', 'edgecore_eap102-ath12', 'edgecore_eap104', 'edgecore_eap104-ath12', 'liteon_wpx8324', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'edgecore_ecw5410', 'edgecore_oap100', 'edgecore_oap101-6e', 'edgecore_oap101e', 'hfcl_ion4','hfcl_ion4xi_wp', 'hfcl_ion4xe', 'hfcl_ion4xi', 'hfcl_ion4x', 'hfcl_ion4x_2', 'hfcl_ion4xi_w', 'hfcl_ion4xi_HMR', 'hfcl_ion4x_w', 'indio_um-305ac', 'indio_um-305ax', 'indio_um-325ac', 'indio_um-510ac-v3', 'indio_um-550ac', 'indio_um-310ax-v1', 'indio_um-510axp-v1', 'indio_um-510axm-v1', 'udaya_a5-id2', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018_v4', 'x64_vm', 'yuncore_ax840', 'yuncore_fap640', 'yuncore_fap650', 'yuncore_fap655' ]
target: [
'udaya_a5-id2'
]
steps:
- uses: actions/checkout@v3

View File

@@ -1,96 +0,0 @@
#!/bin/sh /etc/rc.common
START=80
copy_certificates() {
[ -f /certificates/dev-id ] || return
cp /certificates/*.pem /etc/ucentral/
cp /certificates/dev-id /etc/ucentral/
chown root.network /etc/ucentral/*.pem
chmod 0440 root.network /etc/ucentral/*.pem
chmod 0400 /etc/ucentral/dev-id
[ -f /certificates/restrictions.json ] && cp /certificates/restrictions.json /etc/ucentral/
[ -f /certificates/sign_pubkey.pem ] && cp /certificates/sign_pubkey.pem /etc/ucentral/
exit 0
}
boot() {
[ -f /etc/ucentral/dev-id ] && return
. /lib/functions.sh
mkdir -p /certificates /etc/ucentral/
local mtd=$(find_mtd_index certificates)
if [ "$(head -c 4 /dev/mtd$mtd)" == "hsqs" ]; then
mount -t squashfs /dev/mtdblock$mtd /certificates
else
[ -n "$mtd" -a -f /sys/class/mtd/mtd$mtd/oobsize ] && ubiattach -p /dev/mtd$mtd
if [ -n "$(ubinfo -a | grep certificates)" ]; then
[ -e /dev/ubi0 ] && mount -t ubifs ubi0:certificates /certificates
[ -e /dev/ubi1 ] && mount -t ubifs ubi1:certificates /certificates
fi
fi
case "$(board_name)" in
cig,wf660a)
mmc_dev=$(echo $(find_mmc_part "0:ETHPHYFW") | sed 's/^.\{5\}//')
[ -n "$mmc_dev" ] && mount -t ext4 /dev/$mmc_dev /certificates
;;
esac
copy_certificates
# if we get here no valid certificates were found
local PART_NAME
case "$(board_name)" in
actiontec,web7200)
if grep -q bootselect=0 /proc/cmdline; then
PART_NAME=firmware2
else
PART_NAME=firmware1
fi
;;
edgecore,ecw5211|\
edgecore,eap101|\
edgecore,eap102)
if grep -q rootfs1 /proc/cmdline; then
PART_NAME=rootfs2
else
PART_NAME=rootfs1
fi
;;
hfcl,ion4xi|\
hfcl,ion4xi_w|\
hfcl,ion4x_w|\
hfcl,ion4xi_HMR|\
hfcl,ion4x|\
hfcl,ion4x_2|\
hfcl,ion4xi_wp|\
hfcl,ion4xe)
if grep -q rootfs_1 /proc/cmdline; then
PART_NAME=rootfs
else
PART_NAME=rootfs_1
fi
;;
cig,wf186w|\
cig,wf186h|\
yuncore,ax840|\
yuncore,fap655)
PART_NAME=rootfs_1
;;
*)
return 1
;;
esac
local MTD=$(find_mtd_index $PART_NAME)
[ -z "$MTD" ] && return 1
ubiattach -m $MTD -d 3
[ -e /dev/ubi3 ] && mount -t ubifs ubi3:certificates /certificates
copy_certificates
}

View File

@@ -0,0 +1,36 @@
#!/bin/sh /etc/rc.common
START=09
copy_certificates() {
[ -f /certificates/key.pem ] || return
cp /certificates/cert.pem /certificates/key.pem /certificates/operational.* /etc/ucentral/
chown root.network /etc/ucentral/*.pem /etc/ucentral/*.ca
chmod 0440 root.network /etc/ucentral/*.pem /etc/ucentral/*.ca
[ -f /certificates/gateway.json ] && cp /certificates/gateway.json /etc/ucentral/gateway.flash
[ -f /certificates/restrictions.json ] && cp /certificates/restrictions.json /etc/ucentral/
[ -f /certificates/sign_pubkey.pem ] && cp /certificates/sign_pubkey.pem /etc/ucentral/
country=`cat /certificates/ucentral.defaults | jsonfilter -e '@.country'`
[ -z "$country" -a -f /etc/uci-defaults/30_uboot-envtools ] && {
(. /etc/uci-defaults/30_uboot-envtools)
fw_printenv
country=$(fw_printenv -n country)
}
[ -z "$country" ] && country=US
echo "options cfg80211 ieee80211_regdom="$country > /etc/modules.conf
echo -n $country > /etc/ucentral/country
sync
exit 0
}
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

@@ -2,5 +2,6 @@
uci add system certificates
uci set system.@certificates[-1].key=/etc/ucentral/key.pem
uci set system.@certificates[-1].cert=/etc/ucentral/cert.pem
uci set system.@certificates[-1].ca=/etc/ucentral/cas.pem
uci set system.@certificates[-1].cert=/etc/ucentral/operational.pem
uci set system.@certificates[-1].ca=/etc/ucentral/operational.ca
uci commit

View File

@@ -1,15 +1,158 @@
#!/bin/sh
. /lib/functions.sh
mkdir -p /certificates
mtd=$(find_mtd_index certificates)
check_certificates() {
[ -f /certificates/cert.pem -a -f /certificates/key.pem ] && exit 0
}
if [ "$(head -c 4 /dev/mtd$mtd)" == "hsqs" ]; then
mount -t squashfs /dev/mtdblock$mtd /certificates
else
[ -n "$mtd" -a -f /sys/class/mtd/mtd$mtd/oobsize ] && ubiattach -p /dev/mtd$mtd
if [ -n "$(ubinfo -a | grep certificates)" ]; then
[ -e /dev/ubi0 ] && mount -t ubifs ubi0:certificates /certificates
[ -e /dev/ubi1 ] && mount -t ubifs ubi1:certificates /certificates
check_certificates
tar_part_lookup() {
part="$(fw_printenv -n cert_part)"
if [ "$part" -eq 0 ]; then
echo "$2"
part=1
else
echo "$1"
part=0
fi
fi
fw_setenv cert_part $part
}
. /lib/functions.sh
mkdir -p /certificates /etc/ucentral/
case "$(board_name)" in
cig,wf660a)
mmc_dev=$(echo $(find_mmc_part "0:ETHPHYFW") | sed 's/^.\{5\}//')
[ -n "$mmc_dev" ] && mount -t ext4 /dev/$mmc_dev /certificates
;;
cig,wf672)
mmc_dev=$(echo $(find_mmc_part "cert") | sed 's/^.\{5\}//')
[ -n "$mmc_dev" ] && mount -t ext4 /dev/$mmc_dev /certificates
;;
sonicfi,rap7*)
if [ "$(board_name)" = "sonicfi,rap7110c-341x" ]; then
mmc_dev=$(echo $(find_mmc_part "certificates") | sed 's/^.\{5\}//')
[ -n "$mmc_dev" ] && mount -t ext4 /dev/$mmc_dev /certificates
else
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
fi
mtd=$(find_mtd_index devinfo)
[ -n "$mtd" ] && tar xf /dev/mtdblock$mtd -C /certificates
;;
udaya,a5-id2|\
yuncore,ax820)
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 "insta1" "insta2")
if [ -n "insta" ]; then
mtd=$(find_mtd_index $part)
[ -n "$mtd" ] && tar xf /dev/mtdblock$mtd -C /certificates
fi
;;
*)
mtd=$(find_mtd_index certificates)
if [ "$(head -c 4 /dev/mtd$mtd)" == "hsqs" ]; then
mount -t squashfs /dev/mtdblock$mtd /certificates
else
[ -n "$mtd" -a -f /sys/class/mtd/mtd$mtd/oobsize ] && ubiattach -p /dev/mtd$mtd
if [ -n "$(ubinfo -a | grep certificates)" ]; then
[ -e /dev/ubi0 ] && mount -t ubifs ubi0:certificates /certificates
[ -e /dev/ubi1 ] && mount -t ubifs ubi1:certificates /certificates
fi
fi
esac
check_certificates
# if we get here no valid certificates were found
PART_NAME=
case "$(board_name)" in
actiontec,web7200)
if grep -q bootselect=0 /proc/cmdline; then
PART_NAME=firmware2
else
PART_NAME=firmware1
fi
;;
edgecore,ecw5211|\
edgecore,eap101|\
edgecore,eap102|\
edgecore,eap104|\
edgecore,eap105|\
edgecore,eap111|\
edgecore,eap112|\
edgecore,oap101|\
edgecore,oap101e|\
edgecore,oap101-6e|\
edgecore,oap101e-6e|\
edgecore,oap103)
if grep -q rootfs1 /proc/cmdline; then
PART_NAME=rootfs2
else
PART_NAME=rootfs1
fi
;;
hfcl,ion4xi|\
hfcl,ion4xi_w|\
hfcl,ion4x_w|\
hfcl,ion4xi_HMR|\
hfcl,ion4x|\
hfcl,ion4x_2|\
hfcl,ion4xi_wp|\
hfcl,ion4xe)
if grep -q rootfs_1 /proc/cmdline; then
PART_NAME=rootfs
else
PART_NAME=rootfs_1
fi
;;
cig,wf186w|\
cig,wf189|\
cig,wf189w|\
cig,wf189h|\
cig,wf186h|\
cig,wf196|\
cig,wf188n|\
emplus,wap380c|\
emplus,wap385c|\
emplus,wap386v2|\
emplus,wap581|\
yuncore,ax840|\
yuncore,fap655)
PART_NAME=rootfs_1
;;
senao,iap2300m|\
senao,iap4300m|\
emplus,wap588m|\
senao,jeap6500)
PART_NAME=ubi
;;
*)
return 1
;;
esac
MTD=$(find_mtd_index $PART_NAME)
[ -z "$MTD" ] && return 1
ubiattach -m $MTD -d 3
[ -e /dev/ubi3 ] && mount -t ubifs ubi3:certificates /certificates
check_certificates

View File

@@ -0,0 +1,36 @@
#!/bin/sh
tar_part_lookup() {
part="$(fw_printenv -n cert_part)"
if [ "$part" -eq 0 ]; then
echo "$2"
part=1
else
echo "$1"
part=0
fi
fw_setenv cert_part $part
}
. /lib/functions.sh
case "$(board_name)" in
udaya,a5-id2|\
yuncore,ax820)
cd /certificates
tar cf /tmp/certs.tar .
part=$(tar_part_lookup "insta1" "insta2")
mtd=$(find_mtd_index $part)
dd if=/tmp/certs.tar of=/dev/mtdblock$mtd
;;
sonicfi,rap6*)
if [ "$(fw_printenv -n store_certs_disabled)" != "1" ]; then
cd /certificates
tar cf /tmp/certs.tar .
mtd=$(find_mtd_index devinfo)
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
rm -f /tmp/certs.tar /tmp/certs_pad.tar
fi
;;
esac

View File

@@ -0,0 +1,24 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=cloud_discovery
PKG_RELEASE:=1
PKG_LICENSE:=BSD-3-Clause
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
include $(INCLUDE_DIR)/package.mk
define Package/cloud_discovery
SECTION:=ucentral
CATEGORY:=uCentral
TITLE:=TIP cloud_discovery
DEPENDS:=+certificates +ucode-mod-log
endef
Build/Compile=
define Package/cloud_discovery/install
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,cloud_discovery))

View File

@@ -0,0 +1 @@
touch /tmp/ntp.set

View File

@@ -0,0 +1,42 @@
#!/bin/sh /etc/rc.common
START=98
USE_PROCD=1
PROG=/usr/bin/cloud_discovery
service_triggers() {
procd_add_reload_trigger ucentral
}
reload_service() {
ubus call cloud reload
}
start_service() {
[ -f /etc/ucentral/capabilities.json ] || {
mkdir -p /etc/ucentral/
/usr/share/ucentral/capabilities.uc
}
local valid=$(cat /etc/ucentral/gateway.json | jsonfilter -e '@["valid"]')
[ "$valid" == "true" ] ||
/usr/share/ucentral/ucentral.uc /etc/ucentral/ucentral.cfg.0000000001 > /dev/null
est_client check
[ $? -eq 1 ] && {
logger ERROR
logger ERROR
logger ERROR
logger The certificate used has a CN that does not match the serial of the device
echo The certificate used has a CN that does not match the serial of the device
logger ERROR
logger ERROR
logger ERROR
return
}
procd_open_instance
procd_set_param command "$PROG"
procd_set_param respawn
procd_close_instance
}

View File

@@ -0,0 +1,3 @@
#!/bin/sh
/usr/share/ucentral/cloud_discovery.uc $1

View File

@@ -0,0 +1,445 @@
#!/usr/bin/ucode
'use strict';
import { ulog_open, ulog, ULOG_SYSLOG, ULOG_STDIO, LOG_DAEMON, LOG_INFO } from 'log';
import * as libubus from 'ubus';
import * as uloop from 'uloop';
import * as libuci from 'uci';
import * as math from 'math';
import * as fs from 'fs';
const DISCOVER = 0;
const VALIDATING = 1;
const ONLINE = 2;
const OFFLINE = 3;
const ORPHAN = 4;
const DISCOVER_DHCP = "DHCP";
const DISCOVER_FLASH = "FLASH";
const DISCOVER_LOOKUP = "OpenLAN";
let ubus = libubus.connect();
let uci = libuci.cursor();
let state = DISCOVER;
let discovery_method = "";
let discovery_block_list = [];
let validate_time;
let offline_time;
let orphan_time;
let interval;
let timeouts = {
'offline': 4 * 60 * 60,
'validate': 120,
'orphan': 2 * 60 * 60,
interval: 10000,
expiry_interval: 60 * 60 * 1000,
expiry_threshold: 1 * 365 * 24 * 60 * 60,
};
ulog_open(ULOG_SYSLOG | ULOG_STDIO, LOG_DAEMON, "cloud_discover");
ulog(LOG_INFO, 'Start\n');
uloop.init();
let cds_server = 'discovery.open-lan.org';
function detect_certificate_type() {
let pipe = fs.popen(`openssl x509 -in /etc/ucentral/cert.pem -noout -issuer`);
let issuer = pipe.read("all");
pipe.close();
if (match(issuer, /OpenLAN Demo Birth CA/)) {
ulog(LOG_INFO, 'Certificate type is "Demo" \n');
cds_server = 'discovery-qa.open-lan.org';
timeouts.expiry_threshold = 3 * 24 * 60 * 60;
} else if (match(issuer, /OpenLAN Birth Issuing CA/)) {
ulog(LOG_INFO, 'Certificate type is "Production"\n');
} else {
ulog(LOG_INFO, 'Certificate type is "TIP"\n');
}
}
function readjsonfile(path) {
let file = fs.readfile(path);
if (file)
file = json(file);
return file;
}
function timeouts_load(){
let data = uci.get_all('ucentral', 'timeouts');
for (let key in [ 'offline', 'validate', 'orphan' ])
if (data && data[key])
timeouts[key] = +data[key];
let time_skew = timeouts.offline / 50 * (math.rand() % 50);
timeouts.offline_skew = timeouts.offline + time_skew;
ulog(LOG_INFO, 'Randomizing offline time from %d->%d \n', timeouts.offline, timeouts.offline_skew);
time_skew = timeouts.orphan / 50 * (math.rand() % 50);
timeouts.orphan_skew = timeouts.orphan + time_skew;
ulog(LOG_INFO, 'Randomizing orphan time from %d->%d \n', timeouts.orphan, timeouts.orphan_skew);
}
function client_start() {
ulog(LOG_INFO, '(re)starting client\n');
system('/etc/init.d/ucentral restart');
}
function dhcp_restart() {
ulog(LOG_INFO, 'restarting dhcp\n');
system('killall -USR1 udhcpc');
}
function ntp_restart() {
ulog(LOG_INFO, 'restarting ntp\n');
system('/etc/init.d/sysntpd restart');
}
function gateway_load() {
return readjsonfile('/etc/ucentral/gateway.json');
}
function discovery_state_write() {
if (length(discovery_method) == 0)
return;
let discovery_state = {
"type": discovery_method,
"updated": time()
};
fs.writefile('/etc/ucentral/discovery.state.json', discovery_state);
}
function gateway_write(data) {
let gateway = gateway_load();
gateway ??= {};
let new = {};
let changed = false;
for (let key in [ 'server', 'port', 'valid', 'hostname_validate' ]) {
if (exists(data, key))
new[key] = data[key];
else if (exists(gateway, key))
new[key] = gateway[key];
if (new[key] != gateway[key])
changed = true;
}
if (changed) {
fs.writefile('/etc/ucentral/gateway.json', new);
system('sync');
}
return changed;
}
function gateway_available() {
let gateway = gateway_load();
if (!gateway || !gateway.server || !gateway.port)
return false;
return true;
}
function set_state(set) {
if (state == set)
return;
let prev = state;
state = set;
switch(state) {
case DISCOVER:
ulog(LOG_INFO, 'Setting cloud to undiscovered\n');
fs.unlink('/tmp/cloud.json');
fs.unlink('/etc/ucentral/gateway.json');
gateway_write({ valid: false });
dhcp_restart();
break;
case VALIDATING:
ulog(LOG_INFO, 'Wait for validation\n');
validate_time = time();
state = VALIDATING;
push(discovery_block_list, discovery_method);
break;
case ONLINE:
ulog(LOG_INFO, 'Connected to cloud\n');
if (prev == VALIDATING) {
ulog(LOG_INFO, 'Setting cloud controller to validated\n');
gateway_write({ valid: true });
discovery_state_write();
discovery_block_list = [];
}
break;
case OFFLINE:
ulog(LOG_INFO, 'Lost connection to cloud\n');
offline_time = time();
break;
case ORPHAN:
ulog(LOG_INFO, 'Device is an orphan\n');
orphan_time = time();
break;
}
}
function discover_dhcp() {
let dhcp = readjsonfile('/tmp/cloud.json');
if (dhcp?.dhcp_server && dhcp?.dhcp_port) {
if (gateway_write({ server: dhcp.dhcp_server, port:dhcp.dhcp_port, valid: false, hostname_validate: dhcp.no_validation ? 0 : 1 })) {
ulog(LOG_INFO, `Discovered cloud via DHCP ${dhcp.dhcp_server}:${dhcp.dhcp_port}\n`);
client_start();
set_state(VALIDATING);
}
return true;
}
return !dhcp?.lease;
}
function redirector_lookup() {
const path = '/tmp/ucentral.redirector';
ulog(LOG_INFO, 'Contact redirector service\n');
let serial = uci.get('ucentral', 'config', 'serial');
fs.unlink(path);
system(`curl -k --cert /etc/ucentral/operational.pem --key /etc/ucentral/key.pem --cacert /etc/ucentral/operational.ca https://${cds_server}/v1/devices/${serial} --output /tmp/ucentral.redirector`);
if (!fs.stat(path))
return;
let redir = readjsonfile(path);
if (redir?.controller_endpoint) {
let controller_endpoint = split(redir.controller_endpoint, ':');
if (gateway_write({ server: controller_endpoint[0], port: controller_endpoint[1] || 15002, valid: false, hostname_validate: 1 })) {
ulog(LOG_INFO, `Discovered cloud via lookup service ${controller_endpoint[0]}:${controller_endpoint[1] || 15002}\n`);
client_start();
set_state(VALIDATING);
}
} else {
ulog(LOG_INFO, 'Failed to discover cloud endpoint\n');
}
}
function discover_flash() {
if (!fs.stat('/etc/ucentral/gateway.flash'))
return 1;
ulog(LOG_INFO, 'Using pre-populated cloud information\n');
fs.writefile('/etc/ucentral/gateway.json', fs.readfile('/etc/ucentral/gateway.flash'));
client_start();
set_state(VALIDATING);
return 0;
}
function time_is_valid() {
let valid = !!fs.stat('/tmp/ntp.set');
if (!valid)
ntp_restart();
ulog(LOG_INFO, `Time is ${valid ? '': 'not '}valid\n`);
return valid;
}
function is_discover_method_blacked() {
if (discovery_method in discovery_block_list)
return true;
return false;
}
function interval_handler() {
printf(`State ${state}\n`);
switch(state) {
case DISCOVER:
if (timeouts.interval < 60000)
timeouts.interval += 10000;
break;
default:
timeouts.interval = 10000;
break;
}
printf('setting interval to %d\n', timeouts.interval);
interval.set(timeouts.interval);
switch(state) {
case ORPHAN:
if (time() - orphan_time <= timeouts.orphan_skew)
break;
orphan_time = time();
/* fall through */
case DISCOVER:
ulog(LOG_INFO, 'Starting discover\n');
if (!time_is_valid())
return;
if (system('/usr/bin/est_client enroll'))
return;
discovery_method = DISCOVER_DHCP;
if (!is_discover_method_blacked() && discover_dhcp())
return;
discovery_method = DISCOVER_FLASH;
if (!is_discover_method_blacked() && !discover_flash())
return;
discovery_method = DISCOVER_LOOKUP;
redirector_lookup();
discovery_block_list = [];
break;
case VALIDATING:
if (time() - validate_time <= timeouts.validate)
break;
ulog(LOG_INFO, 'validation failed, restarting discovery process\n');
set_state(DISCOVER);
break;
case OFFLINE:
if (time() - offline_time <= timeouts.offline_skew)
break;
ulog(LOG_INFO, 'offline for too long, setting device as orphaned\n');
set_state(ORPHAN);
break;
}
}
function trigger_reenroll() {
ulog(LOG_INFO, 'triggering reenroll\n');
if (system('/usr/bin/est_client reenroll')) {
ulog(LOG_INFO, 'reenroll failed\n');
return;
}
ulog(LOG_INFO, 'reenroll succeeded\n');
ulog(LOG_INFO, 'stopping client\n');
system('/etc/init.d/ucentral stop');
set_state(DISCOVER);
}
function expiry_handler() {
let stat = fs.stat('/etc/ucentral/operational.ca');
if (!stat)
return;
let ret = system(`openssl x509 -checkend ${timeouts.expiry_threshold} -noout -in /certificates/operational.pem`);
if (!ret) {
ulog(LOG_INFO, 'checked certificate expiry - all ok\n');
return;
}
ulog(LOG_INFO, 'certificate will expire soon\n');
trigger_reenroll();
}
let ubus_methods = {
discover: {
call: function(req) {
set_state(DISCOVER);
return 0;
},
args: {
}
},
renew: {
call: function(req) {
if (state != ONLINE)
return;
ulog(LOG_INFO, 'Validate cloud due to DHCP renew event\n');
let gateway = gateway_load();
let cloud = readjsonfile('/tmp/cloud.json');
if (!cloud?.dhcp_server || !cloud?.dhcp_port)
return 0;
if (cloud.dhcp_server != gateway?.server || cloud.dhcp_port != gateway?.port)
set_state(DISCOVER);
else
ulog(LOG_INFO, 'Cloud has not changed\n');
},
args: {
}
},
online: {
call: function(req) {
set_state(ONLINE);
return 0;
},
args: {
}
},
offline: {
call: function(req) {
if (state == ONLINE)
set_state(OFFLINE);
return 0;
},
args: {
}
},
reload: {
call: function(req) {
timeouts_load();
return 0;
},
args: {
}
},
status: {
call: function(req) {
const names = [ 'discover', 'validate', 'online', 'offline', 'orphan' ];
let ret = { state: names[state] };
switch(state){
case OFFLINE:
ret.since = time() - offline_time;
break;
case ORPHAN:
ret.since = time() - orphan_time;
break;
case VALIDATING:
ret.since = time() - validate_time;;
break;
}
return ret;
},
args: {},
},
reenroll: {
call: function(req) {
trigger_reenroll();
return 0;
},
args: {},
},
};
detect_certificate_type();
if (gateway_available()) {
let status = ubus.call('ucentral', 'status');
ulog(LOG_INFO, 'cloud is known\n');
if (status?.connected) {
state = ONLINE;
} else {
client_start();
set_state(VALIDATING);
}
} else {
dhcp_restart();
}
timeouts_load();
interval = uloop.interval(timeouts.interval, interval_handler);
uloop.interval(timeouts.expiry_interval, expiry_handler);
ubus.publish('cloud', ubus_methods);
uloop.run();
uloop.done();

View File

@@ -0,0 +1,228 @@
#!/usr/bin/ucode
'use strict';
import { ulog_open, ulog, ULOG_SYSLOG, ULOG_STDIO, LOG_DAEMON, LOG_INFO } from 'log';
import * as fs from 'fs';
import * as libuci from 'uci';
let store_operational_pem = false;
let store_operational_ca = false;
let est_server = 'est.certificates.open-lan.org';
let cert_prefix = 'operational';
function set_est_server() {
let pipe = fs.popen(`openssl x509 -in /etc/ucentral/cert.pem -noout -issuer`);
let issuer = pipe.read("all");
pipe.close();
if (match(issuer, /OpenLAN Demo Birth CA/)) {
ulog(LOG_INFO, 'Certificate type is "Demo" \n');
est_server = 'qaest.certificates.open-lan.org:8001';
} else if (match(issuer, /OpenLAN Birth Issuing CA/)) {
ulog(LOG_INFO, 'Certificate type is "Production"\n');
} else {
ulog(LOG_INFO, 'Certificate type is "TIP"\n');
}
}
if (getenv('EST_SERVER'))
est_server = getenv('EST_SERVER');
if (getenv('CERT_PREFIX'))
cert_prefix = getenv('CERT_PREFIX');
ulog_open(ULOG_SYSLOG | ULOG_STDIO, LOG_DAEMON, "est_client");
function generate_csr(cert) {
if (!fs.stat('/tmp/csr.nohdr.p10')) {
let pipe = fs.popen(`openssl x509 -in ${cert} -noout -subject`);
let subject = pipe.read("all");
pipe.close();
subject = rtrim(subject);
subject = replace(subject, 'subject=', '/');
subject = replace(subject, ' = ', '=');
subject = replace(subject, ', ', '/');
let ret = system(`openssl req -subj "${subject}" -new -key /etc/ucentral/key.pem -out /tmp/csr.p10`);
if (ret) {
ulog(LOG_INFO, 'Failed to generate CSR\n');
return 1;
}
let input = fs.open('/tmp/csr.p10', 'r');
let output = fs.open('/tmp/csr.nohdr.p10', 'w');
let line;
while (line = input.read('line')) {
if (substr(line, 0, 4) == '----')
continue;
output.write(line);
}
input.close();
output.close();
ulog(LOG_INFO, 'Generated CSR\n');
}
return 0;
}
function store_operational_cert(path, target) {
system('mount_certs');
system(`cp ${path} /certificates/${target}`);
ulog(LOG_INFO, `Persistently stored ${target}\n`);
}
function p7_too_pem(src, dst) {
let input = fs.readfile(src);
let output = fs.open('/tmp/convert.p7', 'w');
output.write('-----BEGIN PKCS #7 SIGNED DATA-----\n');
output.write(`${input}\n-----END PKCS #7 SIGNED DATA-----`);
output.close();
let ret = system(`openssl pkcs7 -outform PEM -print_certs -in /tmp/convert.p7 -out ${dst}`);
if (ret) {
ulog(LOG_INFO, 'Failed to convert P7 to PEM\n');
return 1;
}
ulog(LOG_INFO, 'Converted P7 to PEM\n');
return 0;
}
function call_est_server(path, cert, target) {
if (generate_csr(cert))
return 1;
set_est_server();
let ret = system('curl -m 10 -X POST https://' + est_server + '/.well-known/est/' + path + ' -d @/tmp/csr.nohdr.p10 -H "Content-Type: application/pkcs10" --cert ' + cert + ' --key /etc/ucentral/key.pem --cacert /etc/ucentral/insta.pem -o /tmp/operational.nohdr.p7');
if (ret) {
ulog(LOG_INFO, 'Failed to request operational certificate\n');
return 1;
}
ulog(LOG_INFO, 'EST succeeded\n');
return p7_too_pem('/tmp/operational.nohdr.p7', target);
}
function simpleenroll() {
if (fs.stat('/etc/ucentral/' + cert_prefix + '.pem')) {
ulog(LOG_INFO, 'Operational certificate is present\n');
return 0;
}
if (call_est_server('simpleenroll', '/etc/ucentral/cert.pem', '/etc/ucentral/' + cert_prefix + '.pem'))
return 1;
ulog(LOG_INFO, 'Operational cert acquired\n');
store_operational_pem = true;
return 0;
}
function simplereenroll() {
if (!fs.stat('/etc/ucentral/' + cert_prefix + '.pem')) {
ulog(LOG_INFO, 'Operational certificate was not found\n');
return 0;
}
if (call_est_server('simplereenroll', '/etc/ucentral/' + cert_prefix + '.pem', '/tmp/' + cert_prefix + '.pem'))
return 1;
ulog(LOG_INFO, 'Operational cert updated\n');
store_operational_cert('/tmp/' + cert_prefix + '.pem', cert_prefix + '.pem');
system('cp /tmp/' + cert_prefix + '.pem /etc/ucentral/');
system('store_certs');
return 0;
}
function load_operational_ca() {
if (fs.stat('/etc/ucentral/' + cert_prefix + '.ca')) {
ulog(LOG_INFO, 'Operational CA is present\n');
return 0;
}
set_est_server();
let ret = system('curl -m 10 -X GET https://' + est_server + '/.well-known/est/cacerts --cert /etc/ucentral/' + cert_prefix + '.pem --key /etc/ucentral/key.pem --cacert /etc/ucentral/insta.pem -o /tmp/' + cert_prefix + '.ca.nohdr.p7');
if (!ret)
ret = p7_too_pem('/tmp/' + cert_prefix + '.ca.nohdr.p7', '/etc/ucentral/' + cert_prefix + '.ca');
if (ret) {
ulog(LOG_INFO, 'Failed to load CA\n');
return 1;
}
system('cat /etc/ucentral/openlan.pem >> /etc/ucentral/' + cert_prefix + '.ca');
ulog(LOG_INFO, 'Acquired CA\n');
store_operational_ca = true;
return 0;
}
function fwtool() {
if (!fs.stat('/etc/ucentral/cert.pem'))
return 0;
let pipe = fs.popen(`openssl x509 -in /etc/ucentral/cert.pem -noout -issuer`);
let issuer = pipe.read("all");
pipe.close();
if (!(match(issuer, /OpenLAN/) && match(issuer, /Birth/)))
return 0;
ulog(LOG_INFO, 'The issuer is insta\n');
let metadata = fs.readfile('/tmp/sysupgrade.meta');
if (metadata)
metadata = json(metadata);
if (!metadata)
return 0;
if (!metadata.est_supported) {
ulog(LOG_INFO, 'The image does not support EST\n');
return 1;
}
ulog(LOG_INFO, 'The image supports EST\n');
return 0;
}
function check_cert() {
if (!fs.stat('/etc/ucentral/cert.pem'))
return 0;
let pipe = fs.popen("openssl x509 -in /etc/ucentral/cert.pem -noout -subject -nameopt multiline | grep commonName | awk '{ print $3 }'");
let cn = pipe.read("all");
pipe.close();
if (!cn)
return 0;
cn = lc(trim(cn));
let uci = libuci.cursor();
let serial = uci.get('ucentral', 'config', 'serial');
return cn != serial;
}
switch(ARGV[0]) {
case 'enroll':
let ret = simpleenroll();
if (!ret)
ret = load_operational_ca();
if (store_operational_pem)
store_operational_cert('/etc/ucentral/' + cert_prefix + '.pem', cert_prefix + '.pem');
if (store_operational_ca)
store_operational_cert('/etc/ucentral/' + cert_prefix + '.ca', cert_prefix + '.ca');
if (store_operational_pem || store_operational_ca)
system('store_certs');
exit(ret);
case 'reenroll':
if (simplereenroll())
exit(1);
exit(0);
case 'fwtool':
exit(fwtool());
case 'check':
exit(check_cert());
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/ucode
import * as libubus from 'ubus';
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');
if (cmd != 'bound' && cmd != 'renew')
exit(0);
/*let file = fs.readfile('/etc/ucentral/gateway.json');
if (file)
file = json(file);
file ??= {};
if (file.server && file.port && file.valid)
exit(0);
*/
let cloud = {
lease: true,
};
if (opt138) {
let dhcp = opt138;
dhcp = split(dhcp, ':');
cloud.dhcp_server = dhcp[0];
cloud.dhcp_port = dhcp[1] ?? 15002;
cloud.no_validation = true;
}
if (opt224) {
let dhcp = opt224;
dhcp = split(dhcp, ':');
cloud.dhcp_server = dhcp[0];
cloud.dhcp_port = dhcp[1] ?? 15002;
}
fs.writefile('/tmp/cloud.json', cloud);
if ((opt138 || opt224) && cmd == 'renew') {
let ubus = libubus.connect();
ubus.call('cloud', 'renew');
}
exit(0);

View File

@@ -1,25 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=firstcontact
PKG_RELEASE:=1
PKG_LICENSE:=BSD-3-Clause
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/firstcontact
SECTION:=ucentral
CATEGORY:=uCentral
TITLE:=TIP DigiCert firstcontact
DEPENDS:=+libubox +libcurl +libopenssl +certificates
endef
define Package/firstcontact/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/firstcontact $(1)/usr/sbin/
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,firstcontact))

View File

@@ -1,20 +0,0 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
PROG=/usr/bin/ucode
start_service() {
[ -f /etc/ucentral/capabilities.json ] || {
mkdir -p /etc/ucentral/
/usr/share/ucentral/capabilities.uc
}
/usr/share/ucentral/ucentral.uc /etc/ucentral/ucentral.cfg.0000000001 > /dev/null
procd_open_instance
procd_set_param command "$PROG" -l uci -l fs /usr/share/ucentral/firstcontact.uc
procd_set_param respawn 1 10 0
procd_close_instance
}

View File

@@ -1,3 +0,0 @@
#!/bin/sh
[ -f "/etc/ucentral/redirector.json" ] && /etc/init.d/firstcontact disable
[ -f "/etc/ucentral/redirector.json" ] || /etc/init.d/ucentral disable

View File

@@ -1,70 +0,0 @@
let devid;
let fd = fs.open("/etc/ucentral/dev-id", "r");
if (!fd) {
warn("firstcontact: failed to find device id");
exit(1);
}
devid = fd.read("all");
fd.close();
let config = {};
function store_config(path) {
let cursor = uci.cursor(path);
let redir = split(config.Redirector, ":");
cursor.load("ucentral");
cursor.set("ucentral", "config", "server", redir[0]);
cursor.set("ucentral", "config", "port", redir[1] || 15002);
cursor.commit();
}
ret = system(sprintf('/usr/sbin/firstcontact -i %s', devid));
if (ret) {
warn("firstcontact failed to contact redirector, check DHCP option\n");
let fd = fs.open("/tmp/capwap/dhcp_opt.txt", "r");
if (!fd) {
warn("No redirector found\n");
exit(1);
} else {
config.Redirector = fd.read("all");
fd.close();
}
} else {
let redirector = { };
let fd = fs.open("/etc/ucentral/redirector.json", "r");
if (fd) {
let data = fd.read("all");
fd.close();
try {
redirector = json(data);
}
catch (e) {
warn("firstcontact: Unable to parse JSON data in %s: %s", path, e);
exit(1);
}
}
for (let r in redirector.fields)
if (r.name && r.value)
config[r.name] = r.value;
if (!config.Redirector) {
warn("Reply is missing Redirector field\n");
exit(1);
}
}
store_config();
store_config("/etc/config-shadow/");
warn("firstcontact: managed to look up redirector\n");
system("/etc/init.d/ucentral enable");
system("/etc/init.d/firstcontact disable");
system("reload_config");
system("/etc/init.d/ucentral start");
system("/etc/init.d/firstcontact stop");

View File

@@ -1,13 +0,0 @@
cmake_minimum_required(VERSION 2.6)
PROJECT(firstcontact 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}
)

View File

@@ -0,0 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIFajCCA1KgAwIBAgICDnowDQYJKoZIhvcNAQELBQAwHzEdMBsGA1UEAwwUT3BlbkxBTiBEZW1vIFJvb3QgQ0EwHhcNMjUwMjIxMTUwMDAwWhcNMjYwMjIxMTUwMDAwWjAgMR4wHAYDVQQDExVPcGVuTEFOIERlbW8gQmlydGggQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVWIyySul6Fv4wl1O+DQpaLRa0p+Az5L/jcqTpdVf6w+8tlmeIY9C28uDQoDjewrIkvf3lcfK86nshs02s9ehqZUnEP8+GvKM19x3JbWxeTvWwFirjHir4x897iQ606bAMbrHHtntI9ZyBZyXDGeElGJxJQNX+0d50SFq609cB3yxpBPJ67ag+4Oq0uHgROHjEQMrfwLwlAune0c1fjQDrN14PDNjMZHvvhc/pkAHxR1PP6LOFNV5NuQ58tC5N7R2EqqFbIJ8VZgcagrGRYuAuFFTaV+D7RIt9xGTuWlCyxHI7VkRBJ1mRoEr4GOrP9QFjBD8NzNK+/wnR/fZwhpEnRsgHiI33wKHBDg+l3r8tvRzuB5X6Gl/SfuAeaoCuDHMncTjQg1zGhyEwjQhUe4RY3w+yHAjeeOE6c5spOMDDdaBibkzLmSjXztuLeAdzsUcD3fvGeOvh9vG14TKEmF8puNkqEcc0W8NyUWKFdr9umdJEMbaRSSsMGtp8bDj3Ddh4PhEJrIFeo89+HwXhU6sk+wzE9BULTohahsfwOV/08t1cZ3Q04Oj1KI+4YWu8BJns5gX35rQ8GIbkXQwfvFMwqmbg+ij2o9HWdkSL4bcqW/83Ho+31ce210rVGPK9cav0CjA2Eexgxi45cbgnfoade74Qa5zXboJEBmp7rbo4swIDAQABo4GuMIGrMB8GA1UdIwQYMBaAFDzIg8eyTI3xc4A2R60f8HanhBZDMB0GA1UdDgQWBBS5xC3inqLQl+vxzn9PsjNzlZ5hYDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vZGVtby5jZXJ0aWZpY2F0ZS5maS9jcmwvT3BlbkxBTkRlbW9Sb290Q0EuY3JsMA0GCSqGSIb3DQEBCwUAA4ICAQA9DJEjsDLqtSFkF0XTWfzbebXA+X8++Qmiukrw0s2LRx798ce0mVITRAFDLf78BeUYF0B+PQ8hgq4fWyFsXRgZVrITd1BszT3LJ2r/6xWQJVpVHzLqKgIlW/PY/uTUz+xqR0Ev6hYrmrjfya0K0XEZZqxkmrTrcECaA3RCFkWQl9ZUlb9BClmdhayO8x1XpJplIYAMKVuoPL9IUQH6HUPFnzlPNQHIK9gcFACtgPVWCJg3IAvSLa41KpRxTDwGFvlrNKtkBlGRYhFGCHWXXZn8fdQHW9vykkkfPOaPR/AVyuRzfAT6wbtVWSy38BurSdqSCuNQPQBfF2vMeUGwNbD/7B4tYrWVtnIbgxRPKvX0o3mZkKry6BJf2m/AKWA16W+i4ojnPRORLTTq9cEZ0WL6NRHCgMrbWaCs/+ADTErqK6cv7GhoOVEiqugvnz93dit2IXg4zdDJ4hF9ZSlicwgZKVvMqnNQ1iiXezIQBehgYcWwXRIfdrRPe88HgkySuDZ2lkKYdc+oTc6e7upRh4Kh2ZSipcRb6ehPan533jnQJyU8A9vFAJiQfZZ4lD3tcsqlsDnlu5YEDYSjcfnkyOH/Mlx5VVTWYGvqNNVKRDw2slSxKwVCobkcF/2dAxP9DqOaGaCnMeOaR7kMaBm5d1fwb+bCl9usQAELjZBv2vAH8g==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFIDCCAwigAwIBAgICDnkwDQYJKoZIhvcNAQELBQAwHzEdMBsGA1UEAwwUT3BlbkxBTiBEZW1vIFJvb3QgQ0EwHhcNMjUwMjIxMTUwMDAwWhcNMjYwMjIxMTUwMDAwWjAfMR0wGwYDVQQDDBRPcGVuTEFOIERlbW8gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMjExylKdJWoJu9mOHPJ6yZFXKe1lE467G65acpS2FKIWnPVFjNCmATMpkMOIFzEFwyFdbQjzOidtiL+73zlE52lOJpXCfOcxDFqDYDJJ8//J1/gQWsBaKpSvgLiHU/0awkQg+yJYZpj8YZa4NkFe+zTjQScSfOsqPPb3rZ7DOQ2BKAhjVShKmVbtNil0iO0zm8vE8DNkktTNMREp2pzb8MbCAgfOkwlrby6T+rV3TvmjThGdFUb5lWDFxWtlF8W0SUII9qj7p5TdGpryeLsO0nZTBtS4HxZNdvmKOHfgcRHmSZIJigB2NzKLNrXF9JBW0WnUSwZJZAG2C1RTx6lADILPueuusyfR/hZ3koKi4PHnSiTwQghzia9K9QjNHq5z9R9ZoCnhBg1VyU4LKmp862L0sIp2vgnOYunEIi9aCYBaDwo+0FuVjZuXyDIatwVuA7TN5IWPHA6XLdOt1mmkeYy1Ldr4XHjdondhtOyeei1UFXmyyLm2+kmRYfTm91TqYmNzRgbRV2NHO50AmsnBknX4Rv3gishGe0+dV5yFcUwZud0z2rSCkuoai5tKrPT+6Y6NqkT9u9HFifIBXnLwEzVUqHRtW6SuWj2DClVQIXIUZtFnhY4GuTuf6DlzgnXO58oDVCZmCW4ULIpbqGeRsvBHR8Sw5JXP/1+TMUYhE8TAgMBAAGjZjBkMB8GA1UdIwQYMBaAFDzIg8eyTI3xc4A2R60f8HanhBZDMB0GA1UdDgQWBBQ8yIPHskyN8XOANketH/B2p4QWQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsFAAOCAgEAkHZ5KR8IOrdfMFy+iOvauvZxfQ84LL6TpB2FQKDjneJUdd7c29UJJFNW/0mp4Gc6jKZab6J8Dx/pNnbH0RqFjGjeRGtJ4Sk0G7gf9zw1S7qut5WJDcisM9l/wXC+zy/KSKKPQmbt0grWOtU7+NNPh1YU76hIrInq/u2sVZyKH8SXQ957fbJk6BX6JTKyNEn05AB6rNSrbOWo8sy2MlcJ7bBsrWYI1t6GcWFh4b36bLu7/dKJWpyFNXXIkKJsgMEDpEQae56+fSSDo0KRNtYB82fNZDIQlGK81rGJWNzAahM+3GD1tgk/3ZVugfaJhcBpoHHKNOGqZAvtirLAIDocno7AzqoeIz974Rh2Olsl2/arApYPyyfi8PMYuFe/d4h+Wie8n+jh5n48lZ2Ve4PK+j+QHD6tTZS4f0bGnPL1puMxzQloltuQWgLDeVfEgrc3snLvjOg8aDzWm/es85lP8XcyW54U4t3JmrNUC2C7v+Uafx7cL7eDeunhs+BRhtGV+IUmjub2IrpqZp3zZqn+LVRdYJIy/qHhjS5+ImckXkFojOmeWhfmEmYSuNP8Oa6cGuXp829qnbxLh9Qzi3TfXV883KLse4kL5Zl7gBA/4hz2hVMyGJ8fY+VvzbaTuOXyvKJ+rGZCTcRSeotBLnIevVMiL7SqOEwN0j4Mfbznfq8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFFTCCAv2gAwIBAgICAxIwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UEAwwPT3BlbkxBTiBSb290IENBMCAXDTI1MDUxNDA4NDcxMFoYDzIwNTUwNTE0MDg0NzEwWjAaMRgwFgYDVQQDDA9PcGVuTEFOIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGibJ04A55kSURTBSKgcBmLnND2I5wws1taKqqU9aaRhB7NtvMHwh2voH9b1brUiulZaZwTN/9kzd4AnXeKQ+0u5tV7Ofk0fzF2MK47n17TS30Yenqc4NuQEKdpKK/pM3VvOEppR/bqtgyLtDmbDnmFOx+zTj/+smTgouwA+Iier0P4s5OohYxn/bjOqwQbHbU79VpGBIWv6/kt55AhH7zvsqqKHkrzTxnsRBv3SBIufrjJr9PIhZBLDrqr56P6KgAi0eoutNt2ToiJbE0WfjU7GI1RSiSN5bGj1zXhjNVzQWs1H9QzRf3c9pl3+haHQZ7FZ1UqiTRewmbNrQ6I9k81au3SttUlb87MyAuDSzatkiq7CjQ8VE1J6te6ZBt2zWpUhHsR/Lg7g3eOw5dL4oZJdK5GgGu/MUajLUXifIqM13Mvg0VTzDhN69VLXLSL0gPcicsQCwJuAza1IC/VqmBGx19fAkyJhOurCXWOgisi0g1+xzPKRphUNwMPUf8vBVOM/Vc6xDIvwVGE3+eWXyhixneFlSpAI03nWWjpwWXihTBoxbfRXO3Y/ilJqrgFN+U4PJcCPA+Wo7ThH0mgX6bOTPcgXMUzT3v3FF6Bx5/PNV3kYrw2yLzribUiS6AGvVGnW4hX2Z6OQvA/aHME8KF+6y6m4pC7FkUjVaRlzWu/wIDAQABo2MwYTAfBgNVHSMEGDAWgBSUaFuoOPk4QLByZP47kj4p1IbCJjAdBgNVHQ4EFgQUlGhbqDj5OECwcmT+O5I+KdSGwiYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAB+/RUC2X6eVoPsFNMkaXO5Iib/ub0JoWhODQm8j2Mr5dpGXESSpXjfDcqDOLuJbWWoflXBLdr8BsVCBqOA9YgCX0H8Br7dUWmCScixxLW0he592/424EvdwifxcKHZLjv9CKV5Txhqnm2djc5RY/nTH5MYVrIh/If2TNO5ydDP6+vgy9GQ4en04VK7rz+PW17O8l7k9/lOmYptZmHgSDAPj/cT3PlG+McqaI5rMSHeEHlzH+PvgWjtSeEhF4FwFBXroDl4/yb4l2JB8bqAZ3vsOXSkigFcZh5MXPe+zuSSW+G8iLr4xoi0CFsP2DaHEyxgqP4B1FtE9nFPo6cvWbwqTVT7QSzqfH+jPJuQvpFXeRF5UFegNZTFT5/uFFPamihakFslEYxeJey1y+OJdLcP6ef87ruSt8amsq56OAETYpnW4JFowlEh0C+QwLGHGGY6WrOgHY/90hJmPgXBdBVg/IoOhzbvk5A+LqZDvxV2/rLNfClw8Kr3g5e8obcB6dWgMCy2z+us0H79ucnmhzQKsjpxM9T1ncHovAQfiD3jVqfHULY53avh0wIAjosoTGbe8dyx80quHe+16qWan7C9idXeAYYJXbZt5hs6hLw4I8M1LsjTg6vwsqiaHZpsmDyyQLdFjNJldG7aosfS9F+BIpuwijF+1dashL0CPsbIJ
-----END CERTIFICATE-----

View File

@@ -0,0 +1,75 @@
-----BEGIN CERTIFICATE-----
MIIEcTCCA1mgAwIBAgIUJFhIMlIJHJ7hW4gEzZuLBUaWjNcwDQYJKoZIhvcNAQEL
BQAwbDELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSkwJwYDVQQDEyBUZWxlY29tIEluZnJhIFBy
b2plY3QgSXNzdWluZyBDQTAeFw0yMTA0MjUyMDMzNTRaFw0yNjA0MTMyMjM4NDZa
MCMxITAfBgNVBAMTGGNhY2VydHMub25lLmRpZ2ljZXJ0LmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJwKRHdkdEQkp32bNi9TdgN4FNRG0nRppguQ
mdCysJHA6/SuyAXNwKSbENysjFrcBkfYTlALjvIMqSu4d26ix6Mv4HnVxLjDzapV
TZhOhfxIbRQa3HNieNup2vMi8jJvgwLcK/4CwhBJsbEMkB5lbyL8UnCBxzW9GGbM
IvurvDFkUDUpUmiFg47nTpjub79KME6NqK38DxKzlUHvJge1TKFM73kZ3YkfWExQ
yRQPRiU5KxMi/Wkr30FOf/rMTx4XNacOgyTJvzcStGwrlr0iGr8eLC1/XVXoOQz3
0lyOeUzTB+HPU1Z2JrbPW5PnGxcQ0f7v/3qkWV1B2wuvFcQk+D0CAwEAAaOCAVIw
ggFOMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFIj2Mhdk10e46DeI+aEZKSSK8Hj+
MB8GA1UdIwQYMBaAFLMbVLjgR6s98ziA5Dzl/QBhbdHoMA4GA1UdDwEB/wQEAwIE
8DAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjCBhgYIKwYBBQUHAQEEejB4MCgGCCsG
AQUFBzABhhxodHRwOi8vb2NzcC5vbmUuZGlnaWNlcnQuY29tMEwGCCsGAQUFBzAC
hkBodHRwOi8vY2FjZXJ0cy5vbmUuZGlnaWNlcnQuY29tL1RlbGVjb21JbmZyYVBy
b2plY3RJc3N1aW5nQ0EuY3J0ME0GA1UdHwRGMEQwQqBAoD6GPGh0dHA6Ly9jcmwu
b25lLmRpZ2ljZXJ0LmNvbS9UZWxlY29tSW5mcmFQcm9qZWN0SXNzdWluZ0NBLmNy
bDANBgkqhkiG9w0BAQsFAAOCAQEADlFwshNPkeI2Gl6ooIauZL9d+6k+RWa5RTle
JWziYL23XVEBT11+dvp4IB9HwVw5dByl3XAfTd1r4qyncwgXQpc6j2X8e45E8izI
z2S1zhLMe1bA2lOiZz/sdpbonvxIHdiISyQI7q3mWQsvNkpkbjivjxLAJTcGPmOS
gc/95YL+2xqPV45XAnPcl5qkLThtmb57Xst1sLWiSS2fUId6HMVuCgZa5su+aAl9
iMXv9YfHcvyfwXBaOtoBlItyMGl60uy0E/Fr5uEhEWi53EIqhty6KQckQBB7wdjQ
eiXNI5Ox5cf+TFdesuKPaoEn3WNpFL9PCA3S5nGegJlZQ4N9Eg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEnDCCA4SgAwIBAgIUVpyCUx1MUeUwxg+7I1BvGFTz7HkwDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjUxMjZaFw0yNjA0MTMyMjM4NDZaMGwx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEpMCcGA1UEAxMgVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IElzc3VpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtKBrq
qd2aKVSk25KfL5xHu8X7/8rJrz3IvyPuVKWhk/N1zabot3suBcGaYNKjnRHxg78R
yKwKzajKYWtiQFqztu24g16LQeAnoUxZnF6a0z3JkkRPsz14A2y8TUhdEe1tx+UU
4VGsk3n+FMmOQHL+79FO57zQC1LwylgfLSltrI6mF3jowVUQvnwzKhUzT87AJ6EO
ndK/q0T/Bgi+aI39zfVOjJjsTJwghvrmYW3iarP1THSKxeib2s02bZKrvvHa5HL4
UI8+LvREpVZl4mzt1z6Nl344Y6f+UeJlYa/Ci0jJqaXJmyVnUbAz+c0i5JfwAVn3
YQzfC4eLnZCmdF8zAgMBAAGjggE3MIIBMzAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSzG1S44EerPfM4gOQ85f0AYW3R6DAfBgNVHSMEGDAWgBQCRpZgebFT9qny
98WfIUDk6ZEB+jAOBgNVHQ8BAf8EBAMCAYYwgYMGCCsGAQUFBwEBBHcwdTAoBggr
BgEFBQcwAYYcaHR0cDovL29jc3Aub25lLmRpZ2ljZXJ0LmNvbTBJBggrBgEFBQcw
AoY9aHR0cDovL2NhY2VydHMub25lLmRpZ2ljZXJ0LmNvbS9UZWxlY29tSW5mcmFQ
cm9qZWN0Um9vdENBLmNydDBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vY3JsLm9u
ZS5kaWdpY2VydC5jb20vVGVsZWNvbUluZnJhUHJvamVjdFJvb3RDQS5jcmwwDQYJ
KoZIhvcNAQELBQADggEBAFbz+K94bHIkBMJqps0dApniUmOn0pO6Q6cGh47UP/kX
IiPIsnYgG+hqYD/qtsiqJhaWi0hixRWn38UmvZxMRk27aSTGE/TWx0JTC3qDGsSe
XkUagumbSfmS0ZyiTwMPeGAjXwyzGorqZWeA95eKfImntMiOf3E7//GK0K7HpCx8
IPCnLZsZD2q/mLyBsduImFIRQJbLAhwIxpcd1qYJk+BlGFL+HtBpEbq6JxW2Xy+v
DpNWc2WIsUTle0rTc9JNJrLX4ChUJmKqf8obKHap3Xh3//qw/jDB9pOAinA33FLJ
EmCnwBvQr9mfNmPBGMYZVU8cPruDQJ57GjmmvdisbJY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDojCCAoqgAwIBAgIUPVYBpqNbcLYygF6Mx+qxSWwQyFowDQYJKoZIhvcNAQEL
BQAwaTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSYwJAYDVQQDEx1UZWxlY29tIEluZnJhIFBy
b2plY3QgUm9vdCBDQTAeFw0yMTA0MTMyMjQyNDRaFw0zMTA0MTMyMjM4NDZaMGkx
CzAJBgNVBAYTAlVTMSQwIgYDVQQKExtUZWxlY29tIEluZnJhIFByb2plY3QsIElu
Yy4xDDAKBgNVBAsTA1RJUDEmMCQGA1UEAxMdVGVsZWNvbSBJbmZyYSBQcm9qZWN0
IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIGCibwf5u
AAwZ+1H8U0e3u2V+0d2gSctucoK86XwUmfe1V2a/qlCYZd29r80IuN1IIeB0naIm
KnK/MzXW87clF6tFd1+HzEvmlY/W4KyIXalVCTEzirFSvBEG2oZpM0yC3AefytAO
aOpA00LaM3xTfTqMKIRhJBuLy0I4ANUVG6ixVebbGuc78IodleqiLoWy2Q9QHyEO
t/7hZndJhiVogh0PveRhho45EbsACu7ymDY+JhlIleevqwlE3iQoq0YcmYADHno6
Eq8vcwLpZFxihupUafkd1T3WJYQAJf9coCjBu2qIhNgrcrGD8R9fGswwNRzMRMpX
720+GjcDW3bJAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFAJG
lmB5sVP2qfL3xZ8hQOTpkQH6MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
AAOCAQEAVjl9dm4epG9NUYnagT9sg7scVQEPfz3Lt6w1NXJXgD8mAUlK0jXmEyvM
dCPD4514n+8+lM7US8fh+nxc7jO//LwK17Wm9FblgjNFR7+anv0Q99T9fP19DLlF
PSNHL2emogy1bl1lLTAoj8nxg2wVKPDSHBGviQ5LR9fsWUIJDv9Bs5k0qWugWYSj
19S6qnHeskRDB8MqRLhKMG82oDVLerSnhD0P6HjySBHgTTU7/tYS/OZr1jI6MPbG
L+/DtiR5fDVMNdBSGU89UNTi0wHY9+RFuNlIuvZC+x/swF0V9R5mN+ywquTPtDLA
5IOM7ItsRmen6u3qu+JXros54e4juQ==
-----END CERTIFICATE-----

View File

@@ -1,31 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ieee8021x
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_SOURCE_URL=https://github.com/blogic/ieee8021x.git
PKG_MIRROR_HASH:=ec3311751a17d37e8ba17d69226392a2bc9ccbcfc3dd01371b8a25148dd41c06
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2023-08-21
PKG_SOURCE_VERSION:=560fe3003fa2a5837b351dba78a4d6652142ce90
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/ieee8021x
SECTION:=net
CATEGORY:=Network
TITLE:=Wired 802.1x
DEPENDS:=+libubox +libubus +libuci
endef
define Package/ieee8021x/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ieee8021x $(1)/usr/sbin/
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,ieee8021x))

View File

@@ -1,6 +0,0 @@
#config network
# option network 'lan'
# list ports 'lan1'
# list ports 'lan2'
# list ports 'lan3'
# list ports 'lan4'

View File

@@ -1,20 +0,0 @@
#!/bin/sh /etc/rc.common
START=80
USE_PROCD=1
PROG=/usr/sbin/ieee8021x
reload_service() {
restart
}
service_triggers() {
procd_add_reload_trigger ieee8021x
}
start_service() {
procd_open_instance
procd_set_param command "$PROG"
procd_set_param respawn
procd_close_instance
}

View File

@@ -27,8 +27,6 @@ start_service() {
cp /etc/config-shadow/ucentral /etc/config/
config_load 'ucentral'
config_get serial 'config' 'serial'
config_get server 'config' 'server'
config_get port 'config' 'port'
config_get debug 'config' 'debug' 0
config_get insecure 'config' 'insecure' 0
@@ -37,6 +35,10 @@ start_service() {
[ "${selfsigned}" == "true" ] && insecure=1
fi
server=$(cat /etc/ucentral/gateway.json | jsonfilter -e '@["server"]')
port=$(cat /etc/ucentral/gateway.json | jsonfilter -e '@["port"]')
[ -n "$server" -a -n "$port" ] || return 0
boot_cause=$(cat /tmp/pstore | jsonfilter -e '@["pstore"][-1]'.boot_cause)
[ -z $boot_cause ] && boot_cause=coldboot
procd_open_instance

View File

@@ -0,0 +1,30 @@
From 4d01f3ee74cd08cb894f372c8cc185d299f977a7 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Fri, 13 Jun 2025 06:28:23 +0200
Subject: [PATCH] use new operational cert and ca
Signed-off-by: John Crispin <john@phrozen.org>
---
main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/main.c b/main.c
index 19a61e8..0adc07e 100644
--- a/main.c
+++ b/main.c
@@ -414,10 +414,10 @@ int main(int argc, char **argv)
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
- info.client_ssl_cert_filepath = UCENTRAL_CONFIG"cert.pem";
+ info.client_ssl_cert_filepath = UCENTRAL_CONFIG"operational.pem";
if (!stat(UCENTRAL_CONFIG"key.pem", &st))
info.client_ssl_private_key_filepath = UCENTRAL_CONFIG"key.pem";
- info.ssl_ca_filepath = UCENTRAL_CONFIG"cas.pem";
+ info.ssl_ca_filepath = UCENTRAL_CONFIG"operational.ca";
info.protocols = protocols;
info.fd_limit_per_thread = 1 + 1 + 1;
info.connect_timeout_secs = 30;
--
2.34.1

View File

@@ -0,0 +1,28 @@
From 8c45f965c30d1cf11e3a5a625a5e2baf3178697f Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Tue, 12 Nov 2024 10:35:52 +0100
Subject: [PATCH] send on/offline events to cloud discovery service
Signed-off-by: John Crispin <john@phrozen.org>
---
ubus.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/main.c
+++ b/main.c
@@ -111,6 +111,7 @@ sul_connect_attempt(struct lws_sorted_us
{
struct per_vhost_data__minimal *vhd;
+ system("ubus call cloud offline");
vhd = lws_container_of(sul, struct per_vhost_data__minimal, sul);
vhd->i.context = vhd->context;
@@ -215,6 +216,7 @@ callback_broker(struct lws *wsi, enum lw
return 0;
case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ system("ubus call cloud online");
ULOG_INFO("connection established\n");
if (!client.selfsigned) {
if (!lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_VALIDITY_TO, &ci, 0))

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

@@ -1,15 +1,14 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <curl/curl.h>
#include <libubox/ulog.h>
static const char *file_cert = "/etc/ucentral/cert.pem";
static const char *file_key = "/etc/ucentral/key.pem";
static const char *file_json = "/etc/ucentral/redirector.json";
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)
@@ -21,8 +20,6 @@ int main(int argc, char **argv)
char *devid = NULL;
char *url;
alarm(15);
while (1) {
int option = getopt(argc, argv, "k:c:o:hi:");
@@ -75,7 +72,7 @@ int main(int argc, char **argv)
return -1;
}
if (asprintf(&url, "https://clientauth.one.digicert.com/iot/api/v2/device/%s", devid) < 0) {
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;
}
@@ -88,7 +85,6 @@ int main(int argc, char **argv)
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLKEY, file_key);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
res = curl_easy_perform(curl);
if (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

@@ -12,21 +12,34 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/jow-/ucode.git
PKG_SOURCE_DATE:=2023-06-06
PKG_SOURCE_VERSION:=c7d84aae09691a99ae3db427c0b2463732ef84f4
PKG_MIRROR_HASH:=38826ae70d886d1d7ada3fc6591ac807169aa28107f60f7f2e617520083525fb
PKG_MIRROR_HASH:=7a4d35d14ede7d853b2095ee239a86aab0b17da2b8cfac814dfa58fabec6374b
PKG_SOURCE_DATE:=2024-04-15
PKG_SOURCE_VERSION:=cfe137be068a7ba1895d3c9bcb7b38d21e5a95dd
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC
PKG_ABI_VERSION:=20220812
PKG_ABI_VERSION:=20230711
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/cmake.mk
CMAKE_OPTIONS += -DSOVERSION=$(PKG_ABI_VERSION) -DLINUX=ON
CMAKE_OPTIONS += \
-DSOVERSION=$(PKG_ABI_VERSION)
CMAKE_HOST_OPTIONS += \
-DCMAKE_SKIP_RPATH=FALSE \
-DCMAKE_INSTALL_RPATH="${STAGING_DIR_HOSTPKG}/lib"
ifeq ($(HOST_OS),Darwin)
CMAKE_HOST_OPTIONS += \
-DCMAKE_MACOSX_RPATH=1
else
CMAKE_HOST_OPTIONS += \
-DUSE_RPATH="${STAGING_DIR_HOSTPKG}/lib"
endif
CMAKE_HOST_OPTIONS += \
-DSOVERSION=$(PKG_ABI_VERSION) \
-DFS_SUPPORT=ON \
-DMATH_SUPPORT=ON \
-DNL80211_SUPPORT=OFF \
@@ -35,8 +48,17 @@ CMAKE_HOST_OPTIONS += \
-DSTRUCT_SUPPORT=ON \
-DUBUS_SUPPORT=OFF \
-DUCI_SUPPORT=OFF \
-DULOOP_SUPPORT=OFF
-DULOOP_SUPPORT=OFF \
-DDEBUG_SUPPORT=ON \
-DLOG_SUPPORT=OFF
ifeq ($(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y)
TARGET_CFLAGS += -DQCA_WIFI_7
endif
ifeq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq40xx),y)
TARGET_CFLAGS += -DQCA_v4_4
endif
define Package/ucode/default
SUBMENU:=ucode
@@ -66,116 +88,41 @@ define Package/libucode
DEPENDS:=+libjson-c
endef
define Package/libucode/description
The libucode package provides the shared runtime library for the ucode interpreter.
endef
define Package/ucode-mod-fs
$(Package/ucode/default)
TITLE+= (filesystem module)
DEPENDS:=ucode
endef
define Package/ucode-mod-fs/description
The filesystem plugin module allows interaction with the local file system.
endef
define Package/ucode-mod-math
$(Package/ucode/default)
TITLE+= (math module)
DEPENDS:=ucode
endef
define Package/ucode-mod-math/description
The math plugin provides access to various <math.h> procedures.
endef
define Package/ucode-mod-nl80211
$(Package/ucode/default)
TITLE+= (nl80211 module)
DEPENDS:=ucode +libnl-tiny +libubox +kmod-mac80211
endef
define Package/ucode-mod-nl80211/description
The nl80211 plugin provides access to the Linux wireless 802.11 netlink API.
endef
define Package/ucode-mod-resolv
$(Package/ucode/default)
TITLE+= (resolv module)
DEPENDS:=ucode
endef
define Package/ucode-mod-resolv/description
The resolv plugin implements simple DNS resolving.
endef
define Package/ucode-mod-rtnl
$(Package/ucode/default)
TITLE+= (rtnl module)
DEPENDS:=ucode +libnl-tiny +libubox
endef
define Package/ucode-mod-rtnl/description
The rtnl plugin provides access to the Linux routing netlink API.
endef
define Package/ucode-mod-struct
$(Package/ucode/default)
TITLE+= (struct module)
DEPENDS:=ucode
endef
define Package/ucode-mod-struct/description
The struct plugin implements Python 3 compatible struct.pack/unpack functionality.
endef
define Package/ucode-mod-ubus
$(Package/ucode/default)
TITLE+= (ubus module)
DEPENDS:=ucode +libubus +libblobmsg-json
endef
define Package/ucode-mod-ubus/description
The ubus module allows ucode template scripts to enumerate and invoke ubus
procedures.
endef
define Package/ucode-mod-uci
$(Package/ucode/default)
TITLE+= (uci module)
DEPENDS:=ucode +libuci
endef
define Package/ucode-mod-uci/description
The uci module allows templates to read and modify uci configuration.
endef
define Package/ucode-mod-uloop
$(Package/ucode/default)
TITLE+= (uloop module)
DEPENDS:=ucode +libubox
endef
define Package/ucode-mod-uloop/description
The uloop module allows ucode scripts to interact with OpenWrt uloop event
loop implementation.
endef
define Build/Prepare
$(Build/Prepare/Default)
$(CP) $(STAGING_DIR)/usr/include/mac80211/uapi/linux/nl80211.h $(PKG_BUILD_DIR)/nl80211_copy.h
endef
define Package/libucode/description
The libucode package provides the shared runtime library for the ucode interpreter.
endef
# 1: name
# 2: cmake symbol
# 3: depends
# 4: description
define UcodeModule
UCODE_MODULES += ucode-mod-$(strip $(1))
CMAKE_OPTIONS += -D$(strip $(2))=$(if $(CONFIG_PACKAGE_ucode-mod-$(strip $(1))),ON,OFF)
PKG_CONFIG_DEPENDS += CONFIG_PACKAGE_ucode-mod-$(strip $(1))
define Package/ucode-mod-$(strip $(1))
$(Package/ucode/default)
TITLE+= ($(strip $(1)) module)
DEPENDS:=ucode $(3)
endef
define Package/ucode-mod-$(strip $(1))/description
$(strip $(4))
endef
define Package/ucode-mod-$(strip $(1))/install
$(INSTALL_DIR) $$(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/$(strip $(1)).so $$(1)/usr/lib/ucode/
endef
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include/ucode
$(CP) $(PKG_INSTALL_DIR)/usr/include/ucode/*.h $(1)/usr/include/ucode/
@@ -193,60 +140,55 @@ define Package/libucode/install
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libucode.so.* $(1)/usr/lib/
endef
define Package/ucode-mod-fs/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/fs.so $(1)/usr/lib/ucode/
endef
define Package/ucode-mod-math/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/math.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
debug, DEBUG_SUPPORT, +libubox +libucode, \
The debug plugin module provides runtime debugging and introspection facilities.))
define Package/ucode-mod-nl80211/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/nl80211.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
fs, FS_SUPPORT, , \
The filesystem plugin module allows interaction with the local file system.))
define Package/ucode-mod-resolv/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/resolv.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
log, LOG_SUPPORT, +libubox, \
The log plugin module provides access to the syslog and libubox ulog APIs.))
define Package/ucode-mod-rtnl/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/rtnl.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
math, MATH_SUPPORT, , \
The math plugin provides access to various <math.h> procedures.))
define Package/ucode-mod-struct/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/struct.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
nl80211, NL80211_SUPPORT, +libnl-tiny +libubox +kmod-mac80211, \
The nl80211 plugin provides access to the Linux wireless 802.11 netlink API.))
define Package/ucode-mod-ubus/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/ubus.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
resolv, RESOLV_SUPPORT, , \
The resolv plugin implements simple DNS resolving.))
define Package/ucode-mod-uci/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/uci.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
rtnl, RTNL_SUPPORT, +libnl-tiny +libubox, \
The rtnl plugin provides access to the Linux routing netlink API.))
define Package/ucode-mod-uloop/install
$(INSTALL_DIR) $(1)/usr/lib/ucode
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/uloop.so $(1)/usr/lib/ucode/
endef
$(eval $(call UcodeModule, \
struct, STRUCT_SUPPORT, , \
The struct plugin implements Python 3 compatible struct.pack/unpack functionality.))
$(eval $(call UcodeModule, \
ubus, UBUS_SUPPORT, +libubus +libblobmsg-json, \
The ubus module allows ucode template scripts to enumerate and invoke ubus procedures.))
$(eval $(call UcodeModule, \
uci, UCI_SUPPORT, +libuci, \
The uci module allows templates to read and modify uci configuration.))
$(eval $(call UcodeModule, \
uloop, ULOOP_SUPPORT, +libubox, \
The uloop module allows ucode scripts to interact with OpenWrt uloop event loop implementation.))
$(eval $(call BuildPackage,libucode))
$(eval $(call BuildPackage,ucode))
$(eval $(call BuildPackage,ucode-mod-fs))
$(eval $(call BuildPackage,ucode-mod-math))
$(eval $(call BuildPackage,ucode-mod-nl80211))
$(eval $(call BuildPackage,ucode-mod-resolv))
$(eval $(call BuildPackage,ucode-mod-rtnl))
$(eval $(call BuildPackage,ucode-mod-struct))
$(eval $(call BuildPackage,ucode-mod-ubus))
$(eval $(call BuildPackage,ucode-mod-uci))
$(eval $(call BuildPackage,ucode-mod-uloop))
$(foreach mod,$(UCODE_MODULES), \
$(eval $(call BuildPackage,$(mod))))
$(eval $(call HostBuild))

View File

@@ -1,10 +1,11 @@
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -38,7 +38,7 @@ limitations under the License.
@@ -37,7 +37,8 @@ limitations under the License.
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
-#include <linux/nl80211.h>
+#define BIT(_n) (1UL << (_n))
+#include "../nl80211_copy.h"
#include <linux/ieee80211.h>
#include <libubox/uloop.h>

View File

@@ -10,91 +10,55 @@ Subject: [PATCH] fixes
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -56,6 +56,8 @@ limitations under the License.
@@ -57,6 +57,33 @@ limitations under the License.
#define NL80211_CMDS_BITMAP_SIZE DIV_ROUND_UP(NL80211_CMD_MAX + 1, 32)
+#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000
+#ifdef QCA_v4_4
+#define NL80211_STA_INFO_CONNECTED_TO_AS NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_FREQUENCY_ATTR_1MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_FREQUENCY_ATTR_2MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_FREQUENCY_ATTR_4MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_FREQUENCY_ATTR_8MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_FREQUENCY_ATTR_16MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_MESHCONF_NOLEARN NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_MESHCONF_CONNECTED_TO_AS NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef QCA_WIFI_7
+#define NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_WIPHY_RADIO_FREQ_ATTR_START NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_WIPHY_RADIO_FREQ_ATTR_END NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_WIPHY_RADIO_ATTR_INDEX NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_ATTR_WIPHY_RADIOS NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_ATTR_VIF_RADIO_MASK NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+
static struct {
int code;
char *msg;
@@ -277,6 +279,14 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -561,7 +588,7 @@ static const uc_nl_nested_spec_t nl80211
+#ifndef NL80211_MESHCONF_NOLEARN
+#define NL80211_MESHCONF_NOLEARN NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef NL80211_MESHCONF_CONNECTED_TO_AS
+#define NL80211_MESHCONF_CONNECTED_TO_AS NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
static const uc_nl_nested_spec_t nl80211_mesh_params_nla = {
.headsize = 0,
.nattrs = 29,
@@ -368,6 +378,14 @@ static const uc_nl_nested_spec_t nl80211
}
};
+#ifndef NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK
+#define NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR
+#define NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
static const uc_nl_nested_spec_t nl80211_peer_measurements_peers_req_data_ftm_nla = {
.headsize = 0,
.nattrs = 13,
@@ -517,6 +535,26 @@ static const uc_nl_nested_spec_t nl80211
}
};
+#ifndef NL80211_FREQUENCY_ATTR_1MHZ
+#define NL80211_FREQUENCY_ATTR_1MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef NL80211_FREQUENCY_ATTR_2MHZ
+#define NL80211_FREQUENCY_ATTR_2MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef NL80211_FREQUENCY_ATTR_4MHZ
+#define NL80211_FREQUENCY_ATTR_4MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef NL80211_FREQUENCY_ATTR_8MHZ
+#define NL80211_FREQUENCY_ATTR_8MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
+#ifndef NL80211_FREQUENCY_ATTR_16MHZ
+#define NL80211_FREQUENCY_ATTR_16MHZ NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
static const uc_nl_nested_spec_t nl80211_wiphy_bands_freqs_nla = {
.headsize = 0,
.nattrs = 25,
@@ -558,6 +596,10 @@ static const uc_nl_nested_spec_t nl80211
}
};
+#ifndef NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS
+#define NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
static const uc_nl_nested_spec_t nl80211_wiphy_bands_iftype_data_nla = {
.headsize = 0,
.nattrs = 7,
@@ -728,6 +770,10 @@ static const uc_nl_nested_spec_t nl80211
- .nattrs = 7,
+ .nattrs = 9,
.attrs = {
{ NL80211_BAND_IFTYPE_ATTR_IFTYPES, "iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, "he_cap_mac", DT_U8, DF_ARRAY, NULL },
@@ -570,6 +597,8 @@ static const uc_nl_nested_spec_t nl80211
{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, "he_cap_ppe", DT_U8, DF_ARRAY, NULL },
{ NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, "he_6ghz_capa", DT_U16, 0, NULL },
{ NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, "vendor_elems", DT_STRING, DF_BINARY, NULL },
+ { NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, "eht_cap_mac", DT_U16, DF_ARRAY, NULL },
+ { NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, "eht_cap_phy", DT_U16, DF_ARRAY, NULL },
}
};
+#ifndef NL80211_STA_INFO_CONNECTED_TO_AS
+#define NL80211_STA_INFO_CONNECTED_TO_AS NL80211_ATTR_NOT_IMPLEMENTED
+#endif
+
static const uc_nl_nested_spec_t nl80211_sta_info_nla = {
.headsize = 0,
.nattrs = 40,

View File

@@ -0,0 +1,67 @@
From 1423ad7b8411a2cb727bfd4e4f3511469abb3214 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jo@mein.io>
Date: Wed, 23 Oct 2024 14:31:49 +0200
Subject: [PATCH] nl80211: cover extended feature and EHT rate info attributes
These new attributes are required when dealing with WiFi 7 radios.
Reported-by: John Crispin <john@phrozen.org>
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
---
lib/nl80211.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -81,6 +81,10 @@ limitations under the License.
#define NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION NL80211_ATTR_NOT_IMPLEMENTED
#define NL80211_ATTR_WIPHY_RADIOS NL80211_ATTR_NOT_IMPLEMENTED
#define NL80211_ATTR_VIF_RADIO_MASK NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_RATE_INFO_EHT_NSS NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_RATE_INFO_EHT_MCS NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_RATE_INFO_EHT_GI NL80211_ATTR_NOT_IMPLEMENTED
+#define NL80211_RATE_INFO_320_MHZ_WIDTH NL80211_ATTR_NOT_IMPLEMENTED
#endif
@@ -695,7 +699,7 @@ static const uc_nl_nested_spec_t nl80211
static const uc_nl_nested_spec_t nl80211_sta_info_bitrate_nla = {
.headsize = 0,
- .nattrs = 18,
+ .nattrs = 22,
.attrs = {
{ NL80211_RATE_INFO_BITRATE, "bitrate", DT_U16, 0, NULL },
{ NL80211_RATE_INFO_BITRATE32, "bitrate32", DT_U32, 0, NULL },
@@ -709,10 +713,14 @@ static const uc_nl_nested_spec_t nl80211
{ NL80211_RATE_INFO_HE_GI, "he_gi", DT_U8, 0, NULL },
{ NL80211_RATE_INFO_HE_DCM, "he_dcm", DT_U8, 0, NULL },
{ NL80211_RATE_INFO_HE_RU_ALLOC, "he_ru_alloc", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_EHT_MCS, "eht_mcs", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_EHT_NSS, "eht_nss", DT_U8, 0, NULL },
+ { NL80211_RATE_INFO_EHT_GI, "eht_gi", DT_U8, 0, NULL },
{ NL80211_RATE_INFO_40_MHZ_WIDTH, "width_40", DT_FLAG, 0, NULL },
{ NL80211_RATE_INFO_80_MHZ_WIDTH, "width_80", DT_FLAG, 0, NULL },
{ NL80211_RATE_INFO_80P80_MHZ_WIDTH, "width_80p80", DT_FLAG, 0, NULL },
{ NL80211_RATE_INFO_160_MHZ_WIDTH, "width_160", DT_FLAG, 0, NULL },
+ { NL80211_RATE_INFO_320_MHZ_WIDTH, "width_320", DT_FLAG, 0, NULL },
{ NL80211_RATE_INFO_10_MHZ_WIDTH, "width_10", DT_FLAG, 0, NULL },
{ NL80211_RATE_INFO_5_MHZ_WIDTH, "width_5", DT_FLAG, 0, NULL },
}
@@ -837,7 +845,7 @@ static const uc_nl_nested_spec_t nl80211
static const uc_nl_nested_spec_t nl80211_msg = {
.headsize = 0,
- .nattrs = 127,
+ .nattrs = 128,
.attrs = {
{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
@@ -864,6 +872,7 @@ static const uc_nl_nested_spec_t nl80211
{ NL80211_ATTR_DFS_REGION, "dfs_region", DT_U8, 0, NULL },
{ NL80211_ATTR_DTIM_PERIOD, "dtim_period", DT_U32, 0, NULL },
{ NL80211_ATTR_DURATION, "duration", DT_U32, 0, NULL },
+ { NL80211_ATTR_EXT_FEATURES, "extended_features", DT_U8, DF_ARRAY, NULL },
{ NL80211_ATTR_FEATURE_FLAGS, "feature_flags", DT_U32, 0, NULL },
{ NL80211_ATTR_FRAME, "frame", DT_STRING, DF_BINARY, NULL },
{ NL80211_ATTR_FRAME_MATCH, "frame_match", DT_STRING, DF_BINARY, NULL },

View File

@@ -0,0 +1,26 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 1 May 2024 18:40:19 +0200
Subject: [PATCH] ubus: fix uc_ubus_have_uloop for eloop+uloop combination
When uloop has been integrated with eloop (in hostapd/wpa_supplicant),
uloop_cancelling will return false, since uloop_run is not being called.
This leads to ubus.defer() calling uloop_run in a context where it can
prevent the other event loop from running.
Fix this by detecting event loop integration via uloop_fd_set_cb being set
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/lib/ubus.c
+++ b/lib/ubus.c
@@ -665,6 +665,9 @@ uc_ubus_have_uloop(void)
bool prev = uloop_cancelled;
bool active;
+ if (uloop_fd_set_cb)
+ return true;
+
uloop_cancelled = true;
active = uloop_cancelling();
uloop_cancelled = prev;

View File

@@ -0,0 +1,341 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 29 Jun 2024 12:03:21 +0200
Subject: [PATCH] nl80211: move access to tb array out of uc_nl_convert_attr
and below
Only one place needs access to another attribute from the tb array
(HE MCS rates). In order to make that access possible, add a flag to indicate
a second attribute dependency via auxdata.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -197,6 +197,7 @@ enum {
DF_OFFSET1 = (1 << 4),
DF_ARRAY = (1 << 5),
DF_BINARY = (1 << 6),
+ DF_RELATED = (1 << 7),
};
typedef struct uc_nl_attr_spec {
@@ -215,6 +216,7 @@ typedef struct uc_nl_nested_spec {
#define SIZE(type) (void *)(uintptr_t)sizeof(struct type)
#define MEMBER(type, field) (void *)(uintptr_t)offsetof(struct type, field)
+#define ATTRID(id) (void *)(uintptr_t)(id)
static const uc_nl_nested_spec_t nl80211_cqm_nla = {
.headsize = 0,
@@ -593,7 +595,7 @@ static const uc_nl_nested_spec_t nl80211
{ NL80211_BAND_IFTYPE_ATTR_IFTYPES, "iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, "he_cap_mac", DT_U8, DF_ARRAY, NULL },
{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, "he_cap_phy", DT_U8, DF_ARRAY, NULL },
- { NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, "he_cap_mcs_set", DT_HE_MCS, 0, NULL },
+ { NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, "he_cap_mcs_set", DT_HE_MCS, DF_RELATED, ATTRID(NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY) },
{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, "he_cap_ppe", DT_U8, DF_ARRAY, NULL },
{ NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, "he_6ghz_capa", DT_U16, 0, NULL },
{ NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, "vendor_elems", DT_STRING, DF_BINARY, NULL },
@@ -1065,12 +1067,12 @@ static bool
uc_nl_parse_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, uc_vm_t *vm, uc_value_t *val, size_t idx);
static uc_value_t *
-uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr **tb, uc_vm_t *vm);
+uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr *attr, struct nlattr *attr2, uc_vm_t *vm);
static bool
uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsize, const uc_nl_attr_spec_t *attrs, size_t nattrs, uc_vm_t *vm, uc_value_t *obj)
{
- struct nlattr **tb, *nla, *nla_nest;
+ struct nlattr **tb, *nla, *nla2, *nla_nest;
size_t i, type, maxattr = 0;
uc_value_t *v, *arr;
int rem;
@@ -1106,9 +1108,7 @@ uc_nl_convert_attrs(struct nl_msg *msg,
attrs[i].auxdata && nla_type(nla) != (intptr_t)attrs[i].auxdata)
continue;
- tb[attrs[i].attr] = nla;
-
- v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb, vm);
+ v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, nla, NULL, vm);
if (!v)
continue;
@@ -1128,7 +1128,12 @@ uc_nl_convert_attrs(struct nl_msg *msg,
v = arr;
}
else {
- v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb, vm);
+ if (attrs[i].flags & DF_RELATED)
+ nla2 = tb[(uintptr_t)attrs[i].auxdata];
+ else
+ nla2 = NULL;
+
+ v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb[attrs[i].attr], nla2, vm);
if (!v)
continue;
@@ -1218,7 +1223,7 @@ uc_nl_parse_rta_nested(const uc_nl_attr_
}
static uc_value_t *
-uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
{
const uc_nl_nested_spec_t *nest = spec->auxdata;
uc_value_t *nested_obj;
@@ -1227,13 +1232,13 @@ uc_nl_convert_rta_nested(const uc_nl_att
if (!nest)
return NULL;
- if (!nla_check_len(tb[spec->attr], nest->headsize))
+ if (!nla_check_len(attr, nest->headsize))
return NULL;
nested_obj = ucv_object_new(vm);
rv = uc_nl_convert_attrs(msg,
- nla_data(tb[spec->attr]), nla_len(tb[spec->attr]), nest->headsize,
+ nla_data(attr), nla_len(attr), nest->headsize,
nest->attrs, nest->nattrs,
vm, nested_obj);
@@ -1247,17 +1252,17 @@ uc_nl_convert_rta_nested(const uc_nl_att
}
static uc_value_t *
-uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
{
uc_value_t *mcs_obj, *mcs_idx;
uint16_t max_rate = 0;
uint8_t *mcs;
size_t i;
- if (!nla_check_len(tb[spec->attr], 16))
+ if (!nla_check_len(attr, 16))
return NULL;
- mcs = nla_data(tb[spec->attr]);
+ mcs = nla_data(attr);
mcs_obj = ucv_object_new(vm);
max_rate = (mcs[10] | ((mcs[11] & 0x3) << 8));
@@ -1282,16 +1287,16 @@ uc_nl_convert_rta_ht_mcs(const uc_nl_att
}
static uc_value_t *
-uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
{
uc_value_t *cap_obj, *mcs_obj, *rx_mask;
struct ieee80211_ht_cap *cap;
size_t i;
- if (!nla_check_len(tb[spec->attr], sizeof(*cap)))
+ if (!nla_check_len(attr, sizeof(*cap)))
return NULL;
- cap = nla_data(tb[spec->attr]);
+ cap = nla_data(attr);
cap_obj = ucv_object_new(vm);
ucv_object_add(cap_obj, "cap_info", ucv_uint64_new(le16toh(cap->cap_info)));
@@ -1316,17 +1321,17 @@ uc_nl_convert_rta_ht_cap(const uc_nl_att
}
static uc_value_t *
-uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
{
uc_value_t *mcs_obj, *mcs_set, *mcs_entry, *mcs_idx;
size_t i, j, max_idx;
uint16_t u16;
uint8_t *mcs;
- if (!nla_check_len(tb[spec->attr], 8))
+ if (!nla_check_len(attr, 8))
return NULL;
- mcs = nla_data(tb[spec->attr]);
+ mcs = nla_data(attr);
mcs_obj = ucv_object_new(vm);
u16 = mcs[0] | (mcs[1] << 8);
@@ -1387,7 +1392,7 @@ uc_nl_convert_rta_vht_mcs(const uc_nl_at
}
static uc_value_t *
-uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, struct nlattr *phy_attr, uc_vm_t *vm)
{
uint8_t bw_support_mask[] = { (1 << 1) | (1 << 2), (1 << 3), (1 << 4) };
uc_value_t *mcs_set, *mcs_bw, *mcs_dir, *mcs_entry, *mcs_idx;
@@ -1395,13 +1400,13 @@ uc_nl_convert_rta_he_mcs(const uc_nl_att
uint16_t u16, phy_cap_0 = 0;
size_t i, j, k, l, max_idx;
- if (!nla_check_len(tb[spec->attr], sizeof(mcs)))
+ if (!nla_check_len(attr, sizeof(mcs)))
return NULL;
- if (nla_check_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY], sizeof(phy_cap_0)))
- phy_cap_0 = nla_get_u16(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
+ if (nla_check_len(phy_attr, sizeof(phy_cap_0)))
+ phy_cap_0 = nla_get_u16(phy_attr);
- memcpy(mcs, nla_data(tb[spec->attr]), sizeof(mcs));
+ memcpy(mcs, nla_data(attr), sizeof(mcs));
mcs_set = ucv_array_new_length(vm, 3);
@@ -1458,14 +1463,14 @@ uc_nl_convert_rta_he_mcs(const uc_nl_att
}
static uc_value_t *
-uc_nl_convert_rta_ie(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_rta_ie(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
{
uc_value_t *ie_arr, *ie_obj;
uint8_t *ie;
size_t len;
- len = nla_len(tb[spec->attr]);
- ie = nla_data(tb[spec->attr]);
+ len = nla_len(attr);
+ ie = nla_data(attr);
if (len < 2)
return NULL;
@@ -1734,7 +1739,7 @@ uc_nl_convert_numval(const uc_nl_attr_sp
}
static uc_value_t *
-uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr **tb, uc_vm_t *vm)
+uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr *attr, struct nlattr *attr2, uc_vm_t *vm)
{
union { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; size_t sz; } t = { 0 };
char buf[sizeof("FF:FF:FF:FF:FF:FF")];
@@ -1751,17 +1756,17 @@ uc_nl_convert_attr(const uc_nl_attr_spec
case DT_U64:
if (spec->flags & DF_ARRAY) {
assert(spec->attr != 0);
- assert((nla_len(tb[spec->attr]) % dt_sizes[spec->type]) == 0);
+ assert((nla_len(attr) % dt_sizes[spec->type]) == 0);
- v = ucv_array_new_length(vm, nla_len(tb[spec->attr]) / dt_sizes[spec->type]);
+ v = ucv_array_new_length(vm, nla_len(attr) / dt_sizes[spec->type]);
- for (i = 0; i < nla_len(tb[spec->attr]); i += dt_sizes[spec->type])
- ucv_array_push(v, uc_nl_convert_numval(spec, nla_data(tb[spec->attr]) + i));
+ for (i = 0; i < nla_len(attr); i += dt_sizes[spec->type])
+ ucv_array_push(v, uc_nl_convert_numval(spec, nla_data(attr) + i));
return v;
}
- else if (nla_check_len(tb[spec->attr], dt_sizes[spec->type])) {
- return uc_nl_convert_numval(spec, nla_data(tb[spec->attr]));
+ else if (nla_check_len(attr, dt_sizes[spec->type])) {
+ return uc_nl_convert_numval(spec, nla_data(attr));
}
return NULL;
@@ -1769,15 +1774,15 @@ uc_nl_convert_attr(const uc_nl_attr_spec
case DT_BOOL:
if (spec->attr == 0)
t.u8 = uc_nl_get_struct_member_u8(base, spec->auxdata);
- else if (nla_check_len(tb[spec->attr], sizeof(t.u8)))
- t.u8 = nla_get_u8(tb[spec->attr]);
+ else if (nla_check_len(attr, sizeof(t.u8)))
+ t.u8 = nla_get_u8(attr);
return ucv_boolean_new(t.u8 != 0);
case DT_FLAG:
if (spec->attr == 0)
t.u8 = uc_nl_get_struct_member_u8(base, spec->auxdata);
- else if (tb[spec->attr] != NULL)
+ else if (attr != NULL)
t.u8 = 1;
return ucv_boolean_new(t.u8 != 0);
@@ -1785,21 +1790,21 @@ uc_nl_convert_attr(const uc_nl_attr_spec
case DT_STRING:
assert(spec->attr != 0);
- if (!nla_check_len(tb[spec->attr], 1))
+ if (!nla_check_len(attr, 1))
return NULL;
- t.sz = nla_len(tb[spec->attr]);
+ t.sz = nla_len(attr);
if (!(spec->flags & DF_BINARY))
t.sz -= 1;
- return ucv_string_new_length(nla_data(tb[spec->attr]), t.sz);
+ return ucv_string_new_length(nla_data(attr), t.sz);
case DT_NETDEV:
if (spec->attr == 0)
t.u32 = uc_nl_get_struct_member_u32(base, spec->auxdata);
- else if (nla_check_len(tb[spec->attr], sizeof(t.u32)))
- t.u32 = nla_get_u32(tb[spec->attr]);
+ else if (nla_check_len(attr, sizeof(t.u32)))
+ t.u32 = nla_get_u32(attr);
if (if_indextoname(t.u32, buf))
return ucv_string_new(buf);
@@ -1809,10 +1814,10 @@ uc_nl_convert_attr(const uc_nl_attr_spec
case DT_LLADDR:
assert(spec->attr != 0);
- if (!nla_check_len(tb[spec->attr], sizeof(*ea)))
+ if (!nla_check_len(attr, sizeof(*ea)))
return NULL;
- ea = nla_data(tb[spec->attr]);
+ ea = nla_data(attr);
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
ea->ether_addr_octet[0], ea->ether_addr_octet[1],
@@ -1824,29 +1829,29 @@ uc_nl_convert_attr(const uc_nl_attr_spec
case DT_INADDR:
assert(spec->attr != 0);
- if (!nla_check_len(tb[spec->attr], sizeof(struct in_addr)) ||
- !inet_ntop(AF_INET, nla_data(tb[spec->attr]), buf, sizeof(buf)))
+ if (!nla_check_len(attr, sizeof(struct in_addr)) ||
+ !inet_ntop(AF_INET, nla_data(attr), buf, sizeof(buf)))
return NULL;
return ucv_string_new(buf);
case DT_NESTED:
- return uc_nl_convert_rta_nested(spec, msg, tb, vm);
+ return uc_nl_convert_rta_nested(spec, msg, attr, vm);
case DT_HT_MCS:
- return uc_nl_convert_rta_ht_mcs(spec, msg, tb, vm);
+ return uc_nl_convert_rta_ht_mcs(spec, msg, attr, vm);
case DT_HT_CAP:
- return uc_nl_convert_rta_ht_cap(spec, msg, tb, vm);
+ return uc_nl_convert_rta_ht_cap(spec, msg, attr, vm);
case DT_VHT_MCS:
- return uc_nl_convert_rta_vht_mcs(spec, msg, tb, vm);
+ return uc_nl_convert_rta_vht_mcs(spec, msg, attr, vm);
case DT_HE_MCS:
- return uc_nl_convert_rta_he_mcs(spec, msg, tb, vm);
+ return uc_nl_convert_rta_he_mcs(spec, msg, attr, attr2, vm);
case DT_IE:
- return uc_nl_convert_rta_ie(spec, msg, tb, vm);
+ return uc_nl_convert_rta_ie(spec, msg, attr, vm);
default:
assert(0);

View File

@@ -0,0 +1,94 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 29 Jun 2024 12:05:29 +0200
Subject: [PATCH] nl80211: add support for multi-attribute arrays
For newly added attributes, the kernel prefers to no longer add a nesting
container attribute. Instead, an attribute with the element type is simply
added multiple times within the outer container.
Add support for this array style, which will be used in the pending wiphy
multi radio support.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -198,6 +198,7 @@ enum {
DF_ARRAY = (1 << 5),
DF_BINARY = (1 << 6),
DF_RELATED = (1 << 7),
+ DF_REPEATED = (1 << 8),
};
typedef struct uc_nl_attr_spec {
@@ -1043,26 +1044,6 @@ uc_nl_get_struct_member_u32(char *base,
return u32;
}
-static void
-uc_nl_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len)
-{
- struct nlattr *nla;
- int rem;
-
- memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
-
- nla_for_each_attr(nla, head, len, rem) {
- int type = nla_type(nla);
-
- if (type <= maxtype)
- tb[type] = nla;
- }
-
- if (rem > 0)
- fprintf(stderr, "netlink: %d bytes leftover after parsing attributes.\n", rem);
-}
-
-
static bool
uc_nl_parse_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, uc_vm_t *vm, uc_value_t *val, size_t idx);
@@ -1086,12 +1067,10 @@ uc_nl_convert_attrs(struct nl_msg *msg,
if (!tb)
return false;
- uc_nl_nla_parse(tb, maxattr, buf + headsize, buflen - headsize);
-
nla_for_each_attr(nla, buf + headsize, buflen - headsize, rem) {
type = nla_type(nla);
- if (type <= maxattr)
+ if (type <= maxattr && !tb[type])
tb[type] = nla;
}
@@ -1099,7 +1078,28 @@ uc_nl_convert_attrs(struct nl_msg *msg,
if (attrs[i].attr != 0 && !tb[attrs[i].attr])
continue;
- if (attrs[i].flags & DF_MULTIPLE) {
+ if (attrs[i].flags & DF_REPEATED) {
+ arr = ucv_array_new(vm);
+
+ nla = tb[attrs[i].attr];
+ rem = buflen - ((void *)nla - buf);
+ for (; nla_ok(nla, rem); nla = nla_next(nla, &rem)) {
+ if (nla_type(nla) != (int)attrs[i].attr)
+ break;
+ v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, nla, NULL, vm);
+ if (!v)
+ continue;
+
+ ucv_array_push(arr, v);
+ }
+ if (!ucv_array_length(arr)) {
+ ucv_put(arr);
+ continue;
+ }
+
+ v = arr;
+ }
+ else if (attrs[i].flags & DF_MULTIPLE) {
arr = ucv_array_new(vm);
nla_nest = tb[attrs[i].attr];

View File

@@ -0,0 +1,50 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 9 Jul 2024 17:53:30 +0200
Subject: [PATCH] nl80211: add wiphy multi-radio support
Support new attributes that describe multiple radios belonging to a single
wiphy.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -842,9 +842,28 @@ static const uc_nl_nested_spec_t nl80211
}
};
+static const uc_nl_nested_spec_t nl80211_radio_freq_range_nla = {
+ .headsize = 0,
+ .nattrs = 2,
+ .attrs = {
+ { NL80211_WIPHY_RADIO_FREQ_ATTR_START, "start", DT_U32, 0, NULL },
+ { NL80211_WIPHY_RADIO_FREQ_ATTR_END, "end", DT_U32, 0, NULL },
+ }
+};
+
+static const uc_nl_nested_spec_t nl80211_wiphy_radio_nla = {
+ .headsize = 0,
+ .nattrs = 3,
+ .attrs = {
+ { NL80211_WIPHY_RADIO_ATTR_INDEX, "index", DT_U32, 0, NULL },
+ { NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE, "freq_ranges", DT_NESTED, DF_REPEATED, &nl80211_radio_freq_range_nla },
+ { NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION, "interface_combinations", DT_NESTED, DF_REPEATED, &nl80211_ifcomb_nla },
+ }
+};
+
static const uc_nl_nested_spec_t nl80211_msg = {
.headsize = 0,
- .nattrs = 128,
+ .nattrs = 129,
.attrs = {
{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
@@ -974,6 +993,7 @@ static const uc_nl_nested_spec_t nl80211
{ NL80211_ATTR_SOFTWARE_IFTYPES, "software_iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
{ NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL },
{ NL80211_ATTR_SURVEY_INFO, "survey_info", DT_NESTED, 0, &nl80211_survey_info_nla },
+ { NL80211_ATTR_WIPHY_RADIOS, "radios", DT_NESTED, DF_MULTIPLE|DF_AUTOIDX, &nl80211_wiphy_radio_nla },
}
};

View File

@@ -0,0 +1,30 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 23 Oct 2024 18:50:10 +0200
Subject: [PATCH] nl80211: add new attributes for multi-radio support
- vif radio mask: used to assign vifs to specific radios
- monitor skip_tx flag: do not pass locally transmitted packets on the monitor interface
- radio antenna mask: radio specific part of the phy antenna mask
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -863,7 +863,7 @@ static const uc_nl_nested_spec_t nl80211
static const uc_nl_nested_spec_t nl80211_msg = {
.headsize = 0,
- .nattrs = 129,
+ .nattrs = 130,
.attrs = {
{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
@@ -994,6 +994,7 @@ static const uc_nl_nested_spec_t nl80211
{ NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL },
{ NL80211_ATTR_SURVEY_INFO, "survey_info", DT_NESTED, 0, &nl80211_survey_info_nla },
{ NL80211_ATTR_WIPHY_RADIOS, "radios", DT_NESTED, DF_MULTIPLE|DF_AUTOIDX, &nl80211_wiphy_radio_nla },
+ { NL80211_ATTR_VIF_RADIO_MASK, "vif_radio_mask", DT_U32, 0, NULL },
}
};

View File

@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: OpenWrt Build System <openwrt@openwrt.org>
Date: Sun, 24 Nov 2024 00:00:00 +0000
Subject: [PATCH] cmake: explicitly link nl80211 and rtnl modules against libnl-tiny
The nl80211 and rtnl modules use symbols from libnl-tiny but were not
being linked against it when the CMake find_library() call failed to
populate the ${libnl_tiny} variable. This resulted in undefined symbol
errors at runtime when loading the modules.
Fix this by explicitly specifying the nl-tiny library name in
target_link_libraries() calls instead of relying on the CMake variable.
Fixes runtime error:
Unable to dlopen file '/usr/lib/ucode/nl80211.so': Error relocating
/usr/lib/ucode/nl80211.so: nl_socket_free: symbol not found
Signed-off-by: OpenWrt Build System <openwrt@openwrt.org>
---
CMakeLists.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -189,7 +189,7 @@ if(RTNL_SUPPORT)
add_library(rtnl_lib MODULE lib/rtnl.c)
set_target_properties(rtnl_lib PROPERTIES OUTPUT_NAME rtnl PREFIX "")
target_link_options(rtnl_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
- target_link_libraries(rtnl_lib ${libnl_tiny} ${libubox})
+ target_link_libraries(rtnl_lib nl-tiny ubox)
endif()
if(NL80211_SUPPORT)
@@ -199,6 +199,6 @@ if(NL80211_SUPPORT)
add_library(nl80211_lib MODULE lib/nl80211.c)
set_target_properties(nl80211_lib PROPERTIES OUTPUT_NAME nl80211 PREFIX "")
target_link_options(nl80211_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
- target_link_libraries(nl80211_lib ${libnl_tiny} ${libubox})
+ target_link_libraries(nl80211_lib nl-tiny ubox)
endif()

View File

@@ -0,0 +1,25 @@
From d5a42e3d2420609a2c745b47e52bbc173e202271 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 11 Dec 2025 08:01:28 +0100
Subject: [PATCH 900/903] uboot-envtools: add udaya board
Signed-off-by: John Crispin <john@phrozen.org>
---
package/boot/uboot-envtools/files/ipq40xx | 1 +
1 file changed, 1 insertion(+)
diff --git a/package/boot/uboot-envtools/files/ipq40xx b/package/boot/uboot-envtools/files/ipq40xx
index d112d9eb40..704e58e462 100644
--- a/package/boot/uboot-envtools/files/ipq40xx
+++ b/package/boot/uboot-envtools/files/ipq40xx
@@ -41,6 +41,7 @@ glinet,gl-b1300 |\
luma,wrtq-329acn |\
openmesh,a42 |\
openmesh,a62 |\
+udaya,a5-id2|\
plasmacloud,pa1200 |\
plasmacloud,pa2200)
ubootenv_add_uci_config "/dev/mtd5" "0x0" "0x10000" "0x10000"
--
2.34.1

View File

@@ -0,0 +1,55 @@
From 7650ca560c9673935e6080be35c497d5e908f1de Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 11 Dec 2025 08:01:48 +0100
Subject: [PATCH 901/903] libnl-tiny: update to version used in v4.2
Signed-off-by: John Crispin <john@phrozen.org>
---
package/libs/libnl-tiny/Makefile | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/package/libs/libnl-tiny/Makefile b/package/libs/libnl-tiny/Makefile
index 48df6a4c8c..4bdd7c1c39 100644
--- a/package/libs/libnl-tiny/Makefile
+++ b/package/libs/libnl-tiny/Makefile
@@ -12,9 +12,9 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/libnl-tiny.git
-PKG_SOURCE_DATE:=2022-05-17
-PKG_SOURCE_VERSION:=b5b2ba09c4f1c8b3c21580aea7223edc2f5e92be
-PKG_MIRROR_HASH:=b957d56aa8c2e7b55184111be69eb8dea734f1feba19e670a91f302459a48a78
+PKG_SOURCE_DATE:=2023-07-27
+PKG_SOURCE_VERSION:=bc92a280186f9becc53c0f17e4e43cfbdeec7e7b
+PKG_MIRROR_HASH:=57c5ac75fdb4413e98e525bee7de419fc6cce5f23389581dafd9ffe22321224d
CMAKE_INSTALL:=1
PKG_LICENSE:=LGPL-2.1
@@ -27,7 +27,7 @@ define Package/libnl-tiny
SECTION:=libs
CATEGORY:=Libraries
TITLE:=netlink socket library
- ABI_VERSION:=$(PKG_SOURCE_DATE)
+ ABI_VERSION:=1
endef
define Package/libnl-tiny/description
@@ -37,13 +37,13 @@ endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig $(1)/usr/include/libnl-tiny
$(CP) $(PKG_INSTALL_DIR)/usr/include/libnl-tiny/* $(1)/usr/include/libnl-tiny
- $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libnl-tiny.so $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl-tiny.so* $(1)/usr/lib/
$(INSTALL_DATA) $(PKG_BUILD_DIR)/libnl-tiny.pc $(1)/usr/lib/pkgconfig
endef
define Package/libnl-tiny/install
$(INSTALL_DIR) $(1)/usr/lib
- $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libnl-tiny.so $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl-tiny.so.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,libnl-tiny))
--
2.34.1

View File

@@ -0,0 +1,56 @@
From ba7a1aa768715d9a533f9c402e30ee7baea9f35b Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 11 Dec 2025 08:02:16 +0100
Subject: [PATCH 902/903] libubox: update to version used in v4.2
Signed-off-by: John Crispin <john@phrozen.org>
---
package/libs/libubox/Makefile | 8 ++++----
.../libs/libubox/patches/001-CLOCK_BOOTTIME.patch | 13 +++++++++++++
2 files changed, 17 insertions(+), 4 deletions(-)
create mode 100644 package/libs/libubox/patches/001-CLOCK_BOOTTIME.patch
diff --git a/package/libs/libubox/Makefile b/package/libs/libubox/Makefile
index ad9016edb8..6bba69ed27 100644
--- a/package/libs/libubox/Makefile
+++ b/package/libs/libubox/Makefile
@@ -1,13 +1,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=libubox
-PKG_RELEASE=2
+PKG_RELEASE=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/libubox.git
-PKG_MIRROR_HASH:=f9f9c631e8167597ce721c64a0023dae9e0f1b2cc37ae846a49984d535a3c480
-PKG_SOURCE_DATE:=2023-07-05
-PKG_SOURCE_VERSION:=75a3b870cace1171faf57bd55e5a9a2f1564f757
+PKG_MIRROR_HASH:=242e33eca235124c7e005d25fbc8f8bf08a324335343e60278d4535c91157ba4
+PKG_SOURCE_DATE:=2024-03-29
+PKG_SOURCE_VERSION:=eb9bcb64185ac155c02cc1a604692c4b00368324
PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE))
CMAKE_INSTALL:=1
diff --git a/package/libs/libubox/patches/001-CLOCK_BOOTTIME.patch b/package/libs/libubox/patches/001-CLOCK_BOOTTIME.patch
new file mode 100644
index 0000000000..5e78d5ade9
--- /dev/null
+++ b/package/libs/libubox/patches/001-CLOCK_BOOTTIME.patch
@@ -0,0 +1,13 @@
+Index: libubox-2023-05-23-82fa6480/uloop.c
+===================================================================
+--- libubox-2023-05-23-82fa6480.orig/uloop.c
++++ libubox-2023-05-23-82fa6480/uloop.c
+@@ -293,7 +293,7 @@ static void uloop_gettime(struct timeval
+ {
+ struct timespec ts;
+
+- clock_gettime(CLOCK_MONOTONIC, &ts);
++ clock_gettime(CLOCK_BOOTTIME, &ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
--
2.34.1

View File

@@ -0,0 +1,42 @@
From 85a7d0292d962a3db6549871e5402e40939ddb1c Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 11 Dec 2025 08:02:43 +0100
Subject: [PATCH 903/903] ipq40xx: add insta partitions
Signed-off-by: John Crispin <john@phrozen.org>
---
.../arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts
index ee2d4ac374..421113607e 100644
--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts
+++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts
@@ -90,7 +90,6 @@
APPSBLENV@e0000 {
label = "APPSBLENV";
reg = <0xe0000 0x10000>;
- read-only;
};
APPSBL@f0000 {
label = "APPSBL";
@@ -104,7 +103,15 @@
};
firmware@180000 {
label = "firmware";
- reg = <0x180000 0x1e70000>;
+ reg = <0x180000 0x1e50000>;
+ };
+ insta1@1ff0000 {
+ label = "insta1";
+ reg = <0x1fd0000 0x10000>;
+ };
+ insta2@1ff0000 {
+ label = "insta2";
+ reg = <0x1fe0000 0x10000>;
};
certificates@1ff0000 {
label = "certificates";
--
2.34.1

View File

@@ -20,7 +20,7 @@ packages:
- curl
- dnsmasq-full
- dynamic-vlan
- firstcontact
- cloud_discovery
- gre
- ethtool
- ieee8021x