2026-08-17 Miroslav Stampar <contact@sekuripy.hr>
    * Version 2.1.0 tagged (one behaviour change, one dropped support claim):
        * loop_filtered(), loop_to_buffer() and set_fanout() accept keyword arguments. Their
          docstrings and the README always documented calls like loop_filtered(..., flow_cutoff=3),
          but the methods were METH_VARARGS, so every such call raised TypeError.
        * Rewrote the flow-table key. The old fold multiplied the destination address by 40503,
          which kept it below 2^48, so the top bits of the 64-bit key carried no destination
          entropy; two flows could then share one counter and a real FLOW_HEAD would be dropped -
          the one failure mode the design excludes (slot collisions are benign, they only restart
          a counter). The key is now a splitmix64 finalizer over the whole 5-tuple, so every input
          bit reaches all 64 output bits. Flow-head counts move by a fraction of a percent.
        * Fixed two shifts into the sign bit of a signed int (undefined behaviour): the source
          port in the old flow key, and PACKET_FANOUT_FLAG_DEFRAG (0x8000) in set_fanout().
        * python_requires is now ">=3.9", matching the CI matrix, the wheels and the classifiers;
          it previously admitted 2.7 and 3.8, which nothing builds or tests. The Python 2 code
          paths in the C sources are untouched, just no longer advertised.
        * benchmarks/results/ (results.csv, results.json, SUMMARY.md) is committed instead of
          git-ignored, so every published ratio can be checked against the run behind it.

2026-08-15 Miroslav Stampar <contact@sekuripy.hr>
    * Version 2.0.2 tagged (bugfix release; no API or behaviour changes):
        * Fixed the slot index of the loop_filtered()/loop_to_buffer() IPv4 address set. It
          multiplied the address and then kept the LOW bits of the product, which discarded
          the mixing, so consecutive addresses (an expanded CIDR block) collapsed onto one
          slot and linear probing degenerated into a scan: ~6850 probes per lookup on a
          100k-entry sequential set, against ~1.3 for random addresses. The index now takes
          the HIGH bits of the product, which costs the same and brings sequential sets to
          ~1.0 probes; measured 2.6x-24x faster on sequential sets of 1k-1M entries, with
          random sets unchanged. Matching results, the packed addr_set format and the API are
          unchanged.
        * Added address-set membership tests covering large sequential ranges (up to 1M
          entries), random sets, expanded CIDR blocks, duplicates and the 0.0.0.0 sentinel.

2026-08-15 Miroslav Stampar <contact@sekuripy.hr>
    * Version 2.0.1 tagged (packaging, CI and documentation release; no API changes):
        * PyPI metadata modernized: long description is now README.md (rendered as Markdown),
          plus an accurate summary, keywords, project URLs, SPDX license, classifiers and a
          python_requires of 2.7 and 3.8+.
        * Packaging fix: data_files no longer globs directories, so a leftover tests/__pycache__
          can no longer abort the build with "can't copy 'tests/__pycache__'".
        * Python 3.14 supported: added to the cibuildwheel matrix (CPython 3.9-3.14) and to the
          test matrix; builds and passes the full test suite.
        * Release workflow fixed: it now triggers on this project's bare version tags, builds and
          tests wheels for Linux (x86_64/aarch64, glibc and musl) and macOS (x86_64/arm64),
          verifies the sdist, and uploads to PyPI only from a published GitHub Release or an
          explicit manual dispatch. New tests workflow builds and tests every commit.
        * Documentation rewritten to describe the full 2.0 API surface - loop_filtered(),
          filtered_stats(), loop_to_buffer(), next_batch(), set_fanout(), flow-head tracking,
          large IPv4 address-set matching and the built-in security profile - and to state what
          is actually shipped (no Windows wheels; Windows builds from source with the Npcap SDK).
        * Dropped the obsolete AppVeyor configuration (Python 2.7/3.4/3.5 against WinPcap).
        * Fix: pcap_dealloc() dropped the new reference to None returned by p_close(), leaking
          one reference to None per destroyed Reader (invisible since None became immortal in
          CPython 3.12).

2026-06-26 Miroslav Stampar <contact@sekuripy.hr>
    * Version 2.0.0 tagged with major new capabilities (in-C classification + scaling):
        * loop_filtered(): classify each packet in C and invoke the callback only for admitted
          classes; provably-inert noise never builds a Python object. Generic profile (0=OTHER,
          1=FLOW_HEAD, 2=SET_MATCH) and a built-in security profile (profile=1).
        * loop_to_buffer(): same classification, GIL released for the whole loop, writes admitted
          packets into a shared buffer for parallel worker draining (no per-packet Python).
        * filtered_stats(): live per-class counter snapshot, pollable from another thread.
        * next_batch(): capture up to N packets in one call (amortized C<->Python boundary).
        * set_fanout(group_id, fanout_type=PACKET_FANOUT_HASH) + PACKET_FANOUT_* constants:
          join a live capture to a Linux kernel PACKET_FANOUT group to scale capture across
          multiple sockets/threads on one interface (flow-hashed, no duplicate capture).
        * Classic Reader API (loop/next/dispatch/setfilter/...) unchanged and backward compatible.

2018-06-17 Alberto Solino <asolino@coresecurity.com>
    * Version 0.11.4 tagged with the following changes
        * bpfobject support get_bpf method (by @palaviv)
        * Monitor mode support & missing methods fix (by @gpotter2)
        * Documentation update (@gpotter2)

2018-03-26 Alberto Solino <asolino@coresecurity.com>
    * Version 0.11.2 tagged with the following substantial changes (since version 0.11.11):
        * Exporting pcap_get_selectable_fd as getfd (by @geekhckr)
        * Add a close method & context manager to Reader (by @segevfiner)

2017-01-16 Martin Balao <mbalao@coresecurity.com>
    * Version 0.11.1 tagged with the following changes (since version 0.10.10):
        * AppVeyor integration (continuous integration service)
         * @takluyver contribution
        * Close method for Pcap Dumper
         * @JinBlack contribution
        * Pcap stats added
         * @duggan contribution

2015-05-19  Andres Blanco <ablanco@coresecurity.com>
    * Added sendpacket support by default

2010-08-25  Ezequiel Gutesman <gutes@coresecurity.com>
    * removed check for pcap_sendpacket function

2010-07-30  Ezequiel Gutesman <gutes@coresecurity.com>
    * pcapy.cc: fixed bug in initpcapy,  Pkthdr_type.ob_type and Pdumpertype.ob_type were not set. See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=589956 (reported by Piotr Lewandowski)

2007-03-27  Max Caceres <max@coresecurity.com>
    * pcapobj.cc: wrapped pcap_sendpacket for sending packets in all platforms.

2005-12-09  Max Caceres <max@coresecurity.com>
    * pcapy.cc: open_live doesn't raise an exception anymore when network/netmask information is not available (i.e. when sniffing on devices without an assigned IP address). Reported by Scott Raynel.

2005-09-14  Max Caceres <max@coresecurity.com>
    * pcapobj.cc: fixed bug where exceptions thrown inside a callback where not handled properly. Fix relies on fairly new pcap_breakloop function.
    * pcapy.cc: in Windows uses findalldevs() packaged with new Winpcap 3.1

2005-08-15  Max Caceres <max@coresecurity.com>
    * pcapy.cc: fixed bug where getnet() and getmask() always returned 0.0.0.0 (reported by Jeff Connelly)

2005-07-28  Max Caceres <max@coresecurity.com>
    * pcapobj.cc: fixed a memory leak in PythonCallback (reported by fraca7 _at_ free.fr).

2004-01-05  Javier Kohen  <jkohen@coresecurity.com>
    * setup.py: force linking with G++ when using GCC, to avoid a missing symbol in some setups.

2003-11-28  Javier Kohen  <jkohen@coresecurity.com>
    * dcerpc_v4.py: Fixed self.bind variable having the same name than a method.
