Blame view
net/ipv6/icmp.c
21.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 |
/* * Internet Control Message Protocol (ICMPv6) * Linux INET6 implementation * * Authors: * Pedro Roque <roque@di.fc.ul.pt> * |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
* Based on net/ipv4/icmp.c * * RFC 1885 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ /* * Changes: * * Andi Kleen : exception handling * Andi Kleen add rate limits. never reply to a icmp. * add more length checks and other fixes. * yoshfuji : ensure to sent parameter problem for * fragments. * YOSHIFUJI Hideaki @USAGI: added sysctl for icmp rate limit. * Randy Dunlap and * YOSHIFUJI Hideaki @USAGI: Per-interface statistics support * Kazunori MIYAZAWA @USAGI: change output process to use ip6_append_data */ #include <linux/module.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 41 |
#include <linux/sockios.h> #include <linux/net.h> #include <linux/skbuff.h> #include <linux/init.h> |
763ecff18 [NETFILTER]: nf_c... |
42 |
#include <linux/netfilter.h> |
5a0e3ad6a include cleanup: ... |
43 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
#ifdef CONFIG_SYSCTL #include <linux/sysctl.h> #endif #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/icmpv6.h> #include <net/ip.h> #include <net/sock.h> #include <net/ipv6.h> #include <net/ip6_checksum.h> #include <net/protocol.h> #include <net/raw.h> #include <net/rawv6.h> #include <net/transp_v6.h> #include <net/ip6_route.h> #include <net/addrconf.h> #include <net/icmp.h> |
8b7817f3a [IPSEC]: Add ICMP... |
65 |
#include <net/xfrm.h> |
1ed8516f0 [IPV6]: Simplify ... |
66 |
#include <net/inet_common.h> |
1da177e4c Linux-2.6.12-rc2 |
67 68 69 |
#include <asm/uaccess.h> #include <asm/system.h> |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 74 75 76 |
/* * The ICMP socket(s). This is the most convenient way to flow control * our ICMP output as well as maintain a clean interface throughout * all layers. All Socketless IP sends will soon be gone. * * On SMP we have one ICMP socket per-cpu. */ |
98c6d1b26 [NETNS]: Make icm... |
77 78 79 80 |
static inline struct sock *icmpv6_sk(struct net *net) { return net->ipv6.icmp_sk[smp_processor_id()]; } |
1da177e4c Linux-2.6.12-rc2 |
81 |
|
e5bbef20e [IPV6]: Replace s... |
82 |
static int icmpv6_rcv(struct sk_buff *skb); |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
41135cc83 net: constify str... |
84 |
static const struct inet6_protocol icmpv6_protocol = { |
1da177e4c Linux-2.6.12-rc2 |
85 |
.handler = icmpv6_rcv, |
8b7817f3a [IPSEC]: Add ICMP... |
86 |
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
1da177e4c Linux-2.6.12-rc2 |
87 |
}; |
fdc0bde90 icmp: icmp_sk() s... |
88 |
static __inline__ struct sock *icmpv6_xmit_lock(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
89 |
{ |
fdc0bde90 icmp: icmp_sk() s... |
90 |
struct sock *sk; |
1da177e4c Linux-2.6.12-rc2 |
91 |
local_bh_disable(); |
fdc0bde90 icmp: icmp_sk() s... |
92 |
sk = icmpv6_sk(net); |
405666db8 [ICMP]: Pass prop... |
93 |
if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
1da177e4c Linux-2.6.12-rc2 |
94 95 96 97 98 |
/* This can happen if the output path (f.e. SIT or * ip6ip6 tunnel) signals dst_link_failure() for an * outgoing ICMP6 packet. */ local_bh_enable(); |
fdc0bde90 icmp: icmp_sk() s... |
99 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
100 |
} |
fdc0bde90 icmp: icmp_sk() s... |
101 |
return sk; |
1da177e4c Linux-2.6.12-rc2 |
102 |
} |
405666db8 [ICMP]: Pass prop... |
103 |
static __inline__ void icmpv6_xmit_unlock(struct sock *sk) |
1da177e4c Linux-2.6.12-rc2 |
104 |
{ |
405666db8 [ICMP]: Pass prop... |
105 |
spin_unlock_bh(&sk->sk_lock.slock); |
1da177e4c Linux-2.6.12-rc2 |
106 |
} |
1ab1457c4 [NET] IPV6: Fix w... |
107 |
/* |
1da177e4c Linux-2.6.12-rc2 |
108 109 |
* Slightly more convenient version of icmpv6_send. */ |
d5fdd6bab ipv6: Use correct... |
110 |
void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) |
1da177e4c Linux-2.6.12-rc2 |
111 |
{ |
3ffe533c8 ipv6: drop unused... |
112 |
icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos); |
1da177e4c Linux-2.6.12-rc2 |
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
kfree_skb(skb); } /* * Figure out, may we reply to this packet with icmp error. * * We do not reply, if: * - it was icmp error message. * - it is truncated, so that it is known, that protocol is ICMPV6 * (i.e. in the middle of some exthdr) * * --ANK (980726) */ static int is_ineligible(struct sk_buff *skb) { |
0660e03f6 [SK_BUFF]: Introd... |
129 |
int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
1da177e4c Linux-2.6.12-rc2 |
130 |
int len = skb->len - ptr; |
0660e03f6 [SK_BUFF]: Introd... |
131 |
__u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
75f2811c6 ipv6: Add fragmen... |
132 |
__be16 frag_off; |
1da177e4c Linux-2.6.12-rc2 |
133 134 135 |
if (len < 0) return 1; |
75f2811c6 ipv6: Add fragmen... |
136 |
ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off); |
1da177e4c Linux-2.6.12-rc2 |
137 138 139 140 141 142 143 144 145 146 147 148 149 |
if (ptr < 0) return 0; if (nexthdr == IPPROTO_ICMPV6) { u8 _type, *tp; tp = skb_header_pointer(skb, ptr+offsetof(struct icmp6hdr, icmp6_type), sizeof(_type), &_type); if (tp == NULL || !(*tp & ICMPV6_INFOMSG_MASK)) return 1; } return 0; } |
1ab1457c4 [NET] IPV6: Fix w... |
150 151 |
/* * Check the ICMP output rate limit |
1da177e4c Linux-2.6.12-rc2 |
152 |
*/ |
92d868292 inetpeer: Move IC... |
153 |
static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type, |
4c9483b2f ipv6: Convert to ... |
154 |
struct flowi6 *fl6) |
1da177e4c Linux-2.6.12-rc2 |
155 156 |
{ struct dst_entry *dst; |
3b1e0a655 [NET] NETNS: Omit... |
157 |
struct net *net = sock_net(sk); |
92d868292 inetpeer: Move IC... |
158 |
bool res = false; |
1da177e4c Linux-2.6.12-rc2 |
159 160 161 |
/* Informational messages are not limited. */ if (type & ICMPV6_INFOMSG_MASK) |
92d868292 inetpeer: Move IC... |
162 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
163 164 165 |
/* Do not limit pmtu discovery, it would break it. */ if (type == ICMPV6_PKT_TOOBIG) |
92d868292 inetpeer: Move IC... |
166 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
167 |
|
1ab1457c4 [NET] IPV6: Fix w... |
168 |
/* |
1da177e4c Linux-2.6.12-rc2 |
169 170 171 172 |
* Look up the output route. * XXX: perhaps the expire for routing entries cloned by * this lookup should be more aggressive (not longer than timeout). */ |
4c9483b2f ipv6: Convert to ... |
173 |
dst = ip6_route_output(net, sk, fl6); |
1da177e4c Linux-2.6.12-rc2 |
174 |
if (dst->error) { |
3bd653c84 netns: add net pa... |
175 |
IP6_INC_STATS(net, ip6_dst_idev(dst), |
a11d206d0 [IPV6]: Per-inter... |
176 |
IPSTATS_MIB_OUTNOROUTES); |
1da177e4c Linux-2.6.12-rc2 |
177 |
} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { |
92d868292 inetpeer: Move IC... |
178 |
res = true; |
1da177e4c Linux-2.6.12-rc2 |
179 180 |
} else { struct rt6_info *rt = (struct rt6_info *)dst; |
9a43b709a [NETNS][IPV6] icm... |
181 |
int tmo = net->ipv6.sysctl.icmpv6_time; |
1da177e4c Linux-2.6.12-rc2 |
182 183 184 185 |
/* Give more bandwidth to wider prefixes. */ if (rt->rt6i_dst.plen < 128) tmo >>= ((128 - rt->rt6i_dst.plen)>>5); |
92d868292 inetpeer: Move IC... |
186 187 188 |
if (!rt->rt6i_peer) rt6_bind_peer(rt, 1); res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo); |
1da177e4c Linux-2.6.12-rc2 |
189 190 191 192 193 194 195 196 |
} dst_release(dst); return res; } /* * an inline helper for the "simple" if statement below * checks if parameter problem report is caused by an |
1ab1457c4 [NET] IPV6: Fix w... |
197 |
* unrecognized IPv6 option that has the Option Type |
1da177e4c Linux-2.6.12-rc2 |
198 199 200 201 202 203 |
* highest-order two bits set to 10 */ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset) { u8 _optval, *op; |
bbe735e42 [SK_BUFF]: Introd... |
204 |
offset += skb_network_offset(skb); |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 208 209 |
op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval); if (op == NULL) return 1; return (*op & 0xC0) == 0x80; } |
4c9483b2f ipv6: Convert to ... |
210 |
static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) |
1da177e4c Linux-2.6.12-rc2 |
211 212 213 214 215 216 217 |
{ struct sk_buff *skb; struct icmp6hdr *icmp6h; int err = 0; if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) goto out; |
cc70ab261 [ICMP6]: Introduc... |
218 |
icmp6h = icmp6_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
219 220 221 222 |
memcpy(icmp6h, thdr, sizeof(struct icmp6hdr)); icmp6h->icmp6_cksum = 0; if (skb_queue_len(&sk->sk_write_queue) == 1) { |
07f0757a6 include/net net/ ... |
223 |
skb->csum = csum_partial(icmp6h, |
1da177e4c Linux-2.6.12-rc2 |
224 |
sizeof(struct icmp6hdr), skb->csum); |
4c9483b2f ipv6: Convert to ... |
225 226 227 |
icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, len, fl6->flowi6_proto, |
1da177e4c Linux-2.6.12-rc2 |
228 229 |
skb->csum); } else { |
868c86bcb [NET]: annotate c... |
230 |
__wsum tmp_csum = 0; |
1da177e4c Linux-2.6.12-rc2 |
231 232 233 234 |
skb_queue_walk(&sk->sk_write_queue, skb) { tmp_csum = csum_add(tmp_csum, skb->csum); } |
07f0757a6 include/net net/ ... |
235 |
tmp_csum = csum_partial(icmp6h, |
1da177e4c Linux-2.6.12-rc2 |
236 |
sizeof(struct icmp6hdr), tmp_csum); |
4c9483b2f ipv6: Convert to ... |
237 238 239 |
icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, len, fl6->flowi6_proto, |
868c86bcb [NET]: annotate c... |
240 |
tmp_csum); |
1da177e4c Linux-2.6.12-rc2 |
241 |
} |
1da177e4c Linux-2.6.12-rc2 |
242 243 244 245 246 247 248 249 |
ip6_push_pending_frames(sk); out: return err; } struct icmpv6_msg { struct sk_buff *skb; int offset; |
763ecff18 [NETFILTER]: nf_c... |
250 |
uint8_t type; |
1da177e4c Linux-2.6.12-rc2 |
251 252 253 254 255 256 |
}; static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) { struct icmpv6_msg *msg = (struct icmpv6_msg *) from; struct sk_buff *org_skb = msg->skb; |
5f92a7388 [NET]: Annotate c... |
257 |
__wsum csum = 0; |
1da177e4c Linux-2.6.12-rc2 |
258 259 260 261 |
csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset, to, len, csum); skb->csum = csum_block_add(skb->csum, csum, odd); |
763ecff18 [NETFILTER]: nf_c... |
262 263 |
if (!(msg->type & ICMPV6_INFOMSG_MASK)) nf_ct_attach(skb, org_skb); |
1da177e4c Linux-2.6.12-rc2 |
264 265 |
return 0; } |
59fbb3a61 [IPV6] MIP6: Load... |
266 |
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
793832361 [IPV6] MIP6: Reve... |
267 268 |
static void mip6_addr_swap(struct sk_buff *skb) { |
0660e03f6 [SK_BUFF]: Introd... |
269 |
struct ipv6hdr *iph = ipv6_hdr(skb); |
793832361 [IPV6] MIP6: Reve... |
270 271 272 273 274 275 276 277 |
struct inet6_skb_parm *opt = IP6CB(skb); struct ipv6_destopt_hao *hao; struct in6_addr tmp; int off; if (opt->dsthao) { off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); if (likely(off >= 0)) { |
d56f90a7c [SK_BUFF]: Introd... |
278 279 |
hao = (struct ipv6_destopt_hao *) (skb_network_header(skb) + off); |
4e3fd7a06 net: remove ipv6_... |
280 281 282 |
tmp = iph->saddr; iph->saddr = hao->addr; hao->addr = tmp; |
793832361 [IPV6] MIP6: Reve... |
283 284 285 286 287 288 |
} } } #else static inline void mip6_addr_swap(struct sk_buff *skb) {} #endif |
b42835dbe ipv6: Make icmp r... |
289 |
static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, |
4c9483b2f ipv6: Convert to ... |
290 |
struct sock *sk, struct flowi6 *fl6) |
b42835dbe ipv6: Make icmp r... |
291 292 |
{ struct dst_entry *dst, *dst2; |
4c9483b2f ipv6: Convert to ... |
293 |
struct flowi6 fl2; |
b42835dbe ipv6: Make icmp r... |
294 |
int err; |
4c9483b2f ipv6: Convert to ... |
295 |
err = ip6_dst_lookup(sk, &dst, fl6); |
b42835dbe ipv6: Make icmp r... |
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
if (err) return ERR_PTR(err); /* * We won't send icmp if the destination is known * anycast. */ if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source "); dst_release(dst); return ERR_PTR(-EINVAL); } /* No need to clone since we're just using its address. */ dst2 = dst; |
4c9483b2f ipv6: Convert to ... |
312 |
dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), sk, 0); |
452edd598 xfrm: Return dst ... |
313 |
if (!IS_ERR(dst)) { |
b42835dbe ipv6: Make icmp r... |
314 315 |
if (dst != dst2) return dst; |
452edd598 xfrm: Return dst ... |
316 317 318 319 320 |
} else { if (PTR_ERR(dst) == -EPERM) dst = NULL; else return dst; |
b42835dbe ipv6: Make icmp r... |
321 |
} |
4c9483b2f ipv6: Convert to ... |
322 |
err = xfrm_decode_session_reverse(skb, flowi6_to_flowi(&fl2), AF_INET6); |
b42835dbe ipv6: Make icmp r... |
323 324 325 326 327 328 |
if (err) goto relookup_failed; err = ip6_dst_lookup(sk, &dst2, &fl2); if (err) goto relookup_failed; |
4c9483b2f ipv6: Convert to ... |
329 |
dst2 = xfrm_lookup(net, dst2, flowi6_to_flowi(&fl2), sk, XFRM_LOOKUP_ICMP); |
452edd598 xfrm: Return dst ... |
330 |
if (!IS_ERR(dst2)) { |
b42835dbe ipv6: Make icmp r... |
331 332 |
dst_release(dst); dst = dst2; |
452edd598 xfrm: Return dst ... |
333 334 335 336 337 338 339 |
} else { err = PTR_ERR(dst2); if (err == -EPERM) { dst_release(dst); return dst2; } else goto relookup_failed; |
b42835dbe ipv6: Make icmp r... |
340 341 342 343 344 345 346 |
} relookup_failed: if (dst) return dst; return ERR_PTR(err); } |
1da177e4c Linux-2.6.12-rc2 |
347 348 349 |
/* * Send an ICMP message in response to a packet in error */ |
3ffe533c8 ipv6: drop unused... |
350 |
void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) |
1da177e4c Linux-2.6.12-rc2 |
351 |
{ |
c346dca10 [NET] NETNS: Omit... |
352 |
struct net *net = dev_net(skb->dev); |
1da177e4c Linux-2.6.12-rc2 |
353 |
struct inet6_dev *idev = NULL; |
0660e03f6 [SK_BUFF]: Introd... |
354 |
struct ipv6hdr *hdr = ipv6_hdr(skb); |
84427d533 [IPV6]: Ensure to... |
355 356 |
struct sock *sk; struct ipv6_pinfo *np; |
b71d1d426 inet: constify ip... |
357 |
const struct in6_addr *saddr = NULL; |
1da177e4c Linux-2.6.12-rc2 |
358 359 |
struct dst_entry *dst; struct icmp6hdr tmp_hdr; |
4c9483b2f ipv6: Convert to ... |
360 |
struct flowi6 fl6; |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 364 |
struct icmpv6_msg msg; int iif = 0; int addr_type = 0; int len; |
e651f03af inet6: Conversion... |
365 |
int hlimit; |
1da177e4c Linux-2.6.12-rc2 |
366 |
int err = 0; |
27a884dc3 [SK_BUFF]: Conver... |
367 368 |
if ((u8 *)hdr < skb->head || (skb->network_header + sizeof(*hdr)) > skb->tail) |
1da177e4c Linux-2.6.12-rc2 |
369 370 371 |
return; /* |
1ab1457c4 [NET] IPV6: Fix w... |
372 |
* Make sure we respect the rules |
1da177e4c Linux-2.6.12-rc2 |
373 374 375 376 377 |
* i.e. RFC 1885 2.4(e) * Rule (e.1) is enforced by not using icmpv6_send * in any code that processes icmp errors. */ addr_type = ipv6_addr_type(&hdr->daddr); |
9a43b709a [NETNS][IPV6] icm... |
378 |
if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0)) |
1da177e4c Linux-2.6.12-rc2 |
379 380 381 382 383 384 385 386 |
saddr = &hdr->daddr; /* * Dest addr check */ if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) { if (type != ICMPV6_PKT_TOOBIG && |
1ab1457c4 [NET] IPV6: Fix w... |
387 388 |
!(type == ICMPV6_PARAMPROB && code == ICMPV6_UNK_OPTION && |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
(opt_unrec(skb, info)))) return; saddr = NULL; } addr_type = ipv6_addr_type(&hdr->saddr); /* * Source addr check */ if (addr_type & IPV6_ADDR_LINKLOCAL) iif = skb->dev->ifindex; /* |
8de3351e6 [IPV6]: Try not t... |
405 406 407 408 |
* Must not send error if the source does not uniquely * identify a single node (RFC2463 Section 2.4). * We check unspecified / multicast addresses here, * and anycast addresses will be checked later. |
1da177e4c Linux-2.6.12-rc2 |
409 410 |
*/ if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { |
64ce20730 [NET]: Make NETDE... |
411 412 |
LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source "); |
1da177e4c Linux-2.6.12-rc2 |
413 414 |
return; } |
1ab1457c4 [NET] IPV6: Fix w... |
415 |
/* |
1da177e4c Linux-2.6.12-rc2 |
416 417 418 |
* Never answer to a ICMP packet. */ if (is_ineligible(skb)) { |
64ce20730 [NET]: Make NETDE... |
419 420 |
LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error "); |
1da177e4c Linux-2.6.12-rc2 |
421 422 |
return; } |
793832361 [IPV6] MIP6: Reve... |
423 |
mip6_addr_swap(skb); |
4c9483b2f ipv6: Convert to ... |
424 425 |
memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_proto = IPPROTO_ICMPV6; |
4e3fd7a06 net: remove ipv6_... |
426 |
fl6.daddr = hdr->saddr; |
1da177e4c Linux-2.6.12-rc2 |
427 |
if (saddr) |
4e3fd7a06 net: remove ipv6_... |
428 |
fl6.saddr = *saddr; |
4c9483b2f ipv6: Convert to ... |
429 |
fl6.flowi6_oif = iif; |
1958b856c net: Put fl6_* ma... |
430 431 |
fl6.fl6_icmp_type = type; fl6.fl6_icmp_code = code; |
4c9483b2f ipv6: Convert to ... |
432 |
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
1da177e4c Linux-2.6.12-rc2 |
433 |
|
fdc0bde90 icmp: icmp_sk() s... |
434 435 |
sk = icmpv6_xmit_lock(net); if (sk == NULL) |
405666db8 [ICMP]: Pass prop... |
436 |
return; |
fdc0bde90 icmp: icmp_sk() s... |
437 |
np = inet6_sk(sk); |
405666db8 [ICMP]: Pass prop... |
438 |
|
4c9483b2f ipv6: Convert to ... |
439 |
if (!icmpv6_xrlim_allow(sk, type, &fl6)) |
1da177e4c Linux-2.6.12-rc2 |
440 441 442 443 444 445 |
goto out; tmp_hdr.icmp6_type = type; tmp_hdr.icmp6_code = code; tmp_hdr.icmp6_cksum = 0; tmp_hdr.icmp6_pointer = htonl(info); |
4c9483b2f ipv6: Convert to ... |
446 447 |
if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) fl6.flowi6_oif = np->mcast_oif; |
1da177e4c Linux-2.6.12-rc2 |
448 |
|
4c9483b2f ipv6: Convert to ... |
449 |
dst = icmpv6_route_lookup(net, skb, sk, &fl6); |
b42835dbe ipv6: Make icmp r... |
450 |
if (IS_ERR(dst)) |
1da177e4c Linux-2.6.12-rc2 |
451 |
goto out; |
8de3351e6 [IPV6]: Try not t... |
452 |
|
4c9483b2f ipv6: Convert to ... |
453 |
if (ipv6_addr_is_multicast(&fl6.daddr)) |
1da177e4c Linux-2.6.12-rc2 |
454 455 456 457 |
hlimit = np->mcast_hops; else hlimit = np->hop_limit; if (hlimit < 0) |
6b75d0908 [IPV6]: Optimize ... |
458 |
hlimit = ip6_dst_hoplimit(dst); |
1da177e4c Linux-2.6.12-rc2 |
459 460 |
msg.skb = skb; |
bbe735e42 [SK_BUFF]: Introd... |
461 |
msg.offset = skb_network_offset(skb); |
763ecff18 [NETFILTER]: nf_c... |
462 |
msg.type = type; |
1da177e4c Linux-2.6.12-rc2 |
463 464 465 466 |
len = skb->len - msg.offset; len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr)); if (len < 0) { |
64ce20730 [NET]: Make NETDE... |
467 468 |
LIMIT_NETDEBUG(KERN_DEBUG "icmp: len problem "); |
1da177e4c Linux-2.6.12-rc2 |
469 470 |
goto out_dst_release; } |
cfdf76474 ipv6: some RCU co... |
471 472 |
rcu_read_lock(); idev = __in6_dev_get(skb->dev); |
1da177e4c Linux-2.6.12-rc2 |
473 474 475 |
err = ip6_append_data(sk, icmpv6_getfrag, &msg, len + sizeof(struct icmp6hdr), |
e651f03af inet6: Conversion... |
476 |
sizeof(struct icmp6hdr), hlimit, |
4c9483b2f ipv6: Convert to ... |
477 |
np->tclass, NULL, &fl6, (struct rt6_info*)dst, |
13b52cd44 IPv6: Add dontfra... |
478 |
MSG_DONTWAIT, np->dontfrag); |
1da177e4c Linux-2.6.12-rc2 |
479 |
if (err) { |
00d9d6a18 ipv6: fix ICMP6_M... |
480 |
ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
1da177e4c Linux-2.6.12-rc2 |
481 |
ip6_flush_pending_frames(sk); |
cfdf76474 ipv6: some RCU co... |
482 483 484 |
} else { err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr)); |
1da177e4c Linux-2.6.12-rc2 |
485 |
} |
cfdf76474 ipv6: some RCU co... |
486 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
487 488 489 |
out_dst_release: dst_release(dst); out: |
405666db8 [ICMP]: Pass prop... |
490 |
icmpv6_xmit_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
491 |
} |
7159039a1 [IPV6]: Decentral... |
492 |
EXPORT_SYMBOL(icmpv6_send); |
1da177e4c Linux-2.6.12-rc2 |
493 494 |
static void icmpv6_echo_reply(struct sk_buff *skb) { |
c346dca10 [NET] NETNS: Omit... |
495 |
struct net *net = dev_net(skb->dev); |
84427d533 [IPV6]: Ensure to... |
496 |
struct sock *sk; |
1da177e4c Linux-2.6.12-rc2 |
497 |
struct inet6_dev *idev; |
84427d533 [IPV6]: Ensure to... |
498 |
struct ipv6_pinfo *np; |
b71d1d426 inet: constify ip... |
499 |
const struct in6_addr *saddr = NULL; |
cc70ab261 [ICMP6]: Introduc... |
500 |
struct icmp6hdr *icmph = icmp6_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
501 |
struct icmp6hdr tmp_hdr; |
4c9483b2f ipv6: Convert to ... |
502 |
struct flowi6 fl6; |
1da177e4c Linux-2.6.12-rc2 |
503 504 505 506 |
struct icmpv6_msg msg; struct dst_entry *dst; int err = 0; int hlimit; |
0660e03f6 [SK_BUFF]: Introd... |
507 |
saddr = &ipv6_hdr(skb)->daddr; |
1da177e4c Linux-2.6.12-rc2 |
508 509 510 511 512 513 |
if (!ipv6_unicast_destination(skb)) saddr = NULL; memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; |
4c9483b2f ipv6: Convert to ... |
514 515 |
memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_proto = IPPROTO_ICMPV6; |
4e3fd7a06 net: remove ipv6_... |
516 |
fl6.daddr = ipv6_hdr(skb)->saddr; |
1da177e4c Linux-2.6.12-rc2 |
517 |
if (saddr) |
4e3fd7a06 net: remove ipv6_... |
518 |
fl6.saddr = *saddr; |
4c9483b2f ipv6: Convert to ... |
519 |
fl6.flowi6_oif = skb->dev->ifindex; |
1958b856c net: Put fl6_* ma... |
520 |
fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; |
4c9483b2f ipv6: Convert to ... |
521 |
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
1da177e4c Linux-2.6.12-rc2 |
522 |
|
fdc0bde90 icmp: icmp_sk() s... |
523 524 |
sk = icmpv6_xmit_lock(net); if (sk == NULL) |
405666db8 [ICMP]: Pass prop... |
525 |
return; |
fdc0bde90 icmp: icmp_sk() s... |
526 |
np = inet6_sk(sk); |
405666db8 [ICMP]: Pass prop... |
527 |
|
4c9483b2f ipv6: Convert to ... |
528 529 |
if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) fl6.flowi6_oif = np->mcast_oif; |
1da177e4c Linux-2.6.12-rc2 |
530 |
|
4c9483b2f ipv6: Convert to ... |
531 |
err = ip6_dst_lookup(sk, &dst, &fl6); |
1da177e4c Linux-2.6.12-rc2 |
532 533 |
if (err) goto out; |
4c9483b2f ipv6: Convert to ... |
534 |
dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0); |
452edd598 xfrm: Return dst ... |
535 |
if (IS_ERR(dst)) |
e104411b8 [XFRM]: Always re... |
536 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
537 |
|
4c9483b2f ipv6: Convert to ... |
538 |
if (ipv6_addr_is_multicast(&fl6.daddr)) |
1da177e4c Linux-2.6.12-rc2 |
539 540 541 542 |
hlimit = np->mcast_hops; else hlimit = np->hop_limit; if (hlimit < 0) |
6b75d0908 [IPV6]: Optimize ... |
543 |
hlimit = ip6_dst_hoplimit(dst); |
1da177e4c Linux-2.6.12-rc2 |
544 |
|
cfdf76474 ipv6: some RCU co... |
545 |
idev = __in6_dev_get(skb->dev); |
1da177e4c Linux-2.6.12-rc2 |
546 547 548 |
msg.skb = skb; msg.offset = 0; |
763ecff18 [NETFILTER]: nf_c... |
549 |
msg.type = ICMPV6_ECHO_REPLY; |
1da177e4c Linux-2.6.12-rc2 |
550 551 |
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
4c9483b2f ipv6: Convert to ... |
552 |
sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl6, |
13b52cd44 IPv6: Add dontfra... |
553 554 |
(struct rt6_info*)dst, MSG_DONTWAIT, np->dontfrag); |
1da177e4c Linux-2.6.12-rc2 |
555 556 |
if (err) { |
00d9d6a18 ipv6: fix ICMP6_M... |
557 |
ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
1da177e4c Linux-2.6.12-rc2 |
558 |
ip6_flush_pending_frames(sk); |
cfdf76474 ipv6: some RCU co... |
559 560 561 |
} else { err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); |
1da177e4c Linux-2.6.12-rc2 |
562 |
} |
1da177e4c Linux-2.6.12-rc2 |
563 |
dst_release(dst); |
1ab1457c4 [NET] IPV6: Fix w... |
564 |
out: |
405666db8 [ICMP]: Pass prop... |
565 |
icmpv6_xmit_unlock(sk); |
1da177e4c Linux-2.6.12-rc2 |
566 |
} |
d5fdd6bab ipv6: Use correct... |
567 |
static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) |
1da177e4c Linux-2.6.12-rc2 |
568 |
{ |
41135cc83 net: constify str... |
569 |
const struct inet6_protocol *ipprot; |
1da177e4c Linux-2.6.12-rc2 |
570 571 572 |
int inner_offset; int hash; u8 nexthdr; |
75f2811c6 ipv6: Add fragmen... |
573 |
__be16 frag_off; |
1da177e4c Linux-2.6.12-rc2 |
574 575 576 577 578 579 580 |
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) return; nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; if (ipv6_ext_hdr(nexthdr)) { /* now skip over extension headers */ |
75f2811c6 ipv6: Add fragmen... |
581 582 |
inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, &frag_off); |
1da177e4c Linux-2.6.12-rc2 |
583 584 585 586 587 588 589 590 591 |
if (inner_offset<0) return; } else { inner_offset = sizeof(struct ipv6hdr); } /* Checkin header including 8 bytes of inner protocol header. */ if (!pskb_may_pull(skb, inner_offset+8)) return; |
1da177e4c Linux-2.6.12-rc2 |
592 593 594 595 596 597 598 599 600 601 602 603 604 605 |
/* BUGGG_FUTURE: we should try to parse exthdrs in this packet. Without this we will not able f.e. to make source routed pmtu discovery. Corresponding argument (opt) to notifiers is already added. --ANK (980726) */ hash = nexthdr & (MAX_INET_PROTOS - 1); rcu_read_lock(); ipprot = rcu_dereference(inet6_protos[hash]); if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, NULL, type, code, inner_offset, info); rcu_read_unlock(); |
69d6da0b0 [IPv6] RAW: Compa... |
606 |
raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); |
1da177e4c Linux-2.6.12-rc2 |
607 |
} |
1ab1457c4 [NET] IPV6: Fix w... |
608 |
|
1da177e4c Linux-2.6.12-rc2 |
609 610 611 |
/* * Handle icmp messages */ |
e5bbef20e [IPV6]: Replace s... |
612 |
static int icmpv6_rcv(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
613 |
{ |
1da177e4c Linux-2.6.12-rc2 |
614 615 |
struct net_device *dev = skb->dev; struct inet6_dev *idev = __in6_dev_get(dev); |
b71d1d426 inet: constify ip... |
616 617 |
const struct in6_addr *saddr, *daddr; const struct ipv6hdr *orig_hdr; |
1da177e4c Linux-2.6.12-rc2 |
618 |
struct icmp6hdr *hdr; |
d5fdd6bab ipv6: Use correct... |
619 |
u8 type; |
1da177e4c Linux-2.6.12-rc2 |
620 |
|
aebcf82c1 [IPSEC]: Do not l... |
621 |
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
def8b4faf net: reduce struc... |
622 |
struct sec_path *sp = skb_sec_path(skb); |
8b7817f3a [IPSEC]: Add ICMP... |
623 |
int nh; |
def8b4faf net: reduce struc... |
624 |
if (!(sp && sp->xvec[sp->len - 1]->props.flags & |
aebcf82c1 [IPSEC]: Do not l... |
625 626 |
XFRM_STATE_ICMP)) goto drop_no_count; |
8b7817f3a [IPSEC]: Add ICMP... |
627 628 629 630 631 632 633 634 635 636 637 |
if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(*orig_hdr))) goto drop_no_count; nh = skb_network_offset(skb); skb_set_network_header(skb, sizeof(*hdr)); if (!xfrm6_policy_check_reverse(NULL, XFRM_POLICY_IN, skb)) goto drop_no_count; skb_set_network_header(skb, nh); } |
e41b5368e ipv6: added net a... |
638 |
ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INMSGS); |
1da177e4c Linux-2.6.12-rc2 |
639 |
|
0660e03f6 [SK_BUFF]: Introd... |
640 641 |
saddr = &ipv6_hdr(skb)->saddr; daddr = &ipv6_hdr(skb)->daddr; |
1da177e4c Linux-2.6.12-rc2 |
642 643 |
/* Perform checksum. */ |
fb286bb29 [NET]: Detect har... |
644 |
switch (skb->ip_summed) { |
84fa7933a [NET]: Replace CH... |
645 |
case CHECKSUM_COMPLETE: |
fb286bb29 [NET]: Detect har... |
646 647 648 649 650 |
if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, skb->csum)) break; /* fall through */ case CHECKSUM_NONE: |
868c86bcb [NET]: annotate c... |
651 652 |
skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 0)); |
fb286bb29 [NET]: Detect har... |
653 |
if (__skb_checksum_complete(skb)) { |
5b095d989 net: replace %p6 ... |
654 655 |
LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6] ", |
0c6ce78ab net: replace uses... |
656 |
saddr, daddr); |
1da177e4c Linux-2.6.12-rc2 |
657 658 659 |
goto discard_it; } } |
8cf229437 [ICMP]: Restore p... |
660 661 |
if (!pskb_pull(skb, sizeof(*hdr))) goto discard_it; |
1da177e4c Linux-2.6.12-rc2 |
662 |
|
cc70ab261 [ICMP6]: Introduc... |
663 |
hdr = icmp6_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
664 665 |
type = hdr->icmp6_type; |
55d43808e ipv6: added net a... |
666 |
ICMP6MSGIN_INC_STATS_BH(dev_net(dev), idev, type); |
1da177e4c Linux-2.6.12-rc2 |
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 |
switch (type) { case ICMPV6_ECHO_REQUEST: icmpv6_echo_reply(skb); break; case ICMPV6_ECHO_REPLY: /* we couldn't care less */ break; case ICMPV6_PKT_TOOBIG: /* BUGGG_FUTURE: if packet contains rthdr, we cannot update standard destination cache. Seems, only "advanced" destination cache will allow to solve this problem --ANK (980726) */ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto discard_it; |
cc70ab261 [ICMP6]: Introduc... |
685 |
hdr = icmp6_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
orig_hdr = (struct ipv6hdr *) (hdr + 1); rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, ntohl(hdr->icmp6_mtu)); /* * Drop through to notify */ case ICMPV6_DEST_UNREACH: case ICMPV6_TIME_EXCEED: case ICMPV6_PARAMPROB: icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); break; case NDISC_ROUTER_SOLICITATION: case NDISC_ROUTER_ADVERTISEMENT: case NDISC_NEIGHBOUR_SOLICITATION: case NDISC_NEIGHBOUR_ADVERTISEMENT: case NDISC_REDIRECT: ndisc_rcv(skb); break; case ICMPV6_MGM_QUERY: igmp6_event_query(skb); break; case ICMPV6_MGM_REPORT: igmp6_event_report(skb); break; case ICMPV6_MGM_REDUCTION: case ICMPV6_NI_QUERY: case ICMPV6_NI_REPLY: case ICMPV6_MLD2_REPORT: case ICMPV6_DHAAD_REQUEST: case ICMPV6_DHAAD_REPLY: case ICMPV6_MOBILE_PREFIX_SOL: case ICMPV6_MOBILE_PREFIX_ADV: break; default: |
64ce20730 [NET]: Make NETDE... |
727 728 |
LIMIT_NETDEBUG(KERN_DEBUG "icmpv6: msg of unknown type "); |
1da177e4c Linux-2.6.12-rc2 |
729 730 731 732 |
/* informational */ if (type & ICMPV6_INFOMSG_MASK) break; |
1ab1457c4 [NET] IPV6: Fix w... |
733 734 735 |
/* * error of unknown type. * must pass to upper level |
1da177e4c Linux-2.6.12-rc2 |
736 737 738 |
*/ icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); |
3ff50b799 [NET]: cleanup ex... |
739 |
} |
1da177e4c Linux-2.6.12-rc2 |
740 741 742 743 |
kfree_skb(skb); return 0; discard_it: |
e41b5368e ipv6: added net a... |
744 |
ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INERRORS); |
8b7817f3a [IPSEC]: Add ICMP... |
745 |
drop_no_count: |
1da177e4c Linux-2.6.12-rc2 |
746 747 748 |
kfree_skb(skb); return 0; } |
4c9483b2f ipv6: Convert to ... |
749 |
void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6, |
95e41e93e [IPV6]: Make ndis... |
750 751 752 753 754 |
u8 type, const struct in6_addr *saddr, const struct in6_addr *daddr, int oif) { |
4c9483b2f ipv6: Convert to ... |
755 |
memset(fl6, 0, sizeof(*fl6)); |
4e3fd7a06 net: remove ipv6_... |
756 757 |
fl6->saddr = *saddr; fl6->daddr = *daddr; |
4c9483b2f ipv6: Convert to ... |
758 |
fl6->flowi6_proto = IPPROTO_ICMPV6; |
1958b856c net: Put fl6_* ma... |
759 760 |
fl6->fl6_icmp_type = type; fl6->fl6_icmp_code = 0; |
4c9483b2f ipv6: Convert to ... |
761 762 |
fl6->flowi6_oif = oif; security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); |
95e41e93e [IPV6]: Make ndis... |
763 |
} |
640c41c77 [IPV6] lockdep: a... |
764 |
/* |
b7e729c4b [ICMP]: Store soc... |
765 |
* Special lock-class for __icmpv6_sk: |
640c41c77 [IPV6] lockdep: a... |
766 767 |
*/ static struct lock_class_key icmpv6_socket_sk_dst_lock_key; |
98c6d1b26 [NETNS]: Make icm... |
768 |
static int __net_init icmpv6_sk_init(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
769 770 771 |
{ struct sock *sk; int err, i, j; |
98c6d1b26 [NETNS]: Make icm... |
772 773 774 |
net->ipv6.icmp_sk = kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); if (net->ipv6.icmp_sk == NULL) |
79c911595 [ICMP]: Allocate ... |
775 |
return -ENOMEM; |
6f9120422 [PATCH] for_each_... |
776 |
for_each_possible_cpu(i) { |
1ed8516f0 [IPV6]: Simplify ... |
777 778 |
err = inet_ctl_sock_create(&sk, PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, net); |
1da177e4c Linux-2.6.12-rc2 |
779 780 781 782 783 784 785 786 |
if (err < 0) { printk(KERN_ERR "Failed to initialize the ICMP6 control socket " "(err %d). ", err); goto fail; } |
1ed8516f0 [IPV6]: Simplify ... |
787 |
net->ipv6.icmp_sk[i] = sk; |
5c8cafd65 [NETNS]: icmp(v6)... |
788 |
|
640c41c77 [IPV6] lockdep: a... |
789 790 791 |
/* * Split off their lock-class, because sk->sk_dst_lock * gets used from softirqs, which is safe for |
b7e729c4b [ICMP]: Store soc... |
792 |
* __icmpv6_sk (because those never get directly used |
640c41c77 [IPV6] lockdep: a... |
793 794 795 796 |
* via userspace syscalls), but unsafe for normal sockets. */ lockdep_set_class(&sk->sk_dst_lock, &icmpv6_socket_sk_dst_lock_key); |
1da177e4c Linux-2.6.12-rc2 |
797 798 799 800 |
/* Enough space for 2 64K ICMP packets, including * sk_buff struct overhead. */ |
87fb4b7b5 net: more accurat... |
801 |
sk->sk_sndbuf = 2 * SKB_TRUESIZE(64 * 1024); |
1da177e4c Linux-2.6.12-rc2 |
802 |
} |
1da177e4c Linux-2.6.12-rc2 |
803 804 805 |
return 0; fail: |
5c8cafd65 [NETNS]: icmp(v6)... |
806 |
for (j = 0; j < i; j++) |
1ed8516f0 [IPV6]: Simplify ... |
807 |
inet_ctl_sock_destroy(net->ipv6.icmp_sk[j]); |
98c6d1b26 [NETNS]: Make icm... |
808 |
kfree(net->ipv6.icmp_sk); |
1da177e4c Linux-2.6.12-rc2 |
809 810 |
return err; } |
98c6d1b26 [NETNS]: Make icm... |
811 |
static void __net_exit icmpv6_sk_exit(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
812 813 |
{ int i; |
6f9120422 [PATCH] for_each_... |
814 |
for_each_possible_cpu(i) { |
1ed8516f0 [IPV6]: Simplify ... |
815 |
inet_ctl_sock_destroy(net->ipv6.icmp_sk[i]); |
1da177e4c Linux-2.6.12-rc2 |
816 |
} |
98c6d1b26 [NETNS]: Make icm... |
817 818 |
kfree(net->ipv6.icmp_sk); } |
8ed7edce8 ipv6: fix inet6_i... |
819 |
static struct pernet_operations icmpv6_sk_ops = { |
98c6d1b26 [NETNS]: Make icm... |
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
.init = icmpv6_sk_init, .exit = icmpv6_sk_exit, }; int __init icmpv6_init(void) { int err; err = register_pernet_subsys(&icmpv6_sk_ops); if (err < 0) return err; err = -EAGAIN; if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) goto fail; return 0; fail: printk(KERN_ERR "Failed to register ICMP6 protocol "); unregister_pernet_subsys(&icmpv6_sk_ops); return err; } |
8ed7edce8 ipv6: fix inet6_i... |
843 |
void icmpv6_cleanup(void) |
98c6d1b26 [NETNS]: Make icm... |
844 845 |
{ unregister_pernet_subsys(&icmpv6_sk_ops); |
1da177e4c Linux-2.6.12-rc2 |
846 847 |
inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); } |
98c6d1b26 [NETNS]: Make icm... |
848 |
|
9b5b5cff9 [NET]: Add const ... |
849 |
static const struct icmp6_err { |
1da177e4c Linux-2.6.12-rc2 |
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 |
int err; int fatal; } tab_unreach[] = { { /* NOROUTE */ .err = ENETUNREACH, .fatal = 0, }, { /* ADM_PROHIBITED */ .err = EACCES, .fatal = 1, }, { /* Was NOT_NEIGHBOUR, now reserved */ .err = EHOSTUNREACH, .fatal = 0, }, { /* ADDR_UNREACH */ .err = EHOSTUNREACH, .fatal = 0, }, { /* PORT_UNREACH */ .err = ECONNREFUSED, .fatal = 1, }, }; |
d5fdd6bab ipv6: Use correct... |
874 |
int icmpv6_err_convert(u8 type, u8 code, int *err) |
1da177e4c Linux-2.6.12-rc2 |
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 |
{ int fatal = 0; *err = EPROTO; switch (type) { case ICMPV6_DEST_UNREACH: fatal = 1; if (code <= ICMPV6_PORT_UNREACH) { *err = tab_unreach[code].err; fatal = tab_unreach[code].fatal; } break; case ICMPV6_PKT_TOOBIG: *err = EMSGSIZE; break; |
1ab1457c4 [NET] IPV6: Fix w... |
892 |
|
1da177e4c Linux-2.6.12-rc2 |
893 894 895 896 897 898 899 900 |
case ICMPV6_PARAMPROB: *err = EPROTO; fatal = 1; break; case ICMPV6_TIME_EXCEED: *err = EHOSTUNREACH; break; |
3ff50b799 [NET]: cleanup ex... |
901 |
} |
1da177e4c Linux-2.6.12-rc2 |
902 903 904 |
return fatal; } |
7159039a1 [IPV6]: Decentral... |
905 |
EXPORT_SYMBOL(icmpv6_err_convert); |
1da177e4c Linux-2.6.12-rc2 |
906 |
#ifdef CONFIG_SYSCTL |
760f2d018 [NETNS][IPV6]: Ma... |
907 |
ctl_table ipv6_icmp_table_template[] = { |
1da177e4c Linux-2.6.12-rc2 |
908 |
{ |
1da177e4c Linux-2.6.12-rc2 |
909 |
.procname = "ratelimit", |
41a76906b [NETNS][IPV6]: Ma... |
910 |
.data = &init_net.ipv6.sysctl.icmpv6_time, |
1da177e4c Linux-2.6.12-rc2 |
911 912 |
.maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
913 |
.proc_handler = proc_dointvec_ms_jiffies, |
1da177e4c Linux-2.6.12-rc2 |
914 |
}, |
f8572d8f2 sysctl net: Remov... |
915 |
{ }, |
1da177e4c Linux-2.6.12-rc2 |
916 |
}; |
760f2d018 [NETNS][IPV6]: Ma... |
917 |
|
2c8c1e729 net: spread __net... |
918 |
struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net) |
760f2d018 [NETNS][IPV6]: Ma... |
919 920 921 922 923 924 |
{ struct ctl_table *table; table = kmemdup(ipv6_icmp_table_template, sizeof(ipv6_icmp_table_template), GFP_KERNEL); |
5ee091050 [IPV6] SYSCTL: co... |
925 926 927 |
if (table) table[0].data = &net->ipv6.sysctl.icmpv6_time; |
760f2d018 [NETNS][IPV6]: Ma... |
928 929 |
return table; } |
1da177e4c Linux-2.6.12-rc2 |
930 |
#endif |