Split loading settings out of network_configure into a new method, network_load_settings. Make sure both consistently handle errors by printing messages and informing the caller. --- src/netconfig.c | 157 +++++++++++++++++++++++++++++++----------------- src/netconfig.h | 5 +- src/p2p.c | 12 +++- src/station.c | 20 +++--- 4 files changed, 127 insertions(+), 67 deletions(-) diff --git a/src/netconfig.c b/src/netconfig.c index 005316cd..d6113c0c 100644 --- a/src/netconfig.c +++ b/src/netconfig.c @@ -273,10 +273,10 @@ static struct l_rtnl_address *netconfig_get_static4_address( struct netconfig *netconfig) { struct l_rtnl_address *ifaddr = NULL; - char *ip; - char *netmask; + L_AUTO_FREE_VAR(char *, ip) = NULL; + L_AUTO_FREE_VAR(char *, netmask) = NULL; struct in_addr in_addr; - char *broadcast; + L_AUTO_FREE_VAR(char *, broadcast) = NULL; uint32_t prefix_len; ip = l_settings_get_string(netconfig->active_settings, "IPv4", @@ -286,33 +286,34 @@ static struct l_rtnl_address *netconfig_get_static4_address( netmask = l_settings_get_string(netconfig->active_settings, "IPv4", "Netmask"); + if (netmask) { + if (inet_pton(AF_INET, netmask, &in_addr) != 1) { + l_error("netconfig: Can't parse IPv4 Netmask"); + return NULL; + } - if (netmask && inet_pton(AF_INET, netmask, &in_addr) > 0) prefix_len = __builtin_popcountl(in_addr.s_addr); - else - prefix_len = 24; - l_free(netmask); + if (ntohl(in_addr.s_addr) != + util_netmask_from_prefix(prefix_len)) { + l_error("netconfig: Invalid IPv4 Netmask"); + return NULL; + } + } else + prefix_len = 24; ifaddr = l_rtnl_address_new(ip, prefix_len); - l_free(ip); - if (!ifaddr) { - l_error("Unable to parse IPv4.Address, ignoring..."); + l_error("netconfig: Unable to parse IPv4.Address"); return NULL; } broadcast = l_settings_get_string(netconfig->active_settings, "IPv4", "Broadcast"); - if (broadcast) { - bool r = l_rtnl_address_set_broadcast(ifaddr, broadcast); - l_free(broadcast); - - if (!r) { - l_error("Unable to parse IPv4.Broadcast, ignoring..."); - l_rtnl_address_free(ifaddr); - return NULL; - } + if (broadcast && !l_rtnl_address_set_broadcast(ifaddr, broadcast)) { + l_error("netconfig: Unable to parse IPv4.Broadcast"); + l_rtnl_address_free(ifaddr); + return NULL; } l_rtnl_address_set_noprefixroute(ifaddr, true); @@ -898,14 +899,17 @@ static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data) } } -static void netconfig_ipv4_select_and_install(struct netconfig *netconfig) +static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig) { - char ip[INET6_ADDRSTRLEN]; + if (netconfig->rtm_protocol == RTPROT_STATIC) { + char ip[INET6_ADDRSTRLEN]; + + if (L_WARN_ON(!netconfig->v4_address || + !l_rtnl_address_get_address( + netconfig->v4_address, + ip))) + return false; - netconfig->v4_address = netconfig_get_static4_address(netconfig); - if (netconfig->v4_address && - l_rtnl_address_get_address(netconfig->v4_address, ip)) { - netconfig->rtm_protocol = RTPROT_STATIC; netconfig->acd = l_acd_new(netconfig->ifindex); l_acd_set_event_handler(netconfig->acd, netconfig_ipv4_acd_event, netconfig, @@ -926,47 +930,42 @@ static void netconfig_ipv4_select_and_install(struct netconfig *netconfig) netconfig, NULL))); } - return; + return true; } - netconfig->rtm_protocol = RTPROT_DHCP; - if (l_dhcp_client_start(netconfig->dhcp_client)) - return; + return true; l_error("netconfig: Failed to start DHCPv4 client for interface %u", netconfig->ifindex); + return false; } -static void netconfig_ipv6_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; - bool enabled; - - if (!l_settings_get_bool(netconfig->active_settings, "IPv6", - "Enabled", &enabled)) - enabled = ipv6_enabled; - if (!enabled) { + if (netconfig->rtm_v6_protocol == RTPROT_UNSPEC) { l_debug("IPV6 configuration disabled"); - return; + return true; } sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "0"); - address = netconfig_get_static6_address(netconfig); - if (address) { - netconfig->rtm_v6_protocol = RTPROT_STATIC; + if (netconfig->rtm_v6_protocol == RTPROT_STATIC) { + struct l_rtnl_address *address = + netconfig_get_static6_address(netconfig); + L_WARN_ON(!(netconfig->addr6_add_cmd_id = l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, address, netconfig_ipv6_ifaddr_add_cmd_cb, netconfig, NULL))); l_rtnl_address_free(address); - return; + return true; } - netconfig->rtm_v6_protocol = RTPROT_DHCP; + /* DHCP */ + return true; } static int validate_dns_list(int family, char **dns_list) @@ -998,22 +997,22 @@ static int validate_dns_list(int family, char **dns_list) return n_valid; } -bool netconfig_configure(struct netconfig *netconfig, +bool netconfig_load_settings(struct netconfig *netconfig, const struct l_settings *active_settings, - const uint8_t *mac_address, - netconfig_notify_func_t notify, void *user_data) + const uint8_t *mac_address) { char *mdns; - char hostname[HOST_NAME_MAX + 1]; bool send_hostname; + bool enabled; + l_strfreev(netconfig->dns4_overrides); netconfig->dns4_overrides = l_settings_get_string_list(active_settings, "IPv4", "DNS", ' '); if (netconfig->dns4_overrides) { int r = validate_dns_list(AF_INET, netconfig->dns4_overrides); - if (r <= 0) { + if (unlikely(r <= 0)) { l_strfreev(netconfig->dns4_overrides); netconfig->dns4_overrides = NULL; } @@ -1022,13 +1021,14 @@ bool netconfig_configure(struct netconfig *netconfig, l_error("netconfig: Empty IPv4.DNS entry, skipping..."); } + l_strfreev(netconfig->dns6_overrides); netconfig->dns6_overrides = l_settings_get_string_list(active_settings, "IPv6", "DNS", ' '); if (netconfig->dns6_overrides) { int r = validate_dns_list(AF_INET6, netconfig->dns6_overrides); - if (r <= 0) { + if (unlikely(r <= 0)) { l_strfreev(netconfig->dns6_overrides); netconfig->dns6_overrides = NULL; } @@ -1038,8 +1038,6 @@ bool netconfig_configure(struct netconfig *netconfig, } netconfig->active_settings = active_settings; - netconfig->notify = notify; - netconfig->user_data = user_data; l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER, mac_address, ETH_ALEN); @@ -1051,6 +1049,8 @@ bool netconfig_configure(struct netconfig *netconfig, send_hostname = false; if (send_hostname) { + char hostname[HOST_NAME_MAX + 1]; + if (gethostname(hostname, sizeof(hostname)) == 0) { l_dhcp_client_set_hostname( netconfig->dhcp_client, hostname); @@ -1060,15 +1060,62 @@ bool netconfig_configure(struct netconfig *netconfig, } } - netconfig_ipv4_select_and_install(netconfig); - - netconfig_ipv6_select_and_install(netconfig); - mdns = l_settings_get_string(active_settings, "Network", "MulticastDNS"); resolve_set_mdns(netconfig->resolve, mdns); l_free(mdns); + if (l_settings_get_value(netconfig->active_settings, "IPv4", + "Address")) { + l_rtnl_address_free(netconfig->v4_address); + netconfig->v4_address = + netconfig_get_static4_address(netconfig); + + if (unlikely(!netconfig->v4_address)) { + l_error("netconfig: Can't parse IPv4 address"); + return false; + } + + netconfig->rtm_protocol = RTPROT_STATIC; + } else + netconfig->rtm_protocol = RTPROT_DHCP; + + if (!l_settings_get_bool(netconfig->active_settings, "IPv6", + "Enabled", &enabled)) + enabled = ipv6_enabled; + + if (!enabled) + netconfig->rtm_v6_protocol = RTPROT_UNSPEC; + else if (l_settings_get_value(netconfig->active_settings, "IPv6", + "Address")) { + __auto_type address = netconfig_get_static6_address(netconfig); + + l_rtnl_address_free(address); + + if (unlikely(!address)) { + l_error("netconfig: Can't parse IPv6 address"); + return false; + } + + netconfig->rtm_v6_protocol = RTPROT_STATIC; + } else + netconfig->rtm_v6_protocol = RTPROT_DHCP; + + return true; +} + +bool netconfig_configure(struct netconfig *netconfig, + netconfig_notify_func_t notify, void *user_data) +{ + netconfig->notify = notify; + netconfig->user_data = user_data; + + if (unlikely(!netconfig_ipv4_select_and_install(netconfig))) + return false; + + if (unlikely(!netconfig_ipv6_select_and_install(netconfig))) + return false; + return true; } diff --git a/src/netconfig.h b/src/netconfig.h index 2c68cb1c..73e4df8b 100644 --- a/src/netconfig.h +++ b/src/netconfig.h @@ -29,9 +29,10 @@ enum netconfig_event { typedef void (*netconfig_notify_func_t)(enum netconfig_event event, void *user_data); -bool netconfig_configure(struct netconfig *netconfig, +bool netconfig_load_settings(struct netconfig *netconfig, const struct l_settings *active_settings, - const uint8_t *mac_address, + const uint8_t *mac_address); +bool netconfig_configure(struct netconfig *netconfig, netconfig_notify_func_t notify, void *user_data); bool netconfig_reconfigure(struct netconfig *netconfig); diff --git a/src/p2p.c b/src/p2p.c index 8170bbe0..3328271b 100644 --- a/src/p2p.c +++ b/src/p2p.c @@ -1328,8 +1328,16 @@ static void p2p_start_client_netconfig(struct p2p_device *dev) } settings = dev->conn_netconfig_settings ?: p2p_dhcp_settings; - netconfig_configure(dev->conn_netconfig, settings, dev->conn_addr, - p2p_netconfig_event_handler, dev); + + if (!netconfig_load_settings(dev->conn_netconfig, settings, + dev->conn_addr) || + !netconfig_configure(dev->conn_netconfig, + p2p_netconfig_event_handler, + dev)) { + p2p_connect_failed(dev); + return; + } + dev->conn_dhcp_timeout = l_timeout_create(p2p_dhcp_timeout_val, p2p_dhcp_timeout, dev, p2p_dhcp_timeout_destroy); diff --git a/src/station.c b/src/station.c index d61e775a..f6237ade 100644 --- a/src/station.c +++ b/src/station.c @@ -2443,14 +2443,12 @@ static void station_connect_ok(struct station *station) network_connected(station->connected_network); - if (station->netconfig) - netconfig_configure(station->netconfig, - network_get_settings( - station->connected_network), - netdev_get_address(station->netdev), - station_netconfig_event_handler, - station); - else + if (station->netconfig) { + if (L_WARN_ON(!netconfig_configure(station->netconfig, + station_netconfig_event_handler, + station))) + return; + } else station_enter_state(station, STATION_STATE_CONNECTED); } @@ -2592,6 +2590,12 @@ int __station_connect_network(struct station *station, struct network *network, struct handshake_state *hs; int r; + if (station->netconfig && !netconfig_load_settings( + station->netconfig, + network_get_settings(network), + netdev_get_address(station->netdev))) + return -EINVAL; + hs = station_handshake_setup(station, network, bss); if (!hs) return -ENOTSUP; -- 2.30.2