pcap-npf.c revision 1.1 1 1.1 christos /*
2 1.1 christos * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 1.1 christos * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
4 1.1 christos * All rights reserved.
5 1.1 christos *
6 1.1 christos * Redistribution and use in source and binary forms, with or without
7 1.1 christos * modification, are permitted provided that the following conditions
8 1.1 christos * are met:
9 1.1 christos *
10 1.1 christos * 1. Redistributions of source code must retain the above copyright
11 1.1 christos * notice, this list of conditions and the following disclaimer.
12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 christos * notice, this list of conditions and the following disclaimer in the
14 1.1 christos * documentation and/or other materials provided with the distribution.
15 1.1 christos * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16 1.1 christos * nor the names of its contributors may be used to endorse or promote
17 1.1 christos * products derived from this software without specific prior written
18 1.1 christos * permission.
19 1.1 christos *
20 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 1.1 christos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 1.1 christos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 1.1 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 1.1 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 1.1 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 1.1 christos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.1 christos *
32 1.1 christos */
33 1.1 christos
34 1.1 christos #ifdef HAVE_CONFIG_H
35 1.1 christos #include <config.h>
36 1.1 christos #endif
37 1.1 christos
38 1.1 christos #include <errno.h>
39 1.1 christos #define PCAP_DONT_INCLUDE_PCAP_BPF_H
40 1.1 christos #include <Packet32.h>
41 1.1 christos #include <pcap-int.h>
42 1.1 christos #include <pcap/dlt.h>
43 1.1 christos
44 1.1 christos /* Old-school MinGW have these headers in a different place.
45 1.1 christos */
46 1.1 christos #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
47 1.1 christos #include <ddk/ntddndis.h>
48 1.1 christos #include <ddk/ndis.h>
49 1.1 christos #else
50 1.1 christos #include <ntddndis.h> /* MSVC/TDM-MinGW/MinGW64 */
51 1.1 christos #endif
52 1.1 christos
53 1.1 christos #ifdef HAVE_DAG_API
54 1.1 christos #include <dagnew.h>
55 1.1 christos #include <dagapi.h>
56 1.1 christos #endif /* HAVE_DAG_API */
57 1.1 christos
58 1.1 christos static int pcap_setfilter_npf(pcap_t *, struct bpf_program *);
59 1.1 christos static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
60 1.1 christos static int pcap_getnonblock_npf(pcap_t *);
61 1.1 christos static int pcap_setnonblock_npf(pcap_t *, int);
62 1.1 christos
63 1.1 christos /*dimension of the buffer in the pcap_t structure*/
64 1.1 christos #define WIN32_DEFAULT_USER_BUFFER_SIZE 256000
65 1.1 christos
66 1.1 christos /*dimension of the buffer in the kernel driver NPF */
67 1.1 christos #define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
68 1.1 christos
69 1.1 christos /* Equivalent to ntohs(), but a lot faster under Windows */
70 1.1 christos #define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
71 1.1 christos
72 1.1 christos /*
73 1.1 christos * Private data for capturing on WinPcap devices.
74 1.1 christos */
75 1.1 christos struct pcap_win {
76 1.1 christos ADAPTER *adapter; /* the packet32 ADAPTER for the device */
77 1.1 christos int nonblock;
78 1.1 christos int rfmon_selfstart; /* a flag tells whether the monitor mode is set by itself */
79 1.1 christos int filtering_in_kernel; /* using kernel filter */
80 1.1 christos
81 1.1 christos #ifdef HAVE_DAG_API
82 1.1 christos int dag_fcs_bits; /* Number of checksum bits from link layer */
83 1.1 christos #endif
84 1.1 christos
85 1.1 christos #ifdef ENABLE_REMOTE
86 1.1 christos int samp_npkt; /* parameter needed for sampling, with '1 out of N' method has been requested */
87 1.1 christos struct timeval samp_time; /* parameter needed for sampling, with '1 every N ms' method has been requested */
88 1.1 christos #endif
89 1.1 christos };
90 1.1 christos
91 1.1 christos /*
92 1.1 christos * Define stub versions of the monitor-mode support routines if this
93 1.1 christos * isn't Npcap. HAVE_NPCAP_PACKET_API is defined by Npcap but not
94 1.1 christos * WinPcap.
95 1.1 christos */
96 1.1 christos #ifndef HAVE_NPCAP_PACKET_API
97 1.1 christos static int
98 1.1 christos PacketIsMonitorModeSupported(PCHAR AdapterName _U_)
99 1.1 christos {
100 1.1 christos /*
101 1.1 christos * We don't support monitor mode.
102 1.1 christos */
103 1.1 christos return (0);
104 1.1 christos }
105 1.1 christos
106 1.1 christos static int
107 1.1 christos PacketSetMonitorMode(PCHAR AdapterName _U_, int mode _U_)
108 1.1 christos {
109 1.1 christos /*
110 1.1 christos * This should never be called, as PacketIsMonitorModeSupported()
111 1.1 christos * will return 0, meaning "we don't support monitor mode, so
112 1.1 christos * don't try to turn it on or off".
113 1.1 christos */
114 1.1 christos return (0);
115 1.1 christos }
116 1.1 christos
117 1.1 christos static int
118 1.1 christos PacketGetMonitorMode(PCHAR AdapterName _U_)
119 1.1 christos {
120 1.1 christos /*
121 1.1 christos * This should fail, so that pcap_activate_npf() returns
122 1.1 christos * PCAP_ERROR_RFMON_NOTSUP if our caller requested monitor
123 1.1 christos * mode.
124 1.1 christos */
125 1.1 christos return (-1);
126 1.1 christos }
127 1.1 christos #endif
128 1.1 christos
129 1.1 christos /*
130 1.1 christos * Sigh. PacketRequest() will have made a DeviceIoControl()
131 1.1 christos * call to the NPF driver to perform the OID request, with a
132 1.1 christos * BIOCQUERYOID ioctl. The kernel code should get back one
133 1.1 christos * of NDIS_STATUS_INVALID_OID, NDIS_STATUS_NOT_SUPPORTED,
134 1.1 christos * or NDIS_STATUS_NOT_RECOGNIZED if the OID request isn't
135 1.1 christos * supported by the OS or the driver, but that doesn't seem
136 1.1 christos * to make it to the caller of PacketRequest() in a
137 1.1 christos * reliable fashion.
138 1.1 christos */
139 1.1 christos #define NDIS_STATUS_INVALID_OID 0xc0010017
140 1.1 christos #define NDIS_STATUS_NOT_SUPPORTED 0xc00000bb /* STATUS_NOT_SUPPORTED */
141 1.1 christos #define NDIS_STATUS_NOT_RECOGNIZED 0x00010001
142 1.1 christos
143 1.1 christos static int
144 1.1 christos oid_get_request(ADAPTER *adapter, bpf_u_int32 oid, void *data, size_t *lenp,
145 1.1 christos char *errbuf)
146 1.1 christos {
147 1.1 christos PACKET_OID_DATA *oid_data_arg;
148 1.1 christos
149 1.1 christos /*
150 1.1 christos * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
151 1.1 christos * It should be big enough to hold "*lenp" bytes of data; it
152 1.1 christos * will actually be slightly larger, as PACKET_OID_DATA has a
153 1.1 christos * 1-byte data array at the end, standing in for the variable-length
154 1.1 christos * data that's actually there.
155 1.1 christos */
156 1.1 christos oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
157 1.1 christos if (oid_data_arg == NULL) {
158 1.1 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
159 1.1 christos "Couldn't allocate argument buffer for PacketRequest");
160 1.1 christos return (PCAP_ERROR);
161 1.1 christos }
162 1.1 christos
163 1.1 christos /*
164 1.1 christos * No need to copy the data - we're doing a fetch.
165 1.1 christos */
166 1.1 christos oid_data_arg->Oid = oid;
167 1.1 christos oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
168 1.1 christos if (!PacketRequest(adapter, FALSE, oid_data_arg)) {
169 1.1 christos char errmsgbuf[PCAP_ERRBUF_SIZE+1];
170 1.1 christos
171 1.1 christos pcap_win32_err_to_str(GetLastError(), errmsgbuf);
172 1.1 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
173 1.1 christos "Error calling PacketRequest: %s", errmsgbuf);
174 1.1 christos free(oid_data_arg);
175 1.1 christos return (-1);
176 1.1 christos }
177 1.1 christos
178 1.1 christos /*
179 1.1 christos * Get the length actually supplied.
180 1.1 christos */
181 1.1 christos *lenp = oid_data_arg->Length;
182 1.1 christos
183 1.1 christos /*
184 1.1 christos * Copy back the data we fetched.
185 1.1 christos */
186 1.1 christos memcpy(data, oid_data_arg->Data, *lenp);
187 1.1 christos free(oid_data_arg);
188 1.1 christos return (0);
189 1.1 christos }
190 1.1 christos
191 1.1 christos static int
192 1.1 christos pcap_stats_npf(pcap_t *p, struct pcap_stat *ps)
193 1.1 christos {
194 1.1 christos struct pcap_win *pw = p->priv;
195 1.1 christos struct bpf_stat bstats;
196 1.1 christos char errbuf[PCAP_ERRBUF_SIZE+1];
197 1.1 christos
198 1.1 christos /*
199 1.1 christos * Try to get statistics.
200 1.1 christos *
201 1.1 christos * (Please note - "struct pcap_stat" is *not* the same as
202 1.1 christos * WinPcap's "struct bpf_stat". It might currently have the
203 1.1 christos * same layout, but let's not cheat.
204 1.1 christos *
205 1.1 christos * Note also that we don't fill in ps_capt, as we might have
206 1.1 christos * been called by code compiled against an earlier version of
207 1.1 christos * WinPcap that didn't have ps_capt, in which case filling it
208 1.1 christos * in would stomp on whatever comes after the structure passed
209 1.1 christos * to us.
210 1.1 christos */
211 1.1 christos if (!PacketGetStats(pw->adapter, &bstats)) {
212 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
213 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
214 1.1 christos "PacketGetStats error: %s", errbuf);
215 1.1 christos return (-1);
216 1.1 christos }
217 1.1 christos ps->ps_recv = bstats.bs_recv;
218 1.1 christos ps->ps_drop = bstats.bs_drop;
219 1.1 christos
220 1.1 christos /*
221 1.1 christos * XXX - PacketGetStats() doesn't fill this in, so we just
222 1.1 christos * return 0.
223 1.1 christos */
224 1.1 christos #if 0
225 1.1 christos ps->ps_ifdrop = bstats.ps_ifdrop;
226 1.1 christos #else
227 1.1 christos ps->ps_ifdrop = 0;
228 1.1 christos #endif
229 1.1 christos
230 1.1 christos return (0);
231 1.1 christos }
232 1.1 christos
233 1.1 christos /*
234 1.1 christos * Win32-only routine for getting statistics.
235 1.1 christos *
236 1.1 christos * This way is definitely safer than passing the pcap_stat * from the userland.
237 1.1 christos * In fact, there could happen than the user allocates a variable which is not
238 1.1 christos * big enough for the new structure, and the library will write in a zone
239 1.1 christos * which is not allocated to this variable.
240 1.1 christos *
241 1.1 christos * In this way, we're pretty sure we are writing on memory allocated to this
242 1.1 christos * variable.
243 1.1 christos *
244 1.1 christos * XXX - but this is the wrong way to handle statistics. Instead, we should
245 1.1 christos * have an API that returns data in a form like the Options section of a
246 1.1 christos * pcapng Interface Statistics Block:
247 1.1 christos *
248 1.1 christos * http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#rfc.section.4.6
249 1.1 christos *
250 1.1 christos * which would let us add new statistics straightforwardly and indicate which
251 1.1 christos * statistics we are and are *not* providing, rather than having to provide
252 1.1 christos * possibly-bogus values for statistics we can't provide.
253 1.1 christos */
254 1.1 christos struct pcap_stat *
255 1.1 christos pcap_stats_ex_npf(pcap_t *p, int *pcap_stat_size)
256 1.1 christos {
257 1.1 christos struct pcap_win *pw = p->priv;
258 1.1 christos struct bpf_stat bstats;
259 1.1 christos char errbuf[PCAP_ERRBUF_SIZE+1];
260 1.1 christos
261 1.1 christos *pcap_stat_size = sizeof (p->stat);
262 1.1 christos
263 1.1 christos /*
264 1.1 christos * Try to get statistics.
265 1.1 christos *
266 1.1 christos * (Please note - "struct pcap_stat" is *not* the same as
267 1.1 christos * WinPcap's "struct bpf_stat". It might currently have the
268 1.1 christos * same layout, but let's not cheat.)
269 1.1 christos */
270 1.1 christos if (!PacketGetStatsEx(pw->adapter, &bstats)) {
271 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
272 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
273 1.1 christos "PacketGetStatsEx error: %s", errbuf);
274 1.1 christos return (NULL);
275 1.1 christos }
276 1.1 christos p->stat.ps_recv = bstats.bs_recv;
277 1.1 christos p->stat.ps_drop = bstats.bs_drop;
278 1.1 christos p->stat.ps_ifdrop = bstats.ps_ifdrop;
279 1.1 christos #ifdef ENABLE_REMOTE
280 1.1 christos p->stat.ps_capt = bstats.bs_capt;
281 1.1 christos #endif
282 1.1 christos return (&p->stat);
283 1.1 christos }
284 1.1 christos
285 1.1 christos /* Set the dimension of the kernel-level capture buffer */
286 1.1 christos static int
287 1.1 christos pcap_setbuff_npf(pcap_t *p, int dim)
288 1.1 christos {
289 1.1 christos struct pcap_win *pw = p->priv;
290 1.1 christos
291 1.1 christos if(PacketSetBuff(pw->adapter,dim)==FALSE)
292 1.1 christos {
293 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
294 1.1 christos return (-1);
295 1.1 christos }
296 1.1 christos return (0);
297 1.1 christos }
298 1.1 christos
299 1.1 christos /* Set the driver working mode */
300 1.1 christos static int
301 1.1 christos pcap_setmode_npf(pcap_t *p, int mode)
302 1.1 christos {
303 1.1 christos struct pcap_win *pw = p->priv;
304 1.1 christos
305 1.1 christos if(PacketSetMode(pw->adapter,mode)==FALSE)
306 1.1 christos {
307 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
308 1.1 christos return (-1);
309 1.1 christos }
310 1.1 christos
311 1.1 christos return (0);
312 1.1 christos }
313 1.1 christos
314 1.1 christos /*set the minimum amount of data that will release a read call*/
315 1.1 christos static int
316 1.1 christos pcap_setmintocopy_npf(pcap_t *p, int size)
317 1.1 christos {
318 1.1 christos struct pcap_win *pw = p->priv;
319 1.1 christos
320 1.1 christos if(PacketSetMinToCopy(pw->adapter, size)==FALSE)
321 1.1 christos {
322 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
323 1.1 christos return (-1);
324 1.1 christos }
325 1.1 christos return (0);
326 1.1 christos }
327 1.1 christos
328 1.1 christos static HANDLE
329 1.1 christos pcap_getevent_npf(pcap_t *p)
330 1.1 christos {
331 1.1 christos struct pcap_win *pw = p->priv;
332 1.1 christos
333 1.1 christos return (PacketGetReadEvent(pw->adapter));
334 1.1 christos }
335 1.1 christos
336 1.1 christos static int
337 1.1 christos pcap_oid_get_request_npf(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
338 1.1 christos {
339 1.1 christos struct pcap_win *pw = p->priv;
340 1.1 christos
341 1.1 christos return (oid_get_request(pw->adapter, oid, data, lenp, p->errbuf));
342 1.1 christos }
343 1.1 christos
344 1.1 christos static int
345 1.1 christos pcap_oid_set_request_npf(pcap_t *p, bpf_u_int32 oid, const void *data,
346 1.1 christos size_t *lenp)
347 1.1 christos {
348 1.1 christos struct pcap_win *pw = p->priv;
349 1.1 christos PACKET_OID_DATA *oid_data_arg;
350 1.1 christos char errbuf[PCAP_ERRBUF_SIZE+1];
351 1.1 christos
352 1.1 christos /*
353 1.1 christos * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
354 1.1 christos * It should be big enough to hold "*lenp" bytes of data; it
355 1.1 christos * will actually be slightly larger, as PACKET_OID_DATA has a
356 1.1 christos * 1-byte data array at the end, standing in for the variable-length
357 1.1 christos * data that's actually there.
358 1.1 christos */
359 1.1 christos oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
360 1.1 christos if (oid_data_arg == NULL) {
361 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
362 1.1 christos "Couldn't allocate argument buffer for PacketRequest");
363 1.1 christos return (PCAP_ERROR);
364 1.1 christos }
365 1.1 christos
366 1.1 christos oid_data_arg->Oid = oid;
367 1.1 christos oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
368 1.1 christos memcpy(oid_data_arg->Data, data, *lenp);
369 1.1 christos if (!PacketRequest(pw->adapter, TRUE, oid_data_arg)) {
370 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
371 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
372 1.1 christos "Error calling PacketRequest: %s", errbuf);
373 1.1 christos free(oid_data_arg);
374 1.1 christos return (PCAP_ERROR);
375 1.1 christos }
376 1.1 christos
377 1.1 christos /*
378 1.1 christos * Get the length actually copied.
379 1.1 christos */
380 1.1 christos *lenp = oid_data_arg->Length;
381 1.1 christos
382 1.1 christos /*
383 1.1 christos * No need to copy the data - we're doing a set.
384 1.1 christos */
385 1.1 christos free(oid_data_arg);
386 1.1 christos return (0);
387 1.1 christos }
388 1.1 christos
389 1.1 christos static u_int
390 1.1 christos pcap_sendqueue_transmit_npf(pcap_t *p, pcap_send_queue *queue, int sync)
391 1.1 christos {
392 1.1 christos struct pcap_win *pw = p->priv;
393 1.1 christos u_int res;
394 1.1 christos char errbuf[PCAP_ERRBUF_SIZE+1];
395 1.1 christos
396 1.1 christos if (pw->adapter==NULL) {
397 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
398 1.1 christos "Cannot transmit a queue to an offline capture or to a TurboCap port");
399 1.1 christos return (0);
400 1.1 christos }
401 1.1 christos
402 1.1 christos res = PacketSendPackets(pw->adapter,
403 1.1 christos queue->buffer,
404 1.1 christos queue->len,
405 1.1 christos (BOOLEAN)sync);
406 1.1 christos
407 1.1 christos if(res != queue->len){
408 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
409 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
410 1.1 christos "Error opening adapter: %s", errbuf);
411 1.1 christos }
412 1.1 christos
413 1.1 christos return (res);
414 1.1 christos }
415 1.1 christos
416 1.1 christos static int
417 1.1 christos pcap_setuserbuffer_npf(pcap_t *p, int size)
418 1.1 christos {
419 1.1 christos unsigned char *new_buff;
420 1.1 christos
421 1.1 christos if (size<=0) {
422 1.1 christos /* Bogus parameter */
423 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
424 1.1 christos "Error: invalid size %d",size);
425 1.1 christos return (-1);
426 1.1 christos }
427 1.1 christos
428 1.1 christos /* Allocate the buffer */
429 1.1 christos new_buff=(unsigned char*)malloc(sizeof(char)*size);
430 1.1 christos
431 1.1 christos if (!new_buff) {
432 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
433 1.1 christos "Error: not enough memory");
434 1.1 christos return (-1);
435 1.1 christos }
436 1.1 christos
437 1.1 christos free(p->buffer);
438 1.1 christos
439 1.1 christos p->buffer=new_buff;
440 1.1 christos p->bufsize=size;
441 1.1 christos
442 1.1 christos return (0);
443 1.1 christos }
444 1.1 christos
445 1.1 christos static int
446 1.1 christos pcap_live_dump_npf(pcap_t *p, char *filename, int maxsize, int maxpacks)
447 1.1 christos {
448 1.1 christos struct pcap_win *pw = p->priv;
449 1.1 christos BOOLEAN res;
450 1.1 christos
451 1.1 christos /* Set the packet driver in dump mode */
452 1.1 christos res = PacketSetMode(pw->adapter, PACKET_MODE_DUMP);
453 1.1 christos if(res == FALSE){
454 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
455 1.1 christos "Error setting dump mode");
456 1.1 christos return (-1);
457 1.1 christos }
458 1.1 christos
459 1.1 christos /* Set the name of the dump file */
460 1.1 christos res = PacketSetDumpName(pw->adapter, filename, (int)strlen(filename));
461 1.1 christos if(res == FALSE){
462 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
463 1.1 christos "Error setting kernel dump file name");
464 1.1 christos return (-1);
465 1.1 christos }
466 1.1 christos
467 1.1 christos /* Set the limits of the dump file */
468 1.1 christos res = PacketSetDumpLimits(pw->adapter, maxsize, maxpacks);
469 1.1 christos if(res == FALSE) {
470 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
471 1.1 christos "Error setting dump limit");
472 1.1 christos return (-1);
473 1.1 christos }
474 1.1 christos
475 1.1 christos return (0);
476 1.1 christos }
477 1.1 christos
478 1.1 christos static int
479 1.1 christos pcap_live_dump_ended_npf(pcap_t *p, int sync)
480 1.1 christos {
481 1.1 christos struct pcap_win *pw = p->priv;
482 1.1 christos
483 1.1 christos return (PacketIsDumpEnded(pw->adapter, (BOOLEAN)sync));
484 1.1 christos }
485 1.1 christos
486 1.1 christos static PAirpcapHandle
487 1.1 christos pcap_get_airpcap_handle_npf(pcap_t *p)
488 1.1 christos {
489 1.1 christos #ifdef HAVE_AIRPCAP_API
490 1.1 christos struct pcap_win *pw = p->priv;
491 1.1 christos
492 1.1 christos return (PacketGetAirPcapHandle(pw->adapter));
493 1.1 christos #else
494 1.1 christos return (NULL);
495 1.1 christos #endif /* HAVE_AIRPCAP_API */
496 1.1 christos }
497 1.1 christos
498 1.1 christos static int
499 1.1 christos pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
500 1.1 christos {
501 1.1 christos PACKET Packet;
502 1.1 christos int cc;
503 1.1 christos int n = 0;
504 1.1 christos register u_char *bp, *ep;
505 1.1 christos u_char *datap;
506 1.1 christos struct pcap_win *pw = p->priv;
507 1.1 christos
508 1.1 christos cc = p->cc;
509 1.1 christos if (p->cc == 0) {
510 1.1 christos /*
511 1.1 christos * Has "pcap_breakloop()" been called?
512 1.1 christos */
513 1.1 christos if (p->break_loop) {
514 1.1 christos /*
515 1.1 christos * Yes - clear the flag that indicates that it
516 1.1 christos * has, and return PCAP_ERROR_BREAK to indicate
517 1.1 christos * that we were told to break out of the loop.
518 1.1 christos */
519 1.1 christos p->break_loop = 0;
520 1.1 christos return (PCAP_ERROR_BREAK);
521 1.1 christos }
522 1.1 christos
523 1.1 christos /*
524 1.1 christos * Capture the packets.
525 1.1 christos *
526 1.1 christos * The PACKET structure had a bunch of extra stuff for
527 1.1 christos * Windows 9x/Me, but the only interesting data in it
528 1.1 christos * in the versions of Windows that we support is just
529 1.1 christos * a copy of p->buffer, a copy of p->buflen, and the
530 1.1 christos * actual number of bytes read returned from
531 1.1 christos * PacketReceivePacket(), none of which has to be
532 1.1 christos * retained from call to call, so we just keep one on
533 1.1 christos * the stack.
534 1.1 christos */
535 1.1 christos PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
536 1.1 christos if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
537 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
538 1.1 christos return (PCAP_ERROR);
539 1.1 christos }
540 1.1 christos
541 1.1 christos cc = Packet.ulBytesReceived;
542 1.1 christos
543 1.1 christos bp = p->buffer;
544 1.1 christos }
545 1.1 christos else
546 1.1 christos bp = p->bp;
547 1.1 christos
548 1.1 christos /*
549 1.1 christos * Loop through each packet.
550 1.1 christos */
551 1.1 christos #define bhp ((struct bpf_hdr *)bp)
552 1.1 christos ep = bp + cc;
553 1.1 christos for (;;) {
554 1.1 christos register int caplen, hdrlen;
555 1.1 christos
556 1.1 christos /*
557 1.1 christos * Has "pcap_breakloop()" been called?
558 1.1 christos * If so, return immediately - if we haven't read any
559 1.1 christos * packets, clear the flag and return PCAP_ERROR_BREAK
560 1.1 christos * to indicate that we were told to break out of the loop,
561 1.1 christos * otherwise leave the flag set, so that the *next* call
562 1.1 christos * will break out of the loop without having read any
563 1.1 christos * packets, and return the number of packets we've
564 1.1 christos * processed so far.
565 1.1 christos */
566 1.1 christos if (p->break_loop) {
567 1.1 christos if (n == 0) {
568 1.1 christos p->break_loop = 0;
569 1.1 christos return (PCAP_ERROR_BREAK);
570 1.1 christos } else {
571 1.1 christos p->bp = bp;
572 1.1 christos p->cc = (int) (ep - bp);
573 1.1 christos return (n);
574 1.1 christos }
575 1.1 christos }
576 1.1 christos if (bp >= ep)
577 1.1 christos break;
578 1.1 christos
579 1.1 christos caplen = bhp->bh_caplen;
580 1.1 christos hdrlen = bhp->bh_hdrlen;
581 1.1 christos datap = bp + hdrlen;
582 1.1 christos
583 1.1 christos /*
584 1.1 christos * Short-circuit evaluation: if using BPF filter
585 1.1 christos * in kernel, no need to do it now - we already know
586 1.1 christos * the packet passed the filter.
587 1.1 christos *
588 1.1 christos * XXX - bpf_filter() should always return TRUE if
589 1.1 christos * handed a null pointer for the program, but it might
590 1.1 christos * just try to "run" the filter, so we check here.
591 1.1 christos */
592 1.1 christos if (pw->filtering_in_kernel ||
593 1.1 christos p->fcode.bf_insns == NULL ||
594 1.1 christos bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
595 1.1 christos #ifdef ENABLE_REMOTE
596 1.1 christos switch (p->rmt_samp.method) {
597 1.1 christos
598 1.1 christos case PCAP_SAMP_1_EVERY_N:
599 1.1 christos pw->samp_npkt = (pw->samp_npkt + 1) % p->rmt_samp.value;
600 1.1 christos
601 1.1 christos /* Discard all packets that are not '1 out of N' */
602 1.1 christos if (pw->samp_npkt != 0) {
603 1.1 christos bp += Packet_WORDALIGN(caplen + hdrlen);
604 1.1 christos continue;
605 1.1 christos }
606 1.1 christos break;
607 1.1 christos
608 1.1 christos case PCAP_SAMP_FIRST_AFTER_N_MS:
609 1.1 christos {
610 1.1 christos struct pcap_pkthdr *pkt_header = (struct pcap_pkthdr*) bp;
611 1.1 christos
612 1.1 christos /*
613 1.1 christos * Check if the timestamp of the arrived
614 1.1 christos * packet is smaller than our target time.
615 1.1 christos */
616 1.1 christos if (pkt_header->ts.tv_sec < pw->samp_time.tv_sec ||
617 1.1 christos (pkt_header->ts.tv_sec == pw->samp_time.tv_sec && pkt_header->ts.tv_usec < pw->samp_time.tv_usec)) {
618 1.1 christos bp += Packet_WORDALIGN(caplen + hdrlen);
619 1.1 christos continue;
620 1.1 christos }
621 1.1 christos
622 1.1 christos /*
623 1.1 christos * The arrived packet is suitable for being
624 1.1 christos * delivered to our caller, so let's update
625 1.1 christos * the target time.
626 1.1 christos */
627 1.1 christos pw->samp_time.tv_usec = pkt_header->ts.tv_usec + p->rmt_samp.value * 1000;
628 1.1 christos if (pw->samp_time.tv_usec > 1000000) {
629 1.1 christos pw->samp_time.tv_sec = pkt_header->ts.tv_sec + pw->samp_time.tv_usec / 1000000;
630 1.1 christos pw->samp_time.tv_usec = pw->samp_time.tv_usec % 1000000;
631 1.1 christos }
632 1.1 christos }
633 1.1 christos }
634 1.1 christos #endif /* ENABLE_REMOTE */
635 1.1 christos
636 1.1 christos /*
637 1.1 christos * XXX A bpf_hdr matches a pcap_pkthdr.
638 1.1 christos */
639 1.1 christos (*callback)(user, (struct pcap_pkthdr*)bp, datap);
640 1.1 christos bp += Packet_WORDALIGN(caplen + hdrlen);
641 1.1 christos if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
642 1.1 christos p->bp = bp;
643 1.1 christos p->cc = (int) (ep - bp);
644 1.1 christos return (n);
645 1.1 christos }
646 1.1 christos } else {
647 1.1 christos /*
648 1.1 christos * Skip this packet.
649 1.1 christos */
650 1.1 christos bp += Packet_WORDALIGN(caplen + hdrlen);
651 1.1 christos }
652 1.1 christos }
653 1.1 christos #undef bhp
654 1.1 christos p->cc = 0;
655 1.1 christos return (n);
656 1.1 christos }
657 1.1 christos
658 1.1 christos #ifdef HAVE_DAG_API
659 1.1 christos static int
660 1.1 christos pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
661 1.1 christos {
662 1.1 christos struct pcap_win *pw = p->priv;
663 1.1 christos PACKET Packet;
664 1.1 christos u_char *dp = NULL;
665 1.1 christos int packet_len = 0, caplen = 0;
666 1.1 christos struct pcap_pkthdr pcap_header;
667 1.1 christos u_char *endofbuf;
668 1.1 christos int n = 0;
669 1.1 christos dag_record_t *header;
670 1.1 christos unsigned erf_record_len;
671 1.1 christos ULONGLONG ts;
672 1.1 christos int cc;
673 1.1 christos unsigned swt;
674 1.1 christos unsigned dfp = pw->adapter->DagFastProcess;
675 1.1 christos
676 1.1 christos cc = p->cc;
677 1.1 christos if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
678 1.1 christos {
679 1.1 christos /*
680 1.1 christos * Get new packets from the network.
681 1.1 christos *
682 1.1 christos * The PACKET structure had a bunch of extra stuff for
683 1.1 christos * Windows 9x/Me, but the only interesting data in it
684 1.1 christos * in the versions of Windows that we support is just
685 1.1 christos * a copy of p->buffer, a copy of p->buflen, and the
686 1.1 christos * actual number of bytes read returned from
687 1.1 christos * PacketReceivePacket(), none of which has to be
688 1.1 christos * retained from call to call, so we just keep one on
689 1.1 christos * the stack.
690 1.1 christos */
691 1.1 christos PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
692 1.1 christos if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
693 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
694 1.1 christos return (-1);
695 1.1 christos }
696 1.1 christos
697 1.1 christos cc = Packet.ulBytesReceived;
698 1.1 christos if(cc == 0)
699 1.1 christos /* The timeout has expired but we no packets arrived */
700 1.1 christos return (0);
701 1.1 christos header = (dag_record_t*)pw->adapter->DagBuffer;
702 1.1 christos }
703 1.1 christos else
704 1.1 christos header = (dag_record_t*)p->bp;
705 1.1 christos
706 1.1 christos endofbuf = (char*)header + cc;
707 1.1 christos
708 1.1 christos /*
709 1.1 christos * Cycle through the packets
710 1.1 christos */
711 1.1 christos do
712 1.1 christos {
713 1.1 christos erf_record_len = SWAPS(header->rlen);
714 1.1 christos if((char*)header + erf_record_len > endofbuf)
715 1.1 christos break;
716 1.1 christos
717 1.1 christos /* Increase the number of captured packets */
718 1.1 christos p->stat.ps_recv++;
719 1.1 christos
720 1.1 christos /* Find the beginning of the packet */
721 1.1 christos dp = ((u_char *)header) + dag_record_size;
722 1.1 christos
723 1.1 christos /* Determine actual packet len */
724 1.1 christos switch(header->type)
725 1.1 christos {
726 1.1 christos case TYPE_ATM:
727 1.1 christos packet_len = ATM_SNAPLEN;
728 1.1 christos caplen = ATM_SNAPLEN;
729 1.1 christos dp += 4;
730 1.1 christos
731 1.1 christos break;
732 1.1 christos
733 1.1 christos case TYPE_ETH:
734 1.1 christos swt = SWAPS(header->wlen);
735 1.1 christos packet_len = swt - (pw->dag_fcs_bits);
736 1.1 christos caplen = erf_record_len - dag_record_size - 2;
737 1.1 christos if (caplen > packet_len)
738 1.1 christos {
739 1.1 christos caplen = packet_len;
740 1.1 christos }
741 1.1 christos dp += 2;
742 1.1 christos
743 1.1 christos break;
744 1.1 christos
745 1.1 christos case TYPE_HDLC_POS:
746 1.1 christos swt = SWAPS(header->wlen);
747 1.1 christos packet_len = swt - (pw->dag_fcs_bits);
748 1.1 christos caplen = erf_record_len - dag_record_size;
749 1.1 christos if (caplen > packet_len)
750 1.1 christos {
751 1.1 christos caplen = packet_len;
752 1.1 christos }
753 1.1 christos
754 1.1 christos break;
755 1.1 christos }
756 1.1 christos
757 1.1 christos if(caplen > p->snapshot)
758 1.1 christos caplen = p->snapshot;
759 1.1 christos
760 1.1 christos /*
761 1.1 christos * Has "pcap_breakloop()" been called?
762 1.1 christos * If so, return immediately - if we haven't read any
763 1.1 christos * packets, clear the flag and return -2 to indicate
764 1.1 christos * that we were told to break out of the loop, otherwise
765 1.1 christos * leave the flag set, so that the *next* call will break
766 1.1 christos * out of the loop without having read any packets, and
767 1.1 christos * return the number of packets we've processed so far.
768 1.1 christos */
769 1.1 christos if (p->break_loop)
770 1.1 christos {
771 1.1 christos if (n == 0)
772 1.1 christos {
773 1.1 christos p->break_loop = 0;
774 1.1 christos return (-2);
775 1.1 christos }
776 1.1 christos else
777 1.1 christos {
778 1.1 christos p->bp = (char*)header;
779 1.1 christos p->cc = endofbuf - (char*)header;
780 1.1 christos return (n);
781 1.1 christos }
782 1.1 christos }
783 1.1 christos
784 1.1 christos if(!dfp)
785 1.1 christos {
786 1.1 christos /* convert between timestamp formats */
787 1.1 christos ts = header->ts;
788 1.1 christos pcap_header.ts.tv_sec = (int)(ts >> 32);
789 1.1 christos ts = (ts & 0xffffffffi64) * 1000000;
790 1.1 christos ts += 0x80000000; /* rounding */
791 1.1 christos pcap_header.ts.tv_usec = (int)(ts >> 32);
792 1.1 christos if (pcap_header.ts.tv_usec >= 1000000) {
793 1.1 christos pcap_header.ts.tv_usec -= 1000000;
794 1.1 christos pcap_header.ts.tv_sec++;
795 1.1 christos }
796 1.1 christos }
797 1.1 christos
798 1.1 christos /* No underlaying filtering system. We need to filter on our own */
799 1.1 christos if (p->fcode.bf_insns)
800 1.1 christos {
801 1.1 christos if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
802 1.1 christos {
803 1.1 christos /* Move to next packet */
804 1.1 christos header = (dag_record_t*)((char*)header + erf_record_len);
805 1.1 christos continue;
806 1.1 christos }
807 1.1 christos }
808 1.1 christos
809 1.1 christos /* Fill the header for the user suppplied callback function */
810 1.1 christos pcap_header.caplen = caplen;
811 1.1 christos pcap_header.len = packet_len;
812 1.1 christos
813 1.1 christos /* Call the callback function */
814 1.1 christos (*callback)(user, &pcap_header, dp);
815 1.1 christos
816 1.1 christos /* Move to next packet */
817 1.1 christos header = (dag_record_t*)((char*)header + erf_record_len);
818 1.1 christos
819 1.1 christos /* Stop if the number of packets requested by user has been reached*/
820 1.1 christos if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
821 1.1 christos {
822 1.1 christos p->bp = (char*)header;
823 1.1 christos p->cc = endofbuf - (char*)header;
824 1.1 christos return (n);
825 1.1 christos }
826 1.1 christos }
827 1.1 christos while((u_char*)header < endofbuf);
828 1.1 christos
829 1.1 christos return (1);
830 1.1 christos }
831 1.1 christos #endif /* HAVE_DAG_API */
832 1.1 christos
833 1.1 christos /* Send a packet to the network */
834 1.1 christos static int
835 1.1 christos pcap_inject_npf(pcap_t *p, const void *buf, size_t size)
836 1.1 christos {
837 1.1 christos struct pcap_win *pw = p->priv;
838 1.1 christos PACKET pkt;
839 1.1 christos
840 1.1 christos PacketInitPacket(&pkt, (PVOID)buf, size);
841 1.1 christos if(PacketSendPacket(pw->adapter,&pkt,TRUE) == FALSE) {
842 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
843 1.1 christos return (-1);
844 1.1 christos }
845 1.1 christos
846 1.1 christos /*
847 1.1 christos * We assume it all got sent if "PacketSendPacket()" succeeded.
848 1.1 christos * "pcap_inject()" is expected to return the number of bytes
849 1.1 christos * sent.
850 1.1 christos */
851 1.1 christos return ((int)size);
852 1.1 christos }
853 1.1 christos
854 1.1 christos static void
855 1.1 christos pcap_cleanup_npf(pcap_t *p)
856 1.1 christos {
857 1.1 christos struct pcap_win *pw = p->priv;
858 1.1 christos
859 1.1 christos if (pw->adapter != NULL) {
860 1.1 christos PacketCloseAdapter(pw->adapter);
861 1.1 christos pw->adapter = NULL;
862 1.1 christos }
863 1.1 christos if (pw->rfmon_selfstart)
864 1.1 christos {
865 1.1 christos PacketSetMonitorMode(p->opt.device, 0);
866 1.1 christos }
867 1.1 christos pcap_cleanup_live_common(p);
868 1.1 christos }
869 1.1 christos
870 1.1 christos static int
871 1.1 christos pcap_activate_npf(pcap_t *p)
872 1.1 christos {
873 1.1 christos struct pcap_win *pw = p->priv;
874 1.1 christos NetType type;
875 1.1 christos int res;
876 1.1 christos char errbuf[PCAP_ERRBUF_SIZE+1];
877 1.1 christos
878 1.1 christos if (p->opt.rfmon) {
879 1.1 christos /*
880 1.1 christos * Monitor mode is supported on Windows Vista and later.
881 1.1 christos */
882 1.1 christos if (PacketGetMonitorMode(p->opt.device) == 1)
883 1.1 christos {
884 1.1 christos pw->rfmon_selfstart = 0;
885 1.1 christos }
886 1.1 christos else
887 1.1 christos {
888 1.1 christos if ((res = PacketSetMonitorMode(p->opt.device, 1)) != 1)
889 1.1 christos {
890 1.1 christos pw->rfmon_selfstart = 0;
891 1.1 christos // Monitor mode is not supported.
892 1.1 christos if (res == 0)
893 1.1 christos {
894 1.1 christos return PCAP_ERROR_RFMON_NOTSUP;
895 1.1 christos }
896 1.1 christos else
897 1.1 christos {
898 1.1 christos return PCAP_ERROR;
899 1.1 christos }
900 1.1 christos }
901 1.1 christos else
902 1.1 christos {
903 1.1 christos pw->rfmon_selfstart = 1;
904 1.1 christos }
905 1.1 christos }
906 1.1 christos }
907 1.1 christos
908 1.1 christos /* Init WinSock */
909 1.1 christos pcap_wsockinit();
910 1.1 christos
911 1.1 christos pw->adapter = PacketOpenAdapter(p->opt.device);
912 1.1 christos
913 1.1 christos if (pw->adapter == NULL)
914 1.1 christos {
915 1.1 christos /* Adapter detected but we are not able to open it. Return failure. */
916 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
917 1.1 christos if (pw->rfmon_selfstart)
918 1.1 christos {
919 1.1 christos PacketSetMonitorMode(p->opt.device, 0);
920 1.1 christos }
921 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
922 1.1 christos "Error opening adapter: %s", errbuf);
923 1.1 christos return (PCAP_ERROR);
924 1.1 christos }
925 1.1 christos
926 1.1 christos /*get network type*/
927 1.1 christos if(PacketGetNetType (pw->adapter,&type) == FALSE)
928 1.1 christos {
929 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
930 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
931 1.1 christos "Cannot determine the network type: %s", errbuf);
932 1.1 christos goto bad;
933 1.1 christos }
934 1.1 christos
935 1.1 christos /*Set the linktype*/
936 1.1 christos switch (type.LinkType)
937 1.1 christos {
938 1.1 christos case NdisMediumWan:
939 1.1 christos p->linktype = DLT_EN10MB;
940 1.1 christos break;
941 1.1 christos
942 1.1 christos case NdisMedium802_3:
943 1.1 christos p->linktype = DLT_EN10MB;
944 1.1 christos /*
945 1.1 christos * This is (presumably) a real Ethernet capture; give it a
946 1.1 christos * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
947 1.1 christos * that an application can let you choose it, in case you're
948 1.1 christos * capturing DOCSIS traffic that a Cisco Cable Modem
949 1.1 christos * Termination System is putting out onto an Ethernet (it
950 1.1 christos * doesn't put an Ethernet header onto the wire, it puts raw
951 1.1 christos * DOCSIS frames out on the wire inside the low-level
952 1.1 christos * Ethernet framing).
953 1.1 christos */
954 1.1 christos p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
955 1.1 christos /*
956 1.1 christos * If that fails, just leave the list empty.
957 1.1 christos */
958 1.1 christos if (p->dlt_list != NULL) {
959 1.1 christos p->dlt_list[0] = DLT_EN10MB;
960 1.1 christos p->dlt_list[1] = DLT_DOCSIS;
961 1.1 christos p->dlt_count = 2;
962 1.1 christos }
963 1.1 christos break;
964 1.1 christos
965 1.1 christos case NdisMediumFddi:
966 1.1 christos p->linktype = DLT_FDDI;
967 1.1 christos break;
968 1.1 christos
969 1.1 christos case NdisMedium802_5:
970 1.1 christos p->linktype = DLT_IEEE802;
971 1.1 christos break;
972 1.1 christos
973 1.1 christos case NdisMediumArcnetRaw:
974 1.1 christos p->linktype = DLT_ARCNET;
975 1.1 christos break;
976 1.1 christos
977 1.1 christos case NdisMediumArcnet878_2:
978 1.1 christos p->linktype = DLT_ARCNET;
979 1.1 christos break;
980 1.1 christos
981 1.1 christos case NdisMediumAtm:
982 1.1 christos p->linktype = DLT_ATM_RFC1483;
983 1.1 christos break;
984 1.1 christos
985 1.1 christos case NdisMediumCHDLC:
986 1.1 christos p->linktype = DLT_CHDLC;
987 1.1 christos break;
988 1.1 christos
989 1.1 christos case NdisMediumPPPSerial:
990 1.1 christos p->linktype = DLT_PPP_SERIAL;
991 1.1 christos break;
992 1.1 christos
993 1.1 christos case NdisMediumNull:
994 1.1 christos p->linktype = DLT_NULL;
995 1.1 christos break;
996 1.1 christos
997 1.1 christos case NdisMediumBare80211:
998 1.1 christos p->linktype = DLT_IEEE802_11;
999 1.1 christos break;
1000 1.1 christos
1001 1.1 christos case NdisMediumRadio80211:
1002 1.1 christos p->linktype = DLT_IEEE802_11_RADIO;
1003 1.1 christos break;
1004 1.1 christos
1005 1.1 christos case NdisMediumPpi:
1006 1.1 christos p->linktype = DLT_PPI;
1007 1.1 christos break;
1008 1.1 christos
1009 1.1 christos default:
1010 1.1 christos p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
1011 1.1 christos break;
1012 1.1 christos }
1013 1.1 christos
1014 1.1 christos /*
1015 1.1 christos * Turn a negative snapshot value (invalid), a snapshot value of
1016 1.1 christos * 0 (unspecified), or a value bigger than the normal maximum
1017 1.1 christos * value, into the maximum allowed value.
1018 1.1 christos *
1019 1.1 christos * If some application really *needs* a bigger snapshot
1020 1.1 christos * length, we should just increase MAXIMUM_SNAPLEN.
1021 1.1 christos */
1022 1.1 christos if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
1023 1.1 christos p->snapshot = MAXIMUM_SNAPLEN;
1024 1.1 christos
1025 1.1 christos /* Set promiscuous mode */
1026 1.1 christos if (p->opt.promisc)
1027 1.1 christos {
1028 1.1 christos
1029 1.1 christos if (PacketSetHwFilter(pw->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
1030 1.1 christos {
1031 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
1032 1.1 christos goto bad;
1033 1.1 christos }
1034 1.1 christos }
1035 1.1 christos else
1036 1.1 christos {
1037 1.1 christos /* NDIS_PACKET_TYPE_ALL_LOCAL selects "All packets sent by installed
1038 1.1 christos * protocols and all packets indicated by the NIC" but if no protocol
1039 1.1 christos * drivers (like TCP/IP) are installed, NDIS_PACKET_TYPE_DIRECTED,
1040 1.1 christos * NDIS_PACKET_TYPE_BROADCAST, and NDIS_PACKET_TYPE_MULTICAST are needed to
1041 1.1 christos * capture incoming frames.
1042 1.1 christos */
1043 1.1 christos if (PacketSetHwFilter(pw->adapter,
1044 1.1 christos NDIS_PACKET_TYPE_ALL_LOCAL |
1045 1.1 christos NDIS_PACKET_TYPE_DIRECTED |
1046 1.1 christos NDIS_PACKET_TYPE_BROADCAST |
1047 1.1 christos NDIS_PACKET_TYPE_MULTICAST) == FALSE)
1048 1.1 christos {
1049 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
1050 1.1 christos goto bad;
1051 1.1 christos }
1052 1.1 christos }
1053 1.1 christos
1054 1.1 christos /* Set the buffer size */
1055 1.1 christos p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
1056 1.1 christos
1057 1.1 christos if(!(pw->adapter->Flags & INFO_FLAG_DAG_CARD))
1058 1.1 christos {
1059 1.1 christos /*
1060 1.1 christos * Traditional Adapter
1061 1.1 christos */
1062 1.1 christos /*
1063 1.1 christos * If the buffer size wasn't explicitly set, default to
1064 1.1 christos * WIN32_DEFAULT_KERNEL_BUFFER_SIZE.
1065 1.1 christos */
1066 1.1 christos if (p->opt.buffer_size == 0)
1067 1.1 christos p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
1068 1.1 christos
1069 1.1 christos if(PacketSetBuff(pw->adapter,p->opt.buffer_size)==FALSE)
1070 1.1 christos {
1071 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
1072 1.1 christos goto bad;
1073 1.1 christos }
1074 1.1 christos
1075 1.1 christos p->buffer = malloc(p->bufsize);
1076 1.1 christos if (p->buffer == NULL)
1077 1.1 christos {
1078 1.1 christos pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1079 1.1 christos errno, "malloc");
1080 1.1 christos goto bad;
1081 1.1 christos }
1082 1.1 christos
1083 1.1 christos if (p->opt.immediate)
1084 1.1 christos {
1085 1.1 christos /* tell the driver to copy the buffer as soon as data arrives */
1086 1.1 christos if(PacketSetMinToCopy(pw->adapter,0)==FALSE)
1087 1.1 christos {
1088 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
1089 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1090 1.1 christos "Error calling PacketSetMinToCopy: %s",
1091 1.1 christos errbuf);
1092 1.1 christos goto bad;
1093 1.1 christos }
1094 1.1 christos }
1095 1.1 christos else
1096 1.1 christos {
1097 1.1 christos /* tell the driver to copy the buffer only if it contains at least 16K */
1098 1.1 christos if(PacketSetMinToCopy(pw->adapter,16000)==FALSE)
1099 1.1 christos {
1100 1.1 christos pcap_win32_err_to_str(GetLastError(), errbuf);
1101 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1102 1.1 christos "Error calling PacketSetMinToCopy: %s",
1103 1.1 christos errbuf);
1104 1.1 christos goto bad;
1105 1.1 christos }
1106 1.1 christos }
1107 1.1 christos } else {
1108 1.1 christos /*
1109 1.1 christos * Dag Card
1110 1.1 christos */
1111 1.1 christos #ifdef HAVE_DAG_API
1112 1.1 christos /*
1113 1.1 christos * We have DAG support.
1114 1.1 christos */
1115 1.1 christos LONG status;
1116 1.1 christos HKEY dagkey;
1117 1.1 christos DWORD lptype;
1118 1.1 christos DWORD lpcbdata;
1119 1.1 christos int postype = 0;
1120 1.1 christos char keyname[512];
1121 1.1 christos
1122 1.1 christos pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
1123 1.1 christos "SYSTEM\\CurrentControlSet\\Services\\DAG",
1124 1.1 christos strstr(_strlwr(p->opt.device), "dag"));
1125 1.1 christos do
1126 1.1 christos {
1127 1.1 christos status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
1128 1.1 christos if(status != ERROR_SUCCESS)
1129 1.1 christos break;
1130 1.1 christos
1131 1.1 christos status = RegQueryValueEx(dagkey,
1132 1.1 christos "PosType",
1133 1.1 christos NULL,
1134 1.1 christos &lptype,
1135 1.1 christos (char*)&postype,
1136 1.1 christos &lpcbdata);
1137 1.1 christos
1138 1.1 christos if(status != ERROR_SUCCESS)
1139 1.1 christos {
1140 1.1 christos postype = 0;
1141 1.1 christos }
1142 1.1 christos
1143 1.1 christos RegCloseKey(dagkey);
1144 1.1 christos }
1145 1.1 christos while(FALSE);
1146 1.1 christos
1147 1.1 christos
1148 1.1 christos p->snapshot = PacketSetSnapLen(pw->adapter, p->snapshot);
1149 1.1 christos
1150 1.1 christos /* Set the length of the FCS associated to any packet. This value
1151 1.1 christos * will be subtracted to the packet length */
1152 1.1 christos pw->dag_fcs_bits = pw->adapter->DagFcsLen;
1153 1.1 christos #else /* HAVE_DAG_API */
1154 1.1 christos /*
1155 1.1 christos * No DAG support.
1156 1.1 christos */
1157 1.1 christos goto bad;
1158 1.1 christos #endif /* HAVE_DAG_API */
1159 1.1 christos }
1160 1.1 christos
1161 1.1 christos PacketSetReadTimeout(pw->adapter, p->opt.timeout);
1162 1.1 christos
1163 1.1 christos /* disable loopback capture if requested */
1164 1.1 christos if (p->opt.nocapture_local)
1165 1.1 christos {
1166 1.1 christos if (!PacketSetLoopbackBehavior(pw->adapter, NPF_DISABLE_LOOPBACK))
1167 1.1 christos {
1168 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1169 1.1 christos "Unable to disable the capture of loopback packets.");
1170 1.1 christos goto bad;
1171 1.1 christos }
1172 1.1 christos }
1173 1.1 christos
1174 1.1 christos #ifdef HAVE_DAG_API
1175 1.1 christos if(pw->adapter->Flags & INFO_FLAG_DAG_CARD)
1176 1.1 christos {
1177 1.1 christos /* install dag specific handlers for read and setfilter */
1178 1.1 christos p->read_op = pcap_read_win32_dag;
1179 1.1 christos p->setfilter_op = pcap_setfilter_win32_dag;
1180 1.1 christos }
1181 1.1 christos else
1182 1.1 christos {
1183 1.1 christos #endif /* HAVE_DAG_API */
1184 1.1 christos /* install traditional npf handlers for read and setfilter */
1185 1.1 christos p->read_op = pcap_read_npf;
1186 1.1 christos p->setfilter_op = pcap_setfilter_npf;
1187 1.1 christos #ifdef HAVE_DAG_API
1188 1.1 christos }
1189 1.1 christos #endif /* HAVE_DAG_API */
1190 1.1 christos p->setdirection_op = NULL; /* Not implemented. */
1191 1.1 christos /* XXX - can this be implemented on some versions of Windows? */
1192 1.1 christos p->inject_op = pcap_inject_npf;
1193 1.1 christos p->set_datalink_op = NULL; /* can't change data link type */
1194 1.1 christos p->getnonblock_op = pcap_getnonblock_npf;
1195 1.1 christos p->setnonblock_op = pcap_setnonblock_npf;
1196 1.1 christos p->stats_op = pcap_stats_npf;
1197 1.1 christos p->stats_ex_op = pcap_stats_ex_npf;
1198 1.1 christos p->setbuff_op = pcap_setbuff_npf;
1199 1.1 christos p->setmode_op = pcap_setmode_npf;
1200 1.1 christos p->setmintocopy_op = pcap_setmintocopy_npf;
1201 1.1 christos p->getevent_op = pcap_getevent_npf;
1202 1.1 christos p->oid_get_request_op = pcap_oid_get_request_npf;
1203 1.1 christos p->oid_set_request_op = pcap_oid_set_request_npf;
1204 1.1 christos p->sendqueue_transmit_op = pcap_sendqueue_transmit_npf;
1205 1.1 christos p->setuserbuffer_op = pcap_setuserbuffer_npf;
1206 1.1 christos p->live_dump_op = pcap_live_dump_npf;
1207 1.1 christos p->live_dump_ended_op = pcap_live_dump_ended_npf;
1208 1.1 christos p->get_airpcap_handle_op = pcap_get_airpcap_handle_npf;
1209 1.1 christos p->cleanup_op = pcap_cleanup_npf;
1210 1.1 christos
1211 1.1 christos /*
1212 1.1 christos * XXX - this is only done because WinPcap supported
1213 1.1 christos * pcap_fileno() returning the hFile HANDLE from the
1214 1.1 christos * ADAPTER structure. We make no general guarantees
1215 1.1 christos * that the caller can do anything useful with it.
1216 1.1 christos *
1217 1.1 christos * (Not that we make any general guarantee of that
1218 1.1 christos * sort on UN*X, either, any more, given that not
1219 1.1 christos * all capture devices are regular OS network
1220 1.1 christos * interfaces.)
1221 1.1 christos */
1222 1.1 christos p->handle = pw->adapter->hFile;
1223 1.1 christos
1224 1.1 christos return (0);
1225 1.1 christos bad:
1226 1.1 christos pcap_cleanup_npf(p);
1227 1.1 christos return (PCAP_ERROR);
1228 1.1 christos }
1229 1.1 christos
1230 1.1 christos /*
1231 1.1 christos * Check if rfmon mode is supported on the pcap_t for Windows systems.
1232 1.1 christos */
1233 1.1 christos static int
1234 1.1 christos pcap_can_set_rfmon_npf(pcap_t *p)
1235 1.1 christos {
1236 1.1 christos return (PacketIsMonitorModeSupported(p->opt.device) == 1);
1237 1.1 christos }
1238 1.1 christos
1239 1.1 christos pcap_t *
1240 1.1 christos pcap_create_interface(const char *device _U_, char *ebuf)
1241 1.1 christos {
1242 1.1 christos pcap_t *p;
1243 1.1 christos
1244 1.1 christos p = pcap_create_common(ebuf, sizeof(struct pcap_win));
1245 1.1 christos if (p == NULL)
1246 1.1 christos return (NULL);
1247 1.1 christos
1248 1.1 christos p->activate_op = pcap_activate_npf;
1249 1.1 christos p->can_set_rfmon_op = pcap_can_set_rfmon_npf;
1250 1.1 christos return (p);
1251 1.1 christos }
1252 1.1 christos
1253 1.1 christos static int
1254 1.1 christos pcap_setfilter_npf(pcap_t *p, struct bpf_program *fp)
1255 1.1 christos {
1256 1.1 christos struct pcap_win *pw = p->priv;
1257 1.1 christos
1258 1.1 christos if(PacketSetBpf(pw->adapter,fp)==FALSE){
1259 1.1 christos /*
1260 1.1 christos * Kernel filter not installed.
1261 1.1 christos *
1262 1.1 christos * XXX - we don't know whether this failed because:
1263 1.1 christos *
1264 1.1 christos * the kernel rejected the filter program as invalid,
1265 1.1 christos * in which case we should fall back on userland
1266 1.1 christos * filtering;
1267 1.1 christos *
1268 1.1 christos * the kernel rejected the filter program as too big,
1269 1.1 christos * in which case we should again fall back on
1270 1.1 christos * userland filtering;
1271 1.1 christos *
1272 1.1 christos * there was some other problem, in which case we
1273 1.1 christos * should probably report an error.
1274 1.1 christos *
1275 1.1 christos * For NPF devices, the Win32 status will be
1276 1.1 christos * STATUS_INVALID_DEVICE_REQUEST for invalid
1277 1.1 christos * filters, but I don't know what it'd be for
1278 1.1 christos * other problems, and for some other devices
1279 1.1 christos * it might not be set at all.
1280 1.1 christos *
1281 1.1 christos * So we just fall back on userland filtering in
1282 1.1 christos * all cases.
1283 1.1 christos */
1284 1.1 christos
1285 1.1 christos /*
1286 1.1 christos * install_bpf_program() validates the program.
1287 1.1 christos *
1288 1.1 christos * XXX - what if we already have a filter in the kernel?
1289 1.1 christos */
1290 1.1 christos if (install_bpf_program(p, fp) < 0)
1291 1.1 christos return (-1);
1292 1.1 christos pw->filtering_in_kernel = 0; /* filtering in userland */
1293 1.1 christos return (0);
1294 1.1 christos }
1295 1.1 christos
1296 1.1 christos /*
1297 1.1 christos * It worked.
1298 1.1 christos */
1299 1.1 christos pw->filtering_in_kernel = 1; /* filtering in the kernel */
1300 1.1 christos
1301 1.1 christos /*
1302 1.1 christos * Discard any previously-received packets, as they might have
1303 1.1 christos * passed whatever filter was formerly in effect, but might
1304 1.1 christos * not pass this filter (BIOCSETF discards packets buffered
1305 1.1 christos * in the kernel, so you can lose packets in any case).
1306 1.1 christos */
1307 1.1 christos p->cc = 0;
1308 1.1 christos return (0);
1309 1.1 christos }
1310 1.1 christos
1311 1.1 christos /*
1312 1.1 christos * We filter at user level, since the kernel driver does't process the packets
1313 1.1 christos */
1314 1.1 christos static int
1315 1.1 christos pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
1316 1.1 christos
1317 1.1 christos if(!fp)
1318 1.1 christos {
1319 1.1 christos strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
1320 1.1 christos return (-1);
1321 1.1 christos }
1322 1.1 christos
1323 1.1 christos /* Install a user level filter */
1324 1.1 christos if (install_bpf_program(p, fp) < 0)
1325 1.1 christos return (-1);
1326 1.1 christos
1327 1.1 christos return (0);
1328 1.1 christos }
1329 1.1 christos
1330 1.1 christos static int
1331 1.1 christos pcap_getnonblock_npf(pcap_t *p)
1332 1.1 christos {
1333 1.1 christos struct pcap_win *pw = p->priv;
1334 1.1 christos
1335 1.1 christos /*
1336 1.1 christos * XXX - if there were a PacketGetReadTimeout() call, we
1337 1.1 christos * would use it, and return 1 if the timeout is -1
1338 1.1 christos * and 0 otherwise.
1339 1.1 christos */
1340 1.1 christos return (pw->nonblock);
1341 1.1 christos }
1342 1.1 christos
1343 1.1 christos static int
1344 1.1 christos pcap_setnonblock_npf(pcap_t *p, int nonblock)
1345 1.1 christos {
1346 1.1 christos struct pcap_win *pw = p->priv;
1347 1.1 christos int newtimeout;
1348 1.1 christos char win_errbuf[PCAP_ERRBUF_SIZE+1];
1349 1.1 christos
1350 1.1 christos if (nonblock) {
1351 1.1 christos /*
1352 1.1 christos * Set the packet buffer timeout to -1 for non-blocking
1353 1.1 christos * mode.
1354 1.1 christos */
1355 1.1 christos newtimeout = -1;
1356 1.1 christos } else {
1357 1.1 christos /*
1358 1.1 christos * Restore the timeout set when the device was opened.
1359 1.1 christos * (Note that this may be -1, in which case we're not
1360 1.1 christos * really leaving non-blocking mode. However, although
1361 1.1 christos * the timeout argument to pcap_set_timeout() and
1362 1.1 christos * pcap_open_live() is an int, you're not supposed to
1363 1.1 christos * supply a negative value, so that "shouldn't happen".)
1364 1.1 christos */
1365 1.1 christos newtimeout = p->opt.timeout;
1366 1.1 christos }
1367 1.1 christos if (!PacketSetReadTimeout(pw->adapter, newtimeout)) {
1368 1.1 christos pcap_win32_err_to_str(GetLastError(), win_errbuf);
1369 1.1 christos pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1370 1.1 christos "PacketSetReadTimeout: %s", win_errbuf);
1371 1.1 christos return (-1);
1372 1.1 christos }
1373 1.1 christos pw->nonblock = (newtimeout == -1);
1374 1.1 christos return (0);
1375 1.1 christos }
1376 1.1 christos
1377 1.1 christos static int
1378 1.1 christos pcap_add_if_npf(pcap_if_list_t *devlistp, char *name, bpf_u_int32 flags,
1379 1.1 christos const char *description, char *errbuf)
1380 1.1 christos {
1381 1.1 christos pcap_if_t *curdev;
1382 1.1 christos npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
1383 1.1 christos LONG if_addr_size;
1384 1.1 christos int res = 0;
1385 1.1 christos
1386 1.1 christos if_addr_size = MAX_NETWORK_ADDRESSES;
1387 1.1 christos
1388 1.1 christos /*
1389 1.1 christos * Add an entry for this interface, with no addresses.
1390 1.1 christos */
1391 1.1 christos curdev = add_dev(devlistp, name, flags, description, errbuf);
1392 1.1 christos if (curdev == NULL) {
1393 1.1 christos /*
1394 1.1 christos * Failure.
1395 1.1 christos */
1396 1.1 christos return (-1);
1397 1.1 christos }
1398 1.1 christos
1399 1.1 christos /*
1400 1.1 christos * Get the list of addresses for the interface.
1401 1.1 christos */
1402 1.1 christos if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
1403 1.1 christos /*
1404 1.1 christos * Failure.
1405 1.1 christos *
1406 1.1 christos * We don't return an error, because this can happen with
1407 1.1 christos * NdisWan interfaces, and we want to supply them even
1408 1.1 christos * if we can't supply their addresses.
1409 1.1 christos *
1410 1.1 christos * We return an entry with an empty address list.
1411 1.1 christos */
1412 1.1 christos return (0);
1413 1.1 christos }
1414 1.1 christos
1415 1.1 christos /*
1416 1.1 christos * Now add the addresses.
1417 1.1 christos */
1418 1.1 christos while (if_addr_size-- > 0) {
1419 1.1 christos /*
1420 1.1 christos * "curdev" is an entry for this interface; add an entry for
1421 1.1 christos * this address to its list of addresses.
1422 1.1 christos */
1423 1.1 christos res = add_addr_to_dev(curdev,
1424 1.1 christos (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
1425 1.1 christos sizeof (struct sockaddr_storage),
1426 1.1 christos (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
1427 1.1 christos sizeof (struct sockaddr_storage),
1428 1.1 christos (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
1429 1.1 christos sizeof (struct sockaddr_storage),
1430 1.1 christos NULL,
1431 1.1 christos 0,
1432 1.1 christos errbuf);
1433 1.1 christos if (res == -1) {
1434 1.1 christos /*
1435 1.1 christos * Failure.
1436 1.1 christos */
1437 1.1 christos break;
1438 1.1 christos }
1439 1.1 christos }
1440 1.1 christos
1441 1.1 christos return (res);
1442 1.1 christos }
1443 1.1 christos
1444 1.1 christos static int
1445 1.1 christos get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
1446 1.1 christos {
1447 1.1 christos char *name_copy;
1448 1.1 christos ADAPTER *adapter;
1449 1.1 christos int status;
1450 1.1 christos size_t len;
1451 1.1 christos NDIS_HARDWARE_STATUS hardware_status;
1452 1.1 christos #ifdef OID_GEN_PHYSICAL_MEDIUM
1453 1.1 christos NDIS_PHYSICAL_MEDIUM phys_medium;
1454 1.1 christos bpf_u_int32 gen_physical_medium_oids[] = {
1455 1.1 christos #ifdef OID_GEN_PHYSICAL_MEDIUM_EX
1456 1.1 christos OID_GEN_PHYSICAL_MEDIUM_EX,
1457 1.1 christos #endif
1458 1.1 christos OID_GEN_PHYSICAL_MEDIUM
1459 1.1 christos };
1460 1.1 christos #define N_GEN_PHYSICAL_MEDIUM_OIDS (sizeof gen_physical_medium_oids / sizeof gen_physical_medium_oids[0])
1461 1.1 christos size_t i;
1462 1.1 christos #endif /* OID_GEN_PHYSICAL_MEDIUM */
1463 1.1 christos #ifdef OID_GEN_LINK_STATE
1464 1.1 christos NDIS_LINK_STATE link_state;
1465 1.1 christos #endif
1466 1.1 christos int connect_status;
1467 1.1 christos
1468 1.1 christos if (*flags & PCAP_IF_LOOPBACK) {
1469 1.1 christos /*
1470 1.1 christos * Loopback interface, so the connection status doesn't
1471 1.1 christos * apply. and it's not wireless (or wired, for that
1472 1.1 christos * matter...). We presume it's up and running.
1473 1.1 christos */
1474 1.1 christos *flags |= PCAP_IF_UP | PCAP_IF_RUNNING | PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
1475 1.1 christos return (0);
1476 1.1 christos }
1477 1.1 christos
1478 1.1 christos /*
1479 1.1 christos * We need to open the adapter to get this information.
1480 1.1 christos *
1481 1.1 christos * XXX - PacketOpenAdapter() takes a non-const pointer
1482 1.1 christos * as an argument, so we make a copy of the argument and
1483 1.1 christos * pass that to it.
1484 1.1 christos */
1485 1.1 christos name_copy = strdup(name);
1486 1.1 christos adapter = PacketOpenAdapter(name_copy);
1487 1.1 christos free(name_copy);
1488 1.1 christos if (adapter == NULL) {
1489 1.1 christos /*
1490 1.1 christos * Give up; if they try to open this device, it'll fail.
1491 1.1 christos */
1492 1.1 christos return (0);
1493 1.1 christos }
1494 1.1 christos
1495 1.1 christos #ifdef HAVE_AIRPCAP_API
1496 1.1 christos /*
1497 1.1 christos * Airpcap.sys do not support the below 'OID_GEN_x' values.
1498 1.1 christos * Just set these flags (and none of the '*flags' entered with).
1499 1.1 christos */
1500 1.1 christos if (PacketGetAirPcapHandle(adapter)) {
1501 1.1 christos /*
1502 1.1 christos * Must be "up" and "running" if the above if succeeded.
1503 1.1 christos */
1504 1.1 christos *flags = PCAP_IF_UP | PCAP_IF_RUNNING;
1505 1.1 christos
1506 1.1 christos /*
1507 1.1 christos * An airpcap device is a wireless device (duh!)
1508 1.1 christos */
1509 1.1 christos *flags |= PCAP_IF_WIRELESS;
1510 1.1 christos
1511 1.1 christos /*
1512 1.1 christos * A "network assosiation state" makes no sense for airpcap.
1513 1.1 christos */
1514 1.1 christos *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
1515 1.1 christos PacketCloseAdapter(adapter);
1516 1.1 christos return (0);
1517 1.1 christos }
1518 1.1 christos #endif
1519 1.1 christos
1520 1.1 christos /*
1521 1.1 christos * Get the hardware status, and derive "up" and "running" from
1522 1.1 christos * that.
1523 1.1 christos */
1524 1.1 christos len = sizeof (hardware_status);
1525 1.1 christos status = oid_get_request(adapter, OID_GEN_HARDWARE_STATUS,
1526 1.1 christos &hardware_status, &len, errbuf);
1527 1.1 christos if (status == 0) {
1528 1.1 christos switch (hardware_status) {
1529 1.1 christos
1530 1.1 christos case NdisHardwareStatusReady:
1531 1.1 christos /*
1532 1.1 christos * "Available and capable of sending and receiving
1533 1.1 christos * data over the wire", so up and running.
1534 1.1 christos */
1535 1.1 christos *flags |= PCAP_IF_UP | PCAP_IF_RUNNING;
1536 1.1 christos break;
1537 1.1 christos
1538 1.1 christos case NdisHardwareStatusInitializing:
1539 1.1 christos case NdisHardwareStatusReset:
1540 1.1 christos /*
1541 1.1 christos * "Initializing" or "Resetting", so up, but
1542 1.1 christos * not running.
1543 1.1 christos */
1544 1.1 christos *flags |= PCAP_IF_UP;
1545 1.1 christos break;
1546 1.1 christos
1547 1.1 christos case NdisHardwareStatusClosing:
1548 1.1 christos case NdisHardwareStatusNotReady:
1549 1.1 christos /*
1550 1.1 christos * "Closing" or "Not ready", so neither up nor
1551 1.1 christos * running.
1552 1.1 christos */
1553 1.1 christos break;
1554 1.1 christos }
1555 1.1 christos } else {
1556 1.1 christos /*
1557 1.1 christos * Can't get the hardware status, so assume both up and
1558 1.1 christos * running.
1559 1.1 christos */
1560 1.1 christos *flags |= PCAP_IF_UP | PCAP_IF_RUNNING;
1561 1.1 christos }
1562 1.1 christos
1563 1.1 christos /*
1564 1.1 christos * Get the network type.
1565 1.1 christos */
1566 1.1 christos #ifdef OID_GEN_PHYSICAL_MEDIUM
1567 1.1 christos /*
1568 1.1 christos * Try the OIDs we have for this, in order.
1569 1.1 christos */
1570 1.1 christos for (i = 0; i < N_GEN_PHYSICAL_MEDIUM_OIDS; i++) {
1571 1.1 christos len = sizeof (phys_medium);
1572 1.1 christos status = oid_get_request(adapter, gen_physical_medium_oids[i],
1573 1.1 christos &phys_medium, &len, errbuf);
1574 1.1 christos if (status == 0) {
1575 1.1 christos /*
1576 1.1 christos * Success.
1577 1.1 christos */
1578 1.1 christos break;
1579 1.1 christos }
1580 1.1 christos /*
1581 1.1 christos * Failed. We can't determine whether it failed
1582 1.1 christos * because that particular OID isn't supported
1583 1.1 christos * or because some other problem occurred, so we
1584 1.1 christos * just drive on and try the next OID.
1585 1.1 christos */
1586 1.1 christos }
1587 1.1 christos if (status == 0) {
1588 1.1 christos /*
1589 1.1 christos * We got the physical medium.
1590 1.1 christos */
1591 1.1 christos switch (phys_medium) {
1592 1.1 christos
1593 1.1 christos case NdisPhysicalMediumWirelessLan:
1594 1.1 christos case NdisPhysicalMediumWirelessWan:
1595 1.1 christos case NdisPhysicalMediumNative802_11:
1596 1.1 christos case NdisPhysicalMediumBluetooth:
1597 1.1 christos case NdisPhysicalMediumUWB:
1598 1.1 christos case NdisPhysicalMediumIrda:
1599 1.1 christos /*
1600 1.1 christos * Wireless.
1601 1.1 christos */
1602 1.1 christos *flags |= PCAP_IF_WIRELESS;
1603 1.1 christos break;
1604 1.1 christos
1605 1.1 christos default:
1606 1.1 christos /*
1607 1.1 christos * Not wireless.
1608 1.1 christos */
1609 1.1 christos break;
1610 1.1 christos }
1611 1.1 christos }
1612 1.1 christos #endif
1613 1.1 christos
1614 1.1 christos /*
1615 1.1 christos * Get the connection status.
1616 1.1 christos */
1617 1.1 christos #ifdef OID_GEN_LINK_STATE
1618 1.1 christos len = sizeof(link_state);
1619 1.1 christos status = oid_get_request(adapter, OID_GEN_LINK_STATE, &link_state,
1620 1.1 christos &len, errbuf);
1621 1.1 christos if (status == 0) {
1622 1.1 christos /*
1623 1.1 christos * NOTE: this also gives us the receive and transmit
1624 1.1 christos * link state.
1625 1.1 christos */
1626 1.1 christos switch (link_state.MediaConnectState) {
1627 1.1 christos
1628 1.1 christos case MediaConnectStateConnected:
1629 1.1 christos /*
1630 1.1 christos * It's connected.
1631 1.1 christos */
1632 1.1 christos *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
1633 1.1 christos break;
1634 1.1 christos
1635 1.1 christos case MediaConnectStateDisconnected:
1636 1.1 christos /*
1637 1.1 christos * It's disconnected.
1638 1.1 christos */
1639 1.1 christos *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
1640 1.1 christos break;
1641 1.1 christos }
1642 1.1 christos }
1643 1.1 christos #else
1644 1.1 christos /*
1645 1.1 christos * OID_GEN_LINK_STATE isn't supported because it's not in our SDK.
1646 1.1 christos */
1647 1.1 christos status = -1;
1648 1.1 christos #endif
1649 1.1 christos if (status == -1) {
1650 1.1 christos /*
1651 1.1 christos * OK, OID_GEN_LINK_STATE didn't work, try
1652 1.1 christos * OID_GEN_MEDIA_CONNECT_STATUS.
1653 1.1 christos */
1654 1.1 christos status = oid_get_request(adapter, OID_GEN_MEDIA_CONNECT_STATUS,
1655 1.1 christos &connect_status, &len, errbuf);
1656 1.1 christos if (status == 0) {
1657 1.1 christos switch (connect_status) {
1658 1.1 christos
1659 1.1 christos case NdisMediaStateConnected:
1660 1.1 christos /*
1661 1.1 christos * It's connected.
1662 1.1 christos */
1663 1.1 christos *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
1664 1.1 christos break;
1665 1.1 christos
1666 1.1 christos case NdisMediaStateDisconnected:
1667 1.1 christos /*
1668 1.1 christos * It's disconnected.
1669 1.1 christos */
1670 1.1 christos *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
1671 1.1 christos break;
1672 1.1 christos }
1673 1.1 christos }
1674 1.1 christos }
1675 1.1 christos PacketCloseAdapter(adapter);
1676 1.1 christos return (0);
1677 1.1 christos }
1678 1.1 christos
1679 1.1 christos int
1680 1.1 christos pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
1681 1.1 christos {
1682 1.1 christos int ret = 0;
1683 1.1 christos const char *desc;
1684 1.1 christos char *AdaptersName;
1685 1.1 christos ULONG NameLength;
1686 1.1 christos char *name;
1687 1.1 christos char our_errbuf[PCAP_ERRBUF_SIZE+1];
1688 1.1 christos
1689 1.1 christos /*
1690 1.1 christos * Find out how big a buffer we need.
1691 1.1 christos *
1692 1.1 christos * This call should always return FALSE; if the error is
1693 1.1 christos * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
1694 1.1 christos * the size of the buffer we need, otherwise there's a
1695 1.1 christos * problem, and NameLength should be set to 0.
1696 1.1 christos *
1697 1.1 christos * It shouldn't require NameLength to be set, but,
1698 1.1 christos * at least as of WinPcap 4.1.3, it checks whether
1699 1.1 christos * NameLength is big enough before it checks for a
1700 1.1 christos * NULL buffer argument, so, while it'll still do
1701 1.1 christos * the right thing if NameLength is uninitialized and
1702 1.1 christos * whatever junk happens to be there is big enough
1703 1.1 christos * (because the pointer argument will be null), it's
1704 1.1 christos * still reading an uninitialized variable.
1705 1.1 christos */
1706 1.1 christos NameLength = 0;
1707 1.1 christos if (!PacketGetAdapterNames(NULL, &NameLength))
1708 1.1 christos {
1709 1.1 christos DWORD last_error = GetLastError();
1710 1.1 christos
1711 1.1 christos if (last_error != ERROR_INSUFFICIENT_BUFFER)
1712 1.1 christos {
1713 1.1 christos pcap_win32_err_to_str(last_error, our_errbuf);
1714 1.1 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1715 1.1 christos "PacketGetAdapterNames: %s", our_errbuf);
1716 1.1 christos return (-1);
1717 1.1 christos }
1718 1.1 christos }
1719 1.1 christos
1720 1.1 christos if (NameLength <= 0)
1721 1.1 christos return 0;
1722 1.1 christos AdaptersName = (char*) malloc(NameLength);
1723 1.1 christos if (AdaptersName == NULL)
1724 1.1 christos {
1725 1.1 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
1726 1.1 christos return (-1);
1727 1.1 christos }
1728 1.1 christos
1729 1.1 christos if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
1730 1.1 christos pcap_win32_err_to_str(GetLastError(), our_errbuf);
1731 1.1 christos pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s",
1732 1.1 christos our_errbuf);
1733 1.1 christos free(AdaptersName);
1734 1.1 christos return (-1);
1735 1.1 christos }
1736 1.1 christos
1737 1.1 christos /*
1738 1.1 christos * "PacketGetAdapterNames()" returned a list of
1739 1.1 christos * null-terminated ASCII interface name strings,
1740 1.1 christos * terminated by a null string, followed by a list
1741 1.1 christos * of null-terminated ASCII interface description
1742 1.1 christos * strings, terminated by a null string.
1743 1.1 christos * This means there are two ASCII nulls at the end
1744 1.1 christos * of the first list.
1745 1.1 christos *
1746 1.1 christos * Find the end of the first list; that's the
1747 1.1 christos * beginning of the second list.
1748 1.1 christos */
1749 1.1 christos desc = &AdaptersName[0];
1750 1.1 christos while (*desc != '\0' || *(desc + 1) != '\0')
1751 1.1 christos desc++;
1752 1.1 christos
1753 1.1 christos /*
1754 1.1 christos * Found it - "desc" points to the first of the two
1755 1.1 christos * nulls at the end of the list of names, so the
1756 1.1 christos * first byte of the list of descriptions is two bytes
1757 1.1 christos * after it.
1758 1.1 christos */
1759 1.1 christos desc += 2;
1760 1.1 christos
1761 1.1 christos /*
1762 1.1 christos * Loop over the elements in the first list.
1763 1.1 christos */
1764 1.1 christos name = &AdaptersName[0];
1765 1.1 christos while (*name != '\0') {
1766 1.1 christos bpf_u_int32 flags = 0;
1767 1.1 christos #ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
1768 1.1 christos /*
1769 1.1 christos * Is this a loopback interface?
1770 1.1 christos */
1771 1.1 christos if (PacketIsLoopbackAdapter(name)) {
1772 1.1 christos /* Yes */
1773 1.1 christos flags |= PCAP_IF_LOOPBACK;
1774 1.1 christos }
1775 1.1 christos #endif
1776 1.1 christos /*
1777 1.1 christos * Get additional flags.
1778 1.1 christos */
1779 1.1 christos if (get_if_flags(name, &flags, errbuf) == -1) {
1780 1.1 christos /*
1781 1.1 christos * Failure.
1782 1.1 christos */
1783 1.1 christos ret = -1;
1784 1.1 christos break;
1785 1.1 christos }
1786 1.1 christos
1787 1.1 christos /*
1788 1.1 christos * Add an entry for this interface.
1789 1.1 christos */
1790 1.1 christos if (pcap_add_if_npf(devlistp, name, flags, desc,
1791 1.1 christos errbuf) == -1) {
1792 1.1 christos /*
1793 1.1 christos * Failure.
1794 1.1 christos */
1795 1.1 christos ret = -1;
1796 1.1 christos break;
1797 1.1 christos }
1798 1.1 christos name += strlen(name) + 1;
1799 1.1 christos desc += strlen(desc) + 1;
1800 1.1 christos }
1801 1.1 christos
1802 1.1 christos free(AdaptersName);
1803 1.1 christos return (ret);
1804 1.1 christos }
1805 1.1 christos
1806 1.1 christos /*
1807 1.1 christos * Return the name of a network interface attached to the system, or NULL
1808 1.1 christos * if none can be found. The interface must be configured up; the
1809 1.1 christos * lowest unit number is preferred; loopback is ignored.
1810 1.1 christos *
1811 1.1 christos * In the best of all possible worlds, this would be the same as on
1812 1.1 christos * UN*X, but there may be software that expects this to return a
1813 1.1 christos * full list of devices after the first device.
1814 1.1 christos */
1815 1.1 christos #define ADAPTERSNAME_LEN 8192
1816 1.1 christos char *
1817 1.1 christos pcap_lookupdev(char *errbuf)
1818 1.1 christos {
1819 1.1 christos DWORD dwVersion;
1820 1.1 christos DWORD dwWindowsMajorVersion;
1821 1.1 christos char our_errbuf[PCAP_ERRBUF_SIZE+1];
1822 1.1 christos
1823 1.1 christos #pragma warning (push)
1824 1.1 christos #pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
1825 1.1 christos dwVersion = GetVersion(); /* get the OS version */
1826 1.1 christos #pragma warning (pop)
1827 1.1 christos dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
1828 1.1 christos
1829 1.1 christos if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
1830 1.1 christos /*
1831 1.1 christos * Windows 95, 98, ME.
1832 1.1 christos */
1833 1.1 christos ULONG NameLength = ADAPTERSNAME_LEN;
1834 1.1 christos static char AdaptersName[ADAPTERSNAME_LEN];
1835 1.1 christos
1836 1.1 christos if (PacketGetAdapterNames(AdaptersName,&NameLength) )
1837 1.1 christos return (AdaptersName);
1838 1.1 christos else
1839 1.1 christos return NULL;
1840 1.1 christos } else {
1841 1.1 christos /*
1842 1.1 christos * Windows NT (NT 4.0 and later).
1843 1.1 christos * Convert the names to Unicode for backward compatibility.
1844 1.1 christos */
1845 1.1 christos ULONG NameLength = ADAPTERSNAME_LEN;
1846 1.1 christos static WCHAR AdaptersName[ADAPTERSNAME_LEN];
1847 1.1 christos size_t BufferSpaceLeft;
1848 1.1 christos char *tAstr;
1849 1.1 christos WCHAR *Unameptr;
1850 1.1 christos char *Adescptr;
1851 1.1 christos size_t namelen, i;
1852 1.1 christos WCHAR *TAdaptersName = (WCHAR*)malloc(ADAPTERSNAME_LEN * sizeof(WCHAR));
1853 1.1 christos int NAdapts = 0;
1854 1.1 christos
1855 1.1 christos if(TAdaptersName == NULL)
1856 1.1 christos {
1857 1.1 christos (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
1858 1.1 christos return NULL;
1859 1.1 christos }
1860 1.1 christos
1861 1.1 christos if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
1862 1.1 christos {
1863 1.1 christos pcap_win32_err_to_str(GetLastError(), our_errbuf);
1864 1.1 christos (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1865 1.1 christos "PacketGetAdapterNames: %s", our_errbuf);
1866 1.1 christos free(TAdaptersName);
1867 1.1 christos return NULL;
1868 1.1 christos }
1869 1.1 christos
1870 1.1 christos
1871 1.1 christos BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
1872 1.1 christos tAstr = (char*)TAdaptersName;
1873 1.1 christos Unameptr = AdaptersName;
1874 1.1 christos
1875 1.1 christos /*
1876 1.1 christos * Convert the device names to Unicode into AdapterName.
1877 1.1 christos */
1878 1.1 christos do {
1879 1.1 christos /*
1880 1.1 christos * Length of the name, including the terminating
1881 1.1 christos * NUL.
1882 1.1 christos */
1883 1.1 christos namelen = strlen(tAstr) + 1;
1884 1.1 christos
1885 1.1 christos /*
1886 1.1 christos * Do we have room for the name in the Unicode
1887 1.1 christos * buffer?
1888 1.1 christos */
1889 1.1 christos if (BufferSpaceLeft < namelen * sizeof(WCHAR)) {
1890 1.1 christos /*
1891 1.1 christos * No.
1892 1.1 christos */
1893 1.1 christos goto quit;
1894 1.1 christos }
1895 1.1 christos BufferSpaceLeft -= namelen * sizeof(WCHAR);
1896 1.1 christos
1897 1.1 christos /*
1898 1.1 christos * Copy the name, converting ASCII to Unicode.
1899 1.1 christos * namelen includes the NUL, so we copy it as
1900 1.1 christos * well.
1901 1.1 christos */
1902 1.1 christos for (i = 0; i < namelen; i++)
1903 1.1 christos *Unameptr++ = *tAstr++;
1904 1.1 christos
1905 1.1 christos /*
1906 1.1 christos * Count this adapter.
1907 1.1 christos */
1908 1.1 christos NAdapts++;
1909 1.1 christos } while (namelen != 1);
1910 1.1 christos
1911 1.1 christos /*
1912 1.1 christos * Copy the descriptions, but don't convert them from
1913 1.1 christos * ASCII to Unicode.
1914 1.1 christos */
1915 1.1 christos Adescptr = (char *)Unameptr;
1916 1.1 christos while(NAdapts--)
1917 1.1 christos {
1918 1.1 christos size_t desclen;
1919 1.1 christos
1920 1.1 christos desclen = strlen(tAstr) + 1;
1921 1.1 christos
1922 1.1 christos /*
1923 1.1 christos * Do we have room for the name in the Unicode
1924 1.1 christos * buffer?
1925 1.1 christos */
1926 1.1 christos if (BufferSpaceLeft < desclen) {
1927 1.1 christos /*
1928 1.1 christos * No.
1929 1.1 christos */
1930 1.1 christos goto quit;
1931 1.1 christos }
1932 1.1 christos
1933 1.1 christos /*
1934 1.1 christos * Just copy the ASCII string.
1935 1.1 christos * namelen includes the NUL, so we copy it as
1936 1.1 christos * well.
1937 1.1 christos */
1938 1.1 christos memcpy(Adescptr, tAstr, desclen);
1939 1.1 christos Adescptr += desclen;
1940 1.1 christos tAstr += desclen;
1941 1.1 christos BufferSpaceLeft -= desclen;
1942 1.1 christos }
1943 1.1 christos
1944 1.1 christos quit:
1945 1.1 christos free(TAdaptersName);
1946 1.1 christos return (char *)(AdaptersName);
1947 1.1 christos }
1948 1.1 christos }
1949 1.1 christos
1950 1.1 christos /*
1951 1.1 christos * We can't use the same code that we use on UN*X, as that's doing
1952 1.1 christos * UN*X-specific calls.
1953 1.1 christos *
1954 1.1 christos * We don't just fetch the entire list of devices, search for the
1955 1.1 christos * particular device, and use its first IPv4 address, as that's too
1956 1.1 christos * much work to get just one device's netmask.
1957 1.1 christos */
1958 1.1 christos int
1959 1.1 christos pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
1960 1.1 christos char *errbuf)
1961 1.1 christos {
1962 1.1 christos /*
1963 1.1 christos * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
1964 1.1 christos * in order to skip non IPv4 (i.e. IPv6 addresses)
1965 1.1 christos */
1966 1.1 christos npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
1967 1.1 christos LONG if_addr_size = MAX_NETWORK_ADDRESSES;
1968 1.1 christos struct sockaddr_in *t_addr;
1969 1.1 christos LONG i;
1970 1.1 christos
1971 1.1 christos if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
1972 1.1 christos *netp = *maskp = 0;
1973 1.1 christos return (0);
1974 1.1 christos }
1975 1.1 christos
1976 1.1 christos for(i = 0; i < if_addr_size; i++)
1977 1.1 christos {
1978 1.1 christos if(if_addrs[i].IPAddress.ss_family == AF_INET)
1979 1.1 christos {
1980 1.1 christos t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
1981 1.1 christos *netp = t_addr->sin_addr.S_un.S_addr;
1982 1.1 christos t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
1983 1.1 christos *maskp = t_addr->sin_addr.S_un.S_addr;
1984 1.1 christos
1985 1.1 christos *netp &= *maskp;
1986 1.1 christos return (0);
1987 1.1 christos }
1988 1.1 christos
1989 1.1 christos }
1990 1.1 christos
1991 1.1 christos *netp = *maskp = 0;
1992 1.1 christos return (0);
1993 1.1 christos }
1994 1.1 christos
1995 1.1 christos static const char *pcap_lib_version_string;
1996 1.1 christos
1997 1.1 christos #ifdef HAVE_VERSION_H
1998 1.1 christos /*
1999 1.1 christos * libpcap being built for Windows, as part of a WinPcap/Npcap source
2000 1.1 christos * tree. Include version.h from that source tree to get the WinPcap/Npcap
2001 1.1 christos * version.
2002 1.1 christos *
2003 1.1 christos * XXX - it'd be nice if we could somehow generate the WinPcap version number
2004 1.1 christos * when building WinPcap. (It'd be nice to do so for the packet.dll version
2005 1.1 christos * number as well.)
2006 1.1 christos */
2007 1.1 christos #include "../../version.h"
2008 1.1 christos
2009 1.1 christos static const char pcap_version_string[] =
2010 1.1 christos WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING ", based on " PCAP_VERSION_STRING;
2011 1.1 christos static const char pcap_version_string_packet_dll_fmt[] =
2012 1.1 christos WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING;
2013 1.1 christos
2014 1.1 christos const char *
2015 1.1 christos pcap_lib_version(void)
2016 1.1 christos {
2017 1.1 christos char *packet_version_string;
2018 1.1 christos size_t full_pcap_version_string_len;
2019 1.1 christos char *full_pcap_version_string;
2020 1.1 christos
2021 1.1 christos if (pcap_lib_version_string == NULL) {
2022 1.1 christos /*
2023 1.1 christos * Generate the version string.
2024 1.1 christos */
2025 1.1 christos packet_version_string = PacketGetVersion();
2026 1.1 christos if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
2027 1.1 christos /*
2028 1.1 christos * WinPcap version string and packet.dll version
2029 1.1 christos * string are the same; just report the WinPcap
2030 1.1 christos * version.
2031 1.1 christos */
2032 1.1 christos pcap_lib_version_string = pcap_version_string;
2033 1.1 christos } else {
2034 1.1 christos /*
2035 1.1 christos * WinPcap version string and packet.dll version
2036 1.1 christos * string are different; that shouldn't be the
2037 1.1 christos * case (the two libraries should come from the
2038 1.1 christos * same version of WinPcap), so we report both
2039 1.1 christos * versions.
2040 1.1 christos *
2041 1.1 christos * The -2 is for the %s in the format string,
2042 1.1 christos * which will be replaced by packet_version_string.
2043 1.1 christos */
2044 1.1 christos full_pcap_version_string_len =
2045 1.1 christos (sizeof pcap_version_string_packet_dll_fmt - 2) +
2046 1.1 christos strlen(packet_version_string);
2047 1.1 christos full_pcap_version_string = malloc(full_pcap_version_string_len);
2048 1.1 christos if (full_pcap_version_string == NULL)
2049 1.1 christos return (NULL);
2050 1.1 christos pcap_snprintf(full_pcap_version_string,
2051 1.1 christos full_pcap_version_string_len,
2052 1.1 christos pcap_version_string_packet_dll_fmt,
2053 1.1 christos packet_version_string);
2054 1.1 christos }
2055 1.1 christos pcap_lib_version_string = full_pcap_version_string;
2056 1.1 christos }
2057 1.1 christos return (pcap_lib_version_string);
2058 1.1 christos }
2059 1.1 christos
2060 1.1 christos #else /* HAVE_VERSION_H */
2061 1.1 christos
2062 1.1 christos /*
2063 1.1 christos * libpcap being built for Windows, not as part of a WinPcap/Npcap source
2064 1.1 christos * tree.
2065 1.1 christos */
2066 1.1 christos static const char pcap_version_string_packet_dll_fmt[] =
2067 1.1 christos PCAP_VERSION_STRING " (packet.dll version %s)";
2068 1.1 christos const char *
2069 1.1 christos pcap_lib_version(void)
2070 1.1 christos {
2071 1.1 christos char *packet_version_string;
2072 1.1 christos size_t full_pcap_version_string_len;
2073 1.1 christos char *full_pcap_version_string;
2074 1.1 christos
2075 1.1 christos if (pcap_lib_version_string == NULL) {
2076 1.1 christos /*
2077 1.1 christos * Generate the version string. Report the packet.dll
2078 1.1 christos * version.
2079 1.1 christos *
2080 1.1 christos * The -2 is for the %s in the format string, which will
2081 1.1 christos * be replaced by packet_version_string.
2082 1.1 christos */
2083 1.1 christos packet_version_string = PacketGetVersion();
2084 1.1 christos full_pcap_version_string_len =
2085 1.1 christos (sizeof pcap_version_string_packet_dll_fmt - 2) +
2086 1.1 christos strlen(packet_version_string);
2087 1.1 christos full_pcap_version_string = malloc(full_pcap_version_string_len);
2088 1.1 christos if (full_pcap_version_string == NULL)
2089 1.1 christos return (NULL);
2090 1.1 christos pcap_snprintf(full_pcap_version_string,
2091 1.1 christos full_pcap_version_string_len,
2092 1.1 christos pcap_version_string_packet_dll_fmt,
2093 1.1 christos packet_version_string);
2094 1.1 christos pcap_lib_version_string = full_pcap_version_string;
2095 1.1 christos }
2096 1.1 christos return (pcap_lib_version_string);
2097 1.1 christos }
2098 1.1 christos #endif /* HAVE_VERSION_H */
2099