iwd.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Andrew Zaborowski <andrew.zaborowski@intel.com>
To: iwd@lists.01.org
Subject: [PATCH 8/9] netconfig: FILS IP assigment API
Date: Mon, 23 Aug 2021 16:14:29 +0200	[thread overview]
Message-ID: <20210823141430.223543-8-andrew.zaborowski@intel.com> (raw)
In-Reply-To: <20210823141430.223543-1-andrew.zaborowski@intel.com>

[-- Attachment #1: Type: text/plain, Size: 10180 bytes --]

Add two methods that will allow station to implement FILS IP Address
Assigment, one method to decide whether to send the request during
association, and fill in the values to be used in the request IE, and
another to handle the response IE values received from the server and
apply them.  The netconfig->rtm_protocol value used when the address is
assigned this way remains RTPROT_DHCP because from the user's point of
view this is automatic IP assigment by the server, a replacement for
DHCP.
---
 src/netconfig.c | 168 ++++++++++++++++++++++++++++++++++++++++++++----
 src/netconfig.h |   6 ++
 2 files changed, 160 insertions(+), 14 deletions(-)

diff --git a/src/netconfig.c b/src/netconfig.c
index d6113c0c..803a8707 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -47,6 +47,8 @@
 #include "src/common.h"
 #include "src/network.h"
 #include "src/resolve.h"
+#include "src/util.h"
+#include "src/ie.h"
 #include "src/netconfig.h"
 
 struct netconfig {
@@ -58,6 +60,7 @@ struct netconfig {
 	struct l_rtnl_address *v4_address;
 	char **dns4_overrides;
 	char **dns6_overrides;
+	struct ie_fils_ip_addr_response_info *fils_override;
 
 	const struct l_settings *active_settings;
 
@@ -163,6 +166,36 @@ static struct netconfig *netconfig_find(uint32_t ifindex)
 			dest[index++] = *p;			\
 	} while (0)						\
 
+static inline char *netconfig_ipv4_to_string(uint32_t addr)
+{
+	struct in_addr in_addr = { .s_addr = addr };
+	char *addr_str = l_malloc(INET_ADDRSTRLEN);
+
+	if (L_WARN_ON(unlikely(!inet_ntop(AF_INET, &in_addr, addr_str,
+						INET_ADDRSTRLEN)))) {
+		l_free(addr_str);
+		return NULL;
+	}
+
+	return addr_str;
+}
+
+static inline char *netconfig_ipv6_to_string(const uint8_t *addr)
+{
+	struct in6_addr in6_addr;
+	char *addr_str = l_malloc(INET6_ADDRSTRLEN);
+
+	memcpy(in6_addr.__in6_u.__u6_addr8, addr, 16);
+
+	if (L_WARN_ON(unlikely(!inet_ntop(AF_INET6, &in6_addr, addr_str,
+						INET6_ADDRSTRLEN)))) {
+		l_free(addr_str);
+		return NULL;
+	}
+
+	return addr_str;
+}
+
 static int netconfig_set_dns(struct netconfig *netconfig)
 {
 	char **dns6_list = NULL;
@@ -172,19 +205,30 @@ static int netconfig_set_dns(struct netconfig *netconfig)
 
 	if (!netconfig->dns4_overrides &&
 			netconfig->rtm_protocol == RTPROT_DHCP) {
-		const struct l_dhcp_lease *lease =
-			l_dhcp_client_get_lease(netconfig->dhcp_client);
-
-		if (lease)
+		const struct l_dhcp_lease *lease;
+
+		if (netconfig->fils_override &&
+				netconfig->fils_override->ipv4_dns) {
+			dns4_list = l_new(char *, 2);
+			dns4_list[0] = netconfig_ipv4_to_string(
+					netconfig->fils_override->ipv4_dns);
+		} else if ((lease = l_dhcp_client_get_lease(
+						netconfig->dhcp_client)))
 			dns4_list = l_dhcp_lease_get_dns(lease);
 	}
 
 	if (!netconfig->dns6_overrides &&
 			netconfig->rtm_v6_protocol == RTPROT_DHCP) {
-		const struct l_dhcp6_lease *lease =
-			l_dhcp6_client_get_lease(netconfig->dhcp6_client);
-
-		if (lease)
+		const struct l_dhcp6_lease *lease;
+
+		if (netconfig->fils_override &&
+				!l_memeqzero(netconfig->fils_override->ipv6_dns,
+						16)) {
+			dns6_list = l_new(char *, 2);
+			dns6_list[0] = netconfig_ipv6_to_string(
+					netconfig->fils_override->ipv6_dns);
+		} else if ((lease = l_dhcp6_client_get_lease(
+						netconfig->dhcp6_client)))
 			dns6_list = l_dhcp6_lease_get_dns(lease);
 	}
 
@@ -337,6 +381,11 @@ static char *netconfig_ipv4_get_gateway(struct netconfig *netconfig)
 		return gateway;
 
 	case RTPROT_DHCP:
+		if (netconfig->fils_override &&
+				netconfig->fils_override->ipv4_gateway)
+			return netconfig_ipv4_to_string(
+					netconfig->fils_override->ipv4_gateway);
+
 		lease = l_dhcp_client_get_lease(netconfig->dhcp_client);
 		if (!lease)
 			return NULL;
@@ -393,7 +442,13 @@ static struct l_rtnl_route *netconfig_get_static6_gateway(
 
 	gateway = l_settings_get_string(netconfig->active_settings,
 						"IPv6", "Gateway");
-	if (!gateway)
+	if (!gateway && netconfig->rtm_v6_protocol == RTPROT_DHCP &&
+			netconfig->fils_override &&
+			!l_memeqzero(netconfig->fils_override->ipv6_gateway,
+					16))
+		gateway = netconfig_ipv6_to_string(
+					netconfig->fils_override->ipv6_gateway);
+	else if (!gateway)
 		return NULL;
 
 	ret = l_rtnl_route_new_gateway(gateway);
@@ -523,7 +578,9 @@ static void netconfig_ifaddr_ipv6_added(struct netconfig *netconfig,
 	l_debug("ifindex %u: ifaddr %s/%u", netconfig->ifindex,
 			ip, ifa->ifa_prefixlen);
 
-	if (netconfig->rtm_v6_protocol != RTPROT_DHCP)
+	if (netconfig->rtm_v6_protocol != RTPROT_DHCP ||
+			(netconfig->fils_override &&
+			 !l_memeqzero(netconfig->fils_override->ipv6_addr, 16)))
 		return;
 
 	inet_pton(AF_INET6, ip, &in6);
@@ -901,7 +958,35 @@ static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data)
 
 static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig)
 {
-	if (netconfig->rtm_protocol == RTPROT_STATIC) {
+	bool set_address = (netconfig->rtm_protocol == RTPROT_STATIC);
+
+	if (netconfig->rtm_protocol == RTPROT_DHCP &&
+			netconfig->fils_override &&
+			netconfig->fils_override->ipv4_addr) {
+		L_AUTO_FREE_VAR(char *, addr_str) = netconfig_ipv4_to_string(
+					netconfig->fils_override->ipv4_addr);
+		uint8_t prefix_len = netconfig->fils_override->ipv4_prefix_len;
+
+		if (unlikely(!addr_str))
+			return false;
+
+		if (L_WARN_ON(unlikely(!(netconfig->v4_address =
+						l_rtnl_address_new(addr_str,
+								prefix_len)))))
+			return false;
+
+		l_rtnl_address_set_noprefixroute(netconfig->v4_address, true);
+		set_address = true;
+
+		/*
+		 * TODO: If netconfig->fils_override->ipv4_lifetime is set,
+		 * start a timeout to renew the address using FILS IP Address
+		 * Assignment or perhaps just start the DHCP client at that
+		 * time.
+		 */
+	}
+
+	if (set_address) {
 		char ip[INET6_ADDRSTRLEN];
 
 		if (L_WARN_ON(!netconfig->v4_address ||
@@ -944,6 +1029,7 @@ static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig)
 static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
 {
 	struct netdev *netdev = netdev_find(netconfig->ifindex);
+	struct l_rtnl_address *address = NULL;
 
 	if (netconfig->rtm_v6_protocol == RTPROT_UNSPEC) {
 		l_debug("IPV6 configuration disabled");
@@ -952,10 +1038,33 @@ static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
 
 	sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "0");
 
-	if (netconfig->rtm_v6_protocol == RTPROT_STATIC) {
-		struct l_rtnl_address *address =
-			netconfig_get_static6_address(netconfig);
+	if (netconfig->rtm_v6_protocol == RTPROT_STATIC)
+		address = netconfig_get_static6_address(netconfig);
+	else if (netconfig->rtm_v6_protocol == RTPROT_DHCP &&
+			netconfig->fils_override &&
+			!l_memeqzero(netconfig->fils_override->ipv6_addr, 16)) {
+		uint8_t prefix_len = netconfig->fils_override->ipv6_prefix_len;
+		L_AUTO_FREE_VAR(char *, addr_str) = netconfig_ipv6_to_string(
+					netconfig->fils_override->ipv6_addr);
+
+		if (unlikely(!addr_str))
+			return false;
+
+		if (L_WARN_ON(unlikely(!(address = l_rtnl_address_new(addr_str,
+								prefix_len)))))
+			return false;
+
+		l_rtnl_address_set_noprefixroute(address, true);
+
+		/*
+		 * TODO: If netconfig->fils_override->ipv6_lifetime is set,
+		 * start a timeout to renew the address using FILS IP Address
+		 * Assignment or perhaps just start the DHCP client at that
+		 * time.
+		 */
+	}
 
+	if (address) {
 		L_WARN_ON(!(netconfig->addr6_add_cmd_id =
 			l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, address,
 					netconfig_ipv6_ifaddr_add_cmd_cb,
@@ -1167,6 +1276,8 @@ bool netconfig_reset(struct netconfig *netconfig)
 						"disable_ipv6", "1");
 	}
 
+	l_free(l_steal_ptr(netconfig->fils_override));
+
 	return true;
 }
 
@@ -1184,6 +1295,35 @@ char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig)
 	return l_dhcp_lease_get_server_id(lease);
 }
 
+bool netconfig_get_fils_ip_req(struct netconfig *netconfig,
+				struct ie_fils_ip_addr_request_info *info)
+{
+	/*
+	 * Fill in the fields used for building the FILS IP Address Assigment
+	 * IE during connection if we're configured to do automatic network
+	 * configuration (usually DHCP).  If we're configured with static
+	 * values return false to mean the IE should not be sent.
+	 */
+	if (netconfig->rtm_protocol != RTPROT_DHCP &&
+			netconfig->rtm_v6_protocol != RTPROT_DHCP)
+		return false;
+
+	memset(info, 0, sizeof(*info));
+	info->ipv4 = (netconfig->rtm_protocol == RTPROT_DHCP);
+	info->ipv6 = (netconfig->rtm_v6_protocol == RTPROT_DHCP);
+	info->dns = (info->ipv4 && !netconfig->dns4_overrides) ||
+		(info->ipv6 && !netconfig->dns6_overrides);
+
+	return true;
+}
+
+void netconfig_handle_fils_ip_resp(struct netconfig *netconfig,
+			const struct ie_fils_ip_addr_response_info *info)
+{
+	l_free(netconfig->fils_override);
+	netconfig->fils_override = l_memdup(info, sizeof(*info));
+}
+
 struct netconfig *netconfig_new(uint32_t ifindex)
 {
 	struct netdev *netdev = netdev_find(ifindex);
diff --git a/src/netconfig.h b/src/netconfig.h
index 73e4df8b..fa46c7c8 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -21,6 +21,8 @@
  */
 
 struct netconfig;
+struct ie_fils_ip_addr_request_info;
+struct ie_fils_ip_addr_response_info;
 
 enum netconfig_event {
 	NETCONFIG_EVENT_CONNECTED,
@@ -38,6 +40,10 @@ bool netconfig_configure(struct netconfig *netconfig,
 bool netconfig_reconfigure(struct netconfig *netconfig);
 bool netconfig_reset(struct netconfig *netconfig);
 char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig);
+bool netconfig_get_fils_ip_req(struct netconfig *netconfig,
+				struct ie_fils_ip_addr_request_info *info);
+void netconfig_handle_fils_ip_resp(struct netconfig *netconfig,
+			const struct ie_fils_ip_addr_response_info *info);
 
 struct netconfig *netconfig_new(uint32_t ifindex);
 void netconfig_destroy(struct netconfig *netconfig);
-- 
2.30.2

  parent reply	other threads:[~2021-08-23 14:14 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-23 14:14 [PATCH 1/9] handshake: Add HANDSHAKE_EVENT_P2P_IP_REQUEST Andrew Zaborowski
2021-08-23 14:14 ` [PATCH 2/9] ap: Implement P2P GO-side 4-way handshake IP Allocation Andrew Zaborowski
2021-08-23 14:14 ` [PATCH 3/9] autotests: Test GO-side IP Allocation in testP2P Andrew Zaborowski
2021-08-23 14:14 ` [PATCH 4/9] ap: Expire client's leases on disconnect Andrew Zaborowski
2021-08-23 14:14 ` [PATCH 5/9] ie: Add FILS IP Address Assignment parsers and builders Andrew Zaborowski
2021-08-25 13:47   ` Denis Kenzior
2021-08-25 21:34     ` Andrew Zaborowski
2021-08-23 14:14 ` [PATCH 6/9] ap: Support FILS IP Address Assignment IE Andrew Zaborowski
2021-08-23 14:14 ` [PATCH 7/9] netconfig: Move loading settings to new method, refactor Andrew Zaborowski
2021-08-25 13:50   ` Denis Kenzior
2021-08-25 22:17     ` Andrew Zaborowski
2021-08-25 22:37       ` Denis Kenzior
2021-08-25 22:56         ` Andrew Zaborowski
2021-08-23 14:14 ` Andrew Zaborowski [this message]
2021-08-23 14:14 ` [PATCH 9/9] station, netdev: Enable FILS IP Address Assignment Andrew Zaborowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210823141430.223543-8-andrew.zaborowski@intel.com \
    --to=andrew.zaborowski@intel.com \
    --cc=iwd@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).