scan.c revision 97ebbaf55e8729c28513d8a73f3e65e8d759ff80
1#include <net/if.h> 2#include <errno.h> 3#include <string.h> 4#include <ctype.h> 5 6#include <netlink/genl/genl.h> 7#include <netlink/genl/family.h> 8#include <netlink/genl/ctrl.h> 9#include <netlink/msg.h> 10#include <netlink/attr.h> 11 12#include "nl80211.h" 13#include "iw.h" 14 15static int handle_scan(struct nl_cb *cb, 16 struct nl_msg *msg, 17 int argc, char **argv) 18{ 19 struct nl_msg *ssids = NULL; 20 int err = -ENOBUFS; 21 22 ssids = nlmsg_alloc(); 23 if (!ssids) 24 return -ENOMEM; 25 NLA_PUT(ssids, 1, 0, ""); 26 nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); 27 28 err = 0; 29 nla_put_failure: 30 nlmsg_free(ssids); 31 return err; 32} 33COMMAND(scan, trigger, NULL, 34 NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan); 35 36typedef void (*printfn)(unsigned char type, unsigned char len, unsigned char *data); 37 38static void print_ssid(unsigned char type, unsigned char len, unsigned char *data) 39{ 40 int i; 41 printf("\tSSID: "); 42 for (i=0; i<len; i++) { 43 if (isprint(data[i])) 44 printf("%c", data[i]); 45 else 46 printf("\\x%.2x", data[i]); 47 } 48 printf("\n"); 49} 50 51static void print_supprates(unsigned char type, unsigned char len, unsigned char *data) 52{ 53 int i; 54 55 if (type == 1) 56 printf("\tSupported rates: "); 57 else 58 printf("\tExtended supported rates: "); 59 60 for (i=0; i<len; i++) { 61 int r = data[i] & 0x7f; 62 printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":""); 63 } 64 printf("\n"); 65} 66 67static void print_ds(unsigned char type, unsigned char len, unsigned char *data) 68{ 69 printf("\tDS Parameter set: channel %d\n", data[0]); 70} 71 72static void print_ign(unsigned char type, unsigned char len, unsigned char *data) 73{ 74 /* ignore for now, not too useful */ 75} 76 77static void print_vendor(unsigned char type, unsigned char len, unsigned char *data) 78{ 79 int i; 80 81 printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data: ", 82 data[0], data[1], data[2]); 83 for (i=3; i<len; i++) 84 printf("\\x%.2x", data[i]); 85 printf("\n"); 86} 87 88static const printfn ieprinters[] = { 89 [0] = print_ssid, 90 [1] = print_supprates, 91 [3] = print_ds, 92 [5] = print_ign, 93 [50] = print_supprates, 94 [221] = print_vendor, 95}; 96 97static void print_ies(unsigned char *ie, int ielen) 98{ 99 while (ielen >= 2 && ielen >= ie[1]) { 100 if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]]) { 101 ieprinters[ie[0]](ie[0], ie[1], ie + 2); 102 } else { 103 int i; 104 105 printf("\tUnknown IE (%d): ", ie[0]); 106 for (i=0; i<ie[1]; i++) 107 printf("\\x%.2x", ie[2+i]); 108 printf("\n"); 109 } 110 ielen -= ie[1] + 2; 111 ie += ie[1] + 2; 112 } 113} 114 115static int print_bss_handler(struct nl_msg *msg, void *arg) 116{ 117 struct nlattr *tb[NL80211_ATTR_MAX + 1]; 118 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 119 struct nlattr *bss[NL80211_BSS_MAX + 1]; 120 char mac_addr[20], dev[20]; 121 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 122 [NL80211_BSS_TSF] = { .type = NLA_U64 }, 123 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, 124 [NL80211_BSS_BSSID] = { }, 125 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, 126 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, 127 [NL80211_BSS_INFORMATION_ELEMENTS] = { }, 128 }; 129 130 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 131 genlmsg_attrlen(gnlh, 0), NULL); 132 133 if (!tb[NL80211_ATTR_BSS]) { 134 fprintf(stderr, "bss info missing!"); 135 return NL_SKIP; 136 } 137 if (nla_parse_nested(bss, NL80211_BSS_MAX, 138 tb[NL80211_ATTR_BSS], 139 bss_policy)) { 140 fprintf(stderr, "failed to parse nested attributes!"); 141 return NL_SKIP; 142 } 143 144 if (!bss[NL80211_BSS_BSSID]) 145 return NL_SKIP; 146 147 mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID])); 148 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev); 149 printf("BSS %s (on %s)\n", mac_addr, dev); 150 151 if (bss[NL80211_BSS_TSF]) 152 printf("\tTSF: %llu usec\n", 153 (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF])); 154 if (bss[NL80211_BSS_FREQUENCY]) 155 printf("\tfreq: %d\n", 156 nla_get_u32(bss[NL80211_BSS_FREQUENCY])); 157 if (bss[NL80211_BSS_BEACON_INTERVAL]) 158 printf("\tbeacon interval: %d\n", 159 nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL])); 160 if (bss[NL80211_BSS_CAPABILITY]) 161 printf("\tcapability: 0x%.4x\n", 162 nla_get_u16(bss[NL80211_BSS_CAPABILITY])); 163 if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) 164 print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), 165 nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS])); 166 167 return NL_SKIP; 168} 169 170 171 172static int handle_scan_dump(struct nl_cb *cb, 173 struct nl_msg *msg, 174 int argc, char **argv) 175{ 176 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, NULL); 177 return 0; 178} 179COMMAND(scan, dump, NULL, 180 NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump); 181