feat: radio1 5GHz/6GHz rogue AP via UCI with hop pause
This commit is contained in:
@@ -1717,7 +1717,7 @@ def _apply_open_radio(openap):
|
||||
daemon's iface-level channel write does not affect the actual radio, so
|
||||
apply channel/country here and reload wifi when they change."""
|
||||
changed = False
|
||||
radio = _uci_wifi_iface('radio0')
|
||||
radio = _uci_wifi_iface('radio0') or {}
|
||||
for key in ('channel', 'country'):
|
||||
value = openap.get(key)
|
||||
if value is None:
|
||||
@@ -1739,11 +1739,100 @@ def _open_channel(value):
|
||||
return 1
|
||||
|
||||
|
||||
def _read_hop():
|
||||
rc, out, err = device_run(['uci', 'get', 'pineapd.wlan1mon.hop'])
|
||||
return out.strip()
|
||||
|
||||
|
||||
def _pause_hop():
|
||||
if _read_hop() != '0':
|
||||
device_run(['uci', 'set', 'pineapd.wlan1mon.hop=0'])
|
||||
device_run(['uci', 'commit', 'pineapd'])
|
||||
device_run(['/etc/init.d/pineapd', 'reload'])
|
||||
|
||||
|
||||
def _resume_hop():
|
||||
if _read_hop() == '0':
|
||||
device_run(['uci', 'set', 'pineapd.wlan1mon.hop=1'])
|
||||
device_run(['uci', 'commit', 'pineapd'])
|
||||
device_run(['/etc/init.d/pineapd', 'reload'])
|
||||
|
||||
|
||||
def _remove_radio1_ap():
|
||||
device_run(['uci', 'delete', 'wireless.wlan1open'])
|
||||
device_run(['uci', 'delete', 'wireless.wlan1wpa'])
|
||||
device_run(['uci', 'set', 'wireless.radio1.channel=auto'])
|
||||
device_run(['uci', 'set', 'wireless.radio1.band=5g'])
|
||||
device_run(['uci', 'commit', 'wireless'])
|
||||
_resume_hop()
|
||||
|
||||
|
||||
def _apply_radio1_ap(openap, wpa):
|
||||
band = None
|
||||
if openap is not None:
|
||||
band = channel_band(openap.get('channel'))
|
||||
iface = 'wlan1open'
|
||||
if wpa is not None:
|
||||
band = channel_band(wpa.get('channel'))
|
||||
iface = 'wlan1wpa'
|
||||
if band not in (BAND_5G, BAND_6G):
|
||||
raise ValueError('radio1 AP requires a 5GHz or 6GHz channel')
|
||||
if band == BAND_6G and wpa is not None:
|
||||
if (wpa.get('enctype') or 'psk2') not in ('sae', 'owe'):
|
||||
raise ValueError('6GHz requires WPA3 (sae or owe)')
|
||||
device_run(['uci', 'delete', 'wireless.wlan1open'])
|
||||
device_run(['uci', 'delete', 'wireless.wlan1wpa'])
|
||||
device_run(['uci', 'set', 'wireless.radio1.band=%s' % ('6g' if band == BAND_6G else '5g')])
|
||||
ch = int(wpa.get('channel') if wpa is not None else openap.get('channel'))
|
||||
device_run(['uci', 'set', 'wireless.radio1.channel=%d' % ch])
|
||||
device_run(['uci', 'set', 'wireless.radio1.htmode=%s' % band_htmode(band)])
|
||||
country = (wpa or openap or {}).get('country')
|
||||
if country:
|
||||
device_run(['uci', 'set', 'wireless.radio1.country=%s' % country])
|
||||
cfg = wpa if wpa is not None else openap
|
||||
device_run(['uci', 'set', 'wireless.%s=wifi-iface' % iface])
|
||||
device_run(['uci', 'set', 'wireless.%s.device=radio1' % iface])
|
||||
device_run(['uci', 'set', 'wireless.%s.mode=ap' % iface])
|
||||
device_run(['uci', 'set', 'wireless.%s.ssid=%s' % (iface, cfg.get('ssid') or '')])
|
||||
device_run(['uci', 'set', 'wireless.%s.hidden=%d' % (iface, 1 if cfg.get('hidden') else 0)])
|
||||
device_run(['uci', 'set', 'wireless.%s.channel=%d' % (iface, int(cfg.get('channel')))])
|
||||
if wpa is not None:
|
||||
device_run(['uci', 'set', 'wireless.%s.encryption=%s' % (iface, wpa.get('enctype') or 'psk2')])
|
||||
device_run(['uci', 'set', 'wireless.%s.key=%s' % (iface, wpa.get('passphrase') or '')])
|
||||
else:
|
||||
device_run(['uci', 'set', 'wireless.%s.encryption=none' % iface])
|
||||
bssid = (openap or {}).get('bssid') or ''
|
||||
if bssid:
|
||||
device_run(['uci', 'set', 'wireless.%s.macaddr=%s' % (iface, bssid)])
|
||||
device_run(['uci', 'commit', 'wireless'])
|
||||
_pause_hop()
|
||||
device_run(['wifi', 'reload'])
|
||||
|
||||
|
||||
def h_pineap_wifi_set_ap(ctx):
|
||||
body = ctx.body or {}
|
||||
configs = []
|
||||
wpa = body.get('wpa') or {}
|
||||
openap = body.get('open') or {}
|
||||
wpa_band = channel_band(wpa.get('channel')) if wpa.get('channel') is not None else None
|
||||
open_band = channel_band(openap.get('channel')) if openap.get('channel') is not None else None
|
||||
use_radio1 = wpa_band in (BAND_5G, BAND_6G) or open_band in (BAND_5G, BAND_6G)
|
||||
if use_radio1:
|
||||
wpa_active = bool(wpa.get('enabled', True)) and wpa.get('channel') is not None
|
||||
open_active = bool(openap.get('enabled', True)) and openap.get('channel') is not None
|
||||
if not (wpa_active or open_active):
|
||||
_remove_radio1_ap()
|
||||
device_run(['wifi', 'reload'])
|
||||
return 200, {'ok': True}
|
||||
try:
|
||||
_apply_radio1_ap(openap if open_active else None,
|
||||
wpa if wpa_active else None)
|
||||
except ValueError as exc:
|
||||
return 400, {'error': str(exc)}
|
||||
return 200, {'ok': True}
|
||||
if _uci_wifi_iface('wlan1open') or _uci_wifi_iface('wlan1wpa'):
|
||||
_remove_radio1_ap()
|
||||
device_run(['wifi', 'reload'])
|
||||
configs = []
|
||||
if wpa.get('ssid') or wpa.get('enabled') is not None:
|
||||
configs.append({
|
||||
'interface': 'wlan0wpa',
|
||||
|
||||
Reference in New Issue
Block a user