netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE
@ 2021-02-03 23:24 Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 1/5] icmp: " Andreas Roeseler
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-03 23:24 UTC (permalink / raw)
  To: davem; +Cc: kuznet, yoshfuji, kuba, netdev

The popular utility ping has several severe limitations such as the
inability to query specific interfaces on a node and requiring
bidirectional connectivity between the probing and probed interfaces.
RFC 8335 attempts to solve these limitations by creating the new utility
PROBE which is a specialized ICMP message that makes use of the ICMP
Extention Structure outlined in RFC 4884.

This patchset adds definitions for the ICMP Extended Echo Request and
Reply (PROBE) types for both IPV4 and IPV6, adds a sysctl to enable 
response to PROBE messages, expands the list of supported ICMP messages
to accommodate PROBE types, and adds functionality to respond to PROBE
requests.

Changes since v1:
 - Add AFI definitions
 - Switch to functions such as dev_get_by_name and ip_dev_find to lookup
   net devices 

Andreas Roeseler (5):
  icmp: add support for RFC 8335 PROBE
  ICMPV6: add support for RFC 8335 PROBE
  net: add sysctl for enabling RFC 8335 PROBE messages
  net: add support for sending RFC 8335 PROBE messages
  icmp: add response to RFC 8335 PROBE messages

 include/net/netns/ipv4.h    |  1 +
 include/uapi/linux/icmp.h   | 24 +++++++++
 include/uapi/linux/icmpv6.h |  6 +++
 net/ipv4/icmp.c             | 98 +++++++++++++++++++++++++++++++++----
 net/ipv4/ping.c             |  4 +-
 net/ipv4/sysctl_net_ipv4.c  |  7 +++
 6 files changed, 129 insertions(+), 11 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH V2 net-next 1/5] icmp: add support for RFC 8335 PROBE
  2021-02-03 23:24 [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE Andreas Roeseler
@ 2021-02-03 23:24 ` Andreas Roeseler
  2021-02-04 19:42   ` Willem de Bruijn
  2021-02-03 23:24 ` [PATCH V2 net-next 2/5] ICMPV6: " Andreas Roeseler
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-03 23:24 UTC (permalink / raw)
  To: davem; +Cc: kuznet, yoshfuji, kuba, netdev

Add definitions for PROBE ICMP types and codes.

Add AFI definitions for IP and IPV6 as specified by IANA

Add a struct to represent the additional header when probing by IP
address (ctype == 3) for use in parsing incoming PROBE messages.

Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
---
Changes since v1:
 - Add AFI_IP and AFI_IP6 definitions
---
 include/uapi/linux/icmp.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/include/uapi/linux/icmp.h b/include/uapi/linux/icmp.h
index fb169a50895e..e70bfcc06247 100644
--- a/include/uapi/linux/icmp.h
+++ b/include/uapi/linux/icmp.h
@@ -66,6 +66,23 @@
 #define ICMP_EXC_TTL		0	/* TTL count exceeded		*/
 #define ICMP_EXC_FRAGTIME	1	/* Fragment Reass time exceeded	*/
 
+/* Codes for EXT_ECHO (PROBE) */
+#define ICMP_EXT_ECHO		42
+#define ICMP_EXT_ECHOREPLY	43
+#define ICMP_EXT_MAL_QUERY	1	/* Malformed Query */
+#define ICMP_EXT_NO_IF		2	/* No such Interface */
+#define ICMP_EXT_NO_TABLE_ENT	3	/* No such Table Entry */
+#define ICMP_EXT_MULT_IFS	4	/* Multiple Interfaces Satisfy Query */
+
+/* constants for EXT_ECHO (PROBE) */
+#define EXT_ECHOREPLY_ACTIVE	(1 << 2)/* position of active flag in reply */
+#define EXT_ECHOREPLY_IPV4	(1 << 1)/* position of ipv4 flag in reply */
+#define EXT_ECHOREPLY_IPV6	1	/* position of ipv6 flag in reply */
+#define CTYPE_NAME		1
+#define CTYPE_INDEX		2
+#define CTYPE_ADDR		3
+#define AFI_IP			1	/* Address Family Identifier for IPV4 */
+#define AFI_IP6			2	/* Address Family Identifier for IPV6 */
 
 struct icmphdr {
   __u8		type;
@@ -118,4 +135,11 @@ struct icmp_extobj_hdr {
 	__u8		class_type;
 };
 
+/* RFC 8335: 2.1 Header for C-type 3 payload */
+struct icmp_ext_ctype3_hdr {
+	__u16		afi;
+	__u8		addrlen;
+	__u8		reserved;
+};
+
 #endif /* _UAPI_LINUX_ICMP_H */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH V2 net-next 2/5] ICMPV6: add support for RFC 8335 PROBE
  2021-02-03 23:24 [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 1/5] icmp: " Andreas Roeseler
@ 2021-02-03 23:24 ` Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 3/5] net: add sysctl for enabling RFC 8335 PROBE messages Andreas Roeseler
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-03 23:24 UTC (permalink / raw)
  To: davem; +Cc: kuznet, yoshfuji, kuba, netdev

Add definitions for the ICMPV6 type of Extended Echo Request and
Extended Echo Reply, as defined in sections 2 and 3 of RFC 8335.

Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
---
 include/uapi/linux/icmpv6.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/uapi/linux/icmpv6.h b/include/uapi/linux/icmpv6.h
index 0564fd7ccde4..b2a9017ddb2d 100644
--- a/include/uapi/linux/icmpv6.h
+++ b/include/uapi/linux/icmpv6.h
@@ -140,6 +140,12 @@ struct icmp6hdr {
 #define ICMPV6_UNK_OPTION		2
 #define ICMPV6_HDR_INCOMP		3
 
+/*
+ *	Codes for EXT_ECHO (PROBE)
+ */
+#define ICMPV6_EXT_ECHO_REQUEST		160
+#define ICMPV6_EXT_ECHO_REPLY		161
+
 /*
  *	constants for (set|get)sockopt
  */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH V2 net-next 3/5] net: add sysctl for enabling RFC 8335 PROBE messages
  2021-02-03 23:24 [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 1/5] icmp: " Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 2/5] ICMPV6: " Andreas Roeseler
@ 2021-02-03 23:24 ` Andreas Roeseler
  2021-02-04 19:52   ` Willem de Bruijn
  2021-02-03 23:24 ` [PATCH V2 net-next 4/5] net: add support for sending " Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 5/5] icmp: add response to " Andreas Roeseler
  4 siblings, 1 reply; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-03 23:24 UTC (permalink / raw)
  To: davem; +Cc: kuznet, yoshfuji, kuba, netdev

Section 8 of RFC 8335 specifies potential security concerns of
responding to PROBE requests, and states that nodes that support PROBE
functionality MUST be able to enable/disable responses and it is
disabled by default. 

Add sysctl to enable responses to PROBE messages. 

Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
---
Changes since v1:
 - Combine patches related to sysctl into one patch
---
 include/net/netns/ipv4.h   | 1 +
 net/ipv4/sysctl_net_ipv4.c | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 70a2a085dd1a..362388ab40c8 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -85,6 +85,7 @@ struct netns_ipv4 {
 #endif
 
 	int sysctl_icmp_echo_ignore_all;
+	int sysctl_icmp_echo_enable_probe;
 	int sysctl_icmp_echo_ignore_broadcasts;
 	int sysctl_icmp_ignore_bogus_error_responses;
 	int sysctl_icmp_ratelimit;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index e5798b3b59d2..06b7241bc01d 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -599,6 +599,13 @@ static struct ctl_table ipv4_net_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
+	{
+		.procname	= "icmp_echo_enable_probe",
+		.data		= &init_net.ipv4.sysctl_icmp_echo_enable_probe,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
 	{
 		.procname	= "icmp_echo_ignore_broadcasts",
 		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH V2 net-next 4/5] net: add support for sending RFC 8335 PROBE messages
  2021-02-03 23:24 [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE Andreas Roeseler
                   ` (2 preceding siblings ...)
  2021-02-03 23:24 ` [PATCH V2 net-next 3/5] net: add sysctl for enabling RFC 8335 PROBE messages Andreas Roeseler
@ 2021-02-03 23:24 ` Andreas Roeseler
  2021-02-03 23:24 ` [PATCH V2 net-next 5/5] icmp: add response to " Andreas Roeseler
  4 siblings, 0 replies; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-03 23:24 UTC (permalink / raw)
  To: davem; +Cc: kuznet, yoshfuji, kuba, netdev

Modify the ping_supported function to support PROBE message types. This
allows tools such as the ping command in the iputils package to be
modified to send PROBE requests through the existing framework for
sending ping requests.

Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
---
 net/ipv4/ping.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 8b943f85fff9..1c9f71a37258 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -453,7 +453,9 @@ EXPORT_SYMBOL_GPL(ping_bind);
 static inline int ping_supported(int family, int type, int code)
 {
 	return (family == AF_INET && type == ICMP_ECHO && code == 0) ||
-	       (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0);
+	       (family == AF_INET && type == ICMP_EXT_ECHO && code == 0) ||
+	       (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0) ||
+	       (family == AF_INET6 && type == ICMPV6_EXT_ECHO_REQUEST && code == 0);
 }
 
 /*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH V2 net-next 5/5] icmp: add response to RFC 8335 PROBE messages
  2021-02-03 23:24 [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE Andreas Roeseler
                   ` (3 preceding siblings ...)
  2021-02-03 23:24 ` [PATCH V2 net-next 4/5] net: add support for sending " Andreas Roeseler
@ 2021-02-03 23:24 ` Andreas Roeseler
  2021-02-04 19:52   ` Willem de Bruijn
  2021-02-04 20:16   ` Jakub Kicinski
  4 siblings, 2 replies; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-03 23:24 UTC (permalink / raw)
  To: davem; +Cc: kuznet, yoshfuji, kuba, netdev

Modify the icmp_rcv function to check for PROBE messages and call
icmp_echo if a PROBE request is detected.

Modify the existing icmp_echo function to respond to both ping and PROBE
requests.

This was tested using a custom modification of the iputils package and
wireshark. It supports IPV4 probing by name, ifindex, and probing by both IPV4 and IPV6
addresses. It currently does not support responding to probes off the proxy node
(See RFC 8335 Section 2). 


Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
---
Changes since v1:
 - Reorder variable declarations to follow coding style
 - Switch to functions such as dev_get_by_name and ip_dev_find to lookup
   net devices
---
 net/ipv4/icmp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 88 insertions(+), 10 deletions(-)

diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 396b492c804f..18f9a2a3bf59 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -983,21 +983,85 @@ static bool icmp_redirect(struct sk_buff *skb)
 
 static bool icmp_echo(struct sk_buff *skb)
 {
+	struct icmp_bxm icmp_param;
 	struct net *net;
+	struct net_device *dev;
+	struct icmp_extobj_hdr *extobj_hdr;
+	struct icmp_ext_ctype3_hdr *ctype3_hdr;
+	__u8 status;
 
 	net = dev_net(skb_dst(skb)->dev);
-	if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
-		struct icmp_bxm icmp_param;
+	/* should there be an ICMP stat for ignored echos? */
+	if (net->ipv4.sysctl_icmp_echo_ignore_all)
+		return true;
+
+	icmp_param.data.icmph		= *icmp_hdr(skb);
+	icmp_param.skb			= skb;
+	icmp_param.offset		= 0;
+	icmp_param.data_len		= skb->len;
+	icmp_param.head_len		= sizeof(struct icmphdr);
 
-		icmp_param.data.icmph	   = *icmp_hdr(skb);
+	if (icmp_param.data.icmph.type == ICMP_ECHO) {
 		icmp_param.data.icmph.type = ICMP_ECHOREPLY;
-		icmp_param.skb		   = skb;
-		icmp_param.offset	   = 0;
-		icmp_param.data_len	   = skb->len;
-		icmp_param.head_len	   = sizeof(struct icmphdr);
-		icmp_reply(&icmp_param, skb);
+		goto send_reply;
 	}
-	/* should there be an ICMP stat for ignored echos? */
+	if (!net->ipv4.sysctl_icmp_echo_enable_probe)
+		return true;
+	/* We currently do not support probing off the proxy node */
+	if (!(ntohs(icmp_param.data.icmph.un.echo.sequence) & 1))
+		return true;
+
+	icmp_param.data.icmph.type = ICMP_EXT_ECHOREPLY;
+	icmp_param.data.icmph.un.echo.sequence &= htons(0xFF00);
+	extobj_hdr = (struct icmp_extobj_hdr *)(skb->data + sizeof(struct icmp_ext_hdr));
+	ctype3_hdr = (struct icmp_ext_ctype3_hdr *)(extobj_hdr + 1);
+	status = 0;
+	switch (extobj_hdr->class_type) {
+	case CTYPE_NAME:
+		dev = dev_get_by_name(net, (char *)(extobj_hdr + 1));
+		break;
+	case CTYPE_INDEX:
+		dev = dev_get_by_index(net, ntohl(*((uint32_t *)(extobj_hdr + 1))));
+		break;
+	case CTYPE_ADDR:
+		switch (ntohs(ctype3_hdr->afi)) {
+		case AFI_IP:
+			dev = ip_dev_find(net, *(__be32 *)(ctype3_hdr + 1));
+			break;
+		case AFI_IP6:
+			dev = ipv6_dev_find(net, (struct in6_addr *)(ctype3_hdr + 1), dev);
+			if(dev) dev_hold(dev);
+			break;
+		default:
+			icmp_param.data.icmph.code = ICMP_EXT_MAL_QUERY;
+			goto send_reply;
+		}
+		break;
+	default:
+		icmp_param.data.icmph.code = ICMP_EXT_MAL_QUERY;
+		goto send_reply;
+	}
+	if(!dev) {
+		icmp_param.data.icmph.code = ICMP_EXT_NO_IF;
+		goto send_reply;
+	}
+	/* RFC 8335: 3 the last 8 bits of the Extended Echo Reply Message
+	 *  are laid out as follows:
+	 *	+-+-+-+-+-+-+-+-+
+	 *	|State|Res|A|4|6|
+	 *	+-+-+-+-+-+-+-+-+
+	 */
+	if (dev->flags & IFF_UP)
+		status |= EXT_ECHOREPLY_ACTIVE;
+	if (dev->ip_ptr->ifa_list)
+		status |= EXT_ECHOREPLY_IPV4;
+	if (!list_empty(&dev->ip6_ptr->addr_list))
+		status |= EXT_ECHOREPLY_IPV6;
+	dev_put(dev);
+	icmp_param.data.icmph.un.echo.sequence |= htons(status);
+
+send_reply:
+	icmp_reply(&icmp_param, skb);
 	return true;
 }
 
@@ -1087,6 +1151,13 @@ int icmp_rcv(struct sk_buff *skb)
 	icmph = icmp_hdr(skb);
 
 	ICMPMSGIN_INC_STATS(net, icmph->type);
+
+	/*
+	 *	Check for ICMP Extended Echo (PROBE) messages
+	 */
+	if (icmph->type == ICMP_EXT_ECHO || icmph->type == ICMPV6_EXT_ECHO_REQUEST)
+		goto probe;
+
 	/*
 	 *	18 is the highest 'known' ICMP type. Anything else is a mystery
 	 *
@@ -1096,7 +1167,6 @@ int icmp_rcv(struct sk_buff *skb)
 	if (icmph->type > NR_ICMP_TYPES)
 		goto error;
 
-
 	/*
 	 *	Parse the ICMP message
 	 */
@@ -1123,6 +1193,7 @@ int icmp_rcv(struct sk_buff *skb)
 
 	success = icmp_pointers[icmph->type].handler(skb);
 
+success_check:
 	if (success)  {
 		consume_skb(skb);
 		return NET_RX_SUCCESS;
@@ -1136,6 +1207,13 @@ int icmp_rcv(struct sk_buff *skb)
 error:
 	__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
 	goto drop;
+probe:
+	/*
+	 * We can't use icmp_pointers[].handler() because the codes for PROBE
+	 *   messages are 42 or 160
+	 */
+	success = icmp_echo(skb);
+	goto success_check;
 }
 
 static bool ip_icmp_error_rfc4884_validate(const struct sk_buff *skb, int off)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH V2 net-next 1/5] icmp: add support for RFC 8335 PROBE
  2021-02-03 23:24 ` [PATCH V2 net-next 1/5] icmp: " Andreas Roeseler
@ 2021-02-04 19:42   ` Willem de Bruijn
  0 siblings, 0 replies; 11+ messages in thread
From: Willem de Bruijn @ 2021-02-04 19:42 UTC (permalink / raw)
  To: Andreas Roeseler
  Cc: David Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI,
	Jakub Kicinski, Network Development

On Wed, Feb 3, 2021 at 6:25 PM Andreas Roeseler
<andreas.a.roeseler@gmail.com> wrote:
>
> Add definitions for PROBE ICMP types and codes.
>
> Add AFI definitions for IP and IPV6 as specified by IANA
>
> Add a struct to represent the additional header when probing by IP
> address (ctype == 3) for use in parsing incoming PROBE messages.
>
> Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
> ---
> Changes since v1:
>  - Add AFI_IP and AFI_IP6 definitions
> ---
>  include/uapi/linux/icmp.h | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/include/uapi/linux/icmp.h b/include/uapi/linux/icmp.h
> index fb169a50895e..e70bfcc06247 100644
> --- a/include/uapi/linux/icmp.h
> +++ b/include/uapi/linux/icmp.h
> @@ -66,6 +66,23 @@
>  #define ICMP_EXC_TTL           0       /* TTL count exceeded           */
>  #define ICMP_EXC_FRAGTIME      1       /* Fragment Reass time exceeded */
>
> +/* Codes for EXT_ECHO (PROBE) */
> +#define ICMP_EXT_ECHO          42
> +#define ICMP_EXT_ECHOREPLY     43
> +#define ICMP_EXT_MAL_QUERY     1       /* Malformed Query */
> +#define ICMP_EXT_NO_IF         2       /* No such Interface */
> +#define ICMP_EXT_NO_TABLE_ENT  3       /* No such Table Entry */
> +#define ICMP_EXT_MULT_IFS      4       /* Multiple Interfaces Satisfy Query */
> +
> +/* constants for EXT_ECHO (PROBE) */
> +#define EXT_ECHOREPLY_ACTIVE   (1 << 2)/* position of active flag in reply */
> +#define EXT_ECHOREPLY_IPV4     (1 << 1)/* position of ipv4 flag in reply */
> +#define EXT_ECHOREPLY_IPV6     1       /* position of ipv6 flag in reply */
> +#define CTYPE_NAME             1
> +#define CTYPE_INDEX            2
> +#define CTYPE_ADDR             3

Please use a prefix. These definitions are too generic and may clash
with others. Same for the two below. Does all this need to be defined
UAPI?

> +#define AFI_IP                 1       /* Address Family Identifier for IPV4 */
> +#define AFI_IP6                        2       /* Address Family Identifier for IPV6 */
>
>  struct icmphdr {
>    __u8         type;
> @@ -118,4 +135,11 @@ struct icmp_extobj_hdr {
>         __u8            class_type;
>  };
>
> +/* RFC 8335: 2.1 Header for C-type 3 payload */
> +struct icmp_ext_ctype3_hdr {
> +       __u16           afi;
> +       __u8            addrlen;
> +       __u8            reserved;
> +};
> +
>  #endif /* _UAPI_LINUX_ICMP_H */
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V2 net-next 5/5] icmp: add response to RFC 8335 PROBE messages
  2021-02-03 23:24 ` [PATCH V2 net-next 5/5] icmp: add response to " Andreas Roeseler
@ 2021-02-04 19:52   ` Willem de Bruijn
  2021-02-05  5:01     ` Andreas Roeseler
  2021-02-04 20:16   ` Jakub Kicinski
  1 sibling, 1 reply; 11+ messages in thread
From: Willem de Bruijn @ 2021-02-04 19:52 UTC (permalink / raw)
  To: Andreas Roeseler
  Cc: David Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI,
	Jakub Kicinski, Network Development

On Wed, Feb 3, 2021 at 6:30 PM Andreas Roeseler
<andreas.a.roeseler@gmail.com> wrote:
>
> Modify the icmp_rcv function to check for PROBE messages and call
> icmp_echo if a PROBE request is detected.
>
> Modify the existing icmp_echo function to respond to both ping and PROBE
> requests.
>
> This was tested using a custom modification of the iputils package and
> wireshark. It supports IPV4 probing by name, ifindex, and probing by both IPV4 and IPV6
> addresses. It currently does not support responding to probes off the proxy node
> (See RFC 8335 Section 2).
>
>
> Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
> ---
> Changes since v1:
>  - Reorder variable declarations to follow coding style
>  - Switch to functions such as dev_get_by_name and ip_dev_find to lookup
>    net devices
> ---
>  net/ipv4/icmp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 88 insertions(+), 10 deletions(-)
>
> diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
> index 396b492c804f..18f9a2a3bf59 100644
> --- a/net/ipv4/icmp.c
> +++ b/net/ipv4/icmp.c
> @@ -983,21 +983,85 @@ static bool icmp_redirect(struct sk_buff *skb)
>
>  static bool icmp_echo(struct sk_buff *skb)
>  {
> +       struct icmp_bxm icmp_param;
>         struct net *net;
> +       struct net_device *dev;
> +       struct icmp_extobj_hdr *extobj_hdr;
> +       struct icmp_ext_ctype3_hdr *ctype3_hdr;
> +       __u8 status;

nit: please maintain reverse christmas tree variable ordering

>
>         net = dev_net(skb_dst(skb)->dev);
> -       if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
> -               struct icmp_bxm icmp_param;
> +       /* should there be an ICMP stat for ignored echos? */
> +       if (net->ipv4.sysctl_icmp_echo_ignore_all)
> +               return true;
> +
> +       icmp_param.data.icmph           = *icmp_hdr(skb);
> +       icmp_param.skb                  = skb;
> +       icmp_param.offset               = 0;
> +       icmp_param.data_len             = skb->len;
> +       icmp_param.head_len             = sizeof(struct icmphdr);
>
> -               icmp_param.data.icmph      = *icmp_hdr(skb);
> +       if (icmp_param.data.icmph.type == ICMP_ECHO) {
>                 icmp_param.data.icmph.type = ICMP_ECHOREPLY;
> -               icmp_param.skb             = skb;
> -               icmp_param.offset          = 0;
> -               icmp_param.data_len        = skb->len;
> -               icmp_param.head_len        = sizeof(struct icmphdr);
> -               icmp_reply(&icmp_param, skb);
> +               goto send_reply;
>         }
> -       /* should there be an ICMP stat for ignored echos? */
> +       if (!net->ipv4.sysctl_icmp_echo_enable_probe)
> +               return true;
> +       /* We currently do not support probing off the proxy node */
> +       if (!(ntohs(icmp_param.data.icmph.un.echo.sequence) & 1))
> +               return true;

What does this comment mean?

And why does the sequence number need to be even?

> +
> +       icmp_param.data.icmph.type = ICMP_EXT_ECHOREPLY;
> +       icmp_param.data.icmph.un.echo.sequence &= htons(0xFF00);

Why this mask?

> +       extobj_hdr = (struct icmp_extobj_hdr *)(skb->data + sizeof(struct icmp_ext_hdr));
> +       ctype3_hdr = (struct icmp_ext_ctype3_hdr *)(extobj_hdr + 1);

It is not safe to trust the contents of unverified packets. We cannot
just cast to a string and call dev_get_by_name. Need to verify packet
length and data format.

Also below code just casts to the expected data type at some offset.
Can that be defined more formally as header structs? Like ctype3_hdr,
but for other headers, as well.

> +       status = 0;
> +       switch (extobj_hdr->class_type) {
> +       case CTYPE_NAME:
> +               dev = dev_get_by_name(net, (char *)(extobj_hdr + 1));
> +               break;
> +       case CTYPE_INDEX:
> +               dev = dev_get_by_index(net, ntohl(*((uint32_t *)(extobj_hdr + 1))));
> +               break;
> +       case CTYPE_ADDR:
> +               switch (ntohs(ctype3_hdr->afi)) {
> +               case AFI_IP:
> +                       dev = ip_dev_find(net, *(__be32 *)(ctype3_hdr + 1));
> +                       break;
> +               case AFI_IP6:
> +                       dev = ipv6_dev_find(net, (struct in6_addr *)(ctype3_hdr + 1), dev);
> +                       if(dev) dev_hold(dev);
> +                       break;
> +               default:
> +                       icmp_param.data.icmph.code = ICMP_EXT_MAL_QUERY;
> +                       goto send_reply;
> +               }
> +               break;
> +       default:
> +               icmp_param.data.icmph.code = ICMP_EXT_MAL_QUERY;
> +               goto send_reply;
> +       }
> +       if(!dev) {
> +               icmp_param.data.icmph.code = ICMP_EXT_NO_IF;
> +               goto send_reply;
> +       }
> +       /* RFC 8335: 3 the last 8 bits of the Extended Echo Reply Message
> +        *  are laid out as follows:
> +        *      +-+-+-+-+-+-+-+-+
> +        *      |State|Res|A|4|6|
> +        *      +-+-+-+-+-+-+-+-+
> +        */
> +       if (dev->flags & IFF_UP)
> +               status |= EXT_ECHOREPLY_ACTIVE;
> +       if (dev->ip_ptr->ifa_list)
> +               status |= EXT_ECHOREPLY_IPV4;
> +       if (!list_empty(&dev->ip6_ptr->addr_list))
> +               status |= EXT_ECHOREPLY_IPV6;
> +       dev_put(dev);
> +       icmp_param.data.icmph.un.echo.sequence |= htons(status);
> +
> +send_reply:
> +       icmp_reply(&icmp_param, skb);
>         return true;
>  }

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V2 net-next 3/5] net: add sysctl for enabling RFC 8335 PROBE messages
  2021-02-03 23:24 ` [PATCH V2 net-next 3/5] net: add sysctl for enabling RFC 8335 PROBE messages Andreas Roeseler
@ 2021-02-04 19:52   ` Willem de Bruijn
  0 siblings, 0 replies; 11+ messages in thread
From: Willem de Bruijn @ 2021-02-04 19:52 UTC (permalink / raw)
  To: Andreas Roeseler
  Cc: David Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI,
	Jakub Kicinski, Network Development

On Wed, Feb 3, 2021 at 6:29 PM Andreas Roeseler
<andreas.a.roeseler@gmail.com> wrote:
>
> Section 8 of RFC 8335 specifies potential security concerns of
> responding to PROBE requests, and states that nodes that support PROBE
> functionality MUST be able to enable/disable responses and it is
> disabled by default.
>
> Add sysctl to enable responses to PROBE messages.
>
> Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
> ---
> Changes since v1:
>  - Combine patches related to sysctl into one patch
> ---
>  include/net/netns/ipv4.h   | 1 +
>  net/ipv4/sysctl_net_ipv4.c | 7 +++++++
>  2 files changed, 8 insertions(+)
>
> diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
> index 70a2a085dd1a..362388ab40c8 100644
> --- a/include/net/netns/ipv4.h
> +++ b/include/net/netns/ipv4.h
> @@ -85,6 +85,7 @@ struct netns_ipv4 {
>  #endif
>
>         int sysctl_icmp_echo_ignore_all;
> +       int sysctl_icmp_echo_enable_probe;
>         int sysctl_icmp_echo_ignore_broadcasts;
>         int sysctl_icmp_ignore_bogus_error_responses;
>         int sysctl_icmp_ratelimit;
> diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
> index e5798b3b59d2..06b7241bc01d 100644
> --- a/net/ipv4/sysctl_net_ipv4.c
> +++ b/net/ipv4/sysctl_net_ipv4.c
> @@ -599,6 +599,13 @@ static struct ctl_table ipv4_net_table[] = {
>                 .mode           = 0644,
>                 .proc_handler   = proc_dointvec
>         },
> +       {
> +               .procname       = "icmp_echo_enable_probe",
> +               .data           = &init_net.ipv4.sysctl_icmp_echo_enable_probe,
> +               .maxlen         = sizeof(int),
> +               .mode           = 0644,
> +               .proc_handler   = proc_dointvec
> +       },

proc_dointvec_minmax with zero and one.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V2 net-next 5/5] icmp: add response to RFC 8335 PROBE messages
  2021-02-03 23:24 ` [PATCH V2 net-next 5/5] icmp: add response to " Andreas Roeseler
  2021-02-04 19:52   ` Willem de Bruijn
@ 2021-02-04 20:16   ` Jakub Kicinski
  1 sibling, 0 replies; 11+ messages in thread
From: Jakub Kicinski @ 2021-02-04 20:16 UTC (permalink / raw)
  To: Andreas Roeseler; +Cc: davem, kuznet, yoshfuji, netdev

On Wed,  3 Feb 2021 15:24:55 -0800 Andreas Roeseler wrote:
> Modify the icmp_rcv function to check for PROBE messages and call
> icmp_echo if a PROBE request is detected.
> 
> Modify the existing icmp_echo function to respond to both ping and PROBE
> requests.
> 
> This was tested using a custom modification of the iputils package and
> wireshark. It supports IPV4 probing by name, ifindex, and probing by both IPV4 and IPV6
> addresses. It currently does not support responding to probes off the proxy node
> (See RFC 8335 Section 2). 
> 
> 
> Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>

make allmodconfig && make W=1 C=1 says:

../net/ipv4/icmp.c: note: in included file (through ../include/linux/spinlock.h, ../include/linux/mmzone.h, ../include/linux/gfp.h, ../include/linux/umh.h, ../include/linux/kmod.h, ../include/linux/module.h):
../include/linux/bottom_half.h:32:30: warning: context imbalance in 'icmp_reply' - different lock contexts for basic block
../include/linux/bottom_half.h:32:30: warning: context imbalance in '__icmp_send' - different lock contexts for basic block
../net/ipv4/icmp.c:1024:45: warning: cast to restricted __be32
../net/ipv4/icmp.c:1024:45: warning: cast to restricted __be32
../net/ipv4/icmp.c:1024:45: warning: cast to restricted __be32
../net/ipv4/icmp.c:1024:45: warning: cast to restricted __be32
../net/ipv4/icmp.c:1024:45: warning: cast to restricted __be32
../net/ipv4/icmp.c:1024:45: warning: cast to restricted __be32
../net/ipv4/icmp.c:1027:25: warning: cast to restricted __be16
../net/ipv4/icmp.c:1027:25: warning: cast to restricted __be16
../net/ipv4/icmp.c:1027:25: warning: cast to restricted __be16
../net/ipv4/icmp.c:1027:25: warning: cast to restricted __be16
../net/ipv4/icmp.c:1058:29: warning: incorrect type in argument 1 (different address spaces)
../net/ipv4/icmp.c:1058:29:    expected struct list_head const *head
../net/ipv4/icmp.c:1058:29:    got struct list_head [noderef] __rcu *
../net/ipv4/icmp.c: note: in included file (through ../include/linux/spinlock.h, ../include/linux/mmzone.h, ../include/linux/gfp.h, ../include/linux/umh.h, ../include/linux/kmod.h, ../include/linux/module.h):
../include/linux/bottom_half.h:32:30: warning: context imbalance in 'icmp_reply' - different lock contexts for basic block
../include/linux/bottom_half.h:32:30: warning: context imbalance in '__icmp_send' - different lock contexts for basic block
../net/ipv4/icmp.c:1056:16: warning: dereference of noderef expression
net/ipv4/icmp.o: In function `icmp_echo':
icmp.c:(.text+0x123a): undefined reference to `ipv6_dev_find'
make[1]: *** [vmlinux] Error 1
make: *** [__sub-make] Error 2
New errors added

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V2 net-next 5/5] icmp: add response to RFC 8335 PROBE messages
  2021-02-04 19:52   ` Willem de Bruijn
@ 2021-02-05  5:01     ` Andreas Roeseler
  0 siblings, 0 replies; 11+ messages in thread
From: Andreas Roeseler @ 2021-02-05  5:01 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: David Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI,
	Jakub Kicinski, Network Development

On Thu, 2021-02-04 at 14:52 -0500, Willem de Bruijn wrote:
> On Wed, Feb 3, 2021 at 6:30 PM Andreas Roeseler
> <andreas.a.roeseler@gmail.com> wrote:
> > 
> > Modify the icmp_rcv function to check for PROBE messages and call
> > icmp_echo if a PROBE request is detected.
> > 
> > Modify the existing icmp_echo function to respond to both ping and
> > PROBE
> > requests.
> > 
> > This was tested using a custom modification of the iputils package
> > and
> > wireshark. It supports IPV4 probing by name, ifindex, and probing
> > by both IPV4 and IPV6
> > addresses. It currently does not support responding to probes off
> > the proxy node
> > (See RFC 8335 Section 2).
> > 
> > 
> > Signed-off-by: Andreas Roeseler <andreas.a.roeseler@gmail.com>
> > ---
> > Changes since v1:
> >  - Reorder variable declarations to follow coding style
> >  - Switch to functions such as dev_get_by_name and ip_dev_find to
> > lookup
> >    net devices
> > ---
> >  net/ipv4/icmp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++-
> > ----
> >  1 file changed, 88 insertions(+), 10 deletions(-)
> > 
> > diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
> > index 396b492c804f..18f9a2a3bf59 100644
> > --- a/net/ipv4/icmp.c
> > +++ b/net/ipv4/icmp.c
> > @@ -983,21 +983,85 @@ static bool icmp_redirect(struct sk_buff
> > *skb)
> > 
> >  static bool icmp_echo(struct sk_buff *skb)
> >  {
> > +       struct icmp_bxm icmp_param;
> >         struct net *net;
> > +       struct net_device *dev;
> > +       struct icmp_extobj_hdr *extobj_hdr;
> > +       struct icmp_ext_ctype3_hdr *ctype3_hdr;
> > +       __u8 status;
> 
> nit: please maintain reverse christmas tree variable ordering
> 
> > 
> >         net = dev_net(skb_dst(skb)->dev);
> > -       if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
> > -               struct icmp_bxm icmp_param;
> > +       /* should there be an ICMP stat for ignored echos? */
> > +       if (net->ipv4.sysctl_icmp_echo_ignore_all)
> > +               return true;
> > +
> > +       icmp_param.data.icmph           = *icmp_hdr(skb);
> > +       icmp_param.skb                  = skb;
> > +       icmp_param.offset               = 0;
> > +       icmp_param.data_len             = skb->len;
> > +       icmp_param.head_len             = sizeof(struct icmphdr);
> > 
> > -               icmp_param.data.icmph      = *icmp_hdr(skb);
> > +       if (icmp_param.data.icmph.type == ICMP_ECHO) {
> >                 icmp_param.data.icmph.type = ICMP_ECHOREPLY;
> > -               icmp_param.skb             = skb;
> > -               icmp_param.offset          = 0;
> > -               icmp_param.data_len        = skb->len;
> > -               icmp_param.head_len        = sizeof(struct
> > icmphdr);
> > -               icmp_reply(&icmp_param, skb);
> > +               goto send_reply;
> >         }
> > -       /* should there be an ICMP stat for ignored echos? */
> > +       if (!net->ipv4.sysctl_icmp_echo_enable_probe)
> > +               return true;
> > +       /* We currently do not support probing off the proxy node
> > */
> > +       if (!(ntohs(icmp_param.data.icmph.un.echo.sequence) & 1))
> > +               return true;
> 
> What does this comment mean?
> 
> And why does the sequence number need to be even?

RFC 8335 Section 2 specifies that the ICMP Extended Echo Request
messages use a modified sequence number field, as follows.
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Identifier          |Sequence Number|   Reserved  |L|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The L-bit is set if the probed interface resides on the proxy node. We
only support probing interfaces that lie on the proxy node since it
simplifies the response handler and, if we wanted to know the status of
an interface on another node, we could simply probe that node instead.
This line ensures that the L-bit is set to 1.

I'll clarify the wording of the comment.

> 
> > +
> > +       icmp_param.data.icmph.type = ICMP_EXT_ECHOREPLY;
> > +       icmp_param.data.icmph.un.echo.sequence &= htons(0xFF00);
> 
> Why this mask?

This clears the status fields of the reply message to avoid sending old
data back to the probing host.

> 
> > +       extobj_hdr = (struct icmp_extobj_hdr *)(skb->data +
> > sizeof(struct icmp_ext_hdr));
> > +       ctype3_hdr = (struct icmp_ext_ctype3_hdr *)(extobj_hdr +
> > 1);
> 
> It is not safe to trust the contents of unverified packets. We cannot
> just cast to a string and call dev_get_by_name. Need to verify packet
> length and data format.
> 

Great catch, I will work on adding this into the next version.

> Also below code just casts to the expected data type at some offset.
> Can that be defined more formally as header structs? Like ctype3_hdr,
> but for other headers, as well.
> 

Will do.

> > +       status = 0;
> > +       switch (extobj_hdr->class_type) {
> > +       case CTYPE_NAME:
> > +               dev = dev_get_by_name(net, (char *)(extobj_hdr +
> > 1));
> > +               break;
> > +       case CTYPE_INDEX:
> > +               dev = dev_get_by_index(net, ntohl(*((uint32_t
> > *)(extobj_hdr + 1))));
> > +               break;
> > +       case CTYPE_ADDR:
> > +               switch (ntohs(ctype3_hdr->afi)) {
> > +               case AFI_IP:
> > +                       dev = ip_dev_find(net, *(__be32
> > *)(ctype3_hdr + 1));
> > +                       break;
> > +               case AFI_IP6:
> > +                       dev = ipv6_dev_find(net, (struct in6_addr
> > *)(ctype3_hdr + 1), dev);
> > +                       if(dev) dev_hold(dev);
> > +                       break;
> > +               default:
> > +                       icmp_param.data.icmph.code =
> > ICMP_EXT_MAL_QUERY;
> > +                       goto send_reply;
> > +               }
> > +               break;
> > +       default:
> > +               icmp_param.data.icmph.code = ICMP_EXT_MAL_QUERY;
> > +               goto send_reply;
> > +       }
> > +       if(!dev) {
> > +               icmp_param.data.icmph.code = ICMP_EXT_NO_IF;
> > +               goto send_reply;
> > +       }
> > +       /* RFC 8335: 3 the last 8 bits of the Extended Echo Reply
> > Message
> > +        *  are laid out as follows:
> > +        *      +-+-+-+-+-+-+-+-+
> > +        *      |State|Res|A|4|6|
> > +        *      +-+-+-+-+-+-+-+-+
> > +        */
> > +       if (dev->flags & IFF_UP)
> > +               status |= EXT_ECHOREPLY_ACTIVE;
> > +       if (dev->ip_ptr->ifa_list)
> > +               status |= EXT_ECHOREPLY_IPV4;
> > +       if (!list_empty(&dev->ip6_ptr->addr_list))
> > +               status |= EXT_ECHOREPLY_IPV6;
> > +       dev_put(dev);
> > +       icmp_param.data.icmph.un.echo.sequence |= htons(status);
> > +
> > +send_reply:
> > +       icmp_reply(&icmp_param, skb);
> >         return true;
> >  }



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-02-05  5:02 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-03 23:24 [PATCH V2 net-next 0/5] add support for RFC 8335 PROBE Andreas Roeseler
2021-02-03 23:24 ` [PATCH V2 net-next 1/5] icmp: " Andreas Roeseler
2021-02-04 19:42   ` Willem de Bruijn
2021-02-03 23:24 ` [PATCH V2 net-next 2/5] ICMPV6: " Andreas Roeseler
2021-02-03 23:24 ` [PATCH V2 net-next 3/5] net: add sysctl for enabling RFC 8335 PROBE messages Andreas Roeseler
2021-02-04 19:52   ` Willem de Bruijn
2021-02-03 23:24 ` [PATCH V2 net-next 4/5] net: add support for sending " Andreas Roeseler
2021-02-03 23:24 ` [PATCH V2 net-next 5/5] icmp: add response to " Andreas Roeseler
2021-02-04 19:52   ` Willem de Bruijn
2021-02-05  5:01     ` Andreas Roeseler
2021-02-04 20:16   ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).