• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * pcapif_helper.c - This file is part of lwIP pcapif and provides helper functions
3  * for managing the link state.
4  */
5 
6 #include "pcapif_helper.h"
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 
11 #include "lwip/arch.h"
12 
13 #ifdef WIN32
14 
15 #define WIN32_LEAN_AND_MEAN
16 
17 #ifdef _MSC_VER
18 #pragma warning( push, 3 )
19 #endif
20 #include <windows.h>
21 #include <packet32.h>
22 #include <ntddndis.h>
23 #ifdef _MSC_VER
24 #pragma warning ( pop )
25 #endif
26 
27 struct pcapifh_linkstate {
28   LPADAPTER        lpAdapter;
29   PPACKET_OID_DATA ppacket_oid_data;
30 };
31 
pcapifh_linkstate_init(char * adapter_name)32 struct pcapifh_linkstate* pcapifh_linkstate_init(char *adapter_name)
33 {
34   struct pcapifh_linkstate* state = (struct pcapifh_linkstate*)malloc(sizeof(struct pcapifh_linkstate));
35   if (state != NULL) {
36     memset(state, 0, sizeof(struct pcapifh_linkstate));
37     state->ppacket_oid_data = (PPACKET_OID_DATA)malloc(sizeof(PACKET_OID_DATA) + sizeof(NDIS_MEDIA_STATE));
38     if (state->ppacket_oid_data == NULL) {
39       free(state);
40       state = NULL;
41     } else {
42       state->lpAdapter = PacketOpenAdapter((char*)adapter_name);
43       if ((state->lpAdapter == NULL) || (state->lpAdapter->hFile == INVALID_HANDLE_VALUE)) {
44         /* failed to open adapter */
45         free(state);
46         state = NULL;
47       }
48     }
49   }
50   return state;
51 }
52 
pcapifh_linkstate_get(struct pcapifh_linkstate * state)53 enum pcapifh_link_event pcapifh_linkstate_get(struct pcapifh_linkstate* state)
54 {
55   enum pcapifh_link_event ret = PCAPIF_LINKEVENT_UNKNOWN;
56   if (state != NULL) {
57     state->ppacket_oid_data->Oid    = OID_GEN_MEDIA_CONNECT_STATUS;
58     state->ppacket_oid_data->Length = sizeof(NDIS_MEDIA_STATE);
59     if (PacketRequest(state->lpAdapter, FALSE, state->ppacket_oid_data)) {
60       NDIS_MEDIA_STATE fNdisMediaState;
61       fNdisMediaState = (*((PNDIS_MEDIA_STATE)(state->ppacket_oid_data->Data)));
62       ret = ((fNdisMediaState == NdisMediaStateConnected) ? PCAPIF_LINKEVENT_UP : PCAPIF_LINKEVENT_DOWN);
63     }
64   }
65   return ret;
66 }
67 
pcapifh_linkstate_close(struct pcapifh_linkstate * state)68 void pcapifh_linkstate_close(struct pcapifh_linkstate* state)
69 {
70   if (state != NULL) {
71     if (state->lpAdapter != NULL) {
72       PacketCloseAdapter(state->lpAdapter);
73     }
74     if (state->ppacket_oid_data != NULL) {
75       free(state->ppacket_oid_data);
76     }
77     free(state);
78   }
79 }
80 
81 /** Helper function for PCAPIF_RX_READONLY for windows: copy the date to a new
82  * page which is set to READONLY after copying.
83  * This is a helper to simulate hardware that receives to memory that cannot be
84  * written by the CPU.
85  */
86 void *
pcapifh_alloc_readonly_copy(void * data,size_t len)87 pcapifh_alloc_readonly_copy(void *data, size_t len)
88 {
89   DWORD oldProtect;
90   void *ret;
91   if (len > 4096) {
92     lwip_win32_platform_diag("pcapifh_alloc_readonly_copy: invalid len: %d\n", len);
93     while(1);
94   }
95   ret = VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE);
96   if (ret == NULL) {
97     lwip_win32_platform_diag("VirtualAlloc failed: %d\n", GetLastError());
98     while(1);
99   }
100   memcpy(ret, data, len);
101   if (!VirtualProtect(ret, len, PAGE_READONLY, &oldProtect)) {
102     lwip_win32_platform_diag("VirtualProtect failed: %d\n", GetLastError());
103     while(1);
104   }
105   return ret;
106 }
107 
108 void
pcapifh_free_readonly_mem(void * data)109 pcapifh_free_readonly_mem(void *data)
110 {
111   if (!VirtualFree(data, 0, MEM_RELEASE)) {
112     lwip_win32_platform_diag("VirtualFree(0x%08x) failed: %d\n", data, GetLastError());
113     while(1);
114   }
115 }
116 
117 /**
118  * Npcap keeps its DLLs in a different directory for compatibility with winpcap.
119  * Make sure they get found by adding that directory to the DLL search path.
120  */
pcapifh_init_npcap(void)121 void pcapifh_init_npcap(void)
122 {
123   char npcap_dir[512];
124   unsigned int len;
125   static char npcap_initialized = 0;
126 
127   if (!npcap_initialized)
128   {
129     npcap_initialized = 1;
130 
131     len = GetSystemDirectory(npcap_dir, 480);
132     if (!len) {
133       lwip_win32_platform_diag("Error in GetSystemDirectory: %x", GetLastError());
134       return;
135     }
136     strcat_s(npcap_dir, 512, "\\Npcap");
137     if (SetDllDirectory(npcap_dir) == 0) {
138       lwip_win32_platform_diag("Error in SetDllDirectory: %x", GetLastError());
139       return;
140     }
141   }
142 }
143 
144 #else /* WIN32 */
145 
146 /* @todo: add linux/unix implementation? */
147 
148 struct pcapifh_linkstate {
149   u8_t empty;
150 };
151 
pcapifh_linkstate_init(char * adapter_name)152 struct pcapifh_linkstate* pcapifh_linkstate_init(char *adapter_name)
153 {
154   LWIP_UNUSED_ARG(adapter_name);
155   return NULL;
156 }
157 
pcapifh_linkstate_get(struct pcapifh_linkstate * state)158 enum pcapifh_link_event pcapifh_linkstate_get(struct pcapifh_linkstate* state)
159 {
160   LWIP_UNUSED_ARG(state);
161   return PCAPIF_LINKEVENT_UP;
162 }
pcapifh_linkstate_close(struct pcapifh_linkstate * state)163 void pcapifh_linkstate_close(struct pcapifh_linkstate* state)
164 {
165   LWIP_UNUSED_ARG(state);
166 }
167 
pcapifh_init_npcap(void)168 void pcapifh_init_npcap(void)
169 {
170 }
171 
172 #endif /* WIN32 */
173