1 /*
2 This file is part of Kismet
3
4 Kismet is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 Kismet is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Kismet; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "config.h"
20
21 #if defined(HAVE_LIBPCAP) && defined(HAVE_LIBAIRPCAP) && defined(SYS_CYGWIN)
22
23 #include "packetsource_airpcap.h"
24
25 #include <unistd.h>
26 #include <errno.h>
27 #include <time.h>
28
29 #include "packetsourcetracker.h"
30
31 // Work around broken pcap.h on cygwin... this is a TERRIBLE THING TO DO but
32 // libwpcap on the airpcap cd seems to come with a pcap.h header for standard
33 // pcap, while the lib contains this symbol.
34 #if defined(HAVE_PCAP_GETEVENT)
35 int pcap_event(pcap_t *);
36 #endif
37
38 // Prototypes of Windows-specific pcap functions.
39 // wpcap.dll contains these functions, but they are not exported to cygwin because
40 // cygwin doesn't "officially" support the Windows extensions. These functions,
41 // however, are safe to use.
42 extern "C" PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);
43 extern "C" HANDLE pcap_getevent (pcap_t *p);
44 extern "C" int pcap_setmintocopy (pcap_t *p, int size);
45
OpenSource()46 int PacketSource_AirPcap::OpenSource() {
47 char errstr[STATUS_MAX] = "";
48 char *unconst = strdup(interface.c_str());
49
50 pd = pcap_open_live(unconst, MAX_PACKET_LEN, 1, 1000, errstr);
51
52 free(unconst);
53
54 if (strlen(errstr) > 0) {
55 _MSG(errstr, MSGFLAG_PRINTERROR);
56 return -1;
57 }
58
59 paused = 0;
60 errstr[0] = '\0';
61 num_packets = 0;
62
63 if (DatalinkType() < 0) {
64 pcap_close(pd);
65 return -1;
66 }
67
68 // Fetch the airpcap handle
69 if ((airpcap_handle = pcap_get_airpcap_handle(pd)) == NULL) {
70 _MSG("Adapter " + interface + " does not have airpcap wireless "
71 "extensions", MSGFLAG_PRINTERROR);
72 pcap_close(pd);
73 return -1;
74 }
75
76
77 // Tell the adapter to only give us packets which pass internal
78 // FCS validation. All we do is throw away frames which do not,
79 // so theres no reason to add the overhead of locally processing
80 // the checksum.
81 if (!AirpcapSetFcsValidation(airpcap_handle,
82 AIRPCAP_VT_ACCEPT_CORRECT_FRAMES)) {
83 _MSG("Airpcap adapter " + interface + " failed setting FCS "
84 "validation: " +
85 StrStrip((const char *) AirpcapGetLastError(airpcap_handle)),
86 MSGFLAG_PRINTERROR);
87 pcap_close(pd);
88 return -1;
89 }
90
91 // Add it to the Handle to FD mangler
92 fd_mangle.AddHandle(pcap_getevent(pd));
93 fd_mangle.Activate();
94
95 return 0;
96 }
97
Poll()98 int PacketSource_AirPcap::Poll() {
99 int ret;
100
101 if ((ret = PacketSource_Pcap::Poll()) == 0) {
102 fd_mangle.Reset();
103 fd_mangle.Signalread();
104 }
105
106 return ret;
107 }
108
AutotypeProbe(string in_device)109 int PacketSource_AirPcap::AutotypeProbe(string in_device) {
110 pcap_if_t *alldevs, *d;
111 char errbuf[1024];
112
113 if (in_device == "airpcap" || in_device == "airpcap_ask") {
114 type = "airpcap";
115 return 1;
116 }
117
118 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
119 _MSG("AirPcapSource failed to find pcap devices: " +
120 string(errbuf), MSGFLAG_PRINTERROR);
121 return 0;
122 }
123
124 for (d = alldevs; d != NULL; d = d->next) {
125 if (string(d->name) == in_device) {
126 type = "airpcap";
127 return 1;
128 }
129 }
130
131 return 0;
132 }
133
RegisterSources(Packetsourcetracker * tracker)134 int PacketSource_AirPcap::RegisterSources(Packetsourcetracker *tracker) {
135 tracker->RegisterPacketProto("airpcap", this, "IEEE80211b", 0);
136 tracker->RegisterPacketProto("airpcap_ask", this, "IEEE80211b", 0);
137 return 1;
138 }
139
PacketSource_AirPcap(GlobalRegistry * in_globalreg,string in_interface,vector<opt_pair> * in_opts)140 PacketSource_AirPcap::PacketSource_AirPcap(GlobalRegistry *in_globalreg,
141 string in_interface,
142 vector<opt_pair> *in_opts) :
143 PacketSource_Pcap(in_globalreg, in_interface, in_opts) {
144
145 pcap_if_t *alldevs, *d;
146 int i, intnum;
147 char errbuf[1024];
148
149 // Look for the first airpcap interface if we're just called "airpcap"
150 if (interface == "airpcap") {
151 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
152 _MSG("AirPcapSource failed to find pcap devices: " +
153 string(errbuf),
154 MSGFLAG_PRINTERROR);
155 return;
156 }
157
158 i = 0;
159 for (d = alldevs; d != NULL; d = d->next) {
160 if (string(d->name).find("airpcap") != string::npos) {
161 interface = d->name;
162 i = 1;
163 break;
164 }
165 }
166
167 if (i == 0) {
168 _MSG("AirPcapSource failed to find any device which looked like "
169 "airpcap, if you're SURE you have an airpcap device you'll "
170 "need to specify a device. NOTE: KISMET WILL ONLY WORK WITH "
171 "THE AIRPCAP DEVICES. THIS IS A SPECIFIC PIECE OF HARDWARE. "
172 "IT WILL NOT WORK WITH ANY OTHER CARDS.", MSGFLAG_PRINTERROR);
173 return;
174 }
175 }
176
177 // Go through the prompting game for 'ask' variant
178 if (type == "airpcap_ask") {
179 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
180 _MSG("AirPcapSource failed to find pcap devices: " +
181 string(errbuf),
182 MSGFLAG_PRINTERROR);
183 return;
184 }
185
186 fprintf(stdout, "Available interfaces:\n");
187 for (d = alldevs, i = 0; d != NULL; d = d->next) {
188 fprintf(stdout, "%d. %s\n", ++i, d->name);
189 if (d->description)
190 fprintf(stdout, " %s\n", d->description);
191 else
192 fprintf(stdout, " No description available\n");
193 }
194
195 if (i == 0) {
196 pcap_freealldevs(alldevs);
197 _MSG("airPcapSource failed to find any devices, are "
198 "WinPcap and AirPcap properly installed?",
199 MSGFLAG_PRINTERROR);
200 return;
201 }
202
203 while (1) {
204 fprintf(stdout, "Enter interface number (1-%d): ", i);
205 if (fscanf(stdin, "%d", &intnum) != 1) {
206 fprintf(stdout, "Invalid entry, expected a number\n");
207 continue;
208 }
209
210 if (intnum < 1 || intnum > i) {
211 fprintf(stdout, "Invalid entry, expected between 1 "
212 "and %d\n", i);
213 continue;
214 }
215
216 break;
217 }
218
219 // Iterate
220 for (d = alldevs, i = 0; i < intnum - 1; d = d->next, i++)
221 ;
222
223 interface = string(d->name);
224
225 pcap_freealldevs(alldevs);
226 }
227
228 }
229
EnableMonitor()230 int PacketSource_AirPcap::EnableMonitor() {
231 // This is handled during the open because we need a working pcap handle
232 return 1;
233 }
234
DisableMonitor()235 int PacketSource_AirPcap::DisableMonitor() {
236 return PACKSOURCE_UNMONITOR_RET_CANTUNMON;
237 }
238
FetchHardwareChannel()239 int PacketSource_AirPcap::FetchHardwareChannel() {
240 unsigned int ch;
241 if (!AirpcapGetDeviceChannel(airpcap_handle, &ch))
242 return -1;
243
244 return (int) ch;
245 }
246
FetchDescriptor()247 int PacketSource_AirPcap::FetchDescriptor() {
248 return fd_mangle.GetFd();
249 }
250
SetChannel(unsigned int in_ch)251 int PacketSource_AirPcap::SetChannel(unsigned int in_ch) {
252 if (!AirpcapSetDeviceChannel(airpcap_handle, in_ch)) {
253 _MSG("Airpcap adapter " + interface + " failed setting channel " +
254 IntToString(in_ch) + ": " +
255 StrStrip((const char *) AirpcapGetLastError(airpcap_handle)),
256 MSGFLAG_PRINTERROR);
257 return -1;
258 }
259
260 return 0;
261 }
262
FetchSupportedChannels(string in_interface)263 vector<unsigned int> PacketSource_AirPcap::FetchSupportedChannels(string in_interface) {
264 char errstr[STATUS_MAX] = "";
265 vector<unsigned int> ret;
266 unsigned int numchans;
267 AirpcapChannelInfo *channels;
268 string qint = in_interface;
269 pcap_if_t *alldevs, *d;
270 int i;
271
272 // Look for the first airpcap interface if we're just called "airpcap"
273 if (in_interface == "airpcap") {
274 if (pcap_findalldevs(&alldevs, errstr) == -1) {
275 return ret;
276 }
277
278 i = 0;
279 for (d = alldevs; d != NULL; d = d->next) {
280 if (string(d->name).find("airpcap") != string::npos) {
281 qint = d->name;
282 i = 1;
283 break;
284 }
285 }
286
287 if (i == 0) {
288 return ret;
289 }
290 }
291
292 /* We have to open the device in pcap to get the airpcap handle to
293 * get the channel list. */
294 pd = pcap_open_live((char *) qint.c_str(), MAX_PACKET_LEN,
295 1, 1000, errstr);
296
297 if (strlen(errstr) > 0) {
298 _MSG(errstr, MSGFLAG_PRINTERROR);
299 return ret;
300 }
301
302 // Fetch the airpcap handle
303 if ((airpcap_handle = pcap_get_airpcap_handle(pd)) == NULL) {
304 pcap_close(pd);
305 return ret;
306 }
307
308 if (AirpcapGetDeviceSupportedChannels(airpcap_handle, &channels,
309 &numchans) == 0) {
310 pcap_close(pd);
311 return ret;
312 }
313
314 for (unsigned int x = 0, i = 0; x < numchans; x++) {
315 if (channels[x].Frequency == i)
316 continue;
317 i = channels[x].Frequency;
318 ret.push_back(FreqToChan(channels[x].Frequency));
319 }
320
321 pcap_close(pd);
322 return ret;
323 }
324
325 #endif
326
327