From: Guy Harris Date: Thu, 7 Sep 2017 02:21:01 +0000 (-0700) Subject: Move the ADAPTER * out of pcap_t into the pcap-win32.c private data. X-Git-Tag: libpcap-1.9-bp~764 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/9aadaa8c2c415ff0ee9cc2170ede277cb28108f9 Move the ADAPTER * out of pcap_t into the pcap-win32.c private data. That avoids leaking packet.dll stuff into the generic code. Have, instead, a HANDLE, and set it to the hFile member of the ADAPTER structure, so we can return it from pcap_fileno(). --- diff --git a/pcap-int.h b/pcap-int.h index acf386c0..36ce1b78 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -40,14 +40,7 @@ extern "C" { #endif -#if defined(_WIN32) - /* - * Make sure Packet32.h doesn't define BPF structures that we've - * probably already defined as a result of including . - */ - #define BPF_MAJOR_VERSION - #include -#elif defined(MSDOS) +#ifdef MSDOS #include #include #endif @@ -112,14 +105,21 @@ struct pcap_opt { int timeout; /* timeout for buffering */ u_int buffer_size; int promisc; -#ifdef __linux__ - int protocol; -#endif int rfmon; /* monitor mode */ int immediate; /* immediate mode - deliver packets as soon as they arrive */ int nonblock; /* non-blocking mode - don't wait for packets to be delivered, return "no packets available" */ int tstamp_type; int tstamp_precision; + + /* + * Platform-dependent options. + */ +#ifdef __linux__ + int protocol; /* protocol to use when creating PF_PACKET socket */ +#endif +#ifdef _WIN32 + int nocapture_local;/* disable NPF loopback */ +#endif }; typedef int (*activate_op_t)(pcap_t *); @@ -165,7 +165,7 @@ struct pcap { int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **); #ifdef _WIN32 - ADAPTER *adapter; + HANDLE handle; #else int fd; int selectable_fd; diff --git a/pcap-new.c b/pcap-new.c index d8fcd693..22964085 100644 --- a/pcap-new.c +++ b/pcap-new.c @@ -381,12 +381,6 @@ pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, if (status < 0) goto fail; } - status = pcap_set_timeout(fp, read_timeout); - if (status < 0) - goto fail; - status = pcap_activate(fp); - if (status < 0) - goto fail; #ifdef _WIN32 /* * This flag is supported on Windows only. @@ -397,20 +391,16 @@ pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, * injected with pcap_sendpacket() or * pcap_inject()". */ - if (fp->adapter != NULL) - { - /* disable loopback capture if requested */ - if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL) - { - if (!PacketSetLoopbackBehavior(fp->adapter, NPF_DISABLE_LOOPBACK)) - { - pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to disable the capture of loopback packets."); - pcap_close(fp); - return NULL; - } - } - } + /* disable loopback capture if requested */ + if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL) + p->opt.nocapture_local = 1; #endif /* _WIN32 */ + status = pcap_set_timeout(fp, read_timeout); + if (status < 0) + goto fail; + status = pcap_activate(fp); + if (status < 0) + goto fail; return fp; fail: diff --git a/pcap-win32.c b/pcap-win32.c index 4b3a18d3..c1d24879 100644 --- a/pcap-win32.c +++ b/pcap-win32.c @@ -72,6 +72,7 @@ static int pcap_setnonblock_win32(pcap_t *, int); * Private data for capturing on WinPcap devices. */ struct pcap_win { + ADAPTER *adapter; /* the packet32 ADAPTER for the device */ int nonblock; int rfmon_selfstart; /* a flag tells whether the monitor mode is set by itself */ int filtering_in_kernel; /* using kernel filter */ @@ -164,6 +165,7 @@ pcap_wsockinit(void) static int pcap_stats_win32(pcap_t *p, struct pcap_stat *ps) { + struct pcap_win *pw = p->priv; struct bpf_stat bstats; char errbuf[PCAP_ERRBUF_SIZE+1]; @@ -180,7 +182,7 @@ pcap_stats_win32(pcap_t *p, struct pcap_stat *ps) * in would stomp on whatever comes after the structure passed * to us. */ - if (!PacketGetStats(p->adapter, &bstats)) { + if (!PacketGetStats(pw->adapter, &bstats)) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", errbuf); @@ -226,6 +228,7 @@ pcap_stats_win32(pcap_t *p, struct pcap_stat *ps) struct pcap_stat * pcap_stats_ex_win32(pcap_t *p, int *pcap_stat_size) { + struct pcap_win *pw = p->priv; struct bpf_stat bstats; char errbuf[PCAP_ERRBUF_SIZE+1]; @@ -238,7 +241,7 @@ pcap_stats_ex_win32(pcap_t *p, int *pcap_stat_size) * WinPcap's "struct bpf_stat". It might currently have the * same layout, but let's not cheat.) */ - if (!PacketGetStatsEx(p->adapter, &bstats)) { + if (!PacketGetStatsEx(pw->adapter, &bstats)) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStatsEx error: %s", errbuf); @@ -257,7 +260,9 @@ pcap_stats_ex_win32(pcap_t *p, int *pcap_stat_size) static int pcap_setbuff_win32(pcap_t *p, int dim) { - if(PacketSetBuff(p->adapter,dim)==FALSE) + struct pcap_win *pw = p->priv; + + if(PacketSetBuff(pw->adapter,dim)==FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); return (-1); @@ -269,7 +274,9 @@ pcap_setbuff_win32(pcap_t *p, int dim) static int pcap_setmode_win32(pcap_t *p, int mode) { - if(PacketSetMode(p->adapter,mode)==FALSE) + struct pcap_win *pw = p->priv; + + if(PacketSetMode(pw->adapter,mode)==FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); return (-1); @@ -282,7 +289,9 @@ pcap_setmode_win32(pcap_t *p, int mode) static int pcap_setmintocopy_win32(pcap_t *p, int size) { - if(PacketSetMinToCopy(p->adapter, size)==FALSE) + struct pcap_win *pw = p->priv; + + if(PacketSetMinToCopy(pw->adapter, size)==FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); return (-1); @@ -293,12 +302,15 @@ pcap_setmintocopy_win32(pcap_t *p, int size) static HANDLE pcap_getevent_win32(pcap_t *p) { - return (PacketGetReadEvent(p->adapter)); + struct pcap_win *pw = p->priv; + + return (PacketGetReadEvent(pw->adapter)); } static int pcap_oid_get_request_win32(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp) { + struct pcap_win *pw = p->priv; PACKET_OID_DATA *oid_data_arg; char errbuf[PCAP_ERRBUF_SIZE+1]; @@ -321,7 +333,7 @@ pcap_oid_get_request_win32(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp) */ oid_data_arg->Oid = oid; oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */ - if (!PacketRequest(p->adapter, FALSE, oid_data_arg)) { + if (!PacketRequest(pw->adapter, FALSE, oid_data_arg)) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error calling PacketRequest: %s", errbuf); @@ -346,6 +358,7 @@ static int pcap_oid_set_request_win32(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp) { + struct pcap_win *pw = p->priv; PACKET_OID_DATA *oid_data_arg; char errbuf[PCAP_ERRBUF_SIZE+1]; @@ -366,7 +379,7 @@ pcap_oid_set_request_win32(pcap_t *p, bpf_u_int32 oid, const void *data, oid_data_arg->Oid = oid; oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */ memcpy(oid_data_arg->Data, data, *lenp); - if (!PacketRequest(p->adapter, TRUE, oid_data_arg)) { + if (!PacketRequest(pw->adapter, TRUE, oid_data_arg)) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error calling PacketRequest: %s", errbuf); @@ -389,16 +402,17 @@ pcap_oid_set_request_win32(pcap_t *p, bpf_u_int32 oid, const void *data, static u_int pcap_sendqueue_transmit_win32(pcap_t *p, pcap_send_queue *queue, int sync) { + struct pcap_win *pw = p->priv; u_int res; char errbuf[PCAP_ERRBUF_SIZE+1]; - if (p->adapter==NULL) { + if (2->adapter==NULL) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot transmit a queue to an offline capture or to a TurboCap port"); return (0); } - res = PacketSendPackets(p->adapter, + res = PacketSendPackets(pw->adapter, queue->buffer, queue->len, (BOOLEAN)sync); @@ -444,10 +458,11 @@ pcap_setuserbuffer_win32(pcap_t *p, int size) static int pcap_live_dump_win32(pcap_t *p, char *filename, int maxsize, int maxpacks) { + struct pcap_win *pw = p->priv; BOOLEAN res; /* Set the packet driver in dump mode */ - res = PacketSetMode(p->adapter, PACKET_MODE_DUMP); + res = PacketSetMode(pw->adapter, PACKET_MODE_DUMP); if(res == FALSE){ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error setting dump mode"); @@ -455,7 +470,7 @@ pcap_live_dump_win32(pcap_t *p, char *filename, int maxsize, int maxpacks) } /* Set the name of the dump file */ - res = PacketSetDumpName(p->adapter, filename, (int)strlen(filename)); + res = PacketSetDumpName(pw->adapter, filename, (int)strlen(filename)); if(res == FALSE){ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error setting kernel dump file name"); @@ -463,7 +478,7 @@ pcap_live_dump_win32(pcap_t *p, char *filename, int maxsize, int maxpacks) } /* Set the limits of the dump file */ - res = PacketSetDumpLimits(p->adapter, maxsize, maxpacks); + res = PacketSetDumpLimits(pw->adapter, maxsize, maxpacks); if(res == FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error setting dump limit"); @@ -476,14 +491,18 @@ pcap_live_dump_win32(pcap_t *p, char *filename, int maxsize, int maxpacks) static int pcap_live_dump_ended_win32(pcap_t *p, int sync) { - return (PacketIsDumpEnded(p->adapter, (BOOLEAN)sync)); + struct pcap_win *pw = p->priv; + + return (PacketIsDumpEnded(pw->adapter, (BOOLEAN)sync)); } static PAirpcapHandle pcap_get_airpcap_handle_win32(pcap_t *p) { #ifdef HAVE_AIRPCAP_API - return (PacketGetAirPcapHandle(p->adapter)); + struct pcap_win *pw = p->priv; + + return (PacketGetAirPcapHandle(pw->adapter)); #else return (NULL); #endif /* HAVE_AIRPCAP_API */ @@ -527,7 +546,7 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * the stack. */ PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize); - if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) { + if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (PCAP_ERROR); } @@ -665,7 +684,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) ULONGLONG ts; int cc; unsigned swt; - unsigned dfp = p->adapter->DagFastProcess; + unsigned dfp = pw->adapter->DagFastProcess; cc = p->cc; if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */ @@ -683,7 +702,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * the stack. */ PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize); - if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) { + if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (-1); } @@ -692,7 +711,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) if(cc == 0) /* The timeout has expired but we no packets arrived */ return (0); - header = (dag_record_t*)p->adapter->DagBuffer; + header = (dag_record_t*)pw->adapter->DagBuffer; } else header = (dag_record_t*)p->bp; @@ -828,10 +847,11 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) static int pcap_inject_win32(pcap_t *p, const void *buf, size_t size) { + struct pcap_win *pw = p->priv; PACKET pkt; PacketInitPacket(&pkt, (PVOID)buf, size); - if(PacketSendPacket(p->adapter,&pkt,TRUE) == FALSE) { + if(PacketSendPacket(pw->adapter,&pkt,TRUE) == FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed"); return (-1); } @@ -848,9 +868,10 @@ static void pcap_cleanup_win32(pcap_t *p) { struct pcap_win *pw = p->priv; - if (p->adapter != NULL) { - PacketCloseAdapter(p->adapter); - p->adapter = NULL; + + if (pw->adapter != NULL) { + PacketCloseAdapter(pw->adapter); + pw->adapter = NULL; } if (pw->rfmon_selfstart) { @@ -900,9 +921,9 @@ pcap_activate_win32(pcap_t *p) /* Init WinSock */ wsockinit(); - p->adapter = PacketOpenAdapter(p->opt.device); + pw->adapter = PacketOpenAdapter(p->opt.device); - if (p->adapter == NULL) + if (pw->adapter == NULL) { /* Adapter detected but we are not able to open it. Return failure. */ pcap_win32_err_to_str(GetLastError(), errbuf); @@ -916,7 +937,7 @@ pcap_activate_win32(pcap_t *p) } /*get network type*/ - if(PacketGetNetType (p->adapter,&type) == FALSE) + if(PacketGetNetType (pw->adapter,&type) == FALSE) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, @@ -1018,7 +1039,7 @@ pcap_activate_win32(pcap_t *p) if (p->opt.promisc) { - if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) + if (PacketSetHwFilter(pw->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode"); goto bad; @@ -1026,7 +1047,7 @@ pcap_activate_win32(pcap_t *p) } else { - if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) + if (PacketSetHwFilter(pw->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode"); goto bad; @@ -1036,7 +1057,7 @@ pcap_activate_win32(pcap_t *p) /* Set the buffer size */ p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE; - if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD)) + if(!(pw->adapter->Flags & INFO_FLAG_DAG_CARD)) { /* * Traditional Adapter @@ -1048,7 +1069,7 @@ pcap_activate_win32(pcap_t *p) if (p->opt.buffer_size == 0) p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE; - if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE) + if(PacketSetBuff(pw->adapter,p->opt.buffer_size)==FALSE) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); goto bad; @@ -1064,7 +1085,7 @@ pcap_activate_win32(pcap_t *p) if (p->opt.immediate) { /* tell the driver to copy the buffer as soon as data arrives */ - if(PacketSetMinToCopy(p->adapter,0)==FALSE) + if(PacketSetMinToCopy(pw->adapter,0)==FALSE) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, @@ -1076,7 +1097,7 @@ pcap_activate_win32(pcap_t *p) else { /* tell the driver to copy the buffer only if it contains at least 16K */ - if(PacketSetMinToCopy(p->adapter,16000)==FALSE) + if(PacketSetMinToCopy(pw->adapter,16000)==FALSE) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, @@ -1126,11 +1147,11 @@ pcap_activate_win32(pcap_t *p) while(FALSE); - p->snapshot = PacketSetSnapLen(p->adapter, p->snapshot); + p->snapshot = PacketSetSnapLen(pw->adapter, p->snapshot); /* Set the length of the FCS associated to any packet. This value * will be subtracted to the packet length */ - pw->dag_fcs_bits = p->adapter->DagFcsLen; + pw->dag_fcs_bits = pw->adapter->DagFcsLen; #else /* HAVE_DAG_API */ /* * No DAG support. @@ -1139,10 +1160,21 @@ pcap_activate_win32(pcap_t *p) #endif /* HAVE_DAG_API */ } - PacketSetReadTimeout(p->adapter, p->opt.timeout); + PacketSetReadTimeout(pw->adapter, p->opt.timeout); + + /* disable loopback capture if requested */ + if (p->opt.nocapture_local) + { + if (!PacketSetLoopbackBehavior(pw->adapter, NPF_DISABLE_LOOPBACK)) + { + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Unable to disable the capture of loopback packets."); + goto bad; + } + } #ifdef HAVE_DAG_API - if(p->adapter->Flags & INFO_FLAG_DAG_CARD) + if(pw->adapter->Flags & INFO_FLAG_DAG_CARD) { /* install dag specific handlers for read and setfilter */ p->read_op = pcap_read_win32_dag; @@ -1178,6 +1210,19 @@ pcap_activate_win32(pcap_t *p) p->get_airpcap_handle_op = pcap_get_airpcap_handle_win32; p->cleanup_op = pcap_cleanup_win32; + /* + * XXX - this is only done because WinPcap supported + * pcap_fileno() returning the hFile HANDLE from the + * ADAPTER structure. We make no general guarantees + * that the caller can do anything useful with it. + * + * (Not that we make any general guarantee of that + * sort on UN*X, either, any more, given that not + * all capture devices are regular OS network + * interfaces.) + */ + p->handle = adapter->hFile; + return (0); bad: pcap_cleanup_win32(p); @@ -1212,7 +1257,7 @@ pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp) { struct pcap_win *pw = p->priv; - if(PacketSetBpf(p->adapter,fp)==FALSE){ + if(PacketSetBpf(pw->adapter,fp)==FALSE){ /* * Kernel filter not installed. * @@ -1325,7 +1370,7 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock) */ newtimeout = p->opt.timeout; } - if (!PacketSetReadTimeout(p->adapter, newtimeout)) { + if (!PacketSetReadTimeout(pw->adapter, newtimeout)) { pcap_win32_err_to_str(GetLastError(), win_errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketSetReadTimeout: %s", win_errbuf); diff --git a/pcap.c b/pcap.c index fccf86a2..aafc2586 100644 --- a/pcap.c +++ b/pcap.c @@ -1822,7 +1822,9 @@ pcap_alloc_pcap_t(char *ebuf, size_t size) */ p = (pcap_t *)chunk; -#ifndef _WIN32 +#ifdef _WIN32 + p->handle = INVALID_HANDLE; /* not opened yet */ +#else p->fd = -1; /* not opened yet */ p->selectable_fd = -1; #endif @@ -1872,13 +1874,19 @@ pcap_create_common(char *ebuf, size_t size) p->opt.timeout = 0; /* no timeout specified */ p->opt.buffer_size = 0; /* use the platform's default */ p->opt.promisc = 0; -#ifdef __linux__ - p->opt.protocol = 0; -#endif p->opt.rfmon = 0; p->opt.immediate = 0; p->opt.tstamp_type = -1; /* default to not setting time stamp type */ p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO; + /* + * Platform-dependent options. + */ +#ifdef __linux__ + p->opt.protocol = 0; +#endif +#ifdef _WIN32 + p->opt.nocapture_local = 0; +#endif /* * Start out with no BPF code generation flags set. @@ -2771,8 +2779,8 @@ pcap_fileno(pcap_t *p) #ifndef _WIN32 return (p->fd); #else - if (p->adapter != NULL) - return ((int)(DWORD)p->adapter->hFile); + if (p->handle != INVALID_HANDLE) + return ((int)(DWORD)p->handle); else return (PCAP_ERROR); #endif