ucentral: various updates and fixes

* Gateway and client are now talking jsonrpc on the wire.
* update the datamodel to the latest version.
* add github workflow
* add zero touch on-boarding

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2021-03-29 16:02:59 +02:00
parent 528a778e38
commit bc13ab4544
35 changed files with 408 additions and 91 deletions

37
.github/workflows/build-dev.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Build OpenWrt with OpenSync
on:
push:
branches: [ uCentral-* ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: ['e8450', 'ea8300', 'wf194c', 'zyxel_gs1900-10hp', 'edgecore_ecs4100-12ph']
steps:
- uses: actions/checkout@v2
- name: Build image for ${{ matrix.target }}
id: build
run: |
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
make -j TARGET=${{ matrix.target }}
- name: Package and upload image for ${{ matrix.target }}
env:
GH_BUILD_USERNAME: ${{ secrets.GH_BUILD_USERNAME }}
GH_BUILD_PASSWORD: ${{ secrets.GH_BUILD_PASSWORD }}
ARTIFACTORY_USERNAME: cicd-indoor-main
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
run: |
BRANCH=$(git rev-parse --abbrev-ref HEAD)
LOWERCASE_TARGET=`echo ${{ matrix.target }} | tr '[:upper:]' '[:lower:]'`
TAR_NAME="$LOWERCASE_TARGET-$BRANCH.tar.gz"
ls openwrt/bin/targets/
tar cfz "$TAR_NAME" -C openwrt/bin/targets/ .
curl -u $GH_BUILD_USERNAME:$GH_BUILD_USERNAME -T "$TAR_NAME" "https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/$LOWERCASE_TARGET/uCentral/dev/"$TAR_NAME""

20
README.md Normal file
View File

@@ -0,0 +1,20 @@
# Setting up your build machine
Requires a recent linux installation. Older systems without python 3.7 will have trouble. See this link for details: https://openwrt.org/docs/guide-developer/quickstart-build-images
Install build packages: sudo apt install build-essential libncurses5-dev gawk git libssl-dev gettext zlib1g-dev swig unzip time rsync python3 python3-setuptools python3-yaml.
# Doing a native build on Linux
First we need to clone and setup our tree. This will result in an openwrt/.
```
python3 setup.py --setup
```
Next we need to select the profile and base package selection. This setup will install the feeds, packages and generate the .config file.
```
cd openwrt
./scripts/gen_config.py ea8300 ucentral-ap wifi
```
Finally we can build the tree.
```
make -j X V=s
```

View File

@@ -7,7 +7,6 @@ TARGET=${1}
if [ -z "$1" ]; then
echo "Error: please specify TARGET"
echo "One of: WF194C, ZYXEL_GS1900-10HP"
exit 1
fi
@@ -19,20 +18,8 @@ else
echo "### OpenWrt repo already setup"
fi
case "${TARGET}" in
WF194C)
TARGET=wf194c
;;
ZYXEL_GS1900-10HP)
TARGET=zyxel_gs1900-10hp
;;
*)
echo "${TARGET} is unknown"
exit 1
;;
esac
cd ${BUILD_DIR}
./scripts/gen_config.py ${TARGET} ucentral-ap || exit 1
./scripts/gen_config.py ${TARGET} || exit 1
cd -
echo "### Building image ..."

View File

@@ -0,0 +1,25 @@
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
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

@@ -0,0 +1,13 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
PROG=/usr/bin/ucode
start_service() {
procd_open_instance
procd_set_param command "$PROG" -m uci -m fs -i /usr/share/ucentral/firstcontact.uc
procd_set_param respawn 1 60 0
procd_close_instance
}

View File

@@ -0,0 +1,2 @@
#!/bin/sh
/etc/init.d/ucentral disable

View File

@@ -0,0 +1,57 @@
{%
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();
ret = system(sprintf('/usr/sbin/firstcontact -i %s', devid));
if (ret) {
warn("firstcontact failed to contact redirector\n");
exit(1);
}
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);
}
}
let config = {};
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);
}
let cursor = uci.cursor("/etc/config-shadow/");
cursor.load("ucentral");
cursor.set("ucentral", "config", "server", config.Redirector);
cursor.set("ucentral", "config", "serial", devid);
cursor.commit();
warn("firstcontact: managed to look up redirector\n");
system("/etc/init.d/ucentral enable");
system("/etc/init.d/ucentral restart");
system("/etc/init.d/firstcontact disable");
system("/etc/init.d/firstcontact stop");
%}

View File

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

View File

@@ -14,7 +14,9 @@ validate_rtty_section() {
'port:port' \
'ssl:bool:0' \
'token:maxlength(32)' \
'verbose:bool:0'
'verbose:bool:0' \
'enable:bool:0' \
'interval:uinteger:0'
}
start_rtty() {
@@ -27,6 +29,8 @@ start_rtty() {
return 1
}
[ $enable -eq 0 -a $interval -eq 0 ] && return 1
[ -n "$interface" ] && network_get_device ifname "$interface"
[ -z "$ifname" -a -z "$id" ] && {
@@ -50,7 +54,8 @@ start_rtty() {
[ "$ssl" = "1" ] && procd_append_param command -s
[ -n "$token" ] && procd_append_param command -t "$token"
[ "$verbose" = "1" ] && procd_append_param command -v
procd_set_param respawn
[ "$interval" -eq "0" ] || procd_append_param command -e $interval
[ "$interval" -eq "0" ] && procd_set_param respawn
procd_close_instance
}

View File

@@ -0,0 +1,68 @@
Index: rtty-7.1.4/src/main.c
===================================================================
--- rtty-7.1.4.orig/src/main.c
+++ rtty-7.1.4/src/main.c
@@ -37,6 +37,8 @@ enum {
LONG_OPT_HELP = 1
};
+static int force_exit;
+
static void signal_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
if (w->signum == SIGINT) {
@@ -53,6 +55,7 @@ static struct option long_options[] = {
{"token", required_argument, NULL, 't'},
{"verbose", no_argument, NULL, 'v'},
{"version", no_argument, NULL, 'V'},
+ {"exit", required_argument, NULL, 'V'},
{"help", no_argument, NULL, LONG_OPT_HELP},
{0, 0, 0, 0}
};
@@ -79,10 +82,16 @@ static void usage(const char *prog)
exit(1);
}
+static void timeout_cb(EV_P_ ev_timer *w, int revents)
+{
+ exit(1);
+}
+
int main(int argc, char **argv)
{
struct ev_loop *loop = EV_DEFAULT;
struct ev_signal signal_watcher;
+ struct ev_timer timeout_watcher;
bool background = false;
bool verbose = false;
struct rtty rtty = {
@@ -95,7 +104,7 @@ int main(int argc, char **argv)
int c;
while (true) {
- c = getopt_long(argc, argv, "I:h:p:d:asDt:f:RS:vV", long_options, &option_index);
+ c = getopt_long(argc, argv, "I:h:p:d:asDt:f:RS:vVe:", long_options, &option_index);
if (c == -1)
break;
@@ -146,6 +155,9 @@ int main(int argc, char **argv)
case LONG_OPT_HELP:
usage(argv[0]);
break;
+ case 'e':
+ force_exit = atoi(optarg);
+ break;
default: /* '?' */
usage(argv[0]);
break;
@@ -167,6 +179,10 @@ int main(int argc, char **argv)
ev_signal_init(&signal_watcher, signal_cb, SIGINT);
ev_signal_start(loop, &signal_watcher);
+ if (force_exit) {
+ ev_timer_init(&timeout_watcher, timeout_cb, force_exit, 0.);
+ ev_timer_start(loop, &timeout_watcher);
+ }
if (rtty_start(&rtty) < 0)
return -1;

View File

@@ -1,65 +0,0 @@
Index: rtty-7.1.4/src/rtty.c
===================================================================
--- rtty-7.1.4.orig/src/rtty.c
+++ rtty-7.1.4/src/rtty.c
@@ -308,7 +308,8 @@ static void parse_msg(struct rtty *rtty)
case MSG_TYPE_LOGOUT:
tty_logout(rtty, buffer_pull_u8(rb));
- break;
+ exit(1);
+ break;
case MSG_TYPE_TERMDATA:
write_data_to_tty(rtty, buffer_pull_u8(rb), msglen - 1);
@@ -429,12 +430,12 @@ static void rtty_timer_cb(struct ev_loop
return;
}
- if (now - rtty->active > RTTY_HEARTBEAT_INTEVAL * 3 / 2) {
+/* if (now - rtty->active > RTTY_HEARTBEAT_INTEVAL * 3 / 2) {
log_err("Inactive too long time\n");
rtty_exit(rtty);
return;
}
-
+*/
if (now - rtty->last_heartbeat > RTTY_HEARTBEAT_INTEVAL - 1) {
rtty->last_heartbeat = now;
rtty_send_msg(rtty, MSG_TYPE_HEARTBEAT, NULL, 0);
Index: rtty-7.1.4/src/main.c
===================================================================
--- rtty-7.1.4.orig/src/main.c
+++ rtty-7.1.4/src/main.c
@@ -95,7 +95,7 @@ int main(int argc, char **argv)
int c;
while (true) {
- c = getopt_long(argc, argv, "I:h:p:d:asDt:f:RS:vV", long_options, &option_index);
+ c = getopt_long(argc, argv, "I:h:p:d:asDt:f:RS:vVT:", long_options, &option_index);
if (c == -1)
break;
@@ -109,6 +109,9 @@ int main(int argc, char **argv)
case 'p':
rtty.port = atoi(optarg);
break;
+ case 'T':
+ rtty.timeout = atoi(optarg);
+ break;
case 'd':
if (strlen(optarg) > 126) {
log_err("Description too long\n");
Index: rtty-7.1.4/src/rtty.h
===================================================================
--- rtty-7.1.4.orig/src/rtty.h
+++ rtty-7.1.4/src/rtty.h
@@ -79,6 +79,8 @@ struct rtty {
void *ssl; /* Context wrap of openssl, wolfssl and mbedtls */
struct tty *ttys[RTTY_MAX_TTY];
struct file_context file_context;
+ int timeout;
+ struct ev_timer kill_timer;
};
int rtty_start(struct rtty *rtty);

View File

@@ -6,7 +6,7 @@ PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-client.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2021-02-15
PKG_SOURCE_VERSION:=cf6333e0934f1b83fdb5cc8368cea2421c97d90b
PKG_SOURCE_VERSION:=6194debc0995550c5169972e150506617a2df970
PKG_LICENSE:=BSD-3-Clause
PKG_MAINTAINER:=John Crispin <john@phrozen.org>

View File

@@ -15,6 +15,7 @@ start_service() {
}
. /lib/functions.sh
cp /etc/config-shadow/ucentral /etc/config/
config_load 'ucentral'
config_get serial 'config' 'serial'
config_get server 'config' 'server'

0
feeds/ucentral/ucentral-client/files/etc/init.d/ustats Normal file → Executable file
View File

View File

@@ -7,6 +7,8 @@ uci set system.@system[-1].hostname=$hname
uci set ucentral.config.serial=$hname
uci set network.wan6.ifname=@wan
uci set network.wan.type=bridge
uci rename opennds.@opennds[-1]=opennds
uci set opennds.opennds.enabled=0
uci commit
cp -r /etc/config/ /etc/config-shadow/

View File

@@ -1,7 +1,10 @@
#!/bin/sh
timeout=$1
. /etc/diag.sh
set_state upgrade
sleep 60
sleep $1
status_led_off
set_state done
exit 0

View File

@@ -1 +0,0 @@
/ucentral/ucentral-client/.git

View File

@@ -6,7 +6,7 @@ PKG_RELEASE:=1
PKG_SOURCE_URL=https://github.com/blogic/ucentral-schema.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2021-02-15
PKG_SOURCE_VERSION:=16d19ac0a02b29828c92479fdba69f0d7a96cb03
PKG_SOURCE_VERSION:=7fb6336b47ebc06a9d990226a028cdf58b7110bd
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause

View File

@@ -23,7 +23,7 @@ endef
define Package/ucentral-tools/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/{dhcpdiscover,dnsprobe,firstcontact,radiusprobe,ip-collide} $(1)/usr/sbin/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/{dhcpdiscover,dnsprobe,radiusprobe,ip-collide} $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,ucentral-tools))

View File

@@ -1 +0,0 @@
/ucentral/ucentral-wifi/.git

View File

@@ -5,8 +5,8 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=git@github.com:stephb9959/ucentralgw.git
PKG_SOURCE_DATE:=2021-03-22
PKG_SOURCE_VERSION:=d4ae407d8b2fabc6ea4ba555061adf3e11025188
PKG_SOURCE_DATE:=2021-03-28
PKG_SOURCE_VERSION:=f45dac773971b7ad6f1e0687f0e60b0d9c61c02d
#PKG_MIRROR_HASH:=3f6569a5e63fdfd032976ac0f79d736d3935101ac1b97fb370514b013c5e6bb6
CMAKE_INSTALL:=1

View File

@@ -1 +0,0 @@
/projects/udevmand/.git/

View File

@@ -0,0 +1,38 @@
From b4b632ac77e22d2522c3cb2cccf24b1dfae379f4 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Mon, 29 Mar 2021 16:05:14 +0200
Subject: [PATCH] target: enable vlan-filtering on various targets
Signed-off-by: John Crispin <john@phrozen.org>
---
target/linux/ipq40xx/base-files/etc/board.d/02_network | 1 +
target/linux/mediatek/mt7622/base-files/etc/board.d/02_network | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network
index fe21dc8035..8b7364ff33 100755
--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network
+++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network
@@ -179,6 +179,7 @@ ipq40xx_setup_macs()
board_config_update
board=$(board_name)
+ucidef_set_bridge_device bridge
ipq40xx_setup_interfaces $board
ipq40xx_setup_macs $board
board_config_flush
diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network
index 82dba44587..d8a90e507e 100755
--- a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network
+++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network
@@ -43,6 +43,7 @@ mediatek_setup_macs()
board_config_update
board=$(board_name)
+ucidef_set_bridge_device bridge
mediatek_setup_interfaces $board
mediatek_setup_macs $board
board_config_flush
--
2.25.1

View File

@@ -3,5 +3,7 @@ profile: linksys_e8450_ubi
target: mediatek
subtarget: mt7622
description: Build image for the Linksys E8450
include:
- ucentral-ap
diffconfig: |
CONFIG_TESTING_KERNEL=y

View File

@@ -3,6 +3,8 @@ profile: linksys_ea8300
target: ipq40xx
subtarget: generic
description: Build image for the Linksys ea8300
include:
- ucentral-ap
packages:
- ath10k-firmware-qca4019-ct-htt
- ath10k-firmware-qca9888-ct-htt

View File

@@ -8,3 +8,4 @@ feeds:
path: ../../feeds/ipq807x
include:
- wifi-ax
- ucentral-ap

View File

@@ -8,3 +8,4 @@ feeds:
path: ../../feeds/ipq807x
include:
- wifi-ax
- ucentral-ap

View File

@@ -5,3 +5,4 @@ subtarget: generic
description: Build image for the EdgeCore ECS4100-12ph
include:
- realtek
- ucentral-switch

View File

@@ -3,6 +3,8 @@ description: Add the ucentral dependencies
feeds:
- name: ucentral
path: ../../feeds/ucentral
- name: tip
path: ../../feeds/tip
packages:
- kmod-batman-adv
@@ -16,10 +18,10 @@ packages:
- wpad-mesh-openssl
- ip-bridge
- dnsmasq-full
- firstcontact
- gre
- ucentral-client
- ucentral-jsonschema
- ucentral-mqtt
- ucentral-schema
- ucentral-wifi
- ucentral-defaults
@@ -28,8 +30,10 @@ packages:
- uledd
- usteer
- udevmand
- opennds
- rtty-openssl
- sqm-scripts
- tmate
- tcpdump
- vxlan
diffconfig: |

View File

@@ -8,3 +8,4 @@ feeds:
path: ../../feeds/ipq807x
include:
- wifi-ax
- ucentral-ap

View File

@@ -8,6 +8,7 @@ feeds:
path: ../../feeds/ipq807x
include:
- wifi-ax
- ucentral-ap
packages:
- kmod-usb-serial
- kmod-usb-serial-pl2303

View File

@@ -5,3 +5,4 @@ subtarget: generic
description: Build image for the Zyxel GS1900-10HP
include:
- realtek
- ucentral-switch