Skip to content

Commit 65a652f

Browse files
committed
CA-323523: Ensure that dhclients get restarted when gateway/DNS changes
Recent commit 75a4c5d changed the `options` argument to `Dhclient.write_conf_file`, but failed to update one of its callers, in `set_gateway_interface`. This meant that dhclient did not get restarted when necessary as a result of configuration changes. Rather than fixing the bad function call, this patch changes the code to be more robust. When starting a `dhclient` process for an interface that requires configuration by DHCP, the function `Dhclient.ensure_running` writes a configuration file to disk and passes its path to `dhclient` as a command line argument. The purpose of saving the configuration is to make `Dhclient.ensure_running` idempotent. When called, the function checks if a `dhclient` process is already running for the given interface, and if the last used configuration is identical to the newly requested one. If so, it leaves the process alone to cause minimal disturbance to the system. An interesting use case is changing the default gateway to another interface, and then back to the original interface (using `set_gateway_interface` and `Interface.make_config` twice). The first change properly updates the gateway, but the change back to the original interface doesn't end up restarting `dhclient` to switch the gateway back. This was addressed by rewriting the conf file of the gateway interface when changing it, in `set_gateway_interface` (see 637db58). Now, is seems wrong that `set_dns_interface`, which is a function with a very similar purpose to `set_gateway_interface`, does not rewrite conf files like `set_gateway_interface` does. Fixing that, however, could lead to the two functions interfering with each other. Therefore, rather than trying to update the conf file, we just delete it so that it will definitely be correctly regenerated later (and do this for both `set_*_interface` functions). Signed-off-by: Rob Hoes <[email protected]>
1 parent b547737 commit 65a652f

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

lib/network_utils.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,12 @@ module Dhclient = struct
759759
let conf = generate_conf ~ipv6 interface options in
760760
Xapi_stdext_unix.Unixext.write_string_to_file (conf_file ~ipv6 interface) conf
761761

762+
let remove_conf_file ?(ipv6=false) interface =
763+
let file = conf_file ~ipv6 interface in
764+
try
765+
Unix.unlink file
766+
with _ -> ()
767+
762768
let start ?(ipv6=false) interface options =
763769
(* If we have a gateway interface, pass it to dhclient-script via -e *)
764770
(* This prevents the default route being set erroneously on CentOS *)

networkd/network_server.ml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,23 +74,28 @@ let reset_state () =
7474
config := Network_config.read_management_conf ()
7575

7676
let set_gateway_interface _dbg name =
77-
(* Update dhclient conf for interface on changing default gateway.
78-
* If new default gateway is not same as gateway_interface from networkd.db then
79-
* we need to remove gateway information from gateway_interface *)
77+
(* Remove dhclient conf (if any) for the old and new gateway interfaces.
78+
* This ensures that dhclient gets restarted with an updated conf file when
79+
* necessary. *)
8080
begin match !config.gateway_interface with
81-
| Some gateway_iface when name <> gateway_iface ->
82-
let opts =
83-
match !config.dns_interface with
84-
| Some dns_iface when gateway_iface = dns_iface -> [`set_dns]
85-
| _ -> []
86-
in
87-
Dhclient.write_conf_file gateway_iface opts
81+
| Some old_iface when name <> old_iface ->
82+
Dhclient.remove_conf_file name;
83+
Dhclient.remove_conf_file old_iface
8884
| _ -> ()
8985
end;
9086
debug "Setting gateway interface to %s" name;
9187
config := {!config with gateway_interface = Some name}
9288

9389
let set_dns_interface _dbg name =
90+
(* Remove dhclient conf (if any) for the old and new DNS interfaces.
91+
* This ensures that dhclient gets restarted with an updated conf file when
92+
* necessary. *)
93+
begin match !config.dns_interface with
94+
| Some old_iface when name <> old_iface ->
95+
Dhclient.remove_conf_file name;
96+
Dhclient.remove_conf_file old_iface
97+
| _ -> ()
98+
end;
9499
debug "Setting DNS interface to %s" name;
95100
config := {!config with dns_interface = Some name}
96101

0 commit comments

Comments
 (0)