diff --git a/contrib/ports/win32/pcapif.c b/contrib/ports/win32/pcapif.c index b531e23e..be0fb7bf 100644 --- a/contrib/ports/win32/pcapif.c +++ b/contrib/ports/win32/pcapif.c @@ -113,6 +113,8 @@ /** If 1, use PBUF_REF for RX (for testing purposes mainly). * For this, LWIP_SUPPORT_CUSTOM_PBUF must be enabled. + * Also, PBUF_POOL_BUFSIZE must be set high enough to ensure all rx packets + * fit into a single pbuf. */ #ifndef PCAPIF_RX_REF #define PCAPIF_RX_REF 0 @@ -127,6 +129,13 @@ #define PCAPIF_GET_STATE_PTR(netif) ((netif)->state) #endif +/** Define this to 1 to allocate readonly pbufs for RX (needs PCAPIF_RX_REF, + * only implemented for windows, for now) + */ +#ifndef PCAPIF_RX_READONLY +#define PCAPIF_RX_READONLY 0 +#endif + #if PCAPIF_HANDLE_LINKSTATE #include "pcapif_helper.h" @@ -320,7 +329,11 @@ pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len) struct pcapif_pbuf_custom { struct pbuf_custom pc; +#if PCAPIF_RX_READONLY + void *ro_mem; +#else struct pbuf* p; +#endif }; #endif /* PCAPIF_RX_REF */ @@ -961,9 +974,15 @@ pcapif_rx_pbuf_free_custom(struct pbuf *p) struct pcapif_pbuf_custom* ppc; LWIP_ASSERT("NULL pointer", p != NULL); ppc = (struct pcapif_pbuf_custom*)p; +#if PCAPIF_RX_READONLY + LWIP_ASSERT("NULL pointer", ppc->ro_mem != NULL); + pcapifh_free_readonly_mem(ppc->ro_mem); + ppc->ro_mem = NULL; +#else LWIP_ASSERT("NULL pointer", ppc->p != NULL); pbuf_free(ppc->p); ppc->p = NULL; +#endif mem_free(p); } @@ -972,6 +991,8 @@ pcapif_rx_ref(struct pbuf* p) { struct pcapif_pbuf_custom* ppc; struct pbuf* q; + u16_t len; + void *payload_mem; LWIP_ASSERT("NULL pointer", p != NULL); LWIP_ASSERT("chained pbuf not supported here", p->next == NULL); @@ -979,9 +1000,18 @@ pcapif_rx_ref(struct pbuf* p) ppc = (struct pcapif_pbuf_custom*)mem_malloc(sizeof(struct pcapif_pbuf_custom)); LWIP_ASSERT("out of memory for RX", ppc != NULL); ppc->pc.custom_free_function = pcapif_rx_pbuf_free_custom; + len = p->tot_len; +#if PCAPIF_RX_READONLY + payload_mem = pcapifh_alloc_readonly_copy(p->payload, len); + LWIP_ASSERT("out of readonly memory for RX", payload_mem != NULL); + pbuf_free(p); + ppc->ro_mem = payload_mem; +#else ppc->p = p; + payload_mem = p->payload; +#endif - q = pbuf_alloced_custom(PBUF_RAW, p->tot_len, PBUF_REF, &ppc->pc, p->payload, p->tot_len); + q = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &ppc->pc, payload_mem, len); LWIP_ASSERT("pbuf_alloced_custom returned NULL", q != NULL); return q; } diff --git a/contrib/ports/win32/pcapif_helper.c b/contrib/ports/win32/pcapif_helper.c index 52670b16..bc6ca8d8 100644 --- a/contrib/ports/win32/pcapif_helper.c +++ b/contrib/ports/win32/pcapif_helper.c @@ -78,6 +78,43 @@ void pcapifh_linkstate_close(struct pcapifh_linkstate* state) } } +/** Helper function for PCAPIF_RX_READONLY for windows: copy the date to a new + * page which is set to READONLY after copying. + * This is a helper to simulate hardware that receives to memory that cannot be + * written by the CPU. + */ +void * +pcapifh_alloc_readonly_copy(void *data, size_t len) +{ + DWORD oldProtect; + void *ret; + if (len > 4096) { + lwip_win32_platform_diag("pcapifh_alloc_readonly_copy: invalid len: %d\n", len); + while(1); + } + ret = VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE); + if (ret == NULL) { + lwip_win32_platform_diag("VirtualAlloc failed: %d\n", GetLastError()); + while(1); + } + memcpy(ret, data, len); + if (!VirtualProtect(ret, len, PAGE_READONLY, &oldProtect)) { + lwip_win32_platform_diag("VirtualProtect failed: %d\n", GetLastError()); + while(1); + } + printf("pcapifh_alloc_readonly_copy(%d): 0x%08x\n", len, ret); + return ret; +} + +void +pcapifh_free_readonly_mem(void *data) +{ + if (!VirtualFree(data, 0, MEM_RELEASE)) { + lwip_win32_platform_diag("VirtualFree(0x%08x) failed: %d\n", data, GetLastError()); + while(1); + } +} + #else /* WIN32 */ /* @todo: add linux/unix implementation? */ diff --git a/contrib/ports/win32/pcapif_helper.h b/contrib/ports/win32/pcapif_helper.h index f2e7fa4b..d4315a0a 100644 --- a/contrib/ports/win32/pcapif_helper.h +++ b/contrib/ports/win32/pcapif_helper.h @@ -1,6 +1,8 @@ #ifndef LWIP_PCAPIF_HELPER_H #define LWIP_PCAPIF_HELPER_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -17,6 +19,8 @@ struct pcapifh_linkstate* pcapifh_linkstate_init(char *adapter_name); enum pcapifh_link_event pcapifh_linkstate_get(struct pcapifh_linkstate* state); void pcapifh_linkstate_close(struct pcapifh_linkstate* state); +void *pcapifh_alloc_readonly_copy(void *data, size_t len); +void pcapifh_free_readonly_mem(void *data); #ifdef __cplusplus }