Commit bfd38e3a authored by Dan Williams's avatar Dan Williams
Browse files

2005-05-16 Dan Williams <dcbw@redhat.com>

	Patch from Tomislav Vujec <tvujec@redhat.com>
	* gnome/applet/applet-dbus-info.c
		- (nmi_dbus_get_vpn_connection_routes): new function, pull routes out of
			GConf and pass them to NetworkManager.  New key is 'routes' under
			the VPN connection, and should be a string list

	* src/NetworkManagerSystem.c
		- (nm_system_vpn_device_set_from_ip4_config): if user-defined routes exist,
			set them on the device when we set the rest of the VPN config.  Ensure
			they are in the correct format since they are passed directly to the
			command line.

	* src/backends/NetworkManagerRedHat.c
	  src/backends/NetworkManagerDebian.c
		- (nm_system_device_add_route_via_device_with_iface): new function

	* src/vpn-manager/nm-dbus-vpn.c
		- (nm_dbus_vpn_get_routes): grab VPN routes from NetworkManagerInfo

	* src/vpn-manager/nm-vpn-manager.c
		- (nm_vpn_manager_handle_ip4_config_signal): grab routes from NMI and pass
			them into the IP4 config functions


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@637 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
parent f8723407
2005-05-16 Dan Williams <dcbw@redhat.com>
Patch from Tomislav Vujec <tvujec@redhat.com>
* gnome/applet/applet-dbus-info.c
- (nmi_dbus_get_vpn_connection_routes): new function, pull routes out of
GConf and pass them to NetworkManager. New key is 'routes' under
the VPN connection, and should be a string list
* src/NetworkManagerSystem.c
- (nm_system_vpn_device_set_from_ip4_config): if user-defined routes exist,
set them on the device when we set the rest of the VPN config. Ensure
they are in the correct format since they are passed directly to the
command line.
* src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerDebian.c
- (nm_system_device_add_route_via_device_with_iface): new function
* src/vpn-manager/nm-dbus-vpn.c
- (nm_dbus_vpn_get_routes): grab VPN routes from NetworkManagerInfo
* src/vpn-manager/nm-vpn-manager.c
- (nm_vpn_manager_handle_ip4_config_signal): grab routes from NMI and pass
them into the IP4 config functions
2005-05-15 Dan Williams <dcbw@redhat.com>
From Filip Miletic:
......
......@@ -668,6 +668,82 @@ static DBusMessage *nmi_dbus_get_vpn_connection_vpn_data (NMWirelessApplet *appl
return (reply);
}
/*
* nmi_dbus_get_vpn_connection_routes
*
* Returns routes for a particular VPN connection.
*
*/
static DBusMessage *nmi_dbus_get_vpn_connection_routes (NMWirelessApplet *applet, DBusMessage *message)
{
DBusMessage *reply = NULL;
gchar *gconf_key = NULL;
char *name = NULL;
GConfValue *routes_value = NULL;
GConfValue *value = NULL;
DBusError error;
char *escaped_name;
DBusMessageIter iter, array_iter;
GSList *elt;
g_return_val_if_fail (applet != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)
|| (strlen (name) <= 0))
{
reply = nmwa_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getVPNConnectionRoutes called with invalid arguments.");
return reply;
}
escaped_name = gconf_escape_key (name, strlen (name));
/* User-visible name of connection */
gconf_key = g_strdup_printf ("%s/%s/name", GCONF_PATH_VPN_CONNECTIONS, escaped_name);
if (!(value = gconf_client_get (applet->gconf_client, gconf_key, NULL)))
{
reply = nmwa_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "BadVPNConnectionData",
"NetworkManagerInfo::getVPNConnectionRoutes could not access the name for connection '%s'", name);
return reply;
}
gconf_value_free (value);
g_free (gconf_key);
/* Grab vpn-daemon specific data */
gconf_key = g_strdup_printf ("%s/%s/routes", GCONF_PATH_VPN_CONNECTIONS, escaped_name);
if (!(routes_value = gconf_client_get (applet->gconf_client, gconf_key, NULL))
|| !(routes_value->type == GCONF_VALUE_LIST)
|| !(gconf_value_get_list_type (routes_value) == GCONF_VALUE_STRING))
{
reply = nmwa_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "BadVPNConnectionData",
"NetworkManagerInfo::getVPNConnectionRoutes could not access the routes for connection '%s'", name);
if (routes_value)
gconf_value_free (routes_value);
return reply;
}
g_free (gconf_key);
reply = dbus_message_new_method_return (message);
dbus_message_iter_init_append (reply, &iter);
dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array_iter);
for (elt = gconf_value_get_list (routes_value); elt; elt = g_slist_next (elt))
{
const char *string = gconf_value_get_string ((GConfValue *)elt->data);
if (string)
dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &string);
}
dbus_message_iter_close_container (&iter, &array_iter);
gconf_value_free (routes_value);
g_free (escaped_name);
return (reply);
}
/*
* nmi_dbus_update_network_auth_method
......@@ -871,6 +947,8 @@ DBusHandlerResult nmi_dbus_info_message_handler (DBusConnection *connection, DBu
reply = nmi_dbus_get_vpn_connection_properties (applet, message);
else if (strcmp ("getVPNConnectionVPNData", method) == 0)
reply = nmi_dbus_get_vpn_connection_vpn_data (applet, message);
else if (strcmp ("getVPNConnectionRoutes", method) == 0)
reply = nmi_dbus_get_vpn_connection_routes (applet, message);
if (reply)
{
......
......@@ -214,13 +214,89 @@ gboolean nm_system_device_set_from_ip4_config (NMDevice *dev)
}
/*
* validate_ip4_route
*
* Ensure that IP4 routes are in the correct format
*
*/
static char *validate_ip4_route (const char *route)
{
char * ret = NULL;
char * temp = NULL;
int slash_pos = -1;
char * p = NULL;
int len, i;
int dot_count = 0;
gboolean have_slash = FALSE;
struct in_addr addr;
g_return_val_if_fail (route != NULL, NULL);
len = strlen (route);
/* Minimum length, ie 1.1.1.1/8 */
if (len < 9)
return NULL;
for (i = 0; i < len; i++)
{
/* Ensure there is only one slash */
if (route[i] == '/')
{
if (have_slash)
goto out;
have_slash = TRUE;
slash_pos = i;
continue;
}
if (route[i] == '.')
{
if (dot_count >= 4)
goto out;
dot_count++;
continue;
}
if (!isdigit (route[i]))
goto out;
}
/* Make sure there is at least one slash and 3 dots */
if (!have_slash || !slash_pos || (dot_count != 3))
goto out;
/* Valid IP address part */
temp = g_strdup (route);
temp[slash_pos] = '\0';
memset (&addr, 0, sizeof (struct in_addr));
if (inet_aton (temp, &addr) == 0)
goto out;
/* Ensure the network # is valid */
p = temp + slash_pos + 1;
i = (int) strtol (p, NULL, 10);
if ((i < 0) || (i > 32))
goto out;
/* Success! */
ret = g_strdup (route);
out:
g_free (temp);
return ret;
}
/*
* nm_system_vpn_device_set_from_ip4_config
*
* Set IPv4 configuration of a VPN device from an NMIP4Config object.
*
*/
gboolean nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named, NMDevice *active_device, const char *iface, NMIP4Config *config)
gboolean nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named, NMDevice *active_device, const char *iface, NMIP4Config *config, char **routes, int num_routes)
{
gboolean success = FALSE;
NMIP4Config * ad_config = NULL;
......@@ -242,9 +318,34 @@ gboolean nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named, NMDevi
nm_system_device_set_ip4_netmask_with_iface (NULL, iface, nm_ip4_config_get_netmask (config));
nm_system_device_set_mtu_with_iface (NULL, iface, 1412);
sleep (1);
nm_system_delete_default_route ();
nm_system_device_flush_routes_with_iface (iface);
nm_system_device_add_default_route_via_device_with_iface (iface);
if (num_routes <= 0)
{
nm_system_delete_default_route ();
nm_system_device_add_default_route_via_device_with_iface (iface);
}
else
{
int i;
for (i = 0; i < num_routes; i++)
{
char *valid_ip4_route;
/* Make sure the route is valid, otherwise it's a security risk as the route
* text is simply taken from the user, and passed directly to system(). If
* we did not check the route, think of:
*
* system("/sbin/ip route add `rm -rf /` dev eth0")
*
* where `rm -rf /` was the route text. As UID 0 (root), we have to be careful.
*/
if ((valid_ip4_route = validate_ip4_route (routes[i])))
{
nm_system_device_add_route_via_device_with_iface (iface, valid_ip4_route);
g_free (valid_ip4_route);
}
}
}
set_nameservers (named, config);
set_search_domains (named, config);
......
......@@ -39,6 +39,8 @@ void nm_system_device_flush_routes_with_iface (const char *iface);
void nm_system_device_add_default_route_via_device(NMDevice *dev);
void nm_system_device_add_default_route_via_device_with_iface(const char *iface);
void nm_system_device_add_route_via_device_with_iface (const char *iface, const char *route);
void nm_system_device_flush_addresses (NMDevice *dev);
void nm_system_device_flush_addresses_with_iface (const char *iface);
......@@ -64,7 +66,7 @@ void nm_system_remove_ip4_config_nameservers (NMNamedManager *named, NMIP4Con
void nm_system_remove_ip4_config_search_domains (NMNamedManager *named, NMIP4Config *config);
gboolean nm_system_device_set_from_ip4_config (NMDevice *dev);
gboolean nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named, NMDevice *active_device, const char *iface, NMIP4Config *config);
gboolean nm_system_vpn_device_set_from_ip4_config (NMNamedManager *named, NMDevice *active_device, const char *iface, NMIP4Config *config, char **routes, int num_routes);
gboolean nm_system_device_set_up_down (NMDevice *dev, gboolean up);
gboolean nm_system_device_set_up_down_with_iface (NMDevice *dev, const char *iface, gboolean up);
......
......@@ -81,6 +81,25 @@ void nm_system_device_add_default_route_via_device_with_iface (const char *iface
g_free (buf);
}
/*
* nm_system_device_add_route_via_device_with_iface
*
* Add route to the given device
*
*/
void nm_system_device_add_route_via_device_with_iface (const char *iface, const char *route)
{
char *buf;
g_return_if_fail (iface != NULL);
/* Add default gateway */
buf = g_strdup_printf ("/sbin/ip route add %s dev %s", route, iface);
nm_spawn_process (buf);
g_free (buf);
}
/*
* nm_system_device_flush_addresses
*
......
......@@ -116,6 +116,25 @@ void nm_system_device_add_default_route_via_device_with_iface (const char *iface
}
/*
* nm_system_device_add_route_via_device_with_iface
*
* Add route to the given device
*
*/
void nm_system_device_add_route_via_device_with_iface (const char *iface, const char *route)
{
char *buf;
g_return_if_fail (iface != NULL);
/* Add default gateway */
buf = g_strdup_printf ("/sbin/ip route add %s dev %s", route, iface);
nm_spawn_process (buf);
g_free (buf);
}
/*
* nm_system_device_has_active_routes
*
......
......@@ -233,6 +233,87 @@ static char ** nm_dbus_vpn_get_vpn_data (DBusConnection *connection, NMVPNConnec
}
/*
* nm_dbus_vpn_get_routes
*
* Get VPN routes from NMI for a vpn connection
*
* NOTE: caller MUST free returned value using g_strfreev()
*
*/
char ** nm_dbus_vpn_get_routes (DBusConnection *connection, NMVPNConnection *vpn, int *num_items)
{
DBusMessage *message;
DBusError error;
DBusMessage *reply;
char **routes = NULL;
const char *vpn_name;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (vpn != NULL, NULL);
g_return_val_if_fail (num_items != NULL, NULL);
*num_items = -1;
if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnectionRoutes")))
{
nm_warning ("nm_dbus_vpn_get_routes(): Couldn't allocate the dbus message");
return (NULL);
}
vpn_name = nm_vpn_connection_get_name (vpn);
dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_INVALID);
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
dbus_message_unref (message);
if (dbus_error_is_set (&error))
nm_warning ("nm_dbus_vpn_get_routes(): %s raised %s", error.name, error.message);
else if (!reply)
nm_info ("nm_dbus_vpn_get_routes(): reply was NULL.");
else
{
DBusMessageIter iter, array_iter;
GArray *buffer;
dbus_message_iter_init (reply, &iter);
dbus_message_iter_recurse (&iter, &array_iter);
buffer = g_array_new (TRUE, TRUE, sizeof (gchar *));
if (buffer == NULL)
return NULL;
while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING)
{
const char *value;
char *str;
dbus_message_iter_get_basic (&array_iter, &value);
str = g_strdup (value);
if (str == NULL)
{
g_array_free (buffer, TRUE);
return NULL;
}
g_array_append_val (buffer, str);
dbus_message_iter_next (&array_iter);
}
routes = (gchar **)(buffer->data);
*num_items = buffer->len;
g_array_free (buffer, FALSE);
}
if (reply)
dbus_message_unref (reply);
return (routes);
}
typedef struct UpdateOneVPNCBData
{
NMData * data;
......
......@@ -35,6 +35,8 @@ void nm_dbus_vpn_signal_vpn_connection_change (DBusConnection *con, NMVPNConn
void nm_dbus_vpn_signal_vpn_failed (DBusConnection *con, const char *signal, NMVPNConnection *vpn, const char *error_msg);
void nm_dbus_vpn_signal_vpn_login_banner (DBusConnection *con, NMVPNConnection *vpn, const char *banner);
char ** nm_dbus_vpn_get_routes (DBusConnection *connection, NMVPNConnection *vpn, int *num_items);
NMDbusMethodList * nm_dbus_vpn_methods_setup (void);
#endif
......@@ -434,10 +434,15 @@ void nm_vpn_manager_handle_ip4_config_signal (NMVPNManager *manager, DBusMessage
vpn_dev = nm_get_active_device (manager->app_data);
if (vpn_dev)
{
int num_routes = -1;
char **routes = nm_dbus_vpn_get_routes (manager->app_data->dbus_connection, con, &num_routes);
nm_system_vpn_device_set_from_ip4_config (manager->app_data->named_manager, vpn_dev,
manager->active_device, manager->active_config);
manager->active_device, manager->active_config,
routes, num_routes);
if (login_banner && strlen (login_banner))
nm_dbus_vpn_signal_vpn_login_banner (manager->app_data->dbus_connection, con, login_banner);
g_strfreev(routes);
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment