mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-08 15:52:32 +01:00
ap: Refactor DHCP settings loading
Extend the [IPv4].Address setting's syntax to allow a new format: a list of <IP>/<prefix_len> -form strings that define the address space from which a subnet is selected. Rewrite the DHCP settings loading with other notable changes: * validate some of the settings more thoroughly, * name all netconfig-related ap_state members with the netconfig_ prefix, * make sure we always call l_dhcp_server_set_netmask(), * allow netmasks other than 24-bit and change the default to 28 bits, * as requested avoid using the l_net_ ioctl-based functions although l_dhcp still uses them internally, * as requested avoid touching the ap_state members until the end of some functions so that on error they're basically a no-op (for readability).
This commit is contained in:
parent
e56e4ade90
commit
c5d1a5c31f
503
src/ap.c
503
src/ap.c
@ -52,6 +52,7 @@
|
||||
#include "src/frame-xchg.h"
|
||||
#include "src/wscutil.h"
|
||||
#include "src/eap-wsc.h"
|
||||
#include "src/ip-pool.h"
|
||||
#include "src/ap.h"
|
||||
#include "src/storage.h"
|
||||
#include "src/diagnostic.h"
|
||||
@ -88,15 +89,15 @@ struct ap_state {
|
||||
uint16_t last_aid;
|
||||
struct l_queue *sta_states;
|
||||
|
||||
struct l_dhcp_server *server;
|
||||
struct l_dhcp_server *netconfig_dhcp;
|
||||
char *netconfig_addr4_str;
|
||||
uint8_t netconfig_prefix_len4;
|
||||
uint32_t rtnl_add_cmd;
|
||||
char *own_ip;
|
||||
unsigned int ip_prefix;
|
||||
|
||||
bool started : 1;
|
||||
bool gtk_set : 1;
|
||||
bool cleanup_ip : 1;
|
||||
bool use_ip_pool : 1;
|
||||
bool netconfig_set_addr4 : 1;
|
||||
bool netconfig_use_ip_pool : 1;
|
||||
};
|
||||
|
||||
struct sta_state {
|
||||
@ -181,7 +182,7 @@ static char *ip_pool_get()
|
||||
|
||||
/* This shouldn't happen */
|
||||
if (next_subnet < pool.sub_start || next_subnet > pool.sub_end)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
l_uintset_put(pool.used, next_subnet);
|
||||
|
||||
@ -321,23 +322,27 @@ static void ap_reset(struct ap_state *ap)
|
||||
ap->started = false;
|
||||
|
||||
/* Delete IP if one was set by IWD */
|
||||
if (ap->cleanup_ip)
|
||||
if (ap->netconfig_set_addr4) {
|
||||
l_rtnl_ifaddr4_delete(rtnl, netdev_get_ifindex(netdev),
|
||||
ap->ip_prefix, ap->own_ip,
|
||||
broadcast_from_ip(ap->own_ip),
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (ap->own_ip) {
|
||||
/* Release IP from pool if used */
|
||||
if (ap->use_ip_pool)
|
||||
ip_pool_put(ap->own_ip);
|
||||
|
||||
l_free(ap->own_ip);
|
||||
ap->netconfig_prefix_len4,
|
||||
ap->netconfig_addr4_str,
|
||||
broadcast_from_ip(ap->netconfig_addr4_str),
|
||||
NULL, NULL, NULL);
|
||||
ap->netconfig_set_addr4 = false;
|
||||
}
|
||||
|
||||
if (ap->server) {
|
||||
l_dhcp_server_destroy(ap->server);
|
||||
ap->server = NULL;
|
||||
if (ap->netconfig_use_ip_pool) {
|
||||
/* Release IP from pool if used */
|
||||
ip_pool_put(ap->netconfig_addr4_str);
|
||||
ap->netconfig_use_ip_pool = false;
|
||||
}
|
||||
|
||||
l_free(ap->netconfig_addr4_str);
|
||||
ap->netconfig_addr4_str = NULL;
|
||||
|
||||
if (ap->netconfig_dhcp) {
|
||||
l_dhcp_server_destroy(ap->netconfig_dhcp);
|
||||
ap->netconfig_dhcp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2165,7 +2170,7 @@ static void ap_start_cb(struct l_genl_msg *msg, void *user_data)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ap->server && !l_dhcp_server_start(ap->server)) {
|
||||
if (ap->netconfig_dhcp && !l_dhcp_server_start(ap->netconfig_dhcp)) {
|
||||
l_error("DHCP server failed to start");
|
||||
goto failed;
|
||||
}
|
||||
@ -2492,182 +2497,290 @@ static void ap_mlme_notify(struct l_genl_msg *msg, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static bool dhcp_load_settings(struct ap_state *ap,
|
||||
const struct l_settings *settings)
|
||||
{
|
||||
struct l_dhcp_server *server = ap->server;
|
||||
struct in_addr ia;
|
||||
#define AP_DEFAULT_IPV4_PREFIX_LEN 28
|
||||
|
||||
L_AUTO_FREE_VAR(char *, netmask) = l_settings_get_string(settings,
|
||||
"IPv4", "Netmask");
|
||||
L_AUTO_FREE_VAR(char *, gateway) = l_settings_get_string(settings,
|
||||
"IPv4", "Gateway");
|
||||
char **dns = l_settings_get_string_list(settings, "IPv4",
|
||||
"DNSList", ',');
|
||||
char **ip_range = l_settings_get_string_list(settings, "IPv4",
|
||||
"IPRange", ',');
|
||||
unsigned int lease_time;
|
||||
bool ret = false;
|
||||
|
||||
if (!l_settings_get_uint(settings, "IPv4", "LeaseTime", &lease_time))
|
||||
lease_time = 0;
|
||||
|
||||
if (gateway && !l_dhcp_server_set_gateway(server, gateway)) {
|
||||
l_error("[IPv4].Gateway value error");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (dns && !l_dhcp_server_set_dns(server, dns)) {
|
||||
l_error("[IPv4].DNSList value error");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (netmask && !l_dhcp_server_set_netmask(server, netmask)) {
|
||||
l_error("[IPv4].Netmask value error");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ip_range) {
|
||||
if (l_strv_length(ip_range) != 2) {
|
||||
l_error("Two addresses expected in [IPv4].IPRange");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!l_dhcp_server_set_ip_range(server, ip_range[0],
|
||||
ip_range[1])) {
|
||||
l_error("Error setting IP range from [IPv4].IPRange");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (lease_time && !l_dhcp_server_set_lease_time(server, lease_time)) {
|
||||
l_error("[IPv4].LeaseTime value error");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (netmask && inet_pton(AF_INET, netmask, &ia) > 0)
|
||||
ap->ip_prefix = __builtin_popcountl(ia.s_addr);
|
||||
else
|
||||
ap->ip_prefix = 24;
|
||||
|
||||
ret = true;
|
||||
|
||||
error:
|
||||
l_strv_free(dns);
|
||||
l_strv_free(ip_range);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will determine the IP being used for DHCP. The IP will be automatically
|
||||
* set to ap->own_ip.
|
||||
*
|
||||
* The address to set (or keep) is determined in this order:
|
||||
* 1. Address defined in provisioning file
|
||||
* 2. Address already set on interface
|
||||
* 3. Address in IP pool.
|
||||
*
|
||||
* Returns: 0 if an IP was successfully selected and needs to be set
|
||||
* -EALREADY if an IP was already set on the interface or
|
||||
* IP configuration was not enabled,
|
||||
* -EEXIST if the IP pool ran out of IP's
|
||||
* -EINVAL if there was an error.
|
||||
*/
|
||||
static int ap_setup_dhcp(struct ap_state *ap, const struct l_settings *settings)
|
||||
static int ap_setup_netconfig4(struct ap_state *ap, const char **addr_str_list,
|
||||
uint8_t prefix_len, const char *gateway_str,
|
||||
const char **ip_range,
|
||||
const char **dns_str_list,
|
||||
unsigned int lease_time)
|
||||
{
|
||||
uint32_t ifindex = netdev_get_ifindex(ap->netdev);
|
||||
struct l_rtnl_address *existing_addr = ip_pool_get_addr4(ifindex);
|
||||
struct l_rtnl_address *new_addr = NULL;
|
||||
int ret;
|
||||
struct in_addr ia;
|
||||
uint32_t address = 0;
|
||||
L_AUTO_FREE_VAR(char *, addr) = NULL;
|
||||
int ret = -EINVAL;
|
||||
struct l_dhcp_server *dhcp = NULL;
|
||||
bool use_ip_pool = false;
|
||||
bool r;
|
||||
char addr_str_buf[INET_ADDRSTRLEN];
|
||||
|
||||
/* get the current address if there is one */
|
||||
if (l_net_get_address(ifindex, &ia) && ia.s_addr != 0)
|
||||
address = ia.s_addr;
|
||||
|
||||
addr = l_settings_get_string(settings, "IPv4", "Address");
|
||||
if (addr) {
|
||||
if (inet_pton(AF_INET, addr, &ia) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Is a matching address already set on interface? */
|
||||
if (ia.s_addr == address)
|
||||
ret = -EALREADY;
|
||||
else
|
||||
ret = 0;
|
||||
} else if (address) {
|
||||
/* No address in config, but interface has one set */
|
||||
addr = l_strdup(inet_ntoa(ia));
|
||||
ret = -EALREADY;
|
||||
} else if (pool.used) {
|
||||
/* No config file, no address set. Use IP pool */
|
||||
addr = ip_pool_get();
|
||||
if (!addr) {
|
||||
l_error("No more IP's in pool, cannot start AP on %u",
|
||||
ifindex);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
ap->use_ip_pool = true;
|
||||
ap->ip_prefix = pool.prefix;
|
||||
ret = 0;
|
||||
} else
|
||||
return -EALREADY;
|
||||
|
||||
ap->server = l_dhcp_server_new(ifindex);
|
||||
if (!ap->server) {
|
||||
l_error("Failed to create DHCP server on %u", ifindex);
|
||||
return -EINVAL;
|
||||
dhcp = l_dhcp_server_new(ifindex);
|
||||
if (!dhcp) {
|
||||
l_error("Failed to create DHCP server on ifindex %u", ifindex);
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (getenv("IWD_DHCP_DEBUG"))
|
||||
l_dhcp_server_set_debug(ap->server, do_debug,
|
||||
"[DHCPv4 SERV] ", NULL);
|
||||
l_dhcp_server_set_debug(dhcp, do_debug,
|
||||
"[DHCPv4 SERV] ", NULL);
|
||||
|
||||
/* Set the remaining DHCP options in config file */
|
||||
if (!dhcp_load_settings(ap, settings))
|
||||
return -EINVAL;
|
||||
/*
|
||||
* The address pool specified for this AP (if any) has the priority,
|
||||
* next is the address currently set on the interface (if any) and
|
||||
* last is the global AP address pool (APRanges setting).
|
||||
*/
|
||||
if (addr_str_list) {
|
||||
if (!prefix_len)
|
||||
prefix_len = AP_DEFAULT_IPV4_PREFIX_LEN;
|
||||
|
||||
if (!l_dhcp_server_set_ip_address(ap->server, addr))
|
||||
return -EINVAL;
|
||||
ret = ip_pool_select_addr4(addr_str_list, prefix_len,
|
||||
&new_addr);
|
||||
} else if (existing_addr &&
|
||||
l_rtnl_address_get_prefix_length(existing_addr) <
|
||||
31) {
|
||||
if (!prefix_len)
|
||||
prefix_len = l_rtnl_address_get_prefix_length(
|
||||
existing_addr);
|
||||
|
||||
ap->own_ip = l_steal_ptr(addr);
|
||||
if (!l_rtnl_address_get_address(existing_addr, addr_str_buf)) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
new_addr = l_rtnl_address_new(addr_str_buf, prefix_len);
|
||||
ret = 0;
|
||||
} else {
|
||||
L_AUTO_FREE_VAR(char *, addr_str) = NULL;
|
||||
|
||||
if (prefix_len) {
|
||||
l_error("[IPv4].Netmask can't be used without an "
|
||||
"address");
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* No config, no address set. Use IP pool */
|
||||
addr_str = ip_pool_get();
|
||||
if (addr_str) {
|
||||
use_ip_pool = true;
|
||||
prefix_len = pool.prefix;
|
||||
new_addr = l_rtnl_address_new(addr_str, prefix_len);
|
||||
ret = 0;
|
||||
} else {
|
||||
l_error("No more IP's in pool, cannot start AP on %u",
|
||||
ifindex);
|
||||
ret = -EEXIST;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
ret = -EIO;
|
||||
|
||||
/*
|
||||
* l_dhcp_server_start() would retrieve the current IPv4 from
|
||||
* the interface but set it anyway in case there are multiple
|
||||
* addresses, saves one ioctl too.
|
||||
*/
|
||||
if (!l_rtnl_address_get_address(new_addr, addr_str_buf)) {
|
||||
l_error("l_rtnl_address_get_address failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!l_dhcp_server_set_ip_address(dhcp, addr_str_buf)) {
|
||||
l_error("l_dhcp_server_set_ip_address failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ia.s_addr = htonl(util_netmask_from_prefix(prefix_len));
|
||||
|
||||
if (!l_dhcp_server_set_netmask(dhcp, inet_ntoa(ia))) {
|
||||
l_error("l_dhcp_server_set_netmask failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (gateway_str && !l_dhcp_server_set_gateway(dhcp, gateway_str)) {
|
||||
l_error("l_dhcp_server_set_gateway failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ip_range) {
|
||||
r = l_dhcp_server_set_ip_range(dhcp, ip_range[0], ip_range[1]);
|
||||
if (!r) {
|
||||
l_error("l_dhcp_server_set_ip_range failed");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (dns_str_list) {
|
||||
r = l_dhcp_server_set_dns(dhcp, (char **) dns_str_list);
|
||||
if (!r) {
|
||||
l_error("l_dhcp_server_set_dns failed");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (lease_time && !l_dhcp_server_set_lease_time(dhcp, lease_time)) {
|
||||
l_error("l_dhcp_server_set_lease_time failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ap->netconfig_addr4_str = l_strdup(addr_str_buf);
|
||||
ap->netconfig_prefix_len4 = prefix_len;
|
||||
ap->netconfig_set_addr4 = true;
|
||||
ap->netconfig_use_ip_pool = use_ip_pool;
|
||||
ap->netconfig_dhcp = l_steal_ptr(dhcp);
|
||||
ret = 0;
|
||||
|
||||
if (existing_addr && l_rtnl_address_get_prefix_length(existing_addr) >
|
||||
prefix_len) {
|
||||
char addr_str_buf2[INET_ADDRSTRLEN];
|
||||
|
||||
if (l_rtnl_address_get_address(existing_addr, addr_str_buf2) &&
|
||||
!strcmp(addr_str_buf, addr_str_buf2))
|
||||
ap->netconfig_set_addr4 = false;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
l_dhcp_server_destroy(dhcp);
|
||||
l_rtnl_address_free(new_addr);
|
||||
l_rtnl_address_free(existing_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ap_load_dhcp(struct ap_state *ap, const struct l_settings *config,
|
||||
bool *wait_dhcp)
|
||||
static int ap_load_ipv4(struct ap_state *ap, const struct l_settings *config)
|
||||
{
|
||||
uint32_t ifindex = netdev_get_ifindex(ap->netdev);
|
||||
int err = -EINVAL;
|
||||
int ret = -EINVAL;
|
||||
char **addr_str_list = NULL;
|
||||
uint32_t static_addr = 0;
|
||||
uint8_t prefix_len = 0;
|
||||
char *gateway_str = NULL;
|
||||
char **ip_range = NULL;
|
||||
char **dns_str_list = NULL;
|
||||
unsigned int lease_time = 0;
|
||||
struct in_addr ia;
|
||||
|
||||
if (!l_settings_has_group(config, "IPv4"))
|
||||
if (!l_settings_has_group(config, "IPv4") || !pool.used)
|
||||
return 0;
|
||||
|
||||
err = ap_setup_dhcp(ap, config);
|
||||
if (err == 0) {
|
||||
/* Address change required */
|
||||
ap->rtnl_add_cmd = l_rtnl_ifaddr4_add(rtnl, ifindex,
|
||||
ap->ip_prefix, ap->own_ip,
|
||||
broadcast_from_ip(ap->own_ip),
|
||||
ap_ifaddr4_added_cb, ap, NULL);
|
||||
|
||||
if (!ap->rtnl_add_cmd) {
|
||||
l_error("Failed to add IPv4 address");
|
||||
return -EIO;
|
||||
if (l_settings_has_key(config, "IPv4", "Address")) {
|
||||
addr_str_list = l_settings_get_string_list(config, "IPv4",
|
||||
"Address", ',');
|
||||
if (!addr_str_list || !*addr_str_list) {
|
||||
l_error("Can't parse the profile [IPv4].Address "
|
||||
"setting as a string list");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ap->cleanup_ip = true;
|
||||
|
||||
*wait_dhcp = true;
|
||||
err = 0;
|
||||
/* Selected address already set, continue normally */
|
||||
} else if (err == -EALREADY) {
|
||||
*wait_dhcp = false;
|
||||
err = 0;
|
||||
/* Check for the static IP syntax: Address=<IP> */
|
||||
if (l_strv_length(addr_str_list) == 1 &&
|
||||
inet_pton(AF_INET, *addr_str_list, &ia) == 1)
|
||||
static_addr = ntohl(ia.s_addr);
|
||||
}
|
||||
|
||||
return err;
|
||||
if (l_settings_has_key(config, "IPv4", "Netmask")) {
|
||||
L_AUTO_FREE_VAR(char *, netmask_str) =
|
||||
l_settings_get_string(config, "IPv4", "Netmask");
|
||||
|
||||
if (inet_pton(AF_INET, netmask_str, &ia) != 1) {
|
||||
l_error("Can't parse the profile [IPv4].Netmask "
|
||||
"setting");
|
||||
goto done;
|
||||
}
|
||||
|
||||
prefix_len = __builtin_popcount(ia.s_addr);
|
||||
|
||||
if (ntohl(ia.s_addr) != util_netmask_from_prefix(prefix_len)) {
|
||||
l_error("Invalid profile [IPv4].Netmask value");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (l_settings_has_key(config, "IPv4", "Gateway")) {
|
||||
gateway_str = l_settings_get_string(config, "IPv4", "Gateway");
|
||||
if (!gateway_str) {
|
||||
l_error("Invalid profile [IPv4].Gateway value");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (l_settings_get_value(config, "IPv4", "IPRange")) {
|
||||
int i;
|
||||
uint32_t netmask;
|
||||
uint8_t tmp_len = prefix_len ?: AP_DEFAULT_IPV4_PREFIX_LEN;
|
||||
|
||||
ip_range = l_settings_get_string_list(config, "IPv4",
|
||||
"IPRange", ',');
|
||||
|
||||
if (!static_addr) {
|
||||
l_error("[IPv4].IPRange only makes sense in an AP "
|
||||
"profile if a static local address has also "
|
||||
"been specified");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!ip_range || l_strv_length(ip_range) != 2) {
|
||||
l_error("Can't parse the profile [IPv4].IPRange "
|
||||
"setting as two address strings");
|
||||
goto done;
|
||||
}
|
||||
|
||||
netmask = util_netmask_from_prefix(tmp_len);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct in_addr range_addr;
|
||||
|
||||
if (inet_aton(ip_range[i], &range_addr) != 1) {
|
||||
l_error("Can't parse address in "
|
||||
"[IPv4].IPRange[%i]", i + 1);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((static_addr ^ ntohl(range_addr.s_addr)) &
|
||||
netmask) {
|
||||
ia.s_addr = htonl(static_addr);
|
||||
l_error("[IPv4].IPRange[%i] is not in the "
|
||||
"%s/%i subnet", i + 1, inet_ntoa(ia),
|
||||
tmp_len);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (l_settings_has_key(config, "IPv4", "DNSList")) {
|
||||
dns_str_list = l_settings_get_string_list(config, "IPv4",
|
||||
"DNSList", ',');
|
||||
if (!dns_str_list || !*dns_str_list) {
|
||||
l_error("Can't parse the profile [IPv4].DNSList "
|
||||
"setting as a string list");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (l_settings_has_key(config, "IPv4", "LeaseTime")) {
|
||||
if (!l_settings_get_uint(config, "IPv4", "LeaseTime",
|
||||
&lease_time) ||
|
||||
lease_time < 1) {
|
||||
l_error("Error parsing [IPv4].LeaseTime as a positive "
|
||||
"integer");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ap_setup_netconfig4(ap, (const char **) addr_str_list, prefix_len,
|
||||
gateway_str, (const char **) ip_range,
|
||||
(const char **) dns_str_list,
|
||||
lease_time);
|
||||
|
||||
done:
|
||||
l_strv_free(addr_str_list);
|
||||
l_free(gateway_str);
|
||||
l_strv_free(ip_range);
|
||||
l_strv_free(dns_str_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool ap_load_psk(struct ap_state *ap, const struct l_settings *config)
|
||||
@ -2722,7 +2835,7 @@ static bool ap_load_psk(struct ap_state *ap, const struct l_settings *config)
|
||||
}
|
||||
|
||||
static int ap_load_config(struct ap_state *ap, const struct l_settings *config,
|
||||
bool *out_wait_dhcp, bool *out_cck_rates)
|
||||
bool *out_cck_rates)
|
||||
{
|
||||
size_t len;
|
||||
L_AUTO_FREE_VAR(char *, strval) = NULL;
|
||||
@ -2748,11 +2861,12 @@ static int ap_load_config(struct ap_state *ap, const struct l_settings *config,
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* This loads DHCP settings either from the l_settings object or uses
|
||||
* the defaults. wait_on_address will be set true if an address change
|
||||
* is required.
|
||||
* This looks at the network configuration settings in @config and
|
||||
* relevant global settings and if it determines that netconfig is to
|
||||
* be enabled for the AP, it both creates the DHCP server object and
|
||||
* processes IP settings, applying the defaults where needed.
|
||||
*/
|
||||
err = ap_load_dhcp(ap, config, out_wait_dhcp);
|
||||
err = ap_load_ipv4(ap, config);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -2868,15 +2982,15 @@ struct ap_state *ap_start(struct netdev *netdev, struct l_settings *config,
|
||||
struct ap_state *ap;
|
||||
struct wiphy *wiphy = netdev_get_wiphy(netdev);
|
||||
uint64_t wdev_id = netdev_get_wdev_id(netdev);
|
||||
int err = -EINVAL;
|
||||
bool wait_on_address = false;
|
||||
int err;
|
||||
bool cck_rates = true;
|
||||
|
||||
if (err_out)
|
||||
*err_out = err;
|
||||
if (L_WARN_ON(!config)) {
|
||||
if (err_out)
|
||||
*err_out = -EINVAL;
|
||||
|
||||
if (L_WARN_ON(!config))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ap = l_new(struct ap_state, 1);
|
||||
ap->nl80211 = l_genl_family_new(iwd_get_genl(), NL80211_GENL_NAME);
|
||||
@ -2884,7 +2998,7 @@ struct ap_state *ap_start(struct netdev *netdev, struct l_settings *config,
|
||||
ap->ops = ops;
|
||||
ap->user_data = user_data;
|
||||
|
||||
err = ap_load_config(ap, config, &wait_on_address, &cck_rates);
|
||||
err = ap_load_config(ap, config, &cck_rates);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
@ -2950,9 +3064,20 @@ struct ap_state *ap_start(struct netdev *netdev, struct l_settings *config,
|
||||
if (!ap->mlme_watch)
|
||||
l_error("Registering for MLME notification failed");
|
||||
|
||||
if (wait_on_address) {
|
||||
if (err_out)
|
||||
*err_out = 0;
|
||||
if (ap->netconfig_set_addr4) {
|
||||
const char *broadcast_str =
|
||||
broadcast_from_ip(ap->netconfig_addr4_str);
|
||||
|
||||
ap->rtnl_add_cmd = l_rtnl_ifaddr4_add(rtnl,
|
||||
netdev_get_ifindex(netdev),
|
||||
ap->netconfig_prefix_len4,
|
||||
ap->netconfig_addr4_str,
|
||||
broadcast_str,
|
||||
ap_ifaddr4_added_cb, ap, NULL);
|
||||
if (!ap->rtnl_add_cmd) {
|
||||
l_error("Failed to add the IPv4 address");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user