summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2009-07-15 13:53:49 -0400
committerDan Williams <dcbw@redhat.com>2009-07-15 13:53:49 -0400
commit3fe8d0eed4c1e2b4c4c2d4454e5ec68d2272d2c3 (patch)
treeef648d663a558a7e42eaa05eface6719d2b3d398
parent0f56957b77b0d86cf4cae3141e70f777cfc8847f (diff)
core: allow devices to specify a DHCP anycast address
Relevant only for OLPC at this point; the mesh device uses it to target DHCP requests at a pre-defined mesh portal anycast address.
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient.c23
-rw-r--r--src/dhcp-manager/nm-dhcp-dhcpcd.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-manager.c5
-rw-r--r--src/dhcp-manager/nm-dhcp-manager.h6
-rw-r--r--src/nm-device.c33
-rw-r--r--src/nm-device.h1
6 files changed, 59 insertions, 12 deletions
diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c
index e8ce4960e6..f35465976b 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient.c
@@ -83,12 +83,13 @@ get_leasefile_for_iface (const char * iface, const char *uuid)
#define DHCP_HOSTNAME_TAG "send host-name"
#define DHCP_HOSTNAME_FORMAT DHCP_HOSTNAME_TAG " \"%s\"; # added by NetworkManager"
static gboolean
merge_dhclient_config (NMDHCPDevice *device,
NMSettingIP4Config *s_ip4,
+ guint8 *anycast_addr,
const char *contents,
const char *orig,
GError **error)
{
GString *new_contents;
gboolean success = FALSE;
@@ -161,12 +162,23 @@ merge_dhclient_config (NMDHCPDevice *device,
tmp = nm_setting_ip4_config_get_dhcp_hostname (s_ip4);
if (tmp)
g_string_append_printf (new_contents, DHCP_HOSTNAME_FORMAT "\n", tmp);
}
+ if (anycast_addr) {
+ g_string_append_printf (new_contents, "interface \"%s\" {\n"
+ " initial-interval 1; \n"
+ " anycast-mac ethernet %02x:%02x:%02x:%02x:%02x:%02x;\n"
+ "}\n",
+ device->iface,
+ anycast_addr[0], anycast_addr[1],
+ anycast_addr[2], anycast_addr[3],
+ anycast_addr[4], anycast_addr[5]);
+ }
+
if (g_file_set_contents (device->conf_file, new_contents->str, -1, error))
success = TRUE;
g_string_free (new_contents, TRUE);
return success;
}
@@ -175,13 +187,15 @@ merge_dhclient_config (NMDHCPDevice *device,
* file cannot be used since DHCP transactions can happen in parallel.
* Since some distros don't have default per-interface dhclient config files,
* read their single config file and merge that into a custom per-interface
* config file along with the NM options.
*/
static gboolean
-create_dhclient_config (NMDHCPDevice *device, NMSettingIP4Config *s_ip4)
+create_dhclient_config (NMDHCPDevice *device,
+ NMSettingIP4Config *s_ip4,
+ guint8 *dhcp_anycast_addr)
{
char *orig = NULL, *contents = NULL;
GError *error = NULL;
gboolean success = FALSE;
char *tmp;
@@ -215,13 +229,13 @@ create_dhclient_config (NMDHCPDevice *device, NMSettingIP4Config *s_ip4)
g_error_free (error);
goto out;
}
out:
error = NULL;
- if (merge_dhclient_config (device, s_ip4, contents, orig, &error))
+ if (merge_dhclient_config (device, s_ip4, dhcp_anycast_addr, contents, orig, &error))
success = TRUE;
else {
nm_warning ("%s: error creating dhclient configuration: %s",
device->iface, error->message);
g_error_free (error);
}
@@ -241,13 +255,14 @@ dhclient_child_setup (gpointer user_data G_GNUC_UNUSED)
}
GPid
nm_dhcp_client_start (NMDHCPDevice *device,
const char *uuid,
- NMSettingIP4Config *s_ip4)
+ NMSettingIP4Config *s_ip4,
+ guint8 *dhcp_anycast_addr)
{
GPtrArray *dhclient_argv = NULL;
GPid pid = 0;
GError *error = NULL;
char *pid_contents = NULL;
@@ -265,13 +280,13 @@ nm_dhcp_client_start (NMDHCPDevice *device,
device->lease_file = get_leasefile_for_iface (device->iface, uuid);
if (!device->lease_file) {
nm_warning ("%s: not enough memory for dhclient options.", device->iface);
goto out;
}
- if (!create_dhclient_config (device, s_ip4))
+ if (!create_dhclient_config (device, s_ip4, dhcp_anycast_addr))
goto out;
/* Kill any existing dhclient bound to this interface */
if (g_file_get_contents (device->pid_file, &pid_contents, NULL, NULL)) {
unsigned long int tmp = strtoul (pid_contents, NULL, 10);
diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c
index 05db9dd16f..a6ce8d21e6 100644
--- a/src/dhcp-manager/nm-dhcp-dhcpcd.c
+++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c
@@ -59,13 +59,14 @@ dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED)
}
GPid
nm_dhcp_client_start (NMDHCPDevice *device,
const char *uuid,
- NMSettingIP4Config *s_ip4)
+ NMSettingIP4Config *s_ip4,
+ guint8 *dhcp_anycast_addr)
{
GPtrArray *argv = NULL;
GPid pid = 0;
GError *error = NULL;
char *pid_contents = NULL;
diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c
index 22368b9677..bdd2695b2a 100644
--- a/src/dhcp-manager/nm-dhcp-manager.c
+++ b/src/dhcp-manager/nm-dhcp-manager.c
@@ -584,13 +584,14 @@ static void dhcp_watch_cb (GPid pid, gint status, gpointer user_data)
gboolean
nm_dhcp_manager_begin_transaction (NMDHCPManager *manager,
const char *iface,
const char *uuid,
NMSettingIP4Config *s_ip4,
- guint32 timeout)
+ guint32 timeout,
+ guint8 *dhcp_anycast_addr)
{
NMDHCPManagerPrivate *priv;
NMDHCPDevice *device;
NMSettingIP4Config *setting;
g_return_val_if_fail (NM_IS_DHCP_MANAGER (manager), FALSE);
@@ -626,13 +627,13 @@ nm_dhcp_manager_begin_transaction (NMDHCPManager *manager,
if (timeout == 0)
timeout = NM_DHCP_TIMEOUT;
nm_info ("Activation (%s) Beginning DHCP transaction (timeout in %d seconds)",
iface, timeout);
- device->pid = nm_dhcp_client_start (device, uuid, setting);
+ device->pid = nm_dhcp_client_start (device, uuid, setting, dhcp_anycast_addr);
if (setting)
g_object_unref (setting);
if (device->pid == 0)
return FALSE;
diff --git a/src/dhcp-manager/nm-dhcp-manager.h b/src/dhcp-manager/nm-dhcp-manager.h
index f8737cbff0..6880a2336c 100644
--- a/src/dhcp-manager/nm-dhcp-manager.h
+++ b/src/dhcp-manager/nm-dhcp-manager.h
@@ -92,13 +92,14 @@ void nm_dhcp_manager_set_hostname_provider(NMDHCPManager *manager,
NMHostnameProvider *provider);
gboolean nm_dhcp_manager_begin_transaction (NMDHCPManager *manager,
const char *iface,
const char *uuid,
NMSettingIP4Config *s_ip4,
- guint32 timeout);
+ guint32 timeout,
+ guint8 *dhcp_anycast_addr);
void nm_dhcp_manager_cancel_transaction (NMDHCPManager *manager,
const char *iface);
NMIP4Config * nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, const char *iface);
NMDHCPState nm_dhcp_manager_get_state_for_device (NMDHCPManager *manager, const char *iface);
gboolean nm_dhcp_manager_foreach_dhcp4_option (NMDHCPManager *self,
@@ -106,13 +107,14 @@ gboolean nm_dhcp_manager_foreach_dhcp4_option (NMDHCPManager *self,
GHFunc func,
gpointer user_data);
/* The following are implemented by the DHCP client backends */
GPid nm_dhcp_client_start (NMDHCPDevice *device,
const char *uuid,
- NMSettingIP4Config *s_ip4);
+ NMSettingIP4Config *s_ip4,
+ guint8 *anycast_addr);
void nm_dhcp_client_stop (NMDHCPDevice *device, pid_t pid);
gboolean nm_dhcp_client_process_classless_routes (GHashTable *options,
NMIP4Config *ip4_config,
guint32 *gwaddr);
diff --git a/src/nm-device.c b/src/nm-device.c
index 401d529af6..db71eaea1d 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -89,12 +89,13 @@ typedef struct {
/* IP configuration info */
NMIP4Config * ip4_config; /* Config from DHCP, PPP, or system config files */
NMDHCPManager * dhcp_manager;
guint32 dhcp_timeout;
gulong dhcp_state_sigid;
gulong dhcp_timeout_sigid;
+ GByteArray * dhcp_anycast_address;
NMDHCP4Config * dhcp4_config;
/* dnsmasq stuff for shared connections */
NMDnsMasqManager *dnsmasq_manager;
gulong dnsmasq_state_id;
@@ -891,20 +892,24 @@ real_act_stage3_ip_config_start (NMDevice *self, NMDeviceStateReason *reason)
if (s_ip4)
method = nm_setting_ip4_config_get_method (s_ip4);
if (!s_ip4 || !method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean success;
+ guint8 *anycast = NULL;
+
+ if (priv->dhcp_anycast_address)
+ anycast = priv->dhcp_anycast_address->data;
/* Begin a DHCP transaction on the interface */
nm_device_set_use_dhcp (self, TRUE);
/* DHCP manager will cancel any transaction already in progress and we do not
want to cancel this activation if we get "down" state from that. */
g_signal_handler_block (priv->dhcp_manager, priv->dhcp_state_sigid);
- success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager, ip_iface, uuid, s_ip4, priv->dhcp_timeout);
+ success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager, ip_iface, uuid, s_ip4, priv->dhcp_timeout, anycast);
g_signal_handler_unblock (priv->dhcp_manager, priv->dhcp_state_sigid);
if (success) {
/* DHCP devices will be notified by the DHCP manager when
* stuff happens.
*/
@@ -2215,12 +2220,14 @@ finalize (GObject *object)
g_free (priv->udi);
g_free (priv->iface);
g_free (priv->ip_iface);
g_free (priv->driver);
g_free (priv->type_desc);
+ if (priv->dhcp_anycast_address)
+ g_byte_array_free (priv->dhcp_anycast_address, TRUE);
G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
}
static void
@@ -2536,14 +2543,34 @@ nm_device_spec_match_list (NMDeviceInterface *device, const GSList *specs)
return NM_DEVICE_GET_CLASS (self)->spec_match_list (self, specs);
return FALSE;
}
void
-nm_device_set_dhcp_timeout (NMDevice *device,
- guint32 timeout)
+nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout)
{
g_return_if_fail (NM_IS_DEVICE (device));
NM_DEVICE_GET_PRIVATE (device)->dhcp_timeout = timeout;
}
+void
+nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr)
+{
+ NMDevicePrivate *priv;
+
+ g_return_if_fail (NM_IS_DEVICE (device));
+
+ priv = NM_DEVICE_GET_PRIVATE (device);
+
+ if (priv->dhcp_anycast_address) {
+ g_byte_array_free (priv->dhcp_anycast_address, TRUE);
+ priv->dhcp_anycast_address = NULL;
+ }
+
+ if (addr) {
+ priv->dhcp_anycast_address = g_byte_array_sized_new (ETH_ALEN);
+ g_byte_array_append (priv->dhcp_anycast_address, addr, ETH_ALEN);
+ }
+}
+
+
diff --git a/src/nm-device.h b/src/nm-device.h
index 39003938a8..45a3f9efcb 100644
--- a/src/nm-device.h
+++ b/src/nm-device.h
@@ -160,10 +160,11 @@ NMDeviceState nm_device_get_state (NMDevice *device);
gboolean nm_device_get_managed (NMDevice *device);
void nm_device_set_managed (NMDevice *device,
gboolean managed,
NMDeviceStateReason reason);
void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout);
+void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr);
G_END_DECLS
#endif /* NM_DEVICE_H */