From a999d57d6a1757078d678a9ab0ae9734a7f8ecc6 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 4 Oct 2021 14:36:40 +0200 Subject: [PATCH] wpcap: Convert pcap_pkthdr structures. Structure layout is different on 64-bit. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51818 Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/wpcap/unixlib.c | 60 ++++++++++++++++++++++++++++++++++++-------- dlls/wpcap/unixlib.h | 26 +++++++++++++------ dlls/wpcap/wpcap.c | 13 +++++----- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/dlls/wpcap/unixlib.c b/dlls/wpcap/unixlib.c index b48a5540edc..96e30fe2f11 100644 --- a/dlls/wpcap/unixlib.c +++ b/dlls/wpcap/unixlib.c @@ -28,6 +28,7 @@ #include #include +#include #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -37,6 +38,7 @@ #include "wine/debug.h" #include "unixlib.h" +WINE_DEFAULT_DEBUG_CHANNEL(wpcap); WINE_DECLARE_DEBUG_CHANNEL(winediag); static const struct pcap_callbacks *callbacks; @@ -101,12 +103,19 @@ static const char * CDECL wrap_datalink_val_to_name( int link ) static void wrap_pcap_handler( unsigned char *user, const struct pcap_pkthdr *hdr, const unsigned char *packet ) { struct handler_callback *cb = (struct handler_callback *)user; - callbacks->handler( cb, hdr, packet ); + struct pcap_pkthdr_win32 hdr_win32; + + if (hdr->ts.tv_sec > INT_MAX || hdr->ts.tv_usec > INT_MAX) WARN( "truncating timeval values(s)\n" ); + hdr_win32.ts.tv_sec = hdr->ts.tv_sec; + hdr_win32.ts.tv_usec = hdr->ts.tv_usec; + hdr_win32.caplen = hdr->caplen; + hdr_win32.len = hdr->len; + callbacks->handler( cb, &hdr_win32, packet ); } static int CDECL wrap_dispatch( struct pcap *pcap, int count, - void (CALLBACK *callback)(unsigned char *, const void *, const unsigned char *), - unsigned char *user ) + void (CALLBACK *callback)(unsigned char *, const struct pcap_pkthdr_win32 *, + const unsigned char *), unsigned char *user ) { if (callback) { @@ -118,9 +127,15 @@ static int CDECL wrap_dispatch( struct pcap *pcap, int count, return pcap_dispatch( pcap->handle, count, NULL, user ); } -static void CDECL wrap_dump( unsigned char *user, const void *hdr, const unsigned char *packet ) +static void CDECL wrap_dump( unsigned char *user, const struct pcap_pkthdr_win32 *hdr, const unsigned char *packet ) { - return pcap_dump( user, hdr, packet ); + struct pcap_pkthdr hdr_unix; + + hdr_unix.ts.tv_sec = hdr->ts.tv_sec; + hdr_unix.ts.tv_usec = hdr->ts.tv_usec; + hdr_unix.caplen = hdr->caplen; + hdr_unix.len = hdr->len; + return pcap_dump( user, &hdr_unix, packet ); } static void * CDECL wrap_dump_open( struct pcap *pcap, const char *name ) @@ -193,8 +208,8 @@ static int CDECL wrap_lookupnet( const char *device, unsigned int *net, unsigned } static int CDECL wrap_loop( struct pcap *pcap, int count, - void (CALLBACK *callback)(unsigned char *, const void *, const unsigned char *), - unsigned char *user ) + void (CALLBACK *callback)(unsigned char *, const struct pcap_pkthdr_win32 *, + const unsigned char *), unsigned char *user ) { if (callback) { @@ -216,14 +231,37 @@ static int CDECL wrap_minor_version( struct pcap *pcap ) return pcap_minor_version( pcap->handle ); } -static const unsigned char * CDECL wrap_next( struct pcap *pcap, void *hdr ) +static const unsigned char * CDECL wrap_next( struct pcap *pcap, struct pcap_pkthdr_win32 *hdr ) { - return pcap_next( pcap->handle, hdr ); + struct pcap_pkthdr hdr_unix; + const unsigned char *ret; + + if ((ret = pcap_next( pcap->handle, &hdr_unix ))) + { + if (hdr_unix.ts.tv_sec > INT_MAX || hdr_unix.ts.tv_usec > INT_MAX) WARN( "truncating timeval values(s)\n" ); + hdr->ts.tv_sec = hdr_unix.ts.tv_sec; + hdr->ts.tv_usec = hdr_unix.ts.tv_usec; + hdr->caplen = hdr_unix.caplen; + hdr->len = hdr_unix.len; + } + return ret; } -static int CDECL wrap_next_ex( struct pcap *pcap, void **hdr, const unsigned char **data ) +static int CDECL wrap_next_ex( struct pcap *pcap, struct pcap_pkthdr_win32 **hdr, const unsigned char **data ) { - return pcap_next_ex( pcap->handle, (struct pcap_pkthdr **)hdr, data ); + struct pcap_pkthdr *hdr_unix; + int ret; + + if ((ret = pcap_next_ex( pcap->handle, &hdr_unix, data )) == 1) + { + if (hdr_unix->ts.tv_sec > INT_MAX || hdr_unix->ts.tv_usec > INT_MAX) WARN( "truncating timeval values(s)\n" ); + pcap->hdr.ts.tv_sec = hdr_unix->ts.tv_sec; + pcap->hdr.ts.tv_usec = hdr_unix->ts.tv_usec; + pcap->hdr.caplen = hdr_unix->caplen; + pcap->hdr.len = hdr_unix->len; + *hdr = &pcap->hdr; + } + return ret; } static struct pcap * CDECL wrap_open_live( const char *source, int snaplen, int promisc, int to_ms, char *errbuf ) diff --git a/dlls/wpcap/unixlib.h b/dlls/wpcap/unixlib.h index c5279f860fd..aa00bc33153 100644 --- a/dlls/wpcap/unixlib.h +++ b/dlls/wpcap/unixlib.h @@ -23,14 +23,26 @@ struct pcap_if_hdr char *name; }; +struct pcap_pkthdr_win32 +{ + struct + { + int tv_sec; + int tv_usec; + } ts; + unsigned int caplen; + unsigned int len; +}; + struct pcap { void *handle; + struct pcap_pkthdr_win32 hdr; }; struct handler_callback { - void (CALLBACK *callback)( unsigned char *, const void *, const unsigned char * ); + void (CALLBACK *callback)( unsigned char *, const struct pcap_pkthdr_win32 *, const unsigned char * ); void *user; }; @@ -47,9 +59,9 @@ struct pcap_funcs const char * (CDECL *datalink_val_to_description)( int ); const char * (CDECL *datalink_val_to_name)( int ); int (CDECL *dispatch)( struct pcap *, int, - void (CALLBACK *)(unsigned char *, const void *, const unsigned char *), + void (CALLBACK *)(unsigned char *, const struct pcap_pkthdr_win32 *, const unsigned char *), unsigned char * ); - void (CDECL *dump)( unsigned char *, const void *, const unsigned char * ); + void (CDECL *dump)( unsigned char *, const struct pcap_pkthdr_win32 *, const unsigned char * ); void * (CDECL *dump_open)( struct pcap *, const char * ); int (CDECL *findalldevs)( struct pcap_if_hdr **, char * ); void (CDECL *free_datalinks)( int * ); @@ -64,12 +76,12 @@ struct pcap_funcs int (CDECL *list_tstamp_types)( struct pcap *, int ** ); int (CDECL *lookupnet)( const char *, unsigned int *, unsigned int *, char * ); int (CDECL *loop)( struct pcap *, int, - void (CALLBACK *)(unsigned char *, const void *, const unsigned char *), + void (CALLBACK *)(unsigned char *, const struct pcap_pkthdr_win32 *, const unsigned char *), unsigned char * ); int (CDECL *major_version)( struct pcap * ); int (CDECL *minor_version)( struct pcap * ); - const unsigned char * (CDECL *next)( struct pcap *, void * ); - int (CDECL *next_ex)( struct pcap *, void **, const unsigned char ** ); + const unsigned char * (CDECL *next)( struct pcap *, struct pcap_pkthdr_win32 * ); + int (CDECL *next_ex)( struct pcap *, struct pcap_pkthdr_win32 **, const unsigned char ** ); struct pcap * (CDECL *open_live)( const char *, int, int, int, char * ); int (CDECL *sendpacket)( struct pcap *, const unsigned char *, int ); int (CDECL *set_buffer_size)( struct pcap *, int ); @@ -92,5 +104,5 @@ struct pcap_funcs struct pcap_callbacks { - void (CDECL *handler)( struct handler_callback *, const void *, const unsigned char * ); + void (CDECL *handler)( struct handler_callback *, const struct pcap_pkthdr_win32 *, const unsigned char * ); }; diff --git a/dlls/wpcap/wpcap.c b/dlls/wpcap/wpcap.c index a190634ac22..ffdb1a3e8d3 100644 --- a/dlls/wpcap/wpcap.c +++ b/dlls/wpcap/wpcap.c @@ -94,14 +94,14 @@ const char * CDECL pcap_datalink_val_to_name( int link ) } int CDECL pcap_dispatch( struct pcap *pcap, int count, - void (CALLBACK *callback)(unsigned char *, const void *, const unsigned char *), + void (CALLBACK *callback)(unsigned char *, const struct pcap_pkthdr_win32 *, const unsigned char *), unsigned char *user ) { TRACE( "%p, %d, %p, %p\n", pcap, count, callback, user ); return pcap_funcs->dispatch( pcap, count, callback, user ); } -void CDECL pcap_dump( unsigned char *user, const void *hdr, const unsigned char *packet ) +void CDECL pcap_dump( unsigned char *user, const struct pcap_pkthdr_win32 *hdr, const unsigned char *packet ) { TRACE( "%p, %p, %p\n", user, hdr, packet ); pcap_funcs->dump( user, hdr, packet ); @@ -249,7 +249,7 @@ int CDECL pcap_lookupnet( const char *device, unsigned int *net, unsigned int *m } int CDECL pcap_loop( struct pcap *pcap, int count, - void (CALLBACK *callback)(unsigned char *, const void *, const unsigned char *), + void (CALLBACK *callback)(unsigned char *, const struct pcap_pkthdr_win32 *, const unsigned char *), unsigned char *user) { TRACE( "%p, %d, %p, %p\n", pcap, count, callback, user ); @@ -268,13 +268,13 @@ int CDECL pcap_minor_version( struct pcap *pcap ) return pcap_funcs->minor_version( pcap ); } -const unsigned char * CDECL pcap_next( struct pcap *pcap, void *hdr ) +const unsigned char * CDECL pcap_next( struct pcap *pcap, struct pcap_pkthdr_win32 *hdr ) { TRACE( "%p, %p\n", pcap, hdr ); return pcap_funcs->next( pcap, hdr ); } -int CDECL pcap_next_ex( struct pcap *pcap, void **hdr, const unsigned char **data ) +int CDECL pcap_next_ex( struct pcap *pcap, struct pcap_pkthdr_win32 **hdr, const unsigned char **data ) { TRACE( "%p, %p, %p\n", pcap, hdr, data ); return pcap_funcs->next_ex( pcap, hdr, data ); @@ -450,7 +450,8 @@ int CDECL wsockinit( void ) return 0; } -static void CDECL pcap_handler_cb( struct handler_callback *cb, const void *hdr, const unsigned char *packet ) +static void CDECL pcap_handler_cb( struct handler_callback *cb, const struct pcap_pkthdr_win32 *hdr, + const unsigned char *packet ) { TRACE( "%p, %p, %p\n", cb, hdr, packet ); cb->callback( cb->user, hdr, packet );