Last active
December 23, 2025 20:19
-
-
Save emabrey/4c8e21f37c40ea35e1f3a529223732cc to your computer and use it in GitHub Desktop.
Hotplug script for modifying the logging level of the hostapd daemon on an openWRT device
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #! /bin/sh | |
| # SPDX-License-Identifier: GPL-2.0-only | |
| # License available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
| # Script written by emabrey; based upon a script written by compact21 | |
| # Hotplug script for modifying the logging level of the hostapd daemon. This | |
| # is a workaround for the hardcoded OpenWRT logging level not respecting | |
| # modifications to the setting through the usual means (LuCI, UCI, etc.) | |
| # The other non-working methods are available on the openWRT website at: | |
| # https://openwrt.org/docs/guide-developer/debugging | |
| # | |
| # Recommended filename/location: /etc/hotplug.d/net/99-hostapd-log-level | |
| # | |
| # This script requires: hostapd_cli, sort, cut, printf (usually provided via entware packages `hostapd-utils` & `busybox`) | |
| # This script includes enhancements if awk and head are present, but they are not required for basic functionality | |
| # The log level to assign to the hostapd daemon for each wireless interface; should be upper case | |
| # If awk is present then this will be converted to all upper case and checked for validity (see below for valid values) | |
| # The hostapd daemon will only print messages at this level *or higher* | |
| LOG_LEVEL="ERROR" | |
| # write_log <priority pair> <message> | |
| write_log () { | |
| if command -v logger >/dev/null 2>&1; then | |
| # Write to normal openWRT log ringbuffer | |
| logger -t hotplug -p "$1" "$2"; | |
| elif command -v printf >/dev/null 2>&1; then | |
| # Write to backup kernel ringbuffer using printf | |
| printf "%s\n" "$1: $2" >> /dev/kmsg; | |
| elif command -v echo >/dev/null 2>&1; then | |
| # Write to backup kernel ringbuffer using echo | |
| # Even though printf is required, we need to be able to log | |
| # that it is missing so echo backup is needed | |
| echo "$1: $2" >> /dev/kmsg; | |
| else | |
| # If you don't have logger, printf, or echo then you've ascended beyond the need for logs | |
| exit 0; | |
| fi | |
| } | |
| # Verify required busybox commands exist | |
| for program in "printf" "cut" "sort"; do | |
| if ! command -v $program >/dev/null 2>&1; then | |
| write_log user.notice "Unable to change hostapd logging level because the $program program was not found"; | |
| write_log user.notice "The $program program should be part of openWRT base; is busybox installed?"; | |
| write_log user.notice "Running \`opkg update && opkg install busybox\` may fix this issue"; | |
| exit 0; | |
| fi; | |
| done; | |
| # Check that we actually have the needed runtime options; should be provided by hotplugd | |
| # but hypothetically a user could call this script directly so lets give them some helptext | |
| if [ -z "${DEVICENAME}" ] || [ -z "${ACTION}" ]; then | |
| printf "%s\n" "$0 - hotplug daemon script which modifies the hostapd log level(s)"; | |
| printf "%s\n" "\$DEVICENAME and \$ACTION variables must be set and non-empty; execution skipped" | |
| exit 0; | |
| fi; | |
| # Verify hostapd daemon cli frontend exists | |
| if ! command -v hostapd_cli >/dev/null 2>&1; then | |
| write_log user.notice "Unable to change hostapd logging level because the hostapd_cli program was not found"; | |
| write_log user.notice "Please run \`opkg update && opkg install hostapd_utils\` to install the missing program"; | |
| exit 0; | |
| fi; | |
| # Ensure that the log level is a valid value (uppercase and present in wpa_debug.h enum) | |
| if command -v awk >/dev/null 2>&1; then | |
| # Make sure log level is upper case | |
| LOG_LEVEL=$(printf "%s" "$LOG_LEVEL" | awk '{print toupper($0)}'); | |
| # See https://github.com/digsrc/wpa_supplicant/blob/master/src/utils/wpa_debug.h#L21 | |
| # enum { | |
| # MSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR | |
| # }; | |
| if [ -z "$LOG_LEVEL" ] || [ "$(printf "%s" "$LOG_LEVEL" | awk '/[^(EXCESSIVE|MSGDUMP|DEBUG|INFO|WARNING|ERROR)]/{print $0}')" != "" ]; then | |
| write_log user.notice "Unable to change hostapd logging level because logging level ${LOG_LEVEL-null} is not valid"; | |
| write_log user.notice "Potentially valid values include: EXCESSIVE, MSGDUMP, DEBUG, INFO, WARNING, or ERROR"; | |
| exit 0; | |
| fi; | |
| fi; | |
| #For each wireless interface by name | |
| for ap_iface in $(printf '%s\n' /sys/class/ieee80211/*/device/net/*/ | cut -d/ -f8 | sort -u); do | |
| #If the current device being hotplugged is one of our interfaces then... | |
| if [ "${DEVICENAME}" = "${ap_iface}" ] && [ "${ACTION}" = "add" ]; then | |
| # Try to log the current logging level, but if not possible this is skipped | |
| if command -v head >/dev/null 2>&1 && command -v awk >/dev/null 2>&1; then | |
| CURRENT_LOG_LEVEL=$(hostapd_cli -i "${DEVICENAME}" log_level | head -n 1 | awk -F" " '{print $NF}'); | |
| write_log user.info "Device [${DEVICENAME}]: hostapd initial logging level was ${CURRENT_LOG_LEVEL:-not configured}"; | |
| fi; | |
| # Change the log level and exit early to prevent wasted cycles | |
| hostapd_cli -i "${DEVICENAME}" log_level "${LOG_LEVEL}"; | |
| write_log user.info "Device [${DEVICENAME}]: hostapd logging level changed to ${LOG_LEVEL}"; | |
| break; | |
| fi; | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment