diff --git a/README b/README index e6300d6..0be35e6 100644 --- a/README +++ b/README @@ -52,7 +52,8 @@ ipt_NETFLOW linux 2.6.x-3.x kernel module by -- 2008-2015. * SNMP-index translation rules, let convert meaningless and unstable interface indexes (ifIndex) to more meaningful numbering scheme. - * Easy support for catching mirrored traffic with promisc option. + * Easy support for catching mirrored traffic with promisc option. Which is + also supporting optional MPLS decapsulation. ============================ @@ -228,13 +229,20 @@ ipt_NETFLOW linux 2.6.x-3.x kernel module by -- 2008-2015. case you will want to install it manually. --enable-physdev - Export ingressPhysicalInterface(252) and egressPhysicalInterface(253) (relevant for bridges) in V9 and IPFIX. If your collector does not support these Elements but you still need physdevs then use --enable-physdev-override, in that case physdevs will override normal interface numbers ingressInterface(10) and egressInterface(14). + --enable-promisc + Enables capturing of promiscuous packets into raw/PREROUTING chain. + See README.promisc Solution 1 for usage details and example. + + --promisc-mpls + Enables MPLS label stack decapsulation for promiscuous packets. (For + IPv4 and IPv6 packets only). + =========== = RUNNING = @@ -538,7 +546,7 @@ ipt_NETFLOW linux 2.6.x-3.x kernel module by -- 2008-2015. in kernel jiffies units (which is x/HZ seconds). promisc=1 - - Enable promisc hack. See README.promisc Solution.1 for details. + - Enables promisc hack. See README.promisc Solution 1 for details. exportcpu=number - Lock exporter to single CPU. This may be useful to fine control CPU diff --git a/compat.h b/compat.h index 26945e6..2e22d8b 100644 --- a/compat.h +++ b/compat.h @@ -268,4 +268,19 @@ static void *__seq_open_private(struct file *f, struct seq_operations *ops, #define __get_cpu_var(var) (*this_cpu_ptr(&(var))) #endif +#ifndef MPLS_HLEN +#define MPLS_HLEN 4 +static inline int eth_p_mpls(__be16 eth_type) +{ + return eth_type == htons(ETH_P_MPLS_UC) || + eth_type == htons(ETH_P_MPLS_MC); +} +#endif +#ifndef MPLS_LS_S_MASK +struct mpls_label { + __be32 entry; +}; +#define MPLS_LS_S_MASK 0x00000100 +#endif + #endif /* COMPAT_NETFLOW_H */ diff --git a/configure b/configure index 3dcbddc..432a2e4 100755 --- a/configure +++ b/configure @@ -270,7 +270,8 @@ show_help() { echo " --enable-sampler enables Flow Sampling" echo " --enable-sampler=hash enables Hash sampler" echo " --enable-aggregation enables aggregation rules" - echo " --enable-promisc enables promisc hack" + echo " --enable-promisc enables promisc hack mode" + echo " --promisc-mpls decapsulate MPLS in promisc mode" echo " --enable-physdev enables physdev reporting" echo " --enable-physdev-override to override interfaces" echo " --disable-snmp-agent disables net-snmp agent" @@ -302,7 +303,8 @@ do --enable-sampl*hash) KOPTS="$KOPTS -DENABLE_SAMPLER -DSAMPLING_HASH" ;; --enable-sampl*) KOPTS="$KOPTS -DENABLE_SAMPLER" ;; --enable-aggr*) KOPTS="$KOPTS -DENABLE_AGGR" ;; - --enable-promi*) KOPTS="$KOPTS -DENABLE_PROMISC" ;; + --enable-promi*) ENABLE_PROMISC=1 ;; + --promisc-mpls) ENABLE_PROMISC=1; PROMISC_MPLS=1 ;; --enable-snmp-r*) KOPTS="$KOPTS -DENABLE_SNMP" ;; --enable-physdev) KOPTS="$KOPTS -DENABLE_PHYSDEV" ;; --enable-physdev-over*) KOPTS="$KOPTS -DENABLE_PHYSDEV_OVER" ;; @@ -318,6 +320,9 @@ do esac done +if [ "$ENABLE_PROMISC" = 1 ]; then KOPTS="$KOPTS -DENABLE_PROMISC"; fi +if [ "$PROMISC_MPLS" = 1 ]; then KOPTS="$KOPTS -DPROMISC_MPLS"; fi + kernel_find_version() { KHOW=requested test "$KVERSION" && return 0 diff --git a/ipt_NETFLOW.c b/ipt_NETFLOW.c index cd74a22..a16ccf2 100644 --- a/ipt_NETFLOW.c +++ b/ipt_NETFLOW.c @@ -578,6 +578,9 @@ static int nf_seq_show(struct seq_file *seq, void *v) #endif #ifdef ENABLE_PROMISC " promisc" +# ifdef PROMISC_MPLS + "+mpls" +# endif #endif #ifdef ENABLE_SAMPLER " samp" @@ -1302,17 +1305,38 @@ static int promisc_rcv(struct sk_buff *skb, struct net_device *dev, struct packe skb_pull(skb, vlan_depth); skb_reset_network_header(skb); - skb_reset_transport_header(skb); skb_reset_mac_len(skb); } +# ifdef PROMISC_MPLS + if (eth_p_mpls(skb->protocol)) { + size_t stack_len = 0; + const struct mpls_label *mpls; + + do { + mpls = (struct mpls_label *)(skb->data + stack_len); + stack_len += MPLS_HLEN; + if (unlikely(!pskb_may_pull(skb, stack_len))) + goto drop; + } while (!(mpls->entry & htonl(MPLS_LS_S_MASK))); + + skb_pull(skb, stack_len); + skb_reset_network_header(skb); + if (!pskb_may_pull(skb, 1)) + goto drop; + switch (ip_hdr(skb)->version) { + case 4: skb->protocol = htons(ETH_P_IP); break; + case 6: skb->protocol = htons(ETH_P_IPV6); break; + default: goto drop; + } + } +# endif switch (skb->protocol) { case htons(ETH_P_IP): return promisc4_rcv(skb, dev, pt, orig_dev); case htons(ETH_P_IPV6): return promisc6_rcv(skb, dev, pt, orig_dev); } - drop: NETFLOW_STAT_INC(pkt_promisc_drop); out: diff --git a/testing.sh b/testing.sh index 5b756e6..d05c92d 100755 --- a/testing.sh +++ b/testing.sh @@ -31,12 +31,12 @@ readarray -t opts <