4 * Copyright 2011, 2014 André Hentschel
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wpcap
);
35 const struct pcap_funcs
*pcap_funcs
= NULL
;
37 int CDECL
pcap_activate( struct pcap
*pcap
)
39 TRACE( "%p\n", pcap
);
40 return pcap_funcs
->activate( pcap
);
43 void CDECL
pcap_breakloop( struct pcap
*pcap
)
45 TRACE( "%p\n", pcap
);
46 pcap_funcs
->breakloop( pcap
);
49 int CDECL
pcap_can_set_rfmon( struct pcap
*pcap
)
51 TRACE( "%p\n", pcap
);
52 return pcap_funcs
->can_set_rfmon( pcap
);
55 void CDECL
pcap_close( struct pcap
*pcap
)
57 TRACE( "%p\n", pcap
);
58 pcap_funcs
->close( pcap
);
61 int CDECL
pcap_compile( struct pcap
*pcap
, void *program
, const char *buf
, int optimize
, unsigned int mask
)
63 TRACE( "%p, %p, %s, %d, %u\n", pcap
, program
, debugstr_a(buf
), optimize
, mask
);
64 return pcap_funcs
->compile( pcap
, program
, buf
, optimize
, mask
);
67 struct pcap
* CDECL
pcap_create( const char *src
, char *errbuf
)
69 TRACE( "%s, %p\n", src
, errbuf
);
70 return pcap_funcs
->create( src
, errbuf
);
73 int CDECL
pcap_datalink( struct pcap
*pcap
)
75 TRACE( "%p\n", pcap
);
76 return pcap_funcs
->datalink( pcap
);
79 int CDECL
pcap_datalink_name_to_val( const char *name
)
81 TRACE( "%s\n", debugstr_a(name
) );
82 return pcap_funcs
->datalink_name_to_val( name
);
85 const char * CDECL
pcap_datalink_val_to_description( int link
)
87 TRACE( "%d\n", link
);
88 return pcap_funcs
->datalink_val_to_description( link
);
91 const char * CDECL
pcap_datalink_val_to_name( int link
)
93 TRACE( "%d\n", link
);
94 return pcap_funcs
->datalink_val_to_name( link
);
97 int CDECL
pcap_dispatch( struct pcap
*pcap
, int count
,
98 void (CALLBACK
*callback
)(unsigned char *, const struct pcap_pkthdr_win32
*, const unsigned char *),
101 TRACE( "%p, %d, %p, %p\n", pcap
, count
, callback
, user
);
102 return pcap_funcs
->dispatch( pcap
, count
, callback
, user
);
105 void CDECL
pcap_dump( unsigned char *user
, const struct pcap_pkthdr_win32
*hdr
, const unsigned char *packet
)
107 TRACE( "%p, %p, %p\n", user
, hdr
, packet
);
108 pcap_funcs
->dump( user
, hdr
, packet
);
111 static inline WCHAR
*strdupAW( const char *str
)
116 int len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
117 if ((ret
= malloc( len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
122 void * CDECL
pcap_dump_open( struct pcap
*pcap
, const char *filename
)
128 TRACE( "%p, %s\n", pcap
, debugstr_a(filename
) );
130 if (!(filenameW
= strdupAW( filename
))) return NULL
;
131 unix_path
= wine_get_unix_file_name( filenameW
);
133 if (!unix_path
) return NULL
;
135 TRACE( "unix_path %s\n", debugstr_a(unix_path
) );
137 dumper
= pcap_funcs
->dump_open( pcap
, unix_path
);
138 RtlFreeHeap( GetProcessHeap(), 0, unix_path
);
142 static void free_addresses( struct pcap_address
*addrs
)
144 struct pcap_address
*next
, *cur
= addrs
;
149 free( cur
->netmask
);
150 free( cur
->broadaddr
);
151 free( cur
->dstaddr
);
158 static void free_devices( struct pcap_interface
*devs
)
160 struct pcap_interface
*next
, *cur
= devs
;
165 free( cur
->description
);
166 free_addresses( cur
->addresses
);
173 static IP_ADAPTER_ADDRESSES
*get_adapters( void )
176 IP_ADAPTER_ADDRESSES
*ret
;
177 ULONG flags
= GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
| GAA_FLAG_SKIP_DNS_SERVER
;
179 if (GetAdaptersAddresses( AF_UNSPEC
, flags
, NULL
, NULL
, &size
) != ERROR_BUFFER_OVERFLOW
) return NULL
;
180 if (!(ret
= malloc( size
))) return NULL
;
181 if (GetAdaptersAddresses( AF_UNSPEC
, flags
, NULL
, ret
, &size
))
189 static IP_ADAPTER_ADDRESSES
*find_adapter( IP_ADAPTER_ADDRESSES
*list
, const char *name
)
191 IP_ADAPTER_ADDRESSES
*ret
;
194 if (!(nameW
= strdupAW( name
))) return NULL
;
195 for (ret
= list
; ret
; ret
= ret
->Next
)
197 if (!wcscmp( nameW
, ret
->FriendlyName
)) break;
203 static char *build_win32_name( const char *source
, const char *adapter_name
)
205 const char prefix
[] = "\\Device\\NPF_";
206 int len
= sizeof(prefix
) + strlen(adapter_name
);
209 if (source
) len
+= strlen( source
);
210 if ((ret
= malloc( len
)))
213 if (source
) strcat( ret
, source
);
214 strcat( ret
, prefix
);
215 strcat( ret
, adapter_name
);
220 static char *build_win32_description( const struct pcap_interface
*unix_dev
)
222 int len
= strlen(unix_dev
->name
) + 1;
225 if (unix_dev
->description
&& unix_dev
->description
[0]) len
+= strlen(unix_dev
->description
) + 1;
226 if ((ret
= ptr
= malloc( len
)))
228 if (unix_dev
->description
)
230 strcpy( ret
, unix_dev
->description
);
232 strcat( ret
, unix_dev
->name
);
234 else strcpy( ret
, unix_dev
->name
);
239 static struct sockaddr_hdr
*dup_sockaddr( const struct sockaddr_hdr
*addr
)
241 struct sockaddr_hdr
*ret
;
243 switch (addr
->sa_family
)
247 struct sockaddr_in
*dst
, *src
= (struct sockaddr_in
*)addr
;
248 if (!(dst
= calloc( 1, sizeof(*dst
) ))) return NULL
;
249 dst
->sin_family
= src
->sin_family
;
250 dst
->sin_port
= src
->sin_port
;
251 dst
->sin_addr
= src
->sin_addr
;
252 ret
= (struct sockaddr_hdr
*)dst
;
257 struct sockaddr_in6
*dst
, *src
= (struct sockaddr_in6
*)addr
;
258 if (!(dst
= malloc( sizeof(*dst
) ))) return NULL
;
259 dst
->sin6_family
= src
->sin6_family
;
260 dst
->sin6_port
= src
->sin6_port
;
261 dst
->sin6_flowinfo
= src
->sin6_flowinfo
;
262 dst
->sin6_addr
= src
->sin6_addr
;
263 dst
->sin6_scope_id
= src
->sin6_scope_id
;
264 ret
= (struct sockaddr_hdr
*)dst
;
268 FIXME( "address family %u not supported\n", addr
->sa_family
);
275 static struct pcap_address
*build_win32_address( struct pcap_address
*src
)
277 struct pcap_address
*dst
;
279 if (!(dst
= calloc( 1, sizeof(*dst
) ))) return NULL
;
280 if (src
->addr
&& !(dst
->addr
= dup_sockaddr( src
->addr
))) goto err
;
281 if (src
->netmask
&& !(dst
->netmask
= dup_sockaddr( src
->netmask
))) goto err
;
282 if (src
->broadaddr
&& !(dst
->broadaddr
= dup_sockaddr( src
->broadaddr
))) goto err
;
283 if (src
->dstaddr
&& !(dst
->dstaddr
= dup_sockaddr( src
->dstaddr
))) goto err
;
288 free( dst
->netmask
);
289 free( dst
->broadaddr
);
290 free( dst
->dstaddr
);
295 static void add_win32_address( struct pcap_address
**list
, struct pcap_address
*addr
)
297 struct pcap_address
*cur
= *list
;
298 if (!cur
) *list
= addr
;
301 while (cur
->next
) { cur
= cur
->next
; }
306 static struct pcap_address
*build_win32_addresses( struct pcap_address
*addrs
)
308 struct pcap_address
*src
, *dst
, *ret
= NULL
;
312 if ((dst
= build_win32_address( src
))) add_win32_address( &ret
, dst
);
318 static struct pcap_interface
*build_win32_device( const struct pcap_interface
*unix_dev
, const char *source
,
319 const char *adapter_name
)
321 struct pcap_interface
*ret
;
323 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
324 if (!(ret
->name
= build_win32_name( source
, adapter_name
))) goto err
;
325 if (!(ret
->description
= build_win32_description( unix_dev
))) goto err
;
326 if (!(ret
->addresses
= build_win32_addresses( unix_dev
->addresses
))) goto err
;
327 ret
->flags
= unix_dev
->flags
;
332 free( ret
->description
);
333 free_addresses( ret
->addresses
);
338 static void add_win32_device( struct pcap_interface
**list
, struct pcap_interface
*dev
)
340 struct pcap_interface
*cur
= *list
;
341 if (!cur
) *list
= dev
;
344 while (cur
->next
) { cur
= cur
->next
; }
349 static int find_all_devices( const char *source
, struct pcap_interface
**devs
, char *errbuf
)
351 struct pcap_interface
*unix_devs
, *win32_devs
= NULL
, *cur
, *dev
;
352 IP_ADAPTER_ADDRESSES
*ptr
, *adapters
= get_adapters();
357 if (errbuf
) sprintf( errbuf
, "Out of memory." );
361 if (!(ret
= pcap_funcs
->findalldevs( &unix_devs
, errbuf
)))
366 if ((ptr
= find_adapter( adapters
, cur
->name
)) && (dev
= build_win32_device( cur
, source
, ptr
->AdapterName
)))
368 add_win32_device( &win32_devs
, dev
);
373 pcap_funcs
->freealldevs( unix_devs
);
380 int CDECL
pcap_findalldevs( struct pcap_interface
**devs
, char *errbuf
)
382 TRACE( "%p, %p\n", devs
, errbuf
);
383 return find_all_devices( NULL
, devs
, errbuf
);
386 int CDECL
pcap_findalldevs_ex( char *source
, void *auth
, struct pcap_interface
**devs
, char *errbuf
)
388 FIXME( "%s, %p, %p, %p: partial stub\n", debugstr_a(source
), auth
, devs
, errbuf
);
389 return find_all_devices( source
, devs
, errbuf
);
392 void CDECL
pcap_free_datalinks( int *links
)
394 TRACE( "%p\n", links
);
395 pcap_funcs
->free_datalinks( links
);
398 void CDECL
pcap_free_tstamp_types( int *types
)
400 TRACE( "%p\n", types
);
401 pcap_funcs
->free_tstamp_types( types
);
404 void CDECL
pcap_freealldevs( struct pcap_interface
*devs
)
406 TRACE( "%p\n", devs
);
407 free_devices( devs
);
410 void CDECL
pcap_freecode( void *program
)
412 TRACE( "%p\n", program
);
413 pcap_funcs
->freecode( program
);
416 void * CDECL
pcap_get_airpcap_handle( struct pcap
*pcap
)
418 TRACE( "%p\n", pcap
);
422 int CDECL
pcap_get_tstamp_precision( struct pcap
*pcap
)
424 TRACE( "%p\n", pcap
);
425 return pcap_funcs
->get_tstamp_precision( pcap
);
428 char * CDECL
pcap_geterr( struct pcap
*pcap
)
430 TRACE( "%p\n", pcap
);
431 return pcap_funcs
->geterr( pcap
);
434 int CDECL
pcap_getnonblock( struct pcap
*pcap
, char *errbuf
)
436 TRACE( "%p, %p\n", pcap
, errbuf
);
437 return pcap_funcs
->getnonblock( pcap
, errbuf
);
440 static char lib_version
[256];
441 static BOOL WINAPI
init_lib_version( INIT_ONCE
*once
, void *param
, void **ctx
)
443 const char *str
= pcap_funcs
->lib_version();
444 if (strlen( str
) < sizeof(lib_version
)) strcpy( lib_version
, str
);
448 const char * CDECL
pcap_lib_version( void )
450 static INIT_ONCE once
= INIT_ONCE_STATIC_INIT
;
451 if (!lib_version
[0]) InitOnceExecuteOnce( &once
, init_lib_version
, NULL
, NULL
);
452 TRACE( "%s\n", debugstr_a(lib_version
) );
456 int CDECL
pcap_list_datalinks( struct pcap
*pcap
, int **buf
)
458 TRACE( "%p, %p\n", pcap
, buf
);
459 return pcap_funcs
->list_datalinks( pcap
, buf
);
462 int CDECL
pcap_list_tstamp_types( struct pcap
*pcap
, int **types
)
464 TRACE( "%p, %p\n", pcap
, types
);
465 return pcap_funcs
->list_tstamp_types( pcap
, types
);
468 char * CDECL
pcap_lookupdev( char *errbuf
)
471 struct pcap_interface
*devs
;
473 TRACE( "%p\n", errbuf
);
476 if (pcap_findalldevs( &devs
, errbuf
) == -1 || devs
) return NULL
;
477 if ((ret
= malloc( strlen(devs
->name
) + 1 ))) strcpy( ret
, devs
->name
);
478 pcap_freealldevs( devs
);
483 int CDECL
pcap_lookupnet( const char *device
, unsigned int *net
, unsigned int *mask
, char *errbuf
)
485 TRACE( "%s, %p, %p, %p\n", debugstr_a(device
), net
, mask
, errbuf
);
486 return pcap_funcs
->lookupnet( device
, net
, mask
, errbuf
);
489 int CDECL
pcap_loop( struct pcap
*pcap
, int count
,
490 void (CALLBACK
*callback
)(unsigned char *, const struct pcap_pkthdr_win32
*, const unsigned char *),
493 TRACE( "%p, %d, %p, %p\n", pcap
, count
, callback
, user
);
494 return pcap_funcs
->loop( pcap
, count
, callback
, user
);
497 int CDECL
pcap_major_version( struct pcap
*pcap
)
499 TRACE( "%p\n", pcap
);
500 return pcap_funcs
->major_version( pcap
);
503 int CDECL
pcap_minor_version( struct pcap
*pcap
)
505 TRACE( "%p\n", pcap
);
506 return pcap_funcs
->minor_version( pcap
);
509 const unsigned char * CDECL
pcap_next( struct pcap
*pcap
, struct pcap_pkthdr_win32
*hdr
)
511 TRACE( "%p, %p\n", pcap
, hdr
);
512 return pcap_funcs
->next( pcap
, hdr
);
515 int CDECL
pcap_next_ex( struct pcap
*pcap
, struct pcap_pkthdr_win32
**hdr
, const unsigned char **data
)
517 TRACE( "%p, %p, %p\n", pcap
, hdr
, data
);
518 return pcap_funcs
->next_ex( pcap
, hdr
, data
);
521 static char *strdupWA( const WCHAR
*src
)
524 int len
= WideCharToMultiByte( CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
525 if ((dst
= malloc( len
))) WideCharToMultiByte( CP_ACP
, 0, src
, -1, dst
, len
, NULL
, NULL
);
529 static char *map_win32_device_name( const char *dev
)
531 IP_ADAPTER_ADDRESSES
*ptr
, *adapters
= get_adapters();
532 const char *name
= strchr( dev
, '{' );
535 if (!adapters
|| !name
) return NULL
;
536 for (ptr
= adapters
; ptr
; ptr
= ptr
->Next
)
538 if (!strcmp( name
, ptr
->AdapterName
))
540 ret
= strdupWA( ptr
->FriendlyName
);
548 static struct pcap
*open_live( const char *source
, int snaplen
, int promisc
, int timeout
, char *errbuf
)
553 if (!(unix_dev
= map_win32_device_name( source
)))
555 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
559 ret
= pcap_funcs
->open_live( unix_dev
, snaplen
, promisc
, timeout
, errbuf
);
564 #define PCAP_OPENFLAG_PROMISCUOUS 1
565 struct pcap
* CDECL
pcap_open( const char *source
, int snaplen
, int flags
, int timeout
, void *auth
, char *errbuf
)
567 FIXME( "%s, %d, %d, %d, %p, %p: partial stub\n", debugstr_a(source
), snaplen
, flags
, timeout
, auth
, errbuf
);
568 return open_live( source
, snaplen
, flags
& PCAP_OPENFLAG_PROMISCUOUS
, timeout
, errbuf
);
571 struct pcap
* CDECL
pcap_open_live( const char *source
, int snaplen
, int promisc
, int to_ms
, char *errbuf
)
573 TRACE( "%s, %d, %d, %d, %p\n", debugstr_a(source
), snaplen
, promisc
, to_ms
, errbuf
);
574 return open_live( source
, snaplen
, promisc
, to_ms
, errbuf
);
577 #define PCAP_SRC_FILE 2
578 #define PCAP_SRC_IFLOCAL 3
580 int CDECL
pcap_parsesrcstr( const char *source
, int *type
, char *host
, char *port
, char *name
, char *errbuf
)
582 int t
= PCAP_SRC_IFLOCAL
;
583 const char *p
= source
;
585 FIXME( "%s, %p, %p, %p, %p, %p: partial stub\n", debugstr_a(source
), type
, host
, port
, name
, errbuf
);
594 if (!strncmp(p
, "rpcap://", strlen("rpcap://")))
595 p
+= strlen("rpcap://");
596 else if (!strncmp(p
, "file://", strlen("file://")))
598 p
+= strlen("file://");
608 sprintf(errbuf
, "The name has not been specified in the source string.");
618 int CDECL
pcap_sendpacket( struct pcap
*pcap
, const unsigned char *buf
, int size
)
620 TRACE( "%p, %p, %d\n", pcap
, buf
, size
);
621 return pcap_funcs
->sendpacket( pcap
, buf
, size
);
624 int CDECL
pcap_set_buffer_size( struct pcap
*pcap
, int size
)
626 TRACE( "%p, %d\n", pcap
, size
);
627 return pcap_funcs
->set_buffer_size( pcap
, size
);
630 int CDECL
pcap_set_datalink( struct pcap
*pcap
, int link
)
632 TRACE( "%p, %d\n", pcap
, link
);
633 return pcap_funcs
->set_datalink( pcap
, link
);
636 int CDECL
pcap_set_promisc( struct pcap
*pcap
, int enable
)
638 TRACE( "%p, %d\n", pcap
, enable
);
639 return pcap_funcs
->set_promisc( pcap
, enable
);
642 int CDECL
pcap_set_rfmon( struct pcap
*pcap
, int enable
)
644 TRACE( "%p, %d\n", pcap
, enable
);
645 return pcap_funcs
->set_rfmon( pcap
, enable
);
648 int CDECL
pcap_set_snaplen( struct pcap
*pcap
, int len
)
650 TRACE( "%p, %d\n", pcap
, len
);
651 return pcap_funcs
->set_snaplen( pcap
, len
);
654 int CDECL
pcap_set_timeout( struct pcap
*pcap
, int timeout
)
656 TRACE( "%p, %d\n", pcap
, timeout
);
657 return pcap_funcs
->set_timeout( pcap
, timeout
);
660 int CDECL
pcap_set_tstamp_precision( struct pcap
*pcap
, int precision
)
662 TRACE( "%p, %d\n", pcap
, precision
);
663 return pcap_funcs
->set_tstamp_precision( pcap
, precision
);
666 int CDECL
pcap_set_tstamp_type( struct pcap
*pcap
, int type
)
668 TRACE( "%p, %d\n", pcap
, type
);
669 return pcap_funcs
->set_tstamp_type( pcap
, type
);
672 int CDECL
pcap_setbuff( struct pcap
*pcap
, int size
)
674 FIXME( "%p, %d\n", pcap
, size
);
678 int CDECL
pcap_setfilter( struct pcap
*pcap
, void *program
)
680 TRACE( "%p, %p\n", pcap
, program
);
681 return pcap_funcs
->setfilter( pcap
, program
);
684 int CDECL
pcap_setnonblock( struct pcap
*pcap
, int nonblock
, char *errbuf
)
686 TRACE( "%p, %d, %p\n", pcap
, nonblock
, errbuf
);
687 return pcap_funcs
->setnonblock( pcap
, nonblock
, errbuf
);
690 int CDECL
pcap_snapshot( struct pcap
*pcap
)
692 TRACE( "%p\n", pcap
);
693 return pcap_funcs
->snapshot( pcap
);
696 int CDECL
pcap_stats( struct pcap
*pcap
, void *stats
)
698 TRACE( "%p, %p\n", pcap
, stats
);
699 return pcap_funcs
->stats( pcap
, stats
);
702 const char * CDECL
pcap_statustostr( int status
)
704 TRACE( "%d\n", status
);
705 return pcap_funcs
->statustostr( status
);
708 int CDECL
pcap_tstamp_type_name_to_val( const char *name
)
710 TRACE( "%s\n", debugstr_a(name
) );
711 return pcap_funcs
->tstamp_type_name_to_val( name
);
714 const char * CDECL
pcap_tstamp_type_val_to_description( int val
)
716 TRACE( "%d\n", val
);
717 return pcap_funcs
->tstamp_type_val_to_description( val
);
720 const char * CDECL
pcap_tstamp_type_val_to_name( int val
)
722 TRACE( "%d\n", val
);
723 return pcap_funcs
->tstamp_type_val_to_name( val
);
726 int CDECL
wsockinit( void )
730 if (WSAStartup( MAKEWORD(1, 1), &wsadata
)) return -1;
734 static void CDECL
pcap_handler_cb( struct handler_callback
*cb
, const struct pcap_pkthdr_win32
*hdr
,
735 const unsigned char *packet
)
737 TRACE( "%p, %p, %p\n", cb
, hdr
, packet
);
738 cb
->callback( cb
->user
, hdr
, packet
);
739 TRACE( "callback completed\n" );
742 const struct pcap_callbacks pcap_callbacks
=
747 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, void *reserved
)
751 case DLL_PROCESS_ATTACH
:
752 DisableThreadLibraryCalls( hinst
);
753 if (__wine_init_unix_lib( hinst
, reason
, &pcap_callbacks
, &pcap_funcs
))
754 ERR( "No pcap support, expect problems\n" );
756 case DLL_PROCESS_DETACH
: