aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/icmp.h3
-rw-r--r--net/ipv4/icmp.c17
-rw-r--r--net/ipv4/ip_sockglue.c14
3 files changed, 19 insertions, 15 deletions
diff --git a/include/linux/icmp.h b/include/linux/icmp.h
index 8fc38a34cb20..0af4d210ee31 100644
--- a/include/linux/icmp.h
+++ b/include/linux/icmp.h
@@ -37,6 +37,7 @@ static inline bool icmp_is_err(int type)
}
void ip_icmp_error_rfc4884(const struct sk_buff *skb,
- struct sock_ee_data_rfc4884 *out);
+ struct sock_ee_data_rfc4884 *out,
+ int thlen, int off);
#endif /* _LINUX_ICMP_H */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 8d2654cdbd77..7498c58460a1 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1151,24 +1151,15 @@ static bool ip_icmp_error_rfc4884_validate(const struct sk_buff *skb, int off)
}
void ip_icmp_error_rfc4884(const struct sk_buff *skb,
- struct sock_ee_data_rfc4884 *out)
+ struct sock_ee_data_rfc4884 *out,
+ int thlen, int off)
{
- int hlen, off;
-
- switch (icmp_hdr(skb)->type) {
- case ICMP_DEST_UNREACH:
- case ICMP_TIME_EXCEEDED:
- case ICMP_PARAMETERPROB:
- break;
- default:
- return;
- }
+ int hlen;
/* original datagram headers: end of icmph to payload (skb->data) */
- hlen = -skb_transport_offset(skb) - sizeof(struct icmphdr);
+ hlen = -skb_transport_offset(skb) - thlen;
/* per rfc 4884: minimal datagram length of 128 bytes */
- off = icmp_hdr(skb)->un.reserved[1] * sizeof(u32);
if (off < 128 || off < hlen)
return;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 8dc027e54c5b..d2c223554ff7 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -390,6 +390,18 @@ int ip_ra_control(struct sock *sk, unsigned char on,
return 0;
}
+static void ipv4_icmp_error_rfc4884(const struct sk_buff *skb,
+ struct sock_ee_data_rfc4884 *out)
+{
+ switch (icmp_hdr(skb)->type) {
+ case ICMP_DEST_UNREACH:
+ case ICMP_TIME_EXCEEDED:
+ case ICMP_PARAMETERPROB:
+ ip_icmp_error_rfc4884(skb, out, sizeof(struct icmphdr),
+ icmp_hdr(skb)->un.reserved[1] * 4);
+ }
+}
+
void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
__be16 port, u32 info, u8 *payload)
{
@@ -413,7 +425,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
if (skb_pull(skb, payload - skb->data)) {
if (inet_sk(sk)->recverr_rfc4884)
- ip_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
+ ipv4_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
skb_reset_transport_header(skb);
if (sock_queue_err_skb(sk, skb) == 0)