aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/icmp.c
diff options
context:
space:
mode:
authorAndreas Roeseler <andreas.a.roeseler@gmail.com>2021-06-26 09:07:46 -0500
committerDavid S. Miller <davem@davemloft.net>2021-06-28 14:29:45 -0700
commit1fd07f33c3ea2b4aa77426f13e8cb91d4f55af8f (patch)
tree6c50937b3c4c2105bffac3ec1bdb205b1e966da7 /net/ipv4/icmp.c
parentnet: sparx5: fix error return code in sparx5_register_notifier_blocks() (diff)
downloadlinux-dev-1fd07f33c3ea2b4aa77426f13e8cb91d4f55af8f.tar.xz
linux-dev-1fd07f33c3ea2b4aa77426f13e8cb91d4f55af8f.zip
ipv6: ICMPV6: add response to ICMPV6 RFC 8335 PROBE messages
This patch builds off of commit 2b246b2569cd2ac6ff700d0dce56b8bae29b1842 and adds functionality to respond to ICMPV6 PROBE requests. Add icmp_build_probe function to construct PROBE requests for both ICMPV4 and ICMPV6. Modify icmpv6_rcv to detect ICMPV6 PROBE messages and call the icmpv6_echo_reply handler. Modify icmpv6_echo_reply to build a PROBE response message based on the queried interface. This patch has been tested using a branch of the iputils git repo which can be found here: https://github.com/Juniper-Clinic-2020/iputils/tree/probe-request Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r--net/ipv4/icmp.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 0a57f1892e7e..c695d294a5df 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -993,14 +993,8 @@ static bool icmp_redirect(struct sk_buff *skb)
static bool icmp_echo(struct sk_buff *skb)
{
- struct icmp_ext_hdr *ext_hdr, _ext_hdr;
- struct icmp_ext_echo_iio *iio, _iio;
struct icmp_bxm icmp_param;
- struct net_device *dev;
- char buff[IFNAMSIZ];
struct net *net;
- u16 ident_len;
- u8 status;
net = dev_net(skb_dst(skb)->dev);
/* should there be an ICMP stat for ignored echos? */
@@ -1013,20 +1007,46 @@ static bool icmp_echo(struct sk_buff *skb)
icmp_param.data_len = skb->len;
icmp_param.head_len = sizeof(struct icmphdr);
- if (icmp_param.data.icmph.type == ICMP_ECHO) {
+ if (icmp_param.data.icmph.type == ICMP_ECHO)
icmp_param.data.icmph.type = ICMP_ECHOREPLY;
- goto send_reply;
- }
- if (!net->ipv4.sysctl_icmp_echo_enable_probe)
+ else if (!icmp_build_probe(skb, &icmp_param.data.icmph))
return true;
+
+ icmp_reply(&icmp_param, skb);
+ return true;
+}
+
+/* Helper for icmp_echo and icmpv6_echo_reply.
+ * Searches for net_device that matches PROBE interface identifier
+ * and builds PROBE reply message in icmphdr.
+ *
+ * Returns false if PROBE responses are disabled via sysctl
+ */
+
+bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
+{
+ struct icmp_ext_hdr *ext_hdr, _ext_hdr;
+ struct icmp_ext_echo_iio *iio, _iio;
+ struct net *net = dev_net(skb->dev);
+ struct net_device *dev;
+ char buff[IFNAMSIZ];
+ u16 ident_len;
+ u8 status;
+
+ if (!net->ipv4.sysctl_icmp_echo_enable_probe)
+ return false;
+
/* We currently only support probing interfaces on the proxy node
* Check to ensure L-bit is set
*/
- if (!(ntohs(icmp_param.data.icmph.un.echo.sequence) & 1))
- return true;
+ if (!(ntohs(icmphdr->un.echo.sequence) & 1))
+ return false;
/* Clear status bits in reply message */
- icmp_param.data.icmph.un.echo.sequence &= htons(0xFF00);
- icmp_param.data.icmph.type = ICMP_EXT_ECHOREPLY;
+ icmphdr->un.echo.sequence &= htons(0xFF00);
+ if (icmphdr->type == ICMP_EXT_ECHO)
+ icmphdr->type = ICMP_EXT_ECHOREPLY;
+ else
+ icmphdr->type = ICMPV6_EXT_ECHO_REPLY;
ext_hdr = skb_header_pointer(skb, 0, sizeof(_ext_hdr), &_ext_hdr);
/* Size of iio is class_type dependent.
* Only check header here and assign length based on ctype in the switch statement
@@ -1087,8 +1107,8 @@ static bool icmp_echo(struct sk_buff *skb)
goto send_mal_query;
}
if (!dev) {
- icmp_param.data.icmph.code = ICMP_EXT_CODE_NO_IF;
- goto send_reply;
+ icmphdr->code = ICMP_EXT_CODE_NO_IF;
+ return true;
}
/* Fill bits in reply message */
if (dev->flags & IFF_UP)
@@ -1098,14 +1118,13 @@ static bool icmp_echo(struct sk_buff *skb)
if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list))
status |= ICMP_EXT_ECHOREPLY_IPV6;
dev_put(dev);
- icmp_param.data.icmph.un.echo.sequence |= htons(status);
-send_reply:
- icmp_reply(&icmp_param, skb);
- return true;
+ icmphdr->un.echo.sequence |= htons(status);
+ return true;
send_mal_query:
- icmp_param.data.icmph.code = ICMP_EXT_CODE_MAL_QUERY;
- goto send_reply;
+ icmphdr->code = ICMP_EXT_CODE_MAL_QUERY;
+ return true;
}
+EXPORT_SYMBOL_GPL(icmp_build_probe);
/*
* Handle ICMP Timestamp requests.