const MaxLength … const cmdNew … const cmdGet … const attrName … const attrPackets … const attrBytes … type runner … // New returns a new Interface. If the netfilter_nfacct subsystem is // not available in the kernel it will return error. func New() (Interface, error) { … } // newInternal returns a new Interface with the given handler. func newInternal(hndlr handler) (Interface, error) { … } // Ensure is part of the interface. func (r *runner) Ensure(name string) error { … } // Add is part of the interface. func (r *runner) Add(name string) error { … } // Get is part of the interface. func (r *runner) Get(name string) (*Counter, error) { … } // List is part of the interface. func (r *runner) List() ([]*Counter, error) { … } var ErrObjectNotFound … var ErrObjectAlreadyExists … var ErrNameExceedsMaxLength … var ErrEmptyName … var ErrUnexpected … var ErrNotSupported … func handleError(err error) error { … } // decode function processes a byte stream, requiring the 'strict' parameter to be true in production and // false only for testing purposes. If in strict mode and any of the relevant attributes (name, packets, or bytes) // have not been processed, an error is returned indicating a failure to decode the byte stream. // // Parse the netlink message as per the documentation outlined in: // https://docs.kernel.org/userspace-api/netlink/intro.html // // Message Components: // - netfilter generic message [4 bytes] // struct nfgenmsg (definition: https://github.com/torvalds/linux/blob/v6.7/include/uapi/linux/netfilter/nfnetlink.h#L32-L38) // - attributes [variable-sized, must align to 4 bytes from the start of attribute] // struct nlattr (definition: https://github.com/torvalds/linux/blob/v6.7/include/uapi/linux/netlink.h#L220-L232) // // Attribute Components: // - length [2 bytes] // length includes bytes for defining the length itself, bytes for defining the type, // and the actual bytes of data without any padding. // - type [2 bytes] // - data [variable-sized] // - padding [optional] // // Example. Counter{Name: "dummy-metric", Packets: 123, Bytes: 54321} in netlink message: // // struct nfgenmsg{ // __u8 nfgen_family: AF_NETLINK // __u8 version: nl.NFNETLINK_V0 // __be16 res_id: nl.NFNETLINK_V0 // } // // struct nlattr{ // __u16 nla_len: 13 // __u16 nla_type: NFACCT_NAME // char data: dummy-metric\0 // } // // (padding:) // data: \0\0\0 // // struct nlattr{ // __u16 nla_len: 12 // __u16 nla_type: NFACCT_PKTS // __u64: data: 123 // } // // struct nlattr{ // __u16 nla_len: 12 // __u16 nla_type: NFACCT_BYTES // __u64: data: 54321 // } func decode(msg []byte, strict bool) (*Counter, error) { … }