net: ipv6: Add support for default gateway discovery.

In IPv6, the default gateway and prefix length are determined by receiving
a router advertisement as defined in -
https://www.rfc-editor.org/rfc/rfc4861.

Add support for sending router solicitation (RS) and processing router
advertisements (RA).

If the RA has prefix info option and following conditions are met, then
gatewayip6 and net_prefix_length of ip6addr env variables are initialized.
These are later consumed by IPv6 code for non-local destination IP.

- "Router Lifetime" != 0
- Prefix is NOT link-local prefix (0xfe80::/10)
- L flag is 1
- "Valid Lifetime" != 0

Timing Parameters:
- MAX_RTR_SOLICITATION_DELAY (0-1s)
- RTR_SOLICITATION_INTERVAL (4s) (min retransmit delay)
- MAX_RTR_SOLICITATIONS (3 RS transmissions)

The functionality is enabled by CONFIG_IPV6_ROUTER_DISCOVERY and invoked
automatically from net_init_loop().

Signed-off-by: Ehsan Mohandesi <emohandesi@linux.microsoft.com>
Tested-by: Viacheslav Mitrofanov <v.v.mitrofanov@yadro.com>Reviewed-by:
Tested-by: Viacheslav Mitrofanov <v.v.mitrofanov@yadro.com>
Reviewed-by: Viacheslav Mitrofanov <v.v.mitrofanov@yadro.com>
Tested-by: Sergei Antonov <saproj@gmail.com>
Reviewed-by: Sergei Antonov <saproj@gmail.com>
diff --git a/include/ndisc.h b/include/ndisc.h
index f6f8eb6..d0fe3ac 100644
--- a/include/ndisc.h
+++ b/include/ndisc.h
@@ -19,6 +19,20 @@
 	__u8		opt[0];
 };
 
+/* struct rs_msg - ICMPv6 Router Solicitation message format */
+struct rs_msg {
+	struct icmp6hdr	icmph;
+	__u8		opt[0];
+};
+
+/* struct ra_msg - ICMPv6 Router Advertisement message format */
+struct ra_msg {
+	struct icmp6hdr	icmph;
+	__u32	reachable_time;
+	__u32	retransmission_timer;
+	__u8	opt[0];
+};
+
 /* struct echo_msg - ICMPv6 echo request/reply message format */
 struct echo_msg {
 	struct icmp6hdr	icmph;
@@ -57,6 +71,11 @@
  */
 void ndisc_init(void);
 
+/*
+ * ip6_send_rs() - Send IPv6 Router Solicitation Message
+ */
+void ip6_send_rs(void);
+
 /**
  * ndisc_receive() - Handle ND packet
  *
@@ -78,6 +97,8 @@
  * Return: 0 if no timeout, -1 otherwise
  */
 int ndisc_timeout_check(void);
+bool validate_ra(struct ip6_hdr *ip6);
+int process_ra(struct ip6_hdr *ip6, int len);
 #else
 static inline void ndisc_init(void)
 {
@@ -97,6 +118,20 @@
 {
 	return 0;
 }
+
+static inline void ip6_send_rs(void)
+{
+}
+
+static inline bool validate_ra(struct ip6_hdr *ip6)
+{
+	return true;
+}
+
+static inline int process_ra(struct ip6_hdr *ip6, int len)
+{
+	return 0;
+}
 #endif
 
 #endif /* __NDISC_H__ */
diff --git a/include/net.h b/include/net.h
index 1b09aa1..785cb10 100644
--- a/include/net.h
+++ b/include/net.h
@@ -508,7 +508,7 @@
 enum proto_t {
 	BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP,
 	NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP,
-	WOL, UDP, NCSI, WGET
+	WOL, UDP, NCSI, WGET, RS
 };
 
 extern char	net_boot_file_name[1024];/* Boot File name */
diff --git a/include/net6.h b/include/net6.h
index 2d7c5a0..beafc05 100644
--- a/include/net6.h
+++ b/include/net6.h
@@ -81,8 +81,17 @@
 			  0x00, 0x00, 0x00, 0x00, \
 			  0x00, 0x00, 0x00, 0x00, \
 			  0x00, 0x00, 0x00, 0x00 } } }
+/*
+ * All-routers multicast address is the link-local scope address to reach all
+ * routers.
+ */
+#define ALL_ROUTERS_MULT_ADDR { { { 0xFF, 0x02, 0x00, 0x00, \
+				  0x00, 0x00, 0x00, 0x00, \
+				  0x00, 0x00, 0x00, 0x00, \
+				  0x00, 0x00, 0x00, 0x02 } } }
 
 #define IPV6_LINK_LOCAL_PREFIX	0xfe80
+#define IPV6_LINK_LOCAL_MASK	0xffb0 /* The first 10-bit of address mask. */
 
 /* hop limit for neighbour discovery packets */
 #define IPV6_NDISC_HOPLIMIT             255
@@ -166,6 +175,37 @@
 #define icmp6_rt_lifetime	icmp6_dataun.u_nd_ra.rt_lifetime
 } __packed;
 
+/*
+ * struct icmp6_ra_prefix_info - Prefix Information option of the ICMPv6 message
+ * The Prefix Information option provides hosts with on-link prefixes and
+ * prefixes for Address Autoconfiguration. Refer to RFC 4861 for more info.
+ */
+struct icmp6_ra_prefix_info {
+	u8	type;		/* Type is 3 for Prefix Information. */
+	u8	len;		/* Len is 4 for Prefix Information. */
+	/* The number of leading bits in the Prefix that are valid. */
+	u8	prefix_len;
+	u8	reserved1:6,	/* MUST be ignored by the receiver. */
+		aac:1,		/* autonomous address-configuration flag */
+	/* Indicates that this prefix can be used for on-link determination. */
+		on_link:1;
+	/*
+	 * The length of time in seconds that the prefix is valid for the
+	 * purpose of on-link determination.
+	 */
+	__be32	valid_lifetime;
+	/* The length of time addresses remain preferred. */
+	__be32	preferred_lifetime;
+	__be32	reserved2;	/* MUST be ignored by the receiver. */
+	/*
+	 * Prefix is an IP address or a prefix of an IP address. The Prefix
+	 * Length field contains the number of valid leading bits in the prefix.
+	 * The bits in the prefix after the prefix length are reserved and MUST
+	 * be initialized to zero by the sender and ignored by the receiver.
+	 */
+	struct in6_addr prefix;
+};
+
 extern struct in6_addr const net_null_addr_ip6;	/* NULL IPv6 address */
 extern struct in6_addr net_gateway6;	/* Our gateways IPv6 address */
 extern struct in6_addr net_ip6;	/* Our IPv6 addr (0 = unknown) */