mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-21 22:09:23 +01:00
netconfig: Add netconfig-commit API
Add netconfig-commit.c whose main method, netconfig_commit actually sets the configuration obtained by l_netconfig to the system netdev, specifically it sets local addresses on the interface, adds routes to the routing table, sets DNS related data and may add entries to the neighbor cache. netconfig-commit.c uses a backend-ops type structure to allow for switching backends. In this commit there's only a default backend that uses l_netconfig_rtnl_apply() and a struct resolve object to write the configuration. netconfig_gateway_to_arp is moved from netconfig.c to netconfig-commit.c (and renamed.) The struct netconfig definition is moved to netconfig.h so that both files can access the settings stored in the struct.
This commit is contained in:
parent
a8b1139dcb
commit
b79c7d49cd
@ -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 \
|
||||
|
203
src/netconfig-commit.c
Normal file
203
src/netconfig-commit.c
Normal file
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user