@@ -237,7 +237,8 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
src/anqp.h src/anqp.c \
src/anqputil.h src/anqputil.c \
src/netconfig.h src/netconfig.c\
- src/resolve.h src/resolve.c\
+ src/netconfig-commit.c \
+ src/resolve.h src/resolve.c \
src/hotspot.c \
src/p2p.h src/p2p.c \
src/p2putil.h src/p2putil.c \
new file mode 100644
@@ -0,0 +1,203 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2022 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <arpa/inet.h>
+#include <netinet/if_ether.h>
+#include <linux/icmpv6.h>
+
+#include <ell/ell.h>
+
+#include "ell/useful.h"
+#include "src/iwd.h"
+#include "src/common.h"
+#include "src/util.h"
+#include "src/netdev.h"
+#include "src/ie.h"
+#include "src/resolve.h"
+#include "src/netconfig.h"
+
+struct netconfig_commit_ops {
+ bool (*init_data)(struct netconfig *netconfig);
+ void (*free_data)(struct netconfig *netconfig, const char *reasonstr);
+ void (*commit)(struct netconfig *netconfig, uint8_t family,
+ enum l_netconfig_event event);
+};
+
+static struct l_netlink *rtnl;
+
+static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
+ enum l_netconfig_event event);
+
+/* Default backend */
+static struct netconfig_commit_ops netconfig_rtnl_ops = {
+ .commit = netconfig_rtnl_commit,
+};
+
+/* Same backend for all netconfig objects */
+static const struct netconfig_commit_ops *commit_ops = &netconfig_rtnl_ops;
+
+static struct l_queue *netconfig_list;
+
+void netconfig_commit_init(struct netconfig *netconfig)
+{
+ if (!rtnl)
+ rtnl = l_rtnl_get();
+
+ if (!netconfig_list)
+ netconfig_list = l_queue_new();
+
+ l_queue_push_tail(netconfig_list, netconfig);
+
+ L_WARN_ON(netconfig->commit_data);
+
+ if (commit_ops->init_data)
+ commit_ops->init_data(netconfig);
+}
+
+void netconfig_commit_free(struct netconfig *netconfig, const char *reasonstr)
+{
+ if (commit_ops->free_data)
+ commit_ops->free_data(netconfig, reasonstr);
+
+ L_WARN_ON(!l_queue_remove(netconfig_list, netconfig));
+
+ if (l_queue_isempty(netconfig_list))
+ l_queue_destroy(l_steal_ptr(netconfig_list), NULL);
+}
+
+void netconfig_commit(struct netconfig *netconfig, uint8_t family,
+ enum l_netconfig_event event)
+{
+ commit_ops->commit(netconfig, family, event);
+
+ if (event == L_NETCONFIG_EVENT_CONFIGURE) {
+ /*
+ * Done here instead of in ops->commit because the MACs are
+ * not considered part of the network configuration
+ * (particularly Network Manager's "level 3 config" or l3cfg)
+ * so we can handle this ourselves independent of the backend.
+ */
+ if (family == AF_INET &&
+ !netconfig->static_config[INDEX_FOR_AF(family)])
+ netconfig_dhcp_gateway_to_arp(netconfig);
+ }
+}
+
+/*
+ * Called by all backends when netconfig_commit finishes, synchronously or
+ * asynchronously.
+ */
+static void netconfig_commit_done(struct netconfig *netconfig, uint8_t family,
+ enum l_netconfig_event event,
+ bool success)
+{
+}
+
+static void netconfig_set_neighbor_entry_cb(int error,
+ uint16_t type, const void *data,
+ uint32_t len, void *user_data)
+{
+ if (error)
+ l_error("l_rtnl_neighbor_set_hwaddr failed: %s (%i)",
+ strerror(-error), error);
+}
+
+void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig)
+{
+ struct l_dhcp_client *dhcp = l_netconfig_get_dhcp_client(netconfig->nc);
+ const struct l_dhcp_lease *lease;
+ _auto_(l_free) char *server_id = NULL;
+ _auto_(l_free) char *gw = NULL;
+ const uint8_t *server_mac;
+ struct in_addr in_gw;
+ uint32_t ifindex = netdev_get_ifindex(netconfig->netdev);
+
+ /* Can only do this for DHCP in certain network setups */
+ if (netconfig->static_config[INDEX_FOR_AF(AF_INET)] ||
+ netconfig->fils_override)
+ return;
+
+ lease = l_dhcp_client_get_lease(dhcp);
+ if (!lease)
+ return;
+
+ server_id = l_dhcp_lease_get_server_id(lease);
+ gw = l_dhcp_lease_get_gateway(lease);
+ server_mac = l_dhcp_lease_get_server_mac(lease);
+
+ if (!gw || strcmp(server_id, gw) || !server_mac)
+ return;
+
+ l_debug("Gateway MAC is known, setting into ARP cache");
+ in_gw.s_addr = l_dhcp_lease_get_gateway_u32(lease);
+
+ if (!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex, AF_INET,
+ &in_gw, server_mac, ETH_ALEN,
+ netconfig_set_neighbor_entry_cb, NULL,
+ NULL))
+ l_debug("l_rtnl_neighbor_set_hwaddr failed");
+}
+
+static void netconfig_dns_list_update(struct netconfig *netconfig)
+{
+ _auto_(l_strv_free) char **dns_list =
+ l_netconfig_get_dns_list(netconfig->nc);
+
+ if (netconfig->resolve && dns_list)
+ resolve_set_dns(netconfig->resolve, dns_list);
+}
+
+static void netconfig_domains_update(struct netconfig *netconfig)
+{
+ _auto_(l_strv_free) char **domains =
+ l_netconfig_get_domain_names(netconfig->nc);
+
+ if (netconfig->resolve && domains)
+ resolve_set_domains(netconfig->resolve, domains);
+}
+
+static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
+ enum l_netconfig_event event)
+{
+ l_netconfig_apply_rtnl(netconfig->nc);
+
+ /* TODO: cache values and skip updates if unchanged */
+ netconfig_dns_list_update(netconfig);
+ netconfig_domains_update(netconfig);
+
+ if (event == L_NETCONFIG_EVENT_CONFIGURE && family == AF_INET)
+ /*
+ * netconfig->mdns is currently only loaded in
+ * netconfig_load_settings() so we can set it once on
+ * the CONFIGURE event.
+ */
+ resolve_set_mdns(netconfig->resolve, netconfig->mdns);
+
+ if (event == L_NETCONFIG_EVENT_UNCONFIGURE && family == AF_INET)
+ resolve_revert(netconfig->resolve);
+
+ netconfig_commit_done(netconfig, family, event, true);
+}
@@ -27,9 +27,7 @@
#include <errno.h>
#include <arpa/inet.h>
#include <net/if_arp.h>
-#include <netinet/if_ether.h>
#include <netinet/in.h>
-#include <linux/rtnetlink.h>
#include <limits.h>
#include <string.h>
#include <fcntl.h>
@@ -52,30 +50,6 @@
#include "src/netconfig.h"
#include "src/sysfs.h"
-struct netconfig {
- struct l_netconfig *nc;
- struct netdev *netdev;
-
- char *mdns;
- struct ie_fils_ip_addr_response_info *fils_override;
- bool enabled[2];
- bool static_config[2];
- bool gateway_overridden[2];
- bool dns_overridden[2];
-
- const struct l_settings *active_settings;
-
- netconfig_notify_func_t notify;
- void *user_data;
-
- struct resolve *resolve;
-};
-
-/* 0 for AF_INET, 1 for AF_INET6 */
-#define INDEX_FOR_AF(af) ((af) != AF_INET)
-
-static struct l_netlink *rtnl;
-
/*
* Routing priority offset, configurable in main.conf. The route with lower
* priority offset is preferred.
@@ -116,7 +90,7 @@ static void netconfig_free(void *data)
l_free(netconfig);
}
-static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
+bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
{
if (!netconfig->enabled[INDEX_FOR_AF(af)])
return false;
@@ -133,15 +107,6 @@ static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
return !l_memeqzero(netconfig->fils_override->ipv6_addr, 16);
}
-static void netconfig_set_neighbor_entry_cb(int error,
- uint16_t type, const void *data,
- uint32_t len, void *user_data)
-{
- if (error)
- l_error("l_rtnl_neighbor_set_hwaddr failed: %s (%i)",
- strerror(-error), error);
-}
-
static struct l_rtnl_address *netconfig_get_static4_address(
const struct l_settings *active_settings)
{
@@ -240,41 +205,6 @@ no_prefix_len:
return l_steal_ptr(ret);
}
-static void netconfig_gateway_to_arp(struct netconfig *netconfig)
-{
- struct l_dhcp_client *dhcp = l_netconfig_get_dhcp_client(netconfig->nc);
- const struct l_dhcp_lease *lease;
- _auto_(l_free) char *server_id = NULL;
- _auto_(l_free) char *gw = NULL;
- const uint8_t *server_mac;
- struct in_addr in_gw;
-
- /* Can only do this for DHCP in certain network setups */
- if (netconfig->static_config[INDEX_FOR_AF(AF_INET)] ||
- netconfig->fils_override)
- return;
-
- lease = l_dhcp_client_get_lease(dhcp);
- if (!lease)
- return;
-
- server_id = l_dhcp_lease_get_server_id(lease);
- gw = l_dhcp_lease_get_gateway(lease);
- server_mac = l_dhcp_lease_get_server_mac(lease);
-
- if (!gw || strcmp(server_id, gw) || !server_mac)
- return;
-
- l_debug("Gateway MAC is known, setting into ARP cache");
- in_gw.s_addr = l_dhcp_lease_get_gateway_u32(lease);
-
- if (!l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex, AF_INET,
- &in_gw, server_mac, ETH_ALEN,
- netconfig_set_neighbor_entry_cb, NULL,
- NULL))
- l_debug("l_rtnl_neighbor_set_hwaddr failed");
-}
-
static bool netconfig_load_dns(struct netconfig *netconfig,
const struct l_settings *active_settings,
const char *group_name, uint8_t family)
@@ -501,7 +431,7 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw)
* to alleviate this
*/
if (set_arp_gw)
- netconfig_gateway_to_arp(netconfig);
+ netconfig_dhcp_gateway_to_arp(netconfig);
if (!netconfig->static_config[INDEX_FOR_AF(AF_INET)]) {
/* TODO l_dhcp_client sending a DHCP inform request */
@@ -584,6 +514,8 @@ struct netconfig *netconfig_new(uint32_t ifindex)
netconfig->netdev = netdev;
netconfig->resolve = resolve_new(ifindex);
+ netconfig_commit_init(netconfig);
+
debug_level = getenv("IWD_DHCP_DEBUG");
if (debug_level != NULL) {
if (!strcmp("debug", debug_level))
@@ -618,6 +550,7 @@ void netconfig_destroy(struct netconfig *netconfig)
l_debug("");
netconfig_reset(netconfig);
+ netconfig_commit_free(netconfig, "aborted");
resolve_free(netconfig->resolve);
netconfig_free(netconfig);
}
@@ -20,6 +20,7 @@
*
*/
+struct netdev;
struct netconfig;
struct ie_fils_ip_addr_request_info;
struct ie_fils_ip_addr_response_info;
@@ -31,6 +32,30 @@ enum netconfig_event {
typedef void (*netconfig_notify_func_t)(enum netconfig_event event,
void *user_data);
+struct netconfig {
+ struct l_netconfig *nc;
+ struct netdev *netdev;
+
+ char *mdns;
+ struct ie_fils_ip_addr_response_info *fils_override;
+ bool enabled[2];
+ bool static_config[2];
+ bool gateway_overridden[2];
+ bool dns_overridden[2];
+
+ const struct l_settings *active_settings;
+
+ netconfig_notify_func_t notify;
+ void *user_data;
+
+ struct resolve *resolve;
+
+ void *commit_data;
+};
+
+/* 0 for AF_INET, 1 for AF_INET6 */
+#define INDEX_FOR_AF(af) ((af) != AF_INET)
+
bool netconfig_load_settings(struct netconfig *netconfig,
const struct l_settings *active_settings);
bool netconfig_configure(struct netconfig *netconfig,
@@ -43,8 +68,16 @@ 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);
+bool netconfig_use_fils_addr(struct netconfig *netconfig, int af);
struct netconfig *netconfig_new(uint32_t ifindex);
void netconfig_destroy(struct netconfig *netconfig);
bool netconfig_enabled(void);
+
+void netconfig_commit_init(struct netconfig *netconfig);
+void netconfig_commit_free(struct netconfig *netconfig, const char *reasonstr);
+void netconfig_commit(struct netconfig *netconfig, uint8_t family,
+ enum l_netconfig_event event);
+
+void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig);