diff --git a/board/common/rootfs/etc/bash.bashrc b/board/common/rootfs/etc/bash.bashrc index 2d4c139a5..8e916c939 100644 --- a/board/common/rootfs/etc/bash.bashrc +++ b/board/common/rootfs/etc/bash.bashrc @@ -40,11 +40,12 @@ log() less +G -r "$fn" } -follow() +follow () { local fn="/var/log/syslog" [ -n "$1" ] && fn="/var/log/$1" - less +F -r "$fn" + + tail -F -n +1 "$fn" } _logfile_completions() diff --git a/board/common/rootfs/etc/default/zebra b/board/common/rootfs/etc/default/zebra index 5ce4e34c3..4467b9af2 100644 --- a/board/common/rootfs/etc/default/zebra +++ b/board/common/rootfs/etc/default/zebra @@ -1,2 +1,2 @@ # --log-level debug -ZEBRA_ARGS="-A 127.0.0.1 -u frr -g frr --log syslog " +ZEBRA_ARGS="-A 127.0.0.1 -u frr -g frr --log syslog --log-level err" diff --git a/board/common/rootfs/etc/finit.d/available/restconf.conf b/board/common/rootfs/etc/finit.d/available/restconf.conf index cf32c4dfe..a8120ec3e 100644 --- a/board/common/rootfs/etc/finit.d/available/restconf.conf +++ b/board/common/rootfs/etc/finit.d/available/restconf.conf @@ -1,3 +1,3 @@ -service name:rousette notify:none log env:/etc/default/confd \ +service name:rousette notify:none log:console env:/etc/default/confd \ [12345] rousette --syslog -t $CONFD_TIMEOUT \ -- RESTCONF server diff --git a/board/common/rootfs/etc/finit.d/available/wifi@.conf b/board/common/rootfs/etc/finit.d/available/wifi@.conf index e530b39c8..7f7bfcee6 100644 --- a/board/common/rootfs/etc/finit.d/available/wifi@.conf +++ b/board/common/rootfs/etc/finit.d/available/wifi@.conf @@ -1,5 +1,3 @@ service name:wpa_supplicant :%i \ - [2345] wpa_supplicant -s -i %i -c /etc/wpa_supplicant-%i.conf -P/var/run/wpa_supplicant-%i.pid \ - -- Wi-Fi Station @%i - -task name:wifi-scanner :%i [2345] /usr/libexec/infix/wifi-scanner %i -- Start scanning for SSID @%i + [2345] wpa_supplicant -s -i %i -c /etc/wpa_supplicant-%i.conf -P/var/run/wpa_supplicant-%i.pid \ + -- Wi-Fi Station @%i diff --git a/board/common/rootfs/etc/nginx/nginx.conf b/board/common/rootfs/etc/nginx/nginx.conf index baf6b6b07..5719371e8 100644 --- a/board/common/rootfs/etc/nginx/nginx.conf +++ b/board/common/rootfs/etc/nginx/nginx.conf @@ -19,6 +19,14 @@ http { include /etc/nginx/enabled/*.conf; - access_log syslog:server=unix:/dev/log,nohostname,facility=local7,severity=info; - error_log syslog:server=unix:/dev/log,nohostname,facility=local7 info; + # Skip 2xx and 3xx + # Skip 400 (e.g., rrousette syntax errors) + map $status $loggable { + ~^[23] 0; + 400 0; + default 1; + } + + access_log syslog:server=unix:/dev/log,nohostname,facility=local7,severity=warn combined if=$loggable; + error_log syslog:server=unix:/dev/log,nohostname,facility=local7 warn; } diff --git a/board/common/rootfs/usr/libexec/infix/wifi-scanner b/board/common/rootfs/usr/libexec/infix/wifi-scanner deleted file mode 100755 index b34c698bb..000000000 --- a/board/common/rootfs/usr/libexec/infix/wifi-scanner +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -if [ $# -ne 1 ]; then - echo "usage: $0 " - exit 1 -fi -ifname=$1 - -TIMEOUT=300 -status=$(wpa_cli -i $ifname scan) -while [ "$status" != "OK" ]; do - status=$(wpa_cli -i $ifname scan) - TIMEOUT=$((TIMEOUT-1)) - [ $TIMEOUT -eq 0 ] && logger -t wifi-scanner "Failed to start scanning $ifname" && exit 1 - sleep 0.5 -done diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index cda0e2e68..54667d3e6 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -149,7 +149,8 @@ BR2_PACKAGE_MARVELL_CN9130_CRB=y BR2_PACKAGE_MARVELL_ESPRESSOBIN=y BR2_PACKAGE_RASPBERRYPI_RPI64=y BR2_PACKAGE_STYX_DCP_SC_28P=y -BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK=y +BR2_PACKAGE_FEATURE_WIFI_MEDIATEK=y +BR2_PACKAGE_FEATURE_WIFI_REALTEK=y BR2_PACKAGE_CONFD=y BR2_PACKAGE_CONFD_TEST_MODE=y BR2_PACKAGE_CURIOS_HTTPD=y diff --git a/doc/scripting-restconf.md b/doc/scripting-restconf.md index cf466afb6..3aa637dba 100644 --- a/doc/scripting-restconf.md +++ b/doc/scripting-restconf.md @@ -18,77 +18,116 @@ To simplify RESTCONF operations, create a `curl.sh` wrapper script: #!/bin/sh # RESTCONF CLI wrapper for curl -# Show usage and exit +HOST=${HOST:-infix.local} +DATASTORE=running +AUTH=admin:admin + usage() { - cat <<-EOF >&2 - Usage: $0 [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD PATH [CURL_ARGS...] - - Options: - -h HOST Target host (default: infix.local) - -d DS Datastore: running, operational, startup (default: running) - -u CREDS Credentials as user:pass (default: admin:admin) - - Methods: GET, POST, PUT, PATCH, DELETE - EOF - exit "$1" + cat <&2 +Usage: $0 [-v] [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD XPATH [CURL_ARGS...] + +Options: + -h HOST Target host (default: infix.local) + -d DS Datastore: running, operational, startup (default: running) + -u CREDS Credentials as user:pass (default: admin:admin) + -v Verbose mode, use it to display variables and curl command + +Methods: GET, POST, PUT, PATCH, DELETE +EOF + exit "$1" } -# Default values -HOST=${HOST:-infix.local} -DATASTORE=running -AUTH=admin:admin +check() +{ + hint="Note: URL may be missing a module prefix (e.g., ietf-system:system)" + resp="$1" + url="$2" + + if ! command -v jq >/dev/null 2>&1; then + printf "%s\n" "$resp" + return + fi + + case "$resp" in + *"Syntax error"*) + path_only="${url#*//}" + + # Check for common URL error(s), e.g., missing module prefix + case "$path_only" in + *":"*) + printf "%s\n" "$resp" | jq . + ;; + *) + printf "%s\n" "$resp" | jq --arg hint "$hint" \ + '.["ietf-restconf:errors"].error[] |= . + {comment: $hint}' + ;; + esac + ;; + *) + printf "%s\n" "$resp" | jq . + ;; + esac +} -# Parse options -while getopts "h:d:u:" opt; do - case $opt in - h) HOST="$OPTARG" ;; - d) DATASTORE="$OPTARG" ;; - u) AUTH="$OPTARG" ;; - *) usage 1 ;; - esac +while getopts "h:d:u:v" opt; do + case $opt in + h) HOST="$OPTARG" ;; + d) DATASTORE="$OPTARG" ;; + u) AUTH="$OPTARG" ;; + v) VERBOSE=1 ;; + *) usage 1 ;; + esac done shift $((OPTIND - 1)) -# Validate required arguments if [ $# -lt 2 ]; then - echo "Error: METHOD and PATH are required" >&2 - usage 1 + echo "Error: METHOD and XPATH are required" >&2 + usage 1 fi METHOD=$1 -PATH=$2 +XPATH=$2 shift 2 -# Ensure PATH starts with / -case "$PATH" in - /*) ;; - *) PATH="/$PATH" ;; +# Ensure XPATH starts with / +case "$XPATH" in + /*) ;; + *) XPATH="/$XPATH" ;; esac -# Build URL based on datastore case "$DATASTORE" in - running|startup) - URL="https://${HOST}/restconf/data${PATH}" - ;; - operational) - URL="https://${HOST}/restconf/data${PATH}" - ;; - *) - echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2 - exit 1 - ;; + running|startup) + URL="https://${HOST}/restconf/data${XPATH}" + ;; + operational) + URL="https://${HOST}/restconf/data${XPATH}" + ;; + *) + echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2 + exit 1 + ;; esac -# Execute curl with all remaining arguments passed through -exec /usr/bin/curl \ - --insecure \ - --user "${AUTH}" \ - --request "${METHOD}" \ - --header "Content-Type: application/yang-data+json" \ - --header "Accept: application/yang-data+json" \ - "$@" \ - "${URL}" +if [ "$VERBOSE" ]; then + echo "DS : $DATASTORE" + echo "OP : $METHOD" + echo "XPATH : $XPATH" + echo "AUTH : $AUTH" + echo "=> URL : $URL" + set -x +fi + +RESP=$(/usr/bin/curl --silent \ + --insecure \ + --user "${AUTH}" \ + --request "${METHOD}" \ + --header "Content-Type: application/yang-data+json" \ + --header "Accept: application/yang-data+json" \ + "$@" \ + "${URL}") + +check "$RESP" "$URL" ``` Make it executable: diff --git a/package/feature-wifi/Config.in b/package/feature-wifi/Config.in index bbf293f30..d0a72aa8d 100644 --- a/package/feature-wifi/Config.in +++ b/package/feature-wifi/Config.in @@ -14,12 +14,25 @@ config BR2_PACKAGE_FEATURE_WIFI help Enables WiFi in Infix. Enables all requried applications. -config BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK - bool "Realtek USB WiFi Dongles" +config BR2_PACKAGE_FEATURE_WIFI_MEDIATEK + bool "Mediatek WiFi Devices" + depends on BR2_PACKAGE_FEATURE_WIFI + select BR2_PACKAGE_LINUX_FIRMWARE + select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7601U + select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7610E + select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT76X2E + select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7921 + select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7922 + select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7925 + help + Enables support for various Mediatek WiFi devices. + +config BR2_PACKAGE_FEATURE_WIFI_REALTEK + bool "Realtek WiFi Devices" depends on BR2_PACKAGE_FEATURE_WIFI select BR2_PACKAGE_LINUX_FIRMWARE select BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX select BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW88 select BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW89 help - Enables Support for RTW88 and RTW89 USB dongles. + Enables support for RTL81xx, RTW88, and RTW89 WiFi devices. diff --git a/package/feature-wifi/feature-wifi.mk b/package/feature-wifi/feature-wifi.mk index 07e665f48..b7c2d3b92 100644 --- a/package/feature-wifi/feature-wifi.mk +++ b/package/feature-wifi/feature-wifi.mk @@ -13,7 +13,24 @@ define FEATURE_WIFI_LINUX_CONFIG_FIXUPS $(call KCONFIG_SET_OPT,CONFIG_MAC80211,m) $(call KCONFIG_SET_OPT,CONFIG_CFG80211,m) - $(if $(filter y,$(BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK)), + $(if $(filter y,$(BR2_PACKAGE_FEATURE_WIFI_MEDIATEK)), + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7601U) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT76x0U) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT76x0E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT76x2E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT76x2U) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7603E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7615E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7663U) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7915E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT798X_WMAC) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7921E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7921U) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7996E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7925E) + $(call KCONFIG_ENABLE_OPT,CONFIG_MT7925U) + ) + $(if $(filter y,$(BR2_PACKAGE_FEATURE_WIFI_REALTEK)), $(call KCONFIG_ENABLE_OPT,CONFIG_WLAN_VENDOR_REALTEK) $(call KCONFIG_ENABLE_OPT,CONFIG_RTL8XXXU) $(call KCONFIG_ENABLE_OPT,CONFIG_RTL8XXXU_UNTESTED) @@ -47,5 +64,4 @@ define FEATURE_WIFI_LINUX_CONFIG_FIXUPS ) endef - $(eval $(generic-package)) diff --git a/src/confd/src/dhcp-common.c b/src/confd/src/dhcp-common.c index 49ba3d983..282af1dd6 100644 --- a/src/confd/src/dhcp-common.c +++ b/src/confd/src/dhcp-common.c @@ -194,7 +194,6 @@ static void infer_options_v4(sr_session_ctx_t *session, const char *xpath) "broadcast", "router", "domain", - "hostname", /* server may use this to register our current name */ "dns-server", "ntp-server" /* will not be activated unless ietf-system also is */ }; @@ -203,6 +202,10 @@ static void infer_options_v4(sr_session_ctx_t *session, const char *xpath) for (i = 0; i < NELEMS(opt); i++) srx_set_item(session, NULL, 0, "%s/option[id='%s']", xpath, opt[i]); + /* server may use this to register our current name */ + val.data.string_val = "auto"; + srx_set_item(session, &val, 0, "%s/option[id='hostname']/value", xpath); + product_name = json_object_get(confd.root, "product-name"); if (product_name) { val.data.string_val = (char *)json_string_value(product_name); diff --git a/src/confd/src/if-wifi.c b/src/confd/src/if-wifi.c index d6567d6b4..39b61c36a 100644 --- a/src/confd/src/if-wifi.c +++ b/src/confd/src/if-wifi.c @@ -1,11 +1,4 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -#include -#include - -#include "interfaces.h" - -#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant-%s.conf" - /* * WiFi Interface Management * @@ -14,6 +7,13 @@ * configuration (hostapd) is handled by hardware.c. */ +#include +#include + +#include "interfaces.h" + +#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant-%s.conf" + /* * Determine WiFi mode from YANG configuration */ @@ -25,28 +25,35 @@ typedef enum wifi_mode_t { static wifi_mode_t wifi_get_mode(struct lyd_node *wifi) { - struct lyd_node *ap = lydx_get_child(wifi, "access-point"); + struct lyd_node *ap; - if (ap && (lydx_get_op(ap) != LYDX_OP_DELETE)) - return wifi_ap; - else - return wifi_station; /* Need to return station even if "station" also is false, since that is the default scanning mode */ + ap = lydx_get_child(wifi, "access-point"); + if (ap) { + if (lydx_get_op(ap) != LYDX_OP_DELETE) + return wifi_ap; + } + + /* + * Need to return station even if "station" also is false, + * because station is the default scanning mode. + */ + return wifi_station; } int wifi_mode_changed(struct lyd_node *wifi) { + enum lydx_op ap_op = LYDX_OP_DELETE; struct lyd_node *ap; - enum lydx_op ap_op; if (!wifi) return 0; ap = lydx_get_child(wifi, "access-point"); - if (ap) ap_op = lydx_get_op(ap); - ERROR("MODE CHANGED: %d", ap && (ap_op == LYDX_OP_CREATE || ap_op == LYDX_OP_DELETE)); + DEBUG("MODE CHANGED: %d", ap && (ap_op == LYDX_OP_CREATE || ap_op == LYDX_OP_DELETE)); + return (ap && (ap_op == LYDX_OP_CREATE || ap_op == LYDX_OP_DELETE)); } @@ -70,21 +77,20 @@ static int wifi_gen_station(struct lyd_node *cif) radio = lydx_get_cattr(wifi, "radio"); station = lydx_get_child(wifi, "station"); - /* If station is NULL, we're in scan-only mode (no station container) */ if (station) { ssid = lydx_get_cattr(station, "ssid"); security = lydx_get_child(station, "security"); security_mode = lydx_get_cattr(security, "mode"); secret_name = lydx_get_cattr(security, "secret"); } else { + /* If station is NULL, we're in scan-only mode (no station container) */ ssid = NULL; security = NULL; security_mode = "disabled"; secret_name = NULL; } - radio_node = lydx_get_xpathf(cif, - "../../hardware/component[name='%s']/wifi-radio", radio); + radio_node = lydx_get_xpathf(cif, "../../hardware/component[name='%s']/wifi-radio", radio); country = lydx_get_cattr(radio_node, "country-code"); if (secret_name && strcmp(security_mode, "disabled") != 0) { @@ -103,6 +109,10 @@ static int wifi_gen_station(struct lyd_node *cif) goto out; } + /* + * Background scanning every 10 seconds while not associated, when we + * have an SSID (below), bgscan assumes this task. + */ fprintf(wpa_supplicant, "ctrl_interface=/run/wpa_supplicant\n" "autoscan=periodic:10\n" @@ -121,14 +131,27 @@ static int wifi_gen_station(struct lyd_node *cif) } fprintf(wpa_supplicant, "network={\n" - "bgscan=\"simple: 30:-45:300\"\n" - "ssid=\"%s\"\n" - "%s\n" + " bgscan=\"simple: 30:-45:300\"\n" + " ssid=\"%s\"\n" + " %s\n" "}\n", ssid, security_str); free(security_str); } else { /* Scan-only mode - no station container configured */ - fprintf(wpa_supplicant, "# Scan-only mode - no network configured\n"); + fprintf(wpa_supplicant, "# Scan-only - need dummy network for state machine\n"); + /* + * This prevents the daemon from actually trying to associate and fail, + * 'bssid' with a reserved/impossible MAC address prevents it from ever + * actually \"finding\" and joining a random open AP + */ + fprintf(wpa_supplicant, + "network={\n" + " ssid=\"\"\n" + " key_mgmt=NONE\n" + " disabled=0\n" + " bssid=00:00:00:00:00:01\n" + " scan_ssid=1\n" + "}\n"); } out: diff --git a/src/confd/src/routing.c b/src/confd/src/routing.c index 194b503ad..e9110e42a 100644 --- a/src/confd/src/routing.c +++ b/src/confd/src/routing.c @@ -26,7 +26,7 @@ hostname Router\n\ password zebra \n\ enable password zebra\n\ no log unique-id\n\ -log syslog informational\n\ +log syslog warnings\n\ log facility local2\n" int parse_rip_redistribute(sr_session_ctx_t *session, struct lyd_node *redistributes, FILE *fp) diff --git a/src/klish-plugin-infix/xml/infix.xml b/src/klish-plugin-infix/xml/infix.xml index b6786a434..e6b29cbf8 100644 --- a/src/klish-plugin-infix/xml/infix.xml +++ b/src/klish-plugin-infix/xml/infix.xml @@ -744,7 +744,7 @@ file=${KLISH_PARAM_fn:-syslog} echo -e "\e[1mPress Ctrl-C to abort ────────────────────────────────────────────\e[0m" - tail -F /log/$file + tail -F -n +1 /log/$file