diff --git a/ChangeLog b/ChangeLog index 8170c30519..4b28ca8098 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2008-06-09 Dan Williams + + * src/dnsmasq-manager/nm-dnsmasq-manager.c + src/dnsmasq-manager/nm-dnsmasq-manager.h + - (create_dm_cmd_line): use the IP4 address of the ip4-config to + calculate the addresses passed to dnsmasq instead of hard-coding + them + + * src/nm-device.c + - (nm_device_new_ip4_shared_config): be somewhat dynamic when choosing + IP addresses for shared connections to guard against shared + connection address collisions + - (real_act_stage4_get_ip4_config): handle possible NULL ip4-configs on + error conditions + - (nm_device_activate_stage5_ip_config_commit): pass ip4-config to + the dnsmasq manager + 2008-06-09 Dan Williams * src/NetworkManagerPolicy.c diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c index 3229a81072..bb69d114b4 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.c +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c @@ -225,11 +225,17 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data) } static NMCmdLine * -create_dm_cmd_line (const char *iface, const char *pidfile, GError **error) +create_dm_cmd_line (const char *iface, + NMIP4Config *ip4_config, + const char *pidfile, + GError **error) { const char *dm_binary; NMCmdLine *cmd; - char *s; + GString *s; + const NMSettingIP4Address *tmp; + struct in_addr addr; + char buf[INET_ADDRSTRLEN + 1]; dm_binary = nm_find_dnsmasq (); if (!dm_binary) { @@ -238,24 +244,68 @@ create_dm_cmd_line (const char *iface, const char *pidfile, GError **error) return NULL; } + /* Find the IP4 address to use */ + tmp = nm_ip4_config_get_address (ip4_config, 0); + /* Create dnsmasq command line */ cmd = nm_cmd_line_new (); nm_cmd_line_add_string (cmd, dm_binary); nm_cmd_line_add_string (cmd, "--no-hosts"); nm_cmd_line_add_string (cmd, "--keep-in-foreground"); - nm_cmd_line_add_string (cmd, "--listen-address=10.42.43.1"); nm_cmd_line_add_string (cmd, "--bind-interfaces"); nm_cmd_line_add_string (cmd, "--no-poll"); - nm_cmd_line_add_string (cmd, "--dhcp-range=10.42.43.10,10.42.43.100,60m"); + + s = g_string_new ("--listen-address="); + addr.s_addr = tmp->address; + if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) { + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + goto error; + } + g_string_append (s, buf); + nm_cmd_line_add_string (cmd, s->str); + g_string_free (s, TRUE); + + s = g_string_new ("--dhcp-range="); + + /* Add start of address range */ + addr.s_addr = tmp->address + ntohl (9); + if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) { + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + goto error; + } + g_string_append (s, buf); + + g_string_append_c (s, ','); + + /* Add end of address range */ + addr.s_addr = tmp->address + ntohl (99); + if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) { + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + goto error; + } + g_string_append (s, buf); + + g_string_append (s, ",60m"); + nm_cmd_line_add_string (cmd, s->str); + g_string_free (s, TRUE); + nm_cmd_line_add_string (cmd, "--dhcp-option=option:router,0.0.0.0"); nm_cmd_line_add_string (cmd, "--dhcp-lease-max=50"); - s = g_strdup_printf ("--pid-file=%s", pidfile); - nm_cmd_line_add_string (cmd, s); - g_free (s); + s = g_string_new ("--pid-file="); + g_string_append (s, pidfile); + nm_cmd_line_add_string (cmd, s->str); + g_string_free (s, TRUE); return cmd; + +error: + nm_cmd_line_destroy (cmd); + return NULL; } static void @@ -300,7 +350,9 @@ out: } gboolean -nm_dnsmasq_manager_start (NMDnsMasqManager *manager, GError **error) +nm_dnsmasq_manager_start (NMDnsMasqManager *manager, + NMIP4Config *ip4_config, + GError **error) { NMDnsMasqManagerPrivate *priv; NMCmdLine *dm_cmd; @@ -315,7 +367,7 @@ nm_dnsmasq_manager_start (NMDnsMasqManager *manager, GError **error) kill_existing_for_iface (priv->iface, priv->pidfile); - dm_cmd = create_dm_cmd_line (priv->iface, priv->pidfile, error); + dm_cmd = create_dm_cmd_line (priv->iface, ip4_config, priv->pidfile, error); if (!dm_cmd) return FALSE; diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.h b/src/dnsmasq-manager/nm-dnsmasq-manager.h index 1dc0177b56..5a7cebfd8d 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.h +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.h @@ -6,6 +6,8 @@ #include #include +#include "nm-ip4-config.h" + #define NM_TYPE_DNSMASQ_MANAGER (nm_dnsmasq_manager_get_type ()) #define NM_DNSMASQ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManager)) #define NM_DNSMASQ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManagerClass)) @@ -35,7 +37,9 @@ GType nm_dnsmasq_manager_get_type (void); NMDnsMasqManager *nm_dnsmasq_manager_new (const char *iface); -gboolean nm_dnsmasq_manager_start (NMDnsMasqManager *manager, GError **error); +gboolean nm_dnsmasq_manager_start (NMDnsMasqManager *manager, + NMIP4Config *ip4_config, + GError **error); void nm_dnsmasq_manager_stop (NMDnsMasqManager *manager); diff --git a/src/nm-device.c b/src/nm-device.c index fa7feb596d..34749fad65 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -653,20 +653,58 @@ nm_device_new_ip4_autoip_config (NMDevice *self) return config; } +static GHashTable *shared_ips = NULL; + +static void +release_shared_ip (gpointer data) +{ + g_hash_table_remove (shared_ips, data); +} + +static guint32 +reserve_shared_ip (void) +{ + guint32 start = (guint32) ntohl (0x0a2a2b01); /* 10.42.43.1 */ + guint32 count = 0; + + while (g_hash_table_lookup (shared_ips, (gpointer) (start + count))) { + count += ntohl (0x100); + if (count > ntohl (0xFE00)) { + nm_warning ("%s: ran out of shared IP addresses!", __func__); + return 0; + } + } + + g_hash_table_insert (shared_ips, (gpointer) (start + count), GUINT_TO_POINTER (TRUE)); + return start + count; +} + static NMIP4Config * nm_device_new_ip4_shared_config (NMDevice *self) { NMIP4Config *config = NULL; NMSettingIP4Address *addr; + guint32 tmp_addr; g_return_val_if_fail (self != NULL, NULL); + if (G_UNLIKELY (shared_ips == NULL)) + shared_ips = g_hash_table_new (g_direct_hash, g_direct_equal); + + tmp_addr = reserve_shared_ip (); + if (!tmp_addr) + return NULL; + config = nm_ip4_config_new (); addr = g_malloc0 (sizeof (NMSettingIP4Address)); - addr->address = (guint32) ntohl (0x0a2a2b01); /* 10.42.43.1 */ + addr->address = tmp_addr; addr->netmask = (guint32) ntohl (0xFFFFFF00); /* 255.255.255.0 */ nm_ip4_config_take_address (config, addr); + /* Remove the address lock when the object gets disposed */ + g_object_set_data_full (G_OBJECT (config), "shared-ip", + GUINT_TO_POINTER (addr->address), release_shared_ip); + return config; } @@ -690,7 +728,8 @@ real_act_stage4_get_ip4_config (NMDevice *self, if (nm_device_get_use_dhcp (self)) { *config = nm_dhcp_manager_get_ip4_config (NM_DEVICE_GET_PRIVATE (self)->dhcp_manager, nm_device_get_iface (self)); - nm_utils_merge_ip4_config (*config, s_ip4); + if (*config) + nm_utils_merge_ip4_config (*config, s_ip4); } else { g_assert (s_ip4); @@ -698,10 +737,12 @@ real_act_stage4_get_ip4_config (NMDevice *self, *config = nm_device_new_ip4_autoip_config (self); } else if (!strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { *config = nm_ip4_config_new (); - nm_utils_merge_ip4_config (*config, s_ip4); + if (*config) + nm_utils_merge_ip4_config (*config, s_ip4); } else if (!strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { *config = nm_device_new_ip4_shared_config (self); - priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self)); + if (*config) + priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self)); } } @@ -895,7 +936,7 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data) if (s_ip4 && !strcmp (s_ip4->method, "shared")) { GError *error = NULL; - if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, &error)) { + if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, ip4_config, &error)) { nm_warning ("(%s): failed to start dnsmasq: %s", iface, error->message); g_error_free (error); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED);