diff --git a/callouts/nm-dispatcher-action.c b/callouts/nm-dispatcher-action.c index b2fba04815..828d8be13c 100644 --- a/callouts/nm-dispatcher-action.c +++ b/callouts/nm-dispatcher-action.c @@ -751,6 +751,7 @@ main (int argc, char **argv) if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) { g_warning ("%s\n", error->message); g_error_free (error); + g_free (d); return 1; } diff --git a/initscript/Arch/networkmanager.in b/initscript/Arch/networkmanager.in index 058477384e..c3b2bfe522 100644 --- a/initscript/Arch/networkmanager.in +++ b/initscript/Arch/networkmanager.in @@ -16,8 +16,6 @@ NETWORKMANAGER_BIN=${sbindir}/NetworkManager PID=`pidof -o %PPID $NETWORKMANAGER_BIN` case "$1" in start) - ck_daemon hal && /etc/rc.d/hal start - sleep 1 stat_busy "Starting NetworkManager" if [ -z "$PID" ]; then $NETWORKMANAGER_BIN diff --git a/introspection/nm-manager-client.xml b/introspection/nm-manager-client.xml index cf89611438..9a0d4da214 100644 --- a/introspection/nm-manager-client.xml +++ b/introspection/nm-manager-client.xml @@ -41,6 +41,8 @@ object. dbus-glib generates the same bound function names for D-Bus the methods + + diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml index 02e8bcf51a..8303f4d469 100644 --- a/introspection/nm-manager.xml +++ b/introspection/nm-manager.xml @@ -108,6 +108,18 @@ + + + Indicates if mobile broadband devices are currently enabled or not. + + + + + + Indicates if the mobile broadband hardware is currently enabled, i.e. the state of the RF kill switch. + + + List of active connection object paths. diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 9ad6c99cf1..d0d8f5c481 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -110,7 +110,7 @@ libnm_glib_la_LIBADD = \ $(GUDEV_LIBS) libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \ - -version-info "3:0:1" + -version-info "4:0:2" noinst_PROGRAMS = libnm-glib-test diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 108a83726f..4b1b09c421 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -40,6 +40,9 @@ global: nm_client_wireless_get_enabled; nm_client_wireless_hardware_get_enabled; nm_client_wireless_set_enabled; + nm_client_wwan_get_enabled; + nm_client_wwan_hardware_get_enabled; + nm_client_wwan_set_enabled; nm_dbus_settings_get_connection_by_path; nm_dbus_settings_get_type; nm_dbus_settings_new; diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index 07f77cedde..05fa4dbf24 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -60,6 +60,9 @@ typedef struct { gboolean wireless_enabled; gboolean wireless_hw_enabled; + + gboolean wwan_enabled; + gboolean wwan_hw_enabled; } NMClientPrivate; enum { @@ -68,6 +71,8 @@ enum { PROP_MANAGER_RUNNING, PROP_WIRELESS_ENABLED, PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, LAST_PROP @@ -153,6 +158,36 @@ wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data) poke_wireless_devices_with_rf_status (NM_CLIENT (object)); } +static void +update_wwan_status (NMClient *client, gboolean notify) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); + gboolean val; + + val = _nm_object_get_boolean_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WwanHardwareEnabled"); + if (val != priv->wwan_hw_enabled) { + priv->wwan_hw_enabled = val; + if (notify) + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_HARDWARE_ENABLED); + } + + if (priv->wwan_hw_enabled == FALSE) + val = FALSE; + else { + val = _nm_object_get_boolean_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WwanEnabled"); + } + + if (val != priv->wwan_enabled) { + priv->wwan_enabled = val; + if (notify) + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_ENABLED); + } +} + static GObject * new_active_connection (DBusGConnection *connection, const char *path) { @@ -217,6 +252,8 @@ register_for_property_changed (NMClient *client) { NM_CLIENT_STATE, _nm_object_demarshal_generic, &priv->state }, { NM_CLIENT_WIRELESS_ENABLED, _nm_object_demarshal_generic, &priv->wireless_enabled }, { NM_CLIENT_WIRELESS_HARDWARE_ENABLED, _nm_object_demarshal_generic, &priv->wireless_hw_enabled }, + { NM_CLIENT_WWAN_ENABLED, _nm_object_demarshal_generic, &priv->wwan_enabled }, + { NM_CLIENT_WWAN_HARDWARE_ENABLED, _nm_object_demarshal_generic, &priv->wwan_hw_enabled }, { NM_CLIENT_ACTIVE_CONNECTIONS, demarshal_active_connections, &priv->active_connections }, { NULL }, }; @@ -291,6 +328,7 @@ constructor (GType type, if (priv->manager_running) { update_wireless_status (NM_CLIENT (object), FALSE); + update_wwan_status (NM_CLIENT (object), FALSE); nm_client_get_state (NM_CLIENT (object)); } @@ -353,6 +391,20 @@ set_property (GObject *object, guint prop_id, _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WIRELESS_HARDWARE_ENABLED); } break; + case PROP_WWAN_ENABLED: + b = g_value_get_boolean (value); + if (priv->wwan_enabled != b) { + priv->wwan_enabled = b; + _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_ENABLED); + } + break; + case PROP_WWAN_HARDWARE_ENABLED: + b = g_value_get_boolean (value); + if (priv->wwan_hw_enabled != b) { + priv->wwan_hw_enabled = b; + _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_HARDWARE_ENABLED); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -381,6 +433,12 @@ get_property (GObject *object, case PROP_WIRELESS_HARDWARE_ENABLED: g_value_set_boolean (value, priv->wireless_hw_enabled); break; + case PROP_WWAN_ENABLED: + g_value_set_boolean (value, priv->wwan_enabled); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->wwan_hw_enabled); + break; case PROP_ACTIVE_CONNECTIONS: g_value_set_boxed (value, nm_client_get_active_connections (self)); break; @@ -457,6 +515,32 @@ nm_client_class_init (NMClientClass *client_class) TRUE, G_PARAM_READABLE)); + /** + * NMClient::wwan-enabled: + * + * Whether WWAN functionality is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WWAN_ENABLED, + g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED, + "WwanEnabled", + "Is WWAN enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * NMClient::wwan-hardware-enabled: + * + * Whether the WWAN hardware is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WWAN_HARDWARE_ENABLED, + g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED, + "WwanHardwareEnabled", + "Is WWAN hardware enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** * NMClient::active-connections: * @@ -566,9 +650,12 @@ proxy_name_owner_changed (DBusGProxy *proxy, free_object_array (&priv->active_connections); priv->wireless_enabled = FALSE; priv->wireless_hw_enabled = FALSE; + priv->wwan_enabled = FALSE; + priv->wwan_hw_enabled = FALSE; } else { _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING); update_wireless_status (client, TRUE); + update_wwan_status (client, TRUE); } } @@ -873,6 +960,61 @@ nm_client_wireless_hardware_get_enabled (NMClient *client) return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled; } +/** + * nm_client_wwan_get_enabled: + * @client: a #NMClient + * + * Determines whether WWAN is enabled. + * + * Returns: %TRUE if WWAN is enabled + **/ +gboolean +nm_client_wwan_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return NM_CLIENT_GET_PRIVATE (client)->wwan_enabled; +} + +/** + * nm_client_wwan_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to enable WWAN + * + * Enables or disables WWAN devices. + **/ +void +nm_client_wwan_set_enabled (NMClient *client, gboolean enabled) +{ + GValue value = {0,}; + + g_return_if_fail (NM_IS_CLIENT (client)); + + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, enabled); + + _nm_object_set_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WwanEnabled", + &value); +} + +/** + * nm_client_wwan_hardware_get_enabled: + * @client: a #NMClient + * + * Determines whether the WWAN hardware is enabled. + * + * Returns: %TRUE if the WWAN hardware is enabled + **/ +gboolean +nm_client_wwan_hardware_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return NM_CLIENT_GET_PRIVATE (client)->wwan_hw_enabled; +} + /** * nm_client_get_state: * @client: a #NMClient diff --git a/libnm-glib/nm-client.h b/libnm-glib/nm-client.h index d6df98ec5b..6aafc0872c 100644 --- a/libnm-glib/nm-client.h +++ b/libnm-glib/nm-client.h @@ -45,6 +45,8 @@ G_BEGIN_DECLS #define NM_CLIENT_MANAGER_RUNNING "manager-running" #define NM_CLIENT_WIRELESS_ENABLED "wireless-enabled" #define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_CLIENT_WWAN_ENABLED "wwan-enabled" +#define NM_CLIENT_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" #define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections" typedef struct { @@ -89,6 +91,11 @@ void nm_client_deactivate_connection (NMClient *client, NMActiveConnection *acti gboolean nm_client_wireless_get_enabled (NMClient *client); void nm_client_wireless_set_enabled (NMClient *client, gboolean enabled); gboolean nm_client_wireless_hardware_get_enabled (NMClient *client); + +gboolean nm_client_wwan_get_enabled (NMClient *client); +void nm_client_wwan_set_enabled (NMClient *client, gboolean enabled); +gboolean nm_client_wwan_hardware_get_enabled (NMClient *client); + NMState nm_client_get_state (NMClient *client); gboolean nm_client_get_manager_running (NMClient *client); const GPtrArray *nm_client_get_active_connections (NMClient *client); diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index d70b94f996..6ca9139316 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -1042,15 +1042,12 @@ NMConnection * nm_connection_new_from_hash (GHashTable *hash, GError **error) { NMConnection *connection; - NMConnectionPrivate *priv; g_return_val_if_fail (hash != NULL, NULL); connection = nm_connection_new (); g_hash_table_foreach (hash, parse_one_setting, connection); - priv = NM_CONNECTION_GET_PRIVATE (connection); - if (!nm_connection_verify (connection, error)) { g_object_unref (connection); return NULL; diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c index c8820a08c6..8ec872d807 100644 --- a/libnm-util/nm-utils.c +++ b/libnm-util/nm-utils.c @@ -1598,7 +1598,6 @@ nm_utils_rsa_key_encrypt (const GByteArray *data, gsize key_len = 0, enc_len = 0; GString *pem = NULL; char *tmp, *tmp_password = NULL; - gboolean success = FALSE; int left; const char *p; GByteArray *ret = NULL; @@ -1679,14 +1678,13 @@ nm_utils_rsa_key_encrypt (const GByteArray *data, g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len); if (tmp_password && out_password) *out_password = g_strdup (tmp_password); - success = TRUE; out: if (key) { memset (key, 0, key_len); g_free (key); } - if (!enc) { + if (enc) { memset (enc, 0, enc_len); g_free (enc); } diff --git a/src/NetworkManager.c b/src/NetworkManager.c index a79d5c86ec..09a4320c78 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -329,14 +329,16 @@ static gboolean parse_state_file (const char *filename, gboolean *net_enabled, gboolean *wifi_enabled, + gboolean *wwan_enabled, GError **error) { GKeyFile *state_file; GError *tmp_error = NULL; - gboolean wifi, net; + gboolean wifi, net, wwan; g_return_val_if_fail (net_enabled != NULL, FALSE); g_return_val_if_fail (wifi_enabled != NULL, FALSE); + g_return_val_if_fail (wwan_enabled != NULL, FALSE); state_file = g_key_file_new (); if (!state_file) { @@ -374,6 +376,7 @@ parse_state_file (const char *filename, /* Write out the initial state to the state file */ g_key_file_set_boolean (state_file, "main", "NetworkingEnabled", *net_enabled); g_key_file_set_boolean (state_file, "main", "WirelessEnabled", *wifi_enabled); + g_key_file_set_boolean (state_file, "main", "WWANEnabled", *wwan_enabled); data = g_key_file_to_data (state_file, &len, NULL); if (data) @@ -400,7 +403,7 @@ parse_state_file (const char *filename, *net_enabled = net; g_clear_error (&tmp_error); - wifi = g_key_file_get_boolean (state_file, "main", "WirelessEnabled", error); + wifi = g_key_file_get_boolean (state_file, "main", "WirelessEnabled", &tmp_error); if (tmp_error) { g_clear_error (error); g_set_error_literal (error, tmp_error->domain, tmp_error->code, tmp_error->message); @@ -408,6 +411,14 @@ parse_state_file (const char *filename, *wifi_enabled = wifi; g_clear_error (&tmp_error); + wwan = g_key_file_get_boolean (state_file, "main", "WWANEnabled", &tmp_error); + if (tmp_error) { + g_clear_error (error); + g_set_error_literal (error, tmp_error->domain, tmp_error->code, tmp_error->message); + } else + *wwan_enabled = wwan; + g_clear_error (&tmp_error); + g_key_file_free (state_file); return TRUE; @@ -426,7 +437,7 @@ main (int argc, char *argv[]) char *pidfile = NULL, *user_pidfile = NULL; char *config = NULL, *plugins = NULL; char *state_file = NM_DEFAULT_SYSTEM_STATE_FILE; - gboolean wifi_enabled = TRUE, net_enabled = TRUE; + gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE; gboolean success; NMPolicy *policy = NULL; NMVPNManager *vpn_manager = NULL; @@ -509,7 +520,7 @@ main (int argc, char *argv[]) g_clear_error (&error); /* Parse the state file */ - if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &error)) { + if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) { g_warning ("State file %s parsing failed: (%d) %s.", state_file, error ? error->code : -1, @@ -583,7 +594,13 @@ main (int argc, char *argv[]) goto done; } - manager = nm_manager_get (config, plugins, state_file, net_enabled, wifi_enabled, &error); + manager = nm_manager_get (config, + plugins, + state_file, + net_enabled, + wifi_enabled, + wwan_enabled, + &error); if (manager == NULL) { nm_error ("Failed to initialize the network manager: %s", error && error->message ? error->message : "(unknown)"); diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index f099ea289c..c3ca358dca 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -178,7 +178,7 @@ nm_dhcp_device_watch_cleanup (NMDHCPDevice * device) static void nm_dhcp_device_destroy (NMDHCPDevice *device) { - int ret; + int ignored; nm_dhcp_device_timeout_cleanup (device); @@ -189,7 +189,7 @@ nm_dhcp_device_destroy (NMDHCPDevice *device) g_hash_table_destroy (device->options); if (device->conf_file) { - ret = unlink (device->conf_file); + ignored = unlink (device->conf_file); g_free (device->conf_file); } diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index 30feb28a79..07f1cf83bd 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -92,7 +92,9 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d if (!error) nm_device_activate_schedule_stage2_device_config (device); else { - nm_warning ("CDMA modem connection failed: %s", error->message); + nm_warning ("CDMA modem connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); g_error_free (error); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); } @@ -115,21 +117,55 @@ create_connect_properties (NMConnection *connection) return properties; } -static NMActStageReturn -real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +static void +do_connect (NMModem *modem) { NMConnection *connection; GHashTable *properties; - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem))); g_assert (connection); properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, - G_TYPE_INVALID); + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE), + "Connect", stage1_prepare_done, + modem, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + do_connect (NM_MODEM (device)); + else { + nm_warning ("CDMA modem enable failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + } +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + gboolean enabled = nm_modem_get_mm_enabled (NM_MODEM (device)); + + if (enabled) + do_connect (NM_MODEM (device)); + else { + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + device, NULL, 20000, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + } return NM_ACT_STAGE_RETURN_POSTPONE; } diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index 2bd8b231a9..8484d0ae4f 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -173,8 +173,11 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d clear_pin (device); required_secret = NM_SETTING_GSM_PIN; retry_secret = TRUE; - } else - nm_warning ("GSM modem connection failed: %s", error->message); + } else { + nm_warning ("GSM modem connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } if (required_secret) { nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); @@ -247,6 +250,41 @@ create_connect_properties (NMConnection *connection) return properties; } +static void +do_connect (NMModem *modem) +{ + NMConnection *connection; + GHashTable *properties; + + connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem))); + g_assert (connection); + + properties = create_connect_properties (connection); + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE), + "Connect", stage1_prepare_done, + modem, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + do_connect (NM_MODEM (device)); + else { + nm_warning ("GSM modem enable failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + } +} + static NMActStageReturn real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { @@ -264,14 +302,18 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) setting_name = nm_connection_need_secrets (connection, &hints); if (!setting_name) { - GHashTable *properties; + NMModem *modem = NM_MODEM (device); + gboolean enabled = nm_modem_get_mm_enabled (modem); - properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, - G_TYPE_INVALID); + if (enabled) + do_connect (modem); + else { + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + modem, NULL, 20000, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + } return NM_ACT_STAGE_RETURN_POSTPONE; } diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 3895a7d83e..d7187ab6ff 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -15,8 +15,12 @@ #include "nm-utils.h" #include "nm-serial-device-glue.h" #include "NetworkManagerUtils.h" +#include "nm-dbus-glib-types.h" -G_DEFINE_TYPE (NMModem, nm_modem, NM_TYPE_DEVICE) +static void device_interface_init (NMDeviceInterface *iface_class); + +G_DEFINE_TYPE_EXTENDED (NMModem, nm_modem, NM_TYPE_DEVICE, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) #define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) @@ -25,19 +29,24 @@ enum { PROP_DEVICE, PROP_PATH, PROP_IP_METHOD, + PROP_ENABLED, LAST_PROP }; typedef struct { NMDBusManager *dbus_mgr; - char *path; DBusGProxy *proxy; + DBusGProxy *props_proxy; + + char *path; NMPPPManager *ppp_manager; NMIP4Config *pending_ip4_config; guint32 ip_method; char *device; + gboolean mm_enabled; + /* PPP stats */ guint32 in_bytes; guint32 out_bytes; @@ -60,6 +69,14 @@ nm_modem_get_ppp_manager (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->ppp_manager; } +gboolean +nm_modem_get_mm_enabled (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), TRUE); + + return NM_MODEM_GET_PRIVATE (self)->mm_enabled; +} + DBusGProxy * nm_modem_get_proxy (NMModem *self, const char *interface) @@ -74,6 +91,9 @@ nm_modem_get_proxy (NMModem *self, if (interface == NULL) interface = MM_DBUS_INTERFACE_MODEM; + if (interface && !strcmp (interface, DBUS_INTERFACE_PROPERTIES)) + return priv->props_proxy; + current_iface = dbus_g_proxy_get_interface (priv->proxy); if (!current_iface || strcmp (current_iface, interface)) dbus_g_proxy_set_interface (priv->proxy, interface); @@ -425,6 +445,10 @@ device_state_changed (NMDeviceInterface *device, { NMModem *self = NM_MODEM (user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + gboolean was_connected = FALSE; + + if (IS_ACTIVATING_STATE (old_state) || (old_state == NM_DEVICE_STATE_ACTIVATED)) + was_connected = TRUE; /* Make sure we don't leave the serial device open */ switch (new_state) { @@ -436,10 +460,11 @@ device_state_changed (NMDeviceInterface *device, case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: - dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, NULL), - "Enable", - G_TYPE_BOOLEAN, FALSE, - G_TYPE_INVALID); + if (was_connected) { + dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), + "Disconnect", + G_TYPE_INVALID); + } break; default: break; @@ -480,8 +505,121 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware) return TRUE; } +static void +get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + GError *error = NULL; + GValue value = { 0, }; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + g_warning ("%s: failed get modem enabled state: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + return; + } + + if (G_VALUE_HOLDS_BOOLEAN (&value)) { + NM_MODEM_GET_PRIVATE (self)->mm_enabled = g_value_get_boolean (&value); + g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + } else + g_warning ("%s: failed get modem enabled state: unexpected reply type", __func__); + + g_value_unset (&value); +} + +static void +query_mm_enabled (NMModem *self) +{ + dbus_g_proxy_begin_call (NM_MODEM_GET_PRIVATE (self)->props_proxy, + "Get", get_mm_enabled_done, + self, NULL, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM, + G_TYPE_STRING, "Enabled", + G_TYPE_INVALID); +} + +static void +set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { + g_warning ("%s: failed to enable/disable modem: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } + + /* Update enabled/disabled state again */ + query_mm_enabled (NM_MODEM (user_data)); +} + +static void +real_set_enabled (NMDeviceInterface *device, gboolean enabled) +{ + NMModem *self = NM_MODEM (device); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + /* FIXME: For now this just toggles the ModemManager enabled state. In the + * future we want to tie this into rfkill state instead so that the user can + * toggle rfkill status of the WWAN modem. + */ + + if (priv->mm_enabled != enabled) { + DBusGProxy *proxy; + + proxy = nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM); + dbus_g_proxy_begin_call (proxy, + "Enable", set_mm_enabled_done, + device, NULL, + G_TYPE_BOOLEAN, enabled, + G_TYPE_INVALID); + } +} + +static void +modem_properties_changed (DBusGProxy *proxy, + const char *interface, + GHashTable *props, + gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + GValue *value; + + if (strcmp (interface, MM_DBUS_INTERFACE_MODEM)) + return; + + value = g_hash_table_lookup (props, "Enabled"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + NMDeviceState state; + + priv->mm_enabled = g_value_get_boolean (value); + g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + + if (priv->mm_enabled == FALSE) { + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (IS_ACTIVATING_STATE (state) || (state == NM_DEVICE_STATE_ACTIVATED)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + } + } + } +} + /*****************************************************************************/ +static void +device_interface_init (NMDeviceInterface *iface_class) +{ + iface_class->set_enabled = real_set_enabled; +} + static void nm_modem_init (NMModem *self) { @@ -497,6 +635,7 @@ constructor (GType type, { GObject *object; NMModemPrivate *priv; + DBusGConnection *bus; object = G_OBJECT_CLASS (nm_modem_parent_class)->constructor (type, n_construct_params, @@ -516,11 +655,32 @@ constructor (GType type, goto err; } - priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - MM_DBUS_SERVICE, priv->path, MM_DBUS_INTERFACE_MODEM); + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + priv->proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + priv->path, + MM_DBUS_INTERFACE_MODEM); + + priv->props_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + priv->path, + DBUS_INTERFACE_PROPERTIES); + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->props_proxy, "MmPropertiesChanged", + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->props_proxy, "MmPropertiesChanged", + G_CALLBACK (modem_properties_changed), + object, + NULL); g_signal_connect (object, "state-changed", G_CALLBACK (device_state_changed), object); + query_mm_enabled (NM_MODEM (object)); + return object; err: @@ -544,6 +704,9 @@ get_property (GObject *object, guint prop_id, case PROP_IP_METHOD: g_value_set_uint (value, priv->ip_method); break; + case PROP_ENABLED: + g_value_set_boolean (value, priv->mm_enabled); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -569,6 +732,8 @@ set_property (GObject *object, guint prop_id, case PROP_IP_METHOD: priv->ip_method = g_value_get_uint (value); break; + case PROP_ENABLED: + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -583,6 +748,9 @@ finalize (GObject *object) if (priv->proxy) g_object_unref (priv->proxy); + if (priv->props_proxy) + g_object_unref (priv->props_proxy); + g_object_unref (priv->dbus_mgr); g_free (priv->path); @@ -639,6 +807,14 @@ nm_modem_class_init (NMModemClass *klass) MM_MODEM_IP_METHOD_PPP, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + g_object_class_install_property + (object_class, PROP_ENABLED, + g_param_spec_boolean (NM_MODEM_ENABLED, + "Enabled", + "Enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + /* Signals */ signals[PPP_STATS] = g_signal_new ("ppp-stats", diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index cd638039f7..fefc6347ca 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -19,6 +19,7 @@ G_BEGIN_DECLS #define NM_MODEM_PATH "path" #define NM_MODEM_DEVICE "device" #define NM_MODEM_IP_METHOD "ip-method" +#define NM_MODEM_ENABLED "enabled" typedef struct { NMDevice parent; @@ -46,6 +47,8 @@ DBusGProxy *nm_modem_get_proxy (NMModem *self, const char *nm_modem_get_ppp_name (NMModem *self, NMConnection *connection); +gboolean nm_modem_get_mm_enabled (NMModem *self); + G_END_DECLS #endif /* NM_MODEM_H */ diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index fab68ada61..037d603380 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -1913,13 +1913,10 @@ mdio_read (NMDeviceEthernet *self, int fd, struct ifreq *ifr, int location) { struct mii_ioctl_data *mii; int val = -1; - const char * iface; g_return_val_if_fail (fd >= 0, -1); g_return_val_if_fail (ifr != NULL, -1); - iface = nm_device_get_iface (NM_DEVICE (self)); - mii = (struct mii_ioctl_data *) &ifr->ifr_ifru; mii->reg_num = location; diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index f53a6028b8..70cce8b624 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -355,3 +355,12 @@ nm_device_interface_can_assume_connection (NMDeviceInterface *device) return !!NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config; } +void +nm_device_interface_set_enabled (NMDeviceInterface *device, gboolean enabled) +{ + g_return_if_fail (NM_IS_DEVICE_INTERFACE (device)); + + if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->set_enabled) + return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->set_enabled (device, enabled); +} + diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h index 54b5c41a59..0ec5e3da14 100644 --- a/src/nm-device-interface.h +++ b/src/nm-device-interface.h @@ -97,6 +97,8 @@ struct _NMDeviceInterface { NMConnection * (*connection_match_config) (NMDeviceInterface *device, const GSList *specs); + void (*set_enabled) (NMDeviceInterface *device, gboolean enabled); + /* Signals */ void (*state_changed) (NMDeviceInterface *device, NMDeviceState new_state, @@ -131,4 +133,6 @@ NMConnection * nm_device_interface_connection_match_config (NMDeviceInterface *d gboolean nm_device_interface_can_assume_connection (NMDeviceInterface *device); +void nm_device_interface_set_enabled (NMDeviceInterface *device, gboolean enabled); + #endif /* NM_DEVICE_INTERFACE_H */ diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c index fb47cf7d56..ad81a5a78b 100644 --- a/src/nm-device-olpc-mesh.c +++ b/src/nm-device-olpc-mesh.c @@ -909,7 +909,7 @@ check_companion_cb (gpointer user_data) if (priv->device_added_cb != 0) return FALSE; - manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, NULL); + manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL); priv->device_added_cb = g_signal_connect (manager, "device-added", G_CALLBACK (device_added_cb), self); diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 20b73fb2fb..e44ac96cd6 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -69,8 +69,10 @@ static gboolean impl_device_get_access_points (NMDeviceWifi *device, #define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" +static void device_interface_init (NMDeviceInterface *iface_class); -G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) +G_DEFINE_TYPE_EXTENDED (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) #define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate)) @@ -3231,7 +3233,6 @@ activation_success_handler (NMDevice *dev) priv->ap_list = g_slist_remove (priv->ap_list, ap); g_object_unref (ap); - ap = tmp_ap; } done: @@ -3420,15 +3421,13 @@ nm_device_wifi_get_activation_ap (NMDeviceWifi *self) return NULL; } -void -nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled) +static void +real_set_enabled (NMDeviceInterface *device, gboolean enabled) { - NMDeviceWifiPrivate *priv; + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDeviceState state; - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); if (priv->enabled == enabled) return; @@ -3490,6 +3489,12 @@ nm_device_wifi_new (const char *udi, NULL); } +static void +device_interface_init (NMDeviceInterface *iface_class) +{ + iface_class->set_enabled = real_set_enabled; +} + static void nm_device_wifi_init (NMDeviceWifi * self) { diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index 126bc13982..c793844c5c 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -102,8 +102,6 @@ NM80211Mode nm_device_wifi_get_mode (NMDeviceWifi *self); NMAccessPoint * nm_device_wifi_get_activation_ap (NMDeviceWifi *self); -void nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled); - guint32 nm_device_wifi_get_ifindex (NMDeviceWifi *self); RfKillState nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self); diff --git a/src/nm-manager.c b/src/nm-manager.c index 6947cc295f..7eecbe0ba8 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -58,6 +58,13 @@ #define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd" #define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd" +#define NM_MANAGER_STATE "state" +#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" +#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_MANAGER_WWAN_ENABLED "wwan-enabled" +#define NM_MANAGER_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" +#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" + static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err); static void impl_manager_activate_connection (NMManager *manager, const char *service_name, @@ -143,6 +150,21 @@ typedef struct { guint timeout_id; } PendingConnectionInfo; +typedef struct { + gboolean enabled; + gboolean hw_enabled; + const char *desc; + const char *key; + const char *prop; + const char *hw_prop; + /* Hack for WWAN for 0.8 release; we'll start using udev + * after 0.8 gets out. + */ + gboolean ignore_udev; + RfKillState (*other_enabled_func) (NMManager *); + gboolean (*object_filter_func) (GObject *); +} RadioState; + typedef struct { char *config_file; char *state_file; @@ -164,8 +186,8 @@ typedef struct { GSList *secrets_calls; PendingConnectionInfo *pending_connection_info; - gboolean wireless_enabled; - gboolean wireless_hw_enabled; + + RadioState radio_states[RFKILL_TYPE_MAX]; gboolean sleeping; NMVPNManager *vpn_manager; @@ -207,6 +229,8 @@ enum { PROP_STATE, PROP_WIRELESS_ENABLED, PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, /* Not exported */ @@ -434,7 +458,7 @@ aipd_handle_event (DBusGProxy *proxy, NMManager *manager = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); GSList *iter; - gboolean handled; + gboolean handled = FALSE; if (!event || !iface) { nm_warning ("Incomplete message received from avahi-autoipd"); @@ -1148,28 +1172,34 @@ write_value_to_state_file (const char *filename, } static void -manager_set_wireless_enabled (NMManager *manager, gboolean enabled) +manager_set_radio_enabled (NMManager *manager, + RadioState *rstate, + gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); GSList *iter; GError *error = NULL; - if (priv->wireless_enabled == enabled) + /* Do nothing for radio types not yet implemented */ + if (!rstate->prop) + return; + + if (rstate->enabled == enabled) return; /* Can't set wireless enabled if it's disabled in hardware */ - if (!priv->wireless_hw_enabled && enabled) + if (!rstate->hw_enabled && enabled) return; - priv->wireless_enabled = enabled; + rstate->enabled = enabled; - g_object_notify (G_OBJECT (manager), NM_MANAGER_WIRELESS_ENABLED); + g_object_notify (G_OBJECT (manager), rstate->prop); - /* Update "WirelessEnabled" key in state file */ + /* Update enabled key in state file */ if (priv->state_file) { if (!write_value_to_state_file (priv->state_file, - "main", "WirelessEnabled", - G_TYPE_BOOLEAN, (gpointer) &priv->wireless_enabled, + "main", rstate->key, + G_TYPE_BOOLEAN, (gpointer) &enabled, &error)) { g_warning ("Writing to state file %s failed: (%d) %s.", priv->state_file, @@ -1184,10 +1214,8 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled) /* enable/disable wireless devices as required */ for (iter = priv->devices; iter; iter = iter->next) { - if (NM_IS_DEVICE_WIFI (iter->data)) - nm_device_wifi_set_enabled (NM_DEVICE_WIFI (iter->data), enabled); - else if (NM_IS_WIMAX_DEVICE (iter->data)) - nm_wimax_device_set_enabled (NM_WIMAX_DEVICE (iter->data), enabled); + if (rstate->object_filter_func (G_OBJECT (iter->data))) + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (iter->data), enabled); } } @@ -1276,48 +1304,108 @@ nm_manager_get_ipw_rfkill_state (NMManager *self) return ipw_state; } -static void -nm_manager_rfkill_update (NMManager *self) +static RfKillState +nm_manager_get_modem_enabled_state (NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - RfKillState udev_state, ipw_state, composite; - gboolean new_we = TRUE, new_whe = TRUE; + GSList *iter; + RfKillState wwan_state = RFKILL_UNBLOCKED; - udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr); - ipw_state = nm_manager_get_ipw_rfkill_state (self); + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *candidate = NM_DEVICE (iter->data); + RfKillState candidate_state = RFKILL_UNBLOCKED; - /* The composite state is the "worst" of either udev or ipw states */ - if (udev_state == RFKILL_HARD_BLOCKED || ipw_state == RFKILL_HARD_BLOCKED) + if (NM_IS_MODEM (candidate)) { + if (nm_modem_get_mm_enabled (NM_MODEM (candidate)) == FALSE) + candidate_state = RFKILL_SOFT_BLOCKED; + + if (candidate_state > wwan_state) + wwan_state = candidate_state; + } + } + + return wwan_state; +} + +static gboolean +rfkill_wlan_filter (GObject *object) +{ + return NM_IS_DEVICE_WIFI (object); +} + +static gboolean +rfkill_wwan_filter (GObject *object) +{ + return NM_IS_MODEM (object); +} + +static void +manager_rfkill_update_one_type (NMManager *self, + RadioState *rstate, + RfKillType rtype) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + RfKillState udev_state = RFKILL_UNBLOCKED; + RfKillState other_state = RFKILL_UNBLOCKED; + RfKillState composite; + gboolean new_e = TRUE, new_he = TRUE; + + if (!rstate->ignore_udev) + udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr, rtype); + + if (rstate->other_enabled_func) + other_state = rstate->other_enabled_func (self); + + /* The composite state is the "worst" of either udev or other states */ + if (udev_state == RFKILL_HARD_BLOCKED || other_state == RFKILL_HARD_BLOCKED) composite = RFKILL_HARD_BLOCKED; - else if (udev_state == RFKILL_SOFT_BLOCKED || ipw_state == RFKILL_SOFT_BLOCKED) + else if (udev_state == RFKILL_SOFT_BLOCKED || other_state == RFKILL_SOFT_BLOCKED) composite = RFKILL_SOFT_BLOCKED; else composite = RFKILL_UNBLOCKED; switch (composite) { case RFKILL_UNBLOCKED: - new_we = TRUE; - new_whe = TRUE; + new_e = TRUE; + new_he = TRUE; break; case RFKILL_SOFT_BLOCKED: - new_we = FALSE; - new_whe = TRUE; + new_e = FALSE; + new_he = TRUE; break; case RFKILL_HARD_BLOCKED: - new_we = FALSE; - new_whe = FALSE; + new_e = FALSE; + new_he = FALSE; break; default: break; } - nm_info ("Wireless now %s by radio killswitch", - (new_we && new_whe) ? "enabled" : "disabled"); - if (new_whe != priv->wireless_hw_enabled) { - priv->wireless_hw_enabled = new_whe; - g_object_notify (G_OBJECT (self), NM_MANAGER_WIRELESS_HARDWARE_ENABLED); + if (new_he != rstate->hw_enabled) { + nm_info ("%s now %s by radio killswitch", + rstate->desc, + (new_e && new_he) ? "enabled" : "disabled"); + + rstate->hw_enabled = new_he; + g_object_notify (G_OBJECT (self), rstate->hw_prop); } - manager_set_wireless_enabled (self, new_we); + manager_set_radio_enabled (self, rstate, new_e); +} + +static void +nm_manager_rfkill_update (NMManager *self, RfKillType rtype) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + guint i; + + if (rtype != RFKILL_TYPE_UNKNOWN) { + manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype); + return; + } + + /* Otherwise sync all radio types */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + manager_rfkill_update_one_type (self, &priv->radio_states[i], i); } static void @@ -1325,7 +1413,15 @@ manager_ipw_rfkill_state_changed (NMDeviceWifi *device, GParamSpec *pspec, gpointer user_data) { - nm_manager_rfkill_update (NM_MANAGER (user_data)); + nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WLAN); +} + +static void +manager_modem_enabled_changed (NMModem *device, + GParamSpec *pspec, + gpointer user_data) +{ + nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN); } static void @@ -1373,10 +1469,22 @@ add_device (NMManager *self, NMDevice *device) /* Update global rfkill state with this device's rfkill state, and * then set this device's rfkill state based on the global state. */ - nm_manager_rfkill_update (self); - nm_device_wifi_set_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled); - } else if (NM_IS_WIMAX_DEVICE (device)) - nm_wimax_device_set_enabled (NM_WIMAX_DEVICE (device), priv->wireless_enabled); + nm_manager_rfkill_update (self, RFKILL_TYPE_WLAN); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), + priv->radio_states[RFKILL_TYPE_WLAN].enabled); + } else if (NM_IS_MODEM (device)) { + g_signal_connect (device, "notify::" NM_MODEM_ENABLED, + G_CALLBACK (manager_modem_enabled_changed), + self); + + nm_manager_rfkill_update (self, RFKILL_TYPE_WWAN); + /* Until we start respecting WWAN rfkill switches the modem itself + * is the source of the enabled/disabled state, so the manager shouldn't + * touch it here. + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), + priv->radio_states[RFKILL_TYPE_WWAN].enabled); + */ + } type_desc = nm_device_get_type_desc (device); g_assert (type_desc); @@ -1696,10 +1804,11 @@ udev_device_removed_cb (NMUdevManager *manager, static void udev_manager_rfkill_changed_cb (NMUdevManager *udev_mgr, + RfKillType rtype, RfKillState udev_state, gpointer user_data) { - nm_manager_rfkill_update (NM_MANAGER (user_data)); + nm_manager_rfkill_update (NM_MANAGER (user_data), rtype); } GSList * @@ -1823,7 +1932,6 @@ user_get_secrets_cb (DBusGProxy *proxy, gpointer user_data) { GetSecretsInfo *info = (GetSecretsInfo *) user_data; - NMManagerPrivate *priv; GHashTable *settings = NULL; GError *error = NULL; GObject *provider; @@ -1832,8 +1940,6 @@ user_get_secrets_cb (DBusGProxy *proxy, g_return_if_fail (info->provider); g_return_if_fail (info->setting_name); - priv = NM_MANAGER_GET_PRIVATE (info->manager); - provider = g_object_ref (info->provider); if (dbus_g_proxy_end_call (proxy, call, &error, @@ -2555,20 +2661,25 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error) /* Ensure rfkill state is up-to-date since we don't respond to state * changes during sleep. */ - nm_manager_rfkill_update (self); + nm_manager_rfkill_update (self, RFKILL_TYPE_UNKNOWN); /* Re-manage managed devices */ for (iter = priv->devices; iter; iter = iter->next) { NMDevice *device = NM_DEVICE (iter->data); - gboolean wifi_enabled = (priv->wireless_hw_enabled && priv->wireless_enabled); + guint i; /* enable/disable wireless devices since that we don't respond * to killswitch changes during sleep. */ - if (NM_IS_DEVICE_WIFI (iter->data)) - nm_device_wifi_set_enabled (NM_DEVICE_WIFI (iter->data), wifi_enabled); - else if (NM_IS_WIMAX_DEVICE (iter->data)) - nm_wimax_device_set_enabled (NM_WIMAX_DEVICE (iter->data), wifi_enabled); + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + RadioState *rstate = &priv->radio_states[i]; + gboolean enabled = (rstate->hw_enabled && rstate->enabled); + + if ( rstate->object_filter_func + && rstate->object_filter_func (G_OBJECT (device))) { + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); + } + } nm_device_clear_autoconnect_inhibit (device); if (nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) @@ -2702,30 +2813,43 @@ void nm_manager_start (NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean we = FALSE; + guint i; - switch (nm_udev_manager_get_rfkill_state (priv->udev_mgr)) { - case RFKILL_UNBLOCKED: - we = TRUE; - priv->wireless_hw_enabled = TRUE; - break; - case RFKILL_SOFT_BLOCKED: - we = FALSE; - priv->wireless_hw_enabled = TRUE; - break; - case RFKILL_HARD_BLOCKED: - we = FALSE; - priv->wireless_hw_enabled = FALSE; - break; - default: - break; + /* Set initial radio enabled/disabled state */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + RadioState *rstate = &priv->radio_states[i]; + gboolean enabled = TRUE, hw_enabled = TRUE; + + if (!rstate->desc) + continue; + + if (!rstate->ignore_udev) { + switch (nm_udev_manager_get_rfkill_state (priv->udev_mgr, i)) { + case RFKILL_UNBLOCKED: + enabled = TRUE; + hw_enabled = TRUE; + break; + case RFKILL_SOFT_BLOCKED: + enabled = FALSE; + hw_enabled = TRUE; + break; + case RFKILL_HARD_BLOCKED: + enabled = FALSE; + hw_enabled = FALSE; + break; + default: + break; + } + } + + rstate->hw_enabled = hw_enabled; + nm_info ("%s %s by radio killswitch; %s by state file", + rstate->desc, + (rstate->hw_enabled && enabled) ? "enabled" : "disabled", + (rstate->enabled) ? "enabled" : "disabled"); + manager_set_radio_enabled (self, rstate, rstate->enabled && enabled); } - nm_info ("Wireless %s by radio killswitch; %s by state file", - (priv->wireless_hw_enabled && we) ? "enabled" : "disabled", - (priv->wireless_enabled) ? "enabled" : "disabled"); - manager_set_wireless_enabled (self, priv->wireless_enabled && we); - system_unmanaged_devices_changed_cb (priv->sys_settings, NULL, self); system_hostname_changed_cb (priv->sys_settings, NULL, self); system_query_connections (self); @@ -2747,6 +2871,7 @@ nm_manager_get (const char *config_file, const char *state_file, gboolean initial_net_enabled, gboolean initial_wifi_enabled, + gboolean initial_wwan_enabled, GError **error) { static NMManager *singleton = NULL; @@ -2777,7 +2902,8 @@ nm_manager_get (const char *config_file, priv->sleeping = !initial_net_enabled; - priv->wireless_enabled = initial_wifi_enabled; + priv->radio_states[RFKILL_TYPE_WLAN].enabled = initial_wifi_enabled; + priv->radio_states[RFKILL_TYPE_WWAN].enabled = initial_wwan_enabled; g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS, G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); @@ -2894,9 +3020,19 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + switch (prop_id) { case PROP_WIRELESS_ENABLED: - manager_set_wireless_enabled (NM_MANAGER (object), g_value_get_boolean (value)); + manager_set_radio_enabled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WLAN], + g_value_get_boolean (value)); + break; + case PROP_WWAN_ENABLED: + manager_set_radio_enabled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WWAN], + g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2917,10 +3053,16 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->state); break; case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, priv->wireless_enabled); + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].enabled); break; case PROP_WIRELESS_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->wireless_hw_enabled); + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); + break; + case PROP_WWAN_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].enabled); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); break; case PROP_ACTIVE_CONNECTIONS: g_value_take_boxed (value, get_active_connections (self, NULL)); @@ -2942,10 +3084,30 @@ nm_manager_init (NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); DBusGConnection *g_connection; - guint id; + guint id, i; + + /* Initialize rfkill structures and states */ + memset (priv->radio_states, 0, sizeof (priv->radio_states)); + + priv->radio_states[RFKILL_TYPE_WLAN].enabled = TRUE; + priv->radio_states[RFKILL_TYPE_WLAN].key = "WirelessEnabled"; + priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi"; + priv->radio_states[RFKILL_TYPE_WLAN].other_enabled_func = nm_manager_get_ipw_rfkill_state; + priv->radio_states[RFKILL_TYPE_WLAN].object_filter_func = rfkill_wlan_filter; + + priv->radio_states[RFKILL_TYPE_WWAN].enabled = TRUE; + priv->radio_states[RFKILL_TYPE_WWAN].key = "WWANEnabled"; + priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; + priv->radio_states[RFKILL_TYPE_WWAN].other_enabled_func = nm_manager_get_modem_enabled_state; + priv->radio_states[RFKILL_TYPE_WWAN].object_filter_func = rfkill_wwan_filter; + + for (i = 0; i < RFKILL_TYPE_MAX; i++) + priv->radio_states[i].hw_enabled = TRUE; - priv->wireless_enabled = TRUE; - priv->wireless_hw_enabled = TRUE; priv->sleeping = FALSE; priv->state = NM_STATE_DISCONNECTED; @@ -3037,6 +3199,22 @@ nm_manager_class_init (NMManagerClass *manager_class) TRUE, G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_WWAN_ENABLED, + g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, + "WwanEnabled", + "Is mobile broadband enabled", + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_WWAN_HARDWARE_ENABLED, + g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, + "WwanHardwareEnabled", + "Whether WWAN is disabled by a hardware switch or not", + TRUE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_ACTIVE_CONNECTIONS, g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, diff --git a/src/nm-manager.h b/src/nm-manager.h index a17323d42f..1090409a9b 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -35,11 +35,6 @@ #define NM_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_MANAGER)) #define NM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MANAGER, NMManagerClass)) -#define NM_MANAGER_STATE "state" -#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" -#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" -#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" - /* Not exported */ #define NM_MANAGER_HOSTNAME "hostname" #define NM_MANAGER_SLEEPING "sleeping" @@ -79,6 +74,7 @@ NMManager *nm_manager_get (const char *config_file, const char *state_file, gboolean initial_net_enabled, gboolean initial_wifi_enabled, + gboolean initial_wwan_enabled, GError **error); void nm_manager_start (NMManager *manager); diff --git a/src/nm-rfkill.h b/src/nm-rfkill.h index cc03e9e1fa..d3cd77744b 100644 --- a/src/nm-rfkill.h +++ b/src/nm-rfkill.h @@ -28,5 +28,18 @@ typedef enum { RFKILL_HARD_BLOCKED = 2 } RfKillState; +typedef enum { + RFKILL_TYPE_WLAN = 0, + RFKILL_TYPE_WWAN = 1, + RFKILL_TYPE_WIMAX = 2, + + /* UNKNOWN and MAX should always be 1 more than + * the last rfkill type since RFKILL_TYPE_MAX is + * used as an array size. + */ + RFKILL_TYPE_UNKNOWN = 3, /* KEEP LAST */ + RFKILL_TYPE_MAX = RFKILL_TYPE_UNKNOWN +} RfKillType; + #endif /* NM_RFKILL_H */ diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index a907afc2ed..090c239392 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -44,7 +44,7 @@ typedef struct { GUdevClient *client; /* Authoritative rfkill state (RFKILL_* enum) */ - RfKillState rfkill_state; + RfKillState rfkill_states[RFKILL_TYPE_MAX]; GSList *killswitches; gboolean disposed; @@ -70,19 +70,21 @@ typedef struct { guint64 seqnum; char *path; char *driver; + RfKillType rtype; gint state; } Killswitch; RfKillState -nm_udev_manager_get_rfkill_state (NMUdevManager *self) +nm_udev_manager_get_rfkill_state (NMUdevManager *self, RfKillType rtype) { g_return_val_if_fail (self != NULL, RFKILL_UNBLOCKED); + g_return_val_if_fail (rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED); - return NM_UDEV_MANAGER_GET_PRIVATE (self)->rfkill_state; + return NM_UDEV_MANAGER_GET_PRIVATE (self)->rfkill_states[rtype]; } static Killswitch * -killswitch_new (GUdevDevice *device) +killswitch_new (GUdevDevice *device, RfKillType rtype) { Killswitch *ks; GUdevDevice *parent = NULL; @@ -92,6 +94,7 @@ killswitch_new (GUdevDevice *device) ks->name = g_strdup (g_udev_device_get_name (device)); ks->seqnum = g_udev_device_get_seqnum (device); ks->path = g_strdup (g_udev_device_get_sysfs_path (device)); + ks->rtype = rtype; driver = g_udev_device_get_property (device, "DRIVER"); if (!driver) { @@ -148,7 +151,12 @@ recheck_killswitches (NMUdevManager *self) { NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); GSList *iter; - RfKillState poll_state = RFKILL_UNBLOCKED; + RfKillState poll_states[RFKILL_TYPE_MAX]; + int i; + + /* Default state is unblocked */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + poll_states[i] = RFKILL_UNBLOCKED; for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { Killswitch *ks = iter->data; @@ -160,15 +168,17 @@ recheck_killswitches (NMUdevManager *self) continue; dev_state = sysfs_state_to_nm_state (g_udev_device_get_property_as_int (device, "RFKILL_STATE")); - if (dev_state > poll_state) - poll_state = dev_state; + if (dev_state > poll_states[ks->rtype]) + poll_states[ks->rtype] = dev_state; g_object_unref (device); } - if (poll_state != priv->rfkill_state) { - priv->rfkill_state = poll_state; - g_signal_emit (self, signals[RFKILL_CHANGED], 0, priv->rfkill_state); + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + if (poll_states[i] != priv->rfkill_states[i]) { + priv->rfkill_states[i] = poll_states[i]; + g_signal_emit (self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]); + } } } @@ -189,21 +199,39 @@ killswitch_find_by_name (NMUdevManager *self, const char *name) return NULL; } +static const RfKillType +rfkill_type_to_enum (const char *str) +{ + g_return_val_if_fail (str != NULL, RFKILL_TYPE_UNKNOWN); + + if (!strcmp (str, "wlan")) + return RFKILL_TYPE_WLAN; + else if (!strcmp (str, "wwan")) + return RFKILL_TYPE_WWAN; + else if (!strcmp (str, "wimax")) + return RFKILL_TYPE_WIMAX; + + return RFKILL_TYPE_UNKNOWN; +} + static void add_one_killswitch (NMUdevManager *self, GUdevDevice *device) { NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - const char *type; + const char *str_type; + RfKillType rtype; Killswitch *ks; - type = g_udev_device_get_property (device, "RFKILL_TYPE"); - if (!type || strcmp (type, "wlan")) + str_type = g_udev_device_get_property (device, "RFKILL_TYPE"); + rtype = rfkill_type_to_enum (str_type); + if (rtype == RFKILL_TYPE_UNKNOWN) return; - ks = killswitch_new (device); + ks = killswitch_new (device, rtype); priv->killswitches = g_slist_prepend (priv->killswitches, ks); - nm_info ("Found radio killswitch %s (at %s) (driver %s)", + nm_info ("Found %s radio killswitch %s (at %s) (driver %s)", + str_type, ks->name, ks->path, ks->driver ? ks->driver : ""); @@ -431,8 +459,11 @@ nm_udev_manager_init (NMUdevManager *self) NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); const char *subsys[3] = { "rfkill", "net", NULL }; GList *switches, *iter; + guint32 i; + + for (i = 0; i < RFKILL_TYPE_MAX; i++) + priv->rfkill_states[i] = RFKILL_UNBLOCKED; - priv->rfkill_state = RFKILL_UNBLOCKED; priv->client = g_udev_client_new (subsys); g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); @@ -501,8 +532,7 @@ nm_udev_manager_class_init (NMUdevManagerClass *klass) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMUdevManagerClass, rfkill_changed), NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, - G_TYPE_UINT); + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); } diff --git a/src/nm-udev-manager.h b/src/nm-udev-manager.h index 61b60a40c3..06a2d35ce3 100644 --- a/src/nm-udev-manager.h +++ b/src/nm-udev-manager.h @@ -57,7 +57,7 @@ typedef struct { void (*device_removed) (NMUdevManager *manager, GUdevDevice *device); - void (*rfkill_changed) (NMUdevManager *manager, RfKillState state); + void (*rfkill_changed) (NMUdevManager *manager, RfKillType rtype, RfKillState state); } NMUdevManagerClass; GType nm_udev_manager_get_type (void); @@ -66,7 +66,7 @@ NMUdevManager *nm_udev_manager_new (void); void nm_udev_manager_query_devices (NMUdevManager *manager); -RfKillState nm_udev_manager_get_rfkill_state (NMUdevManager *manager); +RfKillState nm_udev_manager_get_rfkill_state (NMUdevManager *manager, RfKillType rtype); #endif /* NM_UDEV_MANAGER_H */ diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index 94bfbadf2d..5f8c4f45df 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -584,7 +584,6 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, NMSetting8021x *setting_8021x, const char *connection_uid) { - NMSupplicantConfigPrivate *priv; char *value; gboolean success; const char *key_mgmt, *auth_alg; @@ -594,8 +593,6 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, g_return_val_if_fail (setting != NULL, FALSE); g_return_val_if_fail (connection_uid != NULL, FALSE); - priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); - key_mgmt = nm_setting_wireless_security_get_key_mgmt (setting); if (!add_string_val (self, key_mgmt, "key_mgmt", TRUE, FALSE)) return FALSE; @@ -708,7 +705,6 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self, const char *connection_uid, gboolean wired) { - NMSupplicantConfigPrivate *priv; char *tmp; const char *peapver, *value, *path; gboolean success, added; @@ -719,8 +715,6 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self, g_return_val_if_fail (setting != NULL, FALSE); g_return_val_if_fail (connection_uid != NULL, FALSE); - priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); - value = nm_setting_802_1x_get_password (setting); if (!add_string_val (self, value, "password", FALSE, TRUE)) return FALSE; diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index 104eb008ab..7580319db0 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -254,6 +254,7 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); GSList *iter; char *hostname = NULL; + gboolean have_hostname_providers = FALSE; /* Hostname returned is the hostname returned from the first plugin * that provides one. @@ -263,6 +264,8 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL); if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) { + have_hostname_providers = TRUE; + g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, &hostname, NULL); if (hostname && strlen (hostname)) return hostname; @@ -271,7 +274,7 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) } /* If no plugin provided a hostname, try the original hostname of the machine */ - if (priv->orig_hostname) + if (!have_hostname_providers && priv->orig_hostname) hostname = g_strdup (priv->orig_hostname); return hostname; diff --git a/system-settings/plugins/ifcfg-rh/reader.c b/system-settings/plugins/ifcfg-rh/reader.c index e67eb2bae9..99ae55e28e 100644 --- a/system-settings/plugins/ifcfg-rh/reader.c +++ b/system-settings/plugins/ifcfg-rh/reader.c @@ -2170,7 +2170,6 @@ make_wireless_setting (shvarFile *ifcfg, if (value) { gsize ssid_len = 0, value_len = strlen (value); char *p = value, *tmp; - gboolean quoted = FALSE; char buf[33]; ssid_len = value_len; @@ -2182,7 +2181,6 @@ make_wireless_setting (shvarFile *ifcfg, value[value_len - 1] = '\0'; svUnescape (p); ssid_len = strlen (p); - quoted = TRUE; } else if ((value_len > 2) && (strncmp (value, "0x", 2) == 0)) { /* Hex representation */ if (value_len % 2) { diff --git a/system-settings/plugins/ifcfg-rh/writer.c b/system-settings/plugins/ifcfg-rh/writer.c index 1c3331da66..8a54855cb5 100644 --- a/system-settings/plugins/ifcfg-rh/writer.c +++ b/system-settings/plugins/ifcfg-rh/writer.c @@ -339,17 +339,13 @@ write_8021x_certs (NMSetting8021x *s_8021x, char *generated_pw = NULL; gboolean success = FALSE, is_pkcs12 = FALSE; const ObjectType *otype = NULL; - const char *prop; const GByteArray *blob = NULL; /* CA certificate */ - if (phase2) { - prop = NM_SETTING_802_1X_PHASE2_CA_CERT; + if (phase2) otype = &phase2_ca_type; - } else { - prop = NM_SETTING_802_1X_CA_CERT; + else otype = &ca_type; - } if (!write_object (s_8021x, ifcfg, NULL, otype, error)) return FALSE; @@ -407,13 +403,10 @@ write_8021x_certs (NMSetting8021x *s_8021x, phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", NULL, FALSE); } else { - if (phase2) { - prop = NM_SETTING_802_1X_PHASE2_CLIENT_CERT; + if (phase2) otype = &phase2_client_type; - } else { - prop = NM_SETTING_802_1X_CLIENT_CERT; + else otype = &client_type; - } /* Save the client certificate */ if (!write_object (s_8021x, ifcfg, NULL, otype, error)) diff --git a/system-settings/plugins/ifcfg-suse/Makefile.am b/system-settings/plugins/ifcfg-suse/Makefile.am index c0d5910fd1..f28f57f791 100644 --- a/system-settings/plugins/ifcfg-suse/Makefile.am +++ b/system-settings/plugins/ifcfg-suse/Makefile.am @@ -2,12 +2,6 @@ pkglib_LTLIBRARIES = libnm-settings-plugin-ifcfg-suse.la libnm_settings_plugin_ifcfg_suse_la_SOURCES = \ - nm-suse-connection.c \ - nm-suse-connection.h \ - shvar.c \ - shvar.h \ - parser.c \ - parser.h \ plugin.c \ plugin.h @@ -15,8 +9,6 @@ libnm_settings_plugin_ifcfg_suse_la_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(GMODULE_CFLAGS) \ $(DBUS_CFLAGS) \ - $(POLKIT_CFLAGS) \ - $(GUDEV_CFLAGS) \ -DG_DISABLE_DEPRECATED \ -I${top_srcdir}/src/system-settings \ -I$(top_srcdir)/include \ @@ -30,7 +22,5 @@ libnm_settings_plugin_ifcfg_suse_la_LIBADD = \ $(top_builddir)/libnm-glib/libnm-glib.la \ $(GLIB_LIBS) \ $(GMODULE_LIBS) \ - $(POLKIT_LIBS) \ - $(GUDEV_LIBS) \ $(GIO_LIBS) diff --git a/system-settings/plugins/ifcfg-suse/nm-suse-connection.c b/system-settings/plugins/ifcfg-suse/nm-suse-connection.c deleted file mode 100644 index d776fecf94..0000000000 --- a/system-settings/plugins/ifcfg-suse/nm-suse-connection.c +++ /dev/null @@ -1,171 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Novell, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include "nm-suse-connection.h" -#include "parser.h" -#include "nm-system-config-error.h" - -G_DEFINE_TYPE (NMSuseConnection, nm_suse_connection, NM_TYPE_SYSCONFIG_CONNECTION) - -#define NM_SUSE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionPrivate)) - -typedef struct { - GFileMonitor *monitor; - guint monitor_id; - - const char *iface; - NMDeviceType dev_type; - char *filename; -} NMSuseConnectionPrivate; - -static void -file_changed (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) -{ - NMSuseConnection *self = NM_SUSE_CONNECTION (user_data); - NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (self); - NMConnection *new; - GError *error = NULL; - - switch (event_type) { - case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: - new = parse_ifcfg (priv->iface, priv->dev_type); - if (new) { - if (!nm_sysconfig_connection_update (NM_SYSCONFIG_CONNECTION (self), - NM_CONNECTION (new), - TRUE, - &error)) { - g_warning ("%s: '%s' / '%s' invalid: %d", - __func__, - error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)", - (error && error->message) ? error->message : "(none)", - error ? error->code : -1); - g_clear_error (&error); - } - g_object_unref (new); - } else - g_signal_emit_by_name (self, "removed"); - break; - case G_FILE_MONITOR_EVENT_DELETED: - g_signal_emit_by_name (self, "removed"); - break; - default: - break; - } -} - -NMSuseConnection * -nm_suse_connection_new (const char *iface, NMDeviceType dev_type) -{ - NMConnection *tmp; - GFile *file; - GFileMonitor *monitor; - NMSuseConnection *exported; - NMSuseConnectionPrivate *priv; - NMSettingConnection *s_con; - - g_return_val_if_fail (iface != NULL, NULL); - - tmp = parse_ifcfg (iface, dev_type); - if (!tmp) - return NULL; - - /* Ensure the read connection is read-only since we don't have write capability yet */ - s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION); - g_assert (s_con); - if (!nm_setting_connection_get_read_only (s_con)) { - g_warning ("%s: expected read-only connection!", __func__); - g_object_unref (tmp); - return NULL; - } - - exported = (NMSuseConnection *) g_object_new (NM_TYPE_SUSE_CONNECTION, NULL); - if (!exported) { - g_object_unref (tmp); - return NULL; - } - - /* Update our settings with what was read from the file */ - nm_sysconfig_connection_update (NM_SYSCONFIG_CONNECTION (exported), tmp, FALSE, NULL); - g_object_unref (tmp); - - priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported); - - priv->iface = g_strdup (iface); - priv->dev_type = dev_type; - priv->filename = g_strdup_printf (SYSCONFDIR "/sysconfig/network/ifcfg-%s", iface); - - file = g_file_new_for_path (priv->filename); - monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); - g_object_unref (file); - - if (monitor) { - priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (file_changed), exported); - priv->monitor = monitor; - } - - return exported; -} - -/* GObject */ - -static void -nm_suse_connection_init (NMSuseConnection *connection) -{ -} - -static void -finalize (GObject *object) -{ - NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (object); - - if (priv->monitor) { - if (priv->monitor_id) - g_signal_handler_disconnect (priv->monitor, priv->monitor_id); - - g_file_monitor_cancel (priv->monitor); - g_object_unref (priv->monitor); - } - - nm_connection_clear_secrets (NM_CONNECTION (object)); - g_free (priv->filename); - - G_OBJECT_CLASS (nm_suse_connection_parent_class)->finalize (object); -} - -static void -nm_suse_connection_class_init (NMSuseConnectionClass *suse_connection_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (suse_connection_class); - - g_type_class_add_private (suse_connection_class, sizeof (NMSuseConnectionPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; -} diff --git a/system-settings/plugins/ifcfg-suse/nm-suse-connection.h b/system-settings/plugins/ifcfg-suse/nm-suse-connection.h deleted file mode 100644 index b308d67363..0000000000 --- a/system-settings/plugins/ifcfg-suse/nm-suse-connection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Novell, Inc. - */ - -#ifndef NM_SUSE_CONNECTION_H -#define NM_SUSE_CONNECTION_H - -#include -#include - -G_BEGIN_DECLS - -#define NM_TYPE_SUSE_CONNECTION (nm_suse_connection_get_type ()) -#define NM_SUSE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUSE_CONNECTION, NMSuseConnection)) -#define NM_SUSE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionClass)) -#define NM_IS_SUSE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUSE_CONNECTION)) -#define NM_IS_SUSE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SUSE_CONNECTION)) -#define NM_SUSE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionClass)) - -typedef struct { - NMSysconfigConnection parent; -} NMSuseConnection; - -typedef struct { - NMSysconfigConnectionClass parent; -} NMSuseConnectionClass; - -GType nm_suse_connection_get_type (void); - -NMSuseConnection *nm_suse_connection_new (const char *iface, - NMDeviceType dev_type); - -G_END_DECLS - -#endif /* NM_SUSE_CONNECTION_H */ diff --git a/system-settings/plugins/ifcfg-suse/parser.c b/system-settings/plugins/ifcfg-suse/parser.c deleted file mode 100644 index 6e41adfc06..0000000000 --- a/system-settings/plugins/ifcfg-suse/parser.c +++ /dev/null @@ -1,703 +0,0 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ - -/* NetworkManager system settings service - * - * Søren Sandmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007 Red Hat, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shvar.h" -#include "parser.h" -#include "plugin.h" - -#define WPA_PMK_LEN 32 - -/* Common */ - -static gboolean -get_int (const char *str, int *value) -{ - char *e; - - *value = strtol (str, &e, 0); - if (*e != '\0') - return FALSE; - - return TRUE; -} - -static NMSetting * -make_connection_setting (shvarFile *file, - const char *iface, - const char *type, - const char *suggested) -{ - NMSettingConnection *s_con; - char *str = NULL; - - s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); - if (suggested) { - /* For cosmetic reasons, if the suggested name is the same as - * the ifcfg files name, don't use it. - */ - if (strcmp (iface, suggested)) - str = g_strdup_printf ("System %s (%s)", suggested, iface); - } - - if (!str) - str = g_strdup_printf ("System %s", iface); - - g_object_set (s_con, - NM_SETTING_CONNECTION_ID, str, - NM_SETTING_CONNECTION_TYPE, type, - NM_SETTING_CONNECTION_READ_ONLY, TRUE, - NULL); - - g_free (str); - - str = nm_utils_uuid_generate_from_string (file->fileName); - g_object_set (s_con, NM_SETTING_CONNECTION_UUID, str, NULL); - g_free (str); - - str = svGetValue (file, "STARTMODE"); - if (str && !g_ascii_strcasecmp (str, "manual")) - g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); - else - g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); - g_free (str); - - return (NMSetting *) s_con; -} - - -static NMSetting * -make_ip4_setting (shvarFile *ifcfg) -{ - NMSettingIP4Config *s_ip4; - char *str; - NMIP4Address *addr; - - s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ()); - - str = svGetValue (ifcfg, "BOOTPROTO"); - if (str) { - if (!g_ascii_strcasecmp (str, "bootp") || !g_ascii_strcasecmp (str, "dhcp")) - g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - else if (!g_ascii_strcasecmp (str, "static")) - g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); - else if (!g_ascii_strcasecmp (str, "autoip")) - g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL, NULL); - - g_free (str); - } - - if (!nm_setting_ip4_config_get_method (s_ip4)) - g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - - addr = nm_ip4_address_new (); - - str = svGetValue (ifcfg, "IPADDR"); - if (str) { - char **pieces; - struct in_addr ip4_addr; - - pieces = g_strsplit (str, "/", 2); - - if (inet_pton (AF_INET, pieces[0], &ip4_addr) > 0) { - nm_ip4_address_set_address (addr, ip4_addr.s_addr); - - if (g_strv_length (pieces) == 2) - nm_ip4_address_set_prefix (addr, atoi (pieces[1])); - } else - g_warning ("Ignoring invalid IP4 address '%s'", str); - - g_strfreev (pieces); - g_free (str); - } - - if (nm_ip4_address_get_address (addr) && nm_ip4_address_get_prefix (addr) == 0) { - str = svGetValue (ifcfg, "PREFIXLEN"); - if (str) { - nm_ip4_address_set_prefix (addr, atoi (str)); - g_free (str); - } - } - - if (nm_ip4_address_get_address (addr) && nm_ip4_address_get_prefix (addr) == 0) { - str = svGetValue (ifcfg, "NETMASK"); - if (str) { - struct in_addr mask_addr; - - if (inet_pton (AF_INET, str, &mask_addr) > 0) - nm_ip4_address_set_prefix (addr, nm_utils_ip4_netmask_to_prefix (mask_addr.s_addr)); - else { - g_warning ("Ignoring invalid IP4 address: invalid netmask: '%s'", str); - nm_ip4_address_set_address (addr, 0); - nm_ip4_address_set_prefix (addr, 0); - } - g_free (str); - } - } - - if (!nm_ip4_address_get_prefix (addr) || nm_ip4_address_get_prefix (addr) > 32) { - g_warning ("Ignoring invalid IP4 address: invalid prefix: '%d'", nm_ip4_address_get_prefix (addr)); - nm_ip4_address_set_address (addr, 0); - nm_ip4_address_set_prefix (addr, 0); - } - - if (nm_ip4_address_get_address (addr)) { - if (!nm_setting_ip4_config_add_address (s_ip4, addr)) - g_warning ("Ignoring duplicate IP4 address"); - } - - nm_ip4_address_unref (addr); - - return NM_SETTING (s_ip4); -} - -/* Ethernet */ - -static NMSetting * -make_wired_setting (shvarFile *ifcfg) -{ - NMSettingWired *s_wired; - char *str; - int mtu; - - s_wired = NM_SETTING_WIRED (nm_setting_wired_new ()); - - str = svGetValue (ifcfg, "MTU"); - if (str) { - if (strlen (str) < 1) - /* Ignore empty MTU */ - ; - else if (get_int (str, &mtu)) { - if (mtu >= 0 && mtu < G_MAXINT) - g_object_set (s_wired, NM_SETTING_WIRED_MTU, mtu, NULL); - } else - g_warning ("Ignoring invalid MTU: '%s'", str); - g_free (str); - } - - return (NMSetting *) s_wired; -} - -static void -parse_ethernet (NMConnection *connection, shvarFile *file, const char *iface) -{ - NMSetting *setting; - - setting = make_connection_setting (file, iface, NM_SETTING_WIRED_SETTING_NAME, NULL); - nm_connection_add_setting (connection, setting); - - setting = make_wired_setting (file); - nm_connection_add_setting (connection, setting); - - setting = make_ip4_setting (file); - nm_connection_add_setting (connection, setting); -} - -/* Wireless */ - -static char * -get_one_wep_key (shvarFile *ifcfg, guint8 idx, GError **err) -{ - char *shvar_key; - char *key = NULL; - char *value = NULL; - char *p; - - g_return_val_if_fail (idx <= 3, NULL); - - shvar_key = g_strdup_printf ("WIRELESS_KEY_%d", idx); - value = svGetValue (ifcfg, shvar_key); - g_free (shvar_key); - - /* Ignore empty keys */ - if (!value) - return NULL; - - if (strlen (value) < 1) { - g_free (value); - return NULL; - } - - /* ASCII */ - if (g_str_has_prefix (value, "s:")) { - p = value + 2; - if (strlen (p) != 5 || strlen (p) != 13) - g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid hexadecimal WEP key."); - else { - while (*p) { - if (!isascii (*p)) { - g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid hexadecimal WEP key."); - break; - } - p++; - } - } - - if (!err) - key = g_strdup (p); - } else if (g_str_has_prefix (value, "h:")) { - /* Hashed passphrase */ - p = value + 2; - if (p && (strlen (p) > 0 || strlen (p) < 65)) - key = g_strdup (p); - else - g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid WEP passphrase."); - } else { - /* Hexadecimal */ - GString *str; - - str = g_string_sized_new (26); - p = value + 2; - while (*p) { - if (g_ascii_isxdigit (*p)) - str = g_string_append_c (str, *p); - else if (*p != '-') { - g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid hexadecimal WEP key."); - break; - } - p++; - } - - p = str->str; - - if (p && (strlen (p) == 10 || strlen (p) == 26)) - key = g_string_free (str, FALSE); - else - g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid hexadecimal WEP key."); - } - - g_free (value); - - return key; -} - -#define READ_WEP_KEY(idx) \ - { \ - char *key = get_one_wep_key (ifcfg, idx, &err); \ - if (err) \ - goto error; \ - if (key) { \ - g_object_set (G_OBJECT (security), \ - NM_SETTING_WIRELESS_SECURITY_WEP_KEY##idx, \ - key, \ - NULL); \ - g_free (key); \ - have_key = TRUE; \ - } \ - } - -static void -read_wep_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security) -{ - char *value; - GError *err = NULL; - gboolean have_key = FALSE; - - READ_WEP_KEY(0) - READ_WEP_KEY(1) - READ_WEP_KEY(2) - READ_WEP_KEY(3) - - if (have_key) - g_object_set (security, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); - - value = svGetValue (ifcfg, "WIRELESS_DEFAULT_KEY"); - if (value) { - gboolean success; - int key_idx = 0; - - success = get_int (value, &key_idx); - if (success && (key_idx >= 0) && (key_idx <= 3)) - g_object_set (security, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, key_idx, NULL); - else - g_warning ("Invalid default WEP key: '%s'", value); - - g_free (value); - } - -error: - if (err) { - g_warning ("%s", err->message); - g_error_free (err); - } -} - -static void -read_wpa_psk_settings (shvarFile *ifcfg, - NMSettingWirelessSecurity *security, - NMSettingWireless *s_wireless) -{ - char *value; - - value = svGetValue (ifcfg, "WIRELESS_WPA_PSK"); - if (value) { - if (strlen (value) > 64 || strlen (value) < 8) - g_warning ("Error loading WIRELESS_WPA_PSK: not between 8 and 64 characters inclusive"); - else - g_object_set (security, NM_SETTING_WIRELESS_SECURITY_PSK, value, NULL); - g_free (value); - } else - g_warning ("Missing WPA-PSK key"); -} - -static NMSetting * -read_wpa_eap_settings (shvarFile *ifcfg) -{ - NMSetting8021x *s_802_1x; - char *str; - GError *err = NULL; - NMSetting8021xCKType cert_type; - - s_802_1x = NM_SETTING_802_1X (nm_setting_802_1x_new ()); - - str = svGetValue (ifcfg, "WIRELESS_EAP_MODE"); - if (str) { - char **pieces; - int i; - - pieces = g_strsplit (str, " ", 0); - for (i = 0; pieces[i]; i++) - nm_setting_802_1x_add_eap_method (s_802_1x, pieces[i]); - - g_free (pieces); - g_free (str); - } - - str = svGetValue (ifcfg, "WIRELESS_WPA_ANONID"); - g_object_set (s_802_1x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, str, NULL); - g_free (str); - - str = svGetValue (ifcfg, "WIRELESS_PEAP_VERSION"); - g_object_set (s_802_1x, NM_SETTING_802_1X_PHASE1_PEAPVER, str, NULL); - g_free (str); - - str = svGetValue (ifcfg, "WIRELESS_EAP_AUTH"); - g_object_set (s_802_1x, NM_SETTING_802_1X_PHASE2_AUTH, str, NULL); - g_free (str); - - str = svGetValue (ifcfg, "WIRELESS_WPA_IDENTITY"); - g_object_set (s_802_1x, NM_SETTING_802_1X_IDENTITY, str, NULL); - g_free (str); - - str = svGetValue (ifcfg, "WIRELESS_WPA_PASSWORD"); - g_object_set (s_802_1x, NM_SETTING_802_1X_PASSWORD, str, NULL); - g_free (str); - - str = svGetValue (ifcfg, "WIRELESS_CA_CERT"); - if (str) { - nm_setting_802_1x_set_ca_cert_from_file (s_802_1x, str, &cert_type, &err); - if (err) { - g_warning ("Error loading WIRELESS_CA_CERT: %s", err->message); - g_error_free (err); - } - - g_free (str); - } - - str = svGetValue (ifcfg, "WIRELESS_CLIENT_CERT"); - if (str) { - nm_setting_802_1x_set_client_cert_from_file (s_802_1x, str, &cert_type, &err); - if (err) { - g_warning ("Error loading WIRELESS_CLIENT_CERT: %s", err->message); - g_error_free (err); - } - - g_free (str); - } - - str = svGetValue (ifcfg, "WIRELESS_CLIENT_KEY"); - if (str) { - char *password; - - password = svGetValue (ifcfg, "WIRELESS_CLIENT_KEY_PASSWORD"); - if (password) { - nm_setting_802_1x_set_private_key_from_file (s_802_1x, str, password, &cert_type, &err); - if (err) { - g_warning ("Error loading WIRELESS_CLIENT_KEY: %s", err->message); - g_error_free (err); - } - - g_free (password); - } else - g_warning ("Missing WIRELESS_CLIENT_KEY_PASSWORD"); - - g_free (str); - } - - return (NMSetting *) s_802_1x; -} - -static NMSetting * -make_wireless_security_setting (shvarFile *ifcfg, NMSettingWireless *s_wireless) -{ - NMSettingWirelessSecurity *security; - char *str; - - str = svGetValue (ifcfg, "WIRELESS_AUTH_MODE"); - if (!str || !g_ascii_strcasecmp (str, "no-encryption")) { - g_free (str); - return NULL; - } - - if (!g_ascii_strcasecmp (str, "eap")) - return read_wpa_eap_settings (ifcfg); - - security = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); - - if (!g_ascii_strcasecmp (str, "open")) { - g_object_set (security, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", NULL); - read_wep_settings (ifcfg, security); - } else if (!g_ascii_strcasecmp (str, "sharedkey")) { - g_object_set (security, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", NULL); - read_wep_settings (ifcfg, security); - } else if (!g_ascii_strcasecmp (str, "psk")) { - g_object_set (security, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL); - read_wpa_psk_settings (ifcfg, security, s_wireless); - } else - g_warning ("Invalid authentication algorithm: '%s'", str); - - g_free (str); - - return (NMSetting *) security; -} - -static NMSetting * -make_wireless_setting (shvarFile *ifcfg) -{ - NMSettingWireless *s_wireless; - char *str; - - s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ()); - - str = svGetValue (ifcfg, "WIRELESS_ESSID"); - if (str) { - gsize len = strlen (str); - - if (len > 0 && len <= 32) { - GByteArray *ssid; - - ssid = g_byte_array_sized_new (len); - g_byte_array_append (ssid, (const guint8 *) str, len); - g_object_set (s_wireless, NM_SETTING_WIRELESS_SSID, ssid, NULL); - g_byte_array_free (ssid, TRUE); - } else - g_warning ("Ignoring invalid ESSID '%s', (size %zu not between 1 and 32 inclusive)", str, len); - - g_free (str); - } - - str = svGetValue (ifcfg, "WIRLESS_MODE"); - if (str) { - const char *mode; - - if (!g_ascii_strcasecmp (str, "ad-hoc")) - mode = "adhoc"; - else if (!g_ascii_strcasecmp (str, "managed")) - mode = "infrastructure"; - else - mode = NULL; - - if (mode) - g_object_set (s_wireless, NM_SETTING_WIRELESS_MODE, mode, NULL); - - g_free (str); - } - - // FIXME: channel/freq, other L2 parameters like RTS - - return NM_SETTING (s_wireless); -} - -static char * -get_printable_ssid (NMSetting *setting) -{ - const GByteArray *ssid; - char *printable_ssid = NULL; - - ssid = nm_setting_wireless_get_ssid (NM_SETTING_WIRELESS (setting)); - if (ssid) - printable_ssid = nm_utils_ssid_to_utf8 ((const char *) ssid->data, ssid->len); - - return printable_ssid; -} - -static void -parse_wireless (NMConnection *connection, shvarFile *file, const char *iface) -{ - NMSetting *setting; - NMSetting *security; - char *printable_ssid; - - setting = make_wireless_setting (file); - nm_connection_add_setting (connection, setting); - - security = make_wireless_security_setting (file, NM_SETTING_WIRELESS (setting)); - if (security) { - const char *security_str; - - if (NM_IS_SETTING_802_1X (security)) - security_str = NM_SETTING_802_1X_SETTING_NAME; - else if (NM_IS_SETTING_WIRELESS_SECURITY (security)) - security_str = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; - else { - security_str = NULL; - g_warning ("Invalid security type: '%s'", G_OBJECT_TYPE_NAME (security)); - } - - g_object_set (G_OBJECT (setting), NM_SETTING_WIRELESS_SEC, security_str, NULL); - nm_connection_add_setting (connection, security); - } - - printable_ssid = get_printable_ssid (setting); - setting = make_connection_setting (file, iface, NM_SETTING_WIRELESS_SETTING_NAME, printable_ssid); - nm_connection_add_setting (connection, setting); - g_free (printable_ssid); - - setting = make_ip4_setting (file); - nm_connection_add_setting (connection, setting); -} - -static shvarFile * -parser_get_ifcfg_for_iface (const char *iface) -{ - char *filename; - shvarFile *file = NULL; - - filename = g_strdup_printf (SYSCONFDIR "/sysconfig/network/ifcfg-%s", iface); - if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - file = svNewFile (filename); - - g_free (filename); - - return file; -} - -NMConnection * -parse_ifcfg (const char *iface, NMDeviceType type) -{ - shvarFile *file; - NMConnection *connection; - GError *error = NULL; - - g_return_val_if_fail (iface != NULL, NULL); - - file = parser_get_ifcfg_for_iface (iface); - if (!file) - return NULL; - - connection = nm_connection_new (); - - switch (type) { - case NM_DEVICE_TYPE_ETHERNET: - parse_ethernet (connection, file, iface); - break; - case NM_DEVICE_TYPE_WIFI: - parse_wireless (connection, file, iface); - break; - default: - break; - } - - svCloseFile (file); - - if (!nm_connection_verify (connection, &error)) { - g_warning ("%s: Invalid connection for %s: '%s' / '%s' invalid: %d", - __func__, iface, - g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)), - error->message, error->code); - g_error_free (error); - g_object_unref (connection); - connection = NULL; - } - - return connection; -} - -gboolean -parser_ignore_device (const char *iface) -{ - shvarFile *file; - gboolean ignore = FALSE; - - file = parser_get_ifcfg_for_iface (iface); - if (file) { - char *str; - - if (!svTrueValue (file, "NM_CONTROLLED", 1)) - ignore = TRUE; - - str = svGetValue (file, "STARTMODE"); - if (str && !g_ascii_strcasecmp (str, "off")) - ignore = TRUE; - g_free (str); - - svCloseFile (file); - } - - return ignore; -} - -guint32 -parser_parse_routes (const char *filename) -{ - FILE *f; - char *buf; - char buffer[512]; - guint route = 0; - - g_return_val_if_fail (filename != NULL, 0); - - if ((f = fopen (filename, "r"))) { - while (fgets (buffer, 512, f) && !feof (f)) { - buf = strtok (buffer, " "); - if (strcmp (buf, "default") == 0) { - buf = strtok (NULL, " "); - if (buf) - route = inet_addr (buf); - break; - } - fclose (f); - } - } - - return route; -} diff --git a/system-settings/plugins/ifcfg-suse/parser.h b/system-settings/plugins/ifcfg-suse/parser.h deleted file mode 100644 index b216f77bf0..0000000000 --- a/system-settings/plugins/ifcfg-suse/parser.h +++ /dev/null @@ -1,37 +0,0 @@ -/* NetworkManager system settings service - * - * Søren Sandmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007 Red Hat, Inc. - */ - -#ifndef _PARSER_H_ -#define _PARSER_H_ - -#include -#include -#include - -#define IFCFG_TAG "ifcfg-" -#define BAK_TAG ".bak" - -NMConnection *parse_ifcfg (const char *iface, NMDeviceType type); -gboolean parser_ignore_device (const char *iface); - -guint32 parser_parse_routes (const char *filename); - -#endif /* _PARSER_H_ */ diff --git a/system-settings/plugins/ifcfg-suse/plugin.c b/system-settings/plugins/ifcfg-suse/plugin.c index 1b8b9c9cb0..26c73d2d5e 100644 --- a/system-settings/plugins/ifcfg-suse/plugin.c +++ b/system-settings/plugins/ifcfg-suse/plugin.c @@ -24,32 +24,19 @@ #include #include -#include -#include -#include -#include -#include #include #include -#include #include -#include -#include - -#define G_UDEV_API_IS_SUBJECT_TO_CHANGE -#include - #include "plugin.h" -#include "parser.h" -#include "nm-suse-connection.h" #include "nm-system-config-interface.h" -#include "wireless-helper.h" #define IFCFG_PLUGIN_NAME "ifcfg-suse" #define IFCFG_PLUGIN_INFO "(C) 2008 Novell, Inc. To report bugs please use the NetworkManager mailing list." #define IFCFG_DIR SYSCONFDIR "/sysconfig/network" +#define CONF_DHCP IFCFG_DIR "/dhcp" +#define HOSTNAME_FILE "/etc/HOSTNAME" static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); @@ -63,15 +50,9 @@ G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0, #define IFCFG_FILE_PATH_TAG "ifcfg-file-path" typedef struct { - GUdevClient *client; - - gboolean initialized; - GHashTable *connections; - GHashTable *unmanaged_specs; - - guint32 default_gw; - GFileMonitor *default_gw_monitor; - guint default_gw_monitor_id; + GFileMonitor *hostname_monitor; + GFileMonitor *dhcp_monitor; + char *hostname; } SCPluginIfcfgPrivate; GQuark @@ -85,285 +66,153 @@ ifcfg_plugin_error_quark (void) return error_quark; } -static void -ignore_cb (NMSettingsConnectionInterface *connection, - GError *error, - gpointer user_data) -{ -} +typedef void (*FileChangedFn) (gpointer user_data); + +typedef struct { + FileChangedFn callback; + gpointer user_data; +} FileMonitorInfo; static void -update_connections (SCPluginIfcfg *self) +file_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - GHashTableIter iter; - gpointer value; - - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, NULL, &value)) { - NMSuseConnection *exported = NM_SUSE_CONNECTION (value); - NMSettingIP4Config *ip4_config; - - ip4_config = (NMSettingIP4Config *) nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_IP4_CONFIG); - if (!ip4_config) - continue; - - if (nm_setting_ip4_config_get_num_addresses (ip4_config)) { - /* suse only has one address per device */ - NMIP4Address *ip4_address; - - ip4_address = nm_setting_ip4_config_get_address (ip4_config, 0); - if (nm_ip4_address_get_gateway (ip4_address) != priv->default_gw) { - nm_ip4_address_set_gateway (ip4_address, priv->default_gw); - nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported), - ignore_cb, - NULL); - } - } - } -} - -static void -routes_changed (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) -{ - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - char *filename; - guint32 new_gw; + FileMonitorInfo *info; switch (event_type) { case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: case G_FILE_MONITOR_EVENT_DELETED: - filename = g_file_get_path (file); - new_gw = parser_parse_routes (filename); - g_free (filename); - - if (priv->default_gw != new_gw) { - priv->default_gw = new_gw; - update_connections (self); - } + info = (FileMonitorInfo *) user_data; + info->callback (info->user_data); break; default: break; } } -static void -monitor_routes (SCPluginIfcfg *self, const char *filename) +static GFileMonitor * +monitor_file_changes (const char *filename, + FileChangedFn callback, + gpointer user_data) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); GFile *file; GFileMonitor *monitor; + FileMonitorInfo *info; file = g_file_new_for_path (filename); monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); if (monitor) { - priv->default_gw_monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (routes_changed), self); - priv->default_gw_monitor = monitor; + info = g_new0 (FileMonitorInfo, 1); + info->callback = callback; + info->user_data = user_data; + g_object_weak_ref (G_OBJECT (monitor), (GWeakNotify) g_free, info); + g_signal_connect (monitor, "changed", G_CALLBACK (file_changed), info); } -} -static void -read_connection (SCPluginIfcfg *self, GUdevDevice *device, NMDeviceType dev_type) -{ - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - const char *iface, *address; - guint32 ifindex; - - iface = g_udev_device_get_name (device); - if (!iface) - return; - - ifindex = (guint32) g_udev_device_get_property_as_uint64 (device, "IFINDEX"); - - if (parser_ignore_device (iface)) { - char *spec; - - address = g_udev_device_get_sysfs_attr (device, "address"); - if (address && (strlen (address) == 17)) { - spec = g_strdup_printf ("mac:%s", address); - g_hash_table_insert (priv->unmanaged_specs, GUINT_TO_POINTER (ifindex), spec); - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); - } else - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " (%s) error getting hardware address", iface); - } else { - NMSuseConnection *connection; - - connection = nm_suse_connection_new (iface, dev_type); - if (connection) { - g_hash_table_insert (priv->connections, - GUINT_TO_POINTER (ifindex), - connection); - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection); - } - } -} - -static void -read_connections_by_type (SCPluginIfcfg *self, NMDeviceType dev_type) -{ - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - GList *devices, *iter; - - if ( (dev_type != NM_DEVICE_TYPE_ETHERNET) - && (dev_type != NM_DEVICE_TYPE_WIFI)) - return; - - devices = g_udev_client_query_by_subsystem (priv->client, "net"); - for (iter = devices; iter; iter = g_list_next (iter)) { - read_connection (self, G_UDEV_DEVICE (iter->data), dev_type); - g_object_unref (G_UDEV_DEVICE (iter->data)); - } - g_list_free (devices); + return monitor; } static gboolean -is_wireless (GUdevDevice *device) +hostname_is_dynamic (void) { - char phy80211_path[255]; - struct stat s; - int fd; - struct iwreq iwr; - const char *ifname, *path; - gboolean is_wifi = FALSE; + GIOChannel *channel; + const char *pattern = "DHCLIENT_SET_HOSTNAME="; + char *str = NULL; + int pattern_len; + gboolean dynamic = FALSE; - ifname = g_udev_device_get_name (device); - g_assert (ifname); + channel = g_io_channel_new_file (CONF_DHCP, "r", NULL); + if (!channel) + return dynamic; - fd = socket (PF_INET, SOCK_DGRAM, 0); - strncpy (iwr.ifr_ifrn.ifrn_name, ifname, IFNAMSIZ); + pattern_len = strlen (pattern); - path = g_udev_device_get_sysfs_path (device); - snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", path); + while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) { + if (!strncmp (str, pattern, pattern_len)) { + if (!strncmp (str + pattern_len, "\"yes\"", 5)) + dynamic = TRUE; + break; + } + g_free (str); + } - if ( (ioctl (fd, SIOCGIWNAME, &iwr) == 0) - || (stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR))) - is_wifi = TRUE; + g_io_channel_shutdown (channel, FALSE, NULL); + g_io_channel_unref (channel); - close (fd); - return is_wifi; + return dynamic; +} + +static char * +hostname_read () +{ + GIOChannel *channel; + char *hostname = NULL; + + channel = g_io_channel_new_file (HOSTNAME_FILE, "r", NULL); + if (channel) { + g_io_channel_read_line (channel, &hostname, NULL, NULL, NULL); + g_io_channel_shutdown (channel, FALSE, NULL); + g_io_channel_unref (channel); + + if (hostname) + hostname = g_strchomp (hostname); + } + + return hostname; } static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, - gpointer user_data) +hostname_changed (gpointer data) { - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - const char *subsys; - gboolean wifi; + SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (data); - g_return_if_fail (action != NULL); + g_free (priv->hostname); + if (hostname_is_dynamic ()) + priv->hostname = NULL; + else + priv->hostname = hostname_read (); - /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); - g_return_if_fail (subsys != NULL); - g_return_if_fail (strcmp (subsys, "net") == 0); + g_object_notify (G_OBJECT (data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); +} - wifi = is_wireless (device); +static void +plugin_set_hostname (SCPluginIfcfg *plugin, const char *hostname) +{ + SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + GIOChannel *channel; - if (!strcmp (action, "add")) { - read_connection (self, - device, - wifi ? NM_DEVICE_TYPE_WIFI : NM_DEVICE_TYPE_ETHERNET); - } else if (!strcmp (action, "remove")) { - NMExportedConnection *exported; - guint32 ifindex; - - ifindex = (guint32) g_udev_device_get_property_as_uint64 (device, "IFINDEX"); - if (g_hash_table_remove (priv->unmanaged_specs, GUINT_TO_POINTER (ifindex))) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); - - exported = (NMExportedConnection *) g_hash_table_lookup (priv->connections, - GUINT_TO_POINTER (ifindex)); - if (exported) { - nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (exported), - ignore_cb, - NULL); - g_hash_table_remove (priv->connections, GUINT_TO_POINTER (ifindex)); - } + channel = g_io_channel_new_file (HOSTNAME_FILE, "w", NULL); + if (channel) { + g_io_channel_write_chars (channel, hostname, -1, NULL, NULL); + g_io_channel_write_chars (channel, "\n", -1, NULL, NULL); + g_io_channel_shutdown (channel, TRUE, NULL); + g_io_channel_unref (channel); } + + g_free (priv->hostname); + priv->hostname = hostname ? g_strdup (hostname) : NULL; } static void init (NMSystemConfigInterface *config) { - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - const char *subsys[2] = { "net", NULL }; + SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config); - priv->client = g_udev_client_new (subsys); - if (!priv->client) { - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error initializing libgudev"); - } else - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); -} + priv->hostname_monitor = monitor_file_changes (HOSTNAME_FILE, hostname_changed, config); + priv->dhcp_monitor = monitor_file_changes (CONF_DHCP, hostname_changed, config); -static GSList * -get_connections (NMSystemConfigInterface *config) -{ - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - GSList *list = NULL; - GHashTableIter iter; - gpointer value; - - if (!priv->initialized) { - const char *filename; - - read_connections_by_type (self, NM_DEVICE_TYPE_ETHERNET); - read_connections_by_type (self, NM_DEVICE_TYPE_WIFI); - - filename = SYSCONFDIR"/sysconfig/network/routes"; - monitor_routes (self, filename); - priv->default_gw = parser_parse_routes (filename); - if (priv->default_gw) - update_connections (self); - - priv->initialized = TRUE; - } - - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, NULL, &value)) - list = g_slist_prepend (list, value); - - return list; -} - -static void -add_one_unmanaged_spec (gpointer key, gpointer val, gpointer user_data) -{ - GSList **list = (GSList **) key; - - *list = g_slist_prepend (*list, g_strdup ((const char *) val)); -} - -static GSList * -get_unmanaged_specs (NMSystemConfigInterface *config) -{ - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - GSList *list = NULL; - - g_hash_table_foreach (priv->unmanaged_specs, add_one_unmanaged_spec, &list); - return list; + if (!hostname_is_dynamic ()) + priv->hostname = hostname_read (); } static void sc_plugin_ifcfg_init (SCPluginIfcfg *self) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - - priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); - priv->unmanaged_specs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); } static void @@ -371,19 +220,13 @@ dispose (GObject *object) { SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (object); - g_hash_table_destroy (priv->connections); - g_hash_table_destroy (priv->unmanaged_specs); + if (priv->dhcp_monitor) + g_object_unref (priv->dhcp_monitor); - if (priv->default_gw_monitor) { - if (priv->default_gw_monitor_id) - g_signal_handler_disconnect (priv->default_gw_monitor, priv->default_gw_monitor_id); + if (priv->hostname_monitor) + g_object_unref (priv->hostname_monitor); - g_file_monitor_cancel (priv->default_gw_monitor); - g_object_unref (priv->default_gw_monitor); - } - - if (priv->client) - g_object_unref (priv->client); + g_free (priv->hostname); G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object); } @@ -400,10 +243,29 @@ get_property (GObject *object, guint prop_id, g_value_set_string (value, IFCFG_PLUGIN_INFO); break; case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES: - g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE); + g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME); break; case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: - g_value_set_string (value, ""); + g_value_set_string (value, SC_PLUGIN_IFCFG_GET_PRIVATE (object)->hostname); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + const char *hostname; + + switch (prop_id) { + case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: + hostname = g_value_get_string (value); + if (hostname && strlen (hostname) < 1) + hostname = NULL; + plugin_set_hostname (SC_PLUGIN_IFCFG (object), hostname); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -419,6 +281,7 @@ sc_plugin_ifcfg_class_init (SCPluginIfcfgClass *req_class) g_type_class_add_private (req_class, sizeof (SCPluginIfcfgPrivate)); object_class->get_property = get_property; + object_class->set_property = set_property; object_class->dispose = dispose; g_object_class_override_property (object_class, @@ -442,8 +305,6 @@ static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class) { /* interface implementation */ - system_config_interface_class->get_connections = get_connections; - system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs; system_config_interface_class->init = init; } diff --git a/system-settings/plugins/ifcfg-suse/plugin.h b/system-settings/plugins/ifcfg-suse/plugin.h index 08ed4400f8..97840595c4 100644 --- a/system-settings/plugins/ifcfg-suse/plugin.h +++ b/system-settings/plugins/ifcfg-suse/plugin.h @@ -24,7 +24,7 @@ #include -#define PLUGIN_NAME "ifcfg" +#define PLUGIN_NAME "ifcfg-suse" #define SC_TYPE_PLUGIN_IFCFG (sc_plugin_ifcfg_get_type ()) #define SC_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfg)) diff --git a/system-settings/plugins/ifcfg-suse/shvar.c b/system-settings/plugins/ifcfg-suse/shvar.c deleted file mode 100644 index c978da3d50..0000000000 --- a/system-settings/plugins/ifcfg-suse/shvar.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * shvar.c - * - * Implementation of non-destructively reading/writing files containing - * only shell variable declarations and full-line comments. - * - * Includes explicit inheritance mechanism intended for use with - * Red Hat Linux ifcfg-* files. There is no protection against - * inheritance loops; they will generally cause stack overflows. - * Furthermore, they are only intended for one level of inheritance; - * the value setting algorithm assumes this. - * - * Copyright 1999,2000 Red Hat, Inc. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "shvar.h" - -/* Open the file , returning a shvarFile on success and NULL on failure. - Add a wrinkle to let the caller specify whether or not to create the file - (actually, return a structure anyway) if it doesn't exist. */ -static shvarFile * -svOpenFile(const char *name, gboolean create) -{ - shvarFile *s = NULL; - int closefd = 0; - - s = g_malloc0(sizeof(shvarFile)); - -#if 1 /* NetworkManager local change */ - s->fd = open(name, O_RDONLY); /* NOT O_CREAT */ - if (s->fd != -1) closefd = 1; -#else - s->fd = open(name, O_RDWR); /* NOT O_CREAT */ - if (s->fd == -1) { - /* try read-only */ - s->fd = open(name, O_RDONLY); /* NOT O_CREAT */ - if (s->fd != -1) closefd = 1; - } -#endif - s->fileName = g_strdup(name); - - if (s->fd != -1) { - struct stat buf; - char *p, *q; - - if (fstat(s->fd, &buf) < 0) goto bail; - s->arena = g_malloc0(buf.st_size + 1); - - if (read(s->fd, s->arena, buf.st_size) < 0) goto bail; - - /* we'd use g_strsplit() here, but we want a list, not an array */ - for(p = s->arena; (q = strchr(p, '\n')) != NULL; p = q + 1) { - s->lineList = g_list_append(s->lineList, g_strndup(p, q - p)); - } - - /* closefd is set if we opened the file read-only, so go ahead and - close it, because we can't write to it anyway */ - if (closefd) { - close(s->fd); - s->fd = -1; - } - - return s; - } - - if (create) { - return s; - } - -bail: - if (s->fd != -1) close(s->fd); - if (s->arena) g_free (s->arena); - if (s->fileName) g_free (s->fileName); - g_free (s); - return NULL; -} - -/* Open the file , return shvarFile on success, NULL on failure */ -shvarFile * -svNewFile(const char *name) -{ - return svOpenFile(name, FALSE); -} - -/* Create a new file structure, returning actual data if the file exists, - * and a suitable starting point if it doesn't. */ -shvarFile * -svCreateFile(const char *name) -{ - return svOpenFile(name, TRUE); -} - -/* remove escaped characters in place */ -static void -unescape(char *s) { - int len, i; - - len = strlen(s); - if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) { - i = len - 2; - if (i == 0) - s[0] = '\0'; - else { - memmove(s, s+1, i); - s[i+1] = '\0'; - len = i; - } - } - for (i = 0; i < len; i++) { - if (s[i] == '\\') { - memmove(s+i, s+i+1, len-(i+1)); - len--; - } - s[len] = '\0'; - } -} - - -/* create a new string with all necessary characters escaped. - * caller must free returned string - */ -static const char escapees[] = "\"'\\$~`"; /* must be escaped */ -static const char spaces[] = " \t|&;()<>"; /* only require "" */ -static char * -escape(const char *s) { - char *new; - int i, j, mangle = 0, space = 0; - int newlen, slen; - static int esclen, splen; - - if (!esclen) esclen = strlen(escapees); - if (!splen) splen = strlen(spaces); - slen = strlen(s); - - for (i = 0; i < slen; i++) { - if (strchr(escapees, s[i])) mangle++; - if (strchr(spaces, s[i])) space++; - } - if (!mangle && !space) return strdup(s); - - newlen = slen + mangle + 3; /* 3 is extra ""\0 */ - new = g_malloc0(newlen); - if (!new) return NULL; - - j = 0; - new[j++] = '"'; - for (i = 0; i < slen; i++) { - if (strchr(escapees, s[i])) { - new[j++] = '\\'; - } - new[j++] = s[i]; - } - new[j++] = '"'; - g_assert(j == slen + mangle + 2); /* j is the index of the '\0' */ - - return new; -} - -/* Get the value associated with the key, and leave the current pointer - * pointing at the line containing the value. The char* returned MUST - * be freed by the caller. - */ -char * -svGetValue(shvarFile *s, const char *key) -{ - char *value = NULL; - char *line; - char *keyString; - int len; - - g_assert(s); - g_assert(key); - - keyString = g_malloc0(strlen(key) + 2); - strcpy(keyString, key); - keyString[strlen(key)] = '='; - len = strlen(keyString); - - for (s->current = s->lineList; s->current; s->current = s->current->next) { - line = s->current->data; - if (!strncmp(keyString, line, len)) { - value = g_strdup(line + len); - unescape(value); - break; - } - } - g_free(keyString); - - if (value) { - if (value[0]) { - return value; - } else { - g_free(value); - return NULL; - } - } - if (s->parent) value = svGetValue(s->parent, key); - return value; -} - -/* return 1 if resolves to any truth value (e.g. "yes", "y", "true") - * return 0 if resolves to any non-truth value (e.g. "no", "n", "false") - * return otherwise - */ -int -svTrueValue(shvarFile *s, const char *key, int def) -{ - char *tmp; - int returnValue = def; - - tmp = svGetValue(s, key); - if (!tmp) return returnValue; - - if ( (!strcasecmp("yes", tmp)) || - (!strcasecmp("true", tmp)) || - (!strcasecmp("t", tmp)) || - (!strcasecmp("y", tmp)) ) returnValue = 1; - else - if ( (!strcasecmp("no", tmp)) || - (!strcasecmp("false", tmp)) || - (!strcasecmp("f", tmp)) || - (!strcasecmp("n", tmp)) ) returnValue = 0; - - g_free (tmp); - return returnValue; -} - - -/* Set the variable equal to the value . - * If does not exist, and the pointer is set, append - * the key=value pair after that line. Otherwise, prepend the pair - * to the top of the file. Here's the algorithm, as the C code - * seems to be rather dense: - * - * if (value == NULL), then: - * if val2 (parent): change line to key= or append line key= - * if val1 (this) : delete line - * else noop - * else use this table: - * val2 - * NULL value other - * v NULL append line noop append line - * a - * l value noop noop noop - * 1 - * other change line delete line change line - * - * No changes are ever made to the parent config file, only to the - * specific file passed on the command line. - * - */ -void -svSetValue(shvarFile *s, const char *key, const char *value) -{ - char *newval = NULL, *val1 = NULL, *val2 = NULL; - char *keyValue; - - g_assert(s); - g_assert(key); - /* value may be NULL */ - - if (value) newval = escape(value); - keyValue = g_strdup_printf("%s=%s", key, newval ? newval : ""); - - val1 = svGetValue(s, key); - if (val1 && newval && !strcmp(val1, newval)) goto bail; - if (s->parent) val2 = svGetValue(s->parent, key); - - if (!newval || !newval[0]) { - /* delete value somehow */ - if (val2) { - /* change/append line to get key= */ - if (s->current) s->current->data = keyValue; - else s->lineList = g_list_append(s->lineList, keyValue); - s->freeList = g_list_append(s->freeList, keyValue); - s->modified = 1; - } else if (val1) { - /* delete line */ - s->lineList = g_list_remove_link(s->lineList, s->current); - g_list_free_1(s->current); - s->modified = 1; - goto bail; /* do not need keyValue */ - } - goto end; - } - - if (!val1) { - if (val2 && !strcmp(val2, newval)) goto end; - /* append line */ - s->lineList = g_list_append(s->lineList, keyValue); - s->freeList = g_list_append(s->freeList, keyValue); - s->modified = 1; - goto end; - } - - /* deal with a whole line of noops */ - if (val1 && !strcmp(val1, newval)) goto end; - - /* At this point, val1 && val1 != value */ - if (val2 && !strcmp(val2, newval)) { - /* delete line */ - s->lineList = g_list_remove_link(s->lineList, s->current); - g_list_free_1(s->current); - s->modified = 1; - goto bail; /* do not need keyValue */ - } else { - /* change line */ - if (s->current) s->current->data = keyValue; - else s->lineList = g_list_append(s->lineList, keyValue); - s->freeList = g_list_append(s->freeList, keyValue); - s->modified = 1; - } - -end: - if (newval) free(newval); - if (val1) free(val1); - if (val2) free(val2); - return; - -bail: - if (keyValue) free (keyValue); - goto end; -} - -/* Write the current contents iff modified. Returns -1 on error - * and 0 on success. Do not write if no values have been modified. - * The mode argument is only used if creating the file, not if - * re-writing an existing file, and is passed unchanged to the - * open() syscall. - */ -int -svWriteFile(shvarFile *s, int mode) -{ - FILE *f; - int tmpfd; - - if (s->modified) { - if (s->fd == -1) - s->fd = open(s->fileName, O_WRONLY|O_CREAT, mode); - if (s->fd == -1) - return -1; - if (ftruncate(s->fd, 0) < 0) - return -1; - - tmpfd = dup(s->fd); - f = fdopen(tmpfd, "w"); - fseek(f, 0, SEEK_SET); - for (s->current = s->lineList; s->current; s->current = s->current->next) { - char *line = s->current->data; - fprintf(f, "%s\n", line); - } - fclose(f); - } - - return 0; -} - - -/* Close the file descriptor (if open) and delete the shvarFile. - * Returns -1 on error and 0 on success. - */ -int -svCloseFile(shvarFile *s) -{ - - g_assert(s); - - if (s->fd != -1) close(s->fd); - - g_free(s->arena); - for (s->current = s->freeList; s->current; s->current = s->current->next) { - g_free(s->current->data); - } - g_free(s->fileName); - g_list_free(s->freeList); - g_list_foreach (s->lineList, (GFunc) g_free, NULL); - g_list_free(s->lineList); /* implicitly frees s->current */ - g_free(s); - return 0; -} diff --git a/system-settings/plugins/ifcfg-suse/shvar.h b/system-settings/plugins/ifcfg-suse/shvar.h deleted file mode 100644 index 00e1a8e59f..0000000000 --- a/system-settings/plugins/ifcfg-suse/shvar.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * shvar.h - * - * Interface for non-destructively reading/writing files containing - * only shell variable declarations and full-line comments. - * - * Includes explicit inheritance mechanism intended for use with - * Red Hat Linux ifcfg-* files. There is no protection against - * inheritance loops; they will generally cause stack overflows. - * Furthermore, they are only intended for one level of inheritance; - * the value setting algorithm assumes this. - * - * Copyright 1999 Red Hat, Inc. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef _SHVAR_H -#define _SHVAR_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef struct _shvarFile shvarFile; -struct _shvarFile { - char *fileName; /* read-only */ - int fd; /* read-only */ - char *arena; /* ignore */ - GList *lineList; /* read-only */ - GList *freeList; /* ignore */ - GList *current; /* set implicitly or explicitly, - points to element of lineList */ - shvarFile *parent; /* set explicitly */ - int modified; /* ignore */ -}; - - -/* Create the file , return shvarFile on success, NULL on failure */ -shvarFile * -svCreateFile(const char *name); - -/* Open the file , return shvarFile on success, NULL on failure */ -shvarFile * -svNewFile(const char *name); - -/* Get the value associated with the key, and leave the current pointer - * pointing at the line containing the value. The char* returned MUST - * be freed by the caller. - */ -char * -svGetValue(shvarFile *s, const char *key); - -/* return 1 if resolves to any truth value (e.g. "yes", "y", "true") - * return 0 if resolves to any non-truth value (e.g. "no", "n", "false") - * return otherwise - */ -int -svTrueValue(shvarFile *s, const char *key, int def); - -/* Set the variable equal to the value . - * If does not exist, and the pointer is set, append - * the key=value pair after that line. Otherwise, prepend the pair - * to the top of the file. - */ -void -svSetValue(shvarFile *s, const char *key, const char *value); - - -/* Write the current contents iff modified. Returns -1 on error - * and 0 on success. Do not write if no values have been modified. - * The mode argument is only used if creating the file, not if - * re-writing an existing file, and is passed unchanged to the - * open() syscall. - */ -int -svWriteFile(shvarFile *s, int mode); - -/* Close the file descriptor (if open) and delete the shvarFile. - * Returns -1 on error and 0 on success. - */ -int -svCloseFile(shvarFile *s); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _SHVAR_H */