4 * Copyright 2011, 2014 André Hentschel
5 * Copyright 2022 Hans Leidekker for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define WIN32_NO_STATUS
36 #include "wine/unixlib.h"
37 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(wpcap
);
41 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
43 #define PCAP_CALL( func, params ) WINE_UNIX_CALL( unix_ ## func, params )
46 #define PCAP_ERROR_BREAK -2
47 #define PCAP_ERROR_NOT_ACTIVATED -3
48 #define PCAP_ERROR_ACTIVATED -4
49 #define PCAP_ERROR_NO_SUCH_DEVICE -5
50 #define PCAP_ERROR_RFMON_NOTSUP -6
51 #define PCAP_ERROR_NOT_RFMON -7
52 #define PCAP_ERROR_PERM_DENIED -8
53 #define PCAP_ERROR_IFACE_NOT_UP -9
54 #define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10
55 #define PCAP_ERROR_PROMISC_PERM_DENIED -11
56 #define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12
58 #define PCAP_WARNING 1
59 #define PCAP_WARNING_PROMISC_NOTSUP 2
60 #define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3
62 #define PCAP_ERRBUF_SIZE 256
66 struct pcap_pkthdr_win32 hdr
;
67 char errbuf
[PCAP_ERRBUF_SIZE
];
81 struct bpf_insn
*bf_insns
;
84 int CDECL
pcap_activate( struct pcap
*pcap
)
86 struct activate_params params
;
89 TRACE( "%p\n", pcap
);
91 if (!pcap
) return PCAP_ERROR
;
93 params
.handle
= pcap
->handle
;
94 ret
= PCAP_CALL( activate
, ¶ms
);
95 if (ret
== PCAP_ERROR_PERM_DENIED
)
96 ERR_(winediag
)( "Failed to access raw network (pcap), this requires special permissions.\n" );
100 void CDECL
pcap_breakloop( struct pcap
*pcap
)
102 struct breakloop_params params
;
104 TRACE( "%p\n", pcap
);
107 params
.handle
= pcap
->handle
;
108 PCAP_CALL( breakloop
, ¶ms
);
111 int CDECL
pcap_bufsize( struct pcap
*pcap
)
113 struct bufsize_params params
;
115 TRACE( "%p\n", pcap
);
118 params
.handle
= pcap
->handle
;
119 return PCAP_CALL( bufsize
, ¶ms
);
122 int CDECL
pcap_can_set_rfmon( struct pcap
*pcap
)
124 struct can_set_rfmon_params params
;
126 TRACE( "%p\n", pcap
);
128 if (!pcap
) return PCAP_ERROR
;
129 params
.handle
= pcap
->handle
;
130 return PCAP_CALL( can_set_rfmon
, ¶ms
);
133 void CDECL
pcap_close( struct pcap
*pcap
)
135 struct close_params params
;
137 TRACE( "%p\n", pcap
);
140 params
.handle
= pcap
->handle
;
141 PCAP_CALL( close
, ¶ms
);
145 int CDECL
pcap_compile( struct pcap
*pcap
, struct bpf_program
*program
, const char *str
, int optimize
, unsigned int mask
)
147 struct compile_params params
;
148 unsigned int len
= 64;
149 struct bpf_insn
*tmp
;
152 TRACE( "%p, %p, %s, %d, %#x\n", pcap
, program
, debugstr_a(str
), optimize
, mask
);
154 if (!pcap
|| !program
) return PCAP_ERROR
;
156 if (!(params
.program_insns
= malloc( len
* sizeof(*params
.program_insns
) ))) return PCAP_ERROR
;
157 params
.handle
= pcap
->handle
;
158 params
.program_len
= &len
;
160 params
.optimize
= optimize
;
162 if ((status
= PCAP_CALL( compile
, ¶ms
)) == STATUS_SUCCESS
)
164 program
->bf_len
= *params
.program_len
;
165 program
->bf_insns
= params
.program_insns
;
168 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.program_insns
, len
* sizeof(*tmp
) )))
170 free( params
.program_insns
);
173 params
.program_insns
= tmp
;
174 if (PCAP_CALL( compile
, ¶ms
))
176 free( params
.program_insns
);
179 program
->bf_len
= *params
.program_len
;
180 program
->bf_insns
= params
.program_insns
;
184 int CDECL
pcap_datalink( struct pcap
*pcap
)
186 struct datalink_params params
;
188 TRACE( "%p\n", pcap
);
190 if (!pcap
) return PCAP_ERROR
;
191 params
.handle
= pcap
->handle
;
192 return PCAP_CALL( datalink
, ¶ms
);
195 int CDECL
pcap_datalink_name_to_val( const char *name
)
197 struct datalink_name_to_val_params params
= { name
};
198 TRACE( "%s\n", debugstr_a(name
) );
199 return PCAP_CALL( datalink_name_to_val
, ¶ms
);
208 static void free_datalinks( void )
211 for (i
= 0; i
< ARRAY_SIZE(datalinks
); i
++)
213 free( datalinks
[i
].name
);
214 datalinks
[i
].name
= NULL
;
215 free( datalinks
[i
].description
);
216 datalinks
[i
].description
= NULL
;
220 const char * CDECL
pcap_datalink_val_to_description( int link
)
222 struct datalink_val_to_description_params params
;
223 unsigned int len
= 192;
227 TRACE( "%d\n", link
);
229 if (link
< 0 || link
>= ARRAY_SIZE(datalinks
))
231 WARN( "unhandled link type %d\n", link
);
234 if (datalinks
[link
].description
) return datalinks
[link
].description
;
236 if (!(params
.buf
= malloc( len
))) return NULL
;
238 params
.buflen
= &len
;
239 status
= PCAP_CALL( datalink_val_to_description
, ¶ms
);
240 if (status
== STATUS_SUCCESS
) return (datalinks
[link
].description
= params
.buf
);
241 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.buf
, len
)))
247 if (PCAP_CALL( datalink_val_to_description
, ¶ms
))
253 return (datalinks
[link
].description
= params
.buf
);
256 const char * CDECL
pcap_datalink_val_to_name( int link
)
258 struct datalink_val_to_name_params params
;
259 unsigned int len
= 64;
263 TRACE( "%d\n", link
);
265 if (link
< 0 || link
>= ARRAY_SIZE(datalinks
))
267 WARN( "unhandled link type %d\n", link
);
270 if (datalinks
[link
].name
) return datalinks
[link
].name
;
272 if (!(params
.buf
= malloc( len
))) return NULL
;
274 params
.buflen
= &len
;
275 status
= PCAP_CALL( datalink_val_to_name
, ¶ms
);
276 if (status
== STATUS_SUCCESS
) return (datalinks
[link
].name
= params
.buf
);
277 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.buf
, len
)))
283 if (PCAP_CALL( datalink_val_to_name
, ¶ms
))
289 return (datalinks
[link
].name
= params
.buf
);
292 void CDECL
pcap_dump( unsigned char *user
, const struct pcap_pkthdr_win32
*hdr
, const unsigned char *packet
)
294 struct dump_params params
= { user
, hdr
, packet
};
295 TRACE( "%p, %p, %p\n", user
, hdr
, packet
);
296 PCAP_CALL( dump
, ¶ms
);
304 void CDECL
pcap_dump_close( struct dumper
*dumper
)
306 struct dump_close_params params
;
308 TRACE( "%p\n", dumper
);
311 params
.handle
= dumper
->handle
;
312 PCAP_CALL( dump
, ¶ms
);
316 static inline WCHAR
*strdup_from_utf8( const char *str
)
321 int len
= MultiByteToWideChar( CP_UTF8
, 0, str
, -1, NULL
, 0 );
322 if ((ret
= malloc( len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_UTF8
, 0, str
, -1, ret
, len
);
327 struct dumper
* CDECL
pcap_dump_open( struct pcap
*pcap
, const char *filename
)
329 struct dumper
*dumper
;
331 struct dump_open_params params
;
333 TRACE( "%p, %s\n", pcap
, debugstr_a(filename
) );
335 if (!pcap
) return NULL
;
337 if (!(filenameW
= strdup_from_utf8( filename
))) return NULL
;
338 params
.name
= wine_get_unix_file_name( filenameW
);
340 if (!params
.name
) return NULL
;
342 if (!(dumper
= calloc( 1, sizeof(*dumper
) )))
344 HeapFree( GetProcessHeap(), 0, params
.name
);
348 TRACE( "unix_path %s\n", debugstr_a(params
.name
) );
350 params
.handle
= pcap
->handle
;
351 params
.ret_handle
= &dumper
->handle
;
352 if (PCAP_CALL( dump_open
, ¶ms
))
357 HeapFree( GetProcessHeap(), 0, params
.name
);
361 static void free_addresses( struct pcap_address
*addrs
)
363 struct pcap_address
*next
, *cur
= addrs
;
368 free( cur
->netmask
);
369 free( cur
->broadaddr
);
370 free( cur
->dstaddr
);
377 static void free_devices( struct pcap_interface
*devs
)
379 struct pcap_interface
*next
, *cur
= devs
;
384 free( cur
->description
);
385 free_addresses( cur
->addresses
);
392 static IP_ADAPTER_ADDRESSES
*get_adapters( void )
394 ULONG err
, size
= 4096;
395 IP_ADAPTER_ADDRESSES
*tmp
, *ret
;
396 ULONG flags
= GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
| GAA_FLAG_SKIP_DNS_SERVER
;
398 if (!(ret
= malloc( size
))) return NULL
;
399 err
= GetAdaptersAddresses( AF_UNSPEC
, flags
, NULL
, ret
, &size
);
400 while (err
== ERROR_BUFFER_OVERFLOW
)
402 if (!(tmp
= realloc( ret
, size
))) break;
404 err
= GetAdaptersAddresses( AF_UNSPEC
, flags
, NULL
, ret
, &size
);
406 if (err
== ERROR_SUCCESS
) return ret
;
411 static IP_ADAPTER_ADDRESSES
*find_adapter( IP_ADAPTER_ADDRESSES
*list
, const char *name
)
413 IP_ADAPTER_ADDRESSES
*ret
;
416 if (!(nameW
= strdup_from_utf8( name
))) return NULL
;
417 for (ret
= list
; ret
; ret
= ret
->Next
)
419 if (!wcscmp( nameW
, ret
->FriendlyName
)) break;
425 static char *build_win32_name( const char *source
, const char *adapter_name
)
427 const char prefix
[] = "\\Device\\NPF_";
428 int len
= sizeof(prefix
) + strlen(adapter_name
);
431 if (source
) len
+= strlen( source
);
432 if ((ret
= malloc( len
)))
435 if (source
) strcat( ret
, source
);
436 strcat( ret
, prefix
);
437 strcat( ret
, adapter_name
);
442 static char *build_win32_description( const struct pcap_interface_offsets
*unix_dev
)
444 const char *name
= (const char *)unix_dev
+ unix_dev
->name_offset
;
445 const char *description
= (const char *)unix_dev
+ unix_dev
->description_offset
;
446 int len
= unix_dev
->name_len
+ unix_dev
->description_len
+ 1;
449 if ((ret
= malloc( len
)))
451 if (unix_dev
->description_len
)
453 strcpy( ret
, description
);
457 else strcpy( ret
, name
);
462 static struct sockaddr
*get_address( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
464 struct sockaddr
*ret
;
465 if (!(ret
= malloc( addr
->Address
.iSockaddrLength
))) return NULL
;
466 memcpy( ret
, addr
->Address
.lpSockaddr
, addr
->Address
.iSockaddrLength
);
470 static void convert_length_to_ipv6_mask( ULONG length
, IN6_ADDR
*mask
)
473 for (i
= 0; i
< length
/ 8 - 1; i
++) mask
->u
.Byte
[i
] = 0xff;
474 mask
->u
.Byte
[i
] = 0xff << (8 - length
% 8);
477 static struct sockaddr
*get_netmask( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
479 struct sockaddr
*ret
;
481 switch (addr
->Address
.lpSockaddr
->sa_family
)
485 struct sockaddr_in
*netmask_addr_in
;
487 if (!(netmask_addr_in
= calloc( 1, sizeof(*netmask_addr_in
) ))) return NULL
;
488 netmask_addr_in
->sin_family
= AF_INET
;
489 ConvertLengthToIpv4Mask( addr
->OnLinkPrefixLength
, &netmask_addr_in
->sin_addr
.S_un
.S_addr
);
490 ret
= (struct sockaddr
*)netmask_addr_in
;
495 struct sockaddr_in6
*netmask_addr_in6
;
497 if (!(netmask_addr_in6
= calloc( 1, sizeof(*netmask_addr_in6
) ))) return NULL
;
498 netmask_addr_in6
->sin6_family
= AF_INET6
;
499 convert_length_to_ipv6_mask( addr
->OnLinkPrefixLength
, &netmask_addr_in6
->sin6_addr
);
500 ret
= (struct sockaddr
*)netmask_addr_in6
;
504 FIXME( "address family %u not supported\n", addr
->Address
.lpSockaddr
->sa_family
);
511 static struct sockaddr
*get_broadcast( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
513 struct sockaddr
*ret
;
515 switch (addr
->Address
.lpSockaddr
->sa_family
)
519 struct sockaddr_in
*broadcast_addr_in
, *addr_in
= (struct sockaddr_in
*)addr
->Address
.lpSockaddr
;
522 if (!(broadcast_addr_in
= calloc( 1, sizeof(*broadcast_addr_in
) ))) return NULL
;
523 broadcast_addr_in
->sin_family
= AF_INET
;
524 ConvertLengthToIpv4Mask( addr
->OnLinkPrefixLength
, &netmask
);
525 broadcast_addr_in
->sin_addr
.S_un
.S_addr
= addr_in
->sin_addr
.S_un
.S_addr
| ~netmask
;
526 ret
= (struct sockaddr
*)broadcast_addr_in
;
531 struct sockaddr_in6
*broadcast_addr_in6
, *addr_in6
= (struct sockaddr_in6
*)addr
->Address
.lpSockaddr
;
532 IN6_ADDR netmask
, *address
= (IN6_ADDR
*)&addr_in6
->sin6_addr
;
535 if (!(broadcast_addr_in6
= calloc( 1, sizeof(*broadcast_addr_in6
) ))) return NULL
;
536 broadcast_addr_in6
->sin6_family
= AF_INET6
;
537 convert_length_to_ipv6_mask( addr
->OnLinkPrefixLength
, &netmask
);
538 for (i
= 0; i
< 8; i
++) broadcast_addr_in6
->sin6_addr
.u
.Word
[i
] = address
->u
.Word
[i
] | ~netmask
.u
.Word
[i
];
539 ret
= (struct sockaddr
*)broadcast_addr_in6
;
543 FIXME( "address family %u not supported\n", addr
->Address
.lpSockaddr
->sa_family
);
550 static struct pcap_address
*build_win32_address( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
552 struct pcap_address
*ret
;
554 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
555 if (!(ret
->addr
= get_address( addr
))) goto err
;
556 if (!(ret
->netmask
= get_netmask( addr
))) goto err
;
557 if (!(ret
->broadaddr
= get_broadcast( addr
))) goto err
;
562 free( ret
->netmask
);
563 free( ret
->broadaddr
);
568 static void add_win32_address( struct pcap_address
**list
, struct pcap_address
*addr
)
570 struct pcap_address
*cur
= *list
;
571 if (!cur
) *list
= addr
;
574 while (cur
->next
) { cur
= cur
->next
; }
579 static struct pcap_address
*build_win32_addresses( const IP_ADAPTER_ADDRESSES
*adapter
)
581 struct pcap_address
*dst
, *ret
= NULL
;
582 IP_ADAPTER_UNICAST_ADDRESS
*src
= adapter
->FirstUnicastAddress
;
585 if ((dst
= build_win32_address( src
))) add_win32_address( &ret
, dst
);
591 static struct pcap_interface
*build_win32_device( const struct pcap_interface_offsets
*unix_dev
, const char *source
,
592 const IP_ADAPTER_ADDRESSES
*adapter
)
594 struct pcap_interface
*ret
;
596 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
597 if (!(ret
->name
= build_win32_name( source
, adapter
->AdapterName
))) goto err
;
598 if (!(ret
->description
= build_win32_description( unix_dev
))) goto err
;
599 ret
->addresses
= build_win32_addresses( adapter
);
600 ret
->flags
= unix_dev
->flags
;
605 free( ret
->description
);
606 free_addresses( ret
->addresses
);
611 static void add_win32_device( struct pcap_interface
**list
, struct pcap_interface
*dev
)
613 struct pcap_interface
*cur
= *list
;
614 if (!cur
) *list
= dev
;
617 while (cur
->next
) { cur
= cur
->next
; }
622 static int find_all_devices( const char *source
, struct pcap_interface
**devs
, char *errbuf
)
624 struct pcap_interface
*win32_devs
= NULL
, *dst
;
625 const struct pcap_interface_offsets
*src
;
626 IP_ADAPTER_ADDRESSES
*ptr
, *adapters
;
627 struct findalldevs_params params
;
628 unsigned int len_total
= 0, len
= 512;
631 if (!(params
.buf
= malloc( len
))) return PCAP_ERROR
;
632 params
.buflen
= &len
;
633 params
.errbuf
= errbuf
;
637 if ((ret
= PCAP_CALL( findalldevs
, ¶ms
)) != STATUS_BUFFER_TOO_SMALL
) break;
638 if (!(tmp
= realloc( params
.buf
, *params
.buflen
)))
651 if (!(adapters
= get_adapters()))
657 src
= (const struct pcap_interface_offsets
*)params
.buf
;
660 const char *name
= (const char *)src
+ src
->name_offset
;
661 unsigned int len_src
= sizeof(*src
) + src
->name_len
+ src
->description_len
;
663 if ((ptr
= find_adapter( adapters
, name
)) && (dst
= build_win32_device( src
, source
, ptr
)))
665 add_win32_device( &win32_devs
, dst
);
668 len_total
+= len_src
;
669 if (len_total
>= *params
.buflen
) break;
670 src
= (const struct pcap_interface_offsets
*)((const char *)src
+ len_src
);
679 int CDECL
pcap_findalldevs( struct pcap_interface
**devs
, char *errbuf
)
681 TRACE( "%p, %p\n", devs
, errbuf
);
682 return find_all_devices( NULL
, devs
, errbuf
);
685 int CDECL
pcap_findalldevs_ex( char *source
, void *auth
, struct pcap_interface
**devs
, char *errbuf
)
687 FIXME( "%s, %p, %p, %p: partial stub\n", debugstr_a(source
), auth
, devs
, errbuf
);
688 return find_all_devices( source
, devs
, errbuf
);
691 void CDECL
pcap_free_datalinks( int *links
)
693 TRACE( "%p\n", links
);
697 void CDECL
pcap_free_tstamp_types( int *types
)
699 TRACE( "%p\n", types
);
703 void CDECL
pcap_freealldevs( struct pcap_interface
*devs
)
705 TRACE( "%p\n", devs
);
706 free_devices( devs
);
709 void CDECL
pcap_freecode( struct bpf_program
*program
)
711 TRACE( "%p\n", program
);
713 if (!program
) return;
714 free( program
->bf_insns
);
717 void * CDECL
pcap_get_airpcap_handle( struct pcap
*pcap
)
719 TRACE( "%p\n", pcap
);
723 int CDECL
pcap_get_tstamp_precision( struct pcap
*pcap
)
725 struct get_tstamp_precision_params params
;
727 TRACE( "%p\n", pcap
);
729 if (!pcap
) return PCAP_ERROR
;
730 params
.handle
= pcap
->handle
;
731 return PCAP_CALL( get_tstamp_precision
, ¶ms
);
734 char * CDECL
pcap_geterr( struct pcap
*pcap
)
736 struct geterr_params params
;
738 TRACE( "%p\n", pcap
);
740 if (!pcap
) return NULL
;
741 params
.handle
= pcap
->handle
;
742 params
.errbuf
= pcap
->errbuf
;
743 PCAP_CALL( geterr
, ¶ms
);
744 return pcap
->errbuf
; /* FIXME: keep up-to-date */
747 int CDECL
pcap_getnonblock( struct pcap
*pcap
, char *errbuf
)
749 struct getnonblock_params params
;
751 TRACE( "%p, %p\n", pcap
, errbuf
);
753 if (!pcap
) return PCAP_ERROR
;
754 params
.handle
= pcap
->handle
;
755 params
.errbuf
= errbuf
;
756 return PCAP_CALL( getnonblock
, ¶ms
);
759 static char lib_version
[256];
760 static BOOL WINAPI
init_lib_version( INIT_ONCE
*once
, void *param
, void **ctx
)
762 struct lib_version_params params
= { lib_version
, sizeof(lib_version
) };
763 PCAP_CALL( lib_version
, ¶ms
);
767 const char * CDECL
pcap_lib_version( void )
769 static INIT_ONCE once
= INIT_ONCE_STATIC_INIT
;
770 if (!lib_version
[0]) InitOnceExecuteOnce( &once
, init_lib_version
, NULL
, NULL
);
771 TRACE( "%s\n", debugstr_a(lib_version
) );
775 int CDECL
pcap_list_datalinks( struct pcap
*pcap
, int **links
)
777 struct list_datalinks_params params
;
781 TRACE( "%p, %p\n", pcap
, links
);
783 if (!pcap
|| !links
) return PCAP_ERROR
;
785 if (!(params
.links
= malloc( count
* sizeof(*params
.links
) ))) return PCAP_ERROR
;
786 params
.handle
= pcap
->handle
;
787 params
.count
= &count
;
788 if ((status
= PCAP_CALL( list_datalinks
, ¶ms
)) == STATUS_SUCCESS
)
790 if (count
> 0) *links
= params
.links
;
793 free( params
.links
);
798 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.links
, count
* sizeof(*tmp
) )))
800 free( params
.links
);
804 if (PCAP_CALL( list_datalinks
, ¶ms
))
806 free( params
.links
);
809 *links
= params
.links
;
813 int CDECL
pcap_list_tstamp_types( struct pcap
*pcap
, int **types
)
815 struct list_tstamp_types_params params
;
819 TRACE( "%p, %p\n", pcap
, types
);
821 TRACE( "%p, %p\n", pcap
, types
);
823 if (!pcap
|| !types
) return PCAP_ERROR
;
825 if (!(params
.types
= malloc( count
* sizeof(*params
.types
) ))) return PCAP_ERROR
;
826 params
.handle
= pcap
->handle
;
827 params
.count
= &count
;
828 if ((status
= PCAP_CALL( list_tstamp_types
, ¶ms
)) == STATUS_SUCCESS
)
830 if (count
> 0) *types
= params
.types
;
833 free( params
.types
);
838 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.types
, count
* sizeof(*tmp
) )))
840 free( params
.types
);
844 if (PCAP_CALL( list_tstamp_types
, ¶ms
))
846 free( params
.types
);
849 *types
= params
.types
;
853 char * CDECL
pcap_lookupdev( char *errbuf
)
856 struct pcap_interface
*devs
;
858 TRACE( "%p\n", errbuf
);
861 if (pcap_findalldevs( &devs
, errbuf
) == PCAP_ERROR
|| !devs
) return NULL
;
862 ret
= strdup( devs
->name
);
863 pcap_freealldevs( devs
);
868 static char *strdup_to_utf8( const WCHAR
*src
)
871 int len
= WideCharToMultiByte( CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
872 if ((dst
= malloc( len
))) WideCharToMultiByte( CP_UTF8
, 0, src
, -1, dst
, len
, NULL
, NULL
);
876 static char *map_win32_device_name( const char *dev
)
878 IP_ADAPTER_ADDRESSES
*ptr
, *adapters
= get_adapters();
879 const char *name
= strchr( dev
, '{' );
882 if (!adapters
|| !name
) return NULL
;
883 for (ptr
= adapters
; ptr
; ptr
= ptr
->Next
)
885 if (!strcmp( name
, ptr
->AdapterName
))
887 ret
= strdup_to_utf8( ptr
->FriendlyName
);
895 int CDECL
pcap_lookupnet( const char *device
, unsigned int *net
, unsigned int *mask
, char *errbuf
)
897 struct lookupnet_params params
;
900 TRACE( "%s, %p, %p, %p\n", debugstr_a(device
), net
, mask
, errbuf
);
902 if (!(params
.device
= map_win32_device_name( device
)))
904 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
909 params
.errbuf
= errbuf
;
910 ret
= PCAP_CALL( lookupnet
, ¶ms
);
911 free( params
.device
);
915 int CDECL
pcap_major_version( struct pcap
*pcap
)
917 struct major_version_params params
;
919 TRACE( "%p\n", pcap
);
921 if (!pcap
) return PCAP_ERROR
;
922 params
.handle
= pcap
->handle
;
923 return PCAP_CALL( major_version
, ¶ms
);
926 int CDECL
pcap_minor_version( struct pcap
*pcap
)
928 struct minor_version_params params
;
930 TRACE( "%p\n", pcap
);
932 if (!pcap
) return PCAP_ERROR
;
933 params
.handle
= pcap
->handle
;
934 return PCAP_CALL( minor_version
, ¶ms
);
937 int CDECL
pcap_next_ex( struct pcap
*pcap
, struct pcap_pkthdr_win32
**hdr
, const unsigned char **data
)
939 struct next_ex_params params
;
942 TRACE( "%p, %p, %p\n", pcap
, hdr
, data
);
944 if (!pcap
) return PCAP_ERROR
;
945 params
.handle
= pcap
->handle
;
946 params
.hdr
= &pcap
->hdr
;
948 if ((ret
= PCAP_CALL( next_ex
, ¶ms
)) == 1) *hdr
= &pcap
->hdr
;
952 const unsigned char * CDECL
pcap_next( struct pcap
*pcap
, struct pcap_pkthdr_win32
*hdr
)
954 struct pcap_pkthdr_win32
*hdr_ptr
;
955 const unsigned char *data
;
957 if (pcap_next_ex( pcap
, &hdr_ptr
, &data
) == 1)
965 int CDECL
pcap_dispatch( struct pcap
*pcap
, int count
,
966 void (CALLBACK
*callback
)(unsigned char *, const struct pcap_pkthdr_win32
*, const unsigned char *),
967 unsigned char *user
)
971 TRACE( "%p, %d, %p, %p\n", pcap
, count
, callback
, user
);
973 while (count
<= 0 || processed
< count
)
975 struct pcap_pkthdr_win32
*hdr
= NULL
;
976 const unsigned char *data
= NULL
;
978 int ret
= pcap_next_ex( pcap
, &hdr
, &data
);
984 else if (ret
== PCAP_ERROR_BREAK
)
986 if (processed
== 0) return PCAP_ERROR_BREAK
;
992 callback( user
, hdr
, data
);
998 int CDECL
pcap_loop( struct pcap
*pcap
, int count
,
999 void (CALLBACK
*callback
)(unsigned char *, const struct pcap_pkthdr_win32
*, const unsigned char *),
1000 unsigned char *user
)
1004 TRACE( "%p, %d, %p, %p\n", pcap
, count
, callback
, user
);
1006 while (count
<= 0 || processed
< count
)
1008 struct pcap_pkthdr_win32
*hdr
= NULL
;
1009 const unsigned char *data
= NULL
;
1011 int ret
= pcap_next_ex( pcap
, &hdr
, &data
);
1017 else if (ret
== PCAP_ERROR_BREAK
)
1019 if (processed
== 0) return PCAP_ERROR_BREAK
;
1025 callback( user
, hdr
, data
);
1031 struct pcap
* CDECL
pcap_create( const char *source
, char *errbuf
)
1034 struct create_params params
;
1036 TRACE( "%s, %p\n", source
, errbuf
);
1038 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
1040 if (!(params
.source
= map_win32_device_name( source
)))
1042 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
1046 params
.errbuf
= errbuf
;
1047 params
.handle
= &ret
->handle
;
1048 if (PCAP_CALL( create
, ¶ms
))
1053 free( params
.source
);
1057 static struct pcap
*open_live( const char *source
, int snaplen
, int promisc
, int timeout
, char *errbuf
)
1060 struct open_live_params params
;
1062 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
1064 if (!(params
.source
= map_win32_device_name( source
)))
1066 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
1070 params
.snaplen
= snaplen
;
1071 params
.promisc
= promisc
;
1072 params
.timeout
= timeout
;
1073 params
.errbuf
= errbuf
;
1074 params
.handle
= &ret
->handle
;
1075 if (PCAP_CALL( open_live
, ¶ms
))
1080 free( params
.source
);
1084 #define PCAP_OPENFLAG_PROMISCUOUS 1
1085 struct pcap
* CDECL
pcap_open( const char *source
, int snaplen
, int flags
, int timeout
, void *auth
, char *errbuf
)
1087 FIXME( "%s, %d, %d, %d, %p, %p: partial stub\n", debugstr_a(source
), snaplen
, flags
, timeout
, auth
, errbuf
);
1088 return open_live( source
, snaplen
, flags
& PCAP_OPENFLAG_PROMISCUOUS
, timeout
, errbuf
);
1091 struct pcap
* CDECL
pcap_open_live( const char *source
, int snaplen
, int promisc
, int to_ms
, char *errbuf
)
1093 TRACE( "%s, %d, %d, %d, %p\n", debugstr_a(source
), snaplen
, promisc
, to_ms
, errbuf
);
1094 return open_live( source
, snaplen
, promisc
, to_ms
, errbuf
);
1097 #define PCAP_SRC_FILE 2
1098 #define PCAP_SRC_IFLOCAL 3
1100 int CDECL
pcap_parsesrcstr( const char *source
, int *ret_type
, char *host
, char *port
, char *name
, char *errbuf
)
1102 int type
= PCAP_SRC_IFLOCAL
;
1103 const char *ptr
= source
;
1105 FIXME( "%s, %p, %p, %p, %p, %p: partial stub\n", debugstr_a(source
), ret_type
, host
, port
, name
, errbuf
);
1107 if (host
) *host
= 0;
1108 if (port
) *port
= 0;
1109 if (name
) *name
= 0;
1111 if (!strncmp( ptr
, "rpcap://", strlen("rpcap://"))) ptr
+= strlen( "rpcap://" );
1112 else if (!strncmp( ptr
, "file://", strlen("file://") ))
1114 ptr
+= strlen( "file://" );
1115 type
= PCAP_SRC_FILE
;
1118 if (ret_type
) *ret_type
= type
;
1121 if (errbuf
) sprintf( errbuf
, "The name has not been specified in the source string." );
1125 if (name
) strcpy( name
, ptr
);
1129 int CDECL
pcap_sendpacket( struct pcap
*pcap
, const unsigned char *buf
, int size
)
1131 struct sendpacket_params params
;
1133 TRACE( "%p, %p, %d\n", pcap
, buf
, size
);
1135 if (!pcap
) return PCAP_ERROR
;
1136 params
.handle
= pcap
->handle
;
1139 return PCAP_CALL( sendpacket
, ¶ms
);
1142 int CDECL
pcap_set_buffer_size( struct pcap
*pcap
, int size
)
1144 struct set_buffer_size_params params
;
1146 TRACE( "%p, %d\n", pcap
, size
);
1148 if (!pcap
) return PCAP_ERROR
;
1149 params
.handle
= pcap
->handle
;
1151 return PCAP_CALL( set_buffer_size
, ¶ms
);
1154 int CDECL
pcap_set_datalink( struct pcap
*pcap
, int link
)
1156 struct set_datalink_params params
;
1158 TRACE( "%p, %d\n", pcap
, link
);
1160 if (!pcap
) return PCAP_ERROR
;
1161 params
.handle
= pcap
->handle
;
1163 return PCAP_CALL( set_datalink
, ¶ms
);
1166 int CDECL
pcap_set_promisc( struct pcap
*pcap
, int enable
)
1168 struct set_promisc_params params
;
1170 TRACE( "%p, %d\n", pcap
, enable
);
1172 if (!pcap
) return PCAP_ERROR
;
1173 params
.handle
= pcap
->handle
;
1174 params
.enable
= enable
;
1175 return PCAP_CALL( set_promisc
, ¶ms
);
1178 int CDECL
pcap_set_rfmon( struct pcap
*pcap
, int enable
)
1180 struct set_rfmon_params params
;
1182 TRACE( "%p, %d\n", pcap
, enable
);
1184 if (!pcap
) return PCAP_ERROR
;
1185 params
.handle
= pcap
->handle
;
1186 params
.enable
= enable
;
1187 return PCAP_CALL( set_rfmon
, ¶ms
);
1190 int CDECL
pcap_set_snaplen( struct pcap
*pcap
, int len
)
1192 struct set_snaplen_params params
;
1194 TRACE( "%p, %d\n", pcap
, len
);
1196 if (!pcap
) return PCAP_ERROR
;
1197 params
.handle
= pcap
->handle
;
1199 return PCAP_CALL( set_snaplen
, ¶ms
);
1202 int CDECL
pcap_set_timeout( struct pcap
*pcap
, int timeout
)
1204 struct set_timeout_params params
;
1206 TRACE( "%p, %d\n", pcap
, timeout
);
1208 if (!pcap
) return PCAP_ERROR
;
1209 params
.handle
= pcap
->handle
;
1210 params
.timeout
= timeout
;
1211 return PCAP_CALL( set_timeout
, ¶ms
);
1214 int CDECL
pcap_set_tstamp_precision( struct pcap
*pcap
, int precision
)
1216 struct set_tstamp_precision_params params
;
1218 TRACE( "%p, %d\n", pcap
, precision
);
1220 if (!pcap
) return PCAP_ERROR
;
1221 params
.handle
= pcap
->handle
;
1222 params
.precision
= precision
;
1223 return PCAP_CALL( set_tstamp_precision
, ¶ms
);
1226 int CDECL
pcap_set_tstamp_type( struct pcap
*pcap
, int type
)
1228 struct set_tstamp_type_params params
;
1230 TRACE( "%p, %d\n", pcap
, type
);
1232 if (!pcap
) return PCAP_ERROR
;
1233 params
.handle
= pcap
->handle
;
1235 return PCAP_CALL( set_tstamp_type
, ¶ms
);
1238 int CDECL
pcap_setbuff( struct pcap
*pcap
, int size
)
1240 FIXME( "%p, %d\n", pcap
, size
);
1244 int CDECL
pcap_setfilter( struct pcap
*pcap
, struct bpf_program
*program
)
1246 struct setfilter_params params
;
1248 TRACE( "%p, %p\n", pcap
, program
);
1250 if (!pcap
) return PCAP_ERROR
;
1251 params
.handle
= pcap
->handle
;
1252 params
.program_len
= program
->bf_len
;
1253 params
.program_insns
= program
->bf_insns
;
1254 return PCAP_CALL( setfilter
, ¶ms
);
1257 int CDECL
pcap_setnonblock( struct pcap
*pcap
, int nonblock
, char *errbuf
)
1259 struct setnonblock_params params
;
1261 TRACE( "%p, %d, %p\n", pcap
, nonblock
, errbuf
);
1263 if (!pcap
) return PCAP_ERROR
;
1264 params
.handle
= pcap
->handle
;
1265 params
.nonblock
= nonblock
;
1266 params
.errbuf
= errbuf
;
1267 return PCAP_CALL( setnonblock
, ¶ms
);
1270 int CDECL
pcap_snapshot( struct pcap
*pcap
)
1272 struct snapshot_params params
;
1274 TRACE( "%p\n", pcap
);
1276 if (!pcap
) return PCAP_ERROR
;
1277 params
.handle
= pcap
->handle
;
1278 return PCAP_CALL( snapshot
, ¶ms
);
1281 int CDECL
pcap_stats( struct pcap
*pcap
, struct pcap_stat_win32
*stat
)
1283 struct stats_params params
;
1286 TRACE( "%p, %p\n", pcap
, stat
);
1288 if (!pcap
) return PCAP_ERROR
;
1289 params
.handle
= pcap
->handle
;
1290 if (!(ret
= PCAP_CALL( stats
, ¶ms
))) *stat
= params
.stat
;
1294 const char * CDECL
pcap_statustostr( int status
)
1296 static char errbuf
[32];
1298 TRACE( "%d\n", status
);
1303 return "Generic warning";
1304 case PCAP_WARNING_TSTAMP_TYPE_NOTSUP
:
1305 return "That type of time stamp is not supported by that device";
1306 case PCAP_WARNING_PROMISC_NOTSUP
:
1307 return "That device doesn't support promiscuous mode";
1309 return "Generic error";
1310 case PCAP_ERROR_BREAK
:
1311 return "Loop terminated by pcap_breakloop";
1312 case PCAP_ERROR_NOT_ACTIVATED
:
1313 return "The pcap_t has not been activated";
1314 case PCAP_ERROR_ACTIVATED
:
1315 return "The setting can't be changed after the pcap_t is activated";
1316 case PCAP_ERROR_NO_SUCH_DEVICE
:
1317 return "No such device exists";
1319 sprintf( errbuf
, "Unknown error: %d", status
);
1324 int CDECL
pcap_tstamp_type_name_to_val( const char *name
)
1326 struct tstamp_type_name_to_val_params params
= { name
};
1327 TRACE( "%s\n", debugstr_a(name
) );
1328 return PCAP_CALL( tstamp_type_name_to_val
, ¶ms
);
1337 static void free_tstamp_types( void )
1340 for (i
= 0; i
< ARRAY_SIZE(tstamp_types
); i
++)
1342 free( tstamp_types
[i
].name
);
1343 tstamp_types
[i
].name
= NULL
;
1344 free( tstamp_types
[i
].description
);
1345 tstamp_types
[i
].description
= NULL
;
1349 const char * CDECL
pcap_tstamp_type_val_to_description( int type
)
1351 struct tstamp_type_val_to_description_params params
;
1352 unsigned int len
= 64;
1356 TRACE( "%d\n", type
);
1358 if (type
< 0 || type
>= ARRAY_SIZE(tstamp_types
))
1360 WARN( "unhandled tstamp type %d\n", type
);
1363 if (tstamp_types
[type
].description
) return tstamp_types
[type
].description
;
1365 if (!(params
.buf
= malloc( len
))) return NULL
;
1367 params
.buflen
= &len
;
1368 status
= PCAP_CALL( tstamp_type_val_to_description
, ¶ms
);
1369 if (status
== STATUS_SUCCESS
) return (tstamp_types
[type
].description
= params
.buf
);
1370 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.buf
, len
)))
1376 if (PCAP_CALL( tstamp_type_val_to_description
, ¶ms
))
1382 return (tstamp_types
[type
].description
= params
.buf
);
1385 const char * CDECL
pcap_tstamp_type_val_to_name( int type
)
1387 struct tstamp_type_val_to_name_params params
;
1388 unsigned int len
= 32;
1392 TRACE( "%d\n", type
);
1394 if (type
< 0 || type
>= ARRAY_SIZE(tstamp_types
))
1396 WARN( "unhandled tstamp type %d\n", type
);
1399 if (tstamp_types
[type
].name
) return tstamp_types
[type
].name
;
1401 if (!(params
.buf
= malloc( len
))) return NULL
;
1403 params
.buflen
= &len
;
1404 status
= PCAP_CALL( tstamp_type_val_to_name
, ¶ms
);
1405 if (status
== STATUS_SUCCESS
) return (tstamp_types
[type
].name
= params
.buf
);
1406 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.buf
, len
)))
1412 if (PCAP_CALL( tstamp_type_val_to_name
, ¶ms
))
1418 return (tstamp_types
[type
].name
= params
.buf
);
1421 int CDECL
pcap_wsockinit( void )
1425 if (WSAStartup( MAKEWORD(1, 1), &wsadata
)) return PCAP_ERROR
;
1429 #define PCAP_CHAR_ENC_LOCAL 0
1430 #define PCAP_CHAR_ENC_UTF_8 1
1431 #define PCAP_MMAP_32BIT 2
1433 int CDECL
pcap_init( unsigned int opt
, char *errbuf
)
1435 struct init_params params
;
1437 TRACE( "%u, %p\n", opt
, errbuf
);
1438 if (opt
== PCAP_CHAR_ENC_LOCAL
) FIXME( "need to convert to/from local encoding\n" );
1441 params
.errbuf
= errbuf
;
1442 return PCAP_CALL( init
, ¶ms
);
1445 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, void *reserved
)
1449 case DLL_PROCESS_ATTACH
:
1451 DisableThreadLibraryCalls( hinst
);
1452 if (__wine_init_unix_call()) ERR( "No pcap support, expect problems\n" );
1455 char errbuf
[PCAP_ERRBUF_SIZE
];
1456 struct init_params params
= { PCAP_CHAR_ENC_UTF_8
, errbuf
};
1459 if (PCAP_CALL( init
, ¶ms
) == PCAP_ERROR
)
1460 WARN( "failed to enable UTF-8 encoding %s\n", debugstr_a(errbuf
) );
1461 if (IsWow64Process( GetCurrentProcess(), &is_wow64
) && is_wow64
)
1463 params
.opt
= PCAP_MMAP_32BIT
;
1464 if (PCAP_CALL( init
, ¶ms
) == PCAP_ERROR
)
1465 WARN( "failed to enable 32-bit mmap() %s\n", debugstr_a(errbuf
) );
1470 case DLL_PROCESS_DETACH
:
1471 if (reserved
) break;
1473 free_tstamp_types();