#!/bin/sh /etc/rc.common # Copyright (C) 2018 Dengfeng Liu # After aw-bpf (START=98) so dns_ringbuf_portal is pinned for wildcard trust. START=99 USE_PROCD=1 NAME=wifidogx PROG="/usr/bin/${NAME}" CONFIGFILE="/tmp/wifidogx.conf" handle_gateway() { local section="$1" local gateway_name gateway_channel gateway_id local gateway_subnetv4 local gateway_auth_enabled config_get gateway_name "$section" gateway_name config_get gateway_channel "$section" gateway_channel config_get gateway_id "$section" gateway_id config_get gateway_auth_enabled "$section" gateway_auth_enabled 1 if [ -z "$gateway_name" ] || [ -z "$gateway_channel" ] ; then echo "gateway_name and gateway_channel are required for $section" >&2 return fi # Get gateway_id from gateway_name if not set if [ -z "$gateway_id" ]; then gateway_id=$(ifconfig "$gateway_name" | awk '/HWaddr/ {print toupper($5)}' | tr -d ':') if [ -z "$gateway_id" ]; then echo "Failed to get gateway_id for $gateway_name" >&2 return fi uci set wifidogx."$section".gateway_id="$gateway_id" uci commit wifidogx fi # according to the gateway_name to get the subnetv4 local gateway_ipv4=$(ifconfig "$gateway_name" | awk '/inet addr:/ {print $2}' | cut -d: -f2) local gateway_maskv4=$(ifconfig "$gateway_name" | awk '/Mask:/ {print $4}' | cut -d: -f2) [ -z "$gateway_ipv4" ] && echo "Failed to get gateway_ipv4 for $gateway_name" >&2 && return [ -z "$gateway_maskv4" ] && echo "Failed to get gateway_maskv4 for $gateway_name" >&2 && return # change the gateway_ip4/gateway_maskv4 to CIDR format local mask_bits=0 local mask_value=$(printf '%d' "0x$(echo $gateway_maskv4 | tr '.' ' ' | awk '{printf "%02x%02x%02x%02x",$1,$2,$3,$4}')") while [ $mask_value -ne 0 ]; do mask_bits=$((mask_bits + (mask_value & 1))) mask_value=$((mask_value >> 1)) done gateway_subnetv4="$gateway_ipv4/$mask_bits" uci set wifidogx."$section".gateway_subnetv4="$gateway_subnetv4" uci commit wifidogx printf "GatewaySetting {\n\tGatewayAuthEnabled %s\n\tGatewayInterface %s\n\tGatewayChannel %s\n\tGatewayID %s\n\tGatewaySubnetV4 %s\n}\n" \ "${gateway_auth_enabled}" "${gateway_name}" "${gateway_channel}" "${gateway_id}" "${gateway_subnetv4}" >> "$CONFIGFILE" } add_white_list_entries() { local list_type="$1" local uci_field="$2" local target_variable="$3" list_type=$(uci get wifidogx.common."$list_type") for group in $list_type; do group_list=$(uci get wifidogx."$group"."$uci_field") if [ -n "$group_list" ]; then eval "$target_variable=\"\${$target_variable} \$group_list\"" fi done } prepare_common_settings() { printf "CheckInterval %s\nClientTimeout %s\nJsFilter %s\nWiredPassed %s\nBypassAppleCNA %s\n" \ "$check_interval" "$client_timeout" "$js_filter" "$wired_passed" "$apple_cna" >> "$CONFIGFILE" printf "EnableAntiNat %s\n" "$enable_anti_nat" >> "$CONFIGFILE" printf "TTLValues %s\n" "$ttl_values" >> "$CONFIGFILE" printf "DisablePortalAuth %s\n" "$disable_portal_auth" >> "$CONFIGFILE" printf "EnablePrivilegedOps %s\n" "$enable_privileged_ops" >> "$CONFIGFILE" [ -n "$privileged_ops_secret" ] && printf "PrivilegedOpsSecret %s\n" "$privileged_ops_secret" >> "$CONFIGFILE" [ -n "$anti_nat_permit_macs" ] && printf "AntiNatPermitMACs %s\n" "$anti_nat_permit_macs" >> "$CONFIGFILE" process_trusted_list() { local list="$1" local config_name="$2" if [ -n "$list" ]; then # Clean up whitespace and remove duplicates list=$(echo "$list" | sed -e 's/^[[:space:]]*//;s/[[:space:]]*$//;s/[[:space:]]\+/ /g' \ | tr ' ' '\n' | sort -u | tr '\n' ',' | sed 's/,$//') printf "%s %s\n" "$config_name" "$list" >> "$CONFIGFILE" fi } process_trusted_list "$trusted_domains" "TrustedDomains" process_trusted_list "$trusted_macs" "TrustedMACList" process_trusted_list "$trusted_wildcard_domains" "TrustedWildcardDomains" } prepare_device_info() { # Check if any device info fields are set if [ -n "$ap_device_id" ] || [ -n "$ap_mac_address" ] || [ -n "$ap_longitude" ] || [ -n "$ap_latitude" ] || [ -n "$location_id" ]; then printf "DeviceInfo {\n" >> "$CONFIGFILE" [ -n "$ap_device_id" ] && printf "\tApDeviceId %s\n" "$ap_device_id" >> "$CONFIGFILE" [ -n "$ap_mac_address" ] && printf "\tApMacAddress %s\n" "$ap_mac_address" >> "$CONFIGFILE" [ -n "$ap_longitude" ] && printf "\tApLongitude %s\n" "$ap_longitude" >> "$CONFIGFILE" [ -n "$ap_latitude" ] && printf "\tApLatitude %s\n" "$ap_latitude" >> "$CONFIGFILE" [ -n "$location_id" ] && printf "\tLocationId %s\n" "$location_id" >> "$CONFIGFILE" printf "}\n" >> "$CONFIGFILE" fi } prepare_auth_server_settings() { # 获取选中的认证服务器配置 local selected_auth_server selected_auth_server=$(uci get wifidogx.common.selected_auth_server 2>/dev/null) # 如果是云认证或旁路模式,需要验证选中的认证服务器 if [ "$auth_server_mode" = "cloud" ] || [ "$auth_server_mode" = "bypass" ]; then if [ -z "$selected_auth_server" ]; then echo "Error: selected_auth_server is required for $auth_server_mode mode" >&2 return 1 fi local auth_server_hostname auth_server_port auth_server_path uci_validate_section "$NAME" "auth" "$selected_auth_server" \ 'auth_server_hostname:string:192.168.1.1' \ 'auth_server_port:port:80' \ 'auth_server_path:string:/wifidog/' export auth_server_hostname export auth_server_port export auth_server_path fi case "$auth_server_mode" in cloud|bypass) printf "AuthServerMode 0\n" >> "$CONFIGFILE" printf "DeviceID %s\nAuthServer {\n\tHostname %s\n\tHTTPPort %s\n\tPath %s\n}\n" \ "$device_id" "$auth_server_hostname" "$auth_server_port" "$auth_server_path" >> "$CONFIGFILE" ;; local) printf "AuthServerMode 2\n" >> "$CONFIGFILE" [ -n "$device_id" ] && printf "DeviceID %s\n" "$device_id" >> "$CONFIGFILE" [ -n "$auth_server_offline_file" ] && printf "AuthServerOfflineFile %s\n" "$auth_server_offline_file" >> "$CONFIGFILE" [ -n "$local_portal" ] && printf "LocalPortal %s\n" "$local_portal" >> "$CONFIGFILE" ;; esac [ -n "$internet_offline_file" ] && printf "InternetOfflineFile %s\n" "$internet_offline_file" >> "$CONFIGFILE" } prepare_longconn_settings() { local long_conn_mode ws_server_hostname ws_server_port ws_server_path local mqtt_server_hostname mqtt_server_port mqtt_username mqtt_password local selected_long_conn selected_long_conn=$(uci get wifidogx.common.selected_long_conn 2>/dev/null) [ -z "$selected_long_conn" ] && return if ! uci -q get wifidogx."$selected_long_conn" >/dev/null; then echo "Long connection: selected section $selected_long_conn does not exist" >&2 return fi uci_validate_section "$NAME" "longconn" "$selected_long_conn" \ 'long_conn_mode:or("ws","wss","mqtt","mqtts"):ws' \ 'ws_server_hostname:string' \ 'ws_server_port:port:443' \ 'ws_server_path:string:/ws/wifidogx' \ 'mqtt_server_hostname:string' \ 'mqtt_server_port:port:1883' \ 'mqtt_username:string' \ 'mqtt_password:string' case "$long_conn_mode" in ws|wss) if [ -z "$ws_server_hostname" ]; then echo "Long connection: ws_server_hostname is required" >&2 return fi local ws_ssl ws_ssl=$([ "$long_conn_mode" = "wss" ] && echo 1 || echo 0) printf "WebSocket {\n\tWSServer %s\n\tWSServerPort %s\n\tWSServerPath %s\n\tWSServerSSL %s\n}\n" \ "$ws_server_hostname" "$ws_server_port" "$ws_server_path" "$ws_ssl" >> "$CONFIGFILE" ;; mqtt|mqtts) if [ -z "$mqtt_server_hostname" ]; then echo "Long connection: mqtt_server_hostname is required" >&2 return fi local mqtt_ssl mqtt_ssl=$([ "$long_conn_mode" = "mqtts" ] && echo 1 || echo 0) printf "mqtt {\n\tserveraddr %s\n\tserverport %s\n\tmqttUseSSL %s\n\tmqttUsername %s\n\tmqttPassword %s\n}\n" \ "$mqtt_server_hostname" "$mqtt_server_port" "$mqtt_ssl" "${mqtt_username:-}" "${mqtt_password:-}" >> "$CONFIGFILE" ;; esac } prepare_external_interface() { [ -z "$external_interface" ] && echo "No ExternalInterface " >&2 && return local external_interface_name if [ "$external_interface" = "wwan" ]; then external_interface_name=$(ubus call network.interface."$external_interface" status | jsonfilter -e '@.device') else external_interface_name=$(uci get network."$external_interface".device) fi [ -z "$external_interface_name" ] && echo "Failed to get device name for $external_interface" >&2 && return printf "ExternalInterface %s\n" "$external_interface_name" >> "$CONFIGFILE" } prepare_wifidog_conf() { [ -f "$CONFIGFILE" ] && rm -f "$CONFIGFILE" local auth_server_mode_value='"cloud", "bypass", "local"' # 获取选中的认证服务器 local selected_auth_server selected_auth_server=$(uci get wifidogx.common.selected_auth_server 2>/dev/null) uci_validate_section "$NAME" "$NAME" common \ 'enabled:bool:0' \ "auth_server_mode:or($auth_server_mode_value)" \ 'selected_auth_server:string' \ 'selected_long_conn:string' \ 'log_level:integer:7' \ 'device_id:string' \ 'check_interval:integer:60' \ 'client_timeout:integer:5' \ 'wired_passed:bool:1' \ 'apple_cna:bool:0' \ 'trusted_domains:list(host)' \ 'trusted_wildcard_domains:list(string)' \ 'trusted_macs:list(string)' \ 'app_white_list:list(string)' \ 'mac_white_list:list(string)' \ 'wildcard_white_list:list(string)' \ 'js_filter:bool:1' \ 'auth_server_offline_file:string' \ 'internet_offline_file:string' \ 'local_portal:string' \ 'external_interface:string' \ 'enable_anti_nat:bool:0' \ 'enable_privileged_ops:bool:0' \ 'privileged_ops_secret:string:chawrt@2026' \ 'ttl_values:string:64,128' \ 'anti_nat_permit_macs:string' \ 'disable_portal_auth:bool:1' \ 'ap_device_id:string' \ 'ap_mac_address:string' \ 'ap_longitude:string' \ 'ap_latitude:string' \ 'location_id:string' [ -n "$app_white_list" ] && add_white_list_entries "app_white_list" "domain_name" "trusted_domains" [ -n "$mac_white_list" ] && add_white_list_entries "mac_white_list" "mac_address" "trusted_macs" [ -n "$wildcard_white_list" ] && add_white_list_entries "wildcard_white_list" "wildcard_domain" "trusted_wildcard_domains" prepare_external_interface prepare_auth_server_settings prepare_longconn_settings prepare_device_info config_foreach handle_gateway gateway prepare_common_settings } service_triggers() { procd_add_reload_trigger "wifidogx" } start_service() { config_load "$NAME" prepare_wifidog_conf if [ "$enabled" -eq 0 ]; then echo "wifidogx is disabled, exit..." >&2 return fi procd_open_instance procd_set_param command "$PROG" -c "$CONFIGFILE" -s -f -d "$log_level" procd_set_param respawn procd_set_param file /etc/config/wifidogx procd_close_instance } status_service() { /usr/bin/wdctlx status } reload_service() { stop start }