fix: health check repairs dropped monitors even when pineapd is healthy
wifi reloads during attack deploy/stop drop the monitor interfaces and pineapd only recovers its primary; the monitor now brings both up whenever it finds them down, with or without a pineapd failure.
This commit is contained in:
@@ -3403,30 +3403,39 @@ def health_check():
|
|||||||
h = _health
|
h = _health
|
||||||
rc, out, err = device_run(['pidof', 'pineapd'], timeout=10)
|
rc, out, err = device_run(['pidof', 'pineapd'], timeout=10)
|
||||||
h['pineap_up'] = rc == 0 and bool((out or '').strip())
|
h['pineap_up'] = rc == 0 and bool((out or '').strip())
|
||||||
if h['pineap_up']:
|
if not h['pineap_up']:
|
||||||
|
now = time.time()
|
||||||
|
if now - h['last_fix'] < HEALTH_FIX_COOLDOWN:
|
||||||
|
return dict(h)
|
||||||
|
pool = _uci_section('pineapd.@ssidpool[0]')
|
||||||
|
if pool.get('disable') != '1':
|
||||||
|
device_run(['uci', 'set', 'pineapd.@ssidpool[0].disable=1'])
|
||||||
|
device_run(['uci', 'commit', 'pineapd'])
|
||||||
|
h['last_action'] = 'SSID pool broadcast disabled (pineapd crash-loop fix)'
|
||||||
|
elif _monitor_down('wlan1mon') or _monitor_down('wlan0mon'):
|
||||||
|
_bring_monitors_up(h)
|
||||||
|
else:
|
||||||
|
h['last_action'] = _stabilize_pineapd()
|
||||||
|
device_run(['/etc/init.d/pineapd', 'restart'], timeout=30)
|
||||||
|
h['sigsegv_last'] = _sigsegv_count()
|
||||||
|
h['last_fix'] = now
|
||||||
|
h['fixes'] += 1
|
||||||
return dict(h)
|
return dict(h)
|
||||||
now = time.time()
|
# pineapd is healthy, but wifi reloads still drop the monitors (pineapd
|
||||||
if now - h['last_fix'] < HEALTH_FIX_COOLDOWN:
|
# does not bring secondary monitors back). Repair them without cooldown.
|
||||||
return dict(h)
|
if _monitor_down('wlan1mon') or _monitor_down('wlan0mon'):
|
||||||
pool = _uci_section('pineapd.@ssidpool[0]')
|
_bring_monitors_up(h)
|
||||||
if pool.get('disable') != '1':
|
|
||||||
device_run(['uci', 'set', 'pineapd.@ssidpool[0].disable=1'])
|
|
||||||
device_run(['uci', 'commit', 'pineapd'])
|
|
||||||
h['last_action'] = 'SSID pool broadcast disabled (pineapd crash-loop fix)'
|
|
||||||
elif _monitor_down('wlan1mon') or _monitor_down('wlan0mon'):
|
|
||||||
for name in ('wlan1mon', 'wlan0mon'):
|
|
||||||
if _monitor_down(name):
|
|
||||||
device_run(['ip', 'link', 'set', name, 'up'], timeout=10)
|
|
||||||
h['last_action'] = 'monitor interfaces brought up'
|
|
||||||
else:
|
|
||||||
h['last_action'] = _stabilize_pineapd()
|
|
||||||
device_run(['/etc/init.d/pineapd', 'restart'], timeout=30)
|
|
||||||
h['sigsegv_last'] = _sigsegv_count()
|
|
||||||
h['last_fix'] = now
|
|
||||||
h['fixes'] += 1
|
|
||||||
return dict(h)
|
return dict(h)
|
||||||
|
|
||||||
|
|
||||||
|
def _bring_monitors_up(h):
|
||||||
|
for name in ('wlan1mon', 'wlan0mon'):
|
||||||
|
if _monitor_down(name):
|
||||||
|
device_run(['ip', 'link', 'set', name, 'up'], timeout=10)
|
||||||
|
h['last_action'] = 'monitor interfaces brought up'
|
||||||
|
h['monitor_fixes'] = h.get('monitor_fixes', 0) + 1
|
||||||
|
|
||||||
|
|
||||||
def h_health(ctx):
|
def h_health(ctx):
|
||||||
h = dict(_health)
|
h = dict(_health)
|
||||||
h['sigsegv_count'] = h.pop('sigsegv_last')
|
h['sigsegv_count'] = h.pop('sigsegv_last')
|
||||||
|
|||||||
@@ -59,6 +59,14 @@ class HealthCheckTest(unittest.TestCase):
|
|||||||
self.assertEqual([r[0] for r in self.runs], [['pidof', 'pineapd']],
|
self.assertEqual([r[0] for r in self.runs], [['pidof', 'pineapd']],
|
||||||
'health check must not write to the pineapd socket')
|
'health check must not write to the pineapd socket')
|
||||||
|
|
||||||
|
def test_pineap_up_repairs_dropped_monitors(self):
|
||||||
|
self.iface_up = {'wlan0mon': False, 'wlan1mon': True}
|
||||||
|
result = server.health_check()
|
||||||
|
self.assertTrue(result['pineap_up'])
|
||||||
|
self.assertEqual(result['last_action'], 'monitor interfaces brought up')
|
||||||
|
self.assertIn(['ip', 'link', 'set', 'wlan0mon', 'up'], [r[0] for r in self.runs])
|
||||||
|
self.assertEqual(result['monitor_fixes'], 1)
|
||||||
|
|
||||||
def test_down_with_growing_sigsegv_disables_pool(self):
|
def test_down_with_growing_sigsegv_disables_pool(self):
|
||||||
self.ping_ok = False
|
self.ping_ok = False
|
||||||
self.sigsegs = 5
|
self.sigsegs = 5
|
||||||
|
|||||||
Reference in New Issue
Block a user