File: wlan.py

package info (click to toggle)
python-asusrouter 1.21.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,856 kB
  • sloc: python: 20,497; makefile: 3
file content (223 lines) | stat: -rw-r--r-- 5,812 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
"""WLAN module."""

from __future__ import annotations

from collections.abc import Awaitable, Callable
from enum import Enum, IntEnum
from typing import Any

from asusrouter.modules.const import MapValueType
from asusrouter.tools.converters import (
    get_arguments,
    safe_bool,
    safe_int,
    safe_unpack_key,
)
from asusrouter.tools.writers import nvram


class Wlan(str, Enum):
    """WLAN type class."""

    FREQ_2G = "2ghz"
    FREQ_5G = "5ghz"
    FREQ_5G2 = "5ghz2"
    FREQ_6G = "6ghz"
    UNKNOWN = "unknown"


# A map to correspond possible values to the WlanType
# E.g. `wlc_0` -> FREQ_2G, `wlc_1` -> FREQ_5G, etc.
# But also `wl0` -> FREQ_2G, `wl1` -> FREQ_5G, etc.
WLAN_TYPE: dict[str | int, Wlan] = {
    0: Wlan.FREQ_2G,
    1: Wlan.FREQ_5G,
    2: Wlan.FREQ_5G2,
    3: Wlan.FREQ_6G,
    "2.4G": Wlan.FREQ_2G,
    "5G": Wlan.FREQ_5G,
    "5G-2": Wlan.FREQ_5G2,
    "wifi6e": Wlan.FREQ_6G,
    "wlc_0": Wlan.FREQ_2G,
    "wlc_1": Wlan.FREQ_5G,
    "wlc_2": Wlan.FREQ_5G2,
    "wlc_3": Wlan.FREQ_6G,
    "wl0": Wlan.FREQ_2G,
    "wl1": Wlan.FREQ_5G,
    "wl2": Wlan.FREQ_5G2,
    "wl3": Wlan.FREQ_6G,
}

# A map of NVRAM values for a GWLAN
MAP_GWLAN: list[MapValueType] = [
    ("wl{}_akm"),
    ("wl{}_ap_isolate"),
    ("wl{}_auth"),
    ("wl{}_auth_mode"),
    ("wl{}_auth_mode_x"),
    ("wl{}_bridge"),
    ("wl{}_bss_enabled", safe_bool),
    ("wl{}_bss_maxassoc", safe_int),
    ("wl{}_bw_dl", safe_int),  # Bandwidth limit download
    ("wl{}_bw_enabled", safe_bool),  # Bandwidth limit switch
    ("wl{}_bw_ul", safe_int),  # Bandwidth limit upload
    ("wl{}_closed", safe_bool),
    ("wl{}_crypto"),
    ("wl{}_expire", safe_int),  # Expire time in s
    ("wl{}_expire_tmp", safe_int),  # Expire time left in s
    ("wl{}_gn_wbl_enable"),
    ("wl{}_gn_wbl_rule"),
    ("wl{}_gn_wbl_type"),
    ("wl{}_hwaddr"),  # MAC address
    ("wl{}_ifname"),  # Interface name
    ("wl{}_infra"),
    ("wl{}_key"),
    ("wl{}_key1"),
    ("wl{}_key2"),
    ("wl{}_key3"),
    ("wl{}_key4"),
    ("wl{}_lanaccess", safe_bool),  # LAN access
    ("wl{}_maclist"),
    ("wl{}_macmode"),
    ("wl{}_maxassoc", safe_int),
    ("wl{}_mbss"),
    ("wl{}_mfp"),
    ("wl{}_mode"),
    ("wl{}_net_reauth", safe_int),
    ("wl{}_preauth"),
    ("wl{}_radio", safe_bool),
    ("wl{}_radius_ipaddr"),
    ("wl{}_radius_key"),
    ("wl{}_radius_port", safe_int),
    ("wl{}_sae_anti_clog_threshold"),
    ("wl{}_sae_groups"),
    ("wl{}_sae_sync"),
    ("wl{}_ssid"),  # SSID
    ("wl{}_sta_retry_time"),
    ("wl{}_sync_node", safe_bool),  # Sync AiMesh nodes
    ("wl{}_unit"),  # GWLAN unit id
    ("wl{}_wep", safe_bool),
    ("wl{}_wep_x", safe_bool),
    ("wl{}_wfi_enable", safe_bool),
    ("wl{}_wfi_pinmode"),
    ("wl{}_wme"),
    ("wl{}_wme_bss_disable", safe_bool),
    ("wl{}_wpa_gtk_rekey"),
    ("wl{}_wpa_psk"),  # Password
    ("wl{}_wps_mode"),
]


# A map of NVRAM values for a WLAN
MAP_WLAN: list[MapValueType] = [
    ("wl{}_auth_mode_x"),
    ("wl{}_bw"),
    ("wl{}_channel"),
    ("wl{}_chanspec"),
    ("wl{}_closed", safe_bool),
    ("wl{}_country_code"),
    ("wl{}_crypto"),
    ("wl{}_gmode_check"),
    ("wl{}_maclist_x"),
    ("wl{}_macmode"),
    ("wl{}_mbo_enable"),
    ("wl{}_mfp"),
    ("wl{}_nmode_x"),
    ("wl{}_optimizexbox_ckb"),
    ("wl{}_radio", safe_bool),
    ("wl{}_radius_ipaddr"),
    ("wl{}_radius_key"),
    ("wl{}_radius_port", safe_int),
    ("wl{}_ssid"),
    ("wl{}_wpa_gtk_rekey"),
    ("wl{}_wpa_psk"),
]


class AsusWLAN(IntEnum):
    """Asus WLAN state."""

    UNKNOWN = -999
    OFF = 0
    ON = 1


def _nvram_request(
    wlan: list[Wlan] | None, mapping: list[MapValueType], guest: bool = False
) -> str | None:
    """Create an NVRAM request."""

    if not wlan:
        return None

    request = []

    for interface in wlan:
        for pair in mapping:
            key, _ = safe_unpack_key(pair)
            index = list(Wlan).index(interface)
            if guest:
                request.extend(
                    [key.format(f"{index}.{gid}") for gid in range(1, 4)]
                )
            else:
                request.append(key.format(index))

    return nvram(request)


def wlan_nvram_request(wlan: list[Wlan] | None) -> str | None:
    """Create an NVRAM request for WLAN."""

    return _nvram_request(wlan, MAP_WLAN)


def gwlan_nvram_request(wlan: list[Wlan] | None) -> str | None:
    """Create an NVRAM request for GWLAN."""

    return _nvram_request(wlan, MAP_GWLAN, guest=True)


async def set_state(
    callback: Callable[..., Awaitable[bool]],
    state: AsusWLAN,
    **kwargs: Any,
) -> bool:
    """Set the parental control state."""

    # Get the arguments
    api_type, api_id = get_arguments(("api_type", "api_id"), **kwargs)

    # Check if the api_type and api_id are available
    if api_type is None or api_id is None:
        return False

    # Define the service and callback arguments for each api_type
    api_values = {
        "wlan": {
            "service": "restart_wireless",
            "callback_arguments": {
                f"wl{api_id}_radio": 1 if state == AsusWLAN.ON else 0
            },
        },
        "gwlan": {
            "service": "restart_wireless;restart_firewall",
            "callback_arguments": {
                f"wl{api_id}_bss_enabled": 1 if state == AsusWLAN.ON else 0,
                **({f"wl{api_id}_expire": 0} if state == AsusWLAN.ON else {}),
            },
        },
    }

    # Get the service and callback arguments for the given api_type
    api_value = api_values.get(api_type)
    if not api_value:
        return False

    # Call the service
    return await callback(
        api_value["service"],
        arguments=api_value["callback_arguments"],
        apply=True,
        expect_modify=kwargs.get("expect_modify", False),
    )