You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
5.9 KiB
Plaintext
198 lines
5.9 KiB
Plaintext
4 years ago
|
#
|
||
|
# Copyright 2018 devolo AG
|
||
|
#
|
||
|
|
||
|
set_delos_peer_isolation() { (
|
||
|
#local EBLOG=--log
|
||
|
action="$1"
|
||
|
|
||
|
delos_determine_prefixes
|
||
|
|
||
|
# throw away current user-defined chains
|
||
|
ebtables -D FORWARD -i ${INTERFACE_PREFIX}0+ -o ${INTERFACE_PREFIX}1+ -j ssid-isolation $EBLOG 2>/dev/null
|
||
|
ebtables -D FORWARD -i ${INTERFACE_PREFIX}1+ -o ${INTERFACE_PREFIX}0+ -j ssid-isolation $EBLOG 2>/dev/null
|
||
|
ebtables -X ssid-isolation 2>/dev/null
|
||
|
|
||
|
[ "$action" = "disable" ] && return 0
|
||
|
|
||
|
# enabled radios
|
||
|
radios=$(ubus call uci get '{"config":"wireless","type":"wifi-device"}' | jsonfilter -e '$.*[!(@.disabled="1")][".name"]')
|
||
|
radios=$(echo $radios) # sic! DO NOT ADD QUOTES!
|
||
|
# if at most 1 radio is enabled no rules are required
|
||
|
[ $(echo $radios | wc -w) -lt 2 ] && return
|
||
|
|
||
|
. /usr/share/libubox/jshn.sh
|
||
|
json_load "$(ubus call uci get '{"config":"wireless","type":"wifi-iface"}')"
|
||
|
|
||
|
json_select values
|
||
|
|
||
|
# Note: result is returned in devs (radios), aps_<radio> (for each radio)
|
||
|
delos_enumerate_${DRIVER}
|
||
|
|
||
|
# if SSIDs for at most 1 radio are enabled no rules are required
|
||
|
[ $(echo "$devs" | wc -w) -lt 2 ] && return
|
||
|
|
||
|
# add the specific peer isolation rules to chain ssid-isolation
|
||
|
# problem: must use same wlan iface enumeration as netifd/mac80211.sh
|
||
|
# ebtables -A ssid-isolation -i <wlan0...> -o <wlan1...> -j DROP
|
||
|
# ebtables -A ssid-isolation -i <wlan1...> -o <wlan0...> -j DROP
|
||
|
|
||
|
# match paired APs ifnames (conditions as in delos-webui: same ssid+encr+key)
|
||
|
# for APs with client isolation/guest wifi restrictions enabled!
|
||
|
## works for 2 radios only. match first device SSIDs with those of 2nd
|
||
|
echo $devs | {
|
||
|
read dev1 dev2 _
|
||
|
eval "ifs1=\${aps_$dev1}"
|
||
|
eval "ifs2=\${aps_$dev2}"
|
||
|
pairs=$(for if1 in $ifs1; do
|
||
|
json_select $if1
|
||
|
json_get_vars ifname ssid encryption key isolate:0 dvl_guest:0 dvl_unrestricted_access:0
|
||
|
# isolate too if guest wifi internet is not unrestricted
|
||
|
[ "$isolate" = "1" ] || ([ "$dvl_guest" = "1" ] && [ "$dvl_unrestricted_access" = "0" ]) && (
|
||
|
# subshell! for separate json context
|
||
|
ifname1=$ifname
|
||
|
ssid1=$ssid
|
||
|
encryption1=$encryption
|
||
|
key1=$key
|
||
|
json_get_var dynamic_vlan dynamic_vlan 0
|
||
|
for if2 in $ifs2; do
|
||
|
json_select ..
|
||
|
json_select $if2
|
||
|
json_get_vars ifname ssid encryption key
|
||
|
[ "$ssid1" = "$ssid" ] &&
|
||
|
[ "$encryption1" = "$encryption" ] &&
|
||
|
[ "$key1" = "$key" ] && {
|
||
|
echo "$if1;$if2"
|
||
|
break
|
||
|
}
|
||
|
done
|
||
|
)
|
||
|
json_select ..
|
||
|
done)
|
||
|
# make rules
|
||
|
chains_installed=
|
||
|
for pair in $pairs; do
|
||
|
json_select ${pair%;*}
|
||
|
json_get_var ifname1 ifname
|
||
|
json_get_vars dynamic_vlan
|
||
|
json_select ..
|
||
|
json_select ${pair#*;}
|
||
|
json_get_var ifname2 ifname
|
||
|
json_select ..
|
||
|
# Once install user-defined chains to group rules for easier deletion
|
||
|
[ -z "$chains_installed" ] && {
|
||
|
chains_installed=1
|
||
|
ebtables -N ssid-isolation -P RETURN
|
||
|
ebtables -A FORWARD -i ${INTERFACE_PREFIX}0+ -o ${INTERFACE_PREFIX}1+ -j ssid-isolation $EBLOG
|
||
|
ebtables -A FORWARD -i ${INTERFACE_PREFIX}1+ -o ${INTERFACE_PREFIX}0+ -j ssid-isolation $EBLOG
|
||
|
}
|
||
|
# rule for plain vlan
|
||
|
ebtables -A ssid-isolation -i $ifname1 -o $ifname2 -j DROP $EBLOG
|
||
|
ebtables -A ssid-isolation -i $ifname2 -o $ifname1 -j DROP $EBLOG
|
||
|
[ "$dynamic_vlan" -gt 0 ] && {
|
||
|
# rule for dynamic vlans
|
||
|
ebtables -A ssid-isolation -i $ifname1.+ -o $ifname2.+ -j DROP $EBLOG
|
||
|
ebtables -A ssid-isolation -i $ifname2.+ -o $ifname1.+ -j DROP $EBLOG
|
||
|
}
|
||
|
done
|
||
|
}
|
||
|
json_select ..
|
||
|
json_cleanup
|
||
|
) }
|
||
|
|
||
|
delos_determine_prefixes() {
|
||
|
if [ -d /sys/class/net/wifi0 ]; then
|
||
|
DRIVER=qcawifi
|
||
|
RADIO_PREFIX="wifi"
|
||
|
INTERFACE_PREFIX="ath"
|
||
|
else
|
||
|
DRIVER=mac80211
|
||
|
RADIO_PREFIX="radio"
|
||
|
INTERFACE_PREFIX="wlan"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
delos_enumerate_mac80211() {
|
||
|
# APs' ifnames are generated after those of non AP-interfaces (idx covers this)
|
||
|
# find enabled APs of enabled radios, save new radios list in devs
|
||
|
devs=
|
||
|
json_get_keys ifs
|
||
|
for iface in $ifs; do
|
||
|
json_select $iface
|
||
|
json_get_vars disabled mode device
|
||
|
list_contains radios $device && [ "$disabled" != "1" ] && {
|
||
|
list_contains devs $device || {
|
||
|
append devs $device
|
||
|
eval "non_aps_$device="
|
||
|
eval "aps_$device="
|
||
|
}
|
||
|
[ "$mode" != "ap" ] && {
|
||
|
eval ": \$((non_aps_$device++))"
|
||
|
}
|
||
|
[ "$mode" = "ap" ] && {
|
||
|
eval "append aps_$device $iface"
|
||
|
}
|
||
|
}
|
||
|
json_select ..
|
||
|
done
|
||
|
for i in $devs; do
|
||
|
eval "logger \"$i: \${non_aps_$i:-0} non-APs. APs:\${aps_$i}\""
|
||
|
done
|
||
|
|
||
|
for i in $devs; do
|
||
|
eval "idx=\${non_aps_$i}"
|
||
|
eval "ifs=\${aps_$i}"
|
||
|
[ -z "$ifs" ] && return
|
||
|
for iface in $ifs; do
|
||
|
json_select $iface
|
||
|
json_get_vars ifname mode device
|
||
|
[ "$mode" = "ap" ] && [ -z "$ifname" ] && {
|
||
|
json_add_string ifname "${INTERFACE_PREFIX}${i#${RADIO_PREFIX}}${idx:+-${idx}}"
|
||
|
: $((idx++))
|
||
|
}
|
||
|
json_select ..
|
||
|
done
|
||
|
done
|
||
|
}
|
||
|
|
||
|
delos_enumerate_qcawifi() {
|
||
|
# enumerate APs ifnames as in qcawifi, add to json-config
|
||
|
# qcawifi script just takes one interface after another regardless of its type -> skip non-aps
|
||
|
devs=
|
||
|
json_get_keys ifs
|
||
|
for radio in $radios; do
|
||
|
eval idx_$radio=
|
||
|
done
|
||
|
for iface in $ifs; do
|
||
|
json_select $iface
|
||
|
json_get_vars disabled mode device
|
||
|
list_contains radios $device && [ "$disabled" != "1" ] && {
|
||
|
list_contains devs $device || {
|
||
|
append devs $device
|
||
|
}
|
||
|
[ "$mode" = "ap" ] && {
|
||
|
eval "append aps_$device $iface"
|
||
|
}
|
||
|
eval "json_add_string ifname \"${INTERFACE_PREFIX}\${device#\${RADIO_PREFIX}}\${idx_$device:+\$idx_$device}\""
|
||
|
eval ": \$((idx_$device++))"
|
||
|
}
|
||
|
json_select ..
|
||
|
done
|
||
|
}
|
||
|
|
||
|
delos_wifi_peer_isolation_post() {
|
||
|
set_delos_peer_isolation "$@"
|
||
|
}
|
||
|
|
||
|
# is DELOS_WIFI_DRIVERS defined at all (empty or non-empty)? (force exit code 0 if empty,
|
||
|
# don't exit current script if not defined)
|
||
|
if (: ${DELOS_WIFI_DRIVERS?}) 2>/dev/null; then
|
||
|
# we were sourced to register as a plugin
|
||
|
delos_wifi_driver_peer_isolation() {
|
||
|
type=$1; shift
|
||
|
type delos_wifi_peer_isolation_$type >/dev/null 2>/dev/null && delos_wifi_peer_isolation_$type "$@"
|
||
|
}
|
||
|
|
||
|
append DELOS_WIFI_DRIVERS delos_wifi_driver_peer_isolation
|
||
|
fi
|