summaryrefslogtreecommitdiff
path: root/python/examples/wiphy.py
blob: 572e95a00d105d848f91c5b575de137ad617551e (plain)
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
from __future__ import print_function
import netlink.capi as nl
import netlink.genl.capi as genl
import nl80211
import sys
import traceback


class test_class:
    def __init__(self):
        self.done = 1


def freq_to_ch(freq):
    if freq == 2484:
        return 14

    if freq < 2484:
        return (freq - 2407) / 5

    # FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2)
    if freq < 45000:
        return freq / 5 - 1000

    if freq >= 58320 and freq <= 64800:
        return (freq - 56160) / 2160

    return 0


def handle_freq(attr, pol):
    e, fattr = nl.py_nla_parse_nested(nl80211.NL80211_FREQUENCY_ATTR_MAX, attr, pol)
    if nl80211.NL80211_FREQUENCY_ATTR_FREQ in fattr:
        freq = nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_FREQ])
        sys.stdout.write("\t\tfreq %d MHz [%d]" % (freq, freq_to_ch(freq)))
    if nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER in fattr and not (
        nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr
    ):
        sys.stdout.write(
            " (%.1f dBm)"
            % (
                0.01
                * nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER])
            )
        )
    if nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr:
        sys.stdout.write(" (disabled)")
    sys.stdout.write("\n")


def handle_band(attr, fpol):
    e, battr = nl.py_nla_parse_nested(nl80211.NL80211_BAND_ATTR_MAX, attr, None)
    print("\tband %d:" % nl.nla_type(attr))
    if nl80211.NL80211_BAND_ATTR_FREQS in battr:
        for fattr in nl.nla_get_nested(battr[nl80211.NL80211_BAND_ATTR_FREQS]):
            handle_freq(fattr, fpol)


def cipher_name(suite):
    suite_val = "%02x%02x%02x%02x" % tuple(reversed(suite))
    if suite_val == "000fac01":
        return "WEP40 (00-0f-ac:1)"
    elif suite_val == "000fac05":
        return "WEP104 (00-0f-ac:5)"
    elif suite_val == "000fac02":
        return "TKIP (00-0f-ac:2)"
    elif suite_val == "000fac04":
        return "CCMP (00-0f-ac:4)"
    elif suite_val == "000fac06":
        return "CMAC (00-0f-ac:6)"
    elif suite_val == "000fac08":
        return "GCMP (00-0f-ac:8)"
    elif suite_val == "00147201":
        return "WPI-SMS4 (00-14-72:1)"
    else:
        return suite_val


def msg_handler(m, a):
    try:
        e, attr = genl.py_genlmsg_parse(
            nl.nlmsg_hdr(m), 0, nl80211.NL80211_ATTR_MAX, None
        )
        if nl80211.NL80211_ATTR_WIPHY_NAME in attr:
            print("wiphy %s" % nl.nla_get_string(attr[nl80211.NL80211_ATTR_WIPHY_NAME]))
        if nl80211.NL80211_ATTR_WIPHY_BANDS in attr:
            fpol = nl.nla_policy_array(nl80211.NL80211_FREQUENCY_ATTR_MAX + 1)
            fpol[nl80211.NL80211_FREQUENCY_ATTR_FREQ].type = nl.NLA_U32
            fpol[nl80211.NL80211_FREQUENCY_ATTR_DISABLED].type = nl.NLA_FLAG
            fpol[nl80211.NL80211_FREQUENCY_ATTR_PASSIVE_SCAN].type = nl.NLA_FLAG
            fpol[nl80211.NL80211_FREQUENCY_ATTR_NO_IBSS].type = nl.NLA_FLAG
            fpol[nl80211.NL80211_FREQUENCY_ATTR_RADAR].type = nl.NLA_FLAG
            fpol[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = nl.NLA_U32

            nattrs = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_WIPHY_BANDS])
            for nattr in nattrs:
                handle_band(nattr, fpol)
        if nl80211.NL80211_ATTR_CIPHER_SUITES in attr:
            ciphers = nl.nla_data(attr[nl80211.NL80211_ATTR_CIPHER_SUITES])
            num = len(ciphers) / 4
            if num > 0:
                print("\tSupported Ciphers:")
                for i in range(0, num, 4):
                    print("\t\t* %s" % cipher_name(ciphers[i : i + 4]))
        if nl80211.NL80211_ATTR_SUPPORTED_IFTYPES in attr:
            print("\tSupported interface modes:")
            ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SUPPORTED_IFTYPES])
            for nl_mode in ifattr:
                print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)])
        if nl80211.NL80211_ATTR_SOFTWARE_IFTYPES in attr:
            print("\tsoftware interface modes (can always be added):")
            ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SOFTWARE_IFTYPES])
            for nl_mode in ifattr:
                print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)])
        return nl.NL_SKIP
    except Exception:
        (t, v, tb) = sys.exc_info()
        print(v.message)
        traceback.print_tb(tb)


def error_handler(err, a):
    a.done = err.error
    return nl.NL_STOP


def finish_handler(m, a):
    return nl.NL_SKIP


def ack_handler(m, a):
    a.done = 0
    return nl.NL_STOP


try:
    cbd = test_class()
    tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT)
    rx_cb = nl.nl_cb_clone(tx_cb)
    s = nl.nl_socket_alloc_cb(tx_cb)
    nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd)
    nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd)
    nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd)
    nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd)

    genl.genl_connect(s)
    family = genl.genl_ctrl_resolve(s, "nl80211")
    m = nl.nlmsg_alloc()
    genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_WIPHY, 0)
    nl.nla_put_u32(m, nl80211.NL80211_ATTR_WIPHY, 7)

    err = nl.nl_send_auto_complete(s, m)
    if err < 0:
        nl.nlmsg_free(m)

    while cbd.done > 0 and not err < 0:
        err = nl.nl_recvmsgs(s, rx_cb)
except Exception:
    (t, v, tb) = sys.exc_info()
    print(v.message)
    traceback.print_tb(tb)