lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | import netlink.capi as nl |
| 2 | import netlink.genl.capi as genl |
| 3 | import nl80211 |
| 4 | import sys |
| 5 | import traceback |
| 6 | |
| 7 | class test_class: |
| 8 | def __init__(self): |
| 9 | self.done = 1; |
| 10 | |
| 11 | def freq_to_ch(freq): |
| 12 | if freq == 2484: |
| 13 | return 14; |
| 14 | |
| 15 | if freq < 2484: |
| 16 | return (freq - 2407) / 5; |
| 17 | |
| 18 | # FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2) |
| 19 | if freq < 45000: |
| 20 | return freq/5 - 1000; |
| 21 | |
| 22 | if freq >= 58320 and freq <= 64800: |
| 23 | return (freq - 56160) / 2160; |
| 24 | |
| 25 | return 0; |
| 26 | |
| 27 | def handle_freq(attr, pol): |
| 28 | e, fattr = nl.py_nla_parse_nested(nl80211.NL80211_FREQUENCY_ATTR_MAX, attr, pol) |
| 29 | if nl80211.NL80211_FREQUENCY_ATTR_FREQ in fattr: |
| 30 | freq = nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_FREQ]) |
| 31 | sys.stdout.write("\t\tfreq %d MHz [%d]" % (freq, freq_to_ch(freq))) |
| 32 | if nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER in fattr and not (nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr): |
| 33 | sys.stdout.write(" (%.1f dBm)" % (0.01 * nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER]))) |
| 34 | if nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr: |
| 35 | sys.stdout.write(" (disabled)") |
| 36 | sys.stdout.write("\n") |
| 37 | |
| 38 | def handle_band(attr, fpol): |
| 39 | e, battr = nl.py_nla_parse_nested(nl80211.NL80211_BAND_ATTR_MAX, attr, None) |
| 40 | print("\tband %d:" % nl.nla_type(attr)) |
| 41 | if nl80211.NL80211_BAND_ATTR_FREQS in battr: |
| 42 | for fattr in nl.nla_get_nested(battr[nl80211.NL80211_BAND_ATTR_FREQS]): |
| 43 | handle_freq(fattr, fpol) |
| 44 | |
| 45 | def cipher_name(suite): |
| 46 | suite_val = '%02x%02x%02x%02x' % tuple(reversed(suite)) |
| 47 | if suite_val == '000fac01': |
| 48 | return "WEP40 (00-0f-ac:1)" |
| 49 | elif suite_val == '000fac05': |
| 50 | return "WEP104 (00-0f-ac:5)" |
| 51 | elif suite_val == '000fac02': |
| 52 | return "TKIP (00-0f-ac:2)" |
| 53 | elif suite_val == '000fac04': |
| 54 | return "CCMP (00-0f-ac:4)" |
| 55 | elif suite_val == '000fac06': |
| 56 | return "CMAC (00-0f-ac:6)" |
| 57 | elif suite_val == '000fac08': |
| 58 | return "GCMP (00-0f-ac:8)" |
| 59 | elif suite_val == '00147201': |
| 60 | return "WPI-SMS4 (00-14-72:1)" |
| 61 | else: |
| 62 | return suite_val |
| 63 | |
| 64 | def msg_handler(m, a): |
| 65 | try: |
| 66 | e, attr = genl.py_genlmsg_parse(nl.nlmsg_hdr(m), 0, |
| 67 | nl80211.NL80211_ATTR_MAX, None) |
| 68 | if nl80211.NL80211_ATTR_WIPHY_NAME in attr: |
| 69 | print('wiphy %s' % nl.nla_get_string(attr[nl80211.NL80211_ATTR_WIPHY_NAME])) |
| 70 | if nl80211.NL80211_ATTR_WIPHY_BANDS in attr: |
| 71 | fpol = nl.nla_policy_array(nl80211.NL80211_FREQUENCY_ATTR_MAX + 1) |
| 72 | fpol[nl80211.NL80211_FREQUENCY_ATTR_FREQ].type = nl.NLA_U32 |
| 73 | fpol[nl80211.NL80211_FREQUENCY_ATTR_DISABLED].type = nl.NLA_FLAG |
| 74 | fpol[nl80211.NL80211_FREQUENCY_ATTR_PASSIVE_SCAN].type = nl.NLA_FLAG |
| 75 | fpol[nl80211.NL80211_FREQUENCY_ATTR_NO_IBSS].type = nl.NLA_FLAG |
| 76 | fpol[nl80211.NL80211_FREQUENCY_ATTR_RADAR].type = nl.NLA_FLAG |
| 77 | fpol[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = nl.NLA_U32 |
| 78 | |
| 79 | nattrs = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_WIPHY_BANDS]) |
| 80 | for nattr in nattrs: |
| 81 | handle_band(nattr, fpol) |
| 82 | if nl80211.NL80211_ATTR_CIPHER_SUITES in attr: |
| 83 | ciphers = nl.nla_data(attr[nl80211.NL80211_ATTR_CIPHER_SUITES]) |
| 84 | num = len(ciphers) / 4 |
| 85 | if num > 0: |
| 86 | print("\tSupported Ciphers:"); |
| 87 | for i in range(0, num, 4): |
| 88 | print("\t\t* %s" % cipher_name(ciphers[i:i+4])) |
| 89 | if nl80211.NL80211_ATTR_SUPPORTED_IFTYPES in attr: |
| 90 | print("\tSupported interface modes:") |
| 91 | ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SUPPORTED_IFTYPES]) |
| 92 | for nl_mode in ifattr: |
| 93 | print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)]) |
| 94 | if nl80211.NL80211_ATTR_SOFTWARE_IFTYPES in attr: |
| 95 | print("\tsoftware interface modes (can always be added):") |
| 96 | ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SOFTWARE_IFTYPES]) |
| 97 | for nl_mode in ifattr: |
| 98 | print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)]) |
| 99 | return nl.NL_SKIP |
| 100 | except Exception as e: |
| 101 | (t,v,tb) = sys.exc_info() |
| 102 | print v.message |
| 103 | traceback.print_tb(tb) |
| 104 | |
| 105 | def error_handler(err, a): |
| 106 | a.done = err.error |
| 107 | return nl.NL_STOP |
| 108 | |
| 109 | def finish_handler(m, a): |
| 110 | return nl.NL_SKIP |
| 111 | |
| 112 | def ack_handler(m, a): |
| 113 | a.done = 0 |
| 114 | return nl.NL_STOP |
| 115 | |
| 116 | try: |
| 117 | cbd = test_class() |
| 118 | tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT) |
| 119 | rx_cb = nl.nl_cb_clone(tx_cb) |
| 120 | s = nl.nl_socket_alloc_cb(tx_cb) |
| 121 | nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd); |
| 122 | nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd); |
| 123 | nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd); |
| 124 | nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd); |
| 125 | |
| 126 | genl.genl_connect(s) |
| 127 | family = genl.genl_ctrl_resolve(s, 'nl80211') |
| 128 | m = nl.nlmsg_alloc() |
| 129 | genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_WIPHY, 0) |
| 130 | nl.nla_put_u32(m, nl80211.NL80211_ATTR_WIPHY, 7) |
| 131 | |
| 132 | err = nl.nl_send_auto_complete(s, m); |
| 133 | if err < 0: |
| 134 | nl.nlmsg_free(msg) |
| 135 | |
| 136 | while cbd.done > 0 and not err < 0: |
| 137 | err = nl.nl_recvmsgs(s, rx_cb) |
| 138 | except Exception as e: |
| 139 | (t, v, tb) = sys.exc_info() |
| 140 | print v.message |
| 141 | traceback.print_tb(tb) |