diff options
| author | Li Wei <lw@cn.fujitsu.com> | 2013-02-21 17:18:44 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-02-22 15:10:18 -0500 |
| commit | 5b0520425e5ea81ba95ec486dd6bbb59a09fff0e (patch) | |
| tree | e506570823deb8fd65e52e34fe67cf327af2266e | |
| parent | 08dcdbf6a7b9d14c2302c5bd0c5390ddf122f664 (diff) | |
ipv4: fix error handling in icmp_protocol.
Now we handle icmp errors in each transport protocol's err_handler,
for icmp protocols, that is ping_err. Since this handler only care
of those icmp errors triggered by echo request, errors triggered
by echo reply(which sent by kernel) are sliently ignored.
So wrap ping_err() with icmp_err() to deal with those icmp errors.
Signed-off-by: Li Wei <lw@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/icmp.h | 1 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 2 | ||||
| -rw-r--r-- | net/ipv4/icmp.c | 23 |
3 files changed, 25 insertions, 1 deletions
diff --git a/include/net/icmp.h b/include/net/icmp.h index 9ac2524d1402..081439fd070e 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h | |||
| @@ -41,6 +41,7 @@ struct net; | |||
| 41 | 41 | ||
| 42 | extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info); | 42 | extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info); |
| 43 | extern int icmp_rcv(struct sk_buff *skb); | 43 | extern int icmp_rcv(struct sk_buff *skb); |
| 44 | extern void icmp_err(struct sk_buff *, u32 info); | ||
| 44 | extern int icmp_init(void); | 45 | extern int icmp_init(void); |
| 45 | extern void icmp_out_count(struct net *net, unsigned char type); | 46 | extern void icmp_out_count(struct net *net, unsigned char type); |
| 46 | 47 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9cbcb94a4c6d..15847e19b7dd 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -1577,7 +1577,7 @@ static const struct net_offload udp_offload = { | |||
| 1577 | 1577 | ||
| 1578 | static const struct net_protocol icmp_protocol = { | 1578 | static const struct net_protocol icmp_protocol = { |
| 1579 | .handler = icmp_rcv, | 1579 | .handler = icmp_rcv, |
| 1580 | .err_handler = ping_err, | 1580 | .err_handler = icmp_err, |
| 1581 | .no_policy = 1, | 1581 | .no_policy = 1, |
| 1582 | .netns_ok = 1, | 1582 | .netns_ok = 1, |
| 1583 | }; | 1583 | }; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 17ff9fd7cdda..3ac5dff79627 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
| @@ -934,6 +934,29 @@ error: | |||
| 934 | goto drop; | 934 | goto drop; |
| 935 | } | 935 | } |
| 936 | 936 | ||
| 937 | void icmp_err(struct sk_buff *skb, u32 info) | ||
| 938 | { | ||
| 939 | struct iphdr *iph = (struct iphdr *)skb->data; | ||
| 940 | struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); | ||
| 941 | int type = icmp_hdr(skb)->type; | ||
| 942 | int code = icmp_hdr(skb)->code; | ||
| 943 | struct net *net = dev_net(skb->dev); | ||
| 944 | |||
| 945 | /* | ||
| 946 | * Use ping_err to handle all icmp errors except those | ||
| 947 | * triggered by ICMP_ECHOREPLY which sent from kernel. | ||
| 948 | */ | ||
| 949 | if (icmph->type != ICMP_ECHOREPLY) { | ||
| 950 | ping_err(skb, info); | ||
| 951 | return; | ||
| 952 | } | ||
| 953 | |||
| 954 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) | ||
| 955 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ICMP, 0); | ||
| 956 | else if (type == ICMP_REDIRECT) | ||
| 957 | ipv4_redirect(skb, net, 0, 0, IPPROTO_ICMP, 0); | ||
| 958 | } | ||
| 959 | |||
| 937 | /* | 960 | /* |
| 938 | * This table is the definition of how we handle ICMP. | 961 | * This table is the definition of how we handle ICMP. |
| 939 | */ | 962 | */ |
