#define PACKET_FANOUT_LB 1
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
-@@ -1393,6 +1393,7 @@ static int packet_rcv_spkt(struct sk_buf
+@@ -1414,6 +1414,7 @@ static int packet_rcv_spkt(struct sk_buf
{
struct sock *sk;
struct sockaddr_pkt *spkt;
/*
* When we registered the protocol we saved the socket in the data
-@@ -1400,6 +1401,7 @@ static int packet_rcv_spkt(struct sk_buf
+@@ -1421,6 +1422,7 @@ static int packet_rcv_spkt(struct sk_buf
*/
sk = pt->af_packet_priv;
/*
* Yank back the headers [hope the device set this
-@@ -1412,7 +1414,7 @@ static int packet_rcv_spkt(struct sk_buf
+@@ -1433,7 +1435,7 @@ static int packet_rcv_spkt(struct sk_buf
* so that this procedure is noop.
*/
goto out;
if (!net_eq(dev_net(dev), sock_net(sk)))
-@@ -1619,12 +1621,12 @@ static int packet_rcv(struct sk_buff *sk
+@@ -1640,12 +1642,12 @@ static int packet_rcv(struct sk_buff *sk
int skb_len = skb->len;
unsigned int snaplen, res;
if (!net_eq(dev_net(dev), sock_net(sk)))
goto drop;
-@@ -1737,12 +1739,12 @@ static int tpacket_rcv(struct sk_buff *s
+@@ -1758,12 +1760,12 @@ static int tpacket_rcv(struct sk_buff *s
struct timespec ts;
__u32 ts_status;
if (!net_eq(dev_net(dev), sock_net(sk)))
goto drop;
-@@ -2638,6 +2640,7 @@ static int packet_create(struct net *net
+@@ -2652,6 +2654,7 @@ static int packet_create(struct net *net
spin_lock_init(&po->bind_lock);
mutex_init(&po->pg_vec_lock);
po->prot_hook.func = packet_rcv;
if (sock->type == SOCK_PACKET)
po->prot_hook.func = packet_rcv_spkt;
-@@ -3204,6 +3207,16 @@ packet_setsockopt(struct socket *sock, i
+@@ -3218,6 +3221,16 @@ packet_setsockopt(struct socket *sock, i
po->tp_tx_has_off = !!val;
return 0;
}
default:
return -ENOPROTOOPT;
}
-@@ -3255,6 +3268,13 @@ static int packet_getsockopt(struct sock
+@@ -3269,6 +3282,13 @@ static int packet_getsockopt(struct sock
case PACKET_VNET_HDR:
val = po->has_vnet_hdr;
break;
+From 1b5aaa4b16f6e6471ab1c07b38068197a1b4c395 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Fri, 24 May 2013 14:40:54 +0200
+Subject: [PATCH 1/2] ipv6: allow rejecting with "source address failed policy"
+
+RFC6204 L-14 requires rejecting traffic from invalid addresses with
+ICMPv6 Destination Unreachable, Code 5 (Source address failed ingress/
+egress policy) on the LAN side, so add an appropriate rule for that.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ include/net/netns/ipv6.h | 1 +
+ include/uapi/linux/fib_rules.h | 4 +++
+ include/uapi/linux/rtnetlink.h | 1 +
+ net/ipv4/fib_semantics.c | 4 +++
+ net/ipv4/fib_trie.c | 1 +
+ net/ipv4/ipmr.c | 1 +
+ net/ipv6/fib6_rules.c | 4 +++
+ net/ipv6/ip6mr.c | 2 ++
+ net/ipv6/route.c | 58 +++++++++++++++++++++++++++++++++++++++++-
+ 9 files changed, 75 insertions(+), 1 deletion(-)
+
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -55,6 +55,7 @@ struct netns_ipv6 {
unsigned long ip6_rt_last_gc;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
struct rt6_info *ip6_prohibit_entry;
-+ struct rt6_info *ip6_failed_policy_entry;
++ struct rt6_info *ip6_policy_failed_entry;
struct rt6_info *ip6_blk_hole_entry;
struct fib6_table *fib6_local_tbl;
struct fib_rules_ops *fib6_rules_ops;
+ FR_ACT_RES9,
+ FR_ACT_RES10,
+ FR_ACT_RES11,
-+ FR_ACT_FAILED_POLICY, /* Drop with EPERM */
++ FR_ACT_POLICY_FAILED, /* Drop with EACCES */
__FR_ACT_MAX,
};
RTN_THROW, /* Not in this table */
RTN_NAT, /* Translate this address */
RTN_XRESOLVE, /* Use external resolver */
-+ RTN_FAILED_POLICY, /* Failed ingress/egress policy */
++ RTN_POLICY_FAILED, /* Failed ingress/egress policy */
__RTN_MAX
};
---- a/net/ipv4/fib_rules.c
-+++ b/net/ipv4/fib_rules.c
-@@ -84,6 +84,10 @@ static int fib4_rule_action(struct fib_r
- err = -EACCES;
- goto errout;
-
-+ case FR_ACT_FAILED_POLICY:
-+ err = -EPERM;
-+ goto errout;
-+
- case FR_ACT_BLACKHOLE:
- default:
- err = -EINVAL;
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX
.error = -EINVAL,
.scope = RT_SCOPE_NOWHERE,
},
-+ [RTN_FAILED_POLICY] = {
-+ .error = -EPERM,
++ [RTN_POLICY_FAILED] = {
++ .error = -EACCES,
+ .scope = RT_SCOPE_UNIVERSE,
+ },
};
[RTN_THROW] = "THROW",
[RTN_NAT] = "NAT",
[RTN_XRESOLVE] = "XRESOLVE",
-+ [RTN_FAILED_POLICY] = "FAILED_POLICY",
++ [RTN_POLICY_FAILED] = "POLICY_FAILED",
};
static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
-@@ -181,6 +181,7 @@ static int ipmr_rule_action(struct fib_r
+@@ -184,6 +184,7 @@ static int ipmr_rule_action(struct fib_r
case FR_ACT_UNREACHABLE:
return -ENETUNREACH;
case FR_ACT_PROHIBIT:
-+ case FR_ACT_FAILED_POLICY:
++ case FR_ACT_POLICY_FAILED:
return -EACCES;
case FR_ACT_BLACKHOLE:
default:
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
-@@ -73,6 +73,9 @@ static int fib6_rule_action(struct fib_r
+@@ -73,6 +73,10 @@ static int fib6_rule_action(struct fib_r
err = -EACCES;
rt = net->ipv6.ip6_prohibit_entry;
goto discard_pkt;
-+ case FR_ACT_FAILED_POLICY:
-+ rt = net->ipv6.ip6_failed_policy_entry;
++ case FR_ACT_POLICY_FAILED:
++ err = -EACCES;
++ rt = net->ipv6.ip6_policy_failed_entry;
+ goto discard_pkt;
}
table = fib6_get_table(net, rule->table);
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
-@@ -166,6 +166,8 @@ static int ip6mr_rule_action(struct fib_
+@@ -169,6 +169,8 @@ static int ip6mr_rule_action(struct fib_
return -ENETUNREACH;
case FR_ACT_PROHIBIT:
return -EACCES;
-+ case FR_ACT_FAILED_POLICY:
-+ return -EPERM;
++ case FR_ACT_POLICY_FAILED:
++ return -EACCES;
case FR_ACT_BLACKHOLE:
default:
return -EINVAL;
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
-@@ -252,6 +252,24 @@ static const struct rt6_info ip6_prohibi
+@@ -86,6 +86,8 @@ static int ip6_pkt_discard(struct sk_bu
+ static int ip6_pkt_discard_out(struct sk_buff *skb);
+ static int ip6_pkt_prohibit(struct sk_buff *skb);
+ static int ip6_pkt_prohibit_out(struct sk_buff *skb);
++static int ip6_pkt_policy_failed(struct sk_buff *skb);
++static int ip6_pkt_policy_failed_out(struct sk_buff *skb);
+ static void ip6_link_failure(struct sk_buff *skb);
+ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
+ struct sk_buff *skb, u32 mtu);
+@@ -251,6 +253,21 @@ static const struct rt6_info ip6_prohibi
.rt6i_ref = ATOMIC_INIT(1),
};
-+static int ip6_pkt_failed_policy(struct sk_buff *skb);
-+static int ip6_pkt_failed_policy_out(struct sk_buff *skb);
-+
-+static const struct rt6_info ip6_failed_policy_entry_template = {
++static const struct rt6_info ip6_policy_failed_entry_template = {
+ .dst = {
+ .__refcnt = ATOMIC_INIT(1),
+ .__use = 1,
+ .obsolete = DST_OBSOLETE_FORCE_CHK,
-+ .error = -EPERM,
-+ .input = ip6_pkt_failed_policy,
-+ .output = ip6_pkt_failed_policy_out,
++ .error = -EACCES,
++ .input = ip6_pkt_policy_failed,
++ .output = ip6_pkt_policy_failed_out,
+ },
+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
+ .rt6i_protocol = RTPROT_KERNEL,
static const struct rt6_info ip6_blk_hole_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
-@@ -1583,6 +1601,9 @@ int ip6_route_add(struct fib6_config *cf
- case RTN_THROW:
- rt->dst.error = -EAGAIN;
+@@ -1581,6 +1598,11 @@ int ip6_route_add(struct fib6_config *cf
+ rt->dst.output = ip6_pkt_prohibit_out;
+ rt->dst.input = ip6_pkt_prohibit;
break;
-+ case RTN_FAILED_POLICY:
-+ rt->dst.error = -EPERM;
++ case RTN_POLICY_FAILED:
++ rt->dst.error = -EACCES;
++ rt->dst.output = ip6_pkt_policy_failed_out;
++ rt->dst.input = ip6_pkt_policy_failed;
+ break;
+ case RTN_THROW:
default:
- rt->dst.error = -ENETUNREACH;
- break;
-@@ -2162,6 +2183,17 @@ static int ip6_pkt_prohibit_out(struct s
+ rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
+@@ -2160,6 +2182,17 @@ static int ip6_pkt_prohibit_out(struct s
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
}
-+static int ip6_pkt_failed_policy(struct sk_buff *skb)
++static int ip6_pkt_policy_failed(struct sk_buff *skb)
+{
+ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES);
+}
+
-+static int ip6_pkt_failed_policy_out(struct sk_buff *skb)
++static int ip6_pkt_policy_failed_out(struct sk_buff *skb)
+{
+ skb->dev = skb_dst(skb)->dev;
+ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES);
+}
+
- #endif
-
/*
-@@ -2368,7 +2400,8 @@ static int rtm_to_fib6_config(struct sk_
+ * Allocate a dst for local (unicast / anycast) address.
+ */
+@@ -2362,7 +2395,8 @@ static int rtm_to_fib6_config(struct sk_
if (rtm->rtm_type == RTN_UNREACHABLE ||
rtm->rtm_type == RTN_BLACKHOLE ||
rtm->rtm_type == RTN_PROHIBIT ||
- rtm->rtm_type == RTN_THROW)
+ rtm->rtm_type == RTN_THROW ||
-+ rtm->rtm_type == RTN_FAILED_POLICY)
++ rtm->rtm_type == RTN_POLICY_FAILED)
cfg->fc_flags |= RTF_REJECT;
if (rtm->rtm_type == RTN_LOCAL)
-@@ -2570,6 +2603,9 @@ static int rt6_fill_node(struct net *net
+@@ -2564,6 +2598,9 @@ static int rt6_fill_node(struct net *net
case -EACCES:
rtm->rtm_type = RTN_PROHIBIT;
break;
+ case -EPERM:
-+ rtm->rtm_type = RTN_FAILED_POLICY;
++ rtm->rtm_type = RTN_POLICY_FAILED;
+ break;
case -EAGAIN:
rtm->rtm_type = RTN_THROW;
break;
-@@ -2820,6 +2856,8 @@ static int ip6_route_dev_notify(struct n
+@@ -2814,6 +2851,8 @@ static int ip6_route_dev_notify(struct n
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
net->ipv6.ip6_prohibit_entry->dst.dev = dev;
net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
-+ net->ipv6.ip6_failed_policy_entry->dst.dev = dev;
-+ net->ipv6.ip6_failed_policy_entry->rt6i_idev = in6_dev_get(dev);
++ net->ipv6.ip6_policy_failed_entry->dst.dev = dev;
++ net->ipv6.ip6_policy_failed_entry->rt6i_idev = in6_dev_get(dev);
net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
#endif
-@@ -3080,6 +3118,17 @@ static int __net_init ip6_route_net_init
+@@ -3074,6 +3113,17 @@ static int __net_init ip6_route_net_init
net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
ip6_template_metrics, true);
+
-+ net->ipv6.ip6_failed_policy_entry =
-+ kmemdup(&ip6_failed_policy_entry_template,
-+ sizeof(*net->ipv6.ip6_failed_policy_entry), GFP_KERNEL);
-+ if (!net->ipv6.ip6_failed_policy_entry)
++ net->ipv6.ip6_policy_failed_entry =
++ kmemdup(&ip6_policy_failed_entry_template,
++ sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL);
++ if (!net->ipv6.ip6_policy_failed_entry)
+ goto out_ip6_blk_hole_entry;
-+ net->ipv6.ip6_failed_policy_entry->dst.path =
-+ (struct dst_entry *)net->ipv6.ip6_failed_policy_entry;
-+ net->ipv6.ip6_failed_policy_entry->dst.ops = &net->ipv6.ip6_dst_ops;
-+ dst_init_metrics(&net->ipv6.ip6_failed_policy_entry->dst,
++ net->ipv6.ip6_policy_failed_entry->dst.path =
++ (struct dst_entry *)net->ipv6.ip6_policy_failed_entry;
++ net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops;
++ dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst,
+ ip6_template_metrics, true);
#endif
net->ipv6.sysctl.flush_delay = 0;
-@@ -3098,6 +3147,8 @@ out:
+@@ -3092,6 +3142,8 @@ out:
return ret;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
out_ip6_prohibit_entry:
kfree(net->ipv6.ip6_prohibit_entry);
out_ip6_null_entry:
-@@ -3115,6 +3166,7 @@ static void __net_exit ip6_route_net_exi
+@@ -3109,6 +3161,7 @@ static void __net_exit ip6_route_net_exi
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.ip6_prohibit_entry);
kfree(net->ipv6.ip6_blk_hole_entry);
-+ kfree(net->ipv6.ip6_failed_policy_entry);
++ kfree(net->ipv6.ip6_policy_failed_entry);
#endif
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
}
-@@ -3211,6 +3263,9 @@ int __init ip6_route_init(void)
+@@ -3205,6 +3258,9 @@ int __init ip6_route_init(void)
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-+ init_net.ipv6.ip6_failed_policy_entry->dst.dev = init_net.loopback_dev;
-+ init_net.ipv6.ip6_failed_policy_entry->rt6i_idev =
++ init_net.ipv6.ip6_policy_failed_entry->dst.dev = init_net.loopback_dev;
++ init_net.ipv6.ip6_policy_failed_entry->rt6i_idev =
+ in6_dev_get(init_net.loopback_dev);
#endif
ret = fib6_init();