mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-06 01:30:16 +01:00
dhcp: add DHCP lease release capability
This commit is contained in:
parent
6ae91e2f67
commit
9917da2c71
7 changed files with 123 additions and 62 deletions
|
|
@ -136,10 +136,10 @@ watch_cleanup (NMDHCPClient *self)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_process (GPid pid, const char *iface)
|
||||
void
|
||||
nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs)
|
||||
{
|
||||
int i = 15; /* 3 seconds */
|
||||
int i = (timeout_secs ? timeout_secs : 3) * 5; /* default 3 seconds */
|
||||
|
||||
g_return_if_fail (pid > 0);
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ stop_process (GPid pid, const char *iface)
|
|||
}
|
||||
|
||||
static void
|
||||
real_stop (NMDHCPClient *self)
|
||||
real_stop (NMDHCPClient *self, gboolean release)
|
||||
{
|
||||
NMDHCPClientPrivate *priv;
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ real_stop (NMDHCPClient *self)
|
|||
/* Clean up the watch handler since we're explicitly killing the daemon */
|
||||
watch_cleanup (self);
|
||||
|
||||
stop_process (priv->pid, priv->iface);
|
||||
nm_dhcp_client_stop_pid (priv->pid, priv->iface, 0);
|
||||
|
||||
priv->info_only = FALSE;
|
||||
}
|
||||
|
|
@ -376,7 +376,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name)
|
|||
exe = proc_contents;
|
||||
|
||||
if (!strcmp (exe, binary_name))
|
||||
stop_process ((GPid) tmp, NULL);
|
||||
nm_dhcp_client_stop_pid ((GPid) tmp, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name)
|
|||
}
|
||||
|
||||
void
|
||||
nm_dhcp_client_stop (NMDHCPClient *self)
|
||||
nm_dhcp_client_stop (NMDHCPClient *self, gboolean release)
|
||||
{
|
||||
NMDHCPClientPrivate *priv;
|
||||
|
||||
|
|
@ -398,7 +398,7 @@ nm_dhcp_client_stop (NMDHCPClient *self)
|
|||
|
||||
/* Kill the DHCP client */
|
||||
if (!priv->dead) {
|
||||
NM_DHCP_CLIENT_GET_CLASS (self)->stop (self);
|
||||
NM_DHCP_CLIENT_GET_CLASS (self)->stop (self, release);
|
||||
priv->dead = TRUE;
|
||||
|
||||
nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction, DHCP client pid %d",
|
||||
|
|
|
|||
|
|
@ -76,18 +76,19 @@ typedef struct {
|
|||
|
||||
/* Methods */
|
||||
|
||||
GPid (*ip4_start) (NMDHCPClient *self,
|
||||
NMSettingIP4Config *s_ip4,
|
||||
guint8 *anycast_addr,
|
||||
const char *hostname);
|
||||
GPid (*ip4_start) (NMDHCPClient *self,
|
||||
NMSettingIP4Config *s_ip4,
|
||||
guint8 *anycast_addr,
|
||||
const char *hostname);
|
||||
|
||||
GPid (*ip6_start) (NMDHCPClient *self,
|
||||
NMSettingIP6Config *s_ip6,
|
||||
guint8 *anycast_addr,
|
||||
const char *hostname,
|
||||
gboolean info_only);
|
||||
GPid (*ip6_start) (NMDHCPClient *self,
|
||||
NMSettingIP6Config *s_ip6,
|
||||
guint8 *anycast_addr,
|
||||
const char *hostname,
|
||||
gboolean info_only);
|
||||
|
||||
void (*stop) (NMDHCPClient *self);
|
||||
void (*stop) (NMDHCPClient *self,
|
||||
gboolean release);
|
||||
|
||||
/* Signals */
|
||||
void (*state_changed) (NMDHCPClient *self, NMDHCPState state);
|
||||
|
|
@ -116,7 +117,7 @@ gboolean nm_dhcp_client_start_ip6 (NMDHCPClient *self,
|
|||
const char *hostname,
|
||||
gboolean info_only);
|
||||
|
||||
void nm_dhcp_client_stop (NMDHCPClient *self);
|
||||
void nm_dhcp_client_stop (NMDHCPClient *self, gboolean release);
|
||||
|
||||
void nm_dhcp_client_new_options (NMDHCPClient *self,
|
||||
GHashTable *options,
|
||||
|
|
@ -133,5 +134,7 @@ NMIP6Config *nm_dhcp_client_get_ip6_config (NMDHCPClient *self, gboolean test)
|
|||
/* Backend helpers */
|
||||
void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name);
|
||||
|
||||
void nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs);
|
||||
|
||||
#endif /* NM_DHCP_CLIENT_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -411,15 +411,15 @@ dhclient_child_setup (gpointer user_data G_GNUC_UNUSED)
|
|||
|
||||
static GPid
|
||||
dhclient_start (NMDHCPClient *client,
|
||||
const char *ip_opt,
|
||||
const char *mode_opt)
|
||||
const char *mode_opt,
|
||||
gboolean release)
|
||||
{
|
||||
NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client);
|
||||
GPtrArray *argv = NULL;
|
||||
GPid pid = -1;
|
||||
GError *error = NULL;
|
||||
const char *iface, *uuid;
|
||||
char *binary_name, *cmd_str;
|
||||
char *binary_name, *cmd_str, *pid_file = NULL;
|
||||
gboolean ipv6;
|
||||
guint log_domain;
|
||||
|
||||
|
|
@ -436,28 +436,33 @@ dhclient_start (NMDHCPClient *client,
|
|||
nm_log_warn (log_domain, "(%s): ISC dhcp3 does not support IPv6", iface);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
g_return_val_if_fail (ip_opt != NULL, -1);
|
||||
#endif
|
||||
|
||||
priv->pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid",
|
||||
ipv6 ? "6" : "",
|
||||
iface);
|
||||
if (!priv->pid_file) {
|
||||
nm_log_warn (log_domain, "(%s): not enough memory for dhcpcd options.", iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) {
|
||||
nm_log_warn (log_domain, "%s does not exist.", priv->path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid",
|
||||
ipv6 ? "6" : "",
|
||||
iface);
|
||||
if (!pid_file) {
|
||||
nm_log_warn (log_domain, "(%s): not enough memory for dhcpcd options.", iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Kill any existing dhclient from the pidfile */
|
||||
binary_name = g_path_get_basename (priv->path);
|
||||
nm_dhcp_client_stop_existing (priv->pid_file, binary_name);
|
||||
nm_dhcp_client_stop_existing (pid_file, binary_name);
|
||||
g_free (binary_name);
|
||||
|
||||
if (release) {
|
||||
/* release doesn't use the pidfile after killing an old client */
|
||||
g_free (pid_file);
|
||||
pid_file = NULL;
|
||||
}
|
||||
|
||||
g_free (priv->lease_file);
|
||||
priv->lease_file = get_leasefile_for_iface (iface, uuid, ipv6);
|
||||
if (!priv->lease_file) {
|
||||
nm_log_warn (log_domain, "(%s): not enough memory for dhclient options.", iface);
|
||||
|
|
@ -469,17 +474,26 @@ dhclient_start (NMDHCPClient *client,
|
|||
|
||||
g_ptr_array_add (argv, (gpointer) "-d");
|
||||
|
||||
if (release)
|
||||
g_ptr_array_add (argv, (gpointer) "-r");
|
||||
|
||||
#if !defined(DHCLIENT_V3)
|
||||
g_ptr_array_add (argv, (gpointer) ip_opt);
|
||||
if (mode_opt)
|
||||
g_ptr_array_add (argv, (gpointer) mode_opt);
|
||||
if (ipv6) {
|
||||
g_ptr_array_add (argv, (gpointer) "-6");
|
||||
if (mode_opt)
|
||||
g_ptr_array_add (argv, (gpointer) mode_opt);
|
||||
} else {
|
||||
g_ptr_array_add (argv, (gpointer) "-4");
|
||||
}
|
||||
#endif
|
||||
|
||||
g_ptr_array_add (argv, (gpointer) "-sf"); /* Set script file */
|
||||
g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH );
|
||||
|
||||
g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */
|
||||
g_ptr_array_add (argv, (gpointer) priv->pid_file);
|
||||
if (pid_file) {
|
||||
g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */
|
||||
g_ptr_array_add (argv, (gpointer) pid_file);
|
||||
}
|
||||
|
||||
g_ptr_array_add (argv, (gpointer) "-lf"); /* Set lease file */
|
||||
g_ptr_array_add (argv, (gpointer) priv->lease_file);
|
||||
|
|
@ -501,8 +515,10 @@ dhclient_start (NMDHCPClient *client,
|
|||
nm_log_warn (log_domain, "dhclient failed to start: '%s'", error->message);
|
||||
g_error_free (error);
|
||||
pid = -1;
|
||||
} else
|
||||
} else {
|
||||
nm_log_info (log_domain, "dhclient started with pid %d", pid);
|
||||
priv->pid_file = pid_file;
|
||||
}
|
||||
|
||||
g_ptr_array_free (argv, TRUE);
|
||||
return pid;
|
||||
|
|
@ -525,7 +541,7 @@ real_ip4_start (NMDHCPClient *client,
|
|||
return -1;
|
||||
}
|
||||
|
||||
return dhclient_start (client, "-4", NULL);
|
||||
return dhclient_start (client, NULL, FALSE);
|
||||
}
|
||||
|
||||
static GPid
|
||||
|
|
@ -535,21 +551,34 @@ real_ip6_start (NMDHCPClient *client,
|
|||
const char *hostname,
|
||||
gboolean info_only)
|
||||
{
|
||||
return dhclient_start (client, "-6", info_only ? "-S" : "-N");
|
||||
return dhclient_start (client, info_only ? "-S" : "-N", FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
real_stop (NMDHCPClient *client)
|
||||
real_stop (NMDHCPClient *client, gboolean release)
|
||||
{
|
||||
NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client);
|
||||
|
||||
/* Chain up to parent */
|
||||
NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client);
|
||||
NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client, release);
|
||||
|
||||
if (priv->conf_file)
|
||||
remove (priv->conf_file);
|
||||
if (priv->pid_file)
|
||||
if (priv->pid_file) {
|
||||
remove (priv->pid_file);
|
||||
g_free (priv->pid_file);
|
||||
priv->pid_file = NULL;
|
||||
}
|
||||
|
||||
if (release) {
|
||||
GPid rpid;
|
||||
|
||||
rpid = dhclient_start (client, NULL, TRUE);
|
||||
if (rpid > 0) {
|
||||
/* Wait a few seconds for the release to happen */
|
||||
nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client), 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
|
|
|||
|
|
@ -170,15 +170,17 @@ real_ip6_start (NMDHCPClient *client,
|
|||
}
|
||||
|
||||
static void
|
||||
real_stop (NMDHCPClient *client)
|
||||
real_stop (NMDHCPClient *client, gboolean release)
|
||||
{
|
||||
NMDHCPDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client);
|
||||
|
||||
/* Chain up to parent */
|
||||
NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client);
|
||||
NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client, release);
|
||||
|
||||
if (priv->pid_file)
|
||||
remove (priv->pid_file);
|
||||
|
||||
/* FIXME: implement release... */
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ client_start (NMDHCPManager *self,
|
|||
/* Kill any old client instance */
|
||||
client = get_client_for_iface (self, iface, ipv6);
|
||||
if (client) {
|
||||
nm_dhcp_client_stop (client);
|
||||
nm_dhcp_client_stop (client, FALSE);
|
||||
remove_client (self, client);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,8 +184,8 @@ static NMActStageReturn dhcp6_start (NMDevice *self,
|
|||
NMDeviceStateReason *reason);
|
||||
|
||||
static void addrconf6_cleanup (NMDevice *self);
|
||||
static void dhcp6_cleanup (NMDevice *self, gboolean stop);
|
||||
static void dhcp4_cleanup (NMDevice *self, gboolean stop);
|
||||
static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release);
|
||||
static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release);
|
||||
|
||||
|
||||
static void
|
||||
|
|
@ -1467,7 +1467,7 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data)
|
|||
if (!nm_device_get_act_request (device))
|
||||
return;
|
||||
|
||||
nm_dhcp_client_stop (client);
|
||||
nm_dhcp_client_stop (client, FALSE);
|
||||
|
||||
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) {
|
||||
if (nm_dhcp_client_get_ipv6 (client))
|
||||
|
|
@ -1480,17 +1480,16 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data)
|
|||
static NMActStageReturn
|
||||
dhcp4_start (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
NMSettingIP4Config *s_ip4,
|
||||
NMDeviceStateReason *reason)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
guint8 *anycast = NULL;
|
||||
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
|
||||
g_assert (s_con);
|
||||
|
||||
/* Begin a DHCP transaction on the interface */
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
|
||||
if (priv->dhcp_anycast_address)
|
||||
anycast = priv->dhcp_anycast_address->data;
|
||||
|
|
@ -1500,6 +1499,7 @@ dhcp4_start (NMDevice *self,
|
|||
g_object_unref (priv->dhcp4_config);
|
||||
priv->dhcp4_config = nm_dhcp4_config_new ();
|
||||
|
||||
/* Begin DHCP on the interface */
|
||||
g_warn_if_fail (priv->dhcp4_client == NULL);
|
||||
priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager,
|
||||
nm_device_get_ip_iface (self),
|
||||
|
|
@ -1525,6 +1525,31 @@ dhcp4_start (NMDevice *self,
|
|||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_device_dhcp4_renew (NMDevice *self, gboolean release)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMActStageReturn ret;
|
||||
NMDeviceStateReason reason;
|
||||
NMActRequest *req;
|
||||
NMConnection *connection;
|
||||
|
||||
g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE);
|
||||
|
||||
/* Terminate old DHCP instance and release the old lease */
|
||||
dhcp4_cleanup (self, TRUE, TRUE);
|
||||
|
||||
req = nm_device_get_act_request (self);
|
||||
g_assert (req);
|
||||
connection = nm_act_request_get_connection (req);
|
||||
g_assert (connection);
|
||||
|
||||
/* Start DHCP again on the interface */
|
||||
ret = dhcp4_start (self, connection, &reason);
|
||||
|
||||
return (ret != NM_ACT_STAGE_RETURN_FAILURE);
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
|
||||
{
|
||||
|
|
@ -1554,7 +1579,7 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
|
|||
method = nm_setting_ip4_config_get_method (s_ip4);
|
||||
|
||||
if (!s_ip4 || !method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
|
||||
ret = dhcp4_start (self, connection, s_ip4, reason);
|
||||
ret = dhcp4_start (self, connection, reason);
|
||||
} else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
GError *error = NULL;
|
||||
const char *iface = nm_device_get_iface (self);
|
||||
|
|
@ -2675,7 +2700,7 @@ delayed_transitions_clear (NMDevice *self)
|
|||
}
|
||||
|
||||
static void
|
||||
dhcp4_cleanup (NMDevice *self, gboolean stop)
|
||||
dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
|
|
@ -2698,7 +2723,7 @@ dhcp4_cleanup (NMDevice *self, gboolean stop)
|
|||
}
|
||||
|
||||
if (stop)
|
||||
nm_dhcp_client_stop (priv->dhcp4_client);
|
||||
nm_dhcp_client_stop (priv->dhcp4_client, release);
|
||||
|
||||
g_object_unref (priv->dhcp4_client);
|
||||
priv->dhcp4_client = NULL;
|
||||
|
|
@ -2706,7 +2731,7 @@ dhcp4_cleanup (NMDevice *self, gboolean stop)
|
|||
}
|
||||
|
||||
static void
|
||||
dhcp6_cleanup (NMDevice *self, gboolean stop)
|
||||
dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
|
|
@ -2730,7 +2755,7 @@ dhcp6_cleanup (NMDevice *self, gboolean stop)
|
|||
}
|
||||
|
||||
if (stop)
|
||||
nm_dhcp_client_stop (priv->dhcp6_client);
|
||||
nm_dhcp_client_stop (priv->dhcp6_client, release);
|
||||
|
||||
g_object_unref (priv->dhcp6_client);
|
||||
priv->dhcp6_client = NULL;
|
||||
|
|
@ -2779,8 +2804,8 @@ nm_device_deactivate_quickly (NMDevice *self)
|
|||
/* Clear any delayed transitions */
|
||||
delayed_transitions_clear (self);
|
||||
|
||||
dhcp4_cleanup (self, TRUE);
|
||||
dhcp6_cleanup (self, TRUE);
|
||||
dhcp4_cleanup (self, TRUE, FALSE);
|
||||
dhcp6_cleanup (self, TRUE, FALSE);
|
||||
addrconf6_cleanup (self);
|
||||
dnsmasq_cleanup (self);
|
||||
aipd_cleanup (self);
|
||||
|
|
@ -3357,8 +3382,8 @@ dispose (GObject *object)
|
|||
delayed_transitions_clear (self);
|
||||
|
||||
/* Clean up and stop DHCP */
|
||||
dhcp4_cleanup (self, take_down);
|
||||
dhcp6_cleanup (self, take_down);
|
||||
dhcp4_cleanup (self, take_down, FALSE);
|
||||
dhcp6_cleanup (self, take_down, FALSE);
|
||||
addrconf6_cleanup (self);
|
||||
dnsmasq_cleanup (self);
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,8 @@ void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr);
|
|||
|
||||
void nm_device_clear_autoconnect_inhibit (NMDevice *device);
|
||||
|
||||
gboolean nm_device_dhcp4_renew (NMDevice *device, gboolean release);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_DEVICE_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue