Compare commits

..

1 Commits

Author SHA1 Message Date
Omar e0d7401b16
Merge 171bdb9e66 into fe2348a725 2024-12-19 17:57:03 +01:00
2 changed files with 227 additions and 329 deletions

View File

@ -82,9 +82,9 @@ I'm currently not packaging for any distro. If you do, open a PR and add the lin
- iptables (or nftables with `iptables-nft` translation linked) - iptables (or nftables with `iptables-nft` translation linked)
- WiFi hotspot dependencies - WiFi hotspot dependencies
- hostapd - hostapd
- iw (or iwconfig, when iw can not recognize adapter) - iw
- iwconfig (you only need this if 'iw' can not recognize your adapter)
- haveged (optional) - haveged (optional)
- crda and wireless-regdb (optional)

158
lnxrouter
View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
VERSION=0.8.0-unstable2 VERSION=0.7.6
PROGNAME="$(basename "$0")" PROGNAME="$(basename "$0")"
export LC_ALL=C export LC_ALL=C
@ -124,24 +124,8 @@ Options:
--vht-seg1-ch <channel> Channel index of VHT center frequency for secondary --vht-seg1-ch <channel> Channel index of VHT center frequency for secondary
(second 80MHz) segment. Use with '--vht-ch-width 3' (second 80MHz) segment. Use with '--vht-ch-width 3'
WiFi 6 (802.11ax) configs:
--wifi6 Enable IEEE 802.11ax (HE)
--req-he Require station HE (High Efficiency) mode
--he-ch-width <index> Index of HE channel width:
0 for 20MHz or 40MHz (default)
1 for 80MHz
2 for 160MHz
3 for 80+80MHz (Non-contigous 160MHz)
--he-seg0-ch <channel> Channel index of HE center frequency for primary
segment. Use with '--he-ch-width'
--he-seg1-ch <channel> Channel index of HE center frequency for secondary
(second 80MHz) segment. Use with '--he-ch-width 3'
Instance managing: Instance managing:
--daemon Run in background --daemon Run in background
--keep-confdir Don't delete the temporary config dir after exit
-l, --list-running Show running instances -l, --list-running Show running instances
--lc, --list-clients <id|interface> --lc, --list-clients <id|interface>
List clients of an instance. Or list neighbors of List clients of an instance. Or list neighbors of
@ -214,16 +198,11 @@ define_global_variables(){
REQUIREHT=0 REQUIREHT=0
IEEE80211AC=0 IEEE80211AC=0
REQUIREVHT=0 REQUIREVHT=0
IEEE80211AX=0
REQUIREHE=0
HT_CAPAB='[HT40+]' HT_CAPAB='[HT40+]'
VHT_CAPAB= VHT_CAPAB=
VHTCHANNELWIDTH=0 VHTCHANNELWIDTH=0
VHTSEG0CHINDEX=0 VHTSEG0CHINDEX=0
VHTSEG1CHINDEX=0 VHTSEG1CHINDEX=0
HECHANNELWIDTH=0
HESEG0CHINDEX=0
HESEG1CHINDEX=0
DRIVER=nl80211 DRIVER=nl80211
NO_VIRT=0 # not use virtual interface NO_VIRT=0 # not use virtual interface
COUNTRY= COUNTRY=
@ -235,7 +214,6 @@ define_global_variables(){
QR=0 # show wifi qr QR=0 # show wifi qr
# script variables # script variables
PHY=
VWIFI_IFACE= # virtual wifi interface name, if created VWIFI_IFACE= # virtual wifi interface name, if created
VIRT_NAME= # name to use for virtual interface if --virt-name is used VIRT_NAME= # name to use for virtual interface if --virt-name is used
AP_IFACE= # can be VWIFI_IFACE or WIFI_IFACE AP_IFACE= # can be VWIFI_IFACE or WIFI_IFACE
@ -254,7 +232,6 @@ define_global_variables(){
NM_PID= NM_PID=
FIREWALLD_PID= FIREWALLD_PID=
TMP_FIREWALLD_ZONE= TMP_FIREWALLD_ZONE=
KEEP_CONFDIR=
} }
parse_user_options(){ parse_user_options(){
@ -459,14 +436,6 @@ parse_user_options(){
shift shift
IEEE80211AC=1 IEEE80211AC=1
;; ;;
--wifi6|--ieee80211ax)
shift
IEEE80211AX=1
;;
--req-he|--require-he)
shift
REQUIREHE=1
;;
--req-vht|--require-vht) --req-vht|--require-vht)
shift shift
REQUIREVHT=1 REQUIREVHT=1
@ -496,21 +465,6 @@ parse_user_options(){
VHTSEG1CHINDEX="$1" VHTSEG1CHINDEX="$1"
shift shift
;; ;;
--he-ch-width|--he-channel-width)
shift
HECHANNELWIDTH="$1"
shift
;;
--he-seg0-ch|--he-seg0-channel)
shift
HESEG0CHINDEX="$1"
shift
;;
--he-seg1-ch|--he-seg1-channel)
shift
HESEG1CHINDEX="$1"
shift
;;
--driver) --driver)
shift shift
DRIVER="$1" DRIVER="$1"
@ -575,10 +529,6 @@ parse_user_options(){
LIST_CLIENTS_ID="$1" LIST_CLIENTS_ID="$1"
shift shift
;; ;;
--keep-confdir)
shift
KEEP_CONFDIR=1
;;
*) *)
echo "Invalid parameter: $1" 1>&2 echo "Invalid parameter: $1" 1>&2
@ -654,6 +604,7 @@ get_interface_phy_device() { # only for wifi interface
return 0 return 0
fi fi
done done
echo "Failed to get phy interface" >&2
return 1 return 1
} }
@ -693,22 +644,15 @@ can_be_ap() {
} }
can_transmit_to_channel() { can_transmit_to_channel() {
local IFACE CHANNEL_NUM CHANNEL_INFO CHANNEL_FREQ_FILTER local IFACE CHANNEL_NUM CHANNEL_INFO
IFACE=$1 IFACE=$1
CHANNEL_NUM=$2 CHANNEL_NUM=$2
if [[ $FREQ_BAND == "2.4" ]]; then
CHANNEL_FREQ_FILTER="(24)"
elif [[ $FREQ_BAND -eq 5 ]]; then
CHANNEL_FREQ_FILTER="(5[1-8])"
elif [[ $FREQ_BAND -eq 6 ]]; then
CHANNEL_FREQ_FILTER="((59)|(6[0-9])|(7[0-1]))"
fi
if [[ $USE_IWCONFIG -eq 0 ]]; then if [[ $USE_IWCONFIG -eq 0 ]]; then
CHANNEL_INFO=$(get_adapter_info "${IFACE}" | grep -E " ${CHANNEL_FREQ_FILTER}[0-9]{2}(\.[0-9]+){0,1} MHz \[${CHANNEL_NUM}\]") CHANNEL_INFO=$(get_adapter_info "${IFACE}" | grep -E " [0-9]+(\.[0-9]+){0,1} MHz \[${CHANNEL_NUM}\]")
[[ -z "${CHANNEL_INFO}" ]] && return 1 [[ -z "${CHANNEL_INFO}" ]] && return 1
[[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 2 [[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 1
[[ "${CHANNEL_INFO}" == *disabled* ]] && return 3 [[ "${CHANNEL_INFO}" == *disabled* ]] && return 1
return 0 return 0
else else
CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM}) CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM})
@ -718,26 +662,20 @@ can_transmit_to_channel() {
fi fi
} }
# taken from iw/util.c
ieee80211_frequency_to_channel() { ieee80211_frequency_to_channel() {
local FREQ=$1 local FREQ=$1
if [[ $FREQ -eq 2484 ]]; then
# 2.4G
if [[ $FREQ -ge 2412 && $FREQ -le 2472 ]]; then # 2.4 GHz band: Channels 1-13 (2412~2472 MHz)
echo $(( (FREQ - 2407) / 5 ))
elif [[ $FREQ -eq 2484 ]]; then # 2.4 GHz Channel 14 (2484 MHz, Japan only)
echo 14 echo 14
elif [[ $FREQ -lt 2484 ]]; then
# 5G echo $(( ($FREQ - 2407) / 5 ))
elif [[ $FREQ -ge 5160 && $FREQ -le 5885 ]]; then # 5 GHz band: Standard Channels 36-165 (5180~5825 MHz) (extra: 32, 169-177) elif [[ $FREQ -ge 4910 && $FREQ -le 4980 ]]; then
echo $(( (FREQ - 5000) / 5 )) echo $(( ($FREQ - 4000) / 5 ))
elif [[ $FREQ -le 45000 ]]; then
# 6G echo $(( ($FREQ - 5000) / 5 ))
elif [[ $FREQ -ge 5955 && $FREQ -le 7115 ]]; then # 6 GHz band: Channels 1-233 (5955~7115 MHz), Wi-Fi 6E/7 elif [[ $FREQ -ge 58320 && $FREQ -le 64800 ]]; then
echo $(( (FREQ - 5950) / 5 )) echo $(( ($FREQ - 56160) / 2160 ))
elif [[ $FREQ -eq 5935 ]]; then # 6 GHz band: Special case for 5935 MHz (Channel 2, rare) else
echo 2
else # Frequency not in supported Wi-Fi bands (2.4/5/6 GHz)
echo 0 echo 0
fi fi
} }
@ -954,12 +892,8 @@ get_pid_by_dbus_name() {
} }
is_same_netns() { is_same_netns() {
local pid2="$1" local pid2="$1"
local my_netns his_netns
[[ ! -f /proc/$$/ns/net ]] && return 0 # no netns feature. treat as same [[ ! -f /proc/$$/ns/net ]] && return 0 # no netns feature. treat as same
my_netns="$(readlink /proc/$$/ns/net)" [[ "$(readlink /proc/$$/ns/net)" == "$(readlink /proc/$pid2/ns/net)" ]] && return 0
his_netns="$(readlink /proc/$pid2/ns/net)"
[[ ! -n "$his_netns" ]] && return 1 # can't find his pid or netns (maybe different pidns), treat as not same
[[ "$my_netns" == "$his_netns" ]] && return 0
return 1 return 1
} }
#----------------- #-----------------
@ -1412,7 +1346,7 @@ _cleanup() {
ip addr flush "${SUBNET_IFACE}" ip addr flush "${SUBNET_IFACE}"
[[ ! "$KEEP_CONFDIR" -eq 1 ]] && rm -rf "$CONFDIR" rm -rf "$CONFDIR"
ip link set down dev "${SUBNET_IFACE}" ip link set down dev "${SUBNET_IFACE}"
@ -1448,7 +1382,6 @@ clean_iptables() {
cleanup() { cleanup() {
trap "" SIGINT SIGUSR1 SIGUSR2 EXIT SIGTERM trap "" SIGINT SIGUSR1 SIGUSR2 EXIT SIGTERM
touch "$CONFDIR/exit_$(date +"%Y-%m-%d_%H:%M:%S.%6N")"
echo echo
echo echo
echo "Doing cleanup.. " echo "Doing cleanup.. "
@ -1491,14 +1424,12 @@ init_conf_dirs() {
cd "$TMPDIR" || die "Couldn't change directory to linux-router's temporary path" cd "$TMPDIR" || die "Couldn't change directory to linux-router's temporary path"
CONFDIR="$(mktemp -d $TMPDIR/lnxrouter.${TARGET_IFACE}.conf.XXXXXX)" || die "Instance couldn't make config dir" # config dir for one instance CONFDIR="$(mktemp -d $TMPDIR/lnxrouter.${TARGET_IFACE}.conf.XXXXXX)" || die "Instance couldn't make config dir" # config dir for one instance
echo "Config dir: $CONFDIR" chmod 755 "$CONFDIR"
chmod 755 "$CONFDIR" || die "chmod config dir failed" #echo "Config dir: $CONFDIR"
echo $$ > "$CONFDIR/pid" echo $$ > "$CONFDIR/pid"
touch "$CONFDIR/begin_$(date +"%Y-%m-%d_%H:%M:%S.%6N")"
COMMON_CONFDIR="$TMPDIR/lnxrouter_common.conf" # config dir for all instances COMMON_CONFDIR="$TMPDIR/lnxrouter_common.conf" # config dir for all instances
mkdir -p "$COMMON_CONFDIR" || die "Failed creating common config dir" mkdir -p "$COMMON_CONFDIR"
} }
#== functions to deal with running instances #== functions to deal with running instances
@ -1748,14 +1679,9 @@ daemonizing_check(){
#============================ #============================
check_wifi_settings() { check_wifi_settings() {
PHY="$(get_interface_phy_device "$WIFI_IFACE")"
if [[ -z "$PHY" ]]; then
echo "ERROR: Can't get phy of wifi interface '$WIFI_IFACE' (Did you spell the interface name right?)" >&2
exit 1
fi
if ! ( which iw > /dev/null 2>&1 && iw dev "$WIFI_IFACE" info > /dev/null 2>&1 ); then if ! ( which iw > /dev/null 2>&1 && iw dev "$WIFI_IFACE" info > /dev/null 2>&1 ); then
echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ..." >&2 echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ... (Did you spell the interface name right?)" >&2
USE_IWCONFIG=1 USE_IWCONFIG=1
fi fi
@ -1942,8 +1868,6 @@ prepare_wifi_interface() {
CHANNEL=36 CHANNEL=36
fi fi
fi fi
echo "Freq band: $FREQ_BAND GHz Channel: $CHANNEL"
} }
decide_subnet_interface() { decide_subnet_interface() {
@ -2035,16 +1959,6 @@ write_hostapd_conf() {
echo "require_vht=1" >> "$CONFDIR/hostapd.conf" echo "require_vht=1" >> "$CONFDIR/hostapd.conf"
fi fi
if [[ $IEEE80211AX -eq 1 ]]; then
echo "ieee80211ax=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ $REQUIREHE -eq 1 ]]; then
echo "require_he=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ -n "$VHT_CAPAB" ]]; then if [[ -n "$VHT_CAPAB" ]]; then
echo "vht_capab=${VHT_CAPAB}" >> "$CONFDIR/hostapd.conf" echo "vht_capab=${VHT_CAPAB}" >> "$CONFDIR/hostapd.conf"
fi fi
@ -2067,25 +1981,7 @@ write_hostapd_conf() {
EOF EOF
fi fi
if [[ $HECHANNELWIDTH -gt 0 ]]; then if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
he_oper_chwidth=${HECHANNELWIDTH}
EOF
fi
if [[ $HESEG0CHINDEX -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
he_oper_centr_freq_seg0_idx=${HESEG0CHINDEX}
EOF
fi
if [[ $HESEG1CHINDEX -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
he_oper_centr_freq_seg1_idx=${HESEG1CHINDEX}
EOF
fi
if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]] || [[ $IEEE80211AX -eq 1 ]]; then
echo "wmm_enabled=1" >> "$CONFDIR/hostapd.conf" echo "wmm_enabled=1" >> "$CONFDIR/hostapd.conf"
fi fi
@ -2265,8 +2161,10 @@ start_dnsmasq() {
} }
check_rfkill_unblock_wifi() { check_rfkill_unblock_wifi() {
local PHY
if which rfkill > /dev/null 2>&1 ; then if which rfkill > /dev/null 2>&1 ; then
rfkill unblock $(rfkill | grep "$PHY" | awk '{print $1}') >/dev/null 2>&1 PHY=$(get_interface_phy_device "${SUBNET_IFACE}")
[[ -n $PHY ]] && rfkill unblock $(rfkill | grep "$PHY" | awk '{print $1}') >/dev/null 2>&1
fi fi
} }
@ -2348,7 +2246,7 @@ fi
# judge channel availability after changing country code # judge channel availability after changing country code
if [[ $WIFI_IFACE ]] ; then if [[ $WIFI_IFACE ]] ; then
can_transmit_to_channel "${AP_IFACE}" ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz. (Tips: 1. Check usable channels: 'iw phy $PHY info'. 2. Check country code then check again. )" can_transmit_to_channel "${AP_IFACE}" ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz."
fi fi
[[ $WIFI_IFACE ]] && write_hostapd_conf [[ $WIFI_IFACE ]] && write_hostapd_conf