[PATCH v3] netfilter: nf_conntrack_sip: add sip_external_media logic

2018-12-03 Thread Alin Nastac
From: Alin Nastac 

Allow media streams that are not passing through this router.

When enabled, the sip_external_media logic will leave SDP
payload untouched when it detects that interface towards INVITEd
party is the same with the one towards media endpoint.

Signed-off-by: Alin Nastac 
---
 net/netfilter/nf_conntrack_sip.c | 42 
 1 file changed, 42 insertions(+)

diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index c8d2b66..f067c6b 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -54,6 +56,11 @@ module_param(sip_direct_media, int, 0600);
 MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
   "endpoints only (default 1)");
 
+static int sip_external_media __read_mostly = 0;
+module_param(sip_external_media, int, 0600);
+MODULE_PARM_DESC(sip_external_media, "Expect Media streams between external "
+"endpoints (default 0)");
+
 const struct nf_nat_sip_hooks *nf_nat_sip_hooks;
 EXPORT_SYMBOL_GPL(nf_nat_sip_hooks);
 
@@ -861,6 +868,41 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
if (!nf_inet_addr_cmp(daddr, >tuplehash[dir].tuple.src.u3))
return NF_ACCEPT;
saddr = >tuplehash[!dir].tuple.src.u3;
+   } else if (sip_external_media) {
+   struct net_device *dev = skb_dst(skb)->dev;
+   struct net *net = dev_net(dev);
+   struct rtable *rt;
+   struct flowi4 fl4 = {};
+#if IS_ENABLED(CONFIG_IPV6)
+   struct flowi6 fl6 = {};
+#endif
+   struct dst_entry *dst = NULL;
+
+   switch (nf_ct_l3num(ct)) {
+   case NFPROTO_IPV4:
+   fl4.daddr = daddr->ip;
+   rt = ip_route_output_key(net, );
+   if (!IS_ERR(rt))
+   dst = >dst;
+   break;
+
+#if IS_ENABLED(CONFIG_IPV6)
+   case NFPROTO_IPV6:
+   fl6.daddr = daddr->in6;
+   dst = ip6_route_output(net, NULL, );
+   if (dst->error) {
+   dst_release(dst);
+   dst = NULL;
+   }
+   break;
+#endif
+   }
+
+   /* Don't predict any conntracks when media endpoint is reachable
+* through the same interface as the signalling peer.
+*/
+   if (dst && dst->dev == dev)
+   return NF_ACCEPT;
}
 
/* We need to check whether the registration exists before attempting
-- 
2.7.4



[PATCH v2] netfilter: nf_conntrack_sip: add sip_external_media logic

2018-11-30 Thread Alin Nastac
From: Alin Nastac 

Allow media streams that are not passing through this router.

When enabled, the sip_external_media logic will leave SDP
payload untouched when it detects that interface towards INVITEd
party is the same with the one towards media endpoint.

Signed-off-by: Alin Nastac 
---
 net/netfilter/nf_conntrack_sip.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index c8d2b66..f09a0e1 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -54,6 +56,11 @@ module_param(sip_direct_media, int, 0600);
 MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
   "endpoints only (default 1)");
 
+static int sip_external_media __read_mostly = 0;
+module_param(sip_external_media, int, 0600);
+MODULE_PARM_DESC(sip_external_media, "Expect Media streams between external "
+"endpoints (default 0)");
+
 const struct nf_nat_sip_hooks *nf_nat_sip_hooks;
 EXPORT_SYMBOL_GPL(nf_nat_sip_hooks);
 
@@ -861,6 +868,39 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
if (!nf_inet_addr_cmp(daddr, >tuplehash[dir].tuple.src.u3))
return NF_ACCEPT;
saddr = >tuplehash[!dir].tuple.src.u3;
+   } else if (sip_external_media) {
+   struct net_device *dev = skb_dst(skb)->dev;
+   struct net *net = dev_net(dev);
+   struct rtable *rt;
+   struct flowi4 fl4 = {};
+   struct flowi6 fl6 = {};
+   struct dst_entry *dst = NULL;
+
+   switch (nf_ct_l3num(ct)) {
+   case NFPROTO_IPV4:
+   fl4.daddr = daddr->ip;
+   rt = ip_route_output_key(net, );
+   if (!IS_ERR(rt))
+   dst = >dst;
+   break;
+
+#if IS_ENABLED(CONFIG_IPV6)
+   case NFPROTO_IPV6:
+   fl6.daddr = daddr->in6;
+   dst = ip6_route_output(net, NULL, );
+   if (dst->error) {
+   dst_release(dst);
+   dst = NULL;
+   }
+   break;
+#endif
+   }
+
+   /* Don't predict any conntracks when media endpoint is reachable
+* through the same interface as the signalling peer.
+*/
+   if (dst && dst->dev == dev)
+   return NF_ACCEPT;
}
 
/* We need to check whether the registration exists before attempting
-- 
2.7.4



[PATCH] netfilter: nf_conntrack_sip: add sip_external_media logic

2018-11-29 Thread Alin Nastac
Allow media streams that are not passing through this router.

When enabled, the sip_external_media logic will leave SDP
payload untouched when it detects that interface towards INVITEd
party is the same with the one towards media endpoint.

Signed-off-by: Alin Nastac 
---
 net/netfilter/nf_conntrack_sip.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index c8d2b66..5416c08 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -54,6 +56,11 @@ module_param(sip_direct_media, int, 0600);
 MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
   "endpoints only (default 1)");
 
+static int sip_external_media __read_mostly = 0;
+module_param(sip_external_media, int, 0600);
+MODULE_PARM_DESC(sip_external_media, "Expect Media streams between external "
+"endpoints (default 0)");
+
 const struct nf_nat_sip_hooks *nf_nat_sip_hooks;
 EXPORT_SYMBOL_GPL(nf_nat_sip_hooks);
 
@@ -861,6 +868,37 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
if (!nf_inet_addr_cmp(daddr, >tuplehash[dir].tuple.src.u3))
return NF_ACCEPT;
saddr = >tuplehash[!dir].tuple.src.u3;
+   } else if (sip_external_media) {
+   struct net_device *dev = skb_dst(skb)->dev;
+   struct net *net = dev_net(dev);
+   struct rtable *rt;
+   struct flowi4 fl4 = {};
+   struct flowi6 fl6 = {};
+   struct dst_entry *dst = NULL;
+
+   switch (nf_ct_l3num(ct)) {
+   case NFPROTO_IPV4:
+   fl4.daddr = daddr->ip;
+   rt = ip_route_output_key(net, );
+   if (!IS_ERR(rt))
+   dst = >dst;
+   break;
+
+   case NFPROTO_IPV6:
+   fl6.daddr = daddr->in6;
+   dst = ip6_route_output(net, NULL, );
+   if (dst->error) {
+   dst_release(dst);
+   dst = NULL;
+   }
+   break;
+   }
+
+   /* Don't predict any conntracks when media endpoint is reachable
+* through the same interface as the signalling peer.
+*/
+   if (dst && dst->dev == dev)
+   return NF_ACCEPT;
}
 
/* We need to check whether the registration exists before attempting
-- 
2.7.4



[PATCH] netfilter: nf_nat_sip: fix RTP/RTCP source port translations

2018-11-27 Thread Alin Nastac
Perform the same SNAT translation on RTP/RTCP conntracks regardless of
who sends the first datagram.

Prior to this change, RTP packets send by the peer who required source
port translation were forwarded with unmodified source port when this
peer started its voice/video stream first.

Signed-off-by: Alin Nastac 
---
 net/netfilter/nf_nat_sip.c | 35 +++
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c
index 1f30860..a1e23cc 100644
--- a/net/netfilter/nf_nat_sip.c
+++ b/net/netfilter/nf_nat_sip.c
@@ -18,6 +18,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -316,6 +317,9 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, 
unsigned int protoff,
 static void nf_nat_sip_expected(struct nf_conn *ct,
struct nf_conntrack_expect *exp)
 {
+   struct nf_conn_help *help = nfct_help(ct->master);
+   struct nf_conntrack_expect *pair_exp;
+   int range_set_for_snat = 0;
struct nf_nat_range2 range;
 
/* This must be a fresh one. */
@@ -327,15 +331,38 @@ static void nf_nat_sip_expected(struct nf_conn *ct,
range.min_addr = range.max_addr = exp->saved_addr;
nf_nat_setup_info(ct, , NF_NAT_MANIP_DST);
 
-   /* Change src to where master sends to, but only if the connection
-* actually came from the same source. */
-   if (nf_inet_addr_cmp(>tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
+   /* Do SRC manip according with the parameters found in the
+* paired expected conntrack. */
+   spin_lock_bh(_conntrack_expect_lock);
+   hlist_for_each_entry(pair_exp, >expectations, lnode) {
+   if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) &&
+   pair_exp->tuple.dst.protonum == 
ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum &&
+   
nf_inet_addr_cmp(>tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, 
_exp->saved_addr) &&
+   ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == 
pair_exp->saved_proto.all) {
+   range.flags = (NF_NAT_RANGE_MAP_IPS | 
NF_NAT_RANGE_PROTO_SPECIFIED);
+   range.min_proto.all = range.max_proto.all = 
pair_exp->tuple.dst.u.all;
+   range.min_addr = range.max_addr = 
pair_exp->tuple.dst.u3;
+   range_set_for_snat = 1;
+   break;
+   }
+   }
+   spin_unlock_bh(_conntrack_expect_lock);
+
+   /* When no paired expected conntrack has been found, change src to
+* where master sends to, but only if the connection actually came
+* from the same source. */
+   if (!range_set_for_snat &&
+   nf_inet_addr_cmp(>tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
 >master->tuplehash[exp->dir].tuple.src.u3)) {
range.flags = NF_NAT_RANGE_MAP_IPS;
range.min_addr = range.max_addr
= ct->master->tuplehash[!exp->dir].tuple.dst.u3;
-   nf_nat_setup_info(ct, , NF_NAT_MANIP_SRC);
+   range_set_for_snat = 1;
}
+
+   /* Perform SRC manip. */
+   if (range_set_for_snat)
+   nf_nat_setup_info(ct, , NF_NAT_MANIP_SRC);
 }
 
 static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int 
protoff,
-- 
2.7.4



[PATCH v2] ipv6: Preserve link scope traffic original oif

2018-11-21 Thread Alin Nastac
When ip6_route_me_harder is invoked, it resets outgoing interface of:
  - link-local scoped packets sent by neighbor discovery
  - multicast packets sent by MLD host
  - multicast packets send by MLD proxy daemon that sets outgoing
interface through IPV6_PKTINFO ipi6_ifindex

Link-local and multicast packets must keep their original oif after
ip6_route_me_harder is called.

Signed-off-by: Alin Nastac 
---
 net/ipv6/netfilter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 5ae8e1c..8b075f0 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
-   .flowi6_oif = sk ? sk->sk_bound_dev_if : 0,
+   .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
+   rt6_need_strict(>daddr) ? 
skb_dst(skb)->dev->ifindex : 0,
.flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, sk),
.daddr = iph->daddr,
-- 
2.7.4



[PATCH v2] ipv6: Preserve link scope traffic original oif

2018-11-21 Thread Alin Nastac
When ip6_route_me_harder is invoked, it resets outgoing interface of:
  - link-local scoped packets sent by neighbor discovery
  - multicast packets sent by MLD host
  - multicast packets send by MLD proxy daemon that sets outgoing
interface through IPV6_PKTINFO ipi6_ifindex

Link-local and multicast packets must keep their original oif after
ip6_route_me_harder is called.
---
 net/ipv6/netfilter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 5ae8e1c..8b075f0 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
-   .flowi6_oif = sk ? sk->sk_bound_dev_if : 0,
+   .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
+   rt6_need_strict(>daddr) ? 
skb_dst(skb)->dev->ifindex : 0,
.flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, sk),
.daddr = iph->daddr,
-- 
2.7.4



[PATCH] netfilter: nf_nat_sip: fix RTP/RTCP source port translations

2018-11-05 Thread Alin Nastac
Perform the same SNAT translation on RTP/RTCP conntracks regardless of
who sends the first datagram.

Prior to this change, RTP packets send by the peer who required source
port translation were forwarded with unmodified source port when this
peer started its voice/video stream first.
---
 net/netfilter/nf_nat_sip.c | 35 +++
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c
index 1f30860..a1e23cc 100644
--- a/net/netfilter/nf_nat_sip.c
+++ b/net/netfilter/nf_nat_sip.c
@@ -18,6 +18,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -316,6 +317,9 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, 
unsigned int protoff,
 static void nf_nat_sip_expected(struct nf_conn *ct,
struct nf_conntrack_expect *exp)
 {
+   struct nf_conn_help *help = nfct_help(ct->master);
+   struct nf_conntrack_expect *pair_exp;
+   int range_set_for_snat = 0;
struct nf_nat_range2 range;
 
/* This must be a fresh one. */
@@ -327,15 +331,38 @@ static void nf_nat_sip_expected(struct nf_conn *ct,
range.min_addr = range.max_addr = exp->saved_addr;
nf_nat_setup_info(ct, , NF_NAT_MANIP_DST);
 
-   /* Change src to where master sends to, but only if the connection
-* actually came from the same source. */
-   if (nf_inet_addr_cmp(>tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
+   /* Do SRC manip according with the parameters found in the
+* paired expected conntrack. */
+   spin_lock_bh(_conntrack_expect_lock);
+   hlist_for_each_entry(pair_exp, >expectations, lnode) {
+   if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) &&
+   pair_exp->tuple.dst.protonum == 
ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum &&
+   
nf_inet_addr_cmp(>tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, 
_exp->saved_addr) &&
+   ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == 
pair_exp->saved_proto.all) {
+   range.flags = (NF_NAT_RANGE_MAP_IPS | 
NF_NAT_RANGE_PROTO_SPECIFIED);
+   range.min_proto.all = range.max_proto.all = 
pair_exp->tuple.dst.u.all;
+   range.min_addr = range.max_addr = 
pair_exp->tuple.dst.u3;
+   range_set_for_snat = 1;
+   break;
+   }
+   }
+   spin_unlock_bh(_conntrack_expect_lock);
+
+   /* When no paired expected conntrack has been found, change src to
+* where master sends to, but only if the connection actually came
+* from the same source. */
+   if (!range_set_for_snat &&
+   nf_inet_addr_cmp(>tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
 >master->tuplehash[exp->dir].tuple.src.u3)) {
range.flags = NF_NAT_RANGE_MAP_IPS;
range.min_addr = range.max_addr
= ct->master->tuplehash[!exp->dir].tuple.dst.u3;
-   nf_nat_setup_info(ct, , NF_NAT_MANIP_SRC);
+   range_set_for_snat = 1;
}
+
+   /* Perform SRC manip. */
+   if (range_set_for_snat)
+   nf_nat_setup_info(ct, , NF_NAT_MANIP_SRC);
 }
 
 static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int 
protoff,
-- 
2.7.4



[PATCH] netfilter: add grev6 conntrack support

2018-10-18 Thread Alin Nastac
From: Alin Nastac 

nf_conntrack_proto_generic refuse to handle grev6 packets when
NF_CT_PROTO_GRE is enabled, resulting in grev6 packets being
categorized as INVALID.
---
 net/netfilter/nf_conntrack_proto_gre.c | 49 +-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nf_conntrack_proto_gre.c 
b/net/netfilter/nf_conntrack_proto_gre.c
index 650eb4f..c6b249d 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -380,19 +380,60 @@ static const struct nf_conntrack_l4proto 
nf_conntrack_l4proto_gre4 = {
.init_net   = gre_init_net,
 };
 
+static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre6 = {
+   .l3proto = AF_INET6,
+   .l4proto = IPPROTO_GRE,
+   .pkt_to_tuple= gre_pkt_to_tuple,
+#ifdef CONFIG_NF_CONNTRACK_PROCFS
+   .print_conntrack = gre_print_conntrack,
+#endif
+   .packet  = gre_packet,
+   .new = gre_new,
+   .destroy = gre_destroy,
+   .me  = THIS_MODULE,
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
+   .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+   .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
+   .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+   .nla_policy  = nf_ct_port_nla_policy,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+   .ctnl_timeout= {
+   .nlattr_to_obj  = gre_timeout_nlattr_to_obj,
+   .obj_to_nlattr  = gre_timeout_obj_to_nlattr,
+   .nlattr_max = CTA_TIMEOUT_GRE_MAX,
+   .obj_size   = sizeof(unsigned int) * GRE_CT_MAX,
+   .nla_policy = gre_timeout_nla_policy,
+   },
+#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
+   .net_id = _gre_net_id,
+   .init_net   = gre_init_net,
+};
+
 static int proto_gre_net_init(struct net *net)
 {
int ret = 0;
 
ret = nf_ct_l4proto_pernet_register_one(net,
_conntrack_l4proto_gre4);
-   if (ret < 0)
+   if (ret < 0) {
pr_err("nf_conntrack_gre4: pernet registration failed.\n");
+   return ret;
+   }
+
+   ret = nf_ct_l4proto_pernet_register_one(net,
+   _conntrack_l4proto_gre6);
+   if (ret < 0) {
+   pr_err("nf_conntrack_gre6: pernet registration failed.\n");
+   nf_ct_l4proto_pernet_unregister_one(net, 
_conntrack_l4proto_gre4);
+   }
+
return ret;
 }
 
 static void proto_gre_net_exit(struct net *net)
 {
+   nf_ct_l4proto_pernet_unregister_one(net, _conntrack_l4proto_gre6);
nf_ct_l4proto_pernet_unregister_one(net, _conntrack_l4proto_gre4);
nf_ct_gre_keymap_flush(net);
 }
@@ -414,8 +455,13 @@ static int __init nf_ct_proto_gre_init(void)
ret = nf_ct_l4proto_register_one(_conntrack_l4proto_gre4);
if (ret < 0)
goto out_gre4;
+   ret = nf_ct_l4proto_register_one(_conntrack_l4proto_gre6);
+   if (ret < 0)
+   goto out_gre6;
 
return 0;
+out_gre6:
+   nf_ct_l4proto_unregister_one(_conntrack_l4proto_gre4);
 out_gre4:
unregister_pernet_subsys(_gre_net_ops);
 out_pernet:
@@ -424,6 +470,7 @@ static int __init nf_ct_proto_gre_init(void)
 
 static void __exit nf_ct_proto_gre_fini(void)
 {
+   nf_ct_l4proto_unregister_one(_conntrack_l4proto_gre6);
nf_ct_l4proto_unregister_one(_conntrack_l4proto_gre4);
unregister_pernet_subsys(_gre_net_ops);
 }
-- 
2.7.4



[PATCH] ebtables: fix compat entry padding

2018-05-30 Thread Alin Nastac
On arm64, ebt_entry_{match,watcher,target} structs are 40 bytes long
while on 32-bit arm these structs have a size of 36 bytes.

COMPAT_XT_ALIGN() macro cannot be used here to determine the necessary
padding for the CONFIG_COMPAT because it imposes an 8-byte boundary
alignment, condition that is not found in 32-bit ebtables application.

Signed-off-by: Alin Nastac 
---
 net/bridge/netfilter/ebtables.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 28a4c34..91cf3df 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1610,16 +1610,16 @@ struct compat_ebt_entry_mwt {
compat_uptr_t ptr;
} u;
compat_uint_t match_size;
-   compat_uint_t data[0];
+   compat_uint_t data[0] __attribute__ ((aligned (__alignof__(struct 
compat_ebt_replace;
 };
 
 /* account for possible padding between match_size and ->data */
 static int ebt_compat_entry_padsize(void)
 {
-   BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) <
-   COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)));
-   return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) -
-   COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt));
+   BUILD_BUG_ON(sizeof(struct ebt_entry_match) <
+   sizeof(struct compat_ebt_entry_mwt));
+   return (int) sizeof(struct ebt_entry_match) -
+   sizeof(struct compat_ebt_entry_mwt);
 }
 
 static int ebt_compat_match_offset(const struct xt_match *match,
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ebtables: fix limit and mark modules incompatibilities between 32-bit user space and 64-bit kernel space

2018-05-28 Thread Alin Nastac
Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 include/linux/netfilter_bridge/ebt_limit.h  | 4 
 include/linux/netfilter_bridge/ebt_mark_m.h | 5 +
 include/linux/netfilter_bridge/ebt_mark_t.h | 4 
 3 files changed, 13 insertions(+)

diff --git a/include/linux/netfilter_bridge/ebt_limit.h 
b/include/linux/netfilter_bridge/ebt_limit.h
index 66d80b3..6db2443 100644
--- a/include/linux/netfilter_bridge/ebt_limit.h
+++ b/include/linux/netfilter_bridge/ebt_limit.h
@@ -16,7 +16,11 @@ struct ebt_limit_info {
__u32 burst;  /* Period multiplier for upper limit. */
 
/* Used internally by the kernel */
+#ifdef KERNEL_64_USERSPACE_32
+   uint64_t prev;
+#else
unsigned long prev;
+#endif
__u32 credit;
__u32 credit_cap, cost;
 };
diff --git a/include/linux/netfilter_bridge/ebt_mark_m.h 
b/include/linux/netfilter_bridge/ebt_mark_m.h
index 410f9e5..017307f 100644
--- a/include/linux/netfilter_bridge/ebt_mark_m.h
+++ b/include/linux/netfilter_bridge/ebt_mark_m.h
@@ -7,7 +7,12 @@
 #define EBT_MARK_OR 0x02
 #define EBT_MARK_MASK (EBT_MARK_AND | EBT_MARK_OR)
 struct ebt_mark_m_info {
+#ifdef KERNEL_64_USERSPACE_32
+   union { uint64_t pad1; unsigned long mark; };
+   union { uint64_t pad2; unsigned long mask; };
+#else
unsigned long mark, mask;
+#endif
__u8 invert;
__u8 bitmask;
 };
diff --git a/include/linux/netfilter_bridge/ebt_mark_t.h 
b/include/linux/netfilter_bridge/ebt_mark_t.h
index 7d5a268..5f0f6d5 100644
--- a/include/linux/netfilter_bridge/ebt_mark_t.h
+++ b/include/linux/netfilter_bridge/ebt_mark_t.h
@@ -14,7 +14,11 @@
 #define MARK_XOR_VALUE (0xffc0)
 
 struct ebt_mark_t_info {
+#ifdef KERNEL_64_USERSPACE_32
+   union { uint64_t pad; unsigned long mark; };
+#else
unsigned long mark;
+#endif
/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
int target;
 };
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3] extensions: libxt_hashlimit: fix uint64_t printf formats

2017-05-24 Thread Alin Nastac
From: Alin Nastac <alin.nas...@gmail.com>

The remaining %llu formats are used for unsigned long long values.

Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 extensions/libxt_hashlimit.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index 9e63e1e..d7de540 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -736,7 +736,7 @@ hashlimit_mt_print(const struct hashlimit_cfg2 *cfg, 
unsigned int dmask, int rev
quantum = print_bytes(cfg->avg, cfg->burst, "");
} else {
quantum = print_rate(cfg->avg, revision);
-   printf(" burst %llu", cfg->burst);
+   printf(" burst %"PRIu64, cfg->burst);
}
if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
@@ -846,7 +846,7 @@ hashlimit_mt_save(const struct hashlimit_cfg2 *cfg, const 
char* name, unsigned i
quantum = print_bytes(cfg->avg, cfg->burst, "--hashlimit-");
} else {
quantum = print_rate(cfg->avg, revision);
-   printf(" --hashlimit-burst %llu", cfg->burst);
+   printf(" --hashlimit-burst %"PRIu64, cfg->burst);
}
 
if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
@@ -942,7 +942,7 @@ static void print_packets_rate_xlate(struct xt_xlate *xl, 
uint64_t avg,
_rates[i].mult / avg < _rates[i].mult % avg)
break;
 
-   xt_xlate_add(xl, " %llu/%s burst %lu packets",
+   xt_xlate_add(xl, " %"PRIu64"/%s burst %"PRIu64" packets",
 _rates[i-1].mult / avg, _rates[i-1].name, burst);
 }
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] extensions: libxt_hashlimit: fix 64-bit printf formats

2017-05-18 Thread Alin Nastac
Furthermore, this extension use a mix of PRIu64 and %llu formats for
uint64_t values. IMO it should use only one, for the sake of consistency.

Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 extensions/libxt_hashlimit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index 9e63e1e..970bad9 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -942,7 +942,7 @@ static void print_packets_rate_xlate(struct xt_xlate *xl, 
uint64_t avg,
_rates[i].mult / avg < _rates[i].mult % avg)
break;
 
-   xt_xlate_add(xl, " %llu/%s burst %lu packets",
+   xt_xlate_add(xl, " %"PRIu64"/%s burst %"PRIu64" packets",
 _rates[i-1].mult / avg, _rates[i-1].name, burst);
 }
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] netfilter: Parse ICMPv6 redirects

2017-03-07 Thread Alin Nastac
Extract IPv6 packet that triggered the sending of redirect message from
ICMPv6 Redirected Header option and check if conntrack table contain such
connection. Mark redirect packet as RELATED if a matching connection is found.

Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 87 --
 1 file changed, 82 insertions(+), 5 deletions(-)

diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c 
b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index d2c2ccb..f7bae5c 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -144,7 +144,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct 
sk_buff *skb,
 static int
 icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
 struct sk_buff *skb,
-unsigned int icmp6off,
+unsigned int inneripv6off,
 unsigned int hooknum)
 {
struct nf_conntrack_tuple intuple, origtuple;
@@ -157,9 +157,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct 
sk_buff *skb,
 
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuplepr(skb,
-  skb_network_offset(skb)
-   + sizeof(struct ipv6hdr)
-   + sizeof(struct icmp6hdr),
+  inneripv6off,
   PF_INET6, net, )) {
pr_debug("icmpv6_error: Can't get tuple\n");
return -NF_ACCEPT;
@@ -194,6 +192,82 @@ static bool icmpv6_new(struct nf_conn *ct, const struct 
sk_buff *skb,
 }
 
 static int
+icmpv6_redirect_message(struct net *net, struct nf_conn *tmpl,
+struct sk_buff *skb,
+unsigned int dataoff,
+unsigned int hooknum)
+{
+   const struct in6_addr *dst;
+   struct in6_addr _dst;
+   const struct nd_opt_hdr *opt;
+   struct nd_opt_hdr _opt;
+   const struct ipv6hdr *iph;
+   struct ipv6hdr _iph;
+
+   /* skip target address */
+   dataoff += sizeof(_dst);
+
+   /* read destination address */
+   dst = skb_header_pointer(skb, dataoff, sizeof(_dst), &_dst);
+   if (dst == NULL) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
+ "nf_ct_icmpv6: short redirect packet ");
+   return -NF_ACCEPT;
+   }
+   if (ipv6_addr_is_multicast(dst)) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
+ "nf_ct_icmpv6: redirect destination address is 
multicast ");
+   return -NF_ACCEPT;
+   }
+   dataoff += sizeof(_dst);
+
+   /* find redirected header */
+   while (1) {
+   opt = skb_header_pointer(skb, dataoff, sizeof(_opt), &_opt);
+   if (opt == NULL) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, 
NULL, NULL,
+ "nf_ct_icmpv6: invalid redirect option ");
+   return -NF_ACCEPT;
+   }
+   if (opt->nd_opt_len == 0) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, 
NULL, NULL,
+ "nf_ct_icmpv6: invalid redirect option 
length ");
+   return -NF_ACCEPT;
+   }
+
+   if (opt->nd_opt_type == ND_OPT_REDIRECT_HDR) {
+   dataoff += 8;
+   break;
+   }
+
+   dataoff += opt->nd_opt_len << 3;
+   }
+
+   /* read redirect header */
+   iph = skb_header_pointer(skb, dataoff, sizeof(_iph), &_iph);
+   if (iph == NULL) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
+ "nf_ct_icmpv6: short redirect header ");
+   return -NF_ACCEPT;
+   }
+
+   /* validate destination address */
+   if (!ipv6_addr_equal(>daddr, dst)) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
+ "nf_ct_icmpv6: redirect destination address not 
matching destination address of redirect header ");
+   return -NF_ACCEPT;
+   }
+   
+   return icmpv6_error_message(net, tmpl, skb, dataoff, hooknum);
+}
+
+static int
 icmpv6_error(struct net *net, struct nf_conn *tmpl,
 struct sk_b

[PATCH] netfilter: Parse ICMPv6 redirects

2017-03-01 Thread Alin Nastac
Extract IPv6 packet that triggered the sending of redirect message from
ICMPv6 Redirected Header option and check if conntrack table contain such
connection. Mark redirect packet as RELATED if a matching connection is found.

Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 77 --
 1 file changed, 72 insertions(+), 5 deletions(-)

diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c 
b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index d2c2ccb..2f9a985 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -144,7 +144,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct 
sk_buff *skb,
 static int
 icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
 struct sk_buff *skb,
-unsigned int icmp6off,
+unsigned int inneripv6off,
 unsigned int hooknum)
 {
struct nf_conntrack_tuple intuple, origtuple;
@@ -157,9 +157,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct 
sk_buff *skb,
 
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuplepr(skb,
-  skb_network_offset(skb)
-   + sizeof(struct ipv6hdr)
-   + sizeof(struct icmp6hdr),
+  inneripv6off,
   PF_INET6, net, )) {
pr_debug("icmpv6_error: Can't get tuple\n");
return -NF_ACCEPT;
@@ -225,9 +223,78 @@ static bool icmpv6_new(struct nf_conn *ct, const struct 
sk_buff *skb,
nf_conntrack_get(skb_nfct(skb));
return NF_ACCEPT;
}
+   dataoff += sizeof(struct icmp6hdr);
 
/* is not error message ? */
-   if (icmp6h->icmp6_type >= 128)
+   if (icmp6h->icmp6_type == NDISC_REDIRECT) {
+   const struct in6_addr *dst;
+   struct in6_addr _dst;
+   const struct nd_opt_hdr *opt;
+   struct nd_opt_hdr _opt;
+   const struct ipv6hdr *iph;
+   struct ipv6hdr _iph;
+
+   /* skip target address */
+   dataoff += sizeof(_dst);
+
+   /* read destination address */
+   dst = skb_header_pointer(skb, dataoff, sizeof(_dst), &_dst);
+   if (dst == NULL) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, 
NULL, NULL,
+ "nf_ct_icmpv6: short redirect packet ");
+   return -NF_ACCEPT;
+   }
+   if (ipv6_addr_is_multicast(dst)) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, 
NULL, NULL,
+ "nf_ct_icmpv6: redirect destination 
address is multicast ");
+   return -NF_ACCEPT;
+   }
+   dataoff += sizeof(_dst);
+
+   /* find redirected header */
+   while (1) {
+   opt = skb_header_pointer(skb, dataoff, sizeof(_opt), 
&_opt);
+   if (opt == NULL) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, 
NULL, NULL, NULL,
+ "nf_ct_icmpv6: invalid redirect 
option ");
+   return -NF_ACCEPT;
+   }
+   if (opt->nd_opt_len == 0) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, 
NULL, NULL, NULL,
+ "nf_ct_icmpv6: invalid redirect 
option length ");
+   return -NF_ACCEPT;
+   }
+
+   if (opt->nd_opt_type == ND_OPT_REDIRECT_HDR) {
+   dataoff += 8;
+   break;
+   }
+
+   dataoff += opt->nd_opt_len << 3;
+   }
+
+   /* read redirect header */
+   iph = skb_header_pointer(skb, dataoff, sizeof(_iph), &_iph);
+   if (iph == NULL) {
+   if (LOG_INVALID(net, IPPROTO_ICMPV6))
+   nf_log_packet(net, PF_INET6, 0, skb, NULL, 
NULL, NULL,
+ "nf_ct_icmpv6: short redirect header ");
+   return -NF_ACCEPT;
+   }
+
+   /* validate destination address */
+ 

[PATCH] ipv6: Preserve link scope traffic original oif

2017-03-01 Thread Alin Nastac
Link-local and multicast packets must keep their original oif after
ip6_route_me_harder is called.

Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 net/ipv6/netfilter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 39970e2..02811c5 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
-   .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+   .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if :
+   rt6_need_strict(>daddr) ? 
skb_dst(skb)->dev->ifindex : 0,
.flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, skb->sk),
.daddr = iph->daddr,
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ipv6: Preserve link scope traffic original oif

2017-03-01 Thread Alin Nastac
Link-local and multicast packets must keep their original oif after
ip6_route_me_harder is called.

Signed-off-by: Alin Nastac <alin.nas...@gmail.com>
---
 net/ipv6/netfilter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 39970e2..02811c5 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
-   .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+   .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if :
+   rt6_need_strict(>daddr) ? 
skb_dst(skb)->dev->ifindex : 0,
.flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, skb->sk),
.daddr = iph->daddr,
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html