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