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 )
395 IP_ADAPTER_ADDRESSES
*ret
;
396 ULONG flags
= GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
| GAA_FLAG_SKIP_DNS_SERVER
;
398 if (GetAdaptersAddresses( AF_UNSPEC
, flags
, NULL
, NULL
, &size
) != ERROR_BUFFER_OVERFLOW
) return NULL
;
399 if (!(ret
= malloc( size
))) return NULL
;
400 if (GetAdaptersAddresses( AF_UNSPEC
, flags
, NULL
, ret
, &size
))
408 static IP_ADAPTER_ADDRESSES
*find_adapter( IP_ADAPTER_ADDRESSES
*list
, const char *name
)
410 IP_ADAPTER_ADDRESSES
*ret
;
413 if (!(nameW
= strdup_from_utf8( name
))) return NULL
;
414 for (ret
= list
; ret
; ret
= ret
->Next
)
416 if (!wcscmp( nameW
, ret
->FriendlyName
)) break;
422 static char *build_win32_name( const char *source
, const char *adapter_name
)
424 const char prefix
[] = "\\Device\\NPF_";
425 int len
= sizeof(prefix
) + strlen(adapter_name
);
428 if (source
) len
+= strlen( source
);
429 if ((ret
= malloc( len
)))
432 if (source
) strcat( ret
, source
);
433 strcat( ret
, prefix
);
434 strcat( ret
, adapter_name
);
439 static char *build_win32_description( const struct pcap_interface_offsets
*unix_dev
)
441 const char *name
= (const char *)unix_dev
+ unix_dev
->name_offset
;
442 const char *description
= (const char *)unix_dev
+ unix_dev
->description_offset
;
443 int len
= unix_dev
->name_len
+ unix_dev
->description_len
+ 1;
446 if ((ret
= malloc( len
)))
448 if (unix_dev
->description_len
)
450 strcpy( ret
, description
);
454 else strcpy( ret
, name
);
459 static struct sockaddr
*get_address( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
461 struct sockaddr
*ret
;
462 if (!(ret
= malloc( addr
->Address
.iSockaddrLength
))) return NULL
;
463 memcpy( ret
, addr
->Address
.lpSockaddr
, addr
->Address
.iSockaddrLength
);
467 static void convert_length_to_ipv6_mask( ULONG length
, IN6_ADDR
*mask
)
470 for (i
= 0; i
< length
/ 8 - 1; i
++) mask
->u
.Byte
[i
] = 0xff;
471 mask
->u
.Byte
[i
] = 0xff << (8 - length
% 8);
474 static struct sockaddr
*get_netmask( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
476 struct sockaddr
*ret
;
478 switch (addr
->Address
.lpSockaddr
->sa_family
)
482 struct sockaddr_in
*netmask_addr_in
;
484 if (!(netmask_addr_in
= calloc( 1, sizeof(*netmask_addr_in
) ))) return NULL
;
485 netmask_addr_in
->sin_family
= AF_INET
;
486 ConvertLengthToIpv4Mask( addr
->OnLinkPrefixLength
, &netmask_addr_in
->sin_addr
.S_un
.S_addr
);
487 ret
= (struct sockaddr
*)netmask_addr_in
;
492 struct sockaddr_in6
*netmask_addr_in6
;
494 if (!(netmask_addr_in6
= calloc( 1, sizeof(*netmask_addr_in6
) ))) return NULL
;
495 netmask_addr_in6
->sin6_family
= AF_INET6
;
496 convert_length_to_ipv6_mask( addr
->OnLinkPrefixLength
, &netmask_addr_in6
->sin6_addr
);
497 ret
= (struct sockaddr
*)netmask_addr_in6
;
501 FIXME( "address family %u not supported\n", addr
->Address
.lpSockaddr
->sa_family
);
508 static struct sockaddr
*get_broadcast( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
510 struct sockaddr
*ret
;
512 switch (addr
->Address
.lpSockaddr
->sa_family
)
516 struct sockaddr_in
*broadcast_addr_in
, *addr_in
= (struct sockaddr_in
*)addr
->Address
.lpSockaddr
;
519 if (!(broadcast_addr_in
= calloc( 1, sizeof(*broadcast_addr_in
) ))) return FALSE
;
520 broadcast_addr_in
->sin_family
= AF_INET
;
521 ConvertLengthToIpv4Mask( addr
->OnLinkPrefixLength
, &netmask
);
522 broadcast_addr_in
->sin_addr
.S_un
.S_addr
= addr_in
->sin_addr
.S_un
.S_addr
| ~netmask
;
523 ret
= (struct sockaddr
*)broadcast_addr_in
;
528 struct sockaddr_in6
*broadcast_addr_in6
, *addr_in6
= (struct sockaddr_in6
*)addr
->Address
.lpSockaddr
;
529 IN6_ADDR netmask
, *address
= (IN6_ADDR
*)&addr_in6
->sin6_addr
;
532 if (!(broadcast_addr_in6
= calloc( 1, sizeof(*broadcast_addr_in6
) ))) return NULL
;
533 broadcast_addr_in6
->sin6_family
= AF_INET6
;
534 convert_length_to_ipv6_mask( addr
->OnLinkPrefixLength
, &netmask
);
535 for (i
= 0; i
< 8; i
++) broadcast_addr_in6
->sin6_addr
.u
.Word
[i
] = address
->u
.Word
[i
] | ~netmask
.u
.Word
[i
];
536 ret
= (struct sockaddr
*)broadcast_addr_in6
;
540 FIXME( "address family %u not supported\n", addr
->Address
.lpSockaddr
->sa_family
);
547 static struct pcap_address
*build_win32_address( const IP_ADAPTER_UNICAST_ADDRESS
*addr
)
549 struct pcap_address
*ret
;
551 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
552 if (!(ret
->addr
= get_address( addr
))) goto err
;
553 if (!(ret
->netmask
= get_netmask( addr
))) goto err
;
554 if (!(ret
->broadaddr
= get_broadcast( addr
))) goto err
;
559 free( ret
->netmask
);
560 free( ret
->broadaddr
);
565 static void add_win32_address( struct pcap_address
**list
, struct pcap_address
*addr
)
567 struct pcap_address
*cur
= *list
;
568 if (!cur
) *list
= addr
;
571 while (cur
->next
) { cur
= cur
->next
; }
576 static struct pcap_address
*build_win32_addresses( const IP_ADAPTER_ADDRESSES
*adapter
)
578 struct pcap_address
*dst
, *ret
= NULL
;
579 IP_ADAPTER_UNICAST_ADDRESS
*src
= adapter
->FirstUnicastAddress
;
582 if ((dst
= build_win32_address( src
))) add_win32_address( &ret
, dst
);
588 static struct pcap_interface
*build_win32_device( const struct pcap_interface_offsets
*unix_dev
, const char *source
,
589 const IP_ADAPTER_ADDRESSES
*adapter
)
591 struct pcap_interface
*ret
;
593 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
594 if (!(ret
->name
= build_win32_name( source
, adapter
->AdapterName
))) goto err
;
595 if (!(ret
->description
= build_win32_description( unix_dev
))) goto err
;
596 ret
->addresses
= build_win32_addresses( adapter
);
597 ret
->flags
= unix_dev
->flags
;
602 free( ret
->description
);
603 free_addresses( ret
->addresses
);
608 static void add_win32_device( struct pcap_interface
**list
, struct pcap_interface
*dev
)
610 struct pcap_interface
*cur
= *list
;
611 if (!cur
) *list
= dev
;
614 while (cur
->next
) { cur
= cur
->next
; }
619 static int find_all_devices( const char *source
, struct pcap_interface
**devs
, char *errbuf
)
621 struct pcap_interface
*win32_devs
= NULL
, *dst
;
622 const struct pcap_interface_offsets
*src
;
623 IP_ADAPTER_ADDRESSES
*ptr
, *adapters
;
624 struct findalldevs_params params
;
625 unsigned int len_total
= 0, len
= 512;
628 if (!(params
.buf
= malloc( len
))) return PCAP_ERROR
;
629 params
.buflen
= &len
;
630 params
.errbuf
= errbuf
;
634 if ((ret
= PCAP_CALL( findalldevs
, ¶ms
)) != STATUS_BUFFER_TOO_SMALL
) break;
635 if (!(tmp
= realloc( params
.buf
, *params
.buflen
)))
648 if (!(adapters
= get_adapters()))
654 src
= (const struct pcap_interface_offsets
*)params
.buf
;
657 const char *name
= (const char *)src
+ src
->name_offset
;
658 unsigned int len_src
= sizeof(*src
) + src
->name_len
+ src
->description_len
;
660 if ((ptr
= find_adapter( adapters
, name
)) && (dst
= build_win32_device( src
, source
, ptr
)))
662 add_win32_device( &win32_devs
, dst
);
665 len_total
+= len_src
;
666 if (len_total
>= *params
.buflen
) break;
667 src
= (const struct pcap_interface_offsets
*)((const char *)src
+ len_src
);
676 int CDECL
pcap_findalldevs( struct pcap_interface
**devs
, char *errbuf
)
678 TRACE( "%p, %p\n", devs
, errbuf
);
679 return find_all_devices( NULL
, devs
, errbuf
);
682 int CDECL
pcap_findalldevs_ex( char *source
, void *auth
, struct pcap_interface
**devs
, char *errbuf
)
684 FIXME( "%s, %p, %p, %p: partial stub\n", debugstr_a(source
), auth
, devs
, errbuf
);
685 return find_all_devices( source
, devs
, errbuf
);
688 void CDECL
pcap_free_datalinks( int *links
)
690 TRACE( "%p\n", links
);
694 void CDECL
pcap_free_tstamp_types( int *types
)
696 TRACE( "%p\n", types
);
700 void CDECL
pcap_freealldevs( struct pcap_interface
*devs
)
702 TRACE( "%p\n", devs
);
703 free_devices( devs
);
706 void CDECL
pcap_freecode( struct bpf_program
*program
)
708 TRACE( "%p\n", program
);
710 if (!program
) return;
711 free( program
->bf_insns
);
714 void * CDECL
pcap_get_airpcap_handle( struct pcap
*pcap
)
716 TRACE( "%p\n", pcap
);
720 int CDECL
pcap_get_tstamp_precision( struct pcap
*pcap
)
722 struct get_tstamp_precision_params params
;
724 TRACE( "%p\n", pcap
);
726 if (!pcap
) return PCAP_ERROR
;
727 params
.handle
= pcap
->handle
;
728 return PCAP_CALL( get_tstamp_precision
, ¶ms
);
731 char * CDECL
pcap_geterr( struct pcap
*pcap
)
733 struct geterr_params params
;
735 TRACE( "%p\n", pcap
);
737 if (!pcap
) return NULL
;
738 params
.handle
= pcap
->handle
;
739 params
.errbuf
= pcap
->errbuf
;
740 PCAP_CALL( geterr
, ¶ms
);
741 return pcap
->errbuf
; /* FIXME: keep up-to-date */
744 int CDECL
pcap_getnonblock( struct pcap
*pcap
, char *errbuf
)
746 struct getnonblock_params params
;
748 TRACE( "%p, %p\n", pcap
, errbuf
);
750 if (!pcap
) return PCAP_ERROR
;
751 params
.handle
= pcap
->handle
;
752 params
.errbuf
= errbuf
;
753 return PCAP_CALL( getnonblock
, ¶ms
);
756 static char lib_version
[256];
757 static BOOL WINAPI
init_lib_version( INIT_ONCE
*once
, void *param
, void **ctx
)
759 struct lib_version_params params
= { lib_version
, sizeof(lib_version
) };
760 PCAP_CALL( lib_version
, ¶ms
);
764 const char * CDECL
pcap_lib_version( void )
766 static INIT_ONCE once
= INIT_ONCE_STATIC_INIT
;
767 if (!lib_version
[0]) InitOnceExecuteOnce( &once
, init_lib_version
, NULL
, NULL
);
768 TRACE( "%s\n", debugstr_a(lib_version
) );
772 int CDECL
pcap_list_datalinks( struct pcap
*pcap
, int **links
)
774 struct list_datalinks_params params
;
778 TRACE( "%p, %p\n", pcap
, links
);
780 if (!pcap
|| !links
) return PCAP_ERROR
;
782 if (!(params
.links
= malloc( count
* sizeof(*params
.links
) ))) return PCAP_ERROR
;
783 params
.handle
= pcap
->handle
;
784 params
.count
= &count
;
785 if ((status
= PCAP_CALL( list_datalinks
, ¶ms
)) == STATUS_SUCCESS
)
787 if (count
> 0) *links
= params
.links
;
790 free( params
.links
);
795 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.links
, count
* sizeof(*tmp
) )))
797 free( params
.links
);
801 if (PCAP_CALL( list_datalinks
, ¶ms
))
803 free( params
.links
);
806 *links
= params
.links
;
810 int CDECL
pcap_list_tstamp_types( struct pcap
*pcap
, int **types
)
812 struct list_tstamp_types_params params
;
816 TRACE( "%p, %p\n", pcap
, types
);
818 TRACE( "%p, %p\n", pcap
, types
);
820 if (!pcap
|| !types
) return PCAP_ERROR
;
822 if (!(params
.types
= malloc( count
* sizeof(*params
.types
) ))) return PCAP_ERROR
;
823 params
.handle
= pcap
->handle
;
824 params
.count
= &count
;
825 if ((status
= PCAP_CALL( list_tstamp_types
, ¶ms
)) == STATUS_SUCCESS
)
827 if (count
> 0) *types
= params
.types
;
830 free( params
.types
);
835 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.types
, count
* sizeof(*tmp
) )))
837 free( params
.types
);
841 if (PCAP_CALL( list_tstamp_types
, ¶ms
))
843 free( params
.types
);
846 *types
= params
.types
;
850 char * CDECL
pcap_lookupdev( char *errbuf
)
853 struct pcap_interface
*devs
;
855 TRACE( "%p\n", errbuf
);
858 if (pcap_findalldevs( &devs
, errbuf
) == PCAP_ERROR
|| !devs
) return NULL
;
859 if ((ret
= malloc( strlen(devs
->name
) + 1 ))) strcpy( ret
, devs
->name
);
860 pcap_freealldevs( devs
);
865 static char *strdup_to_utf8( const WCHAR
*src
)
868 int len
= WideCharToMultiByte( CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
869 if ((dst
= malloc( len
))) WideCharToMultiByte( CP_UTF8
, 0, src
, -1, dst
, len
, NULL
, NULL
);
873 static char *map_win32_device_name( const char *dev
)
875 IP_ADAPTER_ADDRESSES
*ptr
, *adapters
= get_adapters();
876 const char *name
= strchr( dev
, '{' );
879 if (!adapters
|| !name
) return NULL
;
880 for (ptr
= adapters
; ptr
; ptr
= ptr
->Next
)
882 if (!strcmp( name
, ptr
->AdapterName
))
884 ret
= strdup_to_utf8( ptr
->FriendlyName
);
892 int CDECL
pcap_lookupnet( const char *device
, unsigned int *net
, unsigned int *mask
, char *errbuf
)
894 struct lookupnet_params params
;
897 TRACE( "%s, %p, %p, %p\n", debugstr_a(device
), net
, mask
, errbuf
);
899 if (!(params
.device
= map_win32_device_name( device
)))
901 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
906 params
.errbuf
= errbuf
;
907 ret
= PCAP_CALL( lookupnet
, ¶ms
);
908 free( params
.device
);
912 int CDECL
pcap_major_version( struct pcap
*pcap
)
914 struct major_version_params params
;
916 TRACE( "%p\n", pcap
);
918 if (!pcap
) return PCAP_ERROR
;
919 params
.handle
= pcap
->handle
;
920 return PCAP_CALL( major_version
, ¶ms
);
923 int CDECL
pcap_minor_version( struct pcap
*pcap
)
925 struct minor_version_params params
;
927 TRACE( "%p\n", pcap
);
929 if (!pcap
) return PCAP_ERROR
;
930 params
.handle
= pcap
->handle
;
931 return PCAP_CALL( minor_version
, ¶ms
);
934 int CDECL
pcap_next_ex( struct pcap
*pcap
, struct pcap_pkthdr_win32
**hdr
, const unsigned char **data
)
936 struct next_ex_params params
;
939 TRACE( "%p, %p, %p\n", pcap
, hdr
, data
);
941 if (!pcap
) return PCAP_ERROR
;
942 params
.handle
= pcap
->handle
;
943 params
.hdr
= &pcap
->hdr
;
945 if ((ret
= PCAP_CALL( next_ex
, ¶ms
)) == 1) *hdr
= &pcap
->hdr
;
949 const unsigned char * CDECL
pcap_next( struct pcap
*pcap
, struct pcap_pkthdr_win32
*hdr
)
951 struct pcap_pkthdr_win32
*hdr_ptr
;
952 const unsigned char *data
;
954 if (pcap_next_ex( pcap
, &hdr_ptr
, &data
) == 1)
962 int CDECL
pcap_dispatch( struct pcap
*pcap
, int count
,
963 void (CALLBACK
*callback
)(unsigned char *, const struct pcap_pkthdr_win32
*, const unsigned char *),
964 unsigned char *user
)
968 TRACE( "%p, %d, %p, %p\n", pcap
, count
, callback
, user
);
970 while (processed
< count
)
972 struct pcap_pkthdr_win32
*hdr
= NULL
;
973 const unsigned char *data
= NULL
;
975 int ret
= pcap_next_ex( pcap
, &hdr
, &data
);
981 else if (ret
== PCAP_ERROR_BREAK
)
983 if (processed
== 0) return PCAP_ERROR_BREAK
;
989 callback( user
, hdr
, data
);
995 int CDECL
pcap_loop( struct pcap
*pcap
, int count
,
996 void (CALLBACK
*callback
)(unsigned char *, const struct pcap_pkthdr_win32
*, const unsigned char *),
1001 TRACE( "%p, %d, %p, %p\n", pcap
, count
, callback
, user
);
1003 while (processed
< count
)
1005 struct pcap_pkthdr_win32
*hdr
= NULL
;
1006 const unsigned char *data
= NULL
;
1008 int ret
= pcap_next_ex( pcap
, &hdr
, &data
);
1014 else if (ret
== PCAP_ERROR_BREAK
)
1016 if (processed
== 0) return PCAP_ERROR_BREAK
;
1022 callback( user
, hdr
, data
);
1028 struct pcap
* CDECL
pcap_create( const char *source
, char *errbuf
)
1031 struct create_params params
;
1033 TRACE( "%s, %p\n", source
, errbuf
);
1035 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
1037 if (!(params
.source
= map_win32_device_name( source
)))
1039 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
1043 params
.errbuf
= errbuf
;
1044 params
.handle
= &ret
->handle
;
1045 if (PCAP_CALL( create
, ¶ms
))
1050 free( params
.source
);
1054 static struct pcap
*open_live( const char *source
, int snaplen
, int promisc
, int timeout
, char *errbuf
)
1057 struct open_live_params params
;
1059 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
1061 if (!(params
.source
= map_win32_device_name( source
)))
1063 if (errbuf
) sprintf( errbuf
, "Unable to open the adapter." );
1067 params
.snaplen
= snaplen
;
1068 params
.promisc
= promisc
;
1069 params
.timeout
= timeout
;
1070 params
.errbuf
= errbuf
;
1071 params
.handle
= &ret
->handle
;
1072 if (PCAP_CALL( open_live
, ¶ms
))
1077 free( params
.source
);
1081 #define PCAP_OPENFLAG_PROMISCUOUS 1
1082 struct pcap
* CDECL
pcap_open( const char *source
, int snaplen
, int flags
, int timeout
, void *auth
, char *errbuf
)
1084 FIXME( "%s, %d, %d, %d, %p, %p: partial stub\n", debugstr_a(source
), snaplen
, flags
, timeout
, auth
, errbuf
);
1085 return open_live( source
, snaplen
, flags
& PCAP_OPENFLAG_PROMISCUOUS
, timeout
, errbuf
);
1088 struct pcap
* CDECL
pcap_open_live( const char *source
, int snaplen
, int promisc
, int to_ms
, char *errbuf
)
1090 TRACE( "%s, %d, %d, %d, %p\n", debugstr_a(source
), snaplen
, promisc
, to_ms
, errbuf
);
1091 return open_live( source
, snaplen
, promisc
, to_ms
, errbuf
);
1094 #define PCAP_SRC_FILE 2
1095 #define PCAP_SRC_IFLOCAL 3
1097 int CDECL
pcap_parsesrcstr( const char *source
, int *ret_type
, char *host
, char *port
, char *name
, char *errbuf
)
1099 int type
= PCAP_SRC_IFLOCAL
;
1100 const char *ptr
= source
;
1102 FIXME( "%s, %p, %p, %p, %p, %p: partial stub\n", debugstr_a(source
), ret_type
, host
, port
, name
, errbuf
);
1104 if (host
) *host
= 0;
1105 if (port
) *port
= 0;
1106 if (name
) *name
= 0;
1108 if (!strncmp( ptr
, "rpcap://", strlen("rpcap://"))) ptr
+= strlen( "rpcap://" );
1109 else if (!strncmp( ptr
, "file://", strlen("file://") ))
1111 ptr
+= strlen( "file://" );
1112 type
= PCAP_SRC_FILE
;
1115 if (ret_type
) *ret_type
= type
;
1118 if (errbuf
) sprintf( errbuf
, "The name has not been specified in the source string." );
1122 if (name
) strcpy( name
, ptr
);
1126 int CDECL
pcap_sendpacket( struct pcap
*pcap
, const unsigned char *buf
, int size
)
1128 struct sendpacket_params params
;
1130 TRACE( "%p, %p, %d\n", pcap
, buf
, size
);
1132 if (!pcap
) return PCAP_ERROR
;
1133 params
.handle
= pcap
->handle
;
1136 return PCAP_CALL( sendpacket
, ¶ms
);
1139 int CDECL
pcap_set_buffer_size( struct pcap
*pcap
, int size
)
1141 struct set_buffer_size_params params
;
1143 TRACE( "%p, %d\n", pcap
, size
);
1145 if (!pcap
) return PCAP_ERROR
;
1146 params
.handle
= pcap
->handle
;
1148 return PCAP_CALL( set_buffer_size
, ¶ms
);
1151 int CDECL
pcap_set_datalink( struct pcap
*pcap
, int link
)
1153 struct set_datalink_params params
;
1155 TRACE( "%p, %d\n", pcap
, link
);
1157 if (!pcap
) return PCAP_ERROR
;
1158 params
.handle
= pcap
->handle
;
1160 return PCAP_CALL( set_datalink
, ¶ms
);
1163 int CDECL
pcap_set_promisc( struct pcap
*pcap
, int enable
)
1165 struct set_promisc_params params
;
1167 TRACE( "%p, %d\n", pcap
, enable
);
1169 if (!pcap
) return PCAP_ERROR
;
1170 params
.handle
= pcap
->handle
;
1171 params
.enable
= enable
;
1172 return PCAP_CALL( set_promisc
, ¶ms
);
1175 int CDECL
pcap_set_rfmon( struct pcap
*pcap
, int enable
)
1177 struct set_rfmon_params params
;
1179 TRACE( "%p, %d\n", pcap
, enable
);
1181 if (!pcap
) return PCAP_ERROR
;
1182 params
.handle
= pcap
->handle
;
1183 params
.enable
= enable
;
1184 return PCAP_CALL( set_rfmon
, ¶ms
);
1187 int CDECL
pcap_set_snaplen( struct pcap
*pcap
, int len
)
1189 struct set_snaplen_params params
;
1191 TRACE( "%p, %d\n", pcap
, len
);
1193 if (!pcap
) return PCAP_ERROR
;
1194 params
.handle
= pcap
->handle
;
1196 return PCAP_CALL( set_snaplen
, ¶ms
);
1199 int CDECL
pcap_set_timeout( struct pcap
*pcap
, int timeout
)
1201 struct set_timeout_params params
;
1203 TRACE( "%p, %d\n", pcap
, timeout
);
1205 if (!pcap
) return PCAP_ERROR
;
1206 params
.handle
= pcap
->handle
;
1207 params
.timeout
= timeout
;
1208 return PCAP_CALL( set_timeout
, ¶ms
);
1211 int CDECL
pcap_set_tstamp_precision( struct pcap
*pcap
, int precision
)
1213 struct set_tstamp_precision_params params
;
1215 TRACE( "%p, %d\n", pcap
, precision
);
1217 if (!pcap
) return PCAP_ERROR
;
1218 params
.handle
= pcap
->handle
;
1219 params
.precision
= precision
;
1220 return PCAP_CALL( set_tstamp_precision
, ¶ms
);
1223 int CDECL
pcap_set_tstamp_type( struct pcap
*pcap
, int type
)
1225 struct set_tstamp_type_params params
;
1227 TRACE( "%p, %d\n", pcap
, type
);
1229 if (!pcap
) return PCAP_ERROR
;
1230 params
.handle
= pcap
->handle
;
1232 return PCAP_CALL( set_tstamp_type
, ¶ms
);
1235 int CDECL
pcap_setbuff( struct pcap
*pcap
, int size
)
1237 FIXME( "%p, %d\n", pcap
, size
);
1241 int CDECL
pcap_setfilter( struct pcap
*pcap
, struct bpf_program
*program
)
1243 struct setfilter_params params
;
1245 TRACE( "%p, %p\n", pcap
, program
);
1247 if (!pcap
) return PCAP_ERROR
;
1248 params
.handle
= pcap
->handle
;
1249 params
.program_len
= program
->bf_len
;
1250 params
.program_insns
= program
->bf_insns
;
1251 return PCAP_CALL( setfilter
, ¶ms
);
1254 int CDECL
pcap_setnonblock( struct pcap
*pcap
, int nonblock
, char *errbuf
)
1256 struct setnonblock_params params
;
1258 TRACE( "%p, %d, %p\n", pcap
, nonblock
, errbuf
);
1260 if (!pcap
) return PCAP_ERROR
;
1261 params
.handle
= pcap
->handle
;
1262 params
.nonblock
= nonblock
;
1263 params
.errbuf
= errbuf
;
1264 return PCAP_CALL( setnonblock
, ¶ms
);
1267 int CDECL
pcap_snapshot( struct pcap
*pcap
)
1269 struct snapshot_params params
;
1271 TRACE( "%p\n", pcap
);
1273 if (!pcap
) return PCAP_ERROR
;
1274 params
.handle
= pcap
->handle
;
1275 return PCAP_CALL( snapshot
, ¶ms
);
1278 int CDECL
pcap_stats( struct pcap
*pcap
, struct pcap_stat_win32
*stat
)
1280 struct stats_params params
;
1283 TRACE( "%p, %p\n", pcap
, stat
);
1285 if (!pcap
) return PCAP_ERROR
;
1286 params
.handle
= pcap
->handle
;
1287 if (!(ret
= PCAP_CALL( stats
, ¶ms
))) *stat
= params
.stat
;
1291 const char * CDECL
pcap_statustostr( int status
)
1293 static char errbuf
[32];
1295 TRACE( "%d\n", status
);
1300 return "Generic warning";
1301 case PCAP_WARNING_TSTAMP_TYPE_NOTSUP
:
1302 return "That type of time stamp is not supported by that device";
1303 case PCAP_WARNING_PROMISC_NOTSUP
:
1304 return "That device doesn't support promiscuous mode";
1306 return "Generic error";
1307 case PCAP_ERROR_BREAK
:
1308 return "Loop terminated by pcap_breakloop";
1309 case PCAP_ERROR_NOT_ACTIVATED
:
1310 return "The pcap_t has not been activated";
1311 case PCAP_ERROR_ACTIVATED
:
1312 return "The setting can't be changed after the pcap_t is activated";
1313 case PCAP_ERROR_NO_SUCH_DEVICE
:
1314 return "No such device exists";
1316 sprintf( errbuf
, "Unknown error: %d", status
);
1321 int CDECL
pcap_tstamp_type_name_to_val( const char *name
)
1323 struct tstamp_type_name_to_val_params params
= { name
};
1324 TRACE( "%s\n", debugstr_a(name
) );
1325 return PCAP_CALL( tstamp_type_name_to_val
, ¶ms
);
1334 static void free_tstamp_types( void )
1337 for (i
= 0; i
< ARRAY_SIZE(tstamp_types
); i
++)
1339 free( tstamp_types
[i
].name
);
1340 tstamp_types
[i
].name
= NULL
;
1341 free( tstamp_types
[i
].description
);
1342 tstamp_types
[i
].description
= NULL
;
1346 const char * CDECL
pcap_tstamp_type_val_to_description( int type
)
1348 struct tstamp_type_val_to_description_params params
;
1349 unsigned int len
= 64;
1353 TRACE( "%d\n", type
);
1355 if (type
< 0 || type
>= ARRAY_SIZE(tstamp_types
))
1357 WARN( "unhandled tstamp type %d\n", type
);
1360 if (tstamp_types
[type
].description
) return tstamp_types
[type
].description
;
1362 if (!(params
.buf
= malloc( len
))) return NULL
;
1364 params
.buflen
= &len
;
1365 status
= PCAP_CALL( tstamp_type_val_to_description
, ¶ms
);
1366 if (status
== STATUS_SUCCESS
) return (tstamp_types
[type
].description
= params
.buf
);
1367 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.buf
, len
)))
1373 if (PCAP_CALL( tstamp_type_val_to_description
, ¶ms
))
1379 return (tstamp_types
[type
].description
= params
.buf
);
1382 const char * CDECL
pcap_tstamp_type_val_to_name( int type
)
1384 struct tstamp_type_val_to_name_params params
;
1385 unsigned int len
= 32;
1389 TRACE( "%d\n", type
);
1391 if (type
< 0 || type
>= ARRAY_SIZE(tstamp_types
))
1393 WARN( "unhandled tstamp type %d\n", type
);
1396 if (tstamp_types
[type
].name
) return tstamp_types
[type
].name
;
1398 if (!(params
.buf
= malloc( len
))) return NULL
;
1400 params
.buflen
= &len
;
1401 status
= PCAP_CALL( tstamp_type_val_to_name
, ¶ms
);
1402 if (status
== STATUS_SUCCESS
) return (tstamp_types
[type
].name
= params
.buf
);
1403 if (status
!= STATUS_BUFFER_TOO_SMALL
|| !(tmp
= realloc( params
.buf
, len
)))
1409 if (PCAP_CALL( tstamp_type_val_to_name
, ¶ms
))
1415 return (tstamp_types
[type
].name
= params
.buf
);
1418 int CDECL
pcap_wsockinit( void )
1422 if (WSAStartup( MAKEWORD(1, 1), &wsadata
)) return PCAP_ERROR
;
1426 #define PCAP_CHAR_ENC_LOCAL 0
1427 #define PCAP_CHAR_ENC_UTF_8 1
1428 #define PCAP_MMAP_32BIT 2
1430 int CDECL
pcap_init( unsigned int opt
, char *errbuf
)
1432 struct init_params params
;
1434 TRACE( "%u, %p\n", opt
, errbuf
);
1435 if (opt
== PCAP_CHAR_ENC_LOCAL
) FIXME( "need to convert to/from local encoding\n" );
1438 params
.errbuf
= errbuf
;
1439 return PCAP_CALL( init
, ¶ms
);
1442 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, void *reserved
)
1446 case DLL_PROCESS_ATTACH
:
1448 DisableThreadLibraryCalls( hinst
);
1449 if (__wine_init_unix_call()) ERR( "No pcap support, expect problems\n" );
1452 char errbuf
[PCAP_ERRBUF_SIZE
];
1453 struct init_params params
= { PCAP_CHAR_ENC_UTF_8
, errbuf
};
1456 if (PCAP_CALL( init
, ¶ms
) == PCAP_ERROR
)
1457 WARN( "failed to enable UTF-8 encoding %s\n", debugstr_a(errbuf
) );
1458 if (IsWow64Process( GetCurrentProcess(), &is_wow64
) && is_wow64
)
1460 params
.opt
= PCAP_MMAP_32BIT
;
1461 if (PCAP_CALL( init
, ¶ms
) == PCAP_ERROR
)
1462 WARN( "failed to enable 32-bit mmap() %s\n", debugstr_a(errbuf
) );
1467 case DLL_PROCESS_DETACH
:
1468 if (reserved
) break;
1470 free_tstamp_types();