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 (pw->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(pw->adapter, queue->buffer, queue->len, (BOOLEAN)sync); if(res != queue->len){ pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", errbuf); } return (res); }
/* * Win32-only routine for getting statistics. * * This way is definitely safer than passing the pcap_stat * from the userland. * In fact, there could happen than the user allocates a variable which is not * big enough for the new structure, and the library will write in a zone * which is not allocated to this variable. * * In this way, we're pretty sure we are writing on memory allocated to this * variable. * * XXX - but this is the wrong way to handle statistics. Instead, we should * have an API that returns data in a form like the Options section of a * pcapng Interface Statistics Block: * * http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#rfc.section.4.6 * * which would let us add new statistics straightforwardly and indicate which * statistics we are and are *not* providing, rather than having to provide * possibly-bogus values for statistics we can't provide. */ 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]; *pcap_stat_size = sizeof (p->stat); /* * Try to get statistics. * * (Please note - "struct pcap_stat" is *not* the same as * WinPcap's "struct bpf_stat". It might currently have the * same layout, but let's not cheat.) */ if (!PacketGetStatsEx(pw->adapter, &bstats)) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStatsEx error: %s", errbuf); return (NULL); } p->stat.ps_recv = bstats.bs_recv; p->stat.ps_drop = bstats.bs_drop; p->stat.ps_ifdrop = bstats.ps_ifdrop; #ifdef ENABLE_REMOTE p->stat.ps_capt = bstats.bs_capt; #endif return (&p->stat); }
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]; /* * Allocate a PACKET_OID_DATA structure to hand to PacketRequest(). * It should be big enough to hold "*lenp" bytes of data; it * will actually be slightly larger, as PACKET_OID_DATA has a * 1-byte data array at the end, standing in for the variable-length * data that's actually there. */ oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp); if (oid_data_arg == NULL) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Couldn't allocate argument buffer for PacketRequest"); return (PCAP_ERROR); } /* * No need to copy the data - we're doing a fetch. */ oid_data_arg->Oid = oid; oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */ 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); free(oid_data_arg); return (PCAP_ERROR); } /* * Get the length actually supplied. */ *lenp = oid_data_arg->Length; /* * Copy back the data we fetched. */ memcpy(data, oid_data_arg->Data, *lenp); free(oid_data_arg); return (0); }
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]; /* * Try to get statistics. * * (Please note - "struct pcap_stat" is *not* the same as * WinPcap's "struct bpf_stat". It might currently have the * same layout, but let's not cheat. * * Note also that we don't fill in ps_capt, as we might have * been called by code compiled against an earlier version of * WinPcap that didn't have ps_capt, in which case filling it * in would stomp on whatever comes after the structure passed * to us. */ if (!PacketGetStats(pw->adapter, &bstats)) { pcap_win32_err_to_str(GetLastError(), errbuf); pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", errbuf); return (-1); } ps->ps_recv = bstats.bs_recv; ps->ps_drop = bstats.bs_drop; /* * XXX - PacketGetStats() doesn't fill this in, so we just * return 0. */ #if 0 ps->ps_ifdrop = bstats.ps_ifdrop; #else ps->ps_ifdrop = 0; #endif return (0); }
/* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * Win32 implementation, based on WinPcap */ int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; int ret = 0; const char *desc; char *AdaptersName; ULONG NameLength; char *name; char our_errbuf[PCAP_ERRBUF_SIZE+1]; /* * Find out how big a buffer we need. * * This call should always return FALSE; if the error is * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to * the size of the buffer we need, otherwise there's a * problem, and NameLength should be set to 0. * * It shouldn't require NameLength to be set, but, * at least as of WinPcap 4.1.3, it checks whether * NameLength is big enough before it checks for a * NULL buffer argument, so, while it'll still do * the right thing if NameLength is uninitialized and * whatever junk happens to be there is big enough * (because the pointer argument will be null), it's * still reading an uninitialized variable. */ NameLength = 0; if (!PacketGetAdapterNames(NULL, &NameLength)) { DWORD last_error = GetLastError(); if (last_error != ERROR_INSUFFICIENT_BUFFER) { pcap_win32_err_to_str(last_error, our_errbuf); pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", our_errbuf); return (-1); } } if (NameLength > 0) AdaptersName = (char*) malloc(NameLength); else { *alldevsp = NULL; return 0; } if (AdaptersName == NULL) { pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); return (-1); } if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { pcap_win32_err_to_str(GetLastError(), our_errbuf); pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", our_errbuf); free(AdaptersName); return (-1); } /* * "PacketGetAdapterNames()" returned a list of * null-terminated ASCII interface name strings, * terminated by a null string, followed by a list * of null-terminated ASCII interface description * strings, terminated by a null string. * This means there are two ASCII nulls at the end * of the first list. * * Find the end of the first list; that's the * beginning of the second list. */ desc = &AdaptersName[0]; while (*desc != '\0' || *(desc + 1) != '\0') desc++; /* * Found it - "desc" points to the first of the two * nulls at the end of the list of names, so the * first byte of the list of descriptions is two bytes * after it. */ desc += 2; /* * Loop over the elements in the first list. */ name = &AdaptersName[0]; while (*name != '\0') { /* * Add an entry for this interface. */ if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { /* * Failure. */ ret = -1; break; } name += strlen(name) + 1; desc += strlen(desc) + 1; } if (ret != -1) { /* * We haven't had any errors yet; do any platform-specific * operations to add devices. */ if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1; } if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; free(AdaptersName); return (ret); }