| /* | |
| * WPcap.dll Proxy. | |
| * | |
| * Copyright 2011, 2014 André Hentschel | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include <pcap/pcap.h> | |
| /* pcap.h might define those: */ | |
| #undef SOCKET | |
| #undef INVALID_SOCKET | |
| #include "winsock2.h" | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(wpcap); | |
| WINE_DECLARE_DEBUG_CHANNEL(winediag); | |
| #ifndef PCAP_SRC_FILE_STRING | |
| #define PCAP_SRC_FILE_STRING "file://" | |
| #endif | |
| #ifndef PCAP_SRC_FILE | |
| #define PCAP_SRC_FILE 2 | |
| #endif | |
| #ifndef PCAP_SRC_IF_STRING | |
| #define PCAP_SRC_IF_STRING "rpcap://" | |
| #endif | |
| #ifndef PCAP_SRC_IFLOCAL | |
| #define PCAP_SRC_IFLOCAL 3 | |
| #endif | |
| void CDECL wine_pcap_breakloop(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return pcap_breakloop(p); | |
| } | |
| void CDECL wine_pcap_close(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| pcap_close(p); | |
| } | |
| int CDECL wine_pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, | |
| unsigned int mask) | |
| { | |
| TRACE("(%p %p %s %i %u)\n", p, program, debugstr_a(buf), optimize, mask); | |
| return pcap_compile(p, program, buf, optimize, mask); | |
| } | |
| int CDECL wine_pcap_datalink(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return pcap_datalink(p); | |
| } | |
| int CDECL wine_pcap_datalink_name_to_val(const char *name) | |
| { | |
| TRACE("(%s)\n", debugstr_a(name)); | |
| return pcap_datalink_name_to_val(name); | |
| } | |
| const char* CDECL wine_pcap_datalink_val_to_description(int dlt) | |
| { | |
| TRACE("(%i)\n", dlt); | |
| return pcap_datalink_val_to_description(dlt); | |
| } | |
| const char* CDECL wine_pcap_datalink_val_to_name(int dlt) | |
| { | |
| TRACE("(%i)\n", dlt); | |
| return pcap_datalink_val_to_name(dlt); | |
| } | |
| typedef struct | |
| { | |
| void (CALLBACK *pfn_cb)(u_char *, const struct pcap_pkthdr *, const u_char *); | |
| void *user_data; | |
| } PCAP_HANDLER_CALLBACK; | |
| static void pcap_handler_callback(u_char *user_data, const struct pcap_pkthdr *h, const u_char *p) | |
| { | |
| PCAP_HANDLER_CALLBACK *pcb; | |
| TRACE("(%p %p %p)\n", user_data, h, p); | |
| pcb = (PCAP_HANDLER_CALLBACK *)user_data; | |
| pcb->pfn_cb(pcb->user_data, h, p); | |
| TRACE("Callback COMPLETED\n"); | |
| } | |
| int CDECL wine_pcap_dispatch(pcap_t *p, int cnt, | |
| void (CALLBACK *callback)(u_char *, const struct pcap_pkthdr *, const u_char *), | |
| unsigned char *user) | |
| { | |
| TRACE("(%p %i %p %p)\n", p, cnt, callback, user); | |
| if (callback) | |
| { | |
| PCAP_HANDLER_CALLBACK pcb; | |
| pcb.pfn_cb = callback; | |
| pcb.user_data = user; | |
| return pcap_dispatch(p, cnt, pcap_handler_callback, (unsigned char *)&pcb); | |
| } | |
| return pcap_dispatch(p, cnt, NULL, user); | |
| } | |
| int CDECL wine_pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) | |
| { | |
| int ret; | |
| TRACE("(%p %p)\n", alldevsp, errbuf); | |
| ret = pcap_findalldevs(alldevsp, errbuf); | |
| if(alldevsp && !*alldevsp) | |
| ERR_(winediag)("Failed to access raw network (pcap), this requires special permissions.\n"); | |
| return ret; | |
| } | |
| int CDECL wine_pcap_findalldevs_ex(char *source, void *auth, pcap_if_t **alldevs, char *errbuf) | |
| { | |
| FIXME("(%s %p %p %p): partial stub\n", debugstr_a(source), auth, alldevs, errbuf); | |
| return wine_pcap_findalldevs(alldevs, errbuf); | |
| } | |
| void CDECL wine_pcap_freealldevs(pcap_if_t *alldevs) | |
| { | |
| TRACE("(%p)\n", alldevs); | |
| pcap_freealldevs(alldevs); | |
| } | |
| void CDECL wine_pcap_freecode(struct bpf_program *fp) | |
| { | |
| TRACE("(%p)\n", fp); | |
| return pcap_freecode(fp); | |
| } | |
| typedef struct _AirpcapHandle *PAirpcapHandle; | |
| PAirpcapHandle CDECL wine_pcap_get_airpcap_handle(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return NULL; | |
| } | |
| char* CDECL wine_pcap_geterr(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return pcap_geterr(p); | |
| } | |
| int CDECL wine_pcap_getnonblock(pcap_t *p, char *errbuf) | |
| { | |
| TRACE("(%p %p)\n", p, errbuf); | |
| return pcap_getnonblock(p, errbuf); | |
| } | |
| const char* CDECL wine_pcap_lib_version(void) | |
| { | |
| const char* ret = pcap_lib_version(); | |
| TRACE("%s\n", debugstr_a(ret)); | |
| return ret; | |
| } | |
| int CDECL wine_pcap_list_datalinks(pcap_t *p, int **dlt_buffer) | |
| { | |
| TRACE("(%p %p)\n", p, dlt_buffer); | |
| return pcap_list_datalinks(p, dlt_buffer); | |
| } | |
| char* CDECL wine_pcap_lookupdev(char *errbuf) | |
| { | |
| TRACE("(%p)\n", errbuf); | |
| return pcap_lookupdev(errbuf); | |
| } | |
| int CDECL wine_pcap_lookupnet(const char *device, unsigned int *netp, unsigned int *maskp, | |
| char *errbuf) | |
| { | |
| TRACE("(%s %p %p %p)\n", debugstr_a(device), netp, maskp, errbuf); | |
| return pcap_lookupnet(device, netp, maskp, errbuf); | |
| } | |
| int CDECL wine_pcap_loop(pcap_t *p, int cnt, | |
| void (CALLBACK *callback)(u_char *, const struct pcap_pkthdr *, const u_char *), | |
| unsigned char *user) | |
| { | |
| TRACE("(%p %i %p %p)\n", p, cnt, callback, user); | |
| if (callback) | |
| { | |
| PCAP_HANDLER_CALLBACK pcb; | |
| pcb.pfn_cb = callback; | |
| pcb.user_data = user; | |
| return pcap_loop(p, cnt, pcap_handler_callback, (unsigned char *)&pcb); | |
| } | |
| return pcap_loop(p, cnt, NULL, user); | |
| } | |
| int CDECL wine_pcap_major_version(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return pcap_major_version(p); | |
| } | |
| int CDECL wine_pcap_minor_version(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return pcap_minor_version(p); | |
| } | |
| const unsigned char* CDECL wine_pcap_next(pcap_t *p, struct pcap_pkthdr *h) | |
| { | |
| TRACE("(%p %p)\n", p, h); | |
| return pcap_next(p, h); | |
| } | |
| int CDECL wine_pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const unsigned char **pkt_data) | |
| { | |
| TRACE("(%p %p %p)\n", p, pkt_header, pkt_data); | |
| return pcap_next_ex(p, pkt_header, pkt_data); | |
| } | |
| #define PCAP_OPENFLAG_PROMISCUOUS 1 | |
| pcap_t* CDECL wine_pcap_open(const char *source, int snaplen, int flags, int read_timeout, | |
| void *auth, char *errbuf) | |
| { | |
| int promisc = flags & PCAP_OPENFLAG_PROMISCUOUS; | |
| FIXME("(%s %i %i %i %p %p): partial stub\n", debugstr_a(source), snaplen, flags, read_timeout, | |
| auth, errbuf); | |
| return pcap_open_live(source, snaplen, promisc, read_timeout, errbuf); | |
| } | |
| pcap_t* CDECL wine_pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, | |
| char *errbuf) | |
| { | |
| TRACE("(%s %i %i %i %p)\n", debugstr_a(source), snaplen, promisc, to_ms, errbuf); | |
| return pcap_open_live(source, snaplen, promisc, to_ms, errbuf); | |
| } | |
| int CDECL wine_pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf) | |
| { | |
| int t = PCAP_SRC_IFLOCAL; | |
| const char *p = source; | |
| FIXME("(%s %p %p %p %p %p): partial stub\n", debugstr_a(source), type, host, port, name, errbuf); | |
| if (host) | |
| *host = '\0'; | |
| if (port) | |
| *port = '\0'; | |
| if (name) | |
| *name = '\0'; | |
| if (!strncmp(p, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING))) | |
| p += strlen(PCAP_SRC_IF_STRING); | |
| else if (!strncmp(p, PCAP_SRC_FILE_STRING, strlen(PCAP_SRC_FILE_STRING))) | |
| { | |
| p += strlen(PCAP_SRC_FILE_STRING); | |
| t = PCAP_SRC_FILE; | |
| } | |
| if (type) | |
| *type = t; | |
| if (!*p) | |
| { | |
| if (errbuf) | |
| sprintf(errbuf, "The name has not been specified in the source string."); | |
| return -1; | |
| } | |
| if (name) | |
| strcpy(name, p); | |
| return 0; | |
| } | |
| int CDECL wine_pcap_sendpacket(pcap_t *p, const unsigned char *buf, int size) | |
| { | |
| TRACE("(%p %p %i)\n", p, buf, size); | |
| return pcap_sendpacket(p, buf, size); | |
| } | |
| int CDECL wine_pcap_set_datalink(pcap_t *p, int dlt) | |
| { | |
| TRACE("(%p %i)\n", p, dlt); | |
| return pcap_set_datalink(p, dlt); | |
| } | |
| int CDECL wine_pcap_setbuff(pcap_t * p, int dim) | |
| { | |
| FIXME("(%p %i) stub\n", p, dim); | |
| return 0; | |
| } | |
| int CDECL wine_pcap_setfilter(pcap_t *p, struct bpf_program *fp) | |
| { | |
| TRACE("(%p %p)\n", p, fp); | |
| return pcap_setfilter(p, fp); | |
| } | |
| int CDECL wine_pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) | |
| { | |
| TRACE("(%p %i %p)\n", p, nonblock, errbuf); | |
| return pcap_setnonblock(p, nonblock, errbuf); | |
| } | |
| int CDECL wine_pcap_snapshot(pcap_t *p) | |
| { | |
| TRACE("(%p)\n", p); | |
| return pcap_snapshot(p); | |
| } | |
| int CDECL wine_pcap_stats(pcap_t *p, struct pcap_stat *ps) | |
| { | |
| TRACE("(%p %p)\n", p, ps); | |
| return pcap_stats(p, ps); | |
| } | |
| int CDECL wine_wsockinit(void) | |
| { | |
| WSADATA wsadata; | |
| TRACE("()\n"); | |
| if (WSAStartup(MAKEWORD(1,1), &wsadata)) return -1; | |
| return 0; | |
| } |