debug keys
[metze/wireshark/wip.git] / caputils / capture_wpcap_packet.c
1 /* capture_wpcap_packet.c
2  * WinPcap-specific interfaces for low-level information (packet.dll).
3  * We load WinPcap at run
4  * time, so that we only need one Wireshark binary and one TShark binary
5  * for Windows, regardless of whether WinPcap is installed or not.
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 2001 Gerald Combs
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13
14 #include "config.h"
15
16 #if defined HAVE_LIBPCAP && defined _WIN32
17
18 #include <glib.h>
19 #include <gmodule.h>
20
21 #include <wsutil/wspcap.h>
22
23 /* XXX - yes, I know, I should move cppmagic.h to a generic location. */
24 #include "tools/lemon/cppmagic.h"
25
26 #include <epan/value_string.h>
27
28 #include <windowsx.h>
29 #include <Ntddndis.h>
30
31 #include "caputils/capture_wpcap_packet.h"
32 #include <wsutil/file_util.h>
33
34 #include <Packet32.h>
35
36 gboolean has_wpacket = FALSE;
37
38 /* This module will use the PacketRequest function in packet.dll (coming with WinPcap) to "directly" access
39  * the Win32 NDIS network driver(s) and ask for various values (status, statistics, ...).
40  *
41  * Unfortunately, the definitions required for this are not available through the usual windows header files,
42  * but require the Windows "Device Driver Kit" which is not available for free :-(
43  *
44  * Fortunately, the definitions needed to access the various NDIS values are available from various OSS projects:
45  * - WinPcap in Ntddndis.h
46  * - Ndiswrapper in driver/ndis.h and driver/iw_ndis.h
47  * - cygwin (MingW?) in usr/include/w32api/ddk/ndis.h and ntddndis.h
48  * - FreeBSD (netperf)
49  */
50
51 /* The MSDN description of the NDIS driver API is available at:
52 /* MSDN Home >  MSDN Library >  Win32 and COM Development >  Driver Development Kit >  Network Devices and Protocols >  Reference */
53 /* "NDIS Objects" */
54 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/network/hh/network/21oidovw_d55042e5-0b8a-4439-8ef2-be7331e98464.xml.asp */
55
56 /* Some more interesting links:
57  * http://sourceforge.net/projects/ndiswrapper/
58  * http://www.osronline.com/lists_archive/windbg/thread521.html
59  * http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/ndis.h?view=markup
60  * http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/ntddndis.h?view=markup
61  */
62
63
64
65 /******************************************************************************************************************************/
66 /* stuff to load WinPcap's packet.dll and the functions required from it */
67
68 static PCHAR     (*p_PacketGetVersion) (void);
69 static LPADAPTER (*p_PacketOpenAdapter) (char *adaptername);
70 static void      (*p_PacketCloseAdapter) (LPADAPTER);
71 static int       (*p_PacketRequest) (LPADAPTER, int, void *);
72
73 typedef struct {
74     const char  *name;
75     gpointer    *ptr;
76     gboolean    optional;
77 } symbol_table_t;
78
79 #define SYM(x, y)   { G_STRINGIFY(x) , (gpointer) &CONCAT(p_,x), y }
80
81 void
82 wpcap_packet_load(void)
83 {
84
85     /* These are the symbols I need or want from packet.dll */
86     static const symbol_table_t symbols[] = {
87         SYM(PacketGetVersion, FALSE),
88         SYM(PacketOpenAdapter, FALSE),
89         SYM(PacketCloseAdapter, FALSE),
90         SYM(PacketRequest, FALSE),
91         { NULL, NULL, FALSE }
92     };
93
94     GModule     *wh; /* wpcap handle */
95     const symbol_table_t    *sym;
96
97     wh = ws_module_open("packet.dll", 0);
98
99     if (!wh) {
100         return;
101     }
102
103     sym = symbols;
104     while (sym->name) {
105         if (!g_module_symbol(wh, sym->name, sym->ptr)) {
106             if (sym->optional) {
107                 /*
108                  * We don't care if it's missing; we just
109                  * don't use it.
110                  */
111                 *sym->ptr = NULL;
112             } else {
113                 /*
114                  * We require this symbol.
115                  */
116                 return;
117             }
118         }
119         sym++;
120     }
121
122     has_wpacket = TRUE;
123 }
124
125
126
127 /******************************************************************************************************************************/
128 /* functions to access the NDIS driver values */
129
130
131 /* get dll version */
132 char *
133 wpcap_packet_get_version(void)
134 {
135     if(!has_wpacket) {
136         return NULL;
137     }
138     return p_PacketGetVersion();
139 }
140
141
142 /* open the interface */
143 void *
144 wpcap_packet_open(char *if_name)
145 {
146     LPADAPTER   adapter;
147
148     g_assert(has_wpacket);
149     adapter = p_PacketOpenAdapter(if_name);
150
151     return adapter;
152 }
153
154
155 /* close the interface */
156 void
157 wpcap_packet_close(void *adapter)
158 {
159
160     g_assert(has_wpacket);
161     p_PacketCloseAdapter(adapter);
162 }
163
164
165 /* do a packet request call */
166 int
167 wpcap_packet_request(void *adapter, ULONG Oid, int set, char *value, unsigned int *length)
168 {
169     BOOLEAN    Status;
170     ULONG      IoCtlBufferLength=(sizeof(PACKET_OID_DATA) + (*length) - 1);
171     PPACKET_OID_DATA  OidData;
172
173
174     g_assert(has_wpacket);
175
176     if(p_PacketRequest == NULL) {
177         g_warning("packet_request not available\n");
178         return 0;
179     }
180
181     /* get a buffer suitable for PacketRequest() */
182     OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
183     if (OidData == NULL) {
184         g_warning("GlobalAllocPtr failed for %u\n", IoCtlBufferLength);
185         return 0;
186     }
187
188     OidData->Oid = Oid;
189     OidData->Length = *length;
190     memcpy(OidData->Data, value, *length);
191
192     Status = p_PacketRequest(adapter, set, OidData);
193
194     if(Status) {
195         if(OidData->Length <= *length) {
196             /* copy value from driver */
197             memcpy(value, OidData->Data, OidData->Length);
198             *length = OidData->Length;
199         } else {
200             /* the driver returned a value that is longer than expected (and longer than the given buffer) */
201             g_warning("returned oid too long, Oid: 0x%x OidLen:%u MaxLen:%u", Oid, OidData->Length, *length);
202             Status = FALSE;
203         }
204     }
205
206     GlobalFreePtr (OidData);
207
208     if(Status) {
209         return 1;
210     } else {
211         return 0;
212     }
213 }
214
215
216 /* get an UINT value using the packet request call */
217 int
218 wpcap_packet_request_uint(void *adapter, ULONG Oid, UINT *value)
219 {
220     BOOLEAN     Status;
221     int         length = sizeof(UINT);
222
223
224     Status = wpcap_packet_request(adapter, Oid, FALSE /* !set */, (char *) value, &length);
225     if(Status && length == sizeof(UINT)) {
226         return 1;
227     } else {
228         return 0;
229     }
230 }
231
232
233 /* get an ULONG value using the NDIS packet request call */
234 int
235 wpcap_packet_request_ulong(void *adapter, ULONG Oid, ULONG *value)
236 {
237     BOOLEAN     Status;
238     int         length = sizeof(ULONG);
239
240
241     Status = wpcap_packet_request(adapter, Oid, FALSE /* !set */, (char *) value, &length);
242     if(Status && length == sizeof(ULONG)) {
243         return 1;
244     } else {
245         return 0;
246     }
247 }
248
249
250 #else /* HAVE_LIBPCAP && _WIN32 */
251
252 void
253 wpcap_packet_load(void)
254 {
255     return;
256 }
257
258 #endif /* HAVE_LIBPCAP */
259
260 /*
261  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
262  *
263  * Local variables:
264  * c-basic-offset: 4
265  * tab-width: 8
266  * indent-tabs-mode: nil
267  * End:
268  *
269  * ex: set shiftwidth=4 tabstop=8 expandtab:
270  * :indentSize=4:tabSize=8:noTabs=true:
271  */