Move the l_netconfig_set_route_priority() and
l_netconfig_set_optimistic_dad_enabled() calls from netconfig_new, which
is called once for the l_netconfig object's lifetime, to
netconfig_load_settings, which is called before every connection attempt.
This is needed because we clean up the l_netconfig configuration by calling
l_netconfig_reset_config() at different points in connection setup and
teardown so we'd reset the route priority that we've set in netconfig_new,
back to 0 and never reload it.
Adds the MulticastDNS option globally to main.conf. If set all
network connections (when netconfig is enabled) will set mDNS
support into the resolver. Note that an individual network profile
can still override the global value if it sets MulticastDNS.
Similarly to l_netconfig track whether IWD's netconfig is active (from
the moment of netconfig_configure() till netconfig_reset()) using a
"started" flag and avoid handling or emitting any events after "started"
is cleared.
This fixes an occasional issue with the Netconfig Agent backend where
station would reset netconfig, netconfig would issue DBus calls to clear
addresses and routes, station would go into DISCONNECTING, perhaps
finish and go into DISCONNECTED and after a while the DBus calls would
come back with an error which would cause a NETCONFIG_EVENT_FAILED
causing station to call netdev_disconnct() for a second time and
transition to and get stuck in DISCONNECTING.
Since l_netconfig's DHCPv6 client instance no longer sets parameters on
the l_icmp6_client instance, call l_icmp6_client_set_nodelay() and
l_icmp6_client_set_debug() directly. Also enable optimistic DAD to
speed up IPv6 setup if available.
Add netconfig_event_handler() that responds to events emitted by
the l_netconfig object by calling netconfig_commit, tracking whether
we're connected for either address family and emitting
NETCONFIG_EVENT_CONNECTED or NETCONFIG_EVENT_FAILED as necessary.
NETCONFIG_EVENT_FAILED is a new event as until now failures would cause
the netconfig state machine to stop but no event emitted so that
station.c could take action. As before, these events are only
emitted based on the IPv4 configuration state, not IPv6.
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.
To avoid repeated lookups by ifindex, replace the ifindex member in
struct netconfig with a struct netdev pointer. A struct netconfig
always lives shorter than the struct netdev.
* make the error handling simpler,
* make error messages more consistent,
* validate address families,
* for IPv4 skip l_rtnl_address_set_noprefixroute()
as l_netconfig will do this internally as needed.
* for IPv6 set the default prefix length to 64 as that's going to be
used for the local prefix route's prefix length and is a more
practical value.
Drop all the struct netconfig members where we were keeping the parsed
netconfig settings and add a struct l_netconfig object. In
netconfig_load_settings load all of the settings once parsed directly
into the l_netconfig object. Only preserve the mdns configuration and
save some boolean values needed to properly handle static configuration
and FILS. Update functions to use the new set of struct netconfig
members.
These booleans mirroring the l_netconfig state could be replaced by
adding l_netconfig getters for settings which currently only have
setters.
In anticipation of switching to use the l_netconfig API, which
internally handles DHCPv4, DHCPv6, ACD, etc., drop pointers to
instances of l_dhcp_client, l_dhcp6_client and l_acd from struct
netconfig. Also drop all code used for handling events from these
APIs, including code to commit the received configurations to the
system. Committing the final settings to the system netdevs is going to
be handled by a new set of utilities in a new file.
Drop the wrong negation in the error check. Check that there are no extra
characters after prefix length suffix. Reset errno 0 before the strtoul
call, as recommended by the manpage.
Allows granularly specifying the DHCP logging level. This allows the
user to tailor the output to what they need. By default, always display
info, errors and warnings to match the rest of iwd.
Setting `IWD_DHCP_DEBUG` to "debug", "info", "warn", "error" will limit
the logging to that level or higher allowing the default logging
verbosity to be reduced.
Setting `IWD_DHCP_DEBUG` to "1" as per the current behavior will
continue to enable debug level logging.
Cache the latest v4 and v6 domain string lists in struct netconfig state
to be able to more easily detect changes in those values in future
commits. For that split netconfig_set_domains's code into this function,
which now only commits the values in netconfig->v{4,6}_domain{,s} to the
resolver, and netconfig_domains_update() which figures out the active
domains string list and saves it into netconfig->v{4,6}_domain{,s}. This
probably saves some cycles as the callers can now decide to only
recalculate the domains list which may have changed.
While there simplify netconfig_set_domains return type to void as the
result was always 0 anyway and was never checked by callers.
Cache the latest v4 and v6 DNS IP string lists in struct netconfig state
to be able to more easily detect changes in those values in future
commits. For that split netconfig_set_dns's code into this function,
which now only commit the values in netconfig->dns{4,6}_list to the
resolver, and netconfig_dns_list_update() which figures out the active
DNS IP address list and saves it in netconfig->dns{4,6} list. This
probably saves some cycles as the callers can now decide to only
recalculate the dns_list which may have changed.
While there simplify netconfig_set_dns return type to void as the result
was always 0 anyway and was never checked by callers.
Cache the latest v4 and v6 gateway IP string in struct netconfig state
to be able to more easily detect changes in those values in future
commits and perhaps to simplify the ..._routes_install functions.
netconfig_ipv4_get_gateway's out_mac parameter can now be NULL. While
editing that function fix a small formatting annoyance.
Use a separate fils variable to make the code a bit prettier.
Also make sure that the out_mac parameter is not NULL prior to storing
the gateway_mac in it.
Add netconfig_enabled() and use that in all places that want to know
whether network configuration is enabled. Drop the enable_network_config
deprecated setting, which was only being handled in one of these 5 or so
places.
strcmp behavior is undefined if one of the parameters is NULL.
Server-id is a mandatory value and cannot be NULL. Gateway can be NULL
in DHCP, so check that explicitly.
Reported-by: Andrew Zaborowski <andrew.zaborowski@intel.com>
In certain situations, it is possible for us to know the MAC of the
default gateway when DHCP finishes. This is quite typical on many home
network and small network setups. It is thus possible to pre-populate
the ARP cache with the gateway MAC address to save an extra round trip
at connection time.
Another advantage is during roaming. After version 4.20, linux kernel
flushes ARP caches by default whenever netdev encounters a no carrier
condition (as is the case during roaming). This can prevent packets
from going out after a roam for a significant amount of time due to
lost/delayed ARP responses.
Make consecutive calls to netconfig_load_settings() memory-leak safe by
introducing a netconfig_free_settings convenience method. This method
will free any settings that are allocated as a result of
netconfig_load_settings() and will be called from netconfig_free() to
ensure that any settings are freed as a result of netconfig_destroy().
For symmetry with IPv4, save the command id for this netlink command so
we can later add logic to the callback as well as be able to cancel the
command. No functional change in this commit alone.
netconfig_load_settings is called when establishing a new initial
association to a network. This function tries to update dhcp/dhcpv6
clients with the MAC address of the netdev being used. However, it is
too early to update the MAC here since netdev might need to powercycle
the underlying network device in order to update the MAC (i.e. when
AddressRandomization="network" is used).
If the MAC is set incorrectly, DHCP clients are unable to obtain the
lease properly and station is stuck in "connecting" mode indefinitely.
Fix this by delaying MAC address update until netconfig_configure() is
invoked.
Fixes: ad228461ab ("netconfig: Move loading settings to new method, refactor")
in6_addr.__in6_u.__u6_addr8 is glibc-specific and named differently in
the headers shipped with musl libc for example. The POSIX compliant and
universal way of accessing it is in6_addr.s6_addr.
Refactor netconfig_set_dns to be a bit easier to follow and remove use
of macros. Also bail out early if no DNS addresses are provided instead
of building an empty DNS list since resolve_set_dns() simply returns if
a NULL or empty DNS list is provided.
In netconfig_load_settings apply the DNS overrides strings we've loaded
instead of leaking them.
Fixes: ad228461ab ("netconfig: Move loading settings to new method, refactor")
Use the MAC addresses for the gateways and DNS servers received in the
FILS IP Assigment IE together with the gateway IP and DNS server IP.
Commit the IP to MAC mappings directly to the ARP/NDP tables so that the
network stack can skip sending the corresponding queries over the air.
Add two methods that will allow station to implement FILS IP Address
Assigment, one method to decide whether to send the request during
association, and fill in the values to be used in the request IE, and
another to handle the response IE values received from the server and
apply them. The netconfig->rtm_protocol value used when the address is
assigned this way remains RTPROT_DHCP because from the user's point of
view this is automatic IP assigment by the server, a replacement for
DHCP.
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.
This is based on a previous patch by Roberto Santalla Fernández.
A new config is introduced into the network config file under IPv4
called SendHostname. If this is set to true then we add the hostname
into all DHCP requests. The default is false.
Don't require a gateway address from the settings file or from the DHCP
server when doing netconfig. Failing when the gateway address was
missing was breaking P2P but also small local networks.
It is possible that the address set command succeeds just after a
netconfig object has been destroyed.
==6485== Invalid read of size 8
==6485== at 0x458A6D: netconfig_ipv4_routes_install (netconfig.c:629)
==6485== by 0x458D1C: netconfig_ipv4_ifaddr_add_cmd_cb (netconfig.c:689)
==6485== by 0x4A5E7B: process_message (netlink.c:181)
==6485== by 0x4A626A: can_read_data (netlink.c:289)
==6485== by 0x4A3E19: io_callback (io.c:120)
==6485== by 0x4A27B5: l_main_iterate (main.c:478)
==6485== by 0x4A28F6: l_main_run (main.c:525)
==6485== by 0x4A2C0E: l_main_run_with_signal (main.c:647)
==6485== by 0x404D27: main (main.c:542)
==6485== Address 0x4a47290 is 32 bytes inside a block of size 104 free'd
==6485== at 0x48399CB: free (vg_replace_malloc.c:538)
==6485== by 0x49998B: l_free (util.c:136)
==6485== by 0x457699: netconfig_free (netconfig.c:130)
==6485== by 0x45A038: netconfig_destroy (netconfig.c:1163)
==6485== by 0x41FD16: station_free (station.c:3613)
==6485== by 0x42020E: station_destroy_interface (station.c:3710)
==6485== by 0x4B990E: interface_instance_free (dbus-service.c:510)
==6485== by 0x4BC193: _dbus_object_tree_remove_interface (dbus-service.c:1694)
==6485== by 0x4BA22A: _dbus_object_tree_object_destroy (dbus-service.c:795)
==6485== by 0x4B078D: l_dbus_unregister_object (dbus.c:1537)
==6485== by 0x417ACB: device_netdev_notify (device.c:361)
==6485== by 0x4062B6: netdev_free (netdev.c:808)
==6485== Block was alloc'd at
==6485== at 0x483879F: malloc (vg_replace_malloc.c:307)
==6485== by 0x499857: l_malloc (util.c:62)
==6485== by 0x459DC0: netconfig_new (netconfig.c:1115)
==6485== by 0x41FC29: station_create (station.c:3592)
==6485== by 0x4207B3: station_netdev_watch (station.c:3864)
==6485== by 0x411A17: netdev_initial_up_cb (netdev.c:5588)
==6485== by 0x4A5E7B: process_message (netlink.c:181)
==6485== by 0x4A626A: can_read_data (netlink.c:289)
==6485== by 0x4A3E19: io_callback (io.c:120)
==6485== by 0x4A27B5: l_main_iterate (main.c:478)
==6485== by 0x4A28F6: l_main_run (main.c:525)
==6485== by 0x4A2C0E: l_main_run_with_signal (main.c:647)
==6485==
==209== by 0x43E48A: netconfig_ipv4_select_and_install (netconfig.c:887)
==209== by 0x43E48A: netconfig_configure (netconfig.c:1025)
==209== by 0x41743C: station_connect_cb (station.c:2556)
==209== by 0x408E0D: netdev_connect_ok (netdev.c:1311)
==209== by 0x47549E: process_unicast (genl.c:994)
==209== by 0x47549E: received_data (genl.c:1102)
==209== by 0x4720EB: io_callback (io.c:120)
==209== by 0x47130C: l_main_iterate (main.c:478)
==209== by 0x4713DB: l_main_run (main.c:525)
==209== by 0x4713DB: l_main_run (main.c:507)
==209== by 0x4715EB: l_main_run_with_signal (main.c:647)
==209== by 0x403EE1: main (main.c:550)
It is possible for the RTNL command callback to come after
netconfig_reset or netconfig_destroy has been called. Make sure that
any outstanding commands that might access the netconfig object are
canceled.
src/netconfig.c:netconfig_ipv4_dhcp_event_handler() DHCPv4 event 0
src/netconfig.c:netconfig_ifaddr_added() wlan0: ifaddr 192.168.1.55/24 broadcast 192.168.1.255
^CTerminate
src/netdev.c:netdev_free() Freeing netdev wlan0[15]
src/device.c:device_free()
src/station.c:station_free()
src/netconfig.c:netconfig_destroy()
src/netconfig.c:netconfig_reset()
src/netconfig.c:netconfig_reset_v4() 16
src/netconfig.c:netconfig_reset_v4() Stopping client
Removing scan context for wdev c
src/scan.c:scan_context_free() sc: 0x4a3cc10
==12792== Invalid read of size 8
==12792== at 0x43BF5A: netconfig_route_add_cmd_cb (netconfig.c:600)
==12792== by 0x4727FA: process_message (netlink.c:181)
==12792== by 0x4727FA: can_read_data (netlink.c:289)
==12792== by 0x470F4B: io_callback (io.c:120)
==12792== by 0x47016C: l_main_iterate (main.c:478)
==12792== by 0x47023B: l_main_run (main.c:525)
==12792== by 0x47023B: l_main_run (main.c:507)
==12792== by 0x47044B: l_main_run_with_signal (main.c:647)
==12792== by 0x403EDB: main (main.c:490)
When using iwd.conf:[General].EnableNetworkConfiguration=true, it is not
possible to configure systemd.network:[Network].MulticastDNS= as
systemd-networkd considers the link to be unmanaged. This patch allows
iwd to configure that setting on systemd-resolved directly.