ieee8021x: replace c code with ucode

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2023-10-06 12:41:20 +02:00
parent f1363f70e9
commit b2ad71e97d
12 changed files with 497 additions and 23 deletions

View File

@@ -0,0 +1,33 @@
Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/ap/vlan_init.c
+++ hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
@@ -37,7 +37,14 @@ static int vlan_if_add(struct hostapd_da
}
#endif /* CONFIG_WEP */
- if (!vlan_exists)
+ if (!hapd->driver || !hapd->driver->if_add) {
+ char *dot = strstr(vlan->ifname, ".");
+ if (dot)
+ *dot = '\0';
+ ret = 0;
+ }
+
+ else if (!vlan_exists)
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
else if (!existsok)
return -1;
Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/ap/vlan_init.c
+++ hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
@@ -59,7 +59,7 @@ static int vlan_if_add(struct hostapd_da
if (hapd->wpa_auth)
ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
- if (!ret && !vlan_exists)
+ if (!ret && !vlan_exists && hapd->driver->if_add)
hostapd_ubus_add_vlan(hapd, vlan);
if (ret == 0)

View File

@@ -431,6 +431,10 @@ radius_user_parse_methods(struct eap_user *eap, struct blob_attr *data)
eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
continue;
}
if (!strcmp(method, "MACACL")) {
eap->macacl = 1;
continue;
}
}
n++;
}

View File

@@ -24,6 +24,7 @@
#include "taxonomy.h"
#include "airtime_policy.h"
#include "hw_features.h"
#include "ieee802_11_auth.h"
static struct ubus_context *ctx;
static struct blob_buf b;
@@ -1604,11 +1605,47 @@ hostapd_wired_del_clients(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
enum {
MAC_AUTH_ADDR,
__MAC_AUTH_MAX
};
static const struct blobmsg_policy mac_auth_policy[__MAC_AUTH_MAX] = {
[MAC_AUTH_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
};
static int
hostapd_wired_mac_auth(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
struct blob_attr *tb[__MAC_AUTH_MAX];
struct radius_sta rad_info;
struct sta_info *sta;
u8 addr[ETH_ALEN];
int acl_res;
blobmsg_parse(mac_auth_policy, __MAC_AUTH_MAX, tb, blob_data(msg), blob_len(msg));
if (hwaddr_aton(blobmsg_data(tb[MAC_AUTH_ADDR]), addr))
return UBUS_STATUS_INVALID_ARGUMENT;
acl_res = hostapd_allowed_address(hapd, addr, NULL, 0, &rad_info, 0);
if (acl_res == HOSTAPD_ACL_REJECT) {
wpa_printf(MSG_ERROR, "Ignore new peer notification\n");
return UBUS_STATUS_INVALID_ARGUMENT;
}
return 0;
}
static const struct ubus_method wired_methods[] = {
UBUS_METHOD_NOARG("reload", hostapd_bss_reload),
UBUS_METHOD_NOARG("get_clients", hostapd_wired_get_clients),
UBUS_METHOD_NOARG("del_clients", hostapd_wired_del_clients),
UBUS_METHOD_NOARG("get_status", hostapd_wired_get_status),
UBUS_METHOD("mac_auth", hostapd_wired_mac_auth, mac_auth_policy),
};
static struct ubus_object_type wired_object_type =
@@ -1847,6 +1884,8 @@ void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *
blob_buf_init(&b, 0);
blobmsg_add_macaddr(&b, "address", sta->addr);
if (sta->vlan_id)
blobmsg_add_u32(&b, "vlan", sta->vlan_id);
blobmsg_add_string(&b, "ifname", hapd->conf->iface);
if (sta->bandwidth[0] || sta->bandwidth[1]) {
void *r = blobmsg_open_array(&b, "rate-limit");

View File

@@ -5,15 +5,9 @@ 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
PKG_SOURCE_DATE:=2023-10-05
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/ieee8021x
SECTION:=net
@@ -22,9 +16,11 @@ define Package/ieee8021x
DEPENDS:=+libubox +libubus +libuci
endef
define Build/Compile
endef
define Package/ieee8021x/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ieee8021x $(1)/usr/sbin/
$(CP) ./files/* $(1)
endef

View File

@@ -1,5 +1,4 @@
#config network
# option network 'lan'
# list ports 'lan1'
# list ports 'lan2'
# list ports 'lan3'

View File

@@ -2,9 +2,10 @@
START=80
USE_PROCD=1
PROG=/usr/sbin/ieee8021x
PROG=/usr/bin/ieee8021x.uc
reload_service() {
ubus call ieee8021x reload
restart
}

View File

@@ -0,0 +1,264 @@
#!/usr/bin/ucode
let ubus = require('ubus').connect();
let uci = require('uci').cursor();
let uloop = require('uloop');
let rtnl = require('rtnl');
let fs = require('fs');
let hapd_subscriber;
let device_subscriber;
let ifaces = {};
/* load UCI */
let config;
function config_load() {
config = uci.get_all('ieee8021x', '@config[0]');
config.ports = {};
for (let k, port in uci.get_all('ieee8021x')) {
if (port['.type'] != 'port')
continue;
config.ports[k] = port;
}
}
/* set a wired ports auth state */
function netifd_handle_iface(name, auth_status, vlan) {
let msg = { name, auth_status, auth_vlans: [ ifaces[name].default_vlan + ':u' ]};
if (ifaces[name].upstream && vlan)
msg.auth_vlans = [ vlan + ':u' ];
ubus.call('network.device', 'set_state', msg);
if (auth_status && ifaces[name].upstream && vlan) {
for (let wan in ifaces[name].wan_ports) {
let msg = {
name: wan,
vlan: [ `${vlan}:t` ]
};
ubus.call('network.interface.up_none', 'add_device', msg);
ubus.call('udevstats', 'add_device', { device: wan, vlan });
}
}
ifaces[name].authenticated = auth_status;
}
/* handle events from hostapd */
function hapd_subscriber_notify_cb(notify) {
switch(notify.type) {
case 'sta-authorized':
printf('authenticated station\n');
push(ifaces[notify.data.ifname].lladdr, notify.data.address);
netifd_handle_iface(notify.data.ifname, true, notify.data.vlan);
break;
};
return 0;
}
/* remove arp and rate limit for a client */
function flush_iface(name) {
/* flush all arp entries */
let neighs = rtnl.request(rtnl.const.RTM_GETNEIGH, rtnl.const.NLM_F_DUMP, { dev: name });
for (let neigh in neighs)
if (neigh.lladdr in ifaces[name].lladdr) {
rtnl.request(rtnl.const.RTM_DELNEIGH, 0, { dst: neigh.dst, dev: neigh.dev, family: neigh.family });
ubus.call('ratelimit', 'client_delete', { device: neigh.dev, address: neigh.lladdr });
}
ifaces[name].lladdr = [];
}
/* handle events from netifd */
function device_subscriber_notify_cb(notify) {
switch(notify.type) {
case 'link_down':
if (!ifaces[notify.data.name])
break;
/* de-auth all clients */
ubus.call(ifaces[notify.data.name].path, 'del_clients');
ifaces[notify.data.name].authenticated = false;
flush_iface(notify.data.name);
ubus.call('ratelimit', 'device_delete', { device: notify.data.name });
break;
};
return 0;
}
function subscriber_remove_cb(remove) {
}
/* track and subscribe to a hostapd/netifd object */
function ubus_unsub_object(add, id, path) {
let object = split(path, '.');
if (path == 'network.device' && add) {
device_subscriber.subscribe(path);
}
if (object[0] != 'hostapd' || !ifaces[object[1]])
return;
if (add) {
printf('adding %s\n', path);
hapd_subscriber.subscribe(path);
ifaces[object[1]].hostapd = true;
ifaces[object[1]].path = path;
} else {
printf('remove: %.J\n', remove);
netifd_handle_iface(object[1], false);
delete ifaces[object[1]];
}
}
/* try to add all enumerated objects */
function ubus_listener_cb(event, payload) {
ubus_unsub_object(event == 'ubus.object.add', payload.id, payload.path);
}
/* setup the ubus object listener, allowing us to track hostapd objects that get added and removed */
function ubus_listener_init() {
/* setup the notification listener */
hapd_subscriber = ubus.subscriber(hapd_subscriber_notify_cb, subscriber_remove_cb);
device_subscriber = ubus.subscriber(device_subscriber_notify_cb, subscriber_remove_cb);
/* enumerate all existing ojects */
let list = ubus.list();
for (let k, path in list)
ubus_unsub_object(true, 0, path);
/* register add/remove handlers */
ubus.listener('ubus.object.add', ubus_listener_cb);
ubus.listener('ubus.object.remove', ubus_listener_cb);
}
/* generate a hostapd configuration */
function hostapd_start(iface) {
let path = '/var/run/hostapd-' + iface + '.conf';
let file = fs.open(path, 'w+');
file.write('driver=wired\n');
file.write('ieee8021x=1\n');
file.write('eap_reauth_period=0\n');
file.write('ctrl_interface=/var/run/hostapd\n');
file.write('interface=' + iface + '\n');
file.write('ca_cert=' + config.ca + '\n');
file.write('server_cert=' + config.cert + '\n');
file.write('private_key=' + config.key + '\n');
file.write('dynamic_vlan=1\n');
file.write('vlan_no_bridge=1\n');
file.write('vlan_naming=1\n');
if (config.auth_server_addr) {
file.write('dynamic_own_ip_addr=1\n');
file.write('auth_server_addr=' + config.auth_server_addr + '\n');
file.write('auth_server_port=' + config.auth_server_port + '\n');
file.write('auth_server_shared_secret=' + config.auth_server_secret + '\n');
if (config.acct_server_addr && config.acct_server_port && config.acct_server_secret + '\n') {
file.write('acct_server_addr=' + config.addr + '\n');
file.write('acct_server_port=' + config.port + '\n');
file.write('acct_server_shared_secret=' + config.secret + '\n');
}
if (config.nas_identifier)
file.write('nas_identifier=' + radius.nas_identifier + '\n');
if (config.coa_server_addr && config.coa_server_addr.port && config.coa_server_secret) {
file.write('radius_das_client=' + config.coa_server_addr + ' ' + config.coa_server_secret + '\n');
file.write('radius_das_port=' + config.coa_server_port + '\n');
}
if (+config.mac_address_bypass)
file.write('macaddr_acl=2\n');
} else {
file.write('eap_server=1\n');
file.write('eap_user_file=/var/run/hostapd-ieee8021x.eap_user\n');
}
file.close();
/* is hostapd already running ? */
if (ifaces[iface].hostapd) {
printf('hostapd.%s is already running\n', iface);
ubus.call(ifaces[iface].path, 'reload');
} else {
ubus.call('hostapd', 'config_add', { iface, config: path });
}
system('ifconfig ' + iface + ' up');
}
/* build a list of all running and new interfaces */
function prepare_ifaces() {
for (let k, v in ifaces)
v.active = false;
for (let k, port in config.ports) {
ifaces[port.iface] ??= {};
ifaces[port.iface].active = true;
ifaces[port.iface].authenticated = false;
ifaces[port.iface].default_vlan = +port.vlan;
ifaces[port.iface].wan_ports = port.wan_ports;
ifaces[port.iface].lladdr = [];
}
for (let iface, v in ifaces) {
if (v.active)
continue;
ubus.call('hostapd', 'config_remove', { iface });
delete ifaces[iface];
system('ifconfig ' + iface + ' down');
}
}
/* start all active interfaces */
function start_ifaces() {
for (let iface, v in ifaces)
hostapd_start(iface);
}
/* shutdown all interfaces */
function shutdown() {
for (let iface, v in ifaces) {
printf('shutdown\n');
ubus.call('hostapd', 'config_remove', { iface });
netifd_handle_iface(iface, false);
flush_iface(iface);
ubus.call('ratelimit', 'device_delete', { device: iface });
}
}
/* the object published on ubus */
let ubus_methods = {
dump: {
call: function(req) {
return ifaces;
},
args: {
}
},
reload: {
call: function(req) {
config_load();
prepare_ifaces();
start_ifaces();
return 0;
},
args: {
}
},
};
/* handle rtnl events for carrier-down events */
function rtnl_cb(msg) {
if (msg.cmd != rtnl.const.RTM_NEWNEIGH)
return;
if (!ifaces[msg.msg.dev] || ifaces[msg.msg.dev].authenticated)
return;
ubus.call(ifaces[msg.msg.dev].path, 'mac_auth', { addr: msg.msg.lladdr });
}
uloop.init();
ubus.publish('ieee8021x', ubus_methods);
config_load();
rtnl.listener(rtnl_cb, null, [ rtnl.const.RTNLGRP_NEIGH ]);
prepare_ifaces();
ubus_listener_init();
start_ifaces();
uloop.run();
uloop.done();
shutdown();

View File

@@ -4,10 +4,10 @@ PKG_NAME:=ucentral-schema
PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-schema.git
PKG_MIRROR_HASH:=93fb1bc67f95bf805c5b603dd0ee92e79d3fb631cfdab6c729f621d10554709a
PKG_MIRROR_HASH:=60480da28aa8eebf6b39d28ab0e2751e8fed2ad7a73ae4dc9753aada7dd8b081
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2022-05-29
PKG_SOURCE_VERSION:=a473a2d4542628d2bc021543cfd50f537dbaf251
PKG_SOURCE_VERSION:=9d2312a51033c21be48722fda62d56b23bcaabe3
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -0,0 +1,55 @@
{
"uuid": 2,
"interfaces": [
{
"name": "WAN",
"role": "upstream",
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ipv4": {
"addressing": "dynamic"
}
},
{
"name": "LAN",
"role": "downstream",
"services": [ "ssh" ],
"ethernet": [
{
"select-ports": [
"LAN2"
]
}
],
"ieee8021x-ports": [ "LAN1" ],
"ipv4": {
"addressing": "static",
"subnet": "192.168.1.1/24",
"dhcp": {
"lease-first": 10,
"lease-count": 100,
"lease-time": "6h"
}
}
}
],
"services": {
"ieee8021x": {
"mode": "radius",
"radius": {
"auth-server-addr": "192.168.178.5",
"auth-server-port": 1812,
"auth-server-secret": "secret",
"mac-address-bypass": true
}
},
"ssh": {
"port": 22
}
}
}

View File

@@ -18,14 +18,15 @@
{
"name": "LAN",
"role": "downstream",
"services": [ "ieee8021x", "ssh" ],
"services": [ "ssh" ],
"ethernet": [
{
"select-ports": [
"LAN*"
"LAN2"
]
}
],
"ieee8021x-ports": [ "LAN1" ],
"ipv4": {
"addressing": "static",
"subnet": "192.168.1.1/24",
@@ -39,15 +40,14 @@
],
"services": {
"ieee8021x": {
"use-local-certificates": true,
"users": [
{
"user-name": "john",
"password": "aaaaaaaa"
}
]
"mode": "radius",
"radius": {
"auth-server-addr": "192.168.178.5",
"auth-server-port": 1812,
"auth-server-secret": "secret"
}
},
"ssh": {
"ssh": {
"port": 22
}
}

View File

@@ -0,0 +1,54 @@
{
"uuid": 2,
"interfaces": [
{
"name": "WAN",
"role": "upstream",
"ethernet": [
{
"select-ports": [
"WAN*"
]
}
],
"ieee8021x-ports": [ "LAN1" ],
"ipv4": {
"addressing": "dynamic"
}
},
{
"name": "LAN",
"role": "downstream",
"services": [ "ssh" ],
"ethernet": [
{
"select-ports": [
"LAN2"
]
}
],
"ipv4": {
"addressing": "static",
"subnet": "192.168.1.1/24",
"dhcp": {
"lease-first": 10,
"lease-count": 100,
"lease-time": "6h"
}
}
}
],
"services": {
"ieee8021x": {
"mode": "radius",
"radius": {
"auth-server-addr": "192.168.178.5",
"auth-server-port": 1812,
"auth-server-secret": "secret"
}
},
"ssh": {
"port": 22
}
}
}

View File

@@ -0,0 +1,29 @@
From 2060e4df4005eff32ce2f0e9c0649b64b046229b Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Fri, 3 Nov 2023 09:36:58 +0100
Subject: [PATCH] netifd: update to latest HEAD
Signed-off-by: John Crispin <john@phrozen.org>
---
package/network/config/netifd/Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile
index e60e592098..4bcb570a49 100644
--- a/package/network/config/netifd/Makefile
+++ b/package/network/config/netifd/Makefile
@@ -5,9 +5,9 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
+PKG_MIRROR_HASH:=7184feb320d1f9dd4a89e7e0375cbdbcb514be7cf925c1a6329cbff1f1140660
PKG_SOURCE_DATE:=2023-09-19
-PKG_SOURCE_VERSION:=7a58b995fdbecd9beed57e4d66d42cb3cf66aee2
-PKG_MIRROR_HASH:=a460a3b912047f8802eb24bb737084a08dad65b2dd520e5f5e7459379d1fcf8c
+PKG_SOURCE_VERSION:=827a02f0343c58d3efc3ba3b381ed8de392f71fc
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=GPL-2.0
--
2.34.1