/* netfilter.stp - netfilter hook tapset
 *
 * Copyright (C) 2012 Red Hat Inc.
 * <tapsetdescription>
 * This family of probe points provides a simple way to examine network traffic using the netfilter hooks mechanism.
 * </tapsetdescription>
 */

/* The below functionality is mostly inspired by tcp.stp and networking.stp. */

%{
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/netfilter_arp.h>
#include <linux/if_arp.h>
#include <net/ipv6.h>
%}

# XXX: IPPROTO_* and NF_* constants should be secure globals -- needs PR10607
  # ... currently we use a hideous copypasta hack which defines them as
  # locals in each probe alias. Blegh

function __read_char:long(addr:long) %{ /* pure */
         STAP_RETVALUE = kderef(sizeof(char), STAP_ARG_addr);
         CATCH_DEREF_FAULT ();
%}

function __mac_addr_to_string:string(addr:long) {
         return sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
                        __read_char(addr), __read_char(addr+1),
                        __read_char(addr+2), __read_char(addr+3),
                        __read_char(addr+4), __read_char(addr+5))         
}

function __get_mac_addr:string(addr:long) {
         return __mac_addr_to_string(@cast(addr, "struct net_device")->dev_addr)
}

function __get_skb_arphdr:long(addr:long)
{
        // The method is exactly the same as for an IP header:
        return __get_skb_iphdr(addr)
}

function __ip6_skb_proto:long(addr:long)
%{ /* pure */
   struct sk_buff *skb = (struct sk_buff *)(uintptr_t)STAP_ARG_addr;
   struct ipv6hdr *hdr;
   u8 nexthdr;

   /* We call deref() here to ensure the memory at the skb location
    * is valid to read, to avoid potential kernel panic calling ipv6_hdr(). */
   (void)kderef_buffer(NULL, skb, sizeof(struct sk_buff));
   hdr = ipv6_hdr(skb);
   nexthdr = kread(&(hdr->nexthdr));

   if (ipv6_ext_hdr(nexthdr)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
     long result = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr);     
#else
     __be16 frag_offp;
     int extoff = (u8 *)(hdr + 1) - kread(&(skb->data));
     long result = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_offp);
#endif
     STAP_RETVALUE = result < 0 ? 0 : result;
   } else {
     STAP_RETVALUE = 0;
   }
   CATCH_DEREF_FAULT();
%}

@define netfilter_common_setup(pf_name) %(
        pf = @pf_name

        /* XXX not relevant for netfilter.arp & netfilter.bridge probes */
        ipproto_tcp = %{ /* pure */ IPPROTO_TCP %}
        ipproto_udp = %{ /* pure */ IPPROTO_UDP %}

        /* from include/linux/netfilter.h: */
        nf_drop = 0
        nf_accept = 1
        nf_stolen = 2
        nf_queue = 3
        nf_repeat = 4
        nf_stop = 5

        indev = $in; outdev = $out
        indev_name = kernel_string2(@cast(indev,"struct net_device")->name,
                                    "")
        outdev_name = kernel_string2(@cast(outdev,"struct net_device")->name,
                                     "")

        if (indev) {
           indev_mac_len = @cast(indev,"struct net_device")->addr_len
           in_mac = __get_mac_addr(indev)
        }
        if (outdev) {
           outdev_mac_len = @cast(outdev,"struct net_device")->addr_len
           out_mac = __get_mac_addr(outdev)
        }
%)

@define netfilter_ip4_setup %(
        iphdr = __get_skb_iphdr($skb)
        family = %{ /* pure */ AF_INET %}
        saddr = format_ipaddr(__ip_skb_saddr(iphdr), %{ /* pure */ AF_INET %})
        daddr = format_ipaddr(__ip_skb_daddr(iphdr), %{ /* pure */ AF_INET %})
        protocol = __ip_skb_proto(iphdr)

        length = @cast($skb, "struct sk_buff")->len

        tcphdr = __get_skb_tcphdr($skb)
        if (protocol == ipproto_tcp) {
           dport = __tcp_skb_dport(tcphdr)
           sport = __tcp_skb_sport(tcphdr)
           urg = __tcp_skb_urg(tcphdr)
           ack = __tcp_skb_ack(tcphdr)
           psh = __tcp_skb_psh(tcphdr)
           rst = __tcp_skb_rst(tcphdr)
           syn = __tcp_skb_syn(tcphdr)
           fin = __tcp_skb_fin(tcphdr)
        }

        udphdr = tcphdr /* the same place where tcphdr would have been */
        if (protocol == ipproto_udp) {
           dport = ntohs(@cast(udphdr,"udphdr")->dest)
           sport = ntohs(@cast(udphdr,"udphdr")->source)
        }
%)

@define netfilter_ip6_setup %(
        iphdr = __get_skb_iphdr($skb)
        family = %{ /* pure */ AF_INET6 %}
        saddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->saddr,
                              %{ /* pure */ AF_INET6 %})
        daddr = format_ipaddr(&@cast(iphdr, "ipv6hdr")->daddr,
                              %{ /* pure */ AF_INET6 %})
        protocol = __ip6_skb_proto($skb)

        length = @cast($skb, "struct sk_buff")->len

        tcphdr = __get_skb_tcphdr($skb)
        if (protocol == ipproto_tcp) {
           dport = __tcp_skb_dport(tcphdr)
           sport = __tcp_skb_sport(tcphdr)
           urg = __tcp_skb_urg(tcphdr)
           ack = __tcp_skb_ack(tcphdr)
           psh = __tcp_skb_psh(tcphdr)
           rst = __tcp_skb_rst(tcphdr)
           syn = __tcp_skb_syn(tcphdr)
           fin = __tcp_skb_fin(tcphdr)
        }

        udphdr = tcphdr /* the same place where tcphdr would have been */
        if (protocol == ipproto_udp) {
           dport = ntohs(@cast(udphdr,"udphdr")->dest)
           sport = ntohs(@cast(udphdr,"udphdr")->source)
        }        
%)

/**
 * probe netfilter.ip.pre_routing - Called before an IP packet is routed
 * @pf: Protocol family - either 'ipv4' or 'ipv6'
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @iphdr: Address of IP header
 * @protocol: Packet protocol from driver (ipv4 only)
 * @ipproto_tcp: Constant used to signify that the packet protocol is TCP
 * @ipproto_udp: Constant used to signify that the packet protocol is UDP
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 * @family: IP address family
 * @saddr: A string representing the source IP address
 * @daddr: A string representing the destination IP address
 * @sport: TCP or UDP source port (ipv4 only)
 * @dport: TCP or UDP destination port (ipv4 only)
 * @urg: TCP URG flag (if protocol is TCP; ipv4 only)
 * @ack: TCP ACK flag (if protocol is TCP; ipv4 only)
 * @psh: TCP PSH flag (if protocol is TCP; ipv4 only)
 * @rst: TCP RST flag (if protocol is TCP; ipv4 only)
 * @syn: TCP SYN flag (if protocol is TCP; ipv4 only)
 * @fin: TCP FIN flag (if protocol is TCP; ipv4 only)
 */
probe netfilter.ip.pre_routing = netfilter.ipv4.pre_routing,
        netfilter.ipv6.pre_routing
{
}

probe netfilter.ipv4.pre_routing
        = netfilter.hook("NF_INET_PRE_ROUTING").pf("NFPROTO_IPV4")
{
        @netfilter_common_setup("ipv4")
        @netfilter_ip4_setup
}


probe netfilter.ipv6.pre_routing
        = netfilter.hook("NF_IP6_PRE_ROUTING").pf("NFPROTO_IPV6")
{
        @netfilter_common_setup("ipv6")
        @netfilter_ip6_setup
}

/**
 * probe netfilter.ip.local_in - Called on an incoming IP packet addressed to the local computer
 * @pf: Protocol family -- either "ipv4" or "ipv6"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @iphdr: Address of IP header
 * @protocol: Packet protocol from driver (ipv4 only)
 * @ipproto_tcp: Constant used to signify that the packet protocol is TCP
 * @ipproto_udp: Constant used to signify that the packet protocol is UDP
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 * @family: IP address family
 * @saddr: A string representing the source IP address
 * @daddr: A string representing the destination IP address
 * @sport: TCP or UDP source port (ipv4 only)
 * @dport: TCP or UDP destination port (ipv4 only)
 * @urg: TCP URG flag (if protocol is TCP; ipv4 only)
 * @ack: TCP ACK flag (if protocol is TCP; ipv4 only)
 * @psh: TCP PSH flag (if protocol is TCP; ipv4 only)
 * @rst: TCP RST flag (if protocol is TCP; ipv4 only)
 * @syn: TCP SYN flag (if protocol is TCP; ipv4 only)
 * @fin: TCP FIN flag (if protocol is TCP; ipv4 only)
 */
probe netfilter.ip.local_in = netfilter.ipv4.local_in,
        netfilter.ipv6.local_in
{
}

probe netfilter.ipv4.local_in
        = netfilter.hook("NF_INET_LOCAL_IN").pf("NFPROTO_IPV4")
{
        @netfilter_common_setup("ipv4")
        @netfilter_ip4_setup
}


probe netfilter.ipv6.local_in
        = netfilter.hook("NF_IP6_LOCAL_IN").pf("NFPROTO_IPV6")
{
        @netfilter_common_setup("ipv6")
        @netfilter_ip6_setup
}

/**
 * probe netfilter.ip.forward - Called on an incoming IP packet addressed to some other computer
 * @pf: Protocol family -- either "ipv4" or "ipv6"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @iphdr: Address of IP header
 * @protocol: Packet protocol from driver (ipv4 only)
 * @ipproto_tcp: Constant used to signify that the packet protocol is TCP
 * @ipproto_udp: Constant used to signify that the packet protocol is UDP
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 * @family: IP address family
 * @saddr: A string representing the source IP address
 * @daddr: A string representing the destination IP address
 * @sport: TCP or UDP source port (ipv4 only)
 * @dport: TCP or UDP destination port (ipv4 only)
 * @urg: TCP URG flag (if protocol is TCP; ipv4 only)
 * @ack: TCP ACK flag (if protocol is TCP; ipv4 only)
 * @psh: TCP PSH flag (if protocol is TCP; ipv4 only)
 * @rst: TCP RST flag (if protocol is TCP; ipv4 only)
 * @syn: TCP SYN flag (if protocol is TCP; ipv4 only)
 * @fin: TCP FIN flag (if protocol is TCP; ipv4 only)
 */
probe netfilter.ip.forward = netfilter.ipv4.forward,
        netfilter.ipv6.forward
{
}

probe netfilter.ipv4.forward
        = netfilter.hook("NF_INET_FORWARD").pf("NFPROTO_IPV4")
{
        @netfilter_common_setup("ipv4")
        @netfilter_ip4_setup
}


probe netfilter.ipv6.forward
        = netfilter.hook("NF_IP6_FORWARD").pf("NFPROTO_IPV6")
{
        @netfilter_common_setup("ipv6")
        @netfilter_ip6_setup
}

/**
 * probe netfilter.ip.local_out - Called on an outgoing IP packet
 * @pf: Protocol family -- either "ipv4" or "ipv6"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @iphdr: Address of IP header
 * @protocol: Packet protocol from driver (ipv4 only)
 * @ipproto_tcp: Constant used to signify that the packet protocol is TCP
 * @ipproto_udp: Constant used to signify that the packet protocol is UDP
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 * @family: IP address family
 * @saddr: A string representing the source IP address
 * @daddr: A string representing the destination IP address
 * @sport: TCP or UDP source port (ipv4 only)
 * @dport: TCP or UDP destination port (ipv4 only)
 * @urg: TCP URG flag (if protocol is TCP; ipv4 only)
 * @ack: TCP ACK flag (if protocol is TCP; ipv4 only)
 * @psh: TCP PSH flag (if protocol is TCP; ipv4 only)
 * @rst: TCP RST flag (if protocol is TCP; ipv4 only)
 * @syn: TCP SYN flag (if protocol is TCP; ipv4 only)
 * @fin: TCP FIN flag (if protocol is TCP; ipv4 only)
 */
probe netfilter.ip.local_out = netfilter.ipv4.local_out,
        netfilter.ipv6.local_out
{
}

probe netfilter.ipv4.local_out
        = netfilter.hook("NF_INET_LOCAL_OUT").pf("NFPROTO_IPV4")
{
        @netfilter_common_setup("ipv4")
        @netfilter_ip4_setup
}

probe netfilter.ipv6.local_out
        = netfilter.hook("NF_IP6_LOCAL_OUT").pf("NFPROTO_IPV6")
{
        @netfilter_common_setup("ipv6")
        @netfilter_ip6_setup
}

/**
 * probe netfilter.ip.post_routing - Called immediately before an outgoing IP packet leaves the computer
 * @pf: Protocol family -- either "ipv4" or "ipv6"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @iphdr: Address of IP header
 * @protocol: Packet protocol from driver (ipv4 only)
 * @ipproto_tcp: Constant used to signify that the packet protocol is TCP
 * @ipproto_udp: Constant used to signify that the packet protocol is UDP
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 * @family: IP address family
 * @saddr: A string representing the source IP address
 * @daddr: A string representing the destination IP address
 * @sport: TCP or UDP source port (ipv4 only)
 * @dport: TCP or UDP destination port (ipv4 only)
 * @urg: TCP URG flag (if protocol is TCP; ipv4 only)
 * @ack: TCP ACK flag (if protocol is TCP; ipv4 only)
 * @psh: TCP PSH flag (if protocol is TCP; ipv4 only)
 * @rst: TCP RST flag (if protocol is TCP; ipv4 only)
 * @syn: TCP SYN flag (if protocol is TCP; ipv4 only)
 * @fin: TCP FIN flag (if protocol is TCP; ipv4 only)
 */
probe netfilter.ip.post_routing = netfilter.ipv4.post_routing,
        netfilter.ipv6.local_out
{
}

probe netfilter.ipv4.post_routing
        = netfilter.hook("NF_INET_POST_ROUTING").pf("NFPROTO_IPV4")
{
        @netfilter_common_setup("ipv4")
        @netfilter_ip4_setup
}


probe netfilter.ipv6.post_routing
        = netfilter.hook("NF_IP6_POST_ROUTING").pf("NFPROTO_IPV6")
{
        @netfilter_common_setup("ipv6")
        @netfilter_ip6_setup
}

function __read4:long (x:long) %{ /* pure */
         long a = kderef(sizeof(u32),STAP_ARG_x);
         STAP_RETVALUE = a;
         CATCH_DEREF_FAULT();
%}

@define netfilter_arp_setup %(
# XXX: include functionality to parse ARP packet contents
        arphdr = __get_skb_arphdr($skb)
        family = %{ /* pure */ NF_ARP %} // from linux/netfilter_arp.h
        ar_hrd = ntohs(@cast(arphdr, "struct arphdr")->ar_hrd)
        ar_pro = ntohs(@cast(arphdr, "struct arphdr")->ar_pro)
        ar_hln = @cast(arphdr, "struct arphdr")->ar_hln
        ar_pln = @cast(arphdr, "struct arphdr")->ar_pln
        ar_op = ntohs(@cast(arphdr, "struct arphdr")->ar_op)

        ar_data = arphdr + 8
        if (ar_hrd == 0x001 && ar_pro == 0x800) {
           /* additional info available for most common (Ethernet+IP) case: */
           ar_sha = __mac_addr_to_string(ar_data)
           ar_sip = format_ipaddr(__read4(ar_data + 6), %{ /* pure */ AF_INET %})
           ar_tha = __mac_addr_to_string(ar_data + 10)
           ar_tip =  format_ipaddr(__read4(ar_data + 16), %{ /* pure */ AF_INET %})
        }
        /* XXX support for additional cases? */

        length = @cast($skb, "struct sk_buff")->len
%)

/**
 * probe netfilter.arp.in -- Called for each incoming ARP packet
 * @pf: Protocol family -- always "arp"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @arphdr: Address of ARP header
 * @ar_hrd: Format of hardware address
 * @ar_pro: Format of protocol address
 * @ar_hln: Length of hardware address
 * @ar_pln: Length of protocol address
 * @ar_op: ARP opcode (command)
 * @ar_data: Address of ARP packet data region (after the header)
 * @ar_sha: Ethernet+IP only (ar_pro==0x800): source hardware (MAC) address 
 * @ar_sip: Ethernet+IP only (ar_pro==0x800): source IP address
 * @ar_tha: Ethernet+IP only (ar_pro==0x800): target hardware (MAC) address
 * @ar_tip: Ethernet+IP only (ar_pro==0x800): target IP address
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.arp.in = netfilter.hook("NF_ARP_IN").pf("NFPROTO_ARP")
{
        @netfilter_common_setup("arp")
        @netfilter_arp_setup
}


/**
 * probe netfilter.arp.out -- Called for each outgoing ARP packet
 * @pf: Protocol family -- always "arp"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @arphdr: Address of ARP header
 * @ar_hrd: Format of hardware address
 * @ar_pro: Format of protocol address
 * @ar_hln: Length of hardware address
 * @ar_pln: Length of protocol address
 * @ar_op: ARP opcode (command)
 * @ar_data: Address of ARP packet data region (after the header)
 * @ar_sha: Ethernet+IP only (ar_pro==0x800): source hardware (MAC) address 
 * @ar_sip: Ethernet+IP only (ar_pro==0x800): source IP address
 * @ar_tha: Ethernet+IP only (ar_pro==0x800): target hardware (MAC) address
 * @ar_tip: Ethernet+IP only (ar_pro==0x800): target IP address
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.arp.out = netfilter.hook("NF_ARP_OUT").pf("NFPROTO_ARP")
{
        @netfilter_common_setup("arp")
        @netfilter_arp_setup
}

/**
 * probe netfilter.arp.forward -- Called for each ARP packet to be forwarded
 * @pf: Protocol family -- always "arp"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @arphdr: Address of ARP header
 * @ar_hrd: Format of hardware address
 * @ar_pro: Format of protocol address
 * @ar_hln: Length of hardware address
 * @ar_pln: Length of protocol address
 * @ar_op: ARP opcode (command)
 * @ar_data: Address of ARP packet data region (after the header)
 * @ar_sha: Ethernet+IP only (ar_pro==0x800): source hardware (MAC) address 
 * @ar_sip: Ethernet+IP only (ar_pro==0x800): source IP address
 * @ar_tha: Ethernet+IP only (ar_pro==0x800): target hardware (MAC) address
 * @ar_tip: Ethernet+IP only (ar_pro==0x800): target IP address
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.arp.forward = netfilter.hook("NF_ARP_FORWARD").pf("NFPROTO_ARP")
{
        @netfilter_common_setup("arp")
        @netfilter_arp_setup
}

# XXX: think of some way to comprehensively study bridged packets?

/**
 * probe netfilter.bridge.pre_routing -- Called before a bridging packet is routed
 * @pf: Protocol family -- always "bridge"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.bridge.pre_routing
        = netfilter.hook("NF_BR_PRE_ROUTING").pf("NFPROTO_BRIDGE")
{
        @netfilter_common_setup("bridge")
        length = @cast($skb, "struct sk_buff")->len
}

/**
 * probe netfilter.bridge.local_in - Called on a bridging packet destined for the local computer
 * @pf: Protocol family -- always "bridge"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.bridge.local_in
        = netfilter.hook("NF_BR_LOCAL_IN").pf("NFPROTO_BRIDGE")
{
        @netfilter_common_setup("bridge")
        length = @cast($skb, "struct sk_buff")->len
}

/**
 * probe netfilter.bridge.forward - Called on an incoming bridging packet destined for some other computer
 * @pf: Protocol family -- always "bridge"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.bridge.forward
        = netfilter.hook("NF_BR_FORWARD").pf("NFPROTO_BRIDGE")
{
        @netfilter_common_setup("bridge")
        length = @cast($skb, "struct sk_buff")->len
}

/**
 * probe netfilter.bridge.local_out - Called on a bridging packet coming from a local process
 * @pf: Protocol family -- always "bridge"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.bridge.local_out
        = netfilter.hook("NF_BR_LOCAL_OUT").pf("NFPROTO_BRIDGE")
{
        @netfilter_common_setup("bridge")
        length = @cast($skb, "struct sk_buff")->len
}

/**
 * probe netfilter.bridge.post_routing -- Called before a bridging packet hits the wire
 * @pf: Protocol family -- always "bridge"
 * @indev: Address of net_device representing input device, 0 if unknown
 * @outdev: Address of net_device representing output device, 0 if unknown
 * @indev_name: Name of network device packet was received on (if known)
 * @outdev_name: Name of network device packet will be routed to (if known)
 * @length: The length of the packet buffer contents, in bytes
 * @nf_drop: Constant used to signify a 'drop' verdict
 * @nf_accept: Constant used to signify an 'accept' verdict
 * @nf_stolen: Constant used to signify a 'stolen' verdict
 * @nf_queue: Constant used to signify a 'queue' verdict
 * @nf_repeat: Constant used to signify a 'repeat' verdict
 * @nf_stop: Constant used to signify a 'stop' verdict
 */
probe netfilter.bridge.post_routing
        = netfilter.hook("NF_BR_POST_ROUTING").pf("NFPROTO_BRIDGE")
{
        @netfilter_common_setup("bridge")
        length = @cast($skb, "struct sk_buff")->len
}
