Skip to content

Commit 75c2520

Browse files
authored
Merge pull request #1215 from kernelkit/robustness
Add error handling to prevent interface query failures Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2 parents 4b37474 + f1f2c66 commit 75c2520

File tree

1 file changed

+85
-50
lines changed
  • src/statd/python/yanger/ietf_interfaces

1 file changed

+85
-50
lines changed

src/statd/python/yanger/ietf_interfaces/wifi.py

Lines changed: 85 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,54 @@
33
import re
44

55
def wifi(ifname):
6-
data=HOST.run(tuple(f"wpa_cli -i {ifname} status".split()), default="")
76
wifi_data={}
87

9-
if data != "":
10-
for line in data.splitlines():
11-
k,v = line.split("=")
12-
if k == "ssid":
13-
wifi_data["ssid"] = v
14-
if k == "wpa_state" and v == "DISCONNECTED": # wpa_suppicant has most likely restarted, restart scanning
15-
HOST.run(tuple(f"wpa_cli -i {ifname} scan".split()), default="")
8+
try:
9+
data=HOST.run(tuple(f"wpa_cli -i {ifname} status".split()), default="")
1610

17-
data=HOST.run(tuple(f"wpa_cli -i {ifname} signal_poll".split()), default="FAIL")
18-
19-
# signal_poll return FAIL not connected
20-
if data.strip() != "FAIL":
11+
if data != "":
2112
for line in data.splitlines():
22-
k,v = line.strip().split("=")
23-
if k == "RSSI":
24-
wifi_data["rssi"]=int(v)
25-
data=HOST.run(tuple(f"wpa_cli -i {ifname} scan_result".split()), default="FAIL")
26-
27-
if data != "FAIL":
28-
wifi_data["scan-results"] = parse_wpa_scan_result(data)
13+
try:
14+
if "=" not in line:
15+
continue
16+
k,v = line.split("=", 1)
17+
if k == "ssid":
18+
wifi_data["ssid"] = v
19+
if k == "wpa_state" and v == "DISCONNECTED": # wpa_suppicant has most likely restarted, restart scanning
20+
HOST.run(tuple(f"wpa_cli -i {ifname} scan".split()), default="")
21+
except ValueError:
22+
# Skip malformed lines
23+
continue
24+
25+
try:
26+
data=HOST.run(tuple(f"wpa_cli -i {ifname} signal_poll".split()), default="FAIL")
27+
28+
# signal_poll return FAIL not connected
29+
if data.strip() != "FAIL":
30+
for line in data.splitlines():
31+
try:
32+
if "=" not in line:
33+
continue
34+
k,v = line.strip().split("=", 1)
35+
if k == "RSSI":
36+
wifi_data["rssi"]=int(v)
37+
except (ValueError, KeyError):
38+
# Skip malformed lines or invalid integers
39+
continue
40+
except Exception:
41+
# If signal_poll fails, continue without RSSI
42+
pass
43+
except Exception:
44+
# If status query fails entirely, continue with scan results
45+
pass
46+
47+
try:
48+
data=HOST.run(tuple(f"wpa_cli -i {ifname} scan_result".split()), default="FAIL")
49+
if data != "FAIL":
50+
wifi_data["scan-results"] = parse_wpa_scan_result(data)
51+
except Exception:
52+
# If scan results fail, just omit them
53+
pass
2954

3055
return wifi_data
3156

@@ -36,39 +61,49 @@ def parse_wpa_scan_result(scan_output):
3661

3762
# Skip header line and any empty lines
3863
for line in lines:
39-
line = line.strip()
40-
if not line or 'bssid / frequency' in line.lower():
41-
continue
42-
43-
# Split by tabs or multiple spaces
44-
parts = re.split(r'\t+|\s{2,}', line)
45-
46-
if len(parts) >= 5:
47-
bssid = parts[0].strip()
48-
frequency = int(parts[1].strip())
49-
rssi = int(parts[2].strip())
50-
flags = parts[3].strip()
51-
ssid = parts[4].strip() if len(parts) > 4 else ""
52-
53-
# Skip hidden SSIDs (empty or whitespace only)
54-
if not ssid or ssid.isspace() or '\\x00' in ssid:
64+
try:
65+
line = line.strip()
66+
if not line or 'bssid / frequency' in line.lower():
5567
continue
5668

57-
# Extract encryption information from flags
58-
encryption = extract_encryption(flags)
59-
60-
# Convert frequency to channel
61-
channel = frequency_to_channel(frequency)
62-
63-
# Keep only the network with best (highest) RSSI per SSID
64-
if ssid not in networks or rssi < networks[ssid]['rssi']:
65-
networks[ssid] = {
66-
'bssid': bssid,
67-
'ssid': ssid,
68-
'rssi': rssi,
69-
'encryption': encryption,
70-
'channel': channel
71-
}
69+
# Split by tabs or multiple spaces
70+
parts = re.split(r'\t+|\s{2,}', line)
71+
72+
if len(parts) >= 5:
73+
bssid = parts[0].strip()
74+
try:
75+
frequency = int(parts[1].strip())
76+
rssi = int(parts[2].strip())
77+
except ValueError:
78+
# Skip lines with invalid frequency or RSSI
79+
continue
80+
81+
flags = parts[3].strip()
82+
ssid = parts[4].strip() if len(parts) > 4 else ""
83+
84+
# Skip hidden SSIDs (empty or whitespace only)
85+
if not ssid or ssid.isspace() or '\\x00' in ssid:
86+
continue
87+
88+
# Extract encryption information from flags
89+
encryption = extract_encryption(flags)
90+
91+
# Convert frequency to channel
92+
channel = frequency_to_channel(frequency)
93+
94+
# Keep only the network with best (highest) RSSI per SSID
95+
if ssid not in networks or rssi < networks[ssid]['rssi']:
96+
networks[ssid] = {
97+
'bssid': bssid,
98+
'ssid': ssid,
99+
'rssi': rssi,
100+
'encryption': encryption,
101+
'channel': channel
102+
}
103+
except Exception:
104+
# Skip any malformed scan result lines
105+
continue
106+
72107
# Convert to list and sort by RSSI (best first)
73108
result = list(networks.values())
74109
result.sort(key=lambda x: x['rssi'], reverse=False)

0 commit comments

Comments
 (0)