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>
15 static int handle_scan(struct nl_cb
*cb
,
17 int argc
, char **argv
)
19 struct nl_msg
*ssids
= NULL
;
22 ssids
= nlmsg_alloc();
25 NLA_PUT(ssids
, 1, 0, "");
26 nla_put_nested(msg
, NL80211_ATTR_SCAN_SSIDS
, ssids
);
33 COMMAND(scan
, trigger
, NULL
,
34 NL80211_CMD_TRIGGER_SCAN
, 0, CIB_NETDEV
, handle_scan
);
36 typedef void (*printfn
)(unsigned char type
, unsigned char len
, unsigned char *data
);
38 static void print_ssid(unsigned char type
, unsigned char len
, unsigned char *data
)
42 for (i
=0; i
<len
; i
++) {
44 printf("%c", data
[i
]);
46 printf("\\x%.2x", data
[i
]);
51 static void print_supprates(unsigned char type
, unsigned char len
, unsigned char *data
)
56 printf("\tSupported rates: ");
58 printf("\tExtended supported rates: ");
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 ? "*":"");
67 static void print_ds(unsigned char type
, unsigned char len
, unsigned char *data
)
69 printf("\tDS Parameter set: channel %d\n", data
[0]);
72 static void print_ign(unsigned char type
, unsigned char len
, unsigned char *data
)
74 /* ignore for now, not too useful */
77 static void print_vendor(unsigned char type
, unsigned char len
, unsigned char *data
)
81 printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data: ",
82 data
[0], data
[1], data
[2]);
84 printf("\\x%.2x", data
[i
]);
88 static const printfn ieprinters
[] = {
90 [1] = print_supprates
,
93 [50] = print_supprates
,
96 #define NUMPRINTERS (sizeof(ieprinters)/sizeof(ieprinters[0]))
98 static void print_ies(unsigned char *ie
, int ielen
)
100 while (ielen
>= 2 && ielen
>= ie
[1]) {
101 if (ie
[0] < NUMPRINTERS
&& ieprinters
[ie
[0]]) {
102 ieprinters
[ie
[0]](ie
[0], ie
[1], ie
+ 2);
106 printf("\tUnknown IE (%d): ", ie
[0]);
107 for (i
=0; i
<ie
[1]; i
++)
108 printf("\\x%.2x", ie
[2+i
]);
116 static int print_bss_handler(struct nl_msg
*msg
, void *arg
)
118 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
119 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
120 struct nlattr
*bss
[NL80211_BSS_MAX
+ 1];
121 char mac_addr
[20], dev
[20];
122 static struct nla_policy bss_policy
[NL80211_BSS_MAX
+ 1] = {
123 [NL80211_BSS_TSF
] = { .type
= NLA_U64
},
124 [NL80211_BSS_FREQUENCY
] = { .type
= NLA_U32
},
125 [NL80211_BSS_BSSID
] = { },
126 [NL80211_BSS_BEACON_INTERVAL
] = { .type
= NLA_U16
},
127 [NL80211_BSS_CAPABILITY
] = { .type
= NLA_U16
},
128 [NL80211_BSS_INFORMATION_ELEMENTS
] = { },
131 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
132 genlmsg_attrlen(gnlh
, 0), NULL
);
134 if (!tb
[NL80211_ATTR_BSS
]) {
135 fprintf(stderr
, "bss info missing!");
138 if (nla_parse_nested(bss
, NL80211_BSS_MAX
,
139 tb
[NL80211_ATTR_BSS
],
141 fprintf(stderr
, "failed to parse nested attributes!");
145 if (!bss
[NL80211_BSS_BSSID
])
148 mac_addr_n2a(mac_addr
, nla_data(bss
[NL80211_BSS_BSSID
]));
149 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), dev
);
150 printf("BSS %s (on %s)\n", mac_addr
, dev
);
152 if (bss
[NL80211_BSS_TSF
])
153 printf("\tTSF: %llu usec\n",
154 (unsigned long long)nla_get_u64(bss
[NL80211_BSS_TSF
]));
155 if (bss
[NL80211_BSS_FREQUENCY
])
156 printf("\tfreq: %d\n",
157 nla_get_u32(bss
[NL80211_BSS_FREQUENCY
]));
158 if (bss
[NL80211_BSS_BEACON_INTERVAL
])
159 printf("\tbeacon interval: %d\n",
160 nla_get_u16(bss
[NL80211_BSS_BEACON_INTERVAL
]));
161 if (bss
[NL80211_BSS_CAPABILITY
])
162 printf("\tcapability: 0x%.4x\n",
163 nla_get_u16(bss
[NL80211_BSS_CAPABILITY
]));
164 if (bss
[NL80211_BSS_INFORMATION_ELEMENTS
])
165 print_ies(nla_data(bss
[NL80211_BSS_INFORMATION_ELEMENTS
]),
166 nla_len(bss
[NL80211_BSS_INFORMATION_ELEMENTS
]));
173 static int handle_scan_dump(struct nl_cb
*cb
,
175 int argc
, char **argv
)
177 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_bss_handler
, NULL
);
180 COMMAND(scan
, dump
, NULL
,
181 NL80211_CMD_GET_SCAN
, NLM_F_DUMP
, CIB_NETDEV
, handle_scan_dump
);