/* 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. */ struct pcap_stat * pcap_stats_ex(pcap_t *p, int *pcap_stat_size) { *pcap_stat_size= sizeof (struct pcap_stat); #ifdef HAVE_REMOTE if (p->rmt_clientside) { /* We are on an remote capture */ return pcap_stats_ex_remote(p); } #endif if (p->adapter == NULL) { sprintf(p->errbuf, "Cannot retrieve the extended statistics from a file or a TurboCap port"); return NULL; } if(PacketGetStatsEx(p->adapter, (struct bpf_stat*) (&p->md.stat) ) != TRUE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStatsEx error: %s", pcap_win32strerror()); return NULL; } return (&p->md.stat); }
/* * 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); }
/* * Return traffic statisistics since started (stats) and * total since adapter was opened. * * \note 'stats' only count traffic we received and transmitted. */ int pkt_get_stats (struct PktStats *stats, struct PktStats *total) { const ADAPTER *adapter; struct bpf_stat b_stat; struct { PACKET_OID_DATA oidData; DWORD value; } oid; DWORD count[4]; if (!_pkt_inf) return (0); adapter = (const ADAPTER*) _pkt_inf->adapter; if (!PacketGetStatsEx(adapter,&b_stat)) return (0); memset (total, 0, sizeof(*total)); /* we don't know yet */ memset (&count, 0, sizeof(count)); /* * Query: OID_GEN_RCV_OK, OID_GEN_RCV_ERROR * OID_GEN_XMIT_OK, OID_GEN_XMIT_ERROR */ memset (&oid, 0, sizeof(oid)); oid.oidData.Oid = OID_GEN_RCV_OK; oid.oidData.Length = sizeof(oid.value); if (!PacketRequest (adapter, FALSE, &oid.oidData)) goto no_total; count[0] = *(DWORD*) &oid.oidData.Data; memset (&oid, 0, sizeof(oid)); oid.oidData.Oid = OID_GEN_XMIT_OK; oid.oidData.Length = sizeof(oid.value); if (!PacketRequest (adapter, FALSE, &oid.oidData)) goto no_total; count[1] = *(DWORD*) &oid.oidData.Data; memset (&oid, 0, sizeof(oid)); oid.oidData.Oid = OID_GEN_RCV_ERROR; oid.oidData.Length = sizeof(oid.value); if (!PacketRequest (adapter, FALSE, &oid.oidData)) goto no_total; count[2] = *(DWORD*) &oid.oidData.Data; memset (&oid, 0, sizeof(oid)); oid.oidData.Oid = OID_GEN_XMIT_ERROR; oid.oidData.Length = sizeof(oid.value); if (!PacketRequest (adapter, FALSE, &oid.oidData)) goto no_total; count[3] = *(DWORD*) &oid.oidData.Data; no_total: total->in_packets = count[0]; total->out_packets = count[1]; total->in_errors = count[2]; total->out_errors = count[3]; stats->in_packets = b_stat.bs_recv; stats->in_bytes = num_tx_bytes; stats->out_packets = num_tx_pkt; stats->out_bytes = num_tx_bytes; stats->in_errors = 0UL; stats->out_errors = num_tx_errors; stats->lost = b_stat.bs_drop + b_stat.ps_ifdrop; return (1); }