]>
Commit | Line | Data |
---|---|---|
a149fcc7 JM |
1 | /* |
2 | * wlantest - IEEE 802.11 protocol monitoring and testing tool | |
219fd441 | 3 | * Copyright (c) 2010-2011, Jouni Malinen <j@w1.fi> |
a149fcc7 | 4 | * |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
a149fcc7 JM |
7 | */ |
8 | ||
9 | #include "utils/includes.h" | |
10 | ||
11 | #include "utils/common.h" | |
12 | #include "utils/eloop.h" | |
13 | #include "wlantest.h" | |
14 | ||
15 | ||
16 | extern int wpa_debug_level; | |
53650bca | 17 | extern int wpa_debug_show_keys; |
a149fcc7 JM |
18 | |
19 | ||
20 | static void wlantest_terminate(int sig, void *signal_ctx) | |
21 | { | |
22 | eloop_terminate(); | |
23 | } | |
24 | ||
25 | ||
26 | static void usage(void) | |
27 | { | |
644fb8c8 | 28 | printf("wlantest [-cddhqq] [-i<ifname>] [-r<pcap file>] " |
3215df77 | 29 | "[-p<passphrase>]\n" |
d06df64d | 30 | " [-I<wired ifname>] [-R<wired pcap file>] " |
64f45d07 | 31 | "[-P<RADIUS shared secret>]\n" |
219fd441 | 32 | " [-w<write pcap file>] [-f<MSK/PMK file>]\n"); |
53650bca JM |
33 | } |
34 | ||
35 | ||
36 | static void passphrase_deinit(struct wlantest_passphrase *p) | |
37 | { | |
38 | dl_list_del(&p->list); | |
39 | os_free(p); | |
a149fcc7 JM |
40 | } |
41 | ||
42 | ||
d06df64d JM |
43 | static void secret_deinit(struct wlantest_radius_secret *r) |
44 | { | |
45 | dl_list_del(&r->list); | |
46 | os_free(r); | |
47 | } | |
48 | ||
49 | ||
d84d3893 JM |
50 | static void wlantest_init(struct wlantest *wt) |
51 | { | |
644fb8c8 | 52 | int i; |
d84d3893 JM |
53 | os_memset(wt, 0, sizeof(*wt)); |
54 | wt->monitor_sock = -1; | |
644fb8c8 JM |
55 | wt->ctrl_sock = -1; |
56 | for (i = 0; i < MAX_CTRL_CONNECTIONS; i++) | |
57 | wt->ctrl_socks[i] = -1; | |
53650bca | 58 | dl_list_init(&wt->passphrase); |
d84d3893 | 59 | dl_list_init(&wt->bss); |
d06df64d JM |
60 | dl_list_init(&wt->secret); |
61 | dl_list_init(&wt->radius); | |
62 | dl_list_init(&wt->pmk); | |
2e479416 | 63 | dl_list_init(&wt->wep); |
d06df64d JM |
64 | } |
65 | ||
66 | ||
67 | void radius_deinit(struct wlantest_radius *r) | |
68 | { | |
69 | dl_list_del(&r->list); | |
70 | os_free(r); | |
d84d3893 JM |
71 | } |
72 | ||
73 | ||
74 | static void wlantest_deinit(struct wlantest *wt) | |
75 | { | |
53650bca | 76 | struct wlantest_passphrase *p, *pn; |
d06df64d JM |
77 | struct wlantest_radius_secret *s, *sn; |
78 | struct wlantest_radius *r, *rn; | |
79 | struct wlantest_pmk *pmk, *np; | |
2e479416 | 80 | struct wlantest_wep *wep, *nw; |
d06df64d | 81 | |
644fb8c8 JM |
82 | if (wt->ctrl_sock >= 0) |
83 | ctrl_deinit(wt); | |
d84d3893 JM |
84 | if (wt->monitor_sock >= 0) |
85 | monitor_deinit(wt); | |
d356bd63 | 86 | bss_flush(wt); |
53650bca JM |
87 | dl_list_for_each_safe(p, pn, &wt->passphrase, |
88 | struct wlantest_passphrase, list) | |
89 | passphrase_deinit(p); | |
d06df64d JM |
90 | dl_list_for_each_safe(s, sn, &wt->secret, |
91 | struct wlantest_radius_secret, list) | |
92 | secret_deinit(s); | |
93 | dl_list_for_each_safe(r, rn, &wt->radius, struct wlantest_radius, list) | |
94 | radius_deinit(r); | |
95 | dl_list_for_each_safe(pmk, np, &wt->pmk, struct wlantest_pmk, list) | |
96 | pmk_deinit(pmk); | |
2e479416 JM |
97 | dl_list_for_each_safe(wep, nw, &wt->wep, struct wlantest_wep, list) |
98 | os_free(wep); | |
64f45d07 | 99 | write_pcap_deinit(wt); |
53650bca JM |
100 | } |
101 | ||
102 | ||
103 | static void add_passphrase(struct wlantest *wt, const char *passphrase) | |
104 | { | |
105 | struct wlantest_passphrase *p; | |
106 | size_t len = os_strlen(passphrase); | |
107 | ||
108 | if (len < 8 || len > 63) | |
109 | return; | |
110 | p = os_zalloc(sizeof(*p)); | |
111 | if (p == NULL) | |
112 | return; | |
113 | os_memcpy(p->passphrase, passphrase, len); | |
114 | dl_list_add(&wt->passphrase, &p->list); | |
d84d3893 JM |
115 | } |
116 | ||
117 | ||
d06df64d JM |
118 | static void add_secret(struct wlantest *wt, const char *secret) |
119 | { | |
120 | struct wlantest_radius_secret *s; | |
121 | size_t len = os_strlen(secret); | |
122 | ||
123 | if (len >= MAX_RADIUS_SECRET_LEN) | |
124 | return; | |
125 | s = os_zalloc(sizeof(*s)); | |
126 | if (s == NULL) | |
127 | return; | |
128 | os_memcpy(s->secret, secret, len); | |
129 | dl_list_add(&wt->secret, &s->list); | |
130 | } | |
131 | ||
132 | ||
219fd441 JM |
133 | static int add_pmk_file(struct wlantest *wt, const char *pmk_file) |
134 | { | |
135 | FILE *f; | |
136 | u8 pmk[32]; | |
137 | char buf[300], *pos; | |
138 | struct wlantest_pmk *p; | |
139 | ||
140 | f = fopen(pmk_file, "r"); | |
141 | if (f == NULL) { | |
142 | wpa_printf(MSG_ERROR, "Could not open '%s'", pmk_file); | |
143 | return -1; | |
144 | } | |
145 | ||
146 | while (fgets(buf, sizeof(buf), f)) { | |
147 | pos = buf; | |
148 | while (*pos && *pos != '\r' && *pos != '\n') | |
149 | pos++; | |
150 | *pos = '\0'; | |
151 | if (pos - buf < 2 * 32) | |
152 | continue; | |
153 | if (hexstr2bin(buf, pmk, 32) < 0) | |
154 | continue; | |
155 | p = os_zalloc(sizeof(*p)); | |
156 | if (p == NULL) | |
157 | break; | |
158 | os_memcpy(p->pmk, pmk, 32); | |
159 | dl_list_add(&wt->pmk, &p->list); | |
160 | wpa_hexdump(MSG_DEBUG, "Added PMK from file", pmk, 32); | |
161 | } | |
162 | ||
163 | fclose(f); | |
164 | return 0; | |
165 | } | |
166 | ||
167 | ||
9a994178 | 168 | int add_wep(struct wlantest *wt, const char *key) |
2e479416 JM |
169 | { |
170 | struct wlantest_wep *w; | |
171 | size_t len = os_strlen(key); | |
172 | ||
173 | if (len != 2 * 5 && len != 2 * 13) { | |
174 | wpa_printf(MSG_INFO, "Invalid WEP key '%s'", key); | |
9a994178 | 175 | return -1; |
2e479416 JM |
176 | } |
177 | w = os_zalloc(sizeof(*w)); | |
178 | if (w == NULL) | |
9a994178 | 179 | return -1; |
2e479416 JM |
180 | if (hexstr2bin(key, w->key, len / 2) < 0) { |
181 | os_free(w); | |
182 | wpa_printf(MSG_INFO, "Invalid WEP key '%s'", key); | |
9a994178 | 183 | return -1; |
2e479416 JM |
184 | } |
185 | w->key_len = len / 2; | |
186 | dl_list_add(&wt->wep, &w->list); | |
9a994178 | 187 | return 0; |
2e479416 JM |
188 | } |
189 | ||
190 | ||
a149fcc7 JM |
191 | int main(int argc, char *argv[]) |
192 | { | |
193 | int c; | |
194 | const char *read_file = NULL; | |
3215df77 | 195 | const char *read_wired_file = NULL; |
64f45d07 | 196 | const char *write_file = NULL; |
a149fcc7 | 197 | const char *ifname = NULL; |
3215df77 | 198 | const char *ifname_wired = NULL; |
a149fcc7 | 199 | struct wlantest wt; |
644fb8c8 | 200 | int ctrl_iface = 0; |
a149fcc7 JM |
201 | |
202 | wpa_debug_level = MSG_INFO; | |
53650bca | 203 | wpa_debug_show_keys = 1; |
a149fcc7 JM |
204 | |
205 | if (os_program_init()) | |
206 | return -1; | |
207 | ||
d84d3893 | 208 | wlantest_init(&wt); |
a149fcc7 JM |
209 | |
210 | for (;;) { | |
219fd441 | 211 | c = getopt(argc, argv, "cdf:hi:I:p:P:qr:R:w:W:"); |
a149fcc7 JM |
212 | if (c < 0) |
213 | break; | |
214 | switch (c) { | |
644fb8c8 JM |
215 | case 'c': |
216 | ctrl_iface = 1; | |
217 | break; | |
a149fcc7 JM |
218 | case 'd': |
219 | if (wpa_debug_level > 0) | |
220 | wpa_debug_level--; | |
221 | break; | |
219fd441 JM |
222 | case 'f': |
223 | if (add_pmk_file(&wt, optarg) < 0) | |
224 | return -1; | |
225 | break; | |
a149fcc7 JM |
226 | case 'h': |
227 | usage(); | |
228 | return 0; | |
229 | case 'i': | |
230 | ifname = optarg; | |
231 | break; | |
3215df77 JM |
232 | case 'I': |
233 | ifname_wired = optarg; | |
234 | break; | |
53650bca JM |
235 | case 'p': |
236 | add_passphrase(&wt, optarg); | |
237 | break; | |
d06df64d JM |
238 | case 'P': |
239 | add_secret(&wt, optarg); | |
240 | break; | |
a149fcc7 JM |
241 | case 'q': |
242 | wpa_debug_level++; | |
243 | break; | |
244 | case 'r': | |
245 | read_file = optarg; | |
246 | break; | |
3215df77 JM |
247 | case 'R': |
248 | read_wired_file = optarg; | |
249 | break; | |
64f45d07 JM |
250 | case 'w': |
251 | write_file = optarg; | |
252 | break; | |
2e479416 | 253 | case 'W': |
9a994178 JM |
254 | if (add_wep(&wt, optarg) < 0) |
255 | return -1; | |
2e479416 | 256 | break; |
a149fcc7 JM |
257 | default: |
258 | usage(); | |
259 | return -1; | |
260 | } | |
261 | } | |
262 | ||
3215df77 JM |
263 | if (ifname == NULL && ifname_wired == NULL && |
264 | read_file == NULL && read_wired_file == NULL) { | |
a149fcc7 JM |
265 | usage(); |
266 | return 0; | |
267 | } | |
268 | ||
269 | if (eloop_init()) | |
270 | return -1; | |
271 | ||
64f45d07 JM |
272 | if (write_file && write_pcap_init(&wt, write_file) < 0) |
273 | return -1; | |
274 | ||
3215df77 JM |
275 | if (read_wired_file && read_wired_cap_file(&wt, read_wired_file) < 0) |
276 | return -1; | |
277 | ||
a149fcc7 JM |
278 | if (read_file && read_cap_file(&wt, read_file) < 0) |
279 | return -1; | |
280 | ||
281 | if (ifname && monitor_init(&wt, ifname) < 0) | |
282 | return -1; | |
283 | ||
3215df77 JM |
284 | if (ifname_wired && monitor_init_wired(&wt, ifname_wired) < 0) |
285 | return -1; | |
286 | ||
644fb8c8 JM |
287 | if (ctrl_iface && ctrl_init(&wt) < 0) |
288 | return -1; | |
289 | ||
a149fcc7 JM |
290 | eloop_register_signal_terminate(wlantest_terminate, &wt); |
291 | ||
292 | eloop_run(); | |
293 | ||
294 | wpa_printf(MSG_INFO, "Processed: rx_mgmt=%u rx_ctrl=%u rx_data=%u " | |
295 | "fcs_error=%u", | |
296 | wt.rx_mgmt, wt.rx_ctrl, wt.rx_data, wt.fcs_error); | |
297 | ||
d84d3893 | 298 | wlantest_deinit(&wt); |
a149fcc7 JM |
299 | |
300 | eloop_destroy(); | |
301 | os_program_deinit(); | |
302 | ||
303 | return 0; | |
304 | } |