diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 24 | ||||
-rw-r--r-- | net/ipv6/addrconf_core.c | 19 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_rpfilter.c | 8 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 12 |
4 files changed, 39 insertions, 24 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 28b61e89bbb8..d1ab6ab29a55 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -169,8 +169,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
169 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 169 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
170 | struct net_device *dev); | 170 | struct net_device *dev); |
171 | 171 | ||
172 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | ||
173 | |||
174 | static struct ipv6_devconf ipv6_devconf __read_mostly = { | 172 | static struct ipv6_devconf ipv6_devconf __read_mostly = { |
175 | .forwarding = 0, | 173 | .forwarding = 0, |
176 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, | 174 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, |
@@ -910,7 +908,7 @@ out2: | |||
910 | rcu_read_unlock_bh(); | 908 | rcu_read_unlock_bh(); |
911 | 909 | ||
912 | if (likely(err == 0)) | 910 | if (likely(err == 0)) |
913 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); | 911 | inet6addr_notifier_call_chain(NETDEV_UP, ifa); |
914 | else { | 912 | else { |
915 | kfree(ifa); | 913 | kfree(ifa); |
916 | ifa = ERR_PTR(err); | 914 | ifa = ERR_PTR(err); |
@@ -1000,7 +998,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
1000 | 998 | ||
1001 | ipv6_ifa_notify(RTM_DELADDR, ifp); | 999 | ipv6_ifa_notify(RTM_DELADDR, ifp); |
1002 | 1000 | ||
1003 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp); | 1001 | inet6addr_notifier_call_chain(NETDEV_DOWN, ifp); |
1004 | 1002 | ||
1005 | /* | 1003 | /* |
1006 | * Purge or update corresponding prefix | 1004 | * Purge or update corresponding prefix |
@@ -3087,7 +3085,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3087 | 3085 | ||
3088 | if (state != INET6_IFADDR_STATE_DEAD) { | 3086 | if (state != INET6_IFADDR_STATE_DEAD) { |
3089 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 3087 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
3090 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 3088 | inet6addr_notifier_call_chain(NETDEV_DOWN, ifa); |
3091 | } | 3089 | } |
3092 | in6_ifa_put(ifa); | 3090 | in6_ifa_put(ifa); |
3093 | 3091 | ||
@@ -5054,22 +5052,6 @@ static struct pernet_operations addrconf_ops = { | |||
5054 | .exit = addrconf_exit_net, | 5052 | .exit = addrconf_exit_net, |
5055 | }; | 5053 | }; |
5056 | 5054 | ||
5057 | /* | ||
5058 | * Device notifier | ||
5059 | */ | ||
5060 | |||
5061 | int register_inet6addr_notifier(struct notifier_block *nb) | ||
5062 | { | ||
5063 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | ||
5064 | } | ||
5065 | EXPORT_SYMBOL(register_inet6addr_notifier); | ||
5066 | |||
5067 | int unregister_inet6addr_notifier(struct notifier_block *nb) | ||
5068 | { | ||
5069 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); | ||
5070 | } | ||
5071 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | ||
5072 | |||
5073 | static struct rtnl_af_ops inet6_ops = { | 5055 | static struct rtnl_af_ops inet6_ops = { |
5074 | .family = AF_INET6, | 5056 | .family = AF_INET6, |
5075 | .fill_link_af = inet6_fill_link_af, | 5057 | .fill_link_af = inet6_fill_link_af, |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index d051e5f4bf34..72104562c864 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
@@ -78,3 +78,22 @@ int __ipv6_addr_type(const struct in6_addr *addr) | |||
78 | } | 78 | } |
79 | EXPORT_SYMBOL(__ipv6_addr_type); | 79 | EXPORT_SYMBOL(__ipv6_addr_type); |
80 | 80 | ||
81 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | ||
82 | |||
83 | int register_inet6addr_notifier(struct notifier_block *nb) | ||
84 | { | ||
85 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | ||
86 | } | ||
87 | EXPORT_SYMBOL(register_inet6addr_notifier); | ||
88 | |||
89 | int unregister_inet6addr_notifier(struct notifier_block *nb) | ||
90 | { | ||
91 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); | ||
92 | } | ||
93 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | ||
94 | |||
95 | int inet6addr_notifier_call_chain(unsigned long val, void *v) | ||
96 | { | ||
97 | return atomic_notifier_call_chain(&inet6addr_chain, val, v); | ||
98 | } | ||
99 | EXPORT_SYMBOL(inet6addr_notifier_call_chain); | ||
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c index 5060d54199ab..e0983f3648a6 100644 --- a/net/ipv6/netfilter/ip6t_rpfilter.c +++ b/net/ipv6/netfilter/ip6t_rpfilter.c | |||
@@ -71,6 +71,12 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb, | |||
71 | return ret; | 71 | return ret; |
72 | } | 72 | } |
73 | 73 | ||
74 | static bool rpfilter_is_local(const struct sk_buff *skb) | ||
75 | { | ||
76 | const struct rt6_info *rt = (const void *) skb_dst(skb); | ||
77 | return rt && (rt->rt6i_flags & RTF_LOCAL); | ||
78 | } | ||
79 | |||
74 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | 80 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) |
75 | { | 81 | { |
76 | const struct xt_rpfilter_info *info = par->matchinfo; | 82 | const struct xt_rpfilter_info *info = par->matchinfo; |
@@ -78,7 +84,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
78 | struct ipv6hdr *iph; | 84 | struct ipv6hdr *iph; |
79 | bool invert = info->flags & XT_RPFILTER_INVERT; | 85 | bool invert = info->flags & XT_RPFILTER_INVERT; |
80 | 86 | ||
81 | if (par->in->flags & IFF_LOOPBACK) | 87 | if (rpfilter_is_local(skb)) |
82 | return true ^ invert; | 88 | return true ^ invert; |
83 | 89 | ||
84 | iph = ipv6_hdr(skb); | 90 | iph = ipv6_hdr(skb); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index e6e44cef8db2..790d9f4b8b0b 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -342,9 +342,17 @@ found: | |||
342 | } | 342 | } |
343 | 343 | ||
344 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 344 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
345 | fq->q.meat == fq->q.len) | 345 | fq->q.meat == fq->q.len) { |
346 | return ip6_frag_reasm(fq, prev, dev); | 346 | int res; |
347 | unsigned long orefdst = skb->_skb_refdst; | ||
348 | |||
349 | skb->_skb_refdst = 0UL; | ||
350 | res = ip6_frag_reasm(fq, prev, dev); | ||
351 | skb->_skb_refdst = orefdst; | ||
352 | return res; | ||
353 | } | ||
347 | 354 | ||
355 | skb_dst_drop(skb); | ||
348 | inet_frag_lru_move(&fq->q); | 356 | inet_frag_lru_move(&fq->q); |
349 | return -1; | 357 | return -1; |
350 | 358 | ||