Blame view

net/ipv6/ip6_icmp.c 1.93 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
5f5624cf1   Pravin B Shelar   ipv6: Kill ipv6 d...
2
3
4
5
6
7
8
9
10
  #include <linux/export.h>
  #include <linux/icmpv6.h>
  #include <linux/mutex.h>
  #include <linux/netdevice.h>
  #include <linux/spinlock.h>
  
  #include <net/ipv6.h>
  
  #if IS_ENABLED(CONFIG_IPV6)
cc7a21b6f   Eric Dumazet   ipv6: icmp6: avoi...
11
  #if !IS_BUILTIN(CONFIG_IPV6)
5f5624cf1   Pravin B Shelar   ipv6: Kill ipv6 d...
12
13
14
15
16
  static ip6_icmp_send_t __rcu *ip6_icmp_send;
  
  int inet6_register_icmp_sender(ip6_icmp_send_t *fn)
  {
  	return (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, NULL, fn) == NULL) ?
67ba4152e   Ian Morris   ipv6: White-space...
17
  		0 : -EBUSY;
5f5624cf1   Pravin B Shelar   ipv6: Kill ipv6 d...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  }
  EXPORT_SYMBOL(inet6_register_icmp_sender);
  
  int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn)
  {
  	int ret;
  
  	ret = (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn) ?
  	      0 : -EINVAL;
  
  	synchronize_net();
  
  	return ret;
  }
  EXPORT_SYMBOL(inet6_unregister_icmp_sender);
  
  void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
  {
  	ip6_icmp_send_t *send;
  
  	rcu_read_lock();
  	send = rcu_dereference(ip6_icmp_send);
cc7a21b6f   Eric Dumazet   ipv6: icmp6: avoi...
40
41
  	if (send)
  		send(skb, type, code, info, NULL);
5f5624cf1   Pravin B Shelar   ipv6: Kill ipv6 d...
42
43
44
  	rcu_read_unlock();
  }
  EXPORT_SYMBOL(icmpv6_send);
cc7a21b6f   Eric Dumazet   ipv6: icmp6: avoi...
45
  #endif
0b41713b6   Jason A. Donenfeld   icmp: introduce h...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  
  #if IS_ENABLED(CONFIG_NF_NAT)
  #include <net/netfilter/nf_conntrack.h>
  void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info)
  {
  	struct sk_buff *cloned_skb = NULL;
  	enum ip_conntrack_info ctinfo;
  	struct in6_addr orig_ip;
  	struct nf_conn *ct;
  
  	ct = nf_ct_get(skb_in, &ctinfo);
  	if (!ct || !(ct->status & IPS_SRC_NAT)) {
  		icmpv6_send(skb_in, type, code, info);
  		return;
  	}
  
  	if (skb_shared(skb_in))
  		skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC);
  
  	if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head ||
  	    (skb_network_header(skb_in) + sizeof(struct ipv6hdr)) >
  	    skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in,
  	    skb_network_offset(skb_in) + sizeof(struct ipv6hdr))))
  		goto out;
  
  	orig_ip = ipv6_hdr(skb_in)->saddr;
  	ipv6_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.in6;
  	icmpv6_send(skb_in, type, code, info);
  	ipv6_hdr(skb_in)->saddr = orig_ip;
  out:
  	consume_skb(cloned_skb);
  }
  EXPORT_SYMBOL(icmpv6_ndo_send);
  #endif
5f5624cf1   Pravin B Shelar   ipv6: Kill ipv6 d...
80
  #endif