libnm-util: verify connection's 'type' setting is actually a base type

By 'base type' I mean a hardware-related type that can actually be used
to activate the connection, like wifi, wired, gsm, cdma, wimax, bluetooth,
etc, but not ipv4, ipv6, 8021x, etc.
This commit is contained in:
Dan Williams 2011-03-28 10:40:38 -05:00
parent 78df8c49a1
commit 74a0b1d9d1
3 changed files with 306 additions and 28 deletions

View file

@ -98,6 +98,7 @@ nm_connection_error_get_type (void)
static const GEnumValue values[] = {
ENUM_ENTRY (NM_CONNECTION_ERROR_UNKNOWN, "UnknownError"),
ENUM_ENTRY (NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, "ConnectionSettingNotFound"),
ENUM_ENTRY (NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID, "ConnectionTypeInvalid"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("NMConnectionError", values);
@ -139,6 +140,7 @@ static struct SettingInfo {
const char *name;
GType type;
guint32 priority;
gboolean base_type;
GQuark error_quark;
} default_map[DEFAULT_MAP_SIZE] = { { NULL } };
@ -170,7 +172,11 @@ setting_unregister (const char *name)
#endif
static void
register_one_setting (const char *name, GType type, GQuark error_quark, guint32 priority)
register_one_setting (const char *name,
GType type,
GQuark error_quark,
guint32 priority,
gboolean base_type)
{
static guint32 i = 0;
@ -181,6 +187,7 @@ register_one_setting (const char *name, GType type, GQuark error_quark, guint32
default_map[i].type = type;
default_map[i].error_quark = error_quark;
default_map[i].priority = priority;
default_map[i].base_type = base_type;
i++;
setting_register (name, type);
@ -197,82 +204,82 @@ register_default_settings (void)
register_one_setting (NM_SETTING_CONNECTION_SETTING_NAME,
NM_TYPE_SETTING_CONNECTION,
NM_SETTING_CONNECTION_ERROR,
0);
0, FALSE);
register_one_setting (NM_SETTING_WIRED_SETTING_NAME,
NM_TYPE_SETTING_WIRED,
NM_SETTING_WIRED_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_WIRELESS_SETTING_NAME,
NM_TYPE_SETTING_WIRELESS,
NM_SETTING_WIRELESS_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_OLPC_MESH_SETTING_NAME,
NM_TYPE_SETTING_OLPC_MESH,
NM_SETTING_OLPC_MESH_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_GSM_SETTING_NAME,
NM_TYPE_SETTING_GSM,
NM_SETTING_GSM_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_CDMA_SETTING_NAME,
NM_TYPE_SETTING_CDMA,
NM_SETTING_CDMA_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_BLUETOOTH_SETTING_NAME,
NM_TYPE_SETTING_BLUETOOTH,
NM_SETTING_BLUETOOTH_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_WIMAX_SETTING_NAME,
NM_TYPE_SETTING_WIMAX,
NM_SETTING_WIMAX_ERROR,
1);
1, TRUE);
register_one_setting (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_TYPE_SETTING_WIRELESS_SECURITY,
NM_SETTING_WIRELESS_SECURITY_ERROR,
2);
2, FALSE);
register_one_setting (NM_SETTING_SERIAL_SETTING_NAME,
NM_TYPE_SETTING_SERIAL,
NM_SETTING_SERIAL_ERROR,
2);
2, FALSE);
register_one_setting (NM_SETTING_PPP_SETTING_NAME,
NM_TYPE_SETTING_PPP,
NM_SETTING_PPP_ERROR,
3);
3, FALSE);
register_one_setting (NM_SETTING_PPPOE_SETTING_NAME,
NM_TYPE_SETTING_PPPOE,
NM_SETTING_PPPOE_ERROR,
3);
3, TRUE);
register_one_setting (NM_SETTING_802_1X_SETTING_NAME,
NM_TYPE_SETTING_802_1X,
NM_SETTING_802_1X_ERROR,
3);
3, FALSE);
register_one_setting (NM_SETTING_VPN_SETTING_NAME,
NM_TYPE_SETTING_VPN,
NM_SETTING_VPN_ERROR,
4);
4, TRUE);
register_one_setting (NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_TYPE_SETTING_IP4_CONFIG,
NM_SETTING_IP4_CONFIG_ERROR,
6);
6, FALSE);
register_one_setting (NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_TYPE_SETTING_IP6_CONFIG,
NM_SETTING_IP6_CONFIG_ERROR,
6);
6, FALSE);
/* Be sure to update DEFAULT_MAP_SIZE if you add another setting!! */
}
@ -290,6 +297,18 @@ get_priority_for_setting_type (GType type)
return G_MAXUINT32;
}
static gboolean
get_base_type_for_setting_type (GType type)
{
int i;
for (i = 0; default_map[i].name; i++) {
if (default_map[i].type == type)
return default_map[i].base_type;
}
return FALSE;
}
/**
* nm_connection_lookup_setting_type:
* @name: a setting name
@ -693,15 +712,17 @@ nm_connection_verify (NMConnection *connection, GError **error)
gpointer value;
GSList *all_settings = NULL;
gboolean success = TRUE;
const char *ctype;
GType base_type;
if (error)
g_return_val_if_fail (*error == NULL, FALSE);
if (!NM_IS_CONNECTION (connection)) {
g_set_error (error,
NM_SETTING_CONNECTION_ERROR,
NM_SETTING_CONNECTION_ERROR_UNKNOWN,
"invalid connection; failed verification");
g_set_error_literal (error,
NM_SETTING_CONNECTION_ERROR,
NM_SETTING_CONNECTION_ERROR_UNKNOWN,
"invalid connection; failed verification");
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
}
@ -710,10 +731,10 @@ nm_connection_verify (NMConnection *connection, GError **error)
/* First, make sure there's at least 'connection' setting */
s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
if (!s_con) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND,
"connection setting not found");
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND,
"connection setting not found");
return FALSE;
}
@ -726,9 +747,42 @@ nm_connection_verify (NMConnection *connection, GError **error)
g_hash_table_iter_init (&iter, priv->settings);
while (g_hash_table_iter_next (&iter, NULL, &value) && success)
success = nm_setting_verify (NM_SETTING (value), all_settings, error);
g_slist_free (all_settings);
return success;
if (success == FALSE)
return FALSE;
/* Now make sure the given 'type' setting can actually be the base setting
* of the connection. Can't have type=ppp for example.
*/
ctype = nm_setting_connection_get_connection_type (NM_SETTING_CONNECTION (s_con));
if (!ctype) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID,
"connection type missing");
return FALSE;
}
base_type = nm_connection_lookup_setting_type (ctype);
if (base_type == 0) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID,
"base setting GType not found");
return FALSE;
}
if (!get_base_type_for_setting_type (base_type)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID,
"connection type '%s' is not a base type",
ctype);
return FALSE;
}
return TRUE;
}
/**

View file

@ -62,6 +62,10 @@ G_BEGIN_DECLS
* @NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND: the #NMConnection object
* did not contain the required #NMSettingConnection object, which must be
* present for all connections
* @NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID: the 'type' property of the
* 'connection' setting did not point to a valid connection base type; ie
* it was not a hardware-related setting like #NMSettingWired or
* #NMSettingWireless.
*
* Describes errors that may result from operations involving a #NMConnection.
*
@ -69,7 +73,8 @@ G_BEGIN_DECLS
typedef enum
{
NM_CONNECTION_ERROR_UNKNOWN = 0,
NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND
NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND,
NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID
} NMConnectionError;
#define NM_TYPE_CONNECTION_ERROR (nm_connection_error_get_type ())

View file

@ -29,11 +29,13 @@
#include "nm-setting-connection.h"
#include "nm-setting-vpn.h"
#include "nm-setting-gsm.h"
#include "nm-setting-cdma.h"
#include "nm-setting-wired.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-serial.h"
#include "nm-dbus-glib-types.h"
static void
@ -900,6 +902,221 @@ test_connection_diff_no_secrets (void)
g_object_unref (b);
}
static void
add_generic_settings (NMConnection *connection, const char *ctype)
{
NMSetting *setting;
char *uuid;
uuid = nm_utils_uuid_generate ();
setting = nm_setting_connection_new ();
g_object_set (setting,
NM_SETTING_CONNECTION_ID, "asdfasdfadf",
NM_SETTING_CONNECTION_TYPE, ctype,
NM_SETTING_CONNECTION_UUID, uuid,
NULL);
nm_connection_add_setting (connection, setting);
g_free (uuid);
setting = nm_setting_ip4_config_new ();
g_object_set (setting, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
nm_connection_add_setting (connection, setting);
setting = nm_setting_ip6_config_new ();
g_object_set (setting, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
nm_connection_add_setting (connection, setting);
}
static void
test_connection_good_base_types (void)
{
NMConnection *connection;
NMSetting *setting;
gboolean success;
GError *error = NULL;
GByteArray *array;
const guint8 bdaddr[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
/* Try a basic wired connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_WIRED_SETTING_NAME);
setting = nm_setting_wired_new ();
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
g_object_unref (connection);
/* Try a wired PPPoE connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_PPPOE_SETTING_NAME);
setting = nm_setting_pppoe_new ();
g_object_set (setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL);
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
g_object_unref (connection);
/* Wifi connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_WIRELESS_SETTING_NAME);
setting = nm_setting_wireless_new ();
array = g_byte_array_new ();
g_byte_array_append (array, (const guint8 *) "1234567", 7);
g_object_set (setting,
NM_SETTING_WIRELESS_SSID, array,
NM_SETTING_WIRELESS_MODE, "infrastructure",
NULL);
g_byte_array_free (array, TRUE);
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
g_object_unref (connection);
/* Bluetooth connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_BLUETOOTH_SETTING_NAME);
setting = nm_setting_bluetooth_new ();
array = g_byte_array_new ();
g_byte_array_append (array, bdaddr, sizeof (bdaddr));
g_object_set (setting,
NM_SETTING_BLUETOOTH_BDADDR, array,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
NULL);
g_byte_array_free (array, TRUE);
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
g_object_unref (connection);
/* WiMAX connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_WIMAX_SETTING_NAME);
setting = nm_setting_wimax_new ();
g_object_set (setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL);
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
g_object_unref (connection);
/* GSM connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_GSM_SETTING_NAME);
setting = nm_setting_gsm_new ();
g_object_set (setting,
NM_SETTING_GSM_NUMBER, "*99#",
NM_SETTING_GSM_APN, "metered.billing.sucks",
NULL);
nm_connection_add_setting (connection, setting);
/* CDMA connection */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_CDMA_SETTING_NAME);
setting = nm_setting_cdma_new ();
g_object_set (setting,
NM_SETTING_CDMA_NUMBER, "#777",
NM_SETTING_CDMA_USERNAME, "foobar@vzw.com",
NULL);
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
g_object_unref (connection);
}
static void
test_connection_bad_base_types (void)
{
NMConnection *connection;
NMSetting *setting;
gboolean success;
GError *error = NULL;
/* Test various non-base connection types to make sure they are rejected;
* using a fake 'wired' connection so the rest of it verifies
*/
/* Connection setting */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_CONNECTION_SETTING_NAME);
setting = nm_setting_wired_new ();
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
g_assert (success == FALSE);
g_object_unref (connection);
g_clear_error (&error);
/* PPP setting */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_PPP_SETTING_NAME);
setting = nm_setting_wired_new ();
nm_connection_add_setting (connection, setting);
setting = nm_setting_ppp_new ();
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
g_assert (success == FALSE);
g_object_unref (connection);
g_clear_error (&error);
/* Serial setting */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_SERIAL_SETTING_NAME);
setting = nm_setting_wired_new ();
nm_connection_add_setting (connection, setting);
setting = nm_setting_serial_new ();
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
g_assert (success == FALSE);
g_object_unref (connection);
g_clear_error (&error);
/* IP4 setting */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_IP4_CONFIG_SETTING_NAME);
setting = nm_setting_wired_new ();
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
g_assert (success == FALSE);
g_object_unref (connection);
g_clear_error (&error);
/* IP6 setting */
connection = nm_connection_new ();
add_generic_settings (connection, NM_SETTING_IP6_CONFIG_SETTING_NAME);
setting = nm_setting_wired_new ();
nm_connection_add_setting (connection, setting);
success = nm_connection_verify (connection, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
g_assert (success == FALSE);
g_object_unref (connection);
g_clear_error (&error);
}
int main (int argc, char **argv)
{
GError *error = NULL;
@ -928,6 +1145,8 @@ int main (int argc, char **argv)
test_connection_diff_same ();
test_connection_diff_different ();
test_connection_diff_no_secrets ();
test_connection_good_base_types ();
test_connection_bad_base_types ();
base = g_path_get_basename (argv[0]);
fprintf (stdout, "%s: SUCCESS\n", base);