All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc
@ 2021-06-30 19:06 Andrew Zaborowski
  2021-06-30 19:06 ` [PATCH 2/3] netconfig: Add network configuration properties on Station and P2P Andrew Zaborowski
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Andrew Zaborowski @ 2021-06-30 19:06 UTC (permalink / raw)
  To: iwd

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

---
 doc/network-configuration-api.txt | 52 +++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 doc/network-configuration-api.txt

diff --git a/doc/network-configuration-api.txt b/doc/network-configuration-api.txt
new file mode 100644
index 00000000..5c302a37
--- /dev/null
+++ b/doc/network-configuration-api.txt
@@ -0,0 +1,52 @@
+Network Configuration hierarchy
+===============================
+
+Service		net.connman.iwd
+Interface	net.connman.iwd.NetworkConfiguration [Experimental]
+Object path	/net/connman/iwd/{phy0,phy1,...}/{1,2,...}/{ipv4,ipv6}
+Object path	/net/connman/iwd/{phy0,phy1,...}/p2p_peers/{aa_bb_cc_dd_ee_ff}
+
+Properties	object Device [readonly]
+
+			The object path of the station, access point or P2P
+			device that this network configuration is active on.
+
+			In station mode, when network configuration is
+			enabled there may be one or two objects using this
+			interface and active on the same device: two if both
+			IPv4 and IPv6 addresses have been configured.
+
+			In P2P mode, this interface always refers to IPv4
+			network configuration.
+
+		string Method [readonly]
+
+			Indicates whether the local address was set
+			statically (value "static") or obtained automatically
+			such as through DHCP (value "auto").  Even when the
+			address was obtained from the remote end some
+			configuration bits, such as DNS addresses, may have
+			been overridden locally.
+
+		string Address [readonly]
+
+			Holds the local IP address.
+
+		byte PrefixLength [readonly]
+
+			Holds the prefix-length of the local subnet.  For
+			IPv4 this maps to the netmask.
+
+		string Gateway [readonly, optional]
+
+			Holds the gateway address for the IPv4 subnet if one
+			exists.
+
+		array(string) DomainNameServers [readonly, optional]
+
+			Holds the list of domain name servers configured if
+			any.
+
+		string DomainNames [readonly, optional]
+
+			Holds the network's local domain names if any exist.
-- 
2.30.2

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

* [PATCH 2/3] netconfig: Add network configuration properties on Station and P2P
  2021-06-30 19:06 [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Andrew Zaborowski
@ 2021-06-30 19:06 ` Andrew Zaborowski
  2021-06-30 19:06 ` [PATCH 3/3] netconfig: Reserve INET_ADDRSTRLEN chars for an IPv4 string Andrew Zaborowski
  2021-07-02 14:49 ` [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Denis Kenzior
  2 siblings, 0 replies; 5+ messages in thread
From: Andrew Zaborowski @ 2021-06-30 19:06 UTC (permalink / raw)
  To: iwd

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

Add NetworkConfiguration D-Bus interfaces under the station and P2P
objects that expose current IP configurations.  Access Point and P2P-GO
are not handled yet, and some of the IP config properties may not
automatically generate PropertiesChanged on DHCP lease renewals but
their values are unlikely to change.
---
 src/dbus.h      |   1 +
 src/netconfig.c | 531 +++++++++++++++++++++++++++++++++++++++++++-----
 src/netconfig.h |   3 +-
 src/p2p.c       |   5 +-
 src/station.c   |  17 +-
 5 files changed, 496 insertions(+), 61 deletions(-)

diff --git a/src/dbus.h b/src/dbus.h
index b3896108..d5c58af2 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -42,6 +42,7 @@
 #define IWD_P2P_WFD_INTERFACE "net.connman.iwd.p2p.Display"
 #define IWD_STATION_DIAGNOSTIC_INTERFACE "net.connman.iwd.StationDiagnostic"
 #define IWD_AP_DIAGNOSTIC_INTERFACE "net.connman.iwd.AccessPointDiagnostic"
+#define IWD_NETCONFIG_INTERFACE "net.connman.iwd.NetworkConfiguration"
 
 #define IWD_BASE_PATH "/net/connman/iwd"
 #define IWD_AGENT_MANAGER_PATH IWD_BASE_PATH
diff --git a/src/netconfig.c b/src/netconfig.c
index 005316cd..20c39f0f 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -47,17 +47,24 @@
 #include "src/common.h"
 #include "src/network.h"
 #include "src/resolve.h"
+#include "src/dbus.h"
 #include "src/netconfig.h"
 
 struct netconfig {
 	uint32_t ifindex;
+	char *device_path;
+	char *ipv4_path;
+	char *ipv6_path;
 	struct l_dhcp_client *dhcp_client;
 	struct l_dhcp6_client *dhcp6_client;
 	uint8_t rtm_protocol;
 	uint8_t rtm_v6_protocol;
 	struct l_rtnl_address *v4_address;
+	struct l_rtnl_address *v6_address;
 	char **dns4_overrides;
 	char **dns6_overrides;
+	char *v4_gateway_str;
+	char *v6_gateway_str;
 
 	const struct l_settings *active_settings;
 
@@ -129,6 +136,9 @@ static void netconfig_free(void *data)
 	l_dhcp_client_destroy(netconfig->dhcp_client);
 	l_dhcp6_client_destroy(netconfig->dhcp6_client);
 
+	l_free(netconfig->device_path);
+	l_free(netconfig->ipv4_path);
+	l_free(netconfig->ipv6_path);
 	l_free(netconfig);
 }
 
@@ -149,6 +159,38 @@ static struct netconfig *netconfig_find(uint32_t ifindex)
 	return NULL;
 }
 
+static char **netconfig_get_dns_list(struct netconfig *netconfig, int af)
+{
+	if (af == AF_INET) {
+		const struct l_dhcp_lease *lease;
+
+		if (netconfig->dns4_overrides)
+			return l_strv_copy(netconfig->dns4_overrides);
+
+		if (netconfig->rtm_protocol != RTPROT_DHCP)
+			return NULL;
+
+		if (!(lease = l_dhcp_client_get_lease(netconfig->dhcp_client)))
+			return NULL;
+
+		return l_dhcp_lease_get_dns(lease);
+	} else {
+		const struct l_dhcp6_lease *lease;
+
+		if (netconfig->dns6_overrides)
+			return l_strv_copy(netconfig->dns6_overrides);
+
+		if (netconfig->rtm_v6_protocol != RTPROT_DHCP)
+			return NULL;
+
+		if (!(lease = l_dhcp6_client_get_lease(
+						netconfig->dhcp6_client)))
+			return NULL;
+
+		return l_dhcp6_lease_get_dns(lease);
+	}
+}
+
 #define APPEND_STRDUPV(dest, index, src)			\
 	do {							\
 		char **p;					\
@@ -165,46 +207,25 @@ static struct netconfig *netconfig_find(uint32_t ifindex)
 
 static int netconfig_set_dns(struct netconfig *netconfig)
 {
-	char **dns6_list = NULL;
-	char **dns4_list = NULL;
-	unsigned int n_entries = 0;
+	char **dns4_list = netconfig_get_dns_list(netconfig, AF_INET);
+	char **dns6_list = netconfig_get_dns_list(netconfig, AF_INET6);
+	unsigned int n_entries4 = l_strv_length(dns4_list);
+	unsigned int n_entries6 = l_strv_length(dns6_list);
 	char **dns_list;
 
-	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)
-			dns4_list = l_dhcp_lease_get_dns(lease);
-	}
+	if (!dns4_list && !dns6_list)
+		return 0;
 
-	if (!netconfig->dns6_overrides &&
-			netconfig->rtm_v6_protocol == RTPROT_DHCP) {
-		const struct l_dhcp6_lease *lease =
-			l_dhcp6_client_get_lease(netconfig->dhcp6_client);
+	dns_list = l_realloc(dns4_list,
+				sizeof(char *) * (n_entries4 + n_entries6 + 1));
 
-		if (lease)
-			dns6_list = l_dhcp6_lease_get_dns(lease);
+	if (dns6_list) {
+		memcpy(dns_list + n_entries4, dns6_list,
+			sizeof(char *) * (n_entries6 + 1));
+		/* Contents now belong to dns_list, so no l_strfreev */
+		l_free(dns6_list);
 	}
 
-	n_entries += l_strv_length(netconfig->dns4_overrides);
-	n_entries += l_strv_length(netconfig->dns6_overrides);
-	n_entries += l_strv_length(dns4_list);
-	n_entries += l_strv_length(dns6_list);
-
-	dns_list = l_new(char *, n_entries + 1);
-	n_entries = 0;
-
-	APPEND_STRDUPV(dns_list, n_entries, netconfig->dns4_overrides);
-	APPENDV(dns_list, n_entries, dns4_list);
-	/* Contents now belong to ret, so not l_strfreev */
-	l_free(dns4_list);
-	APPEND_STRDUPV(dns_list, n_entries, netconfig->dns6_overrides);
-	APPENDV(dns_list, n_entries, dns6_list);
-	/* Contents now belong to ret, so not l_strfreev */
-	l_free(dns6_list);
-
 	resolve_set_dns(netconfig->resolve, dns_list);
 	l_strv_free(dns_list);
 	return 0;
@@ -385,7 +406,8 @@ no_prefix_len:
 }
 
 static struct l_rtnl_route *netconfig_get_static6_gateway(
-						struct netconfig *netconfig)
+						struct netconfig *netconfig,
+						char **out_str)
 {
 	L_AUTO_FREE_VAR(char *, gateway);
 	struct l_rtnl_route *ret;
@@ -405,6 +427,7 @@ static struct l_rtnl_route *netconfig_get_static6_gateway(
 
 	l_rtnl_route_set_priority(ret, ROUTE_PRIORITY_OFFSET);
 	l_rtnl_route_set_protocol(ret, RTPROT_STATIC);
+	*out_str = l_steal_ptr(gateway);
 
 	return ret;
 }
@@ -600,6 +623,47 @@ static void netconfig_route_generic_cb(int error, uint16_t type,
 	}
 }
 
+static void netconfig_connected(struct netconfig *netconfig)
+{
+	struct l_dbus *dbus = dbus_get_bus();
+
+	if (netconfig->notify) {
+		netconfig->notify(NETCONFIG_EVENT_CONNECTED,
+					netconfig->user_data);
+		netconfig->notify = NULL;
+	}
+
+	if (netconfig->ipv4_path &&
+			!l_dbus_object_add_interface(dbus, netconfig->ipv4_path,
+							IWD_NETCONFIG_INTERFACE,
+							netconfig))
+		l_info("Unable to add %s to %s",
+			IWD_NETCONFIG_INTERFACE, netconfig->ipv4_path);
+
+	if (netconfig->ipv4_path &&
+			!l_dbus_object_add_interface(dbus, netconfig->ipv4_path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						netconfig))
+		/* Properties may already exist on the object, not an error */
+		l_info("Unable to add %s to %s",
+			L_DBUS_INTERFACE_PROPERTIES, netconfig->ipv4_path);
+
+	if (netconfig->ipv6_path &&
+			!l_dbus_object_add_interface(dbus, netconfig->ipv6_path,
+							IWD_NETCONFIG_INTERFACE,
+							netconfig))
+		l_info("Unable to add %s to %s",
+			IWD_NETCONFIG_INTERFACE, netconfig->ipv6_path);
+
+	if (netconfig->ipv6_path &&
+			!l_dbus_object_add_interface(dbus, netconfig->ipv6_path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						netconfig))
+		/* Properties may already exist on the object, not an error */
+		l_info("Unable to add %s to %s",
+			L_DBUS_INTERFACE_PROPERTIES, netconfig->ipv6_path);
+}
+
 static void netconfig_route_add_cmd_cb(int error, uint16_t type,
 						const void *data, uint32_t len,
 						void *user_data)
@@ -614,11 +678,7 @@ static void netconfig_route_add_cmd_cb(int error, uint16_t type,
 		return;
 	}
 
-	if (!netconfig->notify)
-		return;
-
-	netconfig->notify(NETCONFIG_EVENT_CONNECTED, netconfig->user_data);
-	netconfig->notify = NULL;
+	netconfig_connected(netconfig);
 }
 
 static bool netconfig_ipv4_routes_install(struct netconfig *netconfig)
@@ -656,12 +716,7 @@ static bool netconfig_ipv4_routes_install(struct netconfig *netconfig)
 				netconfig->rtm_protocol == RTPROT_STATIC ?
 				"setting file" : "DHCPv4 lease");
 
-		if (netconfig->notify) {
-			netconfig->notify(NETCONFIG_EVENT_CONNECTED,
-						netconfig->user_data);
-			netconfig->notify = NULL;
-		}
-
+		netconfig_connected(netconfig);
 		return true;
 	}
 
@@ -719,7 +774,8 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,
 		return;
 	}
 
-	gateway = netconfig_get_static6_gateway(netconfig);
+	gateway = netconfig_get_static6_gateway(netconfig,
+						&netconfig->v6_gateway_str);
 	if (gateway) {
 		L_WARN_ON(!l_rtnl_route_add(rtnl, netconfig->ifindex,
 						gateway,
@@ -752,11 +808,44 @@ static void netconfig_ifaddr_del_cmd_cb(int error, uint16_t type,
 				"Error %d: %s", error, strerror(-error));
 }
 
+static bool netconfig_address_cmp_address(const struct l_rtnl_address *a,
+						const struct l_rtnl_address *b)
+{
+	char str_a[INET6_ADDRSTRLEN];
+	char str_b[INET6_ADDRSTRLEN];
+
+	if (a == b)
+		return true;
+
+	if (!a || !b)
+		return false;
+
+	if (!l_rtnl_address_get_address(a, str_a) ||
+			!l_rtnl_address_get_address(b, str_b))
+		return false;
+
+	return !strcmp(str_a, str_b);
+}
+
+static bool netconfig_address_cmp_prefix_len(const struct l_rtnl_address *a,
+						const struct l_rtnl_address *b)
+{
+	if (a == b)
+		return true;
+
+	if (!a || !b)
+		return false;
+
+	return l_rtnl_address_get_prefix_length(a) ==
+		l_rtnl_address_get_prefix_length(b);
+}
+
 static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
 						enum l_dhcp_client_event event,
 						void *userdata)
 {
 	struct netconfig *netconfig = userdata;
+	struct l_dbus *dbus = dbus_get_bus();
 
 	l_debug("DHCPv4 event %d", event);
 
@@ -766,10 +855,45 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
 					netconfig->v4_address,
 					netconfig_ifaddr_del_cmd_cb,
 					netconfig, NULL));
-		l_rtnl_address_free(netconfig->v4_address);
 		/* Fall through. */
 	case L_DHCP_CLIENT_EVENT_LEASE_OBTAINED:
-		netconfig->v4_address = netconfig_get_dhcp4_address(netconfig);
+	{
+		char *gateway_str;
+		struct l_rtnl_address *address;
+
+		gateway_str = netconfig_ipv4_get_gateway(netconfig);
+		if (l_streq0(netconfig->v4_gateway_str, gateway_str))
+			l_free(gateway_str);
+		else {
+			l_free(netconfig->v4_gateway_str);
+			netconfig->v4_gateway_str = gateway_str;
+
+			if (netconfig->ipv4_path)
+				l_dbus_property_changed(dbus,
+							netconfig->ipv4_path,
+							IWD_NETCONFIG_INTERFACE,
+							"Gateway");
+		}
+
+		address = netconfig_get_dhcp4_address(netconfig);
+
+		if (netconfig->ipv4_path && !netconfig_address_cmp_prefix_len(
+							netconfig->v4_address,
+							address))
+			l_dbus_property_changed(dbus, netconfig->ipv4_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Netmask");
+
+		if (netconfig->ipv4_path && netconfig_address_cmp_address(
+							netconfig->v4_address,
+							address))
+			l_dbus_property_changed(dbus, netconfig->ipv4_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Address");
+
+		l_rtnl_address_free(netconfig->v4_address);
+		netconfig->v4_address = address;
+
 		if (!netconfig->v4_address) {
 			l_error("netconfig: Failed to obtain IP addresses from "
 							"DHCPv4 lease.");
@@ -782,6 +906,7 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
 					netconfig_ipv4_ifaddr_add_cmd_cb,
 					netconfig, NULL)));
 		break;
+	}
 	case L_DHCP_CLIENT_EVENT_LEASE_RENEWED:
 		break;
 	case L_DHCP_CLIENT_EVENT_LEASE_EXPIRED:
@@ -792,6 +917,25 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
 		l_rtnl_address_free(netconfig->v4_address);
 		netconfig->v4_address = NULL;
 
+		if (netconfig->ipv4_path) {
+			l_dbus_property_changed(dbus, netconfig->ipv4_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Address");
+			l_dbus_property_changed(dbus, netconfig->ipv4_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Netmask");
+		}
+
+		if (netconfig->v4_gateway_str) {
+			if (netconfig->ipv4_path)
+				l_dbus_property_changed(dbus,
+							netconfig->ipv4_path,
+							IWD_NETCONFIG_INTERFACE,
+							"Gateway");
+
+			l_free(l_steal_ptr(netconfig->v4_gateway_str));
+		}
+
 		/* Fall through. */
 	case L_DHCP_CLIENT_EVENT_NO_LEASE:
 		/*
@@ -814,18 +958,85 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
 						void *userdata)
 {
 	struct netconfig *netconfig = userdata;
+	struct l_dbus *dbus = dbus_get_bus();
 
 	switch (event) {
 	case L_DHCP6_CLIENT_EVENT_IP_CHANGED:
 	case L_DHCP6_CLIENT_EVENT_LEASE_OBTAINED:
 	case L_DHCP6_CLIENT_EVENT_LEASE_RENEWED:
+	{
+		__auto_type lease =
+			l_dhcp6_client_get_lease(netconfig->dhcp6_client);
+		L_AUTO_FREE_VAR(char *, addr_str) =
+			l_dhcp6_lease_get_address(lease);
+		struct l_rtnl_address *address;
+		__auto_type icmp6 =
+			l_dhcp6_client_get_icmp6(netconfig->dhcp6_client);
+		__auto_type router = l_icmp6_client_get_router(icmp6);
+		char *gateway_str = l_icmp6_router_get_address(router);
+
+		if (l_streq0(netconfig->v6_gateway_str, gateway_str))
+			l_free(gateway_str);
+		else {
+			l_free(netconfig->v6_gateway_str);
+			netconfig->v6_gateway_str = gateway_str;
+
+			if (netconfig->ipv6_path)
+				l_dbus_property_changed(dbus,
+							netconfig->ipv6_path,
+							IWD_NETCONFIG_INTERFACE,
+							"Gateway");
+		}
+
+		address = l_rtnl_address_new(addr_str,
+					l_dhcp6_lease_get_prefix_length(lease));
+
+		if (netconfig->ipv6_path && !netconfig_address_cmp_prefix_len(
+							netconfig->v6_address,
+							address))
+			l_dbus_property_changed(dbus, netconfig->ipv6_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Netmask");
+
+		if (netconfig->ipv4_path && netconfig_address_cmp_address(
+							netconfig->v6_address,
+							address))
+			l_dbus_property_changed(dbus, netconfig->ipv6_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Address");
+
+		l_rtnl_address_free(netconfig->v6_address);
+		netconfig->v4_address = address;
+
 		netconfig_set_dns(netconfig);
 		netconfig_set_domains(netconfig);
 		break;
+	}
 	case L_DHCP6_CLIENT_EVENT_LEASE_EXPIRED:
 		l_debug("Lease for interface %u expired", netconfig->ifindex);
 		netconfig_set_dns(netconfig);
 		netconfig_set_domains(netconfig);
+		l_rtnl_address_free(netconfig->v6_address);
+		netconfig->v6_address = NULL;
+
+		if (netconfig->ipv6_path) {
+			l_dbus_property_changed(dbus, netconfig->ipv6_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Address");
+			l_dbus_property_changed(dbus, netconfig->ipv6_path,
+						IWD_NETCONFIG_INTERFACE,
+						"Netmask");
+		}
+
+		if (netconfig->v6_gateway_str) {
+			if (netconfig->ipv6_path)
+				l_dbus_property_changed(dbus,
+							netconfig->ipv6_path,
+							IWD_NETCONFIG_INTERFACE,
+							"Gateway");
+
+			l_free(l_steal_ptr(netconfig->v6_gateway_str));
+		}
 
 		/* Fall through */
 	case L_DHCP6_CLIENT_EVENT_NO_LEASE:
@@ -862,6 +1073,9 @@ static void netconfig_reset_v4(struct netconfig *netconfig)
 
 		l_acd_destroy(netconfig->acd);
 		netconfig->acd = NULL;
+
+		l_free(netconfig->v4_gateway_str);
+		netconfig->v4_gateway_str = NULL;
 	}
 }
 
@@ -941,7 +1155,6 @@ static void netconfig_ipv4_select_and_install(struct netconfig *netconfig)
 static void netconfig_ipv6_select_and_install(struct netconfig *netconfig)
 {
 	struct netdev *netdev = netdev_find(netconfig->ifindex);
-	struct l_rtnl_address *address;
 	bool enabled;
 
 	if (!l_settings_get_bool(netconfig->active_settings, "IPv6",
@@ -955,14 +1168,14 @@ static void netconfig_ipv6_select_and_install(struct netconfig *netconfig)
 
 	sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "0");
 
-	address = netconfig_get_static6_address(netconfig);
-	if (address) {
+	netconfig->v6_address = netconfig_get_static6_address(netconfig);
+	if (netconfig->v6_address) {
 		netconfig->rtm_v6_protocol = RTPROT_STATIC;
 		L_WARN_ON(!(netconfig->addr6_add_cmd_id =
-			l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, address,
+			l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
+					netconfig->v6_address,
 					netconfig_ipv6_ifaddr_add_cmd_cb,
 					netconfig, NULL)));
-		l_rtnl_address_free(address);
 		return;
 	}
 
@@ -1088,6 +1301,7 @@ bool netconfig_reconfigure(struct netconfig *netconfig)
 bool netconfig_reset(struct netconfig *netconfig)
 {
 	struct netdev *netdev = netdev_find(netconfig->ifindex);
+	struct l_dbus *dbus = dbus_get_bus();
 
 	if (netconfig->route4_add_gateway_cmd_id) {
 		l_netlink_cancel(rtnl, netconfig->route4_add_gateway_cmd_id);
@@ -1110,6 +1324,9 @@ bool netconfig_reset(struct netconfig *netconfig)
 	netconfig_reset_v4(netconfig);
 
 	if (netconfig->rtm_v6_protocol) {
+		l_rtnl_address_free(netconfig->v6_address);
+		netconfig->v6_address = NULL;
+
 		l_strfreev(netconfig->dns6_overrides);
 		netconfig->dns6_overrides = NULL;
 
@@ -1118,8 +1335,17 @@ bool netconfig_reset(struct netconfig *netconfig)
 
 		sysfs_write_ipv6_setting(netdev_get_name(netdev),
 						"disable_ipv6", "1");
+
+		l_free(netconfig->v6_gateway_str);
+		netconfig->v6_gateway_str = NULL;
 	}
 
+	if (netconfig->ipv4_path)
+		l_dbus_unregister_object(dbus, netconfig->ipv4_path);
+
+	if (netconfig->ipv6_path)
+		l_dbus_unregister_object(dbus, netconfig->ipv6_path);
+
 	return true;
 }
 
@@ -1137,7 +1363,8 @@ char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig)
 	return l_dhcp_lease_get_server_id(lease);
 }
 
-struct netconfig *netconfig_new(uint32_t ifindex)
+struct netconfig *netconfig_new(uint32_t ifindex, const char *device_path,
+				const char *ipv4_path, const char *ipv6_path)
 {
 	struct netdev *netdev = netdev_find(ifindex);
 	struct netconfig *netconfig;
@@ -1154,6 +1381,9 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 
 	netconfig = l_new(struct netconfig, 1);
 	netconfig->ifindex = ifindex;
+	netconfig->device_path = l_strdup(device_path);
+	netconfig->ipv4_path = l_strdup(ipv4_path);
+	netconfig->ipv6_path = l_strdup(ipv6_path);
 	netconfig->resolve = resolve_new(ifindex);
 
 	netconfig->dhcp_client = l_dhcp_client_new(ifindex);
@@ -1203,6 +1433,193 @@ void netconfig_destroy(struct netconfig *netconfig)
 	netconfig_free(netconfig);
 }
 
+static bool netconfig_property_get_device(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+
+	l_dbus_message_builder_append_basic(builder, 'o',
+						netconfig->device_path);
+	return true;
+}
+
+static bool netconfig_is_ipv4_obj(struct netconfig *netconfig,
+					struct l_dbus_message *message)
+{
+	return netconfig->ipv4_path &&
+		!strcmp(l_dbus_message_get_path(message), netconfig->ipv4_path);
+}
+
+static bool netconfig_property_get_method(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+	uint8_t protocol;
+
+	protocol = netconfig_is_ipv4_obj(netconfig, message) ?
+		netconfig->rtm_protocol : netconfig->rtm_v6_protocol;
+
+	l_dbus_message_builder_append_basic(builder, 's',
+						protocol == RTPROT_DHCP ?
+						"auto" : "static");
+	return true;
+}
+
+static bool netconfig_property_get_address(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+	const struct l_rtnl_address *address;
+	char ip_str[INET6_ADDRSTRLEN];
+
+	address = netconfig_is_ipv4_obj(netconfig, message) ?
+		netconfig->v4_address : netconfig->v6_address;
+
+	if (!address || !l_rtnl_address_get_address(address, ip_str))
+		return false;
+
+	l_dbus_message_builder_append_basic(builder, 's', ip_str);
+	return true;
+}
+
+static bool netconfig_property_get_prefix(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+	const struct l_rtnl_address *address;
+	uint8_t prefix_len;
+
+	address = netconfig_is_ipv4_obj(netconfig, message) ?
+		netconfig->v4_address : netconfig->v6_address;
+
+	if (!address || !(prefix_len =
+				l_rtnl_address_get_prefix_length(address)))
+		return false;
+
+	l_dbus_message_builder_append_basic(builder, 'y', &prefix_len);
+	return true;
+}
+
+static bool netconfig_property_get_gateway(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+	const char *gateway_str = netconfig_is_ipv4_obj(netconfig, message) ?
+		netconfig->v4_gateway_str : netconfig->v6_gateway_str;
+
+	if (!gateway_str)
+		return false;
+
+	l_dbus_message_builder_append_basic(builder, 's', gateway_str);
+	return true;
+}
+
+static bool netconfig_property_get_dnses(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+	char **dns_str_list = netconfig_get_dns_list(netconfig,
+				netconfig_is_ipv4_obj(netconfig, message) ?
+				AF_INET : AF_INET6);
+	char **i;
+
+	l_dbus_message_builder_enter_array(builder, "s");
+
+	for (i = dns_str_list; i && *i; i++)
+		l_dbus_message_builder_append_basic(builder, 's', *i);
+
+	l_dbus_message_builder_leave_array(builder);
+	l_strv_free(dns_str_list);
+	return true;
+}
+
+static bool netconfig_property_get_domains(struct l_dbus *dbus,
+					struct l_dbus_message *message,
+					struct l_dbus_message_builder *builder,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+
+	if (netconfig_is_ipv4_obj(netconfig, message)) {
+		L_AUTO_FREE_VAR(char *, domain) =
+			l_settings_get_string(netconfig->active_settings,
+						"IPv4", "DomainName");
+
+		if (!domain) {
+			const struct l_dhcp_lease *lease;
+
+			if (netconfig->rtm_protocol != RTPROT_DHCP)
+				return false;
+
+			lease = l_dhcp_client_get_lease(netconfig->dhcp_client);
+			if (!lease)
+				return false;
+
+			if (!(domain = l_dhcp_lease_get_domain_name(lease)))
+				return false;
+		}
+
+		l_dbus_message_builder_enter_array(builder, "s");
+		l_dbus_message_builder_append_basic(builder, 's', domain);
+		l_dbus_message_builder_leave_array(builder);
+	} else {
+		const struct l_dhcp6_lease *lease;
+		char **domains;
+		char **i;
+
+		if (netconfig->rtm_v6_protocol != RTPROT_DHCP)
+			return false;
+
+		lease = l_dhcp6_client_get_lease(netconfig->dhcp6_client);
+		if (!lease)
+			return false;
+
+		domains = l_dhcp6_lease_get_domains(lease);
+		if (!domains)
+			return false;
+
+		l_dbus_message_builder_enter_array(builder, "s");
+
+		for (i = domains; *i; i++)
+			l_dbus_message_builder_append_basic(builder, 's', *i);
+
+		l_dbus_message_builder_leave_array(builder);
+		l_strv_free(domains);
+	}
+
+	return true;
+}
+
+static void netconfig_setup_interface(struct l_dbus_interface *interface)
+{
+	l_dbus_interface_property(interface, "Device", 0, "o",
+					netconfig_property_get_device, NULL);
+	l_dbus_interface_property(interface, "Method", 0, "s",
+					netconfig_property_get_method, NULL);
+	l_dbus_interface_property(interface, "Address", 0, "s",
+					netconfig_property_get_address, NULL);
+	l_dbus_interface_property(interface, "PrefixLength", 0, "y",
+					netconfig_property_get_prefix, NULL);
+	l_dbus_interface_property(interface, "Gateway", 0, "s",
+					netconfig_property_get_gateway, NULL);
+	l_dbus_interface_property(interface, "DomainNameServers", 0, "as",
+					netconfig_property_get_dnses, NULL);
+	l_dbus_interface_property(interface, "DomainNames", 0, "as",
+					netconfig_property_get_domains, NULL);
+}
+
 static int netconfig_init(void)
 {
 	uint32_t r;
@@ -1254,6 +1671,8 @@ static int netconfig_init(void)
 
 	netconfig_list = l_queue_new();
 
+	l_dbus_register_interface(dbus_get_bus(), IWD_NETCONFIG_INTERFACE,
+					netconfig_setup_interface, NULL, false);
 	return 0;
 
 error:
@@ -1270,6 +1689,8 @@ static void netconfig_exit(void)
 	rtnl = NULL;
 
 	l_queue_destroy(netconfig_list, netconfig_free);
+
+	l_dbus_unregister_interface(dbus_get_bus(), IWD_NETCONFIG_INTERFACE);
 }
 
 IWD_MODULE(netconfig, netconfig_init, netconfig_exit)
diff --git a/src/netconfig.h b/src/netconfig.h
index 2c68cb1c..17c26c72 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -38,5 +38,6 @@ bool netconfig_reconfigure(struct netconfig *netconfig);
 bool netconfig_reset(struct netconfig *netconfig);
 char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig);
 
-struct netconfig *netconfig_new(uint32_t ifindex);
+struct netconfig *netconfig_new(uint32_t ifindex, const char *device_path,
+				const char *ipv4_path, const char *ipv6_path);
 void netconfig_destroy(struct netconfig *netconfig);
diff --git a/src/p2p.c b/src/p2p.c
index cb6cd98b..124372e6 100644
--- a/src/p2p.c
+++ b/src/p2p.c
@@ -1319,7 +1319,10 @@ static void p2p_start_client_netconfig(struct p2p_device *dev)
 	struct l_settings *settings;
 
 	if (!dev->conn_netconfig) {
-		dev->conn_netconfig = netconfig_new(ifindex);
+		const char *peer_path = p2p_peer_get_path(dev->conn_peer);
+
+		dev->conn_netconfig = netconfig_new(ifindex, peer_path,
+							peer_path, NULL);
 		if (!dev->conn_netconfig) {
 			p2p_connect_failed(dev);
 			return;
diff --git a/src/station.c b/src/station.c
index 0b0cc59c..6c7843d0 100644
--- a/src/station.c
+++ b/src/station.c
@@ -3568,6 +3568,7 @@ static struct station *station_create(struct netdev *netdev)
 {
 	struct station *station;
 	struct l_dbus *dbus = dbus_get_bus();
+	const char *path;
 
 	station = l_new(struct station, 1);
 	watchlist_init(&station->state_watches, NULL);
@@ -3587,11 +3588,19 @@ static struct station *station_create(struct netdev *netdev)
 
 	station_set_autoconnect(station, true);
 
-	l_dbus_object_add_interface(dbus, netdev_get_path(netdev),
-					IWD_STATION_INTERFACE, station);
+	path = netdev_get_path(netdev);
+	l_dbus_object_add_interface(dbus, path, IWD_STATION_INTERFACE, station);
+
+	if (netconfig_enabled) {
+		L_AUTO_FREE_VAR(char *, ipv4_path) =
+			l_strdup_printf("%s/ipv4", path);
+		L_AUTO_FREE_VAR(char *, ipv6_path) =
+			l_strdup_printf("%s/ipv6", path);
 
-	if (netconfig_enabled)
-		station->netconfig = netconfig_new(netdev_get_ifindex(netdev));
+		station->netconfig = netconfig_new(netdev_get_ifindex(netdev),
+							path, ipv4_path,
+							ipv6_path);
+	}
 
 	station->anqp_pending = l_queue_new();
 
-- 
2.30.2

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

* [PATCH 3/3] netconfig: Reserve INET_ADDRSTRLEN chars for an IPv4 string
  2021-06-30 19:06 [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Andrew Zaborowski
  2021-06-30 19:06 ` [PATCH 2/3] netconfig: Add network configuration properties on Station and P2P Andrew Zaborowski
@ 2021-06-30 19:06 ` Andrew Zaborowski
  2021-07-02 15:04   ` Denis Kenzior
  2021-07-02 14:49 ` [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Denis Kenzior
  2 siblings, 1 reply; 5+ messages in thread
From: Andrew Zaborowski @ 2021-06-30 19:06 UTC (permalink / raw)
  To: iwd

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

For consistency replace an INET6_ADDRSTRLEN instance with
INET_ADDRSTRLEN in a strictly IPv4 context in
netconfig_ipv4_select_and_install.
---
 src/netconfig.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/netconfig.c b/src/netconfig.c
index 20c39f0f..6a7c49d0 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -1114,7 +1114,7 @@ static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data)
 
 static void netconfig_ipv4_select_and_install(struct netconfig *netconfig)
 {
-	char ip[INET6_ADDRSTRLEN];
+	char ip[INET_ADDRSTRLEN];
 
 	netconfig->v4_address = netconfig_get_static4_address(netconfig);
 	if (netconfig->v4_address &&
-- 
2.30.2

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

* Re: [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc
  2021-06-30 19:06 [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Andrew Zaborowski
  2021-06-30 19:06 ` [PATCH 2/3] netconfig: Add network configuration properties on Station and P2P Andrew Zaborowski
  2021-06-30 19:06 ` [PATCH 3/3] netconfig: Reserve INET_ADDRSTRLEN chars for an IPv4 string Andrew Zaborowski
@ 2021-07-02 14:49 ` Denis Kenzior
  2 siblings, 0 replies; 5+ messages in thread
From: Denis Kenzior @ 2021-07-02 14:49 UTC (permalink / raw)
  To: iwd

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

Hi Andrew,

On 6/30/21 2:06 PM, Andrew Zaborowski wrote:
> ---
>   doc/network-configuration-api.txt | 52 +++++++++++++++++++++++++++++++
>   1 file changed, 52 insertions(+)
>   create mode 100644 doc/network-configuration-api.txt
> 
> diff --git a/doc/network-configuration-api.txt b/doc/network-configuration-api.txt
> new file mode 100644
> index 00000000..5c302a37
> --- /dev/null
> +++ b/doc/network-configuration-api.txt
> @@ -0,0 +1,52 @@
> +Network Configuration hierarchy
> +===============================
> +
> +Service		net.connman.iwd
> +Interface	net.connman.iwd.NetworkConfiguration [Experimental]
> +Object path	/net/connman/iwd/{phy0,phy1,...}/{1,2,...}/{ipv4,ipv6}

Encoding anything into the object path is a discouraged design pattern.  You'd 
be better off instantiating multiple interfaces on the same object instead, one 
for IPv4 and one for IPv6.  That way you could even evolve the IPv4/IPv6 
interfaces separately.

Alternatively, you could have a single interface with multiple dictionaries...

> +Object path	/net/connman/iwd/{phy0,phy1,...}/p2p_peers/{aa_bb_cc_dd_ee_ff}
> +
> +Properties	object Device [readonly]

Given the above, this property would then likely become redundant and could be 
removed.

> +
> +			The object path of the station, access point or P2P
> +			device that this network configuration is active on.
> +
> +			In station mode, when network configuration is
> +			enabled there may be one or two objects using this
> +			interface and active on the same device: two if both
> +			IPv4 and IPv6 addresses have been configured.
> +
> +			In P2P mode, this interface always refers to IPv4
> +			network configuration.
> +
> +		string Method [readonly]
> +
> +			Indicates whether the local address was set
> +			statically (value "static") or obtained automatically
> +			such as through DHCP (value "auto").  Even when the
> +			address was obtained from the remote end some
> +			configuration bits, such as DNS addresses, may have
> +			been overridden locally.
> +
> +		string Address [readonly]
> +
> +			Holds the local IP address.
> +
> +		byte PrefixLength [readonly]
> +
> +			Holds the prefix-length of the local subnet.  For
> +			IPv4 this maps to the netmask.
> +
> +		string Gateway [readonly, optional]
> +
> +			Holds the gateway address for the IPv4 subnet if one
> +			exists.
> +
> +		array(string) DomainNameServers [readonly, optional]
> +
> +			Holds the list of domain name servers configured if
> +			any.

Do you need positional information here?  Does NM need to know in what order the 
name servers should be set between IPv6/IPv4?

> +
> +		string DomainNames [readonly, optional]

Why DomainNames (plural) when the type is a single string?

> +
> +			Holds the network's local domain names if any exist.
> 

Regards,
-Denis

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

* Re: [PATCH 3/3] netconfig: Reserve INET_ADDRSTRLEN chars for an IPv4 string
  2021-06-30 19:06 ` [PATCH 3/3] netconfig: Reserve INET_ADDRSTRLEN chars for an IPv4 string Andrew Zaborowski
@ 2021-07-02 15:04   ` Denis Kenzior
  0 siblings, 0 replies; 5+ messages in thread
From: Denis Kenzior @ 2021-07-02 15:04 UTC (permalink / raw)
  To: iwd

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

Hi Andrew,

On 6/30/21 2:06 PM, Andrew Zaborowski wrote:
> For consistency replace an INET6_ADDRSTRLEN instance with
> INET_ADDRSTRLEN in a strictly IPv4 context in
> netconfig_ipv4_select_and_install.
> ---
>   src/netconfig.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 

FYI, Coverity (falsely) complains about this when l_rtnl_address_get_address is 
used with INET_ADDRSTRLEN, since it doesn't know about the family.

Maybe we should make an L_RTNL_* #define for this?

Regards,
-Denis

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

end of thread, other threads:[~2021-07-02 15:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-30 19:06 [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Andrew Zaborowski
2021-06-30 19:06 ` [PATCH 2/3] netconfig: Add network configuration properties on Station and P2P Andrew Zaborowski
2021-06-30 19:06 ` [PATCH 3/3] netconfig: Reserve INET_ADDRSTRLEN chars for an IPv4 string Andrew Zaborowski
2021-07-02 15:04   ` Denis Kenzior
2021-07-02 14:49 ` [PATCH 1/3] doc: Add net.connman.iwd.NetworkConfiguration API doc Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.