diff options
112 files changed, 13122 insertions, 3289 deletions
diff --git a/.gitignore b/.gitignore index 848da36b55..b87df2330d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,12 @@ docs/generate-settings-spec docs/settings-spec.html docs/spec.html +examples/C/add-connection-glib +examples/C/get-active-connections +examples/C/get-ap-info-libnm-glib +examples/C/list-connections-dbus +examples/C/list-connections-libnm-glib + callouts/nm-dhcp-client.action callouts/nm-avahi-autoipd.action callouts/nm-dispatcher.action @@ -95,6 +101,7 @@ libnm-glib/tests/test-remote-settings-client src/tests/test-dhcp-options src/tests/test-policy-hosts src/tests/test-wifi-ap-utils +src/dhcp-manager/tests/test-dhcp-dhclient system-settings/plugins/keyfile/tests/test-keyfile system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh @@ -102,6 +109,7 @@ system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils system-settings/plugins/ifcfg-rh/tests/network-scripts/Test_Write_* system-settings/plugins/ifcfg-rh/tests/network-scripts/*-Test_Write_* system-settings/plugins/ifupdown/tests/test-ifupdown +system-settings/plugins/ifnet/tests/check_ifnet m4/gtk-doc.m4 m4/intltool.m4 diff --git a/cli/src/connections.c b/cli/src/connections.c index 1dd70c164e..50c1373f81 100644 --- a/cli/src/connections.c +++ b/cli/src/connections.c @@ -38,8 +38,10 @@ #include <nm-setting-cdma.h> #include <nm-setting-bluetooth.h> #include <nm-setting-olpc-mesh.h> +#include <nm-setting-wimax.h> #include <nm-device-ethernet.h> #include <nm-device-wifi.h> +#include <nm-device-wimax.h> #include <nm-gsm-device.h> #include <nm-cdma-device.h> #include <nm-device-bt.h> @@ -102,6 +104,7 @@ static NmcOutputField nmc_fields_settings_names[] = { SETTING_FIELD (NM_SETTING_BLUETOOTH_SETTING_NAME, 0), /* 12 */ SETTING_FIELD (NM_SETTING_OLPC_MESH_SETTING_NAME, 0), /* 13 */ SETTING_FIELD (NM_SETTING_VPN_SETTING_NAME, 0), /* 14 */ + SETTING_FIELD (NM_SETTING_WIMAX_SETTING_NAME, 0), /* 15 */ {NULL, NULL, 0, NULL, 0} }; #define NMC_FIELDS_SETTINGS_NAMES_ALL NM_SETTING_CONNECTION_SETTING_NAME","\ @@ -118,7 +121,8 @@ static NmcOutputField nmc_fields_settings_names[] = { NM_SETTING_CDMA_SETTING_NAME","\ NM_SETTING_BLUETOOTH_SETTING_NAME","\ NM_SETTING_OLPC_MESH_SETTING_NAME","\ - NM_SETTING_VPN_SETTING_NAME + NM_SETTING_VPN_SETTING_NAME","\ + NM_SETTING_WIMAX_SETTING_NAME typedef struct { @@ -137,7 +141,7 @@ static void quit (void); static void show_connection (NMConnection *data, gpointer user_data); static NMConnection *find_connection (GSList *list, const char *filter_type, const char *filter_val); static gboolean find_device_for_connection (NmCli *nmc, NMConnection *connection, const char *iface, const char *ap, - NMDevice **device, const char **spec_object, GError **error); + const char *nsp, NMDevice **device, const char **spec_object, GError **error); static const char *active_connection_state_to_string (NMActiveConnectionState state); static void active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, gpointer user_data); static void activate_connection_cb (gpointer user_data, const char *path, GError *error); @@ -155,7 +159,7 @@ usage (void) " COMMAND := { list | status | up | down }\n\n" " list [id <id> | uuid <id>]\n" " status\n" - " up id <id> | uuid <id> [iface <iface>] [ap <hwaddr>] [--nowait] [--timeout <timeout>]\n" + " up id <id> | uuid <id> [iface <iface>] [ap <hwaddr>] [nsp <name>] [--nowait] [--timeout <timeout>]\n" " down id <id> | uuid <id>\n")); } @@ -348,6 +352,15 @@ nmc_connection_detail (NMConnection *connection, NmCli *nmc) continue; } } + + if (!strcasecmp (nmc_fields_settings_names[section_idx].name, nmc_fields_settings_names[15].name)) { + setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX); + if (setting) { + setting_wimax_details (setting, nmc); + was_output = TRUE; + continue; + } + } } if (print_settings_array) @@ -826,6 +839,51 @@ check_olpc_mesh_compatible (NMDeviceOlpcMesh *device, NMConnection *connection, #endif static gboolean +check_wimax_compatible (NMDeviceWimax *device, NMConnection *connection, GError **error) +{ + NMSettingConnection *s_con; + NMSettingWimax *s_wimax; + const GByteArray *mac; + const char *device_mac_str; + struct ether_addr *device_mac = NULL; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIMAX_SETTING_NAME)) { + g_set_error (error, 0, 0, + "The connection was not a WiMAX connection."); + return FALSE; + } + + s_wimax = NM_SETTING_WIMAX (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX)); + if (!s_wimax) { + g_set_error (error, 0, 0, + "The connection was not a valid WiMAX connection."); + return FALSE; + } + + device_mac_str = nm_device_wimax_get_hw_address (device); + if (device_mac_str) + device_mac = ether_aton (device_mac_str); + if (!device_mac) { + g_set_error (error, 0, 0, "Invalid device MAC address."); + return FALSE; + } + + mac = nm_setting_wimax_get_mac_address (s_wimax); + if (mac && memcmp (mac->data, device_mac->ether_addr_octet, ETH_ALEN)) { + g_set_error (error, 0, 0, + "The connection's MAC address did not match this device."); + return FALSE; + } + + return TRUE; +} + +static gboolean nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); @@ -839,6 +897,8 @@ nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, return check_bt_compatible (NM_DEVICE_BT (device), connection, error); // else if (NM_IS_DEVICE_OLPC_MESH (device)) // return check_olpc_mesh_compatible (NM_DEVICE_OLPC_MESH (device), connection, error); + else if (NM_IS_DEVICE_WIMAX (device)) + return check_wimax_compatible (NM_DEVICE_WIMAX (device), connection, error); g_set_error (error, 0, 0, "unhandled device type '%s'", G_OBJECT_TYPE_NAME (device)); return FALSE; @@ -929,13 +989,20 @@ get_default_active_connection (NmCli *nmc, NMDevice **device) * IN: connection: connection to activate * iface: device interface name to use (optional) * ap: access point to use (optional; valid just for 802-11-wireless) + * nsp: Network Service Provider to use (option; valid only for wimax) * OUT: device: found device * spec_object: specific_object path of NMAccessPoint * RETURNS: TRUE when a device is found, FALSE otherwise. */ static gboolean -find_device_for_connection (NmCli *nmc, NMConnection *connection, const char *iface, const char *ap, - NMDevice **device, const char **spec_object, GError **error) +find_device_for_connection (NmCli *nmc, + NMConnection *connection, + const char *iface, + const char *ap, + const char *nsp, + NMDevice **device, + const char **spec_object, + GError **error) { NMSettingConnection *s_con; const char *con_type; @@ -1022,6 +1089,25 @@ find_device_for_connection (NmCli *nmc, NMConnection *connection, const char *if } g_free (hwaddr_up); } + + if ( found_device + && nsp + && !strcmp (con_type, NM_SETTING_WIMAX_SETTING_NAME) + && NM_IS_DEVICE_WIMAX (dev)) { + const GPtrArray *nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (dev)); + found_device = NULL; /* Mark as not found; set to the device again later, only if NSP matches */ + + for (j = 0; nsps && (j < nsps->len); j++) { + NMWimaxNsp *candidate_nsp = g_ptr_array_index (nsps, j); + const char *candidate_name = nm_wimax_nsp_get_name (candidate_nsp); + + if (!strcmp (nsp, candidate_name)) { + found_device = dev; + *spec_object = nm_object_get_path (NM_OBJECT (candidate_nsp)); + break; + } + } + } } if (found_device) { @@ -1263,6 +1349,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) const char *con_type; const char *iface = NULL; const char *ap = NULL; + const char *nsp = NULL; gboolean id_specified = FALSE; gboolean wait = TRUE; GError *error = NULL; @@ -1309,6 +1396,15 @@ do_connection_up (NmCli *nmc, int argc, char **argv) ap = *argv; } + else if (strcmp (*argv, "nsp") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + + nsp = *argv; + } else if (strcmp (*argv, "--nowait") == 0) { wait = FALSE; } else if (strcmp (*argv, "--timeout") == 0) { @@ -1349,7 +1445,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) g_assert (s_con); con_type = nm_setting_connection_get_connection_type (s_con); - device_found = find_device_for_connection (nmc, connection, iface, ap, &device, &spec_object, &error); + device_found = find_device_for_connection (nmc, connection, iface, ap, nsp, &device, &spec_object, &error); if (!device_found) { if (error) diff --git a/cli/src/devices.c b/cli/src/devices.c index 436b4b6eb8..5e67c4ef5d 100644 --- a/cli/src/devices.c +++ b/cli/src/devices.c @@ -29,7 +29,6 @@ #include <glib.h> #include <glib/gi18n.h> #include <nm-client.h> -#include <nm-device-wifi.h> #include <nm-client.h> #include <nm-device.h> @@ -39,6 +38,7 @@ #include <nm-cdma-device.h> #include <nm-device-bt.h> //#include <nm-device-olpc-mesh.h> +#include <nm-device-wimax.h> #include <nm-utils.h> #include <nm-setting-ip4-config.h> #include <nm-setting-ip6-config.h> @@ -51,6 +51,7 @@ #include <nm-setting-cdma.h> #include <nm-setting-bluetooth.h> #include <nm-setting-olpc-mesh.h> +#include <nm-setting-wimax.h> #include "utils.h" #include "devices.h" @@ -75,14 +76,16 @@ static NmcOutputField nmc_fields_dev_list_sections[] = { {"WIFI-PROPERTIES", N_("WIFI-PROPERTIES"), 0, NULL, 0}, /* 2 */ {"AP", N_("AP"), 0, NULL, 0}, /* 3 */ {"WIRED-PROPERTIES", N_("WIRED-PROPERTIES"), 0, NULL, 0}, /* 4 */ - {"IP4-SETTINGS", N_("IP4-SETTINGS"), 0, NULL, 0}, /* 5 */ - {"IP4-DNS", N_("IP4-DNS"), 0, NULL, 0}, /* 6 */ - {"IP6-SETTINGS", N_("IP6-SETTINGS"), 0, NULL, 0}, /* 7 */ - {"IP6-DNS", N_("IP6-DNS"), 0, NULL, 0}, /* 8 */ + {"WIMAX-PROPERTIES", N_("WIMAX-PROPERTIES"), 0, NULL, 0}, /* 5 */ + {"NSP", N_("NSP"), 0, NULL, 0}, /* 6 */ + {"IP4-SETTINGS", N_("IP4-SETTINGS"), 0, NULL, 0}, /* 7 */ + {"IP4-DNS", N_("IP4-DNS"), 0, NULL, 0}, /* 8 */ + {"IP6-SETTINGS", N_("IP6-SETTINGS"), 0, NULL, 0}, /* 9 */ + {"IP6-DNS", N_("IP6-DNS"), 0, NULL, 0}, /* 10 */ {NULL, NULL, 0, NULL, 0} }; -#define NMC_FIELDS_DEV_LIST_SECTIONS_ALL "GENERAL,CAPABILITIES,WIFI-PROPERTIES,AP,WIRED-PROPERTIES,IP4-SETTINGS,IP4-DNS,IP6-SETTINGS,IP6-DNS" -#define NMC_FIELDS_DEV_LIST_SECTIONS_COMMON "GENERAL,CAPABILITIES,WIFI-PROPERTIES,AP,WIRED-PROPERTIES,IP4-SETTINGS,IP4-DNS,IP6-SETTINGS,IP6-DNS" +#define NMC_FIELDS_DEV_LIST_SECTIONS_ALL "GENERAL,CAPABILITIES,WIFI-PROPERTIES,AP,WIRED-PROPERTIES,WIMAX-PROPERTIES,NSP,IP4-SETTINGS,IP4-DNS,IP6-SETTINGS,IP6-DNS" +#define NMC_FIELDS_DEV_LIST_SECTIONS_COMMON "GENERAL,CAPABILITIES,WIFI-PROPERTIES,AP,WIRED-PROPERTIES,WIMAX-PROPERTIES,NSP,IP4-SETTINGS,IP4-DNS,IP6-SETTINGS,IP6-DNS" /* Available fields for 'dev list' - GENERAL part */ static NmcOutputField nmc_fields_dev_list_general[] = { @@ -130,6 +133,19 @@ static NmcOutputField nmc_fields_dev_list_wifi_prop[] = { #define NMC_FIELDS_DEV_LIST_WIFI_PROP_ALL "NAME,WEP,WPA,WPA2,TKIP,CCMP" #define NMC_FIELDS_DEV_LIST_WIFI_PROP_COMMON "NAME,WEP,WPA,WPA2,TKIP,CCMP" +/* Available fields for 'dev list' - wimax properties part */ +static NmcOutputField nmc_fields_dev_list_wimax_prop[] = { + {"NAME", N_("NAME"), 18, NULL, 0}, /* 0 */ + {"CTR-FREQ", N_("CTR-FREQ"), 7, NULL, 0}, /* 1 */ + {"RSSI", N_("RSSI"), 5, NULL, 0}, /* 2 */ + {"CINR", N_("CINR"), 5, NULL, 0}, /* 3 */ + {"TX-POW", N_("TX-POW"), 5, NULL, 0}, /* 4 */ + {"BSID", N_("BSID"), 18, NULL, 0}, /* 5 */ + {NULL, NULL, 0, NULL, 0} +}; +#define NMC_FIELDS_DEV_LIST_WIMAX_PROP_ALL "NAME,CTR-FREQ,RSSI,CINR,TX-POW,BSID" +#define NMC_FIELDS_DEV_LIST_WIMAX_PROP_COMMON "NAME,CTR-FREQ,RSSI,CINR,TX-POW,BSID" + /* Available fields for 'dev list' - IPv4 settings part */ static NmcOutputField nmc_fields_dev_list_ip4_settings[] = { {"NAME", N_("NAME"), 15, NULL, 0}, /* 0 */ @@ -184,12 +200,28 @@ static NmcOutputField nmc_fields_dev_wifi_list[] = { {"RSN-FLAGS", N_("RSN-FLAGS"), 25, NULL, 0}, /* 9 */ {"DEVICE", N_("DEVICE"), 10, NULL, 0}, /* 10 */ {"ACTIVE", N_("ACTIVE"), 8, NULL, 0}, /* 11 */ + {"DBUS-PATH", N_("DBUS-PATH"), 46, NULL, 0}, /* 12 */ {NULL, NULL, 0, NULL, 0} }; -#define NMC_FIELDS_DEV_WIFI_LIST_ALL "SSID,BSSID,MODE,FREQ,RATE,SIGNAL,SECURITY,WPA-FLAGS,RSN-FLAGS,DEVICE,ACTIVE" +#define NMC_FIELDS_DEV_WIFI_LIST_ALL "SSID,BSSID,MODE,FREQ,RATE,SIGNAL,SECURITY,WPA-FLAGS,RSN-FLAGS,DEVICE,ACTIVE,DBUS-PATH" #define NMC_FIELDS_DEV_WIFI_LIST_COMMON "SSID,BSSID,MODE,FREQ,RATE,SIGNAL,SECURITY,ACTIVE" #define NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST "NAME,"NMC_FIELDS_DEV_WIFI_LIST_COMMON +/* Available fields for 'dev wimax list' */ +static NmcOutputField nmc_fields_dev_wimax_list[] = { + {"NAME", N_("NAME"), 15, NULL, 0}, /* 0 */ + {"NSP", N_("NSP"), 33, NULL, 0}, /* 1 */ + {"SIGNAL", N_("SIGNAL"), 8, NULL, 0}, /* 2 */ + {"TYPE", N_("TYPE"), 16, NULL, 0}, /* 3 */ + {"DEVICE", N_("DEVICE"), 10, NULL, 0}, /* 4 */ + {"ACTIVE", N_("ACTIVE"), 8, NULL, 0}, /* 5 */ + {"DBUS-PATH", N_("DBUS-PATH"), 46, NULL, 0}, /* 6 */ + {NULL, NULL, 0, NULL, 0} +}; +#define NMC_FIELDS_DEV_WIMAX_LIST_ALL "NSP,SIGNAL,TYPE,DEVICE,ACTIVE,DBUS-PATH" +#define NMC_FIELDS_DEV_WIMAX_LIST_COMMON "NSP,SIGNAL,TYPE,DEVICE,ACTIVE" +#define NMC_FIELDS_DEV_WIMAX_LIST_FOR_DEV_LIST "NAME,"NMC_FIELDS_DEV_WIMAX_LIST_COMMON + /* static function prototypes */ static void usage (void); @@ -198,6 +230,7 @@ static NMCResultCode do_devices_status (NmCli *nmc, int argc, char **argv); static NMCResultCode do_devices_list (NmCli *nmc, int argc, char **argv); static NMCResultCode do_device_disconnect (NmCli *nmc, int argc, char **argv); static NMCResultCode do_device_wifi (NmCli *nmc, int argc, char **argv); +static NMCResultCode do_device_wimax (NmCli *nmc, int argc, char **argv); extern GMainLoop *loop; /* glib main loop variable */ @@ -207,11 +240,12 @@ usage (void) { fprintf (stderr, _("Usage: nmcli dev { COMMAND | help }\n\n" - " COMMAND := { status | list | disconnect | wifi }\n\n" + " COMMAND := { status | list | disconnect | wifi | wimax }\n\n" " status\n" " list [iface <iface>]\n" " disconnect iface <iface> [--nowait] [--timeout <timeout>]\n" - " wifi [list [iface <iface>] [hwaddr <hwaddr>]]\n\n")); + " wifi [list [iface <iface>] [hwaddr <hwaddr>]]\n" + " wimax [list [iface <iface>] [nsp <name>]]\n\n")); } /* quit main loop */ @@ -264,6 +298,8 @@ get_device_type (NMDevice * device) return NM_SETTING_BLUETOOTH_SETTING_NAME; // else if (NM_IS_DEVICE_OLPC_MESH (device)) // return NM_SETTING_OLPC_MESH_SETTING_NAME; + else if (NM_IS_DEVICE_WIMAX (device)) + return NM_SETTING_WIMAX_SETTING_NAME; else return _("Unknown"); } @@ -431,6 +467,7 @@ detail_access_point (gpointer data, gpointer user_data) info->nmc->allowed_fields[9].value = rsn_flags_str; info->nmc->allowed_fields[10].value = info->device; info->nmc->allowed_fields[11].value = active ? _("yes") : _("no"); + info->nmc->allowed_fields[12].value = nm_object_get_path (NM_OBJECT (ap)); info->nmc->print_fields.flags &= ~NMC_PF_FLAG_MAIN_HEADER_ADD & ~NMC_PF_FLAG_MAIN_HEADER_ONLY & ~NMC_PF_FLAG_FIELD_NAMES; /* Clear header flags */ print_fields (info->nmc->print_fields, info->nmc->allowed_fields); @@ -445,6 +482,52 @@ detail_access_point (gpointer data, gpointer user_data) g_string_free (security_str, TRUE); } +static void +detail_wimax_nsp (NMWimaxNsp *nsp, NmCli *nmc, NMDevice *dev, int idx) +{ + NMDeviceWimax *wimax = NM_DEVICE_WIMAX (dev); + char *nsp_name, *quality_str; + const char *ntype; + gboolean active = FALSE; + + switch (nm_wimax_nsp_get_network_type (nsp)) { + case NM_WIMAX_NSP_NETWORK_TYPE_HOME: + ntype = _("Home"); + break; + case NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: + ntype = _("Partner"); + break; + case NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: + ntype = _("Roaming"); + break; + default: + ntype = _("Unknown"); + break; + } + + if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { + if (nsp == nm_device_wimax_get_active_nsp (wimax)) + active = TRUE; + } + + quality_str = g_strdup_printf ("%u", nm_wimax_nsp_get_signal_quality (nsp)); + nsp_name = g_strdup_printf ("NSP%d", idx); /* NSP */ + + nmc->allowed_fields[0].value = nsp_name; + nmc->allowed_fields[1].value = nm_wimax_nsp_get_name (nsp); + nmc->allowed_fields[2].value = quality_str; + nmc->allowed_fields[3].value = ntype; + nmc->allowed_fields[4].value = nm_device_get_iface (dev); + nmc->allowed_fields[5].value = active ? _("yes") : _("no"); + nmc->allowed_fields[6].value = nm_object_get_path (NM_OBJECT (nsp)); + + nmc->print_fields.flags &= ~NMC_PF_FLAG_MAIN_HEADER_ADD & ~NMC_PF_FLAG_MAIN_HEADER_ONLY & ~NMC_PF_FLAG_FIELD_NAMES; /* Clear header flags */ + print_fields (nmc->print_fields, nmc->allowed_fields); + + g_free (nsp_name); + g_free (quality_str); +} + struct cb_info { NMClient *client; const GPtrArray *active; @@ -521,6 +604,8 @@ show_device_info (gpointer data, gpointer user_data) hwaddr = nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)); else if (NM_IS_DEVICE_WIFI (device)) hwaddr = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device)); + else if (NM_IS_DEVICE_WIMAX (device)) + hwaddr = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device)); nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[0].name; /* "GENERAL"*/ nmc->allowed_fields[1].value = nm_device_get_iface (device); @@ -631,6 +716,74 @@ show_device_info (gpointer data, gpointer user_data) print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */ was_output = TRUE; } + } else if (NM_IS_DEVICE_WIMAX (device)) { + /* WIMAX-PROPERTIES */ + if (!strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[5].name)) { + char *cfreq = NULL, *rssi = NULL, *cinr = NULL, *txpow = NULL; + guint tmp_uint; + gint tmp_int; + const char *bsid; + + nmc->allowed_fields = nmc_fields_dev_list_wimax_prop; + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_DEV_LIST_WIMAX_PROP_ALL, nmc->allowed_fields, NULL); + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + + nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[5].name; /* "WIMAX-PROPERTIES" */ + + /* Center frequency */ + tmp_uint = nm_device_wimax_get_center_frequency (NM_DEVICE_WIMAX (device)); + if (tmp_uint) + cfreq = g_strdup_printf ("%'.1f MHz", (double) tmp_uint / 1000.0); + nmc->allowed_fields[1].value = cfreq ? cfreq : ""; + + /* RSSI */ + tmp_int = nm_device_wimax_get_rssi (NM_DEVICE_WIMAX (device)); + if (tmp_int) + rssi = g_strdup_printf ("%d dBm", tmp_int); + nmc->allowed_fields[2].value = rssi ? rssi : ""; + + /* CINR */ + tmp_int = nm_device_wimax_get_cinr (NM_DEVICE_WIMAX (device)); + if (tmp_int) + cinr = g_strdup_printf ("%d dB", tmp_int); + nmc->allowed_fields[3].value = cinr ? cinr : ""; + + /* TX Power */ + tmp_int = nm_device_wimax_get_tx_power (NM_DEVICE_WIMAX (device)); + if (tmp_int) + txpow = g_strdup_printf ("%'.2f dBm", (float) tmp_int / 2.0); + nmc->allowed_fields[4].value = txpow ? txpow : ""; + + /* BSID */ + bsid = nm_device_wimax_get_bsid (NM_DEVICE_WIMAX (device)); + nmc->allowed_fields[5].value = bsid ? bsid : ""; + + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX; + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */ + was_output = TRUE; + } + + /* section NSP */ + if (!strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[6].name)) { + const GPtrArray *nsps; + int g, idx = 1; + + nmc->allowed_fields = nmc_fields_dev_wimax_list; + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_DEV_WIMAX_LIST_FOR_DEV_LIST, nmc->allowed_fields, NULL); + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX; + + nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device)); + for (g = 0; nsps && g < nsps->len; g++) { + NMWimaxNsp *nsp = g_ptr_array_index (nsps, g); + + detail_wimax_nsp (nsp, nmc, device, idx++); + } + was_output = TRUE; + } } /* IP Setup info */ @@ -640,7 +793,7 @@ show_device_info (gpointer data, gpointer user_data) GSList *iter; /* IP4-SETTINGS */ - if (cfg4 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[5].name)) { + if (cfg4 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[7].name)) { nmc->allowed_fields = nmc_fields_dev_list_ip4_settings; nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_DEV_LIST_IP4_SETTINGS_ALL, nmc->allowed_fields, NULL); @@ -660,7 +813,7 @@ show_device_info (gpointer data, gpointer user_data) gateway_str = ip4_address_as_string (nm_ip4_address_get_gateway (addr)); - nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[5].name; /* "IP4-SETTINGS" */ + nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[7].name; /* "IP4-SETTINGS" */ nmc->allowed_fields[1].value = addr_str; nmc->allowed_fields[2].value = prefix_str; nmc->allowed_fields[3].value = gateway_str; @@ -674,7 +827,7 @@ show_device_info (gpointer data, gpointer user_data) was_output = TRUE; } /* IP4-DNS */ - if (cfg4 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[6].name)) { + if (cfg4 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[8].name)) { array = nm_ip4_config_get_nameservers (cfg4); if (array) { int i; @@ -685,7 +838,7 @@ show_device_info (gpointer data, gpointer user_data) print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ for (i = 0; i < array->len; i++) { - char *dns_name = g_strdup_printf ("%s%d", nmc_fields_dev_list_sections[6].name, i+1); + char *dns_name = g_strdup_printf ("%s%d", nmc_fields_dev_list_sections[8].name, i+1); tmp = ip4_address_as_string (g_array_index (array, guint32, i)); nmc->allowed_fields[0].value = dns_name; /* "IP4-DNS<num>" */ nmc->allowed_fields[1].value = tmp; @@ -700,7 +853,7 @@ show_device_info (gpointer data, gpointer user_data) } /* IP6-SETTINGS */ - if (cfg6 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[7].name)) { + if (cfg6 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[9].name)) { nmc->allowed_fields = nmc_fields_dev_list_ip6_settings; nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_DEV_LIST_IP6_SETTINGS_ALL, nmc->allowed_fields, NULL); @@ -716,7 +869,7 @@ show_device_info (gpointer data, gpointer user_data) prefix_str = g_strdup_printf ("%d", prefix); gateway_str = ip6_address_as_string (nm_ip6_address_get_gateway (addr)); - nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[7].name; /* "IP6-SETTINGS" */ + nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[9].name; /* "IP6-SETTINGS" */ nmc->allowed_fields[1].value = addr_str; nmc->allowed_fields[2].value = prefix_str; nmc->allowed_fields[3].value = gateway_str; @@ -730,7 +883,7 @@ show_device_info (gpointer data, gpointer user_data) was_output = TRUE; } /* IP6-DNS */ - if (cfg6 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[8].name)) { + if (cfg6 && !strcasecmp (nmc_fields_dev_list_sections[section_idx].name, nmc_fields_dev_list_sections[10].name)) { int i = 1; nmc->allowed_fields = nmc_fields_dev_list_ip6_dns; nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; @@ -738,7 +891,7 @@ show_device_info (gpointer data, gpointer user_data) print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ for (iter = (GSList *) nm_ip6_config_get_nameservers (cfg6); iter; iter = g_slist_next (iter)) { - char *dns_name = g_strdup_printf ("%s%d", nmc_fields_dev_list_sections[8].name, i++); + char *dns_name = g_strdup_printf ("%s%d", nmc_fields_dev_list_sections[10].name, i++); tmp = ip6_address_as_string (iter->data); nmc->allowed_fields[0].value = dns_name; /* "IP6-DNS<num>" */ @@ -1244,6 +1397,199 @@ do_device_wifi (NmCli *nmc, int argc, char **argv) return nmc->return_value; } +static void +show_nsp_info (NMDevice *device, NmCli *nmc) +{ + const GPtrArray *nsps; + int i, idx = 1; + + nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device)); + for (i = 0; nsps && i < nsps->len; i++) { + NMWimaxNsp *nsp = g_ptr_array_index (nsps, i); + + detail_wimax_nsp (nsp, nmc, device, idx++); + } +} + +static NMCResultCode +do_device_wimax_list (NmCli *nmc, int argc, char **argv) +{ + GError *error = NULL; + NMDevice *device = NULL; + NMWimaxNsp *nsp = NULL; + const char *iface = NULL; + const char *nsp_user = NULL; + const GPtrArray *devices; + const GPtrArray *nsps; + int i, j; + char *fields_str; + char *fields_all = NMC_FIELDS_DEV_WIMAX_LIST_ALL; + char *fields_common = NMC_FIELDS_DEV_WIMAX_LIST_COMMON; + guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0; + guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0; + guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0; + + while (argc > 0) { + if (strcmp (*argv, "iface") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + iface = *argv; + } else if (strcmp (*argv, "nsp") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + nsp_user = *argv; + } else { + fprintf (stderr, _("Unknown parameter: %s\n"), *argv); + } + + argc--; + argv++; + } + + /* create NMClient */ + if (!nmc->get_client (nmc)) + goto error; + + devices = nm_client_get_devices (nmc->client); + + if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) + fields_str = fields_common; + else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0) + fields_str = fields_all; + else + fields_str = nmc->required_fields; + + nmc->allowed_fields = nmc_fields_dev_wimax_list; + nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error); + + if (error) { + if (error->code == 0) + g_string_printf (nmc->return_text, _("Error: 'dev wimax': %s"), error->message); + else + g_string_printf (nmc->return_text, _("Error: 'dev wimax': %s; allowed fields: %s"), error->message, NMC_FIELDS_DEV_WIMAX_LIST_ALL); + g_error_free (error); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES; + nmc->print_fields.header_name = _("WiMAX NSP list"); + + if (iface) { + /* Device specified - list only NSPs of this interface */ + for (i = 0; devices && (i < devices->len); i++) { + NMDevice *candidate = g_ptr_array_index (devices, i); + const char *dev_iface = nm_device_get_iface (candidate); + + if (!strcmp (dev_iface, iface)) { + device = candidate; + break; + } + } + + if (!device) { + g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + goto error; + } + + if (NM_IS_DEVICE_WIMAX (device)) { + if (nsp_user) { + /* Specific NSP requested - list only that */ + nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device)); + for (j = 0, nsp = NULL; nsps && (j < nsps->len); j++) { + NMWimaxNsp *candidate_nsp = g_ptr_array_index (nsps, j); + const char *candidate_name = nm_wimax_nsp_get_name (candidate_nsp); + char *nsp_up; + + nsp_up = g_ascii_strup (nsp_user, -1); + if (!strcmp (nsp_up, candidate_name)) + nsp = candidate_nsp; + g_free (nsp_up); + } + if (!nsp) { + g_string_printf (nmc->return_text, _("Error: NSP with name '%s' not found."), nsp_user); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + goto error; + } + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + detail_wimax_nsp (nsp, nmc, device, 1); + } else { + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + show_nsp_info (device, nmc); + } + } else { + g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiMAX device."), iface); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + goto error; + } + } else { + /* List NSPs for all devices */ + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + if (nsp_user) { + /* Specific NSP requested - list only that */ + for (i = 0; devices && (i < devices->len); i++) { + NMDevice *dev = g_ptr_array_index (devices, i); + int idx = 1; + + if (!NM_IS_DEVICE_WIMAX (dev)) + continue; + + nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (dev)); + for (j = 0, nsp = NULL; nsps && (j < nsps->len); j++) { + NMWimaxNsp *candidate_nsp = g_ptr_array_index (nsps, j); + const char *candidate_name = nm_wimax_nsp_get_name (candidate_nsp); + char *nsp_up; + + nsp_up = g_ascii_strup (nsp_user, -1); + if (!strcmp (nsp_up, candidate_name)) { + nsp = candidate_nsp; + detail_wimax_nsp (nsp, nmc, dev, idx); + } + g_free (nsp_up); + } + } + if (!nsp) { + g_string_printf (nmc->return_text, _("Error: Access point with hwaddr '%s' not found."), nsp_user); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + goto error; + } + } else { + for (i = 0; devices && (i < devices->len); i++) { + NMDevice *dev = g_ptr_array_index (devices, i); + if (NM_IS_DEVICE_WIMAX (dev)) + show_nsp_info (dev, nmc); + } + } + } + +error: + return nmc->return_value; +} + +static NMCResultCode +do_device_wimax (NmCli *nmc, int argc, char **argv) +{ + if (argc == 0) + nmc->return_value = do_device_wimax_list (nmc, argc-1, argv+1); + else if (argc > 0) { + if (matches (*argv, "list") == 0) { + nmc->return_value = do_device_wimax_list (nmc, argc-1, argv+1); + } + else { + g_string_printf (nmc->return_text, _("Error: 'dev wimax' command '%s' is not valid."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + } + } + + return nmc->return_value; +} NMCResultCode do_devices (NmCli *nmc, int argc, char **argv) @@ -1279,6 +1625,11 @@ do_devices (NmCli *nmc, int argc, char **argv) goto opt_error; nmc->return_value = do_device_wifi (nmc, argc-1, argv+1); } + else if (matches (*argv, "wimax") == 0) { + if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) + goto opt_error; + nmc->return_value = do_device_wimax (nmc, argc-1, argv+1); + } else if (strcmp (*argv, "help") == 0) { usage (); } diff --git a/cli/src/network-manager.c b/cli/src/network-manager.c index 23a2ef11e7..cd7201cc13 100644 --- a/cli/src/network-manager.c +++ b/cli/src/network-manager.c @@ -39,13 +39,16 @@ static NmcOutputField nmc_fields_nm_status[] = { {"WIFI", N_("WIFI"), 10, NULL, 0}, /* 4 */ {"WWAN-HARDWARE", N_("WWAN-HARDWARE"), 15, NULL, 0}, /* 5 */ {"WWAN", N_("WWAN"), 10, NULL, 0}, /* 6 */ - {NULL, NULL, 0, NULL, 0} + {"WIMAX-HARDWARE", N_("WIMAX-HARDWARE"), 15, NULL, 0}, /* 7 */ + {"WIMAX", N_("WIMAX"), 10, NULL, 0}, /* 8 */ + {NULL, NULL, 0, NULL, 0} }; -#define NMC_FIELDS_NM_STATUS_ALL "RUNNING,STATE,NET-ENABLED,WIFI-HARDWARE,WIFI,WWAN-HARDWARE,WWAN" +#define NMC_FIELDS_NM_STATUS_ALL "RUNNING,STATE,NET-ENABLED,WIFI-HARDWARE,WIFI,WWAN-HARDWARE,WWAN,WIMAX-HARDWARE,WIMAX" #define NMC_FIELDS_NM_STATUS_COMMON "RUNNING,STATE,WIFI-HARDWARE,WIFI,WWAN-HARDWARE,WWAN" #define NMC_FIELDS_NM_NET_ENABLED "NET-ENABLED" #define NMC_FIELDS_NM_WIFI "WIFI" #define NMC_FIELDS_NM_WWAN "WWAN" +#define NMC_FIELDS_NM_WIMAX "WIMAX" extern GMainLoop *loop; @@ -62,12 +65,13 @@ usage (void) { fprintf (stderr, _("Usage: nmcli nm { COMMAND | help }\n\n" - " COMMAND := { status | enable | sleep | wifi | wwan }\n\n" + " COMMAND := { status | enable | sleep | wifi | wwan | wimax }\n\n" " status\n" " enable [true|false]\n" " sleep [true|false]\n" " wifi [on|off]\n" - " wwan [on|off]\n\n")); + " wwan [on|off]\n" + " wimax [on|off]\n\n")); } /* quit main loop */ @@ -103,6 +107,7 @@ show_nm_status (NmCli *nmc) NMState state; const char *wireless_hw_enabled_str, *wireless_enabled_str; const char *wwan_hw_enabled_str, *wwan_enabled_str; + const char *wimax_hw_enabled_str, *wimax_enabled_str; GError *error = NULL; const char *fields_str; const char *fields_all = NMC_FIELDS_NM_STATUS_ALL; @@ -145,8 +150,10 @@ show_nm_status (NmCli *nmc) wireless_enabled_str = nm_client_wireless_get_enabled (nmc->client) ? _("enabled") : _("disabled"); wwan_hw_enabled_str = nm_client_wwan_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled"); wwan_enabled_str = nm_client_wwan_get_enabled (nmc->client) ? _("enabled") : _("disabled"); + wimax_hw_enabled_str = nm_client_wimax_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled"); + wimax_enabled_str = nm_client_wimax_get_enabled (nmc->client) ? _("enabled") : _("disabled"); } else { - wireless_hw_enabled_str = wireless_enabled_str = wwan_hw_enabled_str = wwan_enabled_str = _("unknown"); + wireless_hw_enabled_str = wireless_enabled_str = wwan_hw_enabled_str = wwan_enabled_str = wimax_hw_enabled_str = wimax_enabled_str = _("unknown"); } nmc->allowed_fields[0].value = nm_running ? _("running") : _("not running"); @@ -156,6 +163,8 @@ show_nm_status (NmCli *nmc) nmc->allowed_fields[4].value = wireless_enabled_str; nmc->allowed_fields[5].value = wwan_hw_enabled_str; nmc->allowed_fields[6].value = wwan_enabled_str; + nmc->allowed_fields[7].value = wimax_hw_enabled_str; + nmc->allowed_fields[8].value = wimax_enabled_str; nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag; print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */ @@ -208,6 +217,7 @@ do_network_manager (NmCli *nmc, int argc, char **argv) gboolean enable_net; gboolean enable_wifi; gboolean enable_wwan; + gboolean enable_wimax; guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0; guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0; guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0; @@ -341,6 +351,38 @@ do_network_manager (NmCli *nmc, int argc, char **argv) nm_client_wwan_set_enabled (nmc->client, enable_wwan); } } + else if (matches (*argv, "wimax") == 0) { + if (next_arg (&argc, &argv) != 0) { + if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error)) + goto opt_error; + /* no argument, show current WiMAX state */ + if (nmc->required_fields && strcasecmp (nmc->required_fields, "WIMAX")) { + g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here; allowed fields: %s"), + nmc->required_fields, NMC_FIELDS_NM_WIMAX); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto end; + } + nmc->allowed_fields = nmc_fields_nm_status; + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_NM_WIMAX, nmc->allowed_fields, NULL); + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_MAIN_HEADER_ADD | NMC_PF_FLAG_FIELD_NAMES; + nmc->print_fields.header_name = _("WiMAX enabled"); + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + nmc->allowed_fields[8].value = nm_client_wimax_get_enabled (nmc->client) ? _("enabled") : _("disabled"); + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag; + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */ + } else { + if (!strcmp (*argv, "on")) + enable_wimax = TRUE; + else if (!strcmp (*argv, "off")) + enable_wimax = FALSE; + else { + g_string_printf (nmc->return_text, _("Error: invalid 'wimax' parameter: '%s'."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto end; + } + nm_client_wimax_set_enabled (nmc->client, enable_wimax); + } + } else if (strcmp (*argv, "help") == 0) { usage (); } diff --git a/cli/src/settings.c b/cli/src/settings.c index 8b62876479..35711d9238 100644 --- a/cli/src/settings.c +++ b/cli/src/settings.c @@ -402,6 +402,18 @@ static NmcOutputField nmc_fields_setting_vpn[] = { NM_SETTING_VPN_SECRETS #define NMC_FIELDS_SETTING_VPN_COMMON NMC_FIELDS_SETTING_VPN_ALL +/* Available fields for NM_SETTING_WIMAX_SETTING_NAME */ +static NmcOutputField nmc_fields_setting_wimax[] = { + SETTING_FIELD ("name", 6), /* 0 */ + SETTING_FIELD (NM_SETTING_WIMAX_MAC_ADDRESS, 19), /* 1 */ + SETTING_FIELD (NM_SETTING_WIMAX_NETWORK_NAME, 40), /* 2 */ + {NULL, NULL, 0, NULL, 0} +}; +#define NMC_FIELDS_SETTING_WIMAX_ALL "name"","\ + NM_SETTING_WIMAX_MAC_ADDRESS","\ + NM_SETTING_WIMAX_NETWORK_NAME +#define NMC_FIELDS_SETTING_WIMAX_COMMON NMC_FIELDS_SETTING_WIMAX_ALL + static char * wep_key_type_to_string (NMWepKeyType type) @@ -1381,3 +1393,37 @@ setting_vpn_details (NMSetting *setting, NmCli *nmc) return TRUE; } +gboolean +setting_wimax_details (NMSetting *setting, NmCli *nmc) +{ + NMSettingWimax *s_wimax; + const GByteArray *mac; + char *device_mac_str = NULL; + guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0; + guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0; + guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0; + + g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), FALSE); + s_wimax = (NMSettingWimax *) setting; + + nmc->allowed_fields = nmc_fields_setting_wimax; + nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTING_WIMAX_ALL, nmc->allowed_fields, NULL); + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_FIELD_NAMES; + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print field names */ + + mac = nm_setting_wimax_get_mac_address (s_wimax); + if (mac) + device_mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", mac->data[0], mac->data[1], mac->data[2], mac->data[3], mac->data[4], mac->data[5]); + + nmc->allowed_fields[0].value = NM_SETTING_WIMAX_SETTING_NAME; + nmc->allowed_fields[1].value = device_mac_str; + nmc->allowed_fields[2].value = nm_setting_wimax_get_network_name (s_wimax); + + nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX; + print_fields (nmc->print_fields, nmc->allowed_fields); /* Print values */ + + g_free (device_mac_str); + + return TRUE; +} + diff --git a/cli/src/settings.h b/cli/src/settings.h index aec71551da..4901bf2725 100644 --- a/cli/src/settings.h +++ b/cli/src/settings.h @@ -35,6 +35,7 @@ #include <nm-setting-bluetooth.h> #include <nm-setting-olpc-mesh.h> #include <nm-setting-vpn.h> +#include <nm-setting-wimax.h> #include "nmcli.h" #include "utils.h" @@ -55,5 +56,6 @@ gboolean setting_cdma_details (NMSetting *setting, NmCli *nmc); gboolean setting_bluetooth_details (NMSetting *setting, NmCli *nmc); gboolean setting_olpc_mesh_details (NMSetting *setting, NmCli *nmc); gboolean setting_vpn_details (NMSetting *setting, NmCli *nmc); +gboolean setting_wimax_details (NMSetting *setting, NmCli *nmc); #endif /* NMC_SETTINGS_H */ diff --git a/configure.ac b/configure.ac index bc9733036e..a7b8b1a965 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.52) -AC_INIT(NetworkManager, 0.8.990, dcbw@redhat.com, NetworkManager) +AC_INIT(NetworkManager, 0.8.991, dcbw@redhat.com, NetworkManager) AM_INIT_AUTOMAKE([1.9 subdir-objects tar-ustar no-dist-gzip dist-bzip2]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])]) AM_MAINTAINER_MODE @@ -30,7 +30,7 @@ AC_SUBST([ACLOCAL_AMFLAGS]) dnl maintainer mode stuff if test $USE_MAINTAINER_MODE = yes; then - DISABLE_DEPRECATED="-DG_DISABLE_DEPRECATED -DGCONF_DISABLE_DEPRECATED" + DISABLE_DEPRECATED="-DG_DISABLE_DEPRECATED" else DISABLE_DEPRECATED="" fi @@ -281,6 +281,17 @@ PKG_CHECK_MODULES(UUID, uuid) AC_SUBST(UUID_CFLAGS) AC_SUBST(UUID_LIBS) +AC_ARG_ENABLE(wimax, AC_HELP_STRING([--enable-wimax], [enable WiMAX support]), + [enable_wimax=${enableval}], [enable_wimax=yes]) +if (test "${enable_wimax}" = "yes"); then + PKG_CHECK_MODULES(IWMX_SDK, libiWmxSdk-0 >= 1.5.1, dummy=yes, + AC_MSG_ERROR(Intel WiMAX SDK is required)) + AC_SUBST(IWMX_SDK_CFLAGS) + AC_SUBST(IWMX_SDK_LIBS) + AC_DEFINE(WITH_WIMAX, 1, [Define if you have WiMAX support]) +fi +AM_CONDITIONAL(WITH_WIMAX, test "${enable_wimax}" = "yes") + PKG_CHECK_MODULES(POLKIT, polkit-gobject-1) AC_SUBST(POLKIT_CFLAGS) @@ -531,6 +542,7 @@ src/logging/Makefile src/dns-manager/Makefile src/vpn-manager/Makefile src/dhcp-manager/Makefile +src/dhcp-manager/tests/Makefile src/ip6-manager/Makefile src/supplicant-manager/Makefile src/supplicant-manager/tests/Makefile @@ -539,6 +551,7 @@ src/dnsmasq-manager/Makefile src/modem-manager/Makefile src/bluez-manager/Makefile src/settings/Makefile +src/wimax/Makefile src/backends/Makefile libnm-util/libnm-util.pc libnm-util/Makefile @@ -637,6 +650,12 @@ else echo ConsoleKit support: no fi +if test "${enable_wimax}" = "yes"; then + echo WiMAX support: yes +else + echo WiMAX support: no +fi + echo echo Building documentation: ${with_docs} echo Building tests: ${with_tests} diff --git a/examples/C/Makefile.am b/examples/C/Makefile.am index 68c0697b0b..a8b5a64075 100644 --- a/examples/C/Makefile.am +++ b/examples/C/Makefile.am @@ -1,2 +1,54 @@ +INCLUDES = -I${top_srcdir}/libnm-util \ + -I${top_srcdir}/libnm-glib \ + -I${top_srcdir}/include + +AM_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(GLIB_CFLAGS) + +noinst_PROGRAMS = \ + add-connection-glib \ + get-active-connections \ + list-connections-dbus \ + list-connections-libnm-glib \ + get-ap-info-libnm-glib + +add_connection_glib_SOURCES = add-connection-glib.c +add_connection_glib_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) + +get_active_connections_SOURCES = get-active-connections.c +get_active_connections_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) + +list_connections_dbus_SOURCES = list-connections-dbus.c +list_connections_dbus_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) + +list_connections_libnm_glib_SOURCES = list-connections-libnm-glib.c +list_connections_libnm_glib_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(top_builddir)/libnm-glib/libnm-glib.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) + +get_ap_info_libnm_glib_SOURCES = get-ap-info-libnm-glib.c +get_ap_info_libnm_glib_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(top_builddir)/libnm-glib/libnm-glib.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) + EXTRA_DIST = \ - add-connection-glib.c + add-connection-glib.c \ + get-active-connections.c \ + list-connections-dbus.c \ + list-connections-libnm-glib.c \ + get-ap-info-libnm-glib.c + diff --git a/examples/C/add-connection-glib.c b/examples/C/add-connection-glib.c index 0e8dc18036..d650dc2f42 100644 --- a/examples/C/add-connection-glib.c +++ b/examples/C/add-connection-glib.c @@ -13,7 +13,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2010 Red Hat, Inc. + * (C) Copyright 2011 Red Hat, Inc. */ /* @@ -38,7 +38,8 @@ #define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) #define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT)) -void add_connection (DBusGProxy *proxy, const char *con_name) +static void +add_connection (DBusGProxy *proxy, const char *con_name) { NMConnection *connection; NMSettingConnection *s_con; @@ -98,7 +99,7 @@ int main (int argc, char *argv[]) /* Create a D-Bus proxy; NM_DBUS_* defined in NetworkManager.h */ proxy = dbus_g_proxy_new_for_name (bus, - NM_DBUS_SERVICE_SYSTEM_SETTINGS, + NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, NM_DBUS_IFACE_SETTINGS); diff --git a/examples/C/get-active-connections.c b/examples/C/get-active-connections.c new file mode 100644 index 0000000000..36224d29ad --- /dev/null +++ b/examples/C/get-active-connections.c @@ -0,0 +1,248 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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 2010 Red Hat, Inc. + */ + +/* + * The example shows how to call the D-Bus properties interface to get the + * list of currently active connections known to NetworkManager. It uses + * dbus-glib and libnm-util libraries. + * + * Compile with: + * gcc -Wall `pkg-config --libs --cflags glib-2.0 dbus-glib-1 libnm-util` get-active-connections.c -o get-active-connections + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> + +#include <nm-connection.h> +#include <nm-setting-connection.h> +#include <nm-setting-wired.h> +#include <nm-setting-ip4-config.h> +#include <NetworkManager.h> +#include <nm-utils.h> + +#define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) +#define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT)) +#define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH)) + +static void +print_connection (DBusGConnection *bus, const char *service, const char *path) +{ + DBusGProxy *proxy; + GError *error = NULL; + GHashTable *hash = NULL; + NMConnection *connection = NULL; + + /* This function asks the Settings Service that provides this network + * configuration for the details of that configuration. + */ + + /* Create the D-Bus proxy for the Settings Service so we can ask it for the + * connection configuration details. + */ + proxy = dbus_g_proxy_new_for_name (bus, + service, + path, + NM_DBUS_IFACE_SETTINGS_CONNECTION); + g_assert (proxy); + + /* Request the all the configuration of the Connection */ + if (!dbus_g_proxy_call (proxy, "GetSettings", &error, + G_TYPE_INVALID, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &hash, + G_TYPE_INVALID)) { + g_warning ("Failed to get active connection Connection property: %s", + error->message); + g_error_free (error); + goto out; + } + + /* Using the raw configuration, create an NMConnection object for it. This + * step also verifies that the data we got from the settings service is + * valid. */ + connection = nm_connection_new_from_hash (hash, &error); + if (!connection) { + g_warning ("Received invalid connection data: %s", error->message); + g_error_free (error); + goto out; + } + + /* And finally dump all the configuration to stdout */ + g_message ("%s => %s", service, path); + nm_connection_dump (connection); + +out: + if (connection) + g_object_unref (connection); + if (hash) + g_hash_table_destroy (hash); + g_object_unref (proxy); +} + +static void +get_active_connection_details (DBusGConnection *bus, const char *obj_path) +{ + DBusGProxy *props_proxy; + GValue path_value = { 0 }; + GValue serv_value = { 0 }; + GError *error = NULL; + const char *path = NULL, *service = NULL; + + /* This function gets the backing Connection object that describes the + * network configuration that the ActiveConnection object is actually using. + * The ActiveConnection object contains the mapping between the configuration + * and the actual network interfaces that are using that configuration. + */ + + /* Create a D-Bus object proxy for the active connection object's properties */ + props_proxy = dbus_g_proxy_new_for_name (bus, + NM_DBUS_SERVICE, + obj_path, + DBUS_INTERFACE_PROPERTIES); + g_assert (props_proxy); + + /* Get the object path of the Connection details */ + if (!dbus_g_proxy_call (props_proxy, "Get", &error, + G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + G_TYPE_STRING, "Connection", + G_TYPE_INVALID, + G_TYPE_VALUE, &path_value, + G_TYPE_INVALID)) { + g_warning ("Failed to get active connection Connection property: %s", + error->message); + g_error_free (error); + goto out; + } + + if (!G_VALUE_HOLDS (&path_value, DBUS_TYPE_G_OBJECT_PATH)) { + g_warning ("Unexpected type returned getting Connection property: %s", + G_VALUE_TYPE_NAME (&path_value)); + goto out; + } + + path = g_value_get_boxed (&path_value); + if (!path) { + g_warning ("Missing connection path!"); + goto out; + } + + /* Get the service name of the D-Bus service that provides the Connection */ + if (!dbus_g_proxy_call (props_proxy, "Get", &error, + G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + G_TYPE_STRING, "ServiceName", + G_TYPE_INVALID, + G_TYPE_VALUE, &serv_value, + G_TYPE_INVALID)) { + g_warning ("Failed to get active connection ServiceName property: %s", + error->message); + g_error_free (error); + goto out; + } + + if (!G_VALUE_HOLDS (&serv_value, G_TYPE_STRING)) { + g_warning ("Unexpected type returned getting Connection property: %s", + G_VALUE_TYPE_NAME (&serv_value)); + goto out; + } + + service = g_value_get_string (&serv_value); + if (!service) { + g_warning ("Missing connection service name!"); + goto out; + } + + /* Print out the actual connection details */ + print_connection (bus, service, path); + +out: + g_value_unset (&path_value); + g_value_unset (&serv_value); + g_object_unref (props_proxy); +} + +static void +get_active_connections (DBusGConnection *bus, DBusGProxy *proxy) +{ + GError *error = NULL; + GValue value = { 0 }; + GPtrArray *paths = NULL; + int i; + + /* Get the ActiveConnections property from the NM Manager object */ + if (!dbus_g_proxy_call (proxy, "Get", &error, + G_TYPE_STRING, NM_DBUS_INTERFACE, + G_TYPE_STRING, "ActiveConnections", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + g_warning ("Failed to get ActiveConnections property: %s", error->message); + g_error_free (error); + return; + } + + /* Make sure the ActiveConnections property is the type we expect it to be */ + if (!G_VALUE_HOLDS (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH)) { + g_warning ("Unexpected type returned getting ActiveConnections: %s", + G_VALUE_TYPE_NAME (&value)); + goto out; + } + + /* Extract the active connections array from the GValue */ + paths = g_value_get_boxed (&value); + if (!paths) { + g_warning ("Could not retrieve active connections property"); + goto out; + } + + /* And print out the details of each active connection */ + for (i = 0; i < paths->len; i++) + get_active_connection_details (bus, g_ptr_array_index (paths, i)); + +out: + g_value_unset (&value); +} + + +int main (int argc, char *argv[]) +{ + DBusGConnection *bus; + DBusGProxy *props_proxy; + + /* Initialize GType system */ + g_type_init (); + + /* Get system bus */ + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); + + /* Create a D-Bus proxy to get the object properties from the NM Manager + * object. NM_DBUS_* defines are from NetworkManager.h. + */ + props_proxy = dbus_g_proxy_new_for_name (bus, + NM_DBUS_SERVICE, + NM_DBUS_PATH, + DBUS_INTERFACE_PROPERTIES); + g_assert (props_proxy); + + /* Get active connections */ + get_active_connections (bus, props_proxy); + + g_object_unref (props_proxy); + dbus_g_connection_unref (bus); + + return 0; +} diff --git a/examples/C/get-ap-info-libnm-glib.c b/examples/C/get-ap-info-libnm-glib.c new file mode 100644 index 0000000000..6ff310d821 --- /dev/null +++ b/examples/C/get-ap-info-libnm-glib.c @@ -0,0 +1,229 @@ +/* + * 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 2010 Red Hat, Inc. + */ + +/* + * The example shows how to get info about APs visible by Wi-Fi devices + * using libnm-glib (that wraps direct D-Bus calls). + * The example uses dbus-glib, libnm-util and libnm-glib libraries. + * + * Compile with: + * gcc -Wall `pkg-config --libs --cflags glib-2.0 dbus-glib-1 libnm-util libnm-glib` get-ap-info-libnm-glib.c -o get-ap-info-libnm-glib + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <stdio.h> +#include <stdlib.h> + +#include <nm-client.h> +#include <nm-device.h> +#include <nm-device-wifi.h> +#include <nm-access-point.h> +#include <NetworkManager.h> +#include <nm-utils.h> + +/* Convert flags to string */ +static char * +ap_wpa_rsn_flags_to_string (guint32 flags) +{ + char *flags_str[16]; /* Enough space for flags and terminating NULL */ + char *ret_str; + int i = 0; + + if (flags & NM_802_11_AP_SEC_PAIR_WEP40) + flags_str[i++] = g_strdup ("pair_wpe40"); + if (flags & NM_802_11_AP_SEC_PAIR_WEP104) + flags_str[i++] = g_strdup ("pair_wpe104"); + if (flags & NM_802_11_AP_SEC_PAIR_TKIP) + flags_str[i++] = g_strdup ("pair_tkip"); + if (flags & NM_802_11_AP_SEC_PAIR_CCMP) + flags_str[i++] = g_strdup ("pair_ccmp"); + if (flags & NM_802_11_AP_SEC_GROUP_WEP40) + flags_str[i++] = g_strdup ("group_wpe40"); + if (flags & NM_802_11_AP_SEC_GROUP_WEP104) + flags_str[i++] = g_strdup ("group_wpe104"); + if (flags & NM_802_11_AP_SEC_GROUP_TKIP) + flags_str[i++] = g_strdup ("group_tkip"); + if (flags & NM_802_11_AP_SEC_GROUP_CCMP) + flags_str[i++] = g_strdup ("group_ccmp"); + if (flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + flags_str[i++] = g_strdup ("psk"); + if (flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + flags_str[i++] = g_strdup ("802.1X"); + + if (i == 0) + flags_str[i++] = g_strdup ("none"); + + flags_str[i] = NULL; + + ret_str = g_strjoinv (" ", flags_str); + + i = 0; + while (flags_str[i]) + g_free (flags_str[i++]); + + return ret_str; +} + +static void +show_access_point_info (NMAccessPoint *ap) +{ + guint32 flags, wpa_flags, rsn_flags, freq, bitrate; + guint8 strength; + const GByteArray *ssid; + const char *hwaddr; + NM80211Mode mode; + char *freq_str, *ssid_str, *bitrate_str, *strength_str, *wpa_flags_str, *rsn_flags_str; + GString *security_str; + + /* Get AP properties */ + flags = nm_access_point_get_flags (ap); + wpa_flags = nm_access_point_get_wpa_flags (ap); + rsn_flags = nm_access_point_get_rsn_flags (ap); + ssid = nm_access_point_get_ssid (ap); + hwaddr = nm_access_point_get_hw_address (ap); + freq = nm_access_point_get_frequency (ap); + mode = nm_access_point_get_mode (ap); + bitrate = nm_access_point_get_max_bitrate (ap); + strength = nm_access_point_get_strength (ap); + + /* Convert to strings */ + ssid_str = nm_utils_ssid_to_utf8 ((const char *) ssid->data, ssid->len); + freq_str = g_strdup_printf ("%u MHz", freq); + bitrate_str = g_strdup_printf ("%u MB/s", bitrate/1000); + strength_str = g_strdup_printf ("%u", strength); + wpa_flags_str = ap_wpa_rsn_flags_to_string (wpa_flags); + rsn_flags_str = ap_wpa_rsn_flags_to_string (rsn_flags); + + security_str = g_string_new (NULL); + if ( !(flags & NM_802_11_AP_FLAGS_PRIVACY) + && (wpa_flags != NM_802_11_AP_SEC_NONE) + && (rsn_flags != NM_802_11_AP_SEC_NONE)) + g_string_append (security_str, "Encrypted: "); + + if ( (flags & NM_802_11_AP_FLAGS_PRIVACY) + && (wpa_flags == NM_802_11_AP_SEC_NONE) + && (rsn_flags == NM_802_11_AP_SEC_NONE)) + g_string_append (security_str, "WEP "); + if (wpa_flags != NM_802_11_AP_SEC_NONE) + g_string_append (security_str, "WPA "); + if (rsn_flags != NM_802_11_AP_SEC_NONE) + g_string_append (security_str, "WPA2 "); + if ( (wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + || (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + g_string_append (security_str, "Enterprise "); + + if (security_str->len > 0) + g_string_truncate (security_str, security_str->len-1); /* Chop off last space */ + + printf ("SSID: %s\n", ssid_str); + printf ("BSSID: %s\n", hwaddr); + printf ("Mode: %s\n", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc" : mode == NM_802_11_MODE_INFRA ? "Infrastructure" : "Unknown"); + printf ("Freq: %s\n", freq_str); + printf ("Bitrate: %s\n", bitrate_str); + printf ("Strength: %s\n", strength_str); + printf ("Security: %s\n", security_str->str); + printf ("WPA flags: %s\n", wpa_flags_str); + printf ("RSN flags: %s\n", rsn_flags_str); + printf ("D-Bus path: %s\n\n", nm_object_get_path (NM_OBJECT (ap))); + + g_free (ssid_str); + g_free (freq_str); + g_free (bitrate_str); + g_free (strength_str); + g_free (wpa_flags_str); + g_free (rsn_flags_str); + g_string_free (security_str, TRUE); +} + +static void +show_wifi_device_info (NMDevice *device) +{ + NMAccessPoint *active_ap = NULL; + const GPtrArray *aps; + const char *iface; + const char *driver; + guint32 speed; + const GByteArray *active_ssid; + char *active_ssid_str = NULL; + int i; + + /* Get active AP */ + if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) { + if ((active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (device)))) { + active_ssid = nm_access_point_get_ssid (active_ap); + active_ssid_str = nm_utils_ssid_to_utf8 ((const char *) active_ssid->data, active_ssid->len); + } + } + + iface = nm_device_get_iface (device); + driver = nm_device_get_driver (device); + speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (device)); + speed /= 1000; + + printf ("Device: %s ---- Driver: %s ---- Speed: %d MB/s ---- Active AP: %s\n", + iface, driver, speed, active_ssid_str ? active_ssid_str : "none"); + printf ("=================================================================================\n"); + g_free (active_ssid_str); + + /* Get all APs of the Wi-Fi device */ + aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)); + + /* Print AP details */ + for (i = 0; aps && (i < aps->len); i++) { + NMAccessPoint *ap = g_ptr_array_index (aps, i); + show_access_point_info (ap); + } +} + +int main (int argc, char *argv[]) +{ + DBusGConnection *bus; + NMClient *client; + const GPtrArray *devices; + int i; + + /* Initialize GType system */ + g_type_init (); + + /* Get system bus */ + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); + + /* Get NMClient object */ + client = nm_client_new (); + if (!client) { + dbus_g_connection_unref (bus); + g_message ("Error: Could not create NMClient."); + return EXIT_FAILURE; + } + + /* Get all devices managed by NetworkManager */ + devices = nm_client_get_devices (client); + + /* Go through the array and process Wi-Fi devices */ + for (i = 0; devices && (i < devices->len); i++) { + NMDevice *device = g_ptr_array_index (devices, i); + if (NM_IS_DEVICE_WIFI (device)) + show_wifi_device_info (device); + } + + g_object_unref (client); + dbus_g_connection_unref (bus); + + return EXIT_SUCCESS; +} diff --git a/examples/C/list-connections-dbus.c b/examples/C/list-connections-dbus.c new file mode 100644 index 0000000000..2cb584b59b --- /dev/null +++ b/examples/C/list-connections-dbus.c @@ -0,0 +1,83 @@ +/* + * 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 2011 Red Hat, Inc. + */ + +/* + * The example shows how to list connections from System Settings service using direct + * D-Bus call of ListConnections method. + * The example uses dbus-glib, libnm-util libraries. + * + * Compile with: + * gcc -Wall `pkg-config --libs --cflags glib-2.0 dbus-glib-1 libnm-util` list-connections-dbus.c -o list-connections-dbus + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <stdio.h> + +#include <NetworkManager.h> +#include <nm-utils.h> + +#define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH)) + +static void +list_connections (DBusGProxy *proxy) +{ + int i; + GError *error = NULL; + GPtrArray *con_array; + + /* Call ListConnections D-Bus method */ + dbus_g_proxy_call (proxy, "ListConnections", &error, + /* No input arguments */ + G_TYPE_INVALID, + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &con_array, /* Return values */ + G_TYPE_INVALID); + + for (i = 0; con_array && i < con_array->len; i++) { + char *connection_path = g_ptr_array_index (con_array, i); + printf ("%s\n", connection_path); + g_free (connection_path); + } + g_ptr_array_free (con_array, TRUE); +} + +int main (int argc, char *argv[]) +{ + DBusGConnection *bus; + DBusGProxy *proxy; + + /* Initialize GType system */ + g_type_init (); + + /* Get system bus */ + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); + + /* Create a D-Bus proxy; NM_DBUS_* defined in NetworkManager.h */ + proxy = dbus_g_proxy_new_for_name (bus, + NM_DBUS_SERVICE, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS); + + /* List connections of system settings service */ + list_connections (proxy); + + g_object_unref (proxy); + dbus_g_connection_unref (bus); + + return 0; +} diff --git a/examples/C/list-connections-libnm-glib.c b/examples/C/list-connections-libnm-glib.c new file mode 100644 index 0000000000..edb5ccc34b --- /dev/null +++ b/examples/C/list-connections-libnm-glib.c @@ -0,0 +1,176 @@ +/* + * 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 2011 Red Hat, Inc. + */ + +/* + * The example shows how to list connections from System Settings service using libnm-glib + * (that wraps direct D-Bus calls). + * The example uses dbus-glib, libnm-util and libnm-glib libraries. + * + * Compile with: + * gcc -Wall `pkg-config --libs --cflags glib-2.0 dbus-glib-1 libnm-util libnm-glib` list-connections-libnm-glib.c -o list-connections-libnm-glib + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> + +#include <nm-connection.h> +#include <nm-setting-connection.h> +#include <NetworkManager.h> +#include <nm-utils.h> +#include <nm-remote-settings.h> + + +/* Global variables */ +GMainLoop *loop = NULL; /* Main loop variable - needed for waiting for signal */ +int result = EXIT_SUCCESS; + +static void +signal_handler (int signo) +{ + if (signo == SIGINT || signo == SIGTERM) { + g_message ("Caught signal %d, shutting down...", signo); + g_main_loop_quit (loop); + } +} + +static void +setup_signals (void) +{ + struct sigaction action; + sigset_t mask; + + sigemptyset (&mask); + action.sa_handler = signal_handler; + action.sa_mask = mask; + action.sa_flags = 0; + sigaction (SIGTERM, &action, NULL); + sigaction (SIGINT, &action, NULL); +} + +/* Print details of connection */ +static void +show_connection (NMConnection *data, gpointer user_data) +{ + NMConnection *connection = (NMConnection *) data; + NMSettingConnection *s_con; + guint64 timestamp; + char *timestamp_str; + char timestamp_real_str[64]; + const char *val1, *val2, *val3, *val4, *val5; + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + if (s_con) { + /* Get various info from NMSettingConnection and show it */ + timestamp = nm_setting_connection_get_timestamp (s_con); + timestamp_str = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp); + strftime (timestamp_real_str, sizeof (timestamp_real_str), "%c", localtime ((time_t *) ×tamp)); + + val1 = nm_setting_connection_get_id (s_con); + val2 = nm_setting_connection_get_uuid (s_con); + val3 = nm_setting_connection_get_connection_type (s_con); + val4 = nm_connection_get_path (connection); + val5 = timestamp ? timestamp_real_str : "never"; + + printf ("%-25s | %s | %-15s | %-43s | %s\n", val1, val2, val3, val4, val5); + + g_free (timestamp_str); + } +} + +/* This callback is called when connections from the settings service are ready. + * Now the connections can be listed. + */ +static void +get_connections_cb (NMRemoteSettings *settings, gpointer user_data) +{ + GSList *connections; + + connections = nm_remote_settings_list_connections (settings); + + printf ("Connections:\n===================\n"); + + g_slist_foreach (connections, (GFunc) show_connection, NULL); + + g_slist_free (connections); + g_object_unref (settings); + + /* We are done, exit main loop */ + g_main_loop_quit (loop); +} + +/* Get system settings and then connect to connections-read signal */ +static gboolean +list_connections (gpointer data) +{ + DBusGConnection *bus = (DBusGConnection *) data; + NMRemoteSettings *settings; + gboolean settings_running; + + /* Get system settings */ + if (!(settings = nm_remote_settings_new (bus))) { + g_message ("Error: Could not get system settings."); + result = EXIT_FAILURE; + g_main_loop_quit (loop); + return FALSE; + } + + /* Find out whether setting service is running */ + g_object_get (settings, NM_REMOTE_SETTINGS_SERVICE_RUNNING, &settings_running, NULL); + + if (!settings_running) { + g_message ("Error: Can't obtain connections: settings service is not running."); + result = EXIT_FAILURE; + g_main_loop_quit (loop); + return FALSE; + } + + /* Connect to signal "connections-read" - emitted when connections are fetched and ready */ + g_signal_connect (settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ, + G_CALLBACK (get_connections_cb), NULL); + + return FALSE; +} + +int main (int argc, char *argv[]) +{ + DBusGConnection *bus; + + /* Initialize GType system */ + g_type_init (); + + /* Get system bus */ + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); + + /* Run list_connections from main loop, because we need to wait for "connections-read" + * signal to have connections ready. The execution will be finished in get_connections_cb() + * callback on the signal. + */ + g_idle_add (list_connections, bus); + + loop = g_main_loop_new (NULL, FALSE); /* Create main loop */ + setup_signals (); /* Setup UNIX signals */ + g_main_loop_run (loop); /* Run main loop */ + + g_main_loop_unref (loop); + dbus_g_connection_unref (bus); + + return result; +} diff --git a/examples/python/nm-state.py b/examples/python/nm-state.py index 42c96bf56d..051e8ce087 100644 --- a/examples/python/nm-state.py +++ b/examples/python/nm-state.py @@ -47,12 +47,12 @@ active = manager_prop_iface.Get("org.freedesktop.NetworkManager", "ActiveConnect for a in active: ac_proxy = bus.get_object("org.freedesktop.NetworkManager", a) prop_iface = dbus.Interface(ac_proxy, "org.freedesktop.DBus.Properties") - state = prop_iface.Get("org.freedesktop.NetworkManager.ActiveConnection", "State") + state = prop_iface.Get("org.freedesktop.NetworkManager.Connection.Active", "State") # Connections in NM are a collection of settings that describe everything # needed to connect to a specific network. Lets get those details so we # can find the user-readable name of the connection. - con_path = prop_iface.Get("org.freedesktop.NetworkManager.ActiveConnection", "Connection") + con_path = prop_iface.Get("org.freedesktop.NetworkManager.Connection.Active", "Connection") service_proxy = bus.get_object("org.freedesktop.NetworkManager", con_path) con_iface = dbus.Interface(service_proxy, "org.freedesktop.NetworkManager.Settings.Connection") con_details = con_iface.GetSettings() diff --git a/include/NetworkManager.h b/include/NetworkManager.h index 95f0653536..924d044eef 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -38,6 +38,9 @@ #define NM_DBUS_INTERFACE_SERIAL_DEVICE NM_DBUS_INTERFACE_DEVICE ".Serial" #define NM_DBUS_INTERFACE_GSM_DEVICE NM_DBUS_INTERFACE_DEVICE ".Gsm" #define NM_DBUS_INTERFACE_CDMA_DEVICE NM_DBUS_INTERFACE_DEVICE ".Cdma" +#define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" +#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" +#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp" #define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" #define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" #define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" @@ -82,6 +85,7 @@ typedef enum NMDeviceType NM_DEVICE_TYPE_GSM, NM_DEVICE_TYPE_CDMA, NM_DEVICE_TYPE_BT, /* Bluetooth */ + NM_DEVICE_TYPE_WIMAX, NM_DEVICE_TYPE_OLPC_MESH } NMDeviceType; diff --git a/initscript/Slackware/rc.networkmanager.in b/initscript/Slackware/rc.networkmanager.in index 048903847a..6eed87e196 100644 --- a/initscript/Slackware/rc.networkmanager.in +++ b/initscript/Slackware/rc.networkmanager.in @@ -27,11 +27,6 @@ nm_start() return fi - if [ "`pgrep hald`" = "" ]; then - echo "HAL must be running to start NetworkManager" - return - fi - # Just in case the pidfile is still there, we may need to nuke it. if [ -e "$PIDFILE" ]; then rm -f $PIDFILE @@ -67,6 +62,7 @@ nm_stop() nm_restart() { nm_stop + sleep 2 nm_start } diff --git a/introspection/Makefile.am b/introspection/Makefile.am index 54877c7545..42640e3020 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -11,6 +11,7 @@ EXTRA_DIST = \ nm-device-cdma.xml \ nm-device-gsm.xml \ nm-device-serial.xml \ + nm-device-wimax.xml \ nm-device.xml \ nm-ip4-config.xml \ nm-ip6-config.xml \ @@ -24,5 +25,6 @@ EXTRA_DIST = \ nm-active-connection.xml \ nm-dhcp4-config.xml \ nm-dhcp6-config.xml \ - nm-agent-manager.xml + nm-agent-manager.xml \ + nm-wimax-nsp.xml diff --git a/introspection/all.xml b/introspection/all.xml index 73084e1cec..fb2b749e8b 100644 --- a/introspection/all.xml +++ b/introspection/all.xml @@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</ <xi:include href="nm-device-serial.xml"/> <xi:include href="nm-device-bt.xml"/> <xi:include href="nm-device-olpc-mesh.xml"/> +<xi:include href="nm-device-wimax.xml"/> +<xi:include href="nm-wimax-nsp.xml"/> <xi:include href="nm-ip4-config.xml"/> <xi:include href="nm-ip6-config.xml"/> <xi:include href="nm-dhcp4-config.xml"/> diff --git a/introspection/nm-device-wimax.xml b/introspection/nm-device-wimax.xml new file mode 100644 index 0000000000..6e414087fa --- /dev/null +++ b/introspection/nm-device-wimax.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <interface name="org.freedesktop.NetworkManager.Device.WiMax"> + <method name="GetNspList"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_get_nsp_list"/> + <arg name="nsps" type="ao" direction="out"> + <tp:docstring> + List of NSP object paths + </tp:docstring> + </arg> + <tp:docstring> + Get the list of NSPs visible to this device. + </tp:docstring> + </method> + + <property name="HwAddress" type="s" access="read"> + <tp:docstring> + Hardware address of the device. + </tp:docstring> + </property> + + <property name="CenterFrequency" type="u" access="read"> + <tp:docstring> + Center frequency (in KHz) of the radio channel the device is using to + communicate with the network when connected. Has no meaning when the + device is not connected. + </tp:docstring> + </property> + + <property name="Rssi" type="i" access="read"> + <tp:docstring> + RSSI of the current radio link in dBm. This value indicates how strong + the raw received RF signal from the base station is, but does not + indicate the overall quality of the radio link. Has no meaning when the + device is not connected. + </tp:docstring> + </property> + + <property name="Cinr" type="i" access="read"> + <tp:docstring> + CINR (Carrier to Interference + Noise Ratio) of the current radio link + in dB. CINR is a more accurate measure of radio link quality. Has no + meaning when the device is not connected. + </tp:docstring> + </property> + + <property name="TxPower" type="i" access="read"> + <tp:docstring> + Average power of the last burst transmitted by the device, in units of + 0.5 dBm. i.e. a TxPower of -11 represents an actual device TX power of + -5.5 dBm. Has no meaning when the device is not connected. + </tp:docstring> + </property> + + <property name="Bsid" type="s" access="read"> + <tp:docstring> + The ID of the serving base station as received from the network. Has + no meaning when the device is not connected. + </tp:docstring> + </property> + + <property name="ActiveNsp" type="o" access="read"> + <tp:docstring> + Object path of the NSP currently used by the WiMax device. + </tp:docstring> + </property> + + <signal name="PropertiesChanged"> + <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> + <tp:docstring> + A dictionary mapping property names to variant boxed values. + </tp:docstring> + </arg> + <tp:docstring> + Emitted when the WiMax device's properties changed. + </tp:docstring> + </signal> + + <signal name="NspAdded"> + <arg name="nsp" type="o"> + <tp:docstring> + The object path of the newly found NSP. + </tp:docstring> + </arg> + <tp:docstring> + Emitted when a new NSP is found by the device. + </tp:docstring> + </signal> + + <signal name="NspRemoved"> + <arg name="nsp" type="o"> + <tp:docstring> + The object path of the NSP that has disappeared. + </tp:docstring> + </arg> + <tp:docstring> + Emitted when an NSP disappears from view of the device. + </tp:docstring> + </signal> + + </interface> +</node> diff --git a/introspection/nm-manager-client.xml b/introspection/nm-manager-client.xml index 9dde9ddfb3..ba2b25b91a 100644 --- a/introspection/nm-manager-client.xml +++ b/introspection/nm-manager-client.xml @@ -69,6 +69,8 @@ object. dbus-glib generates the same bound function names for D-Bus the methods <property name="WirelessHardwareEnabled" type="b" access="read"/> <property name="WwanEnabled" type="b" access="readwrite"/> <property name="WwanHardwareEnabled" type="b" access="read"/> + <property name="WimaxEnabled" type="b" access="readwrite"/> + <property name="WimaxHardwareEnabled" type="b" access="read"/> <property name="ActiveConnections" type="ao" access="read"/> <property name="Version" type="s" access="read"/> <property name="State" type="u" access="read"/> diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml index 5e087a2634..9a8f34dea7 100644 --- a/introspection/nm-manager.xml +++ b/introspection/nm-manager.xml @@ -243,6 +243,18 @@ </tp:docstring> </property> + <property name="WimaxEnabled" type="b" access="readwrite"> + <tp:docstring> + Indicates if WiMAX devices are currently enabled or not. + </tp:docstring> + </property> + + <property name="WimaxHardwareEnabled" type="b" access="read"> + <tp:docstring> + Indicates if the WiMAX hardware is currently enabled, i.e. the state of the RF kill switch. + </tp:docstring> + </property> + <property name="ActiveConnections" type="ao" access="read"> <tp:docstring> List of active connection object paths. diff --git a/introspection/nm-wimax-nsp.xml b/introspection/nm-wimax-nsp.xml new file mode 100644 index 0000000000..55ac4abcf2 --- /dev/null +++ b/introspection/nm-wimax-nsp.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <interface name="org.freedesktop.NetworkManager.WiMax.Nsp"> + + <property name="Name" type="s" access="read"> + <tp:docstring>The name of the NSP.</tp:docstring> + </property> + <property name="SignalQuality" type="u" access="read"> + <tp:docstring>The current signal quality of the NSP, in percent.</tp:docstring> + </property> + <property name="NetworkType" type="u" access="read" tp:type="NM_WIMAX_NSP_NETWORK_TYPE"> + <tp:docstring>The network type of the NSP.</tp:docstring> + </property> + + <signal name="PropertiesChanged"> + <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> + <tp:docstring> + A dictionary mapping property names to variant boxed values. + </tp:docstring> + </arg> + </signal> + + <tp:flags name="NM_WIMAX_NSP_NETWORK_TYPE" value-prefix="NM_WIMAX_NSP_NETWORK_TYPE" type="u"> + <tp:docstring> + Network type of the NSP. + </tp:docstring> + <tp:flag suffix="UNKNOWN" value="0x0"> + <tp:docstring>Unknown network.</tp:docstring> + </tp:flag> + <tp:flag suffix="HOME" value="0x1"> + <tp:docstring>Home network.</tp:docstring> + </tp:flag> + <tp:flag suffix="PARTNER" value="0x2"> + <tp:docstring>Partner network.</tp:docstring> + </tp:flag> + <tp:flag suffix="ROAMING_PARTNER" value="0x3"> + <tp:docstring>Roaming partner network.</tp:docstring> + </tp:flag> + + </tp:flags> + + </interface> +</node> diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 55c994adf0..bedc9805b6 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -13,6 +13,7 @@ BUILT_SOURCES = \ nm-device-wifi-bindings.h \ nm-device-bt-bindings.h \ nm-sysconfig-connection-bindings.h \ + nm-device-wimax-bindings.h \ nm-settings-bindings.h \ nm-vpn-connection-bindings.h \ nm-vpn-plugin-glue.h \ @@ -55,7 +56,6 @@ lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la libnm_glib_la_CFLAGS = \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ - $(GCONF_CFLAGS) \ $(GUDEV_CFLAGS) libnmincludedir = $(includedir)/libnm-glib @@ -83,7 +83,9 @@ libnminclude_HEADERS = \ nm-dhcp6-config.h \ nm-remote-connection.h \ nm-remote-settings.h \ - nm-secret-agent.h + nm-secret-agent.h \ + nm-device-wimax.h \ + nm-wimax-nsp.h libnm_glib_la_SOURCES = \ nm-object.c \ @@ -113,7 +115,9 @@ libnm_glib_la_SOURCES = \ nm-remote-connection.c \ nm-remote-connection-private.h \ nm-remote-settings.c \ - nm-secret-agent.c + nm-secret-agent.c \ + nm-device-wimax.c \ + nm-wimax-nsp.c libnm_glib_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ @@ -121,7 +125,6 @@ libnm_glib_la_LIBADD = \ $(builddir)/libdeprecated-nm-glib.la \ $(GLIB_LIBS) \ $(DBUS_LIBS) \ - $(GCONF_LIBS) \ $(GUDEV_LIBS) libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \ @@ -211,6 +214,9 @@ nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml nm-secret-agent-glue.h: $(top_srcdir)/introspection/nm-secret-agent.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_secret_agent --mode=glib-server --output=$@ $< +nm-device-wimax-bindings.h: $(top_srcdir)/introspection/nm-device-wimax.xml + dbus-binding-tool --prefix=nm_device_wimax --mode=glib-client --output=$@ $< + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnm-glib.pc libnm-glib-vpn.pc diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 1ac3bdb5c4..6a6cea4c28 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -45,6 +45,9 @@ global: nm_client_wwan_get_enabled; nm_client_wwan_hardware_get_enabled; nm_client_wwan_set_enabled; + nm_client_wimax_get_enabled; + nm_client_wimax_hardware_get_enabled; + nm_client_wimax_set_enabled; nm_dbus_settings_get_connection_by_path; nm_dbus_settings_get_type; nm_dbus_settings_new; @@ -93,6 +96,10 @@ global: nm_dhcp4_config_get_options; nm_dhcp4_config_get_type; nm_dhcp4_config_new; + nm_dhcp6_config_get_one_option; + nm_dhcp6_config_get_options; + nm_dhcp6_config_get_type; + nm_dhcp6_config_new; nm_gsm_device_get_type; nm_gsm_device_new; nm_ip4_config_get_addresses; @@ -142,6 +149,22 @@ global: nm_vpn_connection_get_type; nm_vpn_connection_get_vpn_state; nm_vpn_connection_new; + nm_device_wimax_get_bsid; + nm_device_wimax_get_center_frequency; + nm_device_wimax_get_cinr; + nm_device_wimax_get_hw_address; + nm_device_wimax_get_active_nsp; + nm_device_wimax_get_nsp_by_path; + nm_device_wimax_get_nsps; + nm_device_wimax_get_rssi; + nm_device_wimax_get_tx_power; + nm_device_wimax_get_type; + nm_device_wimax_new; + nm_wimax_nsp_get_name; + nm_wimax_nsp_get_network_type; + nm_wimax_nsp_get_signal_quality; + nm_wimax_nsp_get_type; + nm_wimax_nsp_new; local: *; }; diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index 32a6c972d8..b00f65b692 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -68,6 +68,9 @@ typedef struct { gboolean wwan_enabled; gboolean wwan_hw_enabled; + + gboolean wimax_enabled; + gboolean wimax_hw_enabled; } NMClientPrivate; enum { @@ -79,6 +82,8 @@ enum { PROP_WIRELESS_HARDWARE_ENABLED, PROP_WWAN_ENABLED, PROP_WWAN_HARDWARE_ENABLED, + PROP_WIMAX_ENABLED, + PROP_WIMAX_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, LAST_PROP @@ -214,6 +219,36 @@ update_wwan_status (NMClient *client, gboolean notify) } } +static void +update_wimax_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, + "WimaxHardwareEnabled"); + if (val != priv->wimax_hw_enabled) { + priv->wimax_hw_enabled = val; + if (notify) + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIMAX_HARDWARE_ENABLED); + } + + if (priv->wimax_hw_enabled == FALSE) + val = FALSE; + else { + val = _nm_object_get_boolean_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WimaxEnabled"); + } + + if (val != priv->wimax_enabled) { + priv->wimax_enabled = val; + if (notify) + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIMAX_ENABLED); + } +} + static GObject * new_active_connection (DBusGConnection *connection, const char *path) { @@ -281,6 +316,8 @@ register_for_property_changed (NMClient *client) { 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_WIMAX_ENABLED, _nm_object_demarshal_generic, &priv->wimax_enabled }, + { NM_CLIENT_WIMAX_HARDWARE_ENABLED, _nm_object_demarshal_generic, &priv->wimax_hw_enabled }, { NM_CLIENT_ACTIVE_CONNECTIONS, demarshal_active_connections, &priv->active_connections }, { NULL }, }; @@ -293,6 +330,7 @@ register_for_property_changed (NMClient *client) #define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network" #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX "org.freedesktop.NetworkManager.enable-disable-wimax" #define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake" #define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control" #define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED "org.freedesktop.NetworkManager.wifi.share.protected" @@ -309,6 +347,8 @@ nm_permission_to_client (const char *nm) return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI; else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN)) return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN; + else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX; else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE)) return NM_CLIENT_PERMISSION_SLEEP_WAKE; else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL)) @@ -505,6 +545,7 @@ constructor (GType type, if (priv->manager_running) { update_wireless_status (NM_CLIENT (object), FALSE); update_wwan_status (NM_CLIENT (object), FALSE); + update_wimax_status (NM_CLIENT (object), FALSE); nm_client_get_state (NM_CLIENT (object)); } @@ -586,6 +627,20 @@ set_property (GObject *object, guint prop_id, _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_HARDWARE_ENABLED); } break; + case PROP_WIMAX_ENABLED: + b = g_value_get_boolean (value); + if (priv->wimax_enabled != b) { + priv->wimax_enabled = b; + _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WIMAX_ENABLED); + } + break; + case PROP_WIMAX_HARDWARE_ENABLED: + b = g_value_get_boolean (value); + if (priv->wimax_hw_enabled != b) { + priv->wimax_hw_enabled = b; + _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WIMAX_HARDWARE_ENABLED); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -623,6 +678,12 @@ get_property (GObject *object, case PROP_WWAN_HARDWARE_ENABLED: g_value_set_boolean (value, priv->wwan_hw_enabled); break; + case PROP_WIMAX_ENABLED: + g_value_set_boolean (value, priv->wimax_enabled); + break; + case PROP_WIMAX_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->wimax_hw_enabled); + break; case PROP_ACTIVE_CONNECTIONS: g_value_set_boxed (value, nm_client_get_active_connections (self)); break; @@ -739,6 +800,32 @@ nm_client_class_init (NMClientClass *client_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /** + * NMClient::wimax-enabled: + * + * Whether WiMAX functionality is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WIMAX_ENABLED, + g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED, + "WimaxEnabled", + "Is WiMAX enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * NMClient::wimax-hardware-enabled: + * + * Whether the WiMAX hardware is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WIMAX_HARDWARE_ENABLED, + g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED, + "WimaxHardwareEnabled", + "Is WiMAX hardware enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** * NMClient::active-connections: * * The active connections. @@ -869,10 +956,13 @@ proxy_name_owner_changed (DBusGProxy *proxy, priv->wireless_hw_enabled = FALSE; priv->wwan_enabled = FALSE; priv->wwan_hw_enabled = FALSE; + priv->wimax_enabled = FALSE; + priv->wimax_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); + update_wimax_status (client, TRUE); } } @@ -1299,6 +1389,61 @@ nm_client_wwan_hardware_get_enabled (NMClient *client) } /** + * nm_client_wimax_get_enabled: + * @client: a #NMClient + * + * Determines whether WiMAX is enabled. + * + * Returns: %TRUE if WiMAX is enabled + **/ +gboolean +nm_client_wimax_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return NM_CLIENT_GET_PRIVATE (client)->wimax_enabled; +} + +/** + * nm_client_wimax_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to enable WiMAX + * + * Enables or disables WiMAX devices. + **/ +void +nm_client_wimax_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, + "WimaxEnabled", + &value); +} + +/** + * nm_client_wimax_hardware_get_enabled: + * @client: a #NMClient + * + * Determines whether the WiMAX hardware is enabled. + * + * Returns: %TRUE if the WiMAX hardware is enabled + **/ +gboolean +nm_client_wimax_hardware_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return NM_CLIENT_GET_PRIVATE (client)->wimax_hw_enabled; +} + +/** * nm_client_get_state: * @client: a #NMClient * diff --git a/libnm-glib/nm-client.h b/libnm-glib/nm-client.h index b28afd8c36..eae04c5d2c 100644 --- a/libnm-glib/nm-client.h +++ b/libnm-glib/nm-client.h @@ -48,6 +48,8 @@ G_BEGIN_DECLS #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_WIMAX_ENABLED "wimax-enabled" +#define NM_CLIENT_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled" #define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections" /* Permissions */ @@ -62,8 +64,9 @@ typedef enum { NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 7, NM_CLIENT_PERMISSION_SETTINGS_CONNECTION_MODIFY = 8, NM_CLIENT_PERMISSION_SETTINGS_HOSTNAME_MODIFY = 9, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 10, - NM_CLIENT_PERMISSION_LAST = NM_CLIENT_PERMISSION_SETTINGS_HOSTNAME_MODIFY + NM_CLIENT_PERMISSION_LAST = NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX } NMClientPermission; typedef enum { @@ -140,6 +143,10 @@ 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); +gboolean nm_client_wimax_get_enabled (NMClient *client); +void nm_client_wimax_set_enabled (NMClient *client, gboolean enabled); +gboolean nm_client_wimax_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-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c new file mode 100644 index 0000000000..bdab0eb743 --- /dev/null +++ b/libnm-glib/nm-device-wimax.c @@ -0,0 +1,853 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include <string.h> + +#include "nm-device-wimax.h" +#include "nm-object-private.h" +#include "nm-object-cache.h" +#include "nm-dbus-glib-types.h" +#include "nm-types-private.h" + +#include "nm-device-wimax-bindings.h" + +G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE) + +#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxPrivate)) + +static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field); + +void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled); + +typedef struct { + gboolean disposed; + DBusGProxy *proxy; + + char *hw_address; + NMWimaxNsp *active_nsp; + gboolean null_active_nsp; + GPtrArray *nsps; + + guint center_freq; + gint rssi; + gint cinr; + gint tx_power; + char *bsid; +} NMDeviceWimaxPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_ACTIVE_NSP, + PROP_CENTER_FREQ, + PROP_RSSI, + PROP_CINR, + PROP_TX_POWER, + PROP_BSID, + + LAST_PROP +}; + +#define DBUS_PROP_HW_ADDRESS "HwAddress" +#define DBUS_PROP_ACTIVE_NSP "ActiveNsp" +#define DBUS_PROP_CENTER_FREQUENCY "CenterFrequency" +#define DBUS_PROP_RSSI "Rssi" +#define DBUS_PROP_CINR "Cinr" +#define DBUS_PROP_TX_POWER "TxPower" +#define DBUS_PROP_BSID "Bsid" + +enum { + NSP_ADDED, + NSP_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/** + * nm_device_wimax_new: + * @connection: the #DBusGConnection + * @path: the DBus object path of the wimax + * + * Creates a new #NMDeviceWimax. + * + * Returns: a new wimax + **/ +GObject * +nm_device_wimax_new (DBusGConnection *connection, const char *path) +{ + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + + return g_object_new (NM_TYPE_DEVICE_WIMAX, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); +} + +/** + * nm_device_wimax_get_hw_address: + * @device: a #NMDeviceWimax + * + * Gets the hardware (MAC) address of the #NMDeviceWimax + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_wimax_get_hw_address (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (!priv->hw_address) { + priv->hw_address = _nm_object_get_string_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_HW_ADDRESS); + } + + return priv->hw_address; +} + +/** + * nm_device_wimax_get_active_nsp: + * @wimax: a #NMDeviceWimax + * + * Gets the active #NMWimaxNsp. + * + * Returns: the access point or %NULL if none is active + **/ +NMWimaxNsp * +nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + NMDeviceState state; + char *path; + GValue value = { 0, }; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + state = nm_device_get_state (NM_DEVICE (wimax)); + switch (state) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_ACTIVATED: + break; + default: + return NULL; + break; + } + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (priv->active_nsp) + return priv->active_nsp; + if (priv->null_active_nsp) + return NULL; + + path = _nm_object_get_object_path_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_ACTIVE_NSP); + if (path) { + g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH); + g_value_take_boxed (&value, path); + demarshal_active_nsp (NM_OBJECT (wimax), NULL, &value, &priv->active_nsp); + g_value_unset (&value); + } + + return priv->active_nsp; +} + +/** + * nm_device_wimax_get_nsps: + * @wimax: a #NMDeviceWimax + * + * Gets all the scanned NSPs of the #NMDeviceWimax. + * + * Returns: a #GPtrArray containing all the scanned #NMWimaxNsp<!-- -->s. + * The returned array is owned by the client and should not be modified. + **/ +const GPtrArray * +nm_device_wimax_get_nsps (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + DBusGConnection *connection; + GValue value = { 0, }; + GError *error = NULL; + GPtrArray *temp; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (priv->nsps) + return handle_ptr_array_return (priv->nsps); + + if (!org_freedesktop_NetworkManager_Device_WiMax_get_nsp_list (priv->proxy, &temp, &error)) { + g_warning ("%s: error getting NSPs: %s", __func__, error->message); + g_error_free (error); + return NULL; + } + + g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH); + g_value_take_boxed (&value, temp); + connection = nm_object_get_connection (NM_OBJECT (wimax)); + _nm_object_array_demarshal (&value, &priv->nsps, connection, nm_wimax_nsp_new); + g_value_unset (&value); + + return handle_ptr_array_return (priv->nsps); +} + +/** + * nm_device_wimax_get_nsp_by_path: + * @wimax: a #NMDeviceWimax + * @path: the object path of the NSP + * + * Gets a #NMWimaxNsp by path. + * + * Returns: the access point or %NULL if none is found. + **/ +NMWimaxNsp * +nm_device_wimax_get_nsp_by_path (NMDeviceWimax *wimax, + const char *path) +{ + const GPtrArray *nsps; + int i; + NMWimaxNsp *nsp = NULL; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + g_return_val_if_fail (path != NULL, NULL); + + nsps = nm_device_wimax_get_nsps (wimax); + if (!nsps) + return NULL; + + for (i = 0; i < nsps->len; i++) { + NMWimaxNsp *candidate = g_ptr_array_index (nsps, i); + if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) { + nsp = candidate; + break; + } + } + + return nsp; +} + +static void +nsp_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv; + GObject *nsp; + + g_return_if_fail (self != NULL); + + nsp = G_OBJECT (nm_device_wimax_get_nsp_by_path (self, path)); + if (!nsp) { + DBusGConnection *connection = nm_object_get_connection (NM_OBJECT (self)); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + nsp = G_OBJECT (_nm_object_cache_get (path)); + if (nsp) { + g_ptr_array_add (priv->nsps, g_object_ref (nsp)); + } else { + nsp = G_OBJECT (nm_wimax_nsp_new (connection, path)); + if (nsp) + g_ptr_array_add (priv->nsps, nsp); + } + } + + if (nsp) + g_signal_emit (self, signals[NSP_ADDED], 0, nsp); +} + +static void +nsp_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMWimaxNsp *nsp; + + g_return_if_fail (self != NULL); + + nsp = nm_device_wimax_get_nsp_by_path (self, path); + if (nsp) { + if (nsp == priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + priv->null_active_nsp = FALSE; + + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); + } + + g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); + g_ptr_array_remove (priv->nsps, nsp); + g_object_unref (G_OBJECT (nsp)); + } +} + +static void +clean_up_nsps (NMDeviceWimax *self, gboolean notify) +{ + NMDeviceWimaxPrivate *priv; + + g_return_if_fail (NM_IS_DEVICE_WIMAX (self)); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + } + + if (priv->nsps) { + while (priv->nsps->len) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (g_ptr_array_index (priv->nsps, 0)); + + if (notify) + g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); + g_ptr_array_remove (priv->nsps, nsp); + g_object_unref (nsp); + } + g_ptr_array_free (priv->nsps, TRUE); + priv->nsps = NULL; + } +} + +/** + * nm_device_wimax_get_center_frequency: + * @device: a #NMDeviceWimax + * + * Gets the center frequency (in KHz) of the radio channel the device is using + * to communicate with the network when connected. Has no meaning when the + * device is not connected. + * + * Returns: the center frequency in KHz, or 0 + **/ +guint +nm_device_wimax_get_center_frequency (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), 0); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (!priv->center_freq) { + priv->center_freq = _nm_object_get_uint_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_CENTER_FREQUENCY); + } + return priv->center_freq; +} + +/** + * nm_device_wimax_get_rssi: + * @device: a #NMDeviceWimax + * + * Gets the RSSI of the current radio link in dBm. This value indicates how + * strong the raw received RF signal from the base station is, but does not + * indicate the overall quality of the radio link. Has no meaning when the + * device is not connected. + * + * Returns: the RSSI in dBm, or 0 + **/ +gint +nm_device_wimax_get_rssi (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), 0); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (!priv->rssi) { + priv->rssi = _nm_object_get_int_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_RSSI); + } + return priv->rssi; +} + +/** + * nm_device_wimax_get_cinr: + * @device: a #NMDeviceWimax + * + * Gets the CINR (Carrier to Interference + Noise Ratio) of the current radio + * link in dB. CINR is a more accurate measure of radio link quality. Has no + * meaning when the device is not connected. + * + * Returns: the CINR in dB, or 0 + **/ +gint +nm_device_wimax_get_cinr (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), 0); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (!priv->cinr) { + priv->cinr = _nm_object_get_int_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_CINR); + } + return priv->cinr; +} + +/** + * nm_device_wimax_get_tx_power: + * @device: a #NMDeviceWimax + * + * Average power of the last burst transmitted by the device, in units of + * 0.5 dBm. i.e. a TxPower of -11 represents an actual device TX power of + * -5.5 dBm. Has no meaning when the device is not connected. + * + * Returns: the TX power in dBm, or 0 + **/ +gint +nm_device_wimax_get_tx_power (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), 0); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (!priv->tx_power) { + priv->tx_power = _nm_object_get_int_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_TX_POWER); + } + return priv->tx_power; +} + +/** + * nm_device_wimax_get_bsid: + * @device: a #NMDeviceWimax + * + * Gets the ID of the serving Base Station when the device is connected. + * + * Returns: the ID of the serving Base Station, or NULL + **/ +const char * +nm_device_wimax_get_bsid (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + if (!priv->bsid) { + priv->bsid = _nm_object_get_string_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_DEVICE_WIMAX, + DBUS_PROP_BSID); + } + return priv->bsid; +} + +/**************************************************************/ + +static void +nm_device_wimax_init (NMDeviceWimax *wimax) +{ +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_wimax_get_hw_address (self)); + break; + case PROP_ACTIVE_NSP: + g_value_set_object (value, nm_device_wimax_get_active_nsp (self)); + break; + case PROP_CENTER_FREQ: + g_value_set_uint (value, nm_device_wimax_get_center_frequency (self)); + break; + case PROP_RSSI: + g_value_set_int (value, nm_device_wimax_get_rssi (self)); + break; + case PROP_CINR: + g_value_set_int (value, nm_device_wimax_get_cinr (self)); + break; + case PROP_TX_POWER: + g_value_set_int (value, nm_device_wimax_get_tx_power (self)); + break; + case PROP_BSID: + g_value_set_string (value, nm_device_wimax_get_bsid (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clear_link_status (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->center_freq) { + priv->center_freq = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_CENTER_FREQUENCY); + } + + if (priv->rssi) { + priv->rssi = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_RSSI); + } + + if (priv->cinr) { + priv->cinr = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_CINR); + } + + if (priv->tx_power) { + priv->tx_power = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_TX_POWER); + } + + if (priv->bsid) { + g_free (priv->bsid); + priv->bsid = NULL; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_BSID); + } +} + +static void +state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + + state = nm_device_get_state (device); + switch (state) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + priv->null_active_nsp = FALSE; + } + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIMAX_ACTIVE_NSP); + clear_link_status (self); + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + clear_link_status (self); + break; + default: + break; + } +} + +static gboolean +demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); + const char *path; + NMWimaxNsp *nsp = NULL; + DBusGConnection *connection; + + if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) + return FALSE; + + priv->null_active_nsp = FALSE; + + path = g_value_get_boxed (value); + if (path) { + if (!strcmp (path, "/")) + priv->null_active_nsp = TRUE; + else { + nsp = NM_WIMAX_NSP (_nm_object_cache_get (path)); + if (nsp) + nsp = g_object_ref (nsp); + else { + connection = nm_object_get_connection (object); + nsp = NM_WIMAX_NSP (nm_wimax_nsp_new (connection, path)); + } + } + } + + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + } + + if (nsp) + priv->active_nsp = nsp; + + _nm_object_queue_notify (object, NM_DEVICE_WIMAX_ACTIVE_NSP); + return TRUE; +} + +static void +register_for_property_changed (NMDeviceWimax *wimax) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); + const NMPropertiesChangedInfo property_changed_info[] = { + { NM_DEVICE_WIMAX_HW_ADDRESS, _nm_object_demarshal_generic, &priv->hw_address }, + { NM_DEVICE_WIMAX_ACTIVE_NSP, demarshal_active_nsp, &priv->active_nsp }, + { NM_DEVICE_WIMAX_CENTER_FREQUENCY, _nm_object_demarshal_generic, &priv->center_freq }, + { NM_DEVICE_WIMAX_RSSI, _nm_object_demarshal_generic, &priv->rssi }, + { NM_DEVICE_WIMAX_CINR, _nm_object_demarshal_generic, &priv->cinr }, + { NM_DEVICE_WIMAX_TX_POWER, _nm_object_demarshal_generic, &priv->tx_power }, + { NM_DEVICE_WIMAX_BSID, _nm_object_demarshal_generic, &priv->bsid }, + { NULL }, + }; + + _nm_object_handle_properties_changed (NM_OBJECT (wimax), + priv->proxy, + property_changed_info); +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMDeviceWimaxPrivate *priv; + + object = G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); + + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), + NM_DBUS_SERVICE, + nm_object_get_path (NM_OBJECT (object)), + NM_DBUS_INTERFACE_DEVICE_WIMAX); + + dbus_g_proxy_add_signal (priv->proxy, "NspAdded", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "NspAdded", + G_CALLBACK (nsp_added_proxy), + object, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "NspRemoved", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "NspRemoved", + G_CALLBACK (nsp_removed_proxy), + object, NULL); + + register_for_property_changed (NM_DEVICE_WIMAX (object)); + + g_signal_connect (object, + "notify::" NM_DEVICE_STATE, + G_CALLBACK (state_changed_cb), + NULL); + + return object; +} + +static void +dispose (GObject *object) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + g_free (priv->hw_address); + g_free (priv->bsid); + + clean_up_nsps (NM_DEVICE_WIMAX (object), FALSE); + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); +} + +static void +nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wimax_class); + + g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* properties */ + + /** + * NMDeviceWimax:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIMAX_HW_ADDRESS, + "MAC Address", + "Hardware MAC address", + NULL, + G_PARAM_READABLE)); + + /** + * NMDeviceWimax:active-nsp: + * + * The active #NMWimaxNsp of the device. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_NSP, + g_param_spec_object (NM_DEVICE_WIMAX_ACTIVE_NSP, + "Active NSP", + "Active NSP", + NM_TYPE_WIMAX_NSP, + G_PARAM_READABLE)); + + /** + * NMDeviceWimax:center-frequency: + * + * The center frequency (in KHz) of the radio channel the device is using to + * communicate with the network when connected. Has no meaning when the + * device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_CENTER_FREQ, + g_param_spec_uint (NM_DEVICE_WIMAX_CENTER_FREQUENCY, + "Center frequency", + "Center frequency", + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + + /** + * NMDeviceWimax:rssi: + * + * RSSI of the current radio link in dBm. This value indicates how strong + * the raw received RF signal from the base station is, but does not + * indicate the overall quality of the radio link. Has no meaning when the + * device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_RSSI, + g_param_spec_int (NM_DEVICE_WIMAX_RSSI, + "RSSI", + "RSSI", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + /** + * NMDeviceWimax:cinr: + * + * CINR (Carrier to Interference + Noise Ratio) of the current radio link + * in dB. CINR is a more accurate measure of radio link quality. Has no + * meaning when the device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_CINR, + g_param_spec_int (NM_DEVICE_WIMAX_CINR, + "CINR", + "CINR", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + /** + * NMDeviceWimax:tx-power: + * + * Average power of the last burst transmitted by the device, in units of + * 0.5 dBm. i.e. a TxPower of -11 represents an actual device TX power of + * -5.5 dBm. Has no meaning when the device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_TX_POWER, + g_param_spec_int (NM_DEVICE_WIMAX_TX_POWER, + "TX Power", + "TX Power", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + /** + * NMDeviceWimax:bsid: + * + * The ID of the serving base station as received from the network. Has + * no meaning when the device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_BSID, + g_param_spec_string (NM_DEVICE_WIMAX_BSID, + "BSID", + "BSID", + NULL, + G_PARAM_READABLE)); + + /* signals */ + + /** + * NMDeviceWimax::nsp-added: + * @self: the wimax device that received the signal + * @nsp: the new NSP + * + * Notifies that a #NMWimaxNsp is added to the wimax device. + **/ + signals[NSP_ADDED] = + g_signal_new ("nsp-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + /** + * NMDeviceWimax::nsp-removed: + * @self: the wimax device that received the signal + * @nsp: the removed NSP + * + * Notifies that a #NMWimaxNsp is removed from the wimax device. + **/ + signals[NSP_REMOVED] = + g_signal_new ("nsp-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); +} diff --git a/libnm-glib/nm-device-wimax.h b/libnm-glib/nm-device-wimax.h new file mode 100644 index 0000000000..5e19bbaf95 --- /dev/null +++ b/libnm-glib/nm-device-wimax.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_DEVICE_WIMAX_H +#define NM_DEVICE_WIMAX_H + +#include "nm-device.h" +#include "nm-wimax-nsp.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) +#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) +#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) +#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) + +#define NM_DEVICE_WIMAX_HW_ADDRESS "hw-address" +#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" +#define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency" +#define NM_DEVICE_WIMAX_RSSI "rssi" +#define NM_DEVICE_WIMAX_CINR "cinr" +#define NM_DEVICE_WIMAX_TX_POWER "tx-power" +#define NM_DEVICE_WIMAX_BSID "bsid" + +typedef struct { + NMDevice parent; +} NMDeviceWimax; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*nsp_added) (NMDeviceWimax *self, NMWimaxNsp *nsp); + void (*nsp_removed) (NMDeviceWimax *self, NMWimaxNsp *nsp); +} NMDeviceWimaxClass; + +GType nm_device_wimax_get_type (void); + +GObject *nm_device_wimax_new (DBusGConnection *connection, + const char *path); + +const char *nm_device_wimax_get_hw_address (NMDeviceWimax *wimax); +NMWimaxNsp *nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax); +NMWimaxNsp *nm_device_wimax_get_nsp_by_path (NMDeviceWimax *wimax, + const char *path); + +const GPtrArray *nm_device_wimax_get_nsps (NMDeviceWimax *wimax); + +guint nm_device_wimax_get_center_frequency (NMDeviceWimax *self); +gint nm_device_wimax_get_rssi (NMDeviceWimax *self); +gint nm_device_wimax_get_cinr (NMDeviceWimax *self); +gint nm_device_wimax_get_tx_power (NMDeviceWimax *self); +const char * nm_device_wimax_get_bsid (NMDeviceWimax *self); + +G_END_DECLS + +#endif /* NM_DEVICE_WIMAX_H */ diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index ea2a91d1ce..b494749ada 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -32,6 +32,7 @@ #include "nm-gsm-device.h" #include "nm-cdma-device.h" #include "nm-device-bt.h" +#include "nm-device-wimax.h" #include "nm-device.h" #include "nm-device-private.h" #include "nm-object-private.h" @@ -477,6 +478,20 @@ nm_device_class_init (NMDeviceClass *device_class) G_PARAM_READABLE)); /** + * NMDevice:ip-interface: + * + * The IP interface of the device which should be used for all IP-related + * operations like addressing and routing. + **/ + g_object_class_install_property + (object_class, PROP_IP_INTERFACE, + g_param_spec_string (NM_DEVICE_IP_INTERFACE, + "IP Interface", + "IP Interface name", + NULL, + G_PARAM_READABLE)); + + /** * NMDevice:udi: * * The Unique Device Identifier of the device. @@ -710,6 +725,9 @@ nm_device_new (DBusGConnection *connection, const char *path) case NM_DEVICE_TYPE_BT: dtype = NM_TYPE_DEVICE_BT; break; + case NM_DEVICE_TYPE_WIMAX: + dtype = NM_TYPE_DEVICE_WIMAX; + break; default: g_warning ("Unknown device type %d", g_value_get_uint (&value)); break; diff --git a/libnm-glib/nm-wimax-nsp.c b/libnm-glib/nm-wimax-nsp.c new file mode 100644 index 0000000000..eebdbaaac9 --- /dev/null +++ b/libnm-glib/nm-wimax-nsp.c @@ -0,0 +1,303 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#include <string.h> + +#include "nm-wimax-nsp.h" +#include "NetworkManager.h" +#include "nm-types-private.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, NM_TYPE_OBJECT) + +#define NM_WIMAX_NSP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) + +typedef struct { + gboolean disposed; + DBusGProxy *proxy; + + char *name; + guint32 signal_quality; + NMWimaxNspNetworkType network_type; +} NMWimaxNspPrivate; + +enum { + PROP_0, + PROP_NAME, + PROP_SIGNAL_QUALITY, + PROP_NETWORK_TYPE, + + LAST_PROP +}; + +#define DBUS_PROP_NAME "Name" +#define DBUS_PROP_SIGNAL_QUALITY "SignalQuality" +#define DBUS_PROP_NETWORK_TYPE "NetworkType" + +/** + * nm_wimax_nsp_new: + * @connection: the #DBusGConnection + * @path: the DBusobject path of the wimax NSP + * + * Creates a new #NMWimaxNsp. + * + * Returns: a new wimax nsp + **/ +GObject * +nm_wimax_nsp_new (DBusGConnection *connection, const char *path) +{ + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + + return (GObject *) g_object_new (NM_TYPE_WIMAX_NSP, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); +} + +/** + * nm_wimax_nsp_get_name: + * @nsp: a #NMWimaxNsp + * + * Gets the name of the wimax NSP + * + * Returns: the name + **/ +const char * +nm_wimax_nsp_get_name (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NULL); + + priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + if (!priv->name) + priv->name = _nm_object_get_string_property (NM_OBJECT (nsp), + NM_DBUS_INTERFACE_WIMAX_NSP, + DBUS_PROP_NAME); + + return priv->name; +} + +/** + * nm_wimax_nsp_get_signal_quality: + * @nsp: a #NMWimaxNsp + * + * Gets the WPA signal quality of the wimax NSP. + * + * Returns: the signal quality + **/ +guint32 +nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), 0); + + priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + if (!priv->signal_quality) { + priv->signal_quality = _nm_object_get_uint_property (NM_OBJECT (nsp), + NM_DBUS_INTERFACE_WIMAX_NSP, + DBUS_PROP_SIGNAL_QUALITY); + } + + return priv->signal_quality; +} + +/** + * nm_wimax_nsp_get_network_type: + * @nsp: a #NMWimaxNsp + * + * Gets the network type of the wimax NSP. + * + * Returns: the network type + **/ +NMWimaxNspNetworkType +nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN); + + priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + if (!priv->network_type) { + priv->network_type = _nm_object_get_uint_property (NM_OBJECT (nsp), + NM_DBUS_INTERFACE_WIMAX_NSP, + DBUS_PROP_NETWORK_TYPE); + } + + return priv->network_type; +} + +/************************************************************/ + +static void +nm_wimax_nsp_init (NMWimaxNsp *nsp) +{ +} + +static void +dispose (GObject *object) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + g_free (priv->name); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMWimaxNsp *nsp = NM_WIMAX_NSP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_wimax_nsp_get_name (nsp)); + break; + case PROP_SIGNAL_QUALITY: + g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (nsp)); + break; + case PROP_NETWORK_TYPE: + g_value_set_uint (value, nm_wimax_nsp_get_network_type (nsp)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +register_for_property_changed (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + const NMPropertiesChangedInfo property_changed_info[] = { + { NM_WIMAX_NSP_SIGNAL_QUALITY, _nm_object_demarshal_generic, &priv->signal_quality }, + { NULL }, + }; + + _nm_object_handle_properties_changed (NM_OBJECT (nsp), + priv->proxy, + property_changed_info); +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + NMObject *object; + NMWimaxNspPrivate *priv; + + object = (NMObject *) G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + NM_DBUS_SERVICE, + nm_object_get_path (object), + NM_DBUS_INTERFACE_WIMAX_NSP); + + register_for_property_changed (NM_WIMAX_NSP (object)); + + return G_OBJECT (object); +} + + +static void +nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (nsp_class); + + g_type_class_add_private (nsp_class, sizeof (NMWimaxNspPrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* properties */ + + /** + * NMWimaxNsp:name: + * + * The name of the WiMAX NSP. + **/ + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_WIMAX_NSP_NAME, + "Name", + "Name", + NULL, + G_PARAM_READABLE)); + + /** + * NMWimaxNsp:signal-quality: + * + * The signal quality of the WiMAX NSP. + **/ + g_object_class_install_property + (object_class, PROP_SIGNAL_QUALITY, + g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, + "Signal Quality", + "Signal Quality", + 0, 100, 0, + G_PARAM_READABLE)); + + /** + * NMWimaxNsp:network-type: + * + * The network type of the WiMAX NSP. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_uint (NM_WIMAX_NSP_NETWORK_TYPE, + "Network Type", + "Network Type", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); +} diff --git a/libnm-glib/nm-wimax-nsp.h b/libnm-glib/nm-wimax-nsp.h new file mode 100644 index 0000000000..5507b75295 --- /dev/null +++ b/libnm-glib/nm-wimax-nsp.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_NSP_H +#define NM_WIMAX_NSP_H + +#include <glib.h> +#include <glib-object.h> +#include <NetworkManager.h> +#include "nm-object.h" + +G_BEGIN_DECLS + +#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) +#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) +#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) +#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) + +#define NM_WIMAX_NSP_NAME "name" +#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" +#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" + +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN = 0, + NM_WIMAX_NSP_NETWORK_TYPE_HOME = 1, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER = 2, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER = 3 +} NMWimaxNspNetworkType; + +typedef struct { + NMObject parent; +} NMWimaxNsp; + +typedef struct { + NMObjectClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); + void (*_reserved5) (void); + void (*_reserved6) (void); +} NMWimaxNspClass; + +GType nm_wimax_nsp_get_type (void); + +GObject *nm_wimax_nsp_new (DBusGConnection *connection, const char *path); + +const char * nm_wimax_nsp_get_name (NMWimaxNsp *nsp); +guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp); +NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp); + +G_END_DECLS + +#endif /* NM_WIMAX_NSP_H */ diff --git a/libnm-glib/tests/Makefile.am b/libnm-glib/tests/Makefile.am index a22a2d35dc..06aee71252 100644 --- a/libnm-glib/tests/Makefile.am +++ b/libnm-glib/tests/Makefile.am @@ -11,7 +11,6 @@ test_remote_settings_client_SOURCES = \ test-remote-settings-client.c test_remote_settings_client_CPPFLAGS = \ - -DSERVICEDIR=\"$(builddir)\" \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) @@ -23,12 +22,14 @@ test_remote_settings_client_LDADD = \ ########################################### -EXTRA_DIST = test-remote-settings-service.py +TEST_RSS_BIN = test-remote-settings-service.py + +EXTRA_DIST = $(TEST_RSS_BIN) if WITH_TESTS check-local: test-remote-settings-client - $(abs_builddir)/test-remote-settings-client + $(abs_builddir)/test-remote-settings-client $(abs_srcdir) $(TEST_RSS_BIN) endif diff --git a/libnm-glib/tests/test-remote-settings-client.c b/libnm-glib/tests/test-remote-settings-client.c index 3285735735..619b86d8de 100644 --- a/libnm-glib/tests/test-remote-settings-client.c +++ b/libnm-glib/tests/test-remote-settings-client.c @@ -34,8 +34,6 @@ #include "nm-remote-settings.h" -#define SERVICE_FILE "test-remote-settings-service.py" - static GPid spid = 0; static NMRemoteSettings *settings = NULL; @@ -209,12 +207,14 @@ typedef void (*TCFunc)(void); int main (int argc, char **argv) { GTestSuite *suite; - char *service_argv[3] = { SERVICEDIR "/" SERVICE_FILE, SERVICE_FILE, NULL }; + char *service_argv[3] = { NULL, NULL, NULL }; int ret; GError *error = NULL; DBusGConnection *bus; int i = 100; + g_assert (argc == 3); + g_type_init (); g_test_init (&argc, &argv, NULL); @@ -225,8 +225,9 @@ int main (int argc, char **argv) g_assert (error == NULL); } - if (!g_spawn_async (SERVICEDIR, service_argv, NULL, 0, NULL, NULL, &spid, &error)) { - g_warning ("Error spawning " SERVICE_FILE ": %s", error->message); + service_argv[0] = g_strdup_printf ("%s/%s", argv[1], argv[2]); + if (!g_spawn_async (argv[1], service_argv, NULL, 0, NULL, NULL, &spid, &error)) { + g_warning ("Error spawning %s: %s", argv[2], error->message); g_assert (error == NULL); } diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am index f43fb60242..fdadc7517f 100644 --- a/libnm-util/Makefile.am +++ b/libnm-util/Makefile.am @@ -24,6 +24,7 @@ libnm_util_include_HEADERS = \ nm-setting-gsm.h \ nm-setting-cdma.h \ nm-setting-olpc-mesh.h \ + nm-setting-wimax.h \ nm-setting-wired.h \ nm-setting-wireless.h \ nm-setting-wireless-security.h \ @@ -48,6 +49,7 @@ libnm_util_la_SOURCES= \ nm-setting-gsm.c \ nm-setting-cdma.c \ nm-setting-olpc-mesh.c \ + nm-setting-wimax.c \ nm-setting-wired.c \ nm-setting-wireless.c \ nm-setting-wireless-security.c \ diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index 8eaaad6b2c..2a8181beeb 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver @@ -280,6 +280,12 @@ global: nm_setting_vpn_foreach_secret; nm_setting_vpn_get_secret; nm_setting_vpn_remove_secret; + nm_setting_wimax_error_get_type; + nm_setting_wimax_error_quark; + nm_setting_wimax_get_type; + nm_setting_wimax_new; + nm_setting_wimax_get_network_name; + nm_setting_wimax_get_mac_address; nm_setting_wired_error_get_type; nm_setting_wired_error_quark; nm_setting_wired_get_type; diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index 105dcbe144..3aa10c6a04 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -38,6 +38,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" +#include "nm-setting-wimax.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" @@ -132,7 +133,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; static GHashTable *registered_settings = NULL; -#define DEFAULT_MAP_SIZE 15 +#define DEFAULT_MAP_SIZE 16 static struct SettingInfo { const char *name; @@ -228,6 +229,11 @@ register_default_settings (void) NM_SETTING_BLUETOOTH_ERROR, 1); + register_one_setting (NM_SETTING_WIMAX_SETTING_NAME, + NM_TYPE_SETTING_WIMAX, + NM_SETTING_WIMAX_ERROR, + 1); + register_one_setting (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_ERROR, diff --git a/libnm-util/nm-setting-wimax.c b/libnm-util/nm-setting-wimax.c new file mode 100644 index 0000000000..349a3ae8ea --- /dev/null +++ b/libnm-util/nm-setting-wimax.c @@ -0,0 +1,229 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2009 Novell, Inc. + */ + +#include <net/ethernet.h> +#include <dbus/dbus-glib.h> +#include "nm-setting-wimax.h" +#include "nm-param-spec-specialized.h" + +GQuark +nm_setting_wimax_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-wimax-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_wimax_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_WIMAX_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingWimaxError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING) + +#define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) + +typedef struct { + char *network_name; + GByteArray *mac_address; +} NMSettingWimaxPrivate; + +enum { + PROP_0, + PROP_NETWORK_NAME, + PROP_MAC_ADDRESS, + + LAST_PROP +}; + +NMSetting * +nm_setting_wimax_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIMAX, NULL); +} + +const char * +nm_setting_wimax_get_network_name (NMSettingWimax *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), NULL); + + return NM_SETTING_WIMAX_GET_PRIVATE (setting)->network_name; +} + +const GByteArray * +nm_setting_wimax_get_mac_address (NMSettingWimax *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), NULL); + + return NM_SETTING_WIMAX_GET_PRIVATE (setting)->mac_address; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (setting); + + if (!priv->network_name) { + g_set_error (error, + NM_SETTING_WIMAX_ERROR, + NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY, + NM_SETTING_WIMAX_NETWORK_NAME); + + return FALSE; + } + + if (priv->mac_address && priv->mac_address->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_WIMAX_ERROR, + NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, + NM_SETTING_WIMAX_MAC_ADDRESS); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_wimax_init (NMSettingWimax *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIMAX_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (object); + + g_free (priv->network_name); + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + + G_OBJECT_CLASS (nm_setting_wimax_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NETWORK_NAME: + g_free (priv->network_name); + priv->network_name = g_value_dup_string (value); + break; + case PROP_MAC_ADDRESS: + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + priv->mac_address = g_value_dup_boxed (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingWimax *setting = NM_SETTING_WIMAX (object); + + switch (prop_id) { + case PROP_NETWORK_NAME: + g_value_set_string (value, nm_setting_wimax_get_network_name (setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_boxed (value, nm_setting_wimax_get_mac_address (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingWimaxPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingWimax:network-name: + * + * Network name of the WiMAX network. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_NAME, + g_param_spec_string (NM_SETTING_WIMAX_NETWORK_NAME, + "NetworkName", + "Network name", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWimax:mac-address: + * + * If specified, this connection will only apply to the WiMAX device + * whose MAC address matches. This property does not change the MAC address + * of the device (known as MAC spoofing). + **/ + g_object_class_install_property + (object_class, PROP_MAC_ADDRESS, + _nm_param_spec_specialized (NM_SETTING_WIMAX_MAC_ADDRESS, + "MAC Address", + "If specified, this connection will only apply to " + "the WiMAX device whose MAC address matches. " + "This property does not change the MAC address " + "of the device (known as MAC spoofing).", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-wimax.h b/libnm-util/nm-setting-wimax.h new file mode 100644 index 0000000000..a3e500be51 --- /dev/null +++ b/libnm-util/nm-setting-wimax.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2009 Novell, Inc. + */ + +#ifndef NM_SETTING_WIMAX_H +#define NM_SETTING_WIMAX_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIMAX (nm_setting_wimax_get_type ()) +#define NM_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimax)) +#define NM_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) +#define NM_IS_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIMAX)) +#define NM_IS_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_WIMAX)) +#define NM_SETTING_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) + +#define NM_SETTING_WIMAX_SETTING_NAME "wimax" + +typedef enum +{ + NM_SETTING_WIMAX_ERROR_UNKNOWN = 0, + NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, + NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY +} NMSettingWimaxError; + +#define NM_TYPE_SETTING_WIMAX_ERROR (nm_setting_wimax_error_get_type ()) +GType nm_setting_wimax_error_get_type (void); + +#define NM_SETTING_WIMAX_ERROR nm_setting_wimax_error_quark () +GQuark nm_setting_wimax_error_quark (void); + +#define NM_SETTING_WIMAX_NETWORK_NAME "network-name" +#define NM_SETTING_WIMAX_MAC_ADDRESS "mac-address" + +typedef struct { + NMSetting parent; +} NMSettingWimax; + +typedef struct { + NMSettingClass parent; +} NMSettingWimaxClass; + +GType nm_setting_wimax_get_type (void); + +NMSetting *nm_setting_wimax_new (void); +const char *nm_setting_wimax_get_network_name (NMSettingWimax *setting); +const GByteArray *nm_setting_wimax_get_mac_address (NMSettingWimax *setting); + +G_END_DECLS + +#endif /* NM_SETTING_WIMAX_H */ diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 06994c73de..190199c121 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -620,6 +620,8 @@ nm_setting_to_string (NMSetting *setting) is_serializable = prop_spec->flags & NM_SETTING_PARAM_SERIALIZE; is_default = g_param_value_defaults (prop_spec, &value); + g_value_unset (&value); + if (is_serializable || is_default) { g_string_append (string, " ("); diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c index ce13da3c86..9c3662f47f 100644 --- a/libnm-util/nm-utils.c +++ b/libnm-util/nm-utils.c @@ -1269,14 +1269,24 @@ nm_utils_security_valid (NMUtilsSecurityType type, if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) return FALSE; if (have_ap) { - /* Ad-Hoc WPA APs won't necessarily have the PSK flag set */ - if ((ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) || adhoc) { - if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) + /* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and + * they don't have any pairwise ciphers. */ + if (adhoc) { + if ( (ap_wpa & NM_802_11_AP_SEC_GROUP_TKIP) && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) return TRUE; - if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) + if ( (ap_wpa & NM_802_11_AP_SEC_GROUP_CCMP) && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) return TRUE; + } else { + if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) { + if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } } return FALSE; } @@ -1285,14 +1295,22 @@ nm_utils_security_valid (NMUtilsSecurityType type, if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) return FALSE; if (have_ap) { - /* Ad-Hoc WPA APs won't necessarily have the PSK flag set */ - if ((ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) || adhoc) { - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + /* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and + * they don't have any pairwise ciphers, nor any RSA flags yet. */ + if (adhoc) { + if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) return TRUE; - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) return TRUE; + } else { + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) { + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } } return FALSE; } diff --git a/man/NetworkManager.8.in b/man/NetworkManager.8.in index 4f700e9a38..92c6e5aa26 100644 --- a/man/NetworkManager.8.in +++ b/man/NetworkManager.8.in @@ -52,8 +52,10 @@ A VPN connection has been deactivated. .TP .I "hostname" The system hostname has been updated. Use gethostname(2) to retrieve it. +.TP .I "dhcp4\-change" The DHCPv4 lease has changed (renewed, rebound, etc). +.TP .I "dhcp6\-change" The DHCPv6 lease has changed (renewed, rebound, etc). .SH OPTIONS diff --git a/man/NetworkManager.conf.5.in b/man/NetworkManager.conf.5.in index 0f061ea048..20a8e3ad9b 100644 --- a/man/NetworkManager.conf.5.in +++ b/man/NetworkManager.conf.5.in @@ -2,7 +2,7 @@ .\" .\" Copyright (C) 2010 Red Hat, Inc. .\" -.TH "NetworkManager.conf" "5" "16 September 2010" "" +.TH "NetworkManager.conf" "5" "23 November 2010" "" .SH NAME NetworkManager.conf \- NetworkManager configuration file .SH SYNOPSIS @@ -129,10 +129,12 @@ Set a persistent hostname when using the \fIkeyfile\fP plugin. .B unmanaged-devices=\fImac:<hwaddr>\fP;\fImac:<hwaddr>\fP;... Set devices that should be ignored by NetworkManager when using the \fIkeyfile\fP plugin. Devices are specified in the following format: "mac:<hwaddr>", where -<hwaddr> is MAC address of the device to be ignored, in lowercase. Multiple -entries are separated by a semicolon. Example: +<hwaddr> is MAC address of the device to be ignored, in hex-digits-and-colons notation. +Multiple entries are separated by a semicolon. No spaces are allowed in the value. +.br +Example: .nf -unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1e:65:30:d1:c4 +unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4 .fi .SS [ifupdown] This section contains ifupdown-specific options and thus only has effect when using \fIifupdown\fP plugin. @@ -160,11 +162,11 @@ warning messages. .B domains=\fI<domain1>,<domain2>, ...\fP The following log domains are available: [NONE, HW, RKILL, ETHER, WIFI, BT, MB, DHCP4, DHCP6, PPP, WIFI_SCAN, IP4, IP6, AUTOIP4, DNS, VPN, SHARING, SUPPLICANT, -USER_SET, SETTINGS, SUSPEND, CORE, DEVICE, OLPC]. When "NONE" is given by itself, -logging is disabled. MB = Mobile Broadband, AGENTS = secret agents operations -and communication, SETTINGS = settings/config service operations, OLPC = OLPC -Mesh device operations, CORE = core daemon operations, DEVICE = activation and -general interface operations. +AGENTS, SETTINGS, SUSPEND, CORE, DEVICE, OLPC, WIMAX]. When "NONE" is given by +itself, logging is disabled. MB = Mobile Broadband, AGENTS = secret agents +operations and communication, SETTINGS = settings/config service operations, +OLPC = OLPC Mesh device operations, CORE = core daemon operations, DEVICE = +activation and general interface operations. .SH "SEE ALSO" .BR http://live.gnome.org/NetworkManager/SystemSettings .sp diff --git a/po/LINGUAS b/po/LINGUAS index 2428598623..f77d9c0d23 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -14,6 +14,7 @@ dz el en_CA en_GB +eo es et eu diff --git a/po/POTFILES.in b/po/POTFILES.in index d4d8c4b1e6..94bb473ed7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -15,9 +15,15 @@ policy/org.freedesktop.NetworkManager.policy.in src/nm-netlink-monitor.c src/main.c src/dhcp-manager/nm-dhcp-dhclient.c +src/dhcp-manager/nm-dhcp-dhclient-utils.c src/dhcp-manager/nm-dhcp-manager.c -src/logging/nm-logging.c src/dns-manager/nm-dns-manager.c +src/logging/nm-logging.c +src/modem-manager/nm-modem-cdma.c +src/modem-manager/nm-modem-gsm.c +src/nm-device-bt.c +src/nm-device-ethernet.c +src/nm-device-olpc-mesh.c src/settings/nm-default-wired-connection.c system-settings/plugins/ifcfg-rh/reader.c system-settings/plugins/ifnet/connection_parser.c @@ -8,710 +8,1851 @@ msgid "" msgstr "" "Project-Id-Version: NetworkManager\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-02-13 20:50+0100\n" -"PO-Revision-Date: 2007-02-13 20:50+0100\n" -"Last-Translator: Lasse Bang Mikkelsen <lbm@fatalerror.dk>\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=NetworkManager&component=general\n" +"POT-Creation-Date: 2010-12-11 15:25+0000\n" +"PO-Revision-Date: 2010-12-12 18:49+0100\n" +"Last-Translator: Anders Jenbo <anders@jenbo.dk>\n" "Language-Team: Danish <dansk@dansk-gruppen.dk>\n" +"Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: ../gnome/vpn-properties/nm-vpn-properties.c:417 -msgid "Cannot add VPN connection" -msgstr "Kan ikke tilføje VPN-forbindelse" - -#: ../gnome/vpn-properties/nm-vpn-properties.c:419 +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Launchpad-Export-Date: 2010-12-12 00:44+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: ../cli/src/connections.c:60 +#: ../cli/src/connections.c:76 +#: ../cli/src/devices.c:89 +#: ../cli/src/devices.c:102 +#: ../cli/src/devices.c:112 +#: ../cli/src/devices.c:122 +#: ../cli/src/devices.c:135 +#: ../cli/src/devices.c:146 +#: ../cli/src/devices.c:157 +#: ../cli/src/devices.c:166 +#: ../cli/src/devices.c:175 +msgid "NAME" +msgstr "NAVN" + +#. 0 +#: ../cli/src/connections.c:61 +#: ../cli/src/connections.c:77 +msgid "UUID" +msgstr "UUID" + +#. 1 +#: ../cli/src/connections.c:62 +msgid "DEVICES" +msgstr "ENHEDER" + +#. 2 +#: ../cli/src/connections.c:63 +#: ../cli/src/connections.c:79 +msgid "SCOPE" +msgstr "ANVENDELSESOMRÅDE" + +#. 3 +#: ../cli/src/connections.c:64 +msgid "DEFAULT" +msgstr "STANDARD" + +#. 4 +#: ../cli/src/connections.c:65 +msgid "DBUS-SERVICE" +msgstr "DBUS-TJENESTE" + +#. 5 +#: ../cli/src/connections.c:66 +msgid "SPEC-OBJECT" +msgstr "SPEC-OBJEKT" + +#. 6 +#: ../cli/src/connections.c:67 +msgid "VPN" +msgstr "VPN" + +#. 7 +#. 2 +#: ../cli/src/connections.c:68 +#: ../cli/src/connections.c:84 +#: ../cli/src/devices.c:64 +msgid "DBUS-PATH" +msgstr "DBUS-STI" + +#. 1 +#. 0 +#. 1 +#: ../cli/src/connections.c:78 +#: ../cli/src/devices.c:62 +#: ../cli/src/devices.c:91 +msgid "TYPE" +msgstr "TYPE" + +#. 3 +#: ../cli/src/connections.c:80 +msgid "TIMESTAMP" +msgstr "TIDSSTEMPEL" + +#. 4 +#: ../cli/src/connections.c:81 +msgid "TIMESTAMP-REAL" +msgstr "TIDSSTEMPEL-ÆGTE" + +#. 5 +#: ../cli/src/connections.c:82 +msgid "AUTOCONNECT" +msgstr "FORBIND AUTOMATISK" + +#. 6 +#: ../cli/src/connections.c:83 +msgid "READONLY" +msgstr "SKRIVEBESKYTTET" + +#: ../cli/src/connections.c:160 +#, c-format msgid "" -"No suitable VPN software was found on your system. Contact your system " -"administrator." +"Usage: nmcli con { COMMAND | help }\n" +" COMMAND := { list | status | up | down }\n" +"\n" +" list [id <id> | uuid <id> | system | user]\n" +" status\n" +" up id <id> | uuid <id> [iface <iface>] [ap <hwaddr>] [--nowait] [--timeout <timeout>]\n" +" down id <id> | uuid <id>\n" msgstr "" -"Ingen passende VPN-programmel blev fundet på dit system. Kontakt din system-" -"administrator." +"Brug: nmcli con { KOMMANDO | help }\n" +" KOMMANDO := { list | status | up | down }\n" +"\n" +" list [id <id> | uuid <id> | system | user]\n" +" status\n" +" up id <id> | uuid <id> [iface <iface>] [ap <hwadr>] [--nowait] [--timeout <tidsudløb>]\n" +" down id <id> | uuid <id>\n" + +#: ../cli/src/connections.c:200 +#: ../cli/src/connections.c:541 +#, c-format +msgid "Error: 'con list': %s" +msgstr "Fejl: 'con list': %s" -#: ../gnome/vpn-properties/nm-vpn-properties.c:461 -msgid "Cannot import VPN connection" -msgstr "Kan ikke importere VPN-forbindelse" +#: ../cli/src/connections.c:202 +#: ../cli/src/connections.c:543 +#, c-format +msgid "Error: 'con list': %s; allowed fields: %s" +msgstr "Fejl: 'con list': %s; tilladte felter: %s" + +#: ../cli/src/connections.c:210 +msgid "Connection details" +msgstr "Forbindelsesdetaljer" + +#: ../cli/src/connections.c:385 +#: ../cli/src/connections.c:606 +msgid "system" +msgstr "system" + +#: ../cli/src/connections.c:385 +#: ../cli/src/connections.c:606 +msgid "user" +msgstr "bruger" + +#: ../cli/src/connections.c:387 +msgid "never" +msgstr "aldrig" + +#. "CAPABILITIES" +#. Print header +#. "WIFI-PROPERTIES" +#: ../cli/src/connections.c:388 +#: ../cli/src/connections.c:389 +#: ../cli/src/connections.c:607 +#: ../cli/src/connections.c:610 +#: ../cli/src/devices.c:433 +#: ../cli/src/devices.c:558 +#: ../cli/src/devices.c:584 +#: ../cli/src/devices.c:585 +#: ../cli/src/devices.c:586 +#: ../cli/src/devices.c:587 +#: ../cli/src/devices.c:588 +#: ../cli/src/settings.c:508 +#: ../cli/src/settings.c:551 +#: ../cli/src/settings.c:652 +#: ../cli/src/settings.c:926 +#: ../cli/src/settings.c:927 +#: ../cli/src/settings.c:929 +#: ../cli/src/settings.c:931 +#: ../cli/src/settings.c:1056 +#: ../cli/src/settings.c:1057 +#: ../cli/src/settings.c:1058 +#: ../cli/src/settings.c:1137 +#: ../cli/src/settings.c:1138 +#: ../cli/src/settings.c:1139 +#: ../cli/src/settings.c:1140 +#: ../cli/src/settings.c:1141 +#: ../cli/src/settings.c:1142 +#: ../cli/src/settings.c:1143 +#: ../cli/src/settings.c:1144 +#: ../cli/src/settings.c:1145 +#: ../cli/src/settings.c:1146 +#: ../cli/src/settings.c:1147 +#: ../cli/src/settings.c:1148 +#: ../cli/src/settings.c:1149 +#: ../cli/src/settings.c:1224 +msgid "yes" +msgstr "ja" + +#: ../cli/src/connections.c:388 +#: ../cli/src/connections.c:389 +#: ../cli/src/connections.c:607 +#: ../cli/src/connections.c:610 +#: ../cli/src/devices.c:433 +#: ../cli/src/devices.c:558 +#: ../cli/src/devices.c:584 +#: ../cli/src/devices.c:585 +#: ../cli/src/devices.c:586 +#: ../cli/src/devices.c:587 +#: ../cli/src/devices.c:588 +#: ../cli/src/settings.c:508 +#: ../cli/src/settings.c:510 +#: ../cli/src/settings.c:551 +#: ../cli/src/settings.c:652 +#: ../cli/src/settings.c:926 +#: ../cli/src/settings.c:927 +#: ../cli/src/settings.c:929 +#: ../cli/src/settings.c:931 +#: ../cli/src/settings.c:1056 +#: ../cli/src/settings.c:1057 +#: ../cli/src/settings.c:1058 +#: ../cli/src/settings.c:1137 +#: ../cli/src/settings.c:1138 +#: ../cli/src/settings.c:1139 +#: ../cli/src/settings.c:1140 +#: ../cli/src/settings.c:1141 +#: ../cli/src/settings.c:1142 +#: ../cli/src/settings.c:1143 +#: ../cli/src/settings.c:1144 +#: ../cli/src/settings.c:1145 +#: ../cli/src/settings.c:1146 +#: ../cli/src/settings.c:1147 +#: ../cli/src/settings.c:1148 +#: ../cli/src/settings.c:1149 +#: ../cli/src/settings.c:1224 +msgid "no" +msgstr "nej" + +#: ../cli/src/connections.c:462 +#: ../cli/src/connections.c:505 +msgid "System connections" +msgstr "System forbindelser" + +#: ../cli/src/connections.c:467 +#: ../cli/src/connections.c:518 +msgid "User connections" +msgstr "Bruger forbindelser" + +#: ../cli/src/connections.c:479 +#: ../cli/src/connections.c:1342 +#: ../cli/src/connections.c:1358 +#: ../cli/src/connections.c:1367 +#: ../cli/src/connections.c:1378 +#: ../cli/src/connections.c:1463 +#: ../cli/src/devices.c:964 +#: ../cli/src/devices.c:974 +#: ../cli/src/devices.c:1076 +#: ../cli/src/devices.c:1083 +#, c-format +msgid "Error: %s argument is missing." +msgstr "Fejl: %s parameter mangler." -#: ../gnome/vpn-properties/nm-vpn-properties.c:463 +#: ../cli/src/connections.c:492 #, c-format -msgid "" -"Cannot find suitable software for VPN connection type '%s' to import the " -"file '%s'. Contact your system administrator." -msgstr "" -"Kan ikke finde passende programmel til VPN-forbindelsestypen '%s', til " -"import af filen '%s'. Kontakt din system-administrator." +msgid "Error: %s - no such connection." +msgstr "Fejl: %s - ingen sådan forbindelse." + +#: ../cli/src/connections.c:524 +#: ../cli/src/connections.c:1391 +#: ../cli/src/connections.c:1481 +#: ../cli/src/devices.c:787 +#: ../cli/src/devices.c:854 +#: ../cli/src/devices.c:988 +#: ../cli/src/devices.c:1089 +#, c-format +msgid "Unknown parameter: %s\n" +msgstr "Ukendt parameter: %s\n" -#: ../gnome/vpn-properties/nm-vpn-properties.c:580 +#: ../cli/src/connections.c:533 #, c-format -msgid "Error retrieving VPN connection '%s'" -msgstr "Fejl ved hentning af VPN-forbindelsen '%s'" +msgid "Error: no valid parameter specified." +msgstr "Fejl: ingen korrekte parameter angivet." -#: ../gnome/vpn-properties/nm-vpn-properties.c:583 +#: ../cli/src/connections.c:548 +#: ../cli/src/connections.c:1584 +#: ../cli/src/devices.c:1295 +#: ../cli/src/network-manager.c:359 #, c-format -msgid "" -"Could not find the UI files for VPN connection type '%s'. Contact your " -"system administrator." -msgstr "" -"Kunne ikke finde brugergrænseflade-filerne til VPN-forbindelsestypen '%s'. " -"Kontakt din system-administrator." +msgid "Error: %s." +msgstr "Fejl: %s." -#: ../gnome/vpn-properties/nm-vpn-properties.c:727 +#: ../cli/src/connections.c:655 #, c-format -msgid "Delete VPN connection \"%s\"?" -msgstr "Slet VPN-forbindelsen \"%s\"?" +msgid "Error: 'con status': %s" +msgstr "Fejl: 'con status': %s" -#: ../gnome/vpn-properties/nm-vpn-properties.c:730 +#: ../cli/src/connections.c:657 #, c-format -msgid "" -"All information about the VPN connection \"%s\" will be lost and you may " -"need your system administrator to provide information to create a new " -"connection." -msgstr "" -"Al information omkring VPN-forbindelsen \"%s\" vil gå tabt og du får " -"muligvis brug for din system-administrator, som kan give dig de nødvendige " -"informationer til oprettelse af en ny forbindelse." - -#: ../gnome/vpn-properties/nm-vpn-properties.c:924 -msgid "Unable to load" -msgstr "Kan ikke indlæse" - -#: ../gnome/vpn-properties/nm-vpn-properties.c:926 -msgid "Cannot find some needed resources (the glade file)!" -msgstr "Kan ikke finde nogle krævede ressourcer (glade-filen)!" - -#. druid_window = GTK_DIALOG (gtk_dialog_new_with_buttons (_("Create VPN Connection"), -#. NULL, -#. GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, -#. GTK_STOCK_CANCEL, -#. GTK_RESPONSE_REJECT, -#. GTK_STOCK_APPLY, -#. GTK_RESPONSE_ACCEPT, -#. NULL)); -#: ../gnome/vpn-properties/nm-vpn-properties.c:1081 -msgid "Create VPN Connection" -msgstr "Opret VPN-forbindelse" - -#. gtk_container_add (GTK_CONTAINER (druid_window->vbox), GTK_WIDGET(gtk_label_new("Some label"))); -#. gtk_box_pack_start (GTK_BOX (druid_window->vbox), GTK_WIDGET(druid), TRUE,TRUE,0); -#. gtk_box_pack_start (GTK_BOX (druid_window->vbox), GTK_WIDGET(gtk_label_new("Some label")), TRUE,TRUE,0); -#. toplevel = gtk_widget_get_toplevel (GTK_WIDGET (druid)); -#. gtk_signal_connect (GTK_OBJECT (toplevel), "delete_event", GTK_SIGNAL_FUNC (vpn_window_close), NULL); -#. make the druid window modal wrt. our main window -#. gtk_window_set_modal (druid_window, TRUE); -#. gtk_window_set_transient_for (GTK_WINDOW(druid_window), GTK_WINDOW (dialog)); -#. Edit dialog -#: ../gnome/vpn-properties/nm-vpn-properties.c:1099 -msgid "Edit VPN Connection" -msgstr "Redigér VPN-forbindelse" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:1 -msgid "Add a new VPN connection" -msgstr "Tilføj ny VPN-forbindelse" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:2 -msgid "Delete the selected VPN connection" -msgstr "Slet den valgte VPN-forbindelse" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:3 -msgid "E_xport" -msgstr "E_ksportér" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:4 -msgid "Edit the selected VPN connection" -msgstr "Redigér den valgte VPN-forbindelse" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:5 -msgid "Export the VPN settings to a file" -msgstr "Eksportér VPN-opsætningen til en fil" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:6 -msgid "Export the selected VPN connection to a file" -msgstr "Eksportér den valgte VPN-forbindelse til en fil" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:7 -msgid "Manage Virtual Private Network Connections" -msgstr "Håndtér virtuelle private netværks-forbindelser (VPN)" - -#: ../gnome/vpn-properties/nm-vpn-properties.glade.h:8 -msgid "VPN Connections" -msgstr "VPN-forbindelser" - -#: ../src/nm-ap-security-wep.c:52 -msgid "40-bit WEP" -msgstr "40-bit WEP" - -#: ../src/nm-ap-security-wep.c:54 -msgid "104-bit WEP" -msgstr "104-bit WEP" - -#: ../src/nm-ap-security-wpa-psk.c:51 -msgid "WPA TKIP" -msgstr "WPA TKIP" - -#: ../src/nm-ap-security-wpa-psk.c:53 -msgid "WPA CCMP" -msgstr "WPA CCMP" - -#: ../src/nm-ap-security-wpa-psk.c:55 -msgid "WPA Automatic" -msgstr "WPA automatisk" - -#: ../src/nm-ap-security-wpa-psk.c:60 -msgid "WPA2 TKIP" -msgstr "WPA2 TKIP" - -#: ../src/nm-ap-security-wpa-psk.c:62 -msgid "WPA2 CCMP" -msgstr "WPA2 CCMP" - -#: ../src/nm-ap-security-wpa-psk.c:64 -msgid "WPA2 Automatic" -msgstr "WPA2 automatisk" - -#: ../src/nm-ap-security.c:334 +msgid "Error: 'con status': %s; allowed fields: %s" +msgstr "Fejl: 'con status': %s; tilladte fejlter: %s" + +#: ../cli/src/connections.c:664 +msgid "Active connections" +msgstr "Aktive forbindelser" + +#: ../cli/src/connections.c:1034 +#, c-format +msgid "no active connection on device '%s'" +msgstr "ingen aktiv forbindelse på enhed '%s'" + +#: ../cli/src/connections.c:1042 +#, c-format +msgid "no active connection or device" +msgstr "ingen aktiv forbindelse eller enhed" + +#: ../cli/src/connections.c:1092 +#, c-format +msgid "device '%s' not compatible with connection '%s'" +msgstr "enhed \"%s\" er ikke kompatibel med forbindelse \"%s\"" + +#: ../cli/src/connections.c:1094 +#, c-format +msgid "no device found for connection '%s'" +msgstr "ingen enhed fundet til forbindelsen '%s'" + +#: ../cli/src/connections.c:1105 +msgid "activating" +msgstr "aktiverer" + +#: ../cli/src/connections.c:1107 +msgid "activated" +msgstr "aktiveret" + +#: ../cli/src/connections.c:1110 +#: ../cli/src/connections.c:1133 +#: ../cli/src/connections.c:1166 +#: ../cli/src/devices.c:247 +#: ../cli/src/devices.c:559 +#: ../cli/src/network-manager.c:94 +#: ../cli/src/network-manager.c:149 +#: ../cli/src/settings.c:473 +msgid "unknown" +msgstr "ukendt" + +#: ../cli/src/connections.c:1119 +msgid "VPN connecting (prepare)" +msgstr "VPN-forbinder (forbered)" + +#: ../cli/src/connections.c:1121 +msgid "VPN connecting (need authentication)" +msgstr "VPN-forbinder (kræver godkendelse)" + +#: ../cli/src/connections.c:1123 +msgid "VPN connecting" +msgstr "VPN-forbinder" + +#: ../cli/src/connections.c:1125 +msgid "VPN connecting (getting IP configuration)" +msgstr "VPN-forbinder (indhenter IP-konfiguration)" + +#: ../cli/src/connections.c:1127 +msgid "VPN connected" +msgstr "VPN-forbundet" + +#: ../cli/src/connections.c:1129 +msgid "VPN connection failed" +msgstr "VPN-forbindelse fejlede" + +#: ../cli/src/connections.c:1131 +msgid "VPN disconnected" +msgstr "VPN afbrudt" + +#: ../cli/src/connections.c:1142 +msgid "unknown reason" +msgstr "ukendt årsag" + +#: ../cli/src/connections.c:1144 msgid "none" msgstr "ingen" -#: ../src/nm-netlink-monitor.c:174 +#: ../cli/src/connections.c:1146 +msgid "the user was disconnected" +msgstr "brugeren blev frakoblet" + +#: ../cli/src/connections.c:1148 +msgid "the base network connection was interrupted" +msgstr "basenetværketsforbindelsen blev afbrudt" + +#: ../cli/src/connections.c:1150 +msgid "the VPN service stopped unexpectedly" +msgstr "VPN servicen stoppede uventet" + +#: ../cli/src/connections.c:1152 +msgid "the VPN service returned invalid configuration" +msgstr "VPN-tjenesten retunerede en ikke gyldig konfiguration" + +#: ../cli/src/connections.c:1154 +msgid "the connection attempt timed out" +msgstr "forbindelsesforsøget udløb" + +#: ../cli/src/connections.c:1156 +msgid "the VPN service did not start in time" +msgstr "VPN-tjenesten startede ikke i tide" + +#: ../cli/src/connections.c:1158 +msgid "the VPN service failed to start" +msgstr "VPN-tjenesten kunne ikke starte" + +#: ../cli/src/connections.c:1160 +msgid "no valid VPN secrets" +msgstr "ingen korrekte VPN-hemmeligheder" + +#: ../cli/src/connections.c:1162 +msgid "invalid VPN secrets" +msgstr "ukorrekte VPN-hemmeligheder" + +#: ../cli/src/connections.c:1164 +msgid "the connection was removed" +msgstr "forbindelsen blev fjernet" + +#: ../cli/src/connections.c:1178 +#, c-format +msgid "state: %s\n" +msgstr "tilstand: %s\n" + +#: ../cli/src/connections.c:1181 +#: ../cli/src/connections.c:1207 +#, c-format +msgid "Connection activated\n" +msgstr "Forbindelse aktiveret\n" + +#: ../cli/src/connections.c:1184 +#, c-format +msgid "Error: Connection activation failed." +msgstr "Fejl: Forbindelsesaktivering fejlede." + +#: ../cli/src/connections.c:1203 +#, c-format +msgid "state: %s (%d)\n" +msgstr "tilstand: %s (%d)\n" + +#: ../cli/src/connections.c:1213 +#, c-format +msgid "Error: Connection activation failed: %s." +msgstr "Fejl: Forbindelsesaktivering fejlede: %s." + +#: ../cli/src/connections.c:1230 +#: ../cli/src/devices.c:911 +#, c-format +msgid "Error: Timeout %d sec expired." +msgstr "Fejl: Ventetid på %d sek udløb." + +#: ../cli/src/connections.c:1273 +#, c-format +msgid "Error: Connection activation failed: %s" +msgstr "Fejl: Forbindelsesaktivering fejlede: %s" + +#: ../cli/src/connections.c:1287 +#, c-format +msgid "Error: Obtaining active connection for '%s' failed." +msgstr "Fejl: Indhentelse af aktiv forbindelse for '%s' mislykkedes." + +#: ../cli/src/connections.c:1296 +#, c-format +msgid "Active connection state: %s\n" +msgstr "Aktiv forbindelsestilstand: %s\n" + +#: ../cli/src/connections.c:1297 +#, c-format +msgid "Active connection path: %s\n" +msgstr "Aktiv forbindelsessti: %s\n" + +#: ../cli/src/connections.c:1351 +#: ../cli/src/connections.c:1472 +#, c-format +msgid "Error: Unknown connection: %s." +msgstr "Fejl: Ukendt forbindelse: %s." + +#: ../cli/src/connections.c:1386 +#: ../cli/src/devices.c:982 +#, c-format +msgid "Error: timeout value '%s' is not valid." +msgstr "Fejl: Værdi for tidsudløb \"%s\" er ikke korrekt." + +#: ../cli/src/connections.c:1399 +#: ../cli/src/connections.c:1489 +#, c-format +msgid "Error: id or uuid has to be specified." +msgstr "Fejl: Id eller uuid skal angives." + +#: ../cli/src/connections.c:1419 +#, c-format +msgid "Error: No suitable device found: %s." +msgstr "Fejl: Ingen passende enhed fundet: %s." + +#: ../cli/src/connections.c:1421 +#, c-format +msgid "Error: No suitable device found." +msgstr "Fejl: Ingen passende enhed fundet." + +#: ../cli/src/connections.c:1516 +#, c-format +msgid "Warning: Connection not active\n" +msgstr "Advarsel: Forbindelse ikke aktiv\n" + +#: ../cli/src/connections.c:1573 +#, c-format +msgid "Error: 'con' command '%s' is not valid." +msgstr "Fejl: 'con'-kommandoen '%s' er ikke gyldig." + +#: ../cli/src/connections.c:1609 +#, c-format +msgid "Error: could not connect to D-Bus." +msgstr "Fejl: Kunne ikke forbinde til D-Bus." + +#: ../cli/src/connections.c:1616 +#, c-format +msgid "Error: Could not get system settings." +msgstr "Fejl: Kunne ikke indhente systemopsætning." + +#: ../cli/src/connections.c:1624 +#, c-format +msgid "Error: Could not get user settings." +msgstr "Fejl: Kunne ikke indhente brugeropsætning." + +#: ../cli/src/connections.c:1634 +#, c-format +msgid "Error: Can't obtain connections: settings services are not running." +msgstr "Fejl: Kan ikke indhente forbindelser: Opsætningstjenester kører ikke." + +#. 0 +#. 9 +#: ../cli/src/devices.c:61 +#: ../cli/src/devices.c:90 +#: ../cli/src/devices.c:185 +msgid "DEVICE" +msgstr "ENHED" + +#. 1 +#. 4 +#. 0 +#: ../cli/src/devices.c:63 +#: ../cli/src/devices.c:94 +#: ../cli/src/network-manager.c:36 +msgid "STATE" +msgstr "TILSTAND" + +#: ../cli/src/devices.c:73 +msgid "GENERAL" +msgstr "GENERELT" + +#. 0 +#: ../cli/src/devices.c:74 +msgid "CAPABILITIES" +msgstr "FUNKTIONALITETER" + +#. 1 +#: ../cli/src/devices.c:75 +msgid "WIFI-PROPERTIES" +msgstr "WIFI-EGENSKABER" + +#. 2 +#: ../cli/src/devices.c:76 +msgid "AP" +msgstr "AP" + +#. 3 +#: ../cli/src/devices.c:77 +msgid "WIRED-PROPERTIES" +msgstr "TRÅDET-EGENSKABER" + +#. 4 +#: ../cli/src/devices.c:78 +msgid "IP4-SETTINGS" +msgstr "IP4-INSTILLINGER" + +#. 5 +#: ../cli/src/devices.c:79 +msgid "IP4-DNS" +msgstr "IP4-DNS" + +#. 6 +#: ../cli/src/devices.c:80 +msgid "IP6-SETTINGS" +msgstr "IP6-INDSTILLINGER" + +#. 7 +#: ../cli/src/devices.c:81 +msgid "IP6-DNS" +msgstr "IP6-DNS" + +#. 2 +#: ../cli/src/devices.c:92 +msgid "DRIVER" +msgstr "DRIVER" + +#. 3 +#: ../cli/src/devices.c:93 +msgid "HWADDR" +msgstr "HWADDR" + +#. 0 +#: ../cli/src/devices.c:103 +msgid "CARRIER-DETECT" +msgstr "UDBYDER-OPFANG" + +#. 1 +#: ../cli/src/devices.c:104 +msgid "SPEED" +msgstr "HASTIGHED" + +#. 0 +#: ../cli/src/devices.c:113 +msgid "CARRIER" +msgstr "UDBYDER" + +#. 0 +#: ../cli/src/devices.c:123 +msgid "WEP" +msgstr "WEP" + +#. 1 +#: ../cli/src/devices.c:124 +msgid "WPA" +msgstr "WPA" + +#. 2 +#: ../cli/src/devices.c:125 +msgid "WPA2" +msgstr "WPA2" + +#. 3 +#: ../cli/src/devices.c:126 +msgid "TKIP" +msgstr "TKIP" + +#. 4 +#: ../cli/src/devices.c:127 +msgid "CCMP" +msgstr "CCMP" + +#. 0 +#: ../cli/src/devices.c:136 +#: ../cli/src/devices.c:147 +msgid "ADDRESS" +msgstr "ADRESSE" + +#. 1 +#: ../cli/src/devices.c:137 +#: ../cli/src/devices.c:148 +msgid "PREFIX" +msgstr "PRÆFIKS" + +#. 2 +#: ../cli/src/devices.c:138 +#: ../cli/src/devices.c:149 +msgid "GATEWAY" +msgstr "ADGANGSPUNKT" + +#. 0 +#: ../cli/src/devices.c:158 +#: ../cli/src/devices.c:167 +msgid "DNS" +msgstr "DNS" + +#. 0 +#: ../cli/src/devices.c:176 +msgid "SSID" +msgstr "SSID" + +#. 1 +#: ../cli/src/devices.c:177 +msgid "BSSID" +msgstr "BSSID" + +#. 2 +#: ../cli/src/devices.c:178 +msgid "MODE" +msgstr "TILSTAND" + +#. 3 +#: ../cli/src/devices.c:179 +msgid "FREQ" +msgstr "FREK" + +#. 4 +#: ../cli/src/devices.c:180 +msgid "RATE" +msgstr "RATE" + +#. 5 +#: ../cli/src/devices.c:181 +msgid "SIGNAL" +msgstr "SIGNAL" + +#. 6 +#: ../cli/src/devices.c:182 +msgid "SECURITY" +msgstr "SIKKERHED" + +#. 7 +#: ../cli/src/devices.c:183 +msgid "WPA-FLAGS" +msgstr "WPA-FLAG" + +#. 8 +#: ../cli/src/devices.c:184 +msgid "RSN-FLAGS" +msgstr "RSN-FLAG" + +#. 10 +#: ../cli/src/devices.c:186 +msgid "ACTIVE" +msgstr "AKTIV" + +#: ../cli/src/devices.c:209 #, c-format msgid "" -"unable to create netlink socket for monitoring wired ethernet devices - %s" +"Usage: nmcli dev { COMMAND | help }\n" +"\n" +" COMMAND := { status | list | disconnect | wifi }\n" +"\n" +" status\n" +" list [iface <iface>]\n" +" disconnect iface <iface> [--nowait] [--timeout <timeout>]\n" +" wifi [list [iface <iface>] [hwaddr <hwaddr>]]\n" +"\n" msgstr "" -"kan ikke oprette netlink sokkel til overvågning af kablede ethernet enheder " -"- %s" +"Brug: nmcli dev { KOMMANDO | help }\n" +"\n" +" KOMMANDO := { status | list | disconnect | wifi }\n" +"\n" +" status\n" +" list [iface <iface>]\n" +" disconnect iface <iface> [--nowait] [--timeout <tidsudløb>]\n" +" wifi [list [iface <iface>] [hwaddr <hwadr>]]\n" +"\n" + +#: ../cli/src/devices.c:229 +msgid "unmanaged" +msgstr "uhåndteret" + +#: ../cli/src/devices.c:231 +msgid "unavailable" +msgstr "utilgængelig" + +#: ../cli/src/devices.c:233 +#: ../cli/src/network-manager.c:91 +msgid "disconnected" +msgstr "frakoblet" + +#: ../cli/src/devices.c:235 +msgid "connecting (prepare)" +msgstr "forbinder (forbereder)" + +#: ../cli/src/devices.c:237 +msgid "connecting (configuring)" +msgstr "forbinder (konfigurerer)" + +#: ../cli/src/devices.c:239 +msgid "connecting (need authentication)" +msgstr "forbinder (venter på godkendelse)" + +#: ../cli/src/devices.c:241 +msgid "connecting (getting IP configuration)" +msgstr "forbinder (henter IP-konfiguration)" + +#: ../cli/src/devices.c:243 +#: ../cli/src/network-manager.c:89 +msgid "connected" +msgstr "tilsluttet" + +#: ../cli/src/devices.c:245 +msgid "connection failed" +msgstr "forbindelse fejlet" + +#: ../cli/src/devices.c:268 +#: ../cli/src/devices.c:425 +msgid "Unknown" +msgstr "Ukendt" + +#: ../cli/src/devices.c:300 +msgid "(none)" +msgstr "(ingen)" + +#: ../cli/src/devices.c:325 +#, c-format +msgid "%s: error converting IP4 address 0x%X" +msgstr "%s: Fejl under konvertering af IP4-adresse 0x%X" + +#: ../cli/src/devices.c:394 +#, c-format +msgid "%u MHz" +msgstr "%u MHz" + +#: ../cli/src/devices.c:395 +#, c-format +msgid "%u MB/s" +msgstr "%u MB/s" + +#: ../cli/src/devices.c:404 +msgid "Encrypted: " +msgstr "Krypteret: " + +#: ../cli/src/devices.c:409 +msgid "WEP " +msgstr "WEP " + +#: ../cli/src/devices.c:411 +msgid "WPA " +msgstr "WPA " + +#: ../cli/src/devices.c:413 +msgid "WPA2 " +msgstr "WPA2 " + +#: ../cli/src/devices.c:416 +msgid "Enterprise " +msgstr "Erhverv " + +#: ../cli/src/devices.c:425 +msgid "Ad-Hoc" +msgstr "Ad-Hoc" + +#: ../cli/src/devices.c:425 +msgid "Infrastructure" +msgstr "Infrastruktur" + +#: ../cli/src/devices.c:487 +#, c-format +msgid "Error: 'dev list': %s" +msgstr "Fejl: 'dev list': %s" + +#: ../cli/src/devices.c:489 +#, c-format +msgid "Error: 'dev list': %s; allowed fields: %s" +msgstr "Fejl: 'dev list'': %s; tilladte felter: %s" + +#: ../cli/src/devices.c:498 +msgid "Device details" +msgstr "Enhedsdetaljer" -#: ../src/nm-netlink-monitor.c:192 +#: ../cli/src/devices.c:528 +#: ../cli/src/devices.c:927 +msgid "(unknown)" +msgstr "(ukendt)" + +#: ../cli/src/devices.c:529 +msgid "unknown)" +msgstr "ukendt)" + +#: ../cli/src/devices.c:555 +#, c-format +msgid "%u Mb/s" +msgstr "%u Mb/s" + +#. Print header +#. "WIRED-PROPERTIES" +#: ../cli/src/devices.c:628 +msgid "on" +msgstr "tændt" + +#: ../cli/src/devices.c:628 +msgid "off" +msgstr "slukket" + +#: ../cli/src/devices.c:810 +#, c-format +msgid "Error: 'dev status': %s" +msgstr "Fejl: 'dev status': %s" + +#: ../cli/src/devices.c:812 +#, c-format +msgid "Error: 'dev status': %s; allowed fields: %s" +msgstr "Fejl: 'dev status': %s; tilladte felter: %s" + +#: ../cli/src/devices.c:819 +msgid "Status of devices" +msgstr "Status på enheder" + +#: ../cli/src/devices.c:847 +#, c-format +msgid "Error: '%s' argument is missing." +msgstr "Fejl: '%s'-parameter mangler." + +#: ../cli/src/devices.c:876 +#: ../cli/src/devices.c:1015 +#: ../cli/src/devices.c:1138 +#, c-format +msgid "Error: Device '%s' not found." +msgstr "Fejl: Enhed \"%s\" ikke fundet." + +#: ../cli/src/devices.c:899 +#, c-format +msgid "Success: Device '%s' successfully disconnected." +msgstr "Succes: Enhed '%s' frakoblet." + +#: ../cli/src/devices.c:924 +#, c-format +msgid "Error: Device '%s' (%s) disconnecting failed: %s" +msgstr "Fejl: Frakobling af enhed \"%s\" (%s) mislykkedes: %s" + +#: ../cli/src/devices.c:932 +#, c-format +msgid "Device state: %d (%s)\n" +msgstr "Enhedstilstand: %d (%s)\n" + +#: ../cli/src/devices.c:996 +#, c-format +msgid "Error: iface has to be specified." +msgstr "Fejl: iface skal være angivet." + +#: ../cli/src/devices.c:1114 +#, c-format +msgid "Error: 'dev wifi': %s" +msgstr "Fejl: 'dev wifi': %s" + +#: ../cli/src/devices.c:1116 +#, c-format +msgid "Error: 'dev wifi': %s; allowed fields: %s" +msgstr "Fejl: 'dev wifi': %s; tilladte felter: %s" + +#: ../cli/src/devices.c:1123 +msgid "WiFi scan list" +msgstr "WiFi-skanningsliste" + +#: ../cli/src/devices.c:1158 +#: ../cli/src/devices.c:1212 +#, c-format +msgid "Error: Access point with hwaddr '%s' not found." +msgstr "Fejl: Adgangspunkt med hwadr '%s' blev ikke fundet." + +#: ../cli/src/devices.c:1175 +#, c-format +msgid "Error: Device '%s' is not a WiFi device." +msgstr "Fejl: Enhed '%s' er ikke en WiFi-enhed." + +#: ../cli/src/devices.c:1239 +#, c-format +msgid "Error: 'dev wifi' command '%s' is not valid." +msgstr "Fejl: 'dev wifi'-kommandoen '%s' er ikke gyldig." + +#: ../cli/src/devices.c:1286 +#, c-format +msgid "Error: 'dev' command '%s' is not valid." +msgstr "Fejl: 'dev'-kommanoden '%s' er ikke gyldig." + +#: ../cli/src/network-manager.c:35 +msgid "RUNNING" +msgstr "KØRER" + +#. 1 +#: ../cli/src/network-manager.c:37 +msgid "NET-ENABLED" +msgstr "NET-AKTIVERET" + +#. 2 +#: ../cli/src/network-manager.c:38 +msgid "WIFI-HARDWARE" +msgstr "WIFI-HARDWARE" + +#. 3 +#: ../cli/src/network-manager.c:39 +msgid "WIFI" +msgstr "WIFI" + +#. 4 +#: ../cli/src/network-manager.c:40 +msgid "WWAN-HARDWARE" +msgstr "WWAN-HARDWARE" + +#. 5 +#: ../cli/src/network-manager.c:41 +msgid "WWAN" +msgstr "WWAN" + +#: ../cli/src/network-manager.c:64 #, c-format msgid "" -"unable to bind to netlink socket for monitoring wired ethernet devices - %s" +"Usage: nmcli nm { COMMAND | help }\n" +"\n" +" COMMAND := { status | enable | sleep | wifi | wwan }\n" +"\n" +" status\n" +" enable [true|false]\n" +" sleep [true|false]\n" +" wifi [on|off]\n" +" wwan [on|off]\n" +"\n" msgstr "" -"kan ikke tilslutte netlink sokkel til overvågning af kablede ethernet " -"enheder - %s" +"Brug: nmcli nm { KOMMANDO | help }\n" +"\n" +" KOMMANDO := { status | enable | sleep | wifi | wwan }\n" +"\n" +" status\n" +" enable [true|false]\n" +" sleep [true|false]\n" +" wifi [on|off]\n" +" wwan [on|off]\n" +"\n" + +#: ../cli/src/network-manager.c:85 +msgid "asleep" +msgstr "sover" + +#: ../cli/src/network-manager.c:87 +msgid "connecting" +msgstr "forbinder" + +#: ../cli/src/network-manager.c:128 +#, c-format +msgid "Error: 'nm status': %s" +msgstr "Fejl: 'nm status': %s" -#: ../src/nm-netlink-monitor.c:427 -msgid "operation took too long" -msgstr "handlingen overskred tidsgrænsen" +#: ../cli/src/network-manager.c:130 +#, c-format +msgid "Error: 'nm status': %s; allowed fields: %s" +msgstr "Fejl: 'nm status': %s; tilladte felter: %s" + +#: ../cli/src/network-manager.c:137 +msgid "NetworkManager status" +msgstr "Status for NetworkManager" + +#. Print header +#: ../cli/src/network-manager.c:144 +#: ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:146 +#: ../cli/src/network-manager.c:147 +#: ../cli/src/network-manager.c:154 +#: ../cli/src/network-manager.c:247 +#: ../cli/src/network-manager.c:296 +#: ../cli/src/network-manager.c:328 +msgid "enabled" +msgstr "aktiveret" + +#: ../cli/src/network-manager.c:144 +#: ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:146 +#: ../cli/src/network-manager.c:147 +#: ../cli/src/network-manager.c:154 +#: ../cli/src/network-manager.c:247 +#: ../cli/src/network-manager.c:296 +#: ../cli/src/network-manager.c:328 +msgid "disabled" +msgstr "deaktiveret" + +#: ../cli/src/network-manager.c:152 +msgid "running" +msgstr "kører" + +#: ../cli/src/network-manager.c:152 +msgid "not running" +msgstr "kører ikke" + +#: ../cli/src/network-manager.c:175 +#, c-format +msgid "Error: Couldn't connect to system bus: %s" +msgstr "Fejl: Kunne ikke forbinde til systembus: %s" -#: ../src/nm-netlink-monitor.c:524 -msgid "received data from wrong type of sender" -msgstr "modtog data fra forkert type afsender" +#: ../cli/src/network-manager.c:186 +#, c-format +msgid "Error: Couldn't create D-Bus object proxy." +msgstr "Fejl: Kunne ikke oprette proxy-objekt for D-Bus." -#: ../src/nm-netlink-monitor.c:537 -msgid "received data from unexpected sender" -msgstr "modtog data fra uventet afsender" +#: ../cli/src/network-manager.c:192 +#, c-format +msgid "Error in sleep: %s" +msgstr "Fejl ved søvn: %s" -#: ../src/nm-netlink-monitor.c:666 -msgid "too much data was sent over socket and some of it was lost" -msgstr "for meget data var sendt over sokkelen og noget gik tabt" +#: ../cli/src/network-manager.c:237 +#: ../cli/src/network-manager.c:286 +#: ../cli/src/network-manager.c:318 +#, c-format +msgid "Error: '--fields' value '%s' is not valid here; allowed fields: %s" +msgstr "Fejl: '--fields'-værdi '%s' er ikke gyldig her; tilladte felter: %s" -#: ../src/nm-netlink-monitor.c:774 -msgid "error occurred while waiting for data on socket" -msgstr "der opstod en fejl mens der blev ventet på data på sokkelen" +#: ../cli/src/network-manager.c:245 +msgid "Networking enabled" +msgstr "Netværk aktiveret" -#: ../src/nm-ap-security-wpa-eap.c:93 ../src/nm-ap-security-wpa-eap.c:117 -msgid "WPA2 Enterprise" -msgstr "WPA2 i virksomhed" +#: ../cli/src/network-manager.c:256 +#, c-format +msgid "Error: invalid 'enable' parameter: '%s'; use 'true' or 'false'." +msgstr "Fejl: Ugyldig 'enable'-parameter: '%s'; brug 'true' eller 'false'." -#: ../src/nm-ap-security-wpa-eap.c:95 ../src/nm-ap-security-wpa-eap.c:122 -msgid "WPA Enterprise" -msgstr "WPA i virksomhed" +#: ../cli/src/network-manager.c:265 +#, c-format +msgid "Error: Sleeping status is not exported by NetworkManager." +msgstr "Fejl: NetworkManager eksporterer ikke søvnstatus." -#: ../src/nm-ap-security-leap.c:66 ../src/nm-ap-security-leap.c:82 -msgid "LEAP" -msgstr "LEAP" +#: ../cli/src/network-manager.c:273 +#, c-format +msgid "Error: invalid 'sleep' parameter: '%s'; use 'true' or 'false'." +msgstr "Fejl: Ugyldig 'sleep'-parameter: '%s'; brug 'true' eller 'false'." -#~ msgid "Passphrase for wireless network %s" -#~ msgstr "Adgangskode til trådløst netværk %s" +#: ../cli/src/network-manager.c:294 +msgid "WiFi enabled" +msgstr "WiFi aktiveret" -#~ msgid "Connection to the wireless network '%s' failed." -#~ msgstr "Tilslutning til det trådløse netværk '%s' mislykkedes." +#: ../cli/src/network-manager.c:305 +#, c-format +msgid "Error: invalid 'wifi' parameter: '%s'." +msgstr "Fejl: Ugyldig 'wifi'-parameter: '%s'." -#~ msgid "Connection to the wired network failed." -#~ msgstr "Tilslutning til det kablede netværk mislykkedes." +#: ../cli/src/network-manager.c:326 +msgid "WWAN enabled" +msgstr "WWAN aktiveret" -#~ msgid "Error displaying connection information: " -#~ msgstr "Fejl ved visning af forbindelses-information: " +#: ../cli/src/network-manager.c:337 +#, c-format +msgid "Error: invalid 'wwan' parameter: '%s'." +msgstr "Fejl: Ugyldig 'wwan'-parameter: '%s'." -#~ msgid "Could not find some required resources (the glade file)!" -#~ msgstr "Kunne ikke finde nogle krævede ressourcer (glade-filen)!" +#: ../cli/src/network-manager.c:348 +#, c-format +msgid "Error: 'nm' command '%s' is not valid." +msgstr "Fejl: 'nm'-kommando '%s' er ikke gyldig." -#~ msgid "No active connections!" -#~ msgstr "Ingen aktive forbindelser!" +#: ../cli/src/nmcli.c:69 +#, c-format +msgid "" +"Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" +"\n" +"OPTIONS\n" +" -t[erse] terse output\n" +" -p[retty] pretty output\n" +" -m[ode] tabular|multiline output mode\n" +" -f[ields] <field1,field2,...>|all|common specify fields to output\n" +" -e[scape] yes|no escape columns separators in values\n" +" -v[ersion] show program version\n" +" -h[elp] print this help\n" +"\n" +"OBJECT\n" +" nm NetworkManager status\n" +" con NetworkManager connections\n" +" dev devices managed by NetworkManager\n" +"\n" +msgstr "" +"Brug: %s [TILVALG] OBJEKT { KOMMANDO | help }\n" +"\n" +"TILVALG\n" +" -t[erse] kort udskrift\n" +" -p[retty] pæn udskrift\n" +" -m[ode] tabular|multiline udskriftstilstand\n" +" -f[ields] <felt1,felt2,...>|all|common angiv felter til udskrift\n" +" -e[scape] yes|no undvig kolonneadskillere i værdier\n" +" -v[ersion] vis programversion\n" +" -h[elp] vis denne hjælpetekst\n" +"\n" +"OBJEKT\n" +" nm status for NetworkManager \n" +" con forbindelser for NetworkManager\n" +" dev enheder håndteret af NetworkManager\n" +"\n" + +#: ../cli/src/nmcli.c:113 +#, c-format +msgid "Error: Object '%s' is unknown, try 'nmcli help'." +msgstr "Fejl: Objekt '%s' er ukendt, prøv 'nmcli help'." -#~ msgid "Wired Ethernet (%s)" -#~ msgstr "Kablet Ethernet (%s)" +#: ../cli/src/nmcli.c:143 +#, c-format +msgid "Error: Option '--terse' is specified the second time." +msgstr "Fejl: Tilvalg '--terse' er angivet anden gang." -#~ msgid "Wireless Ethernet (%s)" -#~ msgstr "Trådløst Ethernet (%s)" +#: ../cli/src/nmcli.c:148 +#, c-format +msgid "Error: Option '--terse' is mutually exclusive with '--pretty'." +msgstr "Fejl: Tilvalg '--terse' kan ikke bruges sammen med '--pretty'." + +#: ../cli/src/nmcli.c:156 +#, c-format +msgid "Error: Option '--pretty' is specified the second time." +msgstr "Fejl: Tilvalg '--pretty' er angivet anden gang." + +#: ../cli/src/nmcli.c:161 +#, c-format +msgid "Error: Option '--pretty' is mutually exclusive with '--terse'." +msgstr "Fejl: Tilvalg '--pretty' kan ikke bruges sammen med '--terse'." + +#: ../cli/src/nmcli.c:171 +#: ../cli/src/nmcli.c:187 +#, c-format +msgid "Error: missing argument for '%s' option." +msgstr "Fejl: Mangler argument for tilvalget '%s'." + +#: ../cli/src/nmcli.c:180 +#: ../cli/src/nmcli.c:196 +#, c-format +msgid "Error: '%s' is not valid argument for '%s' option." +msgstr "Fejl: '%s' er ikke et gyldigt argument for tilvalget '%s'." + +#: ../cli/src/nmcli.c:203 +#, c-format +msgid "Error: fields for '%s' options are missing." +msgstr "Fejl: Felter for tilvalgene '%s' mangler." + +#: ../cli/src/nmcli.c:209 +#, c-format +msgid "nmcli tool, version %s\n" +msgstr "nmcli-værktøj, version %s\n" + +#: ../cli/src/nmcli.c:215 +#, c-format +msgid "Error: Option '%s' is unknown, try 'nmcli -help'." +msgstr "Fejl: Tilvalg '%s' er ukendt, prøv 'nmcli -help'." + +#: ../cli/src/nmcli.c:234 +#, c-format +msgid "Caught signal %d, shutting down..." +msgstr "Fik signal %d, afslutter..." + +#: ../cli/src/nmcli.c:259 +#, c-format +msgid "Error: Could not connect to NetworkManager." +msgstr "Fejl: Kunne ikke oprette forbinde til NetworkManager." + +#: ../cli/src/nmcli.c:275 +msgid "Success" +msgstr "Succes" + +#: ../cli/src/settings.c:411 +#, c-format +msgid "%d (hex-ascii-key)" +msgstr "%d (hex-ascii-nøgle)" + +#: ../cli/src/settings.c:413 +#, c-format +msgid "%d (104/128-bit passphrase)" +msgstr "%d (104/128-bit adgangsfrase)" + +#: ../cli/src/settings.c:416 +#, c-format +msgid "%d (unknown)" +msgstr "%d (ukendt)" + +#: ../cli/src/settings.c:442 +msgid "0 (unknown)" +msgstr "0 (ukendt)" + +#: ../cli/src/settings.c:448 +msgid "any, " +msgstr "enhver, " + +#: ../cli/src/settings.c:450 +msgid "900 MHz, " +msgstr "900 MHz, " + +#: ../cli/src/settings.c:452 +msgid "1800 MHz, " +msgstr "1800 MHz, " + +#: ../cli/src/settings.c:454 +msgid "1900 MHz, " +msgstr "1900 MHz, " + +#: ../cli/src/settings.c:456 +msgid "850 MHz, " +msgstr "850 MHz, " + +#: ../cli/src/settings.c:458 +msgid "WCDMA 3GPP UMTS 2100 MHz, " +msgstr "WCDMA 3GPP UMTS 2100 MHz, " + +#: ../cli/src/settings.c:460 +msgid "WCDMA 3GPP UMTS 1800 MHz, " +msgstr "WCDMA 3GPP UMTS 1800 MHz, " + +#: ../cli/src/settings.c:462 +msgid "WCDMA 3GPP UMTS 1700/2100 MHz, " +msgstr "WCDMA 3GPP UMTS 1700/2100 MHz, " + +#: ../cli/src/settings.c:464 +msgid "WCDMA 3GPP UMTS 800 MHz, " +msgstr "WCDMA 3GPP UMTS 800 MHz, " + +#: ../cli/src/settings.c:466 +msgid "WCDMA 3GPP UMTS 850 MHz, " +msgstr "WCDMA 3GPP UMTS 850 MHz, " + +#: ../cli/src/settings.c:468 +msgid "WCDMA 3GPP UMTS 900 MHz, " +msgstr "WCDMA 3GPP UMTS 900 MHz, " + +#: ../cli/src/settings.c:470 +msgid "WCDMA 3GPP UMTS 1700 MHz, " +msgstr "WCDMA 3GPP UMTS 1700 MHz, " + +#: ../cli/src/settings.c:554 +#: ../cli/src/settings.c:721 +msgid "auto" +msgstr "automatisk" + +#: ../cli/src/settings.c:716 +#: ../cli/src/settings.c:719 +#: ../cli/src/settings.c:720 +#: ../cli/src/utils.c:172 +msgid "not set" +msgstr "ikke sat" + +#: ../cli/src/utils.c:124 +#, c-format +msgid "field '%s' has to be alone" +msgstr "feltet '%s' skal stå alene" + +#: ../cli/src/utils.c:127 +#, c-format +msgid "invalid field '%s'" +msgstr "ugyldigt felt '%s'" + +#: ../cli/src/utils.c:146 +#, c-format +msgid "Option '--terse' requires specifying '--fields'" +msgstr "Tilvalg '--terse' kræver angivelse af '--fields'" + +#: ../cli/src/utils.c:150 +#, c-format +msgid "Option '--terse' requires specific '--fields' option values , not '%s'" +msgstr "Tilvalg '--terse' kræver specifikke tilvalgsværdier for '--fields', ikke '%s'" + +#: ../libnm-util/crypto.c:121 +#, c-format +msgid "PEM key file had no end tag '%s'." +msgstr "PEM-nøglefil havde intet slutmærke \"%s\"." + +#: ../libnm-util/crypto.c:131 +#, c-format +msgid "Doesn't look like a PEM private key file." +msgstr "Ligner ikke en privat PEM-nøglefil." + +#: ../libnm-util/crypto.c:139 +#, c-format +msgid "Not enough memory to store PEM file data." +msgstr "Ikke nok hukommelse til at lagre PEM-fildata." + +#: ../libnm-util/crypto.c:155 +#, c-format +msgid "Malformed PEM file: Proc-Type was not first tag." +msgstr "Fejlskrevet PEM-fil: Proc-Type var ikke første mærke." + +#: ../libnm-util/crypto.c:163 +#, c-format +msgid "Malformed PEM file: unknown Proc-Type tag '%s'." +msgstr "Fejlskrevet PEM-fil: Ukendt mærke \"%s\" for Proc-type." + +#: ../libnm-util/crypto.c:173 +#, c-format +msgid "Malformed PEM file: DEK-Info was not the second tag." +msgstr "Fejlskrevet PEM-fil: DEK-info var ikke andet mærke." + +#: ../libnm-util/crypto.c:184 +#, c-format +msgid "Malformed PEM file: no IV found in DEK-Info tag." +msgstr "Fejlskrevet PEM-fil: intet IV fundet i mærket DEK-Info." + +#: ../libnm-util/crypto.c:191 +#, c-format +msgid "Malformed PEM file: invalid format of IV in DEK-Info tag." +msgstr "Fejlskrevet PEM-fil: ugyldigt format af IV i mærket DEK-Info." + +#: ../libnm-util/crypto.c:204 +#, c-format +msgid "Malformed PEM file: unknown private key cipher '%s'." +msgstr "Fejlskrevet PEM-fil: ukendt privat nøgleciffer \"%s\"." + +#: ../libnm-util/crypto.c:223 +#, c-format +msgid "Could not decode private key." +msgstr "Kunne ikke afkode privat nøgle." + +#: ../libnm-util/crypto.c:268 +#, c-format +msgid "PEM certificate '%s' had no end tag '%s'." +msgstr "PEM-certifikatet \"%s\" har intet slutmærke \"%s\"." + +#: ../libnm-util/crypto.c:278 +#, c-format +msgid "Failed to decode certificate." +msgstr "Fejl ved afkodning af certifikat." + +#: ../libnm-util/crypto.c:287 +#, c-format +msgid "Not enough memory to store certificate data." +msgstr "Ikke nok hukommelse til at gemme certifikatdata." + +#: ../libnm-util/crypto.c:295 +#, c-format +msgid "Not enough memory to store file data." +msgstr "Ikke nok hukommelse til at gemme fildata." + +#: ../libnm-util/crypto.c:325 +#, c-format +msgid "IV must be an even number of bytes in length." +msgstr "IV skal have en længde på et lige antal byte." + +#: ../libnm-util/crypto.c:334 +#, c-format +msgid "Not enough memory to store the IV." +msgstr "Ikke nok hukommelse til at gemme IV'en." + +#: ../libnm-util/crypto.c:345 +#, c-format +msgid "IV contains non-hexadecimal digits." +msgstr "IV indeholder ikke-hexadecimale cifre." + +#: ../libnm-util/crypto.c:383 +#: ../libnm-util/crypto_gnutls.c:148 +#: ../libnm-util/crypto_gnutls.c:266 +#: ../libnm-util/crypto_nss.c:171 +#: ../libnm-util/crypto_nss.c:336 +#, c-format +msgid "Private key cipher '%s' was unknown." +msgstr "Privat nøgleciffer \"%s\" var ukendt." + +#: ../libnm-util/crypto.c:392 +#, c-format +msgid "Not enough memory to decrypt private key." +msgstr "Ikke nok hukommelse til at dekryptere privat nøgle." + +#: ../libnm-util/crypto.c:512 +#, c-format +msgid "Unable to determine private key type." +msgstr "Kunne ikke afgøre typen af privat nøgle." -#~ msgid "NetworkManager Applet" -#~ msgstr "NetworkManager-panelprogram" +#: ../libnm-util/crypto.c:531 +#, c-format +msgid "Not enough memory to store decrypted private key." +msgstr "Ikke nok hukommelse til at gemme dekrypteret privat nøgle." -#~ msgid "Copyright © 2004-2005 Red Hat, Inc." -#~ msgstr "Copyright © 2004-2005 Red Hat, Inc." +#: ../libnm-util/crypto_gnutls.c:49 +msgid "Failed to initialize the crypto engine." +msgstr "Kunne ikke initialisere kryptomotor." -#~ msgid "" -#~ "Notification area applet for managing your network devices and " -#~ "connections." -#~ msgstr "" -#~ "Statusfelt-panelprogram til håndtering af dine netværks-enheder og -" -#~ "forbindelser." +#: ../libnm-util/crypto_gnutls.c:93 +#, c-format +msgid "Failed to initialize the MD5 engine: %s / %s." +msgstr "Kunne ikke initialisere MD5-motor: %s / %s." -#~ msgid "translator-credits" -#~ msgstr "" -#~ "David Nielsen\n" -#~ "Martin Willemoes Hansen\n" -#~ "Lasse Bang Mikkelsen\n" -#~ "\n" -#~ "Dansk-gruppen <dansk@dansk-gruppen.dk>\n" -#~ "Mere info: http://www.dansk-gruppen.dk" +#: ../libnm-util/crypto_gnutls.c:156 +#, c-format +msgid "Invalid IV length (must be at least %zd)." +msgstr "Ugyldig IV-længde (skal være mindst %zd)." -#~ msgid "VPN Error" -#~ msgstr "VPN fejl" +#: ../libnm-util/crypto_gnutls.c:165 +#: ../libnm-util/crypto_nss.c:188 +#, c-format +msgid "Not enough memory for decrypted key buffer." +msgstr "Ikke nok hukommelse til afkodet nøglebuffer." -#~ msgid "VPN Login Failure" -#~ msgstr "VPN logind-fejl" +#: ../libnm-util/crypto_gnutls.c:173 +#, c-format +msgid "Failed to initialize the decryption cipher context: %s / %s." +msgstr "Kunne ikke initialisere cifferkontekst til dekryptering: %s / %s." -#~ msgid "Could not start the VPN connection '%s' due to a login failure." -#~ msgstr "" -#~ "Kunne ikke etablere VPN-forbindelsen '%s' pågrund af en logind-fejl." +#: ../libnm-util/crypto_gnutls.c:182 +#, c-format +msgid "Failed to set symmetric key for decryption: %s / %s." +msgstr "Kunne ikke sætte symmetrisk nøgle til dekryptering: %s / %s." -#~ msgid "VPN Start Failure" -#~ msgstr "VPN etablerings-fejl" +#: ../libnm-util/crypto_gnutls.c:191 +#, c-format +msgid "Failed to set IV for decryption: %s / %s." +msgstr "Kunne ikke sætte IV til dekryptering: %s / %s." -#~ msgid "" -#~ "Could not start the VPN connection '%s' due to a failure launching the " -#~ "VPN program." -#~ msgstr "" -#~ "Kunne ikke etablere VPN-forbindelsen '%s' pågrund af fejl ved start af " -#~ "VPN-program." +#: ../libnm-util/crypto_gnutls.c:200 +#, c-format +msgid "Failed to decrypt the private key: %s / %s." +msgstr "Kunne ikke dekryptere den private nøgle: %s / %s." -#~ msgid "VPN Connect Failure" -#~ msgstr "VPN tilslutnings-fejl" +#: ../libnm-util/crypto_gnutls.c:210 +#: ../libnm-util/crypto_nss.c:267 +#, c-format +msgid "Failed to decrypt the private key: unexpected padding length." +msgstr "Kunne ikke dekryptere den private nøgle: uventet længde af fylddata." -#~ msgid "Could not start the VPN connection '%s' due to a connection error." -#~ msgstr "" -#~ "Kunne ikke etablere VPN-forbindelsen '%s' pågrund af en forbindelses-fejl." +#: ../libnm-util/crypto_gnutls.c:221 +#: ../libnm-util/crypto_nss.c:278 +#, c-format +msgid "Failed to decrypt the private key." +msgstr "Kunne ikke dekryptere den private nøgle." -#~ msgid "VPN Configuration Error" -#~ msgstr "VPN konfigurations-fejl" +#: ../libnm-util/crypto_gnutls.c:286 +#: ../libnm-util/crypto_nss.c:356 +#, c-format +msgid "Could not allocate memory for encrypting." +msgstr "Kunne ikke allokere hukommelse til kryptering." -#~ msgid "The VPN connection '%s' was not correctly configured." -#~ msgstr "VPN-forbindelsen '%s' er ikke konfigureret korrekt." +#: ../libnm-util/crypto_gnutls.c:294 +#, c-format +msgid "Failed to initialize the encryption cipher context: %s / %s." +msgstr "Kunne ikke initialisere krypteringscifferkontekst: %s / %s." -#~ msgid "" -#~ "Could not start the VPN connection '%s' because the VPN server did not " -#~ "return an adequate network configuration." -#~ msgstr "" -#~ "Kunne ikke etablere VPN-forbindelsen '%s' fordi VPN-serveren ikke " -#~ "returnerede en passende netværks-konfiguration." +#: ../libnm-util/crypto_gnutls.c:303 +#, c-format +msgid "Failed to set symmetric key for encryption: %s / %s." +msgstr "Kunne ikke sætte symmetrisk nøgle til kryptering: %s / %s." -#~ msgid "The VPN service said: \"%s\"" -#~ msgstr "VPN-tjenesten sagde: \"%s\"" +#: ../libnm-util/crypto_gnutls.c:313 +#, c-format +msgid "Failed to set IV for encryption: %s / %s." +msgstr "Kunne ikke sætte IV til kryptering: %s / %s." -#~ msgid "VPN connection '%s' said:" -#~ msgstr "VPN-forbindelsen '%s' sagde:" +#: ../libnm-util/crypto_gnutls.c:322 +#, c-format +msgid "Failed to encrypt the data: %s / %s." +msgstr "Kunne ikke kryptere data: %s / %s." -#~ msgid "VPN Login Message" -#~ msgstr "VPN logind-meddelelse" +#: ../libnm-util/crypto_gnutls.c:362 +#, c-format +msgid "Error initializing certificate data: %s" +msgstr "Fejl under initialisering af certifikatdata: %s" -#~ msgid "" -#~ "The NetworkManager Applet could not find some required resources (the " -#~ "glade file was not found)." -#~ msgstr "" -#~ "NetworkManager panelprogrammet kunne ikke finde nogle krævede ressourcer " -#~ "(glade-filen blev ikke fundet)." +#: ../libnm-util/crypto_gnutls.c:384 +#, c-format +msgid "Couldn't decode certificate: %s" +msgstr "Kunne ikke afkode certifikat: %s" -#~ msgid "The network device \"%s (%s)\" does not support wireless scanning." -#~ msgstr "Netværks-enheden \"%s (%s)\" understøtter ikke trådløs scanning." +#: ../libnm-util/crypto_gnutls.c:408 +#, c-format +msgid "Couldn't initialize PKCS#12 decoder: %s" +msgstr "Kunne ikke initialisere PKCS#12-afkoder: %s" -#~ msgid "The network device \"%s (%s)\" does not support link detection." -#~ msgstr "Netværks-enheden \"%s (%s)\" understøtter ikke link-detektering." +#: ../libnm-util/crypto_gnutls.c:421 +#, c-format +msgid "Couldn't decode PKCS#12 file: %s" +msgstr "Kunne ikke afkode PKCS#12-fil: %s" -#~ msgid "Preparing device %s for the wired network..." -#~ msgstr "Klargører enheden %s til det kablede netværk..." +#: ../libnm-util/crypto_gnutls.c:433 +#, c-format +msgid "Couldn't verify PKCS#12 file: %s" +msgstr "Kunne ikke bekræfte PKCS#12-fil: %s" -#~ msgid "Preparing device %s for the wireless network '%s'..." -#~ msgstr "Klargører enheden %s til det trådløse netværk '%s'..." +#: ../libnm-util/crypto_nss.c:56 +#, c-format +msgid "Failed to initialize the crypto engine: %d." +msgstr "Kunne ikke initialisere kryptomotor: %d." -#~ msgid "Configuring device %s for the wired network..." -#~ msgstr "Konfigurerer enheden %s til det kablede netværk..." +#: ../libnm-util/crypto_nss.c:111 +#, c-format +msgid "Failed to initialize the MD5 context: %d." +msgstr "Kunne ikke initialisere MD5-kontekst: %d." -#~ msgid "Attempting to join the wireless network '%s'..." -#~ msgstr "Forsøger at tilslutte til det trådløse netværk '%s'..." +#: ../libnm-util/crypto_nss.c:179 +#, c-format +msgid "Invalid IV length (must be at least %d)." +msgstr "Ugyldig IV-længde (skal være mindst %d)." -#~ msgid "Waiting for Network Key for the wireless network '%s'..." -#~ msgstr "Venter på netværksnøglen til det trådløse netværk '%s'..." +#: ../libnm-util/crypto_nss.c:196 +#, c-format +msgid "Failed to initialize the decryption cipher slot." +msgstr "Kunne ikke initialisere cifferplads til dekryptering." -#~ msgid "Requesting a network address from the wired network..." -#~ msgstr "Forespørger en netværks-adresse fra det kablede netværk..." +#: ../libnm-util/crypto_nss.c:206 +#, c-format +msgid "Failed to set symmetric key for decryption." +msgstr "Kunne ikke sætte symmetrisk nøgle til kryptering." -#~ msgid "Requesting a network address from the wireless network '%s'..." -#~ msgstr "Forespørger en netværks-adresse fra det trådløse netværk '%s'..." +#: ../libnm-util/crypto_nss.c:216 +#, c-format +msgid "Failed to set IV for decryption." +msgstr "Kunne ikke sætte IV til dekryptering." -#~ msgid "Finishing connection to the wired network..." -#~ msgstr "Færdiggører tilslutning til det kablede netværk..." +#: ../libnm-util/crypto_nss.c:224 +#, c-format +msgid "Failed to initialize the decryption context." +msgstr "Kunne ikke initialisere dekrypteringskonteksten." -#~ msgid "Finishing connection to the wireless network '%s'..." -#~ msgstr "Færdiggører tilslutning til det trådløse netværk '%s'..." +#: ../libnm-util/crypto_nss.c:237 +#, c-format +msgid "Failed to decrypt the private key: %d." +msgstr "Kunne ikke dekryptere den private nøgle: %d." -#~ msgid "NetworkManager is not running" -#~ msgstr "NetworkManager kører ikke" +#: ../libnm-util/crypto_nss.c:245 +#, c-format +msgid "Failed to decrypt the private key: decrypted data too large." +msgstr "Kunne ikke dekryptere den private nøgle: for stor mængde dekrypteret data." -#~ msgid "Networking disabled" -#~ msgstr "Netværks-understøttelse deaktiveret" +#: ../libnm-util/crypto_nss.c:256 +#, c-format +msgid "Failed to finalize decryption of the private key: %d." +msgstr "Kunne ikke afslutte dekryptering af den private nøgle: %d." -#~ msgid "No network connection" -#~ msgstr "Ingen netværks-forbindelse" +#: ../libnm-util/crypto_nss.c:364 +#, c-format +msgid "Failed to initialize the encryption cipher slot." +msgstr "Kunne ikke initialisere cifferplads til kryptering." -#~ msgid "Wired network connection" -#~ msgstr "Kablet netværks-forbindelse" +#: ../libnm-util/crypto_nss.c:372 +#, c-format +msgid "Failed to set symmetric key for encryption." +msgstr "Kunne ikke sætte symmetrisk nøgle til kryptering." -#~ msgid "Connected to an Ad-Hoc wireless network" -#~ msgstr "Tilsluttet til et trådløst ad hoc netværk" +#: ../libnm-util/crypto_nss.c:380 +#, c-format +msgid "Failed to set IV for encryption." +msgstr "Kunne ikke sætte IV til kryptering." -#~ msgid "Wireless network connection to '%s' (%d%%)" -#~ msgstr "Trådløs netværks-forbindelse til '%s' (%d%%)" +#: ../libnm-util/crypto_nss.c:388 +#, c-format +msgid "Failed to initialize the encryption context." +msgstr "Kunne ikke initialisere krypteringskontekst." -#~ msgid "VPN connection to '%s'" -#~ msgstr "VPN-forbindelse til '%s'" +#: ../libnm-util/crypto_nss.c:396 +#, c-format +msgid "Failed to encrypt: %d." +msgstr "Kunne ikke kryptere: %d." -#~ msgid "VPN connecting to '%s'" -#~ msgstr "VPN tilslutter til '%s'" +#: ../libnm-util/crypto_nss.c:404 +#, c-format +msgid "Unexpected amount of data after encrypting." +msgstr "Uventet mængde af data efter kryptering." -#~ msgid "_Connect to Other Wireless Network..." -#~ msgstr "_Tilslut til andet trådløst netværk..." +#: ../libnm-util/crypto_nss.c:447 +#, c-format +msgid "Couldn't decode certificate: %d" +msgstr "Kunne ikke afkode certifikat: %d" -#~ msgid "Create _New Wireless Network..." -#~ msgstr "Opret _nyt trådløst netværk..." +#: ../libnm-util/crypto_nss.c:482 +#, c-format +msgid "Couldn't convert password to UCS2: %d" +msgstr "Kunne ikke konvertere adgangskode til UCS2: %d" -#~ msgid "_VPN Connections" -#~ msgstr "_VPN-forbindelser" +#: ../libnm-util/crypto_nss.c:510 +#, c-format +msgid "Couldn't initialize PKCS#12 decoder: %d" +msgstr "Kunne ikke initialisere PKCS#12-afkoder: %d" -#~ msgid "_Configure VPN..." -#~ msgstr "_Konfigurér VPN..." +#: ../libnm-util/crypto_nss.c:519 +#, c-format +msgid "Couldn't decode PKCS#12 file: %d" +msgstr "Kunne ikke afkode PKCS#12-fil: %d" -#~ msgid "_Disconnect VPN..." -#~ msgstr "_Afbryd VPN..." +#: ../libnm-util/crypto_nss.c:528 +#, c-format +msgid "Couldn't verify PKCS#12 file: %d" +msgstr "Kunne ikke verificere PKCS#12-fil: %d" -#~ msgid "_Dial Up Connections" -#~ msgstr "_Opkalds-forbindelser" +#: ../libnm-util/crypto_nss.c:557 +msgid "Could not generate random data." +msgstr "Kunne ikke generere tilfældige data." -#~ msgid "Connect to %s..." -#~ msgstr "Tilslut til %s..." +#: ../libnm-util/nm-utils.c:1975 +#, c-format +msgid "Not enough memory to make encryption key." +msgstr "Ikke nok hukommelse til at oprette krypteringsnøgle." -#~ msgid "Disconnect from %s..." -#~ msgstr "Afbryd fra %s..." +#: ../libnm-util/nm-utils.c:2085 +msgid "Could not allocate memory for PEM file creation." +msgstr "Kunne ikke allokere hukommelse til PEM-filoprettelse." -#~ msgid "No network devices have been found" -#~ msgstr "Ingen netværks-enheder blev fundet" +#: ../libnm-util/nm-utils.c:2097 +#, c-format +msgid "Could not allocate memory for writing IV to PEM file." +msgstr "Kunne ikke allokere hukommelse til at skrive IV til PEM-fil." -#~ msgid "NetworkManager is not running..." -#~ msgstr "NetworkManager kører ikke..." +#: ../libnm-util/nm-utils.c:2109 +#, c-format +msgid "Could not allocate memory for writing encrypted key to PEM file." +msgstr "Kunne ikke allokere hukommelse til at skrive krypteret nøgle til PEM-fil." -#~ msgid "Enable _Networking" -#~ msgstr "Aktivér _netværks-understøttelse" +#: ../libnm-util/nm-utils.c:2128 +#, c-format +msgid "Could not allocate memory for PEM file data." +msgstr "Kunne ikke allokere hukommelse til PEM-fildata." -#~ msgid "Enable _Wireless" -#~ msgstr "Aktivér _trådløst netværk" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:1 +msgid "Connection sharing via a protected WiFi network" +msgstr "Deling af forbindelse via et beskyttet WiFi-netværk" -#~ msgid "Connection _Information" -#~ msgstr "Forbindelses-_information" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:2 +msgid "Connection sharing via an open WiFi network" +msgstr "Deling af forbindelse via et åbent WiFi-netværk" -#~ msgid "_Help" -#~ msgstr "_Hjælp" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:3 +msgid "Modify persistent system hostname" +msgstr "Ændr fast systemværtsnavn" -#~ msgid "_About" -#~ msgstr "_Om" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:4 +msgid "Modify system connections" +msgstr "Ændr systemforbindelser" -#~ msgid "" -#~ "The NetworkManager applet could not find some required resources. It " -#~ "cannot continue.\n" -#~ msgstr "" -#~ "NetworkManager panelprogrammet kunne ikke finde nogle krævede ressourcer " -#~ "- kan ikke fortsætte.\n" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:5 +msgid "System policy prevents modification of system settings" +msgstr "Systempolitikken forhindrer modifikation af systemindstillinger" -#~ msgid "Open System" -#~ msgstr "Åbent system" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:6 +msgid "System policy prevents modification of the persistent system hostname" +msgstr "Systempolitikken forhindrer ændring af det faste systemværtsnavn" -#~ msgid "Shared Key" -#~ msgstr "Delt nøgle" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:7 +msgid "System policy prevents sharing connections via a protected WiFi network" +msgstr "Systempolitikken forhindrer deling af forbindelser via et beskyttet WiFi-netværk" -#~ msgid "TKIP (Default)" -#~ msgstr "TKIP (forvalgt)" +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:8 +msgid "System policy prevents sharing connections via an open WiFi network" +msgstr "Systempolitikken forhindrer deling af forbindelser via et åbent WiFi-netværk" -#~ msgid "AES-CCMP" -#~ msgstr "AES-CCMP" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:1 +msgid "Allow control of network connections" +msgstr "Tillad kontrol af netværksforbindelser" -#~ msgid "None" -#~ msgstr "Ingen" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:2 +msgid "Allow use of user-specific connections" +msgstr "Tillad brug af brugerspecifikke forbindelser" -#~ msgid "WEP 40/128-bit ASCII" -#~ msgstr "WEP 40/128-bit ASCII" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:3 +msgid "Enable or disable WiFi devices" +msgstr "Aktiver eller deaktiver WiFi-enheder" -#~ msgid "WEP 40/128-bit hex" -#~ msgstr "WEP 40/128-bit hex" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:4 +msgid "Enable or disable mobile broadband devices" +msgstr "Aktiver eller deaktiver mobile bredbåndsenheder" -#~ msgid "WEP Passphrase" -#~ msgstr "WEP-adgangskode:" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:5 +msgid "Enable or disable system networking" +msgstr "Aktiver eller deaktiver systemnetværk" -#~ msgid "Orientation" -#~ msgstr "Retning" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:6 +msgid "Put NetworkManager to sleep or wake it up (should only be used by system power management)" +msgstr "Sæt NetworkManager i hvile eller væk den (bør kun bruges af systemstrømstyringen)" -#~ msgid "The orientation of the tray." -#~ msgstr "Retningen på statusikonet." +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:7 +msgid "System policy prevents control of network connections" +msgstr "Systempolitik forhindrer kontrol af netværksforbindelser" -#~ msgid "Wired Network (%s)" -#~ msgstr "Kablet netværk (%s)" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:8 +msgid "System policy prevents enabling or disabling WiFi devices" +msgstr "Systempolitik forhindrer aktivering eller deaktivering af WiFi-enheder" -#~ msgid "_Wired Network" -#~ msgstr "_Kablet netværk" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:9 +msgid "System policy prevents enabling or disabling mobile broadband devices" +msgstr "Systempolitik forhindrer aktivering eller deaktivering af mobile bredbåndsenheder" -#~ msgid "Wireless Network (%s)" -#~ msgid_plural "Wireless Networks (%s)" -#~ msgstr[0] "Trådløst netværk (%s)" -#~ msgstr[1] "Trådløse netværk (%s)" - -#~ msgid "Wireless Network" -#~ msgid_plural "Wireless Networks" -#~ msgstr[0] "Trådløst netværk" -#~ msgstr[1] "Trådløse netværk" - -#~ msgid " (invalid Unicode)" -#~ msgstr " (ugyldig Unicode)" - -#~ msgid "" -#~ "By default, the wireless network's name is set to your computer's name, %" -#~ "s, with no encryption enabled" -#~ msgstr "" -#~ "Som standard navngives det trådløse netværk til din maskines navn, %s, " -#~ "uden nogen kryptering slået til" - -#~ msgid "Create new wireless network" -#~ msgstr "Opret nyt trådløst netværk" - -#~ msgid "" -#~ "Enter the name and security settings of the wireless network you wish to " -#~ "create." -#~ msgstr "" -#~ "Indtast navn- og sikkerhedsopsætning på det trådløse netværk du ønsker at " -#~ "oprette." - -#~ msgid "Create New Wireless Network" -#~ msgstr "Opret nyt trådløst netværk" - -#~ msgid "Existing wireless network" -#~ msgstr "Eksisterende trådløst netværk" - -#~ msgid "Enter the name of the wireless network to which you wish to connect." -#~ msgstr "Indtast navnet på det trådløse netværk du ønsker at tilslutte dig." - -#~ msgid "Connect to Other Wireless Network" -#~ msgstr "Tilslut til andet trådløst netværk" - -#~ msgid "Cannot start VPN connection '%s'" -#~ msgstr "Kan ikke etablere VPN-forbindelsen '%s'" - -#~ msgid "" -#~ "Could not find the authentication dialog for VPN connection type '%s'. " -#~ "Contact your system administrator." -#~ msgstr "" -#~ "Kunne ikke finde godkendelses-vinduet til VPN-forbindelsestypen '%s'. " -#~ "Kontakt din system-administrator." - -#~ msgid "" -#~ "There was a problem launching the authentication dialog for VPN " -#~ "connection type '%s'. Contact your system administrator." -#~ msgstr "" -#~ "Der opstod en fejl ved start af godkendelses-vinduet til VPN-" -#~ "forbindelsestypen '%s'. Kontakt din system-administrator." - -#~ msgid " " -#~ msgstr " " - -#~ msgid "" -#~ "<span weight=\"bold\" size=\"larger\">Active Connection Information</span>" -#~ msgstr "" -#~ "<span weight=\"bold\" size=\"larger\">Information om aktiv forbindelse</" -#~ "span>" - -#~ msgid "" -#~ "<span weight=\"bold\" size=\"larger\">Passphrase Required by Wireless " -#~ "Network</span>\n" -#~ "\n" -#~ "A passphrase or encryption key is required to access the wireless network " -#~ "'%s'." -#~ msgstr "" -#~ "<span weight=\"bold\" size=\"larger\">Adgangskode påkrævet af trådløst " -#~ "netværk</span>\n" -#~ "\n" -#~ "En adgangskode eller krypteringsnøgle er påkrævet, for at opnå adgang til " -#~ "det trådløse netværk '%s'." - -#~ msgid "" -#~ "<span weight=\"bold\" size=\"larger\">Reduced Network Functionality</" -#~ "span>\n" -#~ "\n" -#~ "%s It will not be completely functional." -#~ msgstr "" -#~ "<span weight=\"bold\" size=\"larger\">Reduceret netværks-funktionalitet</" -#~ "span>\n" -#~ "\n" -#~ "%s Den vil ikke være fuldstændig funktionsdygtig." - -#~ msgid "" -#~ "<span weight=\"bold\" size=\"larger\">Wireless Network Login " -#~ "Confirmation</span>\n" -#~ "\n" -#~ "You have chosen to log in to the wireless network '%s'. If you are sure " -#~ "that this wireless network is secure, click the checkbox below and " -#~ "NetworkManager will not require confirmation on subsequent log ins." -#~ msgstr "" -#~ "<span weight=\"bold\" size=\"larger\">Bekræftelse af logind på trådløst " -#~ "netværk</span>\n" -#~ "\n" -#~ "Du har valgt at logge på det trådløse netværk '%s'. Hvis du er sikker på " -#~ "at dette trådløse netværk er sikkert, afkryds nedenstående " -#~ "afkrydsningsfelt og NetworkManager vil ikke spørge i fremtiden." - -#~ msgid "Authentication:" -#~ msgstr "Godkendelse:" - -#~ msgid "Broadcast Address:" -#~ msgstr "Rundsendings-adresse:" - -#~ msgid "C_onnect" -#~ msgstr "T_ilslut" - -#~ msgid "Connection Information" -#~ msgstr "Forbindelses-information" - -#~ msgid "Default Route:" -#~ msgstr "Standard rute:" - -#~ msgid "Destination Address:" -#~ msgstr "Destinations-adresse:" - -#~ msgid "Hardware Address:" -#~ msgstr "Hardware-adresse:" - -#~ msgid "IP Address:" -#~ msgstr "IP-adresse:" - -#~ msgid "Interface:" -#~ msgstr "Enhed:" - -#~ msgid "Key:" -#~ msgstr "Nøgle:" - -#~ msgid "" -#~ "None\n" -#~ "WEP Passphrase\n" -#~ "WEP 40/128-bit hex\n" -#~ "WEP 40/128-bit ASCII\n" -#~ msgstr "" -#~ "Ingen\n" -#~ "WEP-adgangskode\n" -#~ "WEP 40/128-bit hex\n" -#~ "WEP 40/128-bit ASCII\n" - -#~ msgid "" -#~ "Open System\n" -#~ "Shared Key" -#~ msgstr "" -#~ "Åbent system\n" -#~ "Delt nøgle" - -#~ msgid "Other Wireless Network..." -#~ msgstr "Andet trådløst netværk..." - -#~ msgid "Passphrase:" -#~ msgstr "Adgangskode:" - -#~ msgid "Password:" -#~ msgstr "Adgangskode:" - -#~ msgid "Primary DNS:" -#~ msgstr "Primær DNS:" - -#~ msgid "Secondary DNS:" -#~ msgstr "Sekundær DNS:" - -#~ msgid "Subnet Mask:" -#~ msgstr "Undernet-maske:" - -#~ msgid "Type:" -#~ msgstr "Type:" - -#~ msgid "User Name:" -#~ msgstr "Brugernavn:" - -#~ msgid "Wireless Network Key Required" -#~ msgstr "Nøgle til trådløst netværk påkrævet" - -#~ msgid "Wireless _adapter:" -#~ msgstr "Trådløs _adapter:" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:10 +msgid "System policy prevents enabling or disabling system networking" +msgstr "Systempolitik forhindrer aktivering eller deaktivering af systemnetværk" -#~ msgid "_Always Trust this Wireless Network" -#~ msgstr "_Stol altid på dette trådløse netværk" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:11 +msgid "System policy prevents putting NetworkManager to sleep or waking it up" +msgstr "Systempolitik forhindrer at sætte NetworkManager i hvile eller at vække den" -#~ msgid "_Don't remind me again" -#~ msgstr "_Påmind mig ikke igen" +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:12 +msgid "System policy prevents use of user-specific connections" +msgstr "Systempolitik forhindrer brug af brugerspecifikke forbindelser" -#~ msgid "_Login to Network" -#~ msgstr "_Log på netværk" +#: ../src/nm-netlink-monitor.c:100 +#: ../src/nm-netlink-monitor.c:231 +#: ../src/nm-netlink-monitor.c:653 +#, c-format +msgid "error processing netlink message: %s" +msgstr "fejl under behandling af netlink-besked: %s" -#~ msgid "_Network Name:" -#~ msgstr "_Netværksnavn:" +#: ../src/nm-netlink-monitor.c:214 +msgid "error occurred while waiting for data on socket" +msgstr "der opstod en fejl mens der blev ventet på data på soklen" -#~ msgid "_Wireless Security:" -#~ msgstr "Trådløs sikkerhed:" +#: ../src/nm-netlink-monitor.c:254 +#, c-format +msgid "unable to connect to netlink for monitoring link status: %s" +msgstr "kan ikke forbinde til netlink for at overvåge forbindelsesstatus: %s" -#~ msgid "leap_subwindow" -#~ msgstr "leap_subwindow" +#: ../src/nm-netlink-monitor.c:265 +#, c-format +msgid "unable to enable netlink handle credential passing: %s" +msgstr "kan ikke aktivere videregivelse af akkreditiver for netlink-håndtag: %s" -#~ msgid "wep_key_subwindow" -#~ msgstr "wep_key_subwindow" +#: ../src/nm-netlink-monitor.c:291 +#: ../src/nm-netlink-monitor.c:353 +#, c-format +msgid "unable to allocate netlink handle for monitoring link status: %s" +msgstr "kan ikke allokere netlink-håndtag til overvågning af forbindelsesstatus: %s" -#~ msgid "wep_passphrase_subwindow" -#~ msgstr "wep_passphrase_subwindow" +#: ../src/nm-netlink-monitor.c:376 +#, c-format +msgid "unable to allocate netlink link cache for monitoring link status: %s" +msgstr "kan ikke allokere netlink-forbindelsesmellemlager til overvågning af forbindelsesstatus: %s" -#~ msgid "wpa_psk_subwindow" -#~ msgstr "wpa_psk_subwindow" +#: ../src/nm-netlink-monitor.c:502 +#, c-format +msgid "unable to join netlink group: %s" +msgstr "kan ikke gå ind i netlink-gruppen: %s" -#~ msgid "WPA2 Personal" -#~ msgstr "Personlig WPA2" +#: ../src/nm-netlink-monitor.c:629 +#: ../src/nm-netlink-monitor.c:642 +#, c-format +msgid "error updating link cache: %s" +msgstr "fejl ved opdatering af forbindelsesmellemlager: %s" -#~ msgid "WPA Personal" -#~ msgstr "Personlig WPA" +#: ../src/main.c:506 +#, c-format +msgid "Invalid option. Please use --help to see a list of valid options.\n" +msgstr "Ugyldigt tilvalg. Brug venligst --help for at se en liste af gyldige tilvalg.\n" -#~ msgid "Choose which type of VPN connection you wish to create." -#~ msgstr "Vælg hvilken type VPN-forbindelse du ønsker at oprette." +#: ../src/main.c:577 +#, c-format +msgid "%s. Please use --help to see a list of valid options.\n" +msgstr "%s. Brug venligst --help for at få en liste af gyldige tilvalg.\n" -#~ msgid "Connect to:" -#~ msgstr "Tilslut til:" +#: ../src/dhcp-manager/nm-dhcp-dhclient.c:328 +msgid "# Created by NetworkManager\n" +msgstr "# Oprettet af NetworkManager\n" -#~ msgid "Create VPN Connection - 1 of 2" -#~ msgstr "Opret VPN-forbindelse - 1 af 2" +#: ../src/dhcp-manager/nm-dhcp-dhclient.c:344 +#, c-format +msgid "" +"# Merged from %s\n" +"\n" +msgstr "" +"# Sammenflettet fra %s\n" +"\n" -#~ msgid "Create VPN Connection - 2 of 2" -#~ msgstr "Opret VPN-forbindelse - 2 af 2" +#: ../src/dhcp-manager/nm-dhcp-manager.c:284 +msgid "no usable DHCP client could be found." +msgstr "kunne ikke finde en brugbar DHCP-klient." + +#: ../src/dhcp-manager/nm-dhcp-manager.c:293 +msgid "'dhclient' could be found." +msgstr "'dhclient' blev fundet." + +#: ../src/dhcp-manager/nm-dhcp-manager.c:303 +msgid "'dhcpcd' could be found." +msgstr "'dhcpcd' blev fundet." + +#: ../src/dhcp-manager/nm-dhcp-manager.c:311 +#, c-format +msgid "unsupported DHCP client '%s'" +msgstr "ikke-understøttet DHCP-klient '%s'" + +#: ../src/logging/nm-logging.c:146 +#, c-format +msgid "Unknown log level '%s'" +msgstr "Ukendt logningsniveau '%s'" + +#: ../src/logging/nm-logging.c:171 +#, c-format +msgid "Unknown log domain '%s'" +msgstr "Ukendt logningsdomæne '%s'" + +#: ../src/dns-manager/nm-dns-manager.c:367 +msgid "NOTE: the libc resolver may not support more than 3 nameservers." +msgstr "BEMÆRK: libc-opløseren understøtter måske ikke mere end tre navneservere." + +#: ../src/dns-manager/nm-dns-manager.c:369 +msgid "The nameservers listed below may not be recognized." +msgstr "Navneserverne vist nedenfor vil måske ikke blive genkendt." + +#: ../src/system-settings/nm-default-wired-connection.c:157 +#, c-format +msgid "Auto %s" +msgstr "Auto %s" -#~ msgid "Finish Creating VPN Connection" -#~ msgstr "Færdiggør oprettelse af VPN-forbindelse" +#: ../system-settings/plugins/ifcfg-rh/reader.c:3408 +#: ../system-settings/plugins/ifnet/connection_parser.c:49 +msgid "System" +msgstr "System" -#~ msgid "" -#~ "This assistant will guide you through the creation of a connection to a " -#~ "Virtual Private Network (VPN).\n" -#~ "\n" -#~ "It will require some information, such as IP addresses and secrets. " -#~ "Please see your system administrator to obtain this information." -#~ msgstr "" -#~ "Denne vil guide dig gennem oprettelsen af en forbindelse til et virtuelt " -#~ "privat netværk (VPN).\n" -#~ "\n" -#~ "Denne guide vil kræve nogle informationer, såsom IP-adresser og " -#~ "adgangskode. Henvend dig venligst til din system-administrator for at få " -#~ "disse informationer." diff --git a/po/eo.po b/po/eo.po new file mode 100644 index 0000000000..c099b86cd0 --- /dev/null +++ b/po/eo.po @@ -0,0 +1,1766 @@ +# Esperanto translation for NetworkManager +# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 +# This file is distributed under the same license as the network-manager package. +# +# Patrick (Petriko) OUDEJANS < >, 2010. +# Aisano < >, 2010. +# Kim RIBEIRO < >, 2010. +# Serge LEBLANC < >, 2010. +# Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: network-manager\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=NetworkManager&component=general\n" +"POT-Creation-Date: 2010-12-10 15:25+0000\n" +"PO-Revision-Date: 2010-12-11 10:32+0100\n" +"Last-Translator: Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>\n" +"Language-Team: Esperanto <ubuntu-l10n-eo@lists.launchpad.net>\n" +"Language: eo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"X-Launchpad-Export-Date: 2010-12-10 16:56+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: ../cli/src/connections.c:60 ../cli/src/connections.c:76 +#: ../cli/src/devices.c:89 ../cli/src/devices.c:102 ../cli/src/devices.c:112 +#: ../cli/src/devices.c:122 ../cli/src/devices.c:135 ../cli/src/devices.c:146 +#: ../cli/src/devices.c:157 ../cli/src/devices.c:166 ../cli/src/devices.c:175 +msgid "NAME" +msgstr "NOMO" + +#. 0 +#: ../cli/src/connections.c:61 ../cli/src/connections.c:77 +msgid "UUID" +msgstr "UUID" + +#. 1 +#: ../cli/src/connections.c:62 +msgid "DEVICES" +msgstr "APARATOJ" + +#. 2 +#: ../cli/src/connections.c:63 ../cli/src/connections.c:79 +msgid "SCOPE" +msgstr "AMPLEKSO" + +#. 3 +#: ../cli/src/connections.c:64 +msgid "DEFAULT" +msgstr "DEFAŬLTA" + +#. 4 +#: ../cli/src/connections.c:65 +msgid "DBUS-SERVICE" +msgstr "DBUS-SERVO" + +#. 5 +#: ../cli/src/connections.c:66 +msgid "SPEC-OBJECT" +msgstr "SPEC-OBJEKTO" + +#. 6 +#: ../cli/src/connections.c:67 +msgid "VPN" +msgstr "VPN" + +#. 7 +#. 2 +#: ../cli/src/connections.c:68 ../cli/src/connections.c:84 +#: ../cli/src/devices.c:64 +msgid "DBUS-PATH" +msgstr "DBUS-VOJO" + +#. 1 +#. 0 +#. 1 +#: ../cli/src/connections.c:78 ../cli/src/devices.c:62 ../cli/src/devices.c:91 +msgid "TYPE" +msgstr "SPECO" + +#. 3 +#: ../cli/src/connections.c:80 +msgid "TIMESTAMP" +msgstr "TEMPINDIKO" + +#. 4 +#: ../cli/src/connections.c:81 +msgid "TIMESTAMP-REAL" +msgstr "REALA-TEMPINDIKO" + +#. 5 +#: ../cli/src/connections.c:82 +msgid "AUTOCONNECT" +msgstr "AŬTOMATA-KONEKTO" + +#. 6 +#: ../cli/src/connections.c:83 +msgid "READONLY" +msgstr "NUR-LEGI" + +#: ../cli/src/connections.c:160 +#, c-format +msgid "" +"Usage: nmcli con { COMMAND | help }\n" +" COMMAND := { list | status | up | down }\n" +"\n" +" list [id <id> | uuid <id> | system | user]\n" +" status\n" +" up id <id> | uuid <id> [iface <iface>] [ap <hwaddr>] [--nowait] [--timeout " +"<timeout>]\n" +" down id <id> | uuid <id>\n" +msgstr "" +"Uzo: nmcli con { KOMANDO | help }\n" +" KOMANDO := { list | status | up | down }\n" +"\n" +" list [id <id> | uuid <id> | system | user]\n" +" status\n" +" up id <id> | uuid <id> [iface <iface>] [ap <hwaddr>] [--nowait] [--timeout " +"<timeout>]\n" +" down id <id> | uuid <id>\n" + +#: ../cli/src/connections.c:200 ../cli/src/connections.c:541 +#, c-format +msgid "Error: 'con list': %s" +msgstr "Eraro: 'con list': %s" + +#: ../cli/src/connections.c:202 ../cli/src/connections.c:543 +#, c-format +msgid "Error: 'con list': %s; allowed fields: %s" +msgstr "Eraro: 'con list': %s; permesataj kampoj: %s" + +#: ../cli/src/connections.c:210 +msgid "Connection details" +msgstr "Konektodetaloj" + +#: ../cli/src/connections.c:385 ../cli/src/connections.c:606 +msgid "system" +msgstr "sistemo" + +#: ../cli/src/connections.c:385 ../cli/src/connections.c:606 +msgid "user" +msgstr "uzanto" + +#: ../cli/src/connections.c:387 +msgid "never" +msgstr "neniam" + +#. "CAPABILITIES" +#. Print header +#. "WIFI-PROPERTIES" +#: ../cli/src/connections.c:388 ../cli/src/connections.c:389 +#: ../cli/src/connections.c:607 ../cli/src/connections.c:610 +#: ../cli/src/devices.c:433 ../cli/src/devices.c:558 ../cli/src/devices.c:584 +#: ../cli/src/devices.c:585 ../cli/src/devices.c:586 ../cli/src/devices.c:587 +#: ../cli/src/devices.c:588 ../cli/src/settings.c:508 +#: ../cli/src/settings.c:551 ../cli/src/settings.c:652 +#: ../cli/src/settings.c:926 ../cli/src/settings.c:927 +#: ../cli/src/settings.c:929 ../cli/src/settings.c:931 +#: ../cli/src/settings.c:1056 ../cli/src/settings.c:1057 +#: ../cli/src/settings.c:1058 ../cli/src/settings.c:1137 +#: ../cli/src/settings.c:1138 ../cli/src/settings.c:1139 +#: ../cli/src/settings.c:1140 ../cli/src/settings.c:1141 +#: ../cli/src/settings.c:1142 ../cli/src/settings.c:1143 +#: ../cli/src/settings.c:1144 ../cli/src/settings.c:1145 +#: ../cli/src/settings.c:1146 ../cli/src/settings.c:1147 +#: ../cli/src/settings.c:1148 ../cli/src/settings.c:1149 +#: ../cli/src/settings.c:1224 +msgid "yes" +msgstr "jes" + +#: ../cli/src/connections.c:388 ../cli/src/connections.c:389 +#: ../cli/src/connections.c:607 ../cli/src/connections.c:610 +#: ../cli/src/devices.c:433 ../cli/src/devices.c:558 ../cli/src/devices.c:584 +#: ../cli/src/devices.c:585 ../cli/src/devices.c:586 ../cli/src/devices.c:587 +#: ../cli/src/devices.c:588 ../cli/src/settings.c:508 +#: ../cli/src/settings.c:510 ../cli/src/settings.c:551 +#: ../cli/src/settings.c:652 ../cli/src/settings.c:926 +#: ../cli/src/settings.c:927 ../cli/src/settings.c:929 +#: ../cli/src/settings.c:931 ../cli/src/settings.c:1056 +#: ../cli/src/settings.c:1057 ../cli/src/settings.c:1058 +#: ../cli/src/settings.c:1137 ../cli/src/settings.c:1138 +#: ../cli/src/settings.c:1139 ../cli/src/settings.c:1140 +#: ../cli/src/settings.c:1141 ../cli/src/settings.c:1142 +#: ../cli/src/settings.c:1143 ../cli/src/settings.c:1144 +#: ../cli/src/settings.c:1145 ../cli/src/settings.c:1146 +#: ../cli/src/settings.c:1147 ../cli/src/settings.c:1148 +#: ../cli/src/settings.c:1149 ../cli/src/settings.c:1224 +msgid "no" +msgstr "ne" + +#: ../cli/src/connections.c:462 ../cli/src/connections.c:505 +msgid "System connections" +msgstr "Sistemkonektoj" + +#: ../cli/src/connections.c:467 ../cli/src/connections.c:518 +msgid "User connections" +msgstr "Uzanto-konektoj" + +#: ../cli/src/connections.c:479 ../cli/src/connections.c:1342 +#: ../cli/src/connections.c:1358 ../cli/src/connections.c:1367 +#: ../cli/src/connections.c:1378 ../cli/src/connections.c:1463 +#: ../cli/src/devices.c:964 ../cli/src/devices.c:974 ../cli/src/devices.c:1076 +#: ../cli/src/devices.c:1083 +#, c-format +msgid "Error: %s argument is missing." +msgstr "Eraro: argumento %s mankas." + +#: ../cli/src/connections.c:492 +#, c-format +msgid "Error: %s - no such connection." +msgstr "Eraro: %s - neniu tia konekto" + +#: ../cli/src/connections.c:524 ../cli/src/connections.c:1391 +#: ../cli/src/connections.c:1481 ../cli/src/devices.c:787 +#: ../cli/src/devices.c:854 ../cli/src/devices.c:988 ../cli/src/devices.c:1089 +#, c-format +msgid "Unknown parameter: %s\n" +msgstr "Nekonata parametro: %s\n" + +#: ../cli/src/connections.c:533 +#, c-format +msgid "Error: no valid parameter specified." +msgstr "Eraro: neniu valida parametro difinita." + +#: ../cli/src/connections.c:548 ../cli/src/connections.c:1584 +#: ../cli/src/devices.c:1295 ../cli/src/network-manager.c:359 +#, c-format +msgid "Error: %s." +msgstr "Eraro: %s." + +#: ../cli/src/connections.c:655 +#, c-format +msgid "Error: 'con status': %s" +msgstr "Eraro: 'con status': %s" + +#: ../cli/src/connections.c:657 +#, c-format +msgid "Error: 'con status': %s; allowed fields: %s" +msgstr "Eraro: 'con status': %s; permesataj kampoj: %s" + +#: ../cli/src/connections.c:664 +msgid "Active connections" +msgstr "Aktivaj konektoj" + +#: ../cli/src/connections.c:1034 +#, c-format +msgid "no active connection on device '%s'" +msgstr "neniu aktiva konekto sur aparato '%s'" + +#: ../cli/src/connections.c:1042 +#, c-format +msgid "no active connection or device" +msgstr "neniu aktiva konekto aŭ aparato" + +#: ../cli/src/connections.c:1092 +#, c-format +msgid "device '%s' not compatible with connection '%s'" +msgstr "aparato '%s' ne kongruas kun konekto '%s'" + +#: ../cli/src/connections.c:1094 +#, c-format +msgid "no device found for connection '%s'" +msgstr "neniu aparato trovita por konekto '%s'" + +#: ../cli/src/connections.c:1105 +msgid "activating" +msgstr "enŝaltas" + +#: ../cli/src/connections.c:1107 +msgid "activated" +msgstr "enŝaltite" + +#: ../cli/src/connections.c:1110 ../cli/src/connections.c:1133 +#: ../cli/src/connections.c:1166 ../cli/src/devices.c:247 +#: ../cli/src/devices.c:559 ../cli/src/network-manager.c:94 +#: ../cli/src/network-manager.c:149 ../cli/src/settings.c:473 +msgid "unknown" +msgstr "nekonate" + +#: ../cli/src/connections.c:1119 +msgid "VPN connecting (prepare)" +msgstr "VPN konektas (preparo)" + +#: ../cli/src/connections.c:1121 +msgid "VPN connecting (need authentication)" +msgstr "VPN konektas (bezonas aŭtentigon)" + +#: ../cli/src/connections.c:1123 +msgid "VPN connecting" +msgstr "VPN konektas" + +#: ../cli/src/connections.c:1125 +msgid "VPN connecting (getting IP configuration)" +msgstr "VPN konektas (akiras IP-agordaron)" + +#: ../cli/src/connections.c:1127 +msgid "VPN connected" +msgstr "VPN konektita" + +#: ../cli/src/connections.c:1129 +msgid "VPN connection failed" +msgstr "VPN-konekto fiaskis" + +#: ../cli/src/connections.c:1131 +msgid "VPN disconnected" +msgstr "VPN malkonektis" + +#: ../cli/src/connections.c:1142 +msgid "unknown reason" +msgstr "nekonata kialo" + +#: ../cli/src/connections.c:1144 +msgid "none" +msgstr "nenio" + +#: ../cli/src/connections.c:1146 +msgid "the user was disconnected" +msgstr "la uzanto estis malkonektita" + +#: ../cli/src/connections.c:1148 +msgid "the base network connection was interrupted" +msgstr "la baza retkonekto estis interrompita" + +#: ../cli/src/connections.c:1150 +msgid "the VPN service stopped unexpectedly" +msgstr "la VPN-servo neatendite ĉesis" + +#: ../cli/src/connections.c:1152 +msgid "the VPN service returned invalid configuration" +msgstr "la VPN-servo revenigis nevalidan agordaron" + +#: ../cli/src/connections.c:1154 +msgid "the connection attempt timed out" +msgstr "la konektoprovo eltempiĝis" + +#: ../cli/src/connections.c:1156 +msgid "the VPN service did not start in time" +msgstr "la VPN-servo ne startis ĝustatempe" + +#: ../cli/src/connections.c:1158 +msgid "the VPN service failed to start" +msgstr "la VPN-servo fiaskis starti" + +#: ../cli/src/connections.c:1160 +msgid "no valid VPN secrets" +msgstr "neniu valida VPN-sekreto" + +#: ../cli/src/connections.c:1162 +msgid "invalid VPN secrets" +msgstr "nevalidaj VPN-sekretoj" + +#: ../cli/src/connections.c:1164 +msgid "the connection was removed" +msgstr "la konekto estis forigita" + +#: ../cli/src/connections.c:1178 +#, c-format +msgid "state: %s\n" +msgstr "stato: %s\n" + +#: ../cli/src/connections.c:1181 ../cli/src/connections.c:1207 +#, c-format +msgid "Connection activated\n" +msgstr "Konekto enŝaltita\n" + +#: ../cli/src/connections.c:1184 +#, c-format +msgid "Error: Connection activation failed." +msgstr "Eraro: Enŝalto de konekto fiaskis." + +#: ../cli/src/connections.c:1203 +#, c-format +msgid "state: %s (%d)\n" +msgstr "stato: %s (%d)\n" + +#: ../cli/src/connections.c:1213 +#, c-format +msgid "Error: Connection activation failed: %s." +msgstr "Eraro: Enŝalto de konekto fiaskis: %s." + +#: ../cli/src/connections.c:1230 ../cli/src/devices.c:911 +#, c-format +msgid "Error: Timeout %d sec expired." +msgstr "Eraro: Eltempiĝo finiĝis %d sek." + +#: ../cli/src/connections.c:1273 +#, c-format +msgid "Error: Connection activation failed: %s" +msgstr "Eraro: Enŝalto de konekto fiaskis: %s" + +#: ../cli/src/connections.c:1287 +#, c-format +msgid "Error: Obtaining active connection for '%s' failed." +msgstr "Eraro: Akiro de aktiva konekto por '%s' fiaskis." + +#: ../cli/src/connections.c:1296 +#, c-format +msgid "Active connection state: %s\n" +msgstr "Stato de aktiva konekto: %s\n" + +#: ../cli/src/connections.c:1297 +#, c-format +msgid "Active connection path: %s\n" +msgstr "Vojo de aktiva konekto: %s\n" + +#: ../cli/src/connections.c:1351 ../cli/src/connections.c:1472 +#, c-format +msgid "Error: Unknown connection: %s." +msgstr "Eraro: Nekonata konekto: %s." + +#: ../cli/src/connections.c:1386 ../cli/src/devices.c:982 +#, c-format +msgid "Error: timeout value '%s' is not valid." +msgstr "Eraro: eltempiĝa valoro '%s' ne validas." + +#: ../cli/src/connections.c:1399 ../cli/src/connections.c:1489 +#, c-format +msgid "Error: id or uuid has to be specified." +msgstr "Eraro: id aŭ uuid devas esti specifata." + +#: ../cli/src/connections.c:1419 +#, c-format +msgid "Error: No suitable device found: %s." +msgstr "Eraro: Trovis neniun taŭgan aparaton: %s." + +#: ../cli/src/connections.c:1421 +#, c-format +msgid "Error: No suitable device found." +msgstr "Eraro: Trovis neniun taŭgan aparaton." + +#: ../cli/src/connections.c:1516 +#, c-format +msgid "Warning: Connection not active\n" +msgstr "Atenton: Konekto ne aktivas\n" + +#: ../cli/src/connections.c:1573 +#, c-format +msgid "Error: 'con' command '%s' is not valid." +msgstr "Eraro: 'con'-komando '%s' ne validas." + +#: ../cli/src/connections.c:1609 +#, c-format +msgid "Error: could not connect to D-Bus." +msgstr "Eraro: ne povis konekti al D-Bus." + +#: ../cli/src/connections.c:1616 +#, c-format +msgid "Error: Could not get system settings." +msgstr "Eraro: Ne povis akiri sistemajn agordojn." + +#: ../cli/src/connections.c:1624 +#, c-format +msgid "Error: Could not get user settings." +msgstr "Eraro: Ne povis akiri uzanto-agordojn." + +#: ../cli/src/connections.c:1634 +#, c-format +msgid "Error: Can't obtain connections: settings services are not running." +msgstr "Eraro: Ne povas obteni konektojn: agordo-servoj ne aktivas." + +#. 0 +#. 9 +#: ../cli/src/devices.c:61 ../cli/src/devices.c:90 ../cli/src/devices.c:185 +msgid "DEVICE" +msgstr "APARATO" + +#. 1 +#. 4 +#. 0 +#: ../cli/src/devices.c:63 ../cli/src/devices.c:94 +#: ../cli/src/network-manager.c:36 +msgid "STATE" +msgstr "STATO" + +#: ../cli/src/devices.c:73 +msgid "GENERAL" +msgstr "ĜENERALA" + +#. 0 +#: ../cli/src/devices.c:74 +msgid "CAPABILITIES" +msgstr "KAPABLOJ" + +#. 1 +#: ../cli/src/devices.c:75 +msgid "WIFI-PROPERTIES" +msgstr "WIFI-ECOJ" + +#. 2 +#: ../cli/src/devices.c:76 +msgid "AP" +msgstr "AP" + +#. 3 +#: ../cli/src/devices.c:77 +msgid "WIRED-PROPERTIES" +msgstr "DRATA-ECOJ" + +#. 4 +#: ../cli/src/devices.c:78 +msgid "IP4-SETTINGS" +msgstr "IP4-AGORDOJ" + +#. 5 +#: ../cli/src/devices.c:79 +msgid "IP4-DNS" +msgstr "IP4-DNS" + +#. 6 +#: ../cli/src/devices.c:80 +msgid "IP6-SETTINGS" +msgstr "IP6-AGORDOJ" + +#. 7 +#: ../cli/src/devices.c:81 +msgid "IP6-DNS" +msgstr "IP6-DNS" + +#. 2 +#: ../cli/src/devices.c:92 +msgid "DRIVER" +msgstr "PELILO" + +#. 3 +#: ../cli/src/devices.c:93 +msgid "HWADDR" +msgstr "APARATADRESO" + +#. 0 +#: ../cli/src/devices.c:103 +msgid "CARRIER-DETECT" +msgstr "PORTANTO-REKONO" + +#. 1 +#: ../cli/src/devices.c:104 +msgid "SPEED" +msgstr "RAPIDO" + +#. 0 +#: ../cli/src/devices.c:113 +msgid "CARRIER" +msgstr "PORTANTO" + +#. 0 +#: ../cli/src/devices.c:123 +msgid "WEP" +msgstr "WEP" + +#. 1 +#: ../cli/src/devices.c:124 +msgid "WPA" +msgstr "WPA" + +#. 2 +#: ../cli/src/devices.c:125 +msgid "WPA2" +msgstr "WPA2" + +#. 3 +#: ../cli/src/devices.c:126 +msgid "TKIP" +msgstr "TKIP" + +#. 4 +#: ../cli/src/devices.c:127 +msgid "CCMP" +msgstr "CCMP" + +#. 0 +#: ../cli/src/devices.c:136 ../cli/src/devices.c:147 +msgid "ADDRESS" +msgstr "ADRESO" + +#. 1 +#: ../cli/src/devices.c:137 ../cli/src/devices.c:148 +msgid "PREFIX" +msgstr "PREFIKSO" + +#. 2 +#: ../cli/src/devices.c:138 ../cli/src/devices.c:149 +msgid "GATEWAY" +msgstr "KLUZO" + +#. 0 +#: ../cli/src/devices.c:158 ../cli/src/devices.c:167 +msgid "DNS" +msgstr "DNS" + +#. 0 +#: ../cli/src/devices.c:176 +msgid "SSID" +msgstr "SSID" + +#. 1 +#: ../cli/src/devices.c:177 +msgid "BSSID" +msgstr "BSSID" + +#. 2 +#: ../cli/src/devices.c:178 +msgid "MODE" +msgstr "REĜIMO" + +#. 3 +#: ../cli/src/devices.c:179 +msgid "FREQ" +msgstr "FREKV" + +#. 4 +#: ../cli/src/devices.c:180 +msgid "RATE" +msgstr "TRANSMETRAPIDO" + +#. 5 +#: ../cli/src/devices.c:181 +msgid "SIGNAL" +msgstr "SIGNALO" + +#. 6 +#: ../cli/src/devices.c:182 +msgid "SECURITY" +msgstr "SEKURECO" + +#. 7 +#: ../cli/src/devices.c:183 +msgid "WPA-FLAGS" +msgstr "WPA-FLAGOJ" + +#. 8 +#: ../cli/src/devices.c:184 +msgid "RSN-FLAGS" +msgstr "RSN-FLAGOJ" + +#. 10 +#: ../cli/src/devices.c:186 +msgid "ACTIVE" +msgstr "AKTIVA" + +#: ../cli/src/devices.c:209 +#, c-format +msgid "" +"Usage: nmcli dev { COMMAND | help }\n" +"\n" +" COMMAND := { status | list | disconnect | wifi }\n" +"\n" +" status\n" +" list [iface <iface>]\n" +" disconnect iface <iface> [--nowait] [--timeout <timeout>]\n" +" wifi [list [iface <iface>] [hwaddr <hwaddr>]]\n" +"\n" +msgstr "" +"Usage: nmcli dev { KOMANDO | help }\n" +"\n" +" KOMANDO := { status | list | disconnect | wifi }\n" +"\n" +" status\n" +" list [iface <iface>]\n" +" disconnect iface <iface> [--nowait] [--timeout <timeout>]\n" +" wifi [list [iface <iface>] [hwaddr <hwaddr>]]\n" +"\n" + +#: ../cli/src/devices.c:229 +msgid "unmanaged" +msgstr "nemastrumata" + +#: ../cli/src/devices.c:231 +msgid "unavailable" +msgstr "neatingebla" + +#: ../cli/src/devices.c:233 ../cli/src/network-manager.c:91 +msgid "disconnected" +msgstr "nekonektite" + +#: ../cli/src/devices.c:235 +msgid "connecting (prepare)" +msgstr "konektas (preparo)" + +#: ../cli/src/devices.c:237 +msgid "connecting (configuring)" +msgstr "konektas (agordado)" + +#: ../cli/src/devices.c:239 +msgid "connecting (need authentication)" +msgstr "konektas (bezonas aŭtentigon)" + +#: ../cli/src/devices.c:241 +msgid "connecting (getting IP configuration)" +msgstr "konektas (akiras IP-agordaron)" + +#: ../cli/src/devices.c:243 ../cli/src/network-manager.c:89 +msgid "connected" +msgstr "konektita" + +#: ../cli/src/devices.c:245 +msgid "connection failed" +msgstr "konekto fiaskis" + +#: ../cli/src/devices.c:268 ../cli/src/devices.c:425 +msgid "Unknown" +msgstr "Nekonata" + +#: ../cli/src/devices.c:300 +msgid "(none)" +msgstr "(nenio)" + +#: ../cli/src/devices.c:325 +#, c-format +msgid "%s: error converting IP4 address 0x%X" +msgstr "%s: eraro dum konverto de IP4-adreso 0x%X" + +#: ../cli/src/devices.c:394 +#, c-format +msgid "%u MHz" +msgstr "%u MHz" + +#: ../cli/src/devices.c:395 +#, c-format +msgid "%u MB/s" +msgstr "%u MB/s" + +#: ../cli/src/devices.c:404 +msgid "Encrypted: " +msgstr "Ĉifrita: " + +#: ../cli/src/devices.c:409 +msgid "WEP " +msgstr "WEP " + +#: ../cli/src/devices.c:411 +msgid "WPA " +msgstr "WPA " + +#: ../cli/src/devices.c:413 +msgid "WPA2 " +msgstr "WPA2 " + +#: ../cli/src/devices.c:416 +msgid "Enterprise " +msgstr "Entrepreno " + +#: ../cli/src/devices.c:425 +msgid "Ad-Hoc" +msgstr "Laŭcela" + +#: ../cli/src/devices.c:425 +msgid "Infrastructure" +msgstr "Infrastrukturo" + +#: ../cli/src/devices.c:487 +#, c-format +msgid "Error: 'dev list': %s" +msgstr "Eraro: 'dev list': %s" + +#: ../cli/src/devices.c:489 +#, c-format +msgid "Error: 'dev list': %s; allowed fields: %s" +msgstr "Eraro: 'dev list': %s; permesataj kampoj: %s" + +#: ../cli/src/devices.c:498 +msgid "Device details" +msgstr "Detaloj de aparato" + +#: ../cli/src/devices.c:528 ../cli/src/devices.c:927 +msgid "(unknown)" +msgstr "(nekonata)" + +#: ../cli/src/devices.c:529 +msgid "unknown)" +msgstr "nekonata)" + +#: ../cli/src/devices.c:555 +#, c-format +msgid "%u Mb/s" +msgstr "%u Mb/s" + +#. Print header +#. "WIRED-PROPERTIES" +#: ../cli/src/devices.c:628 +msgid "on" +msgstr "enŝaltite" + +#: ../cli/src/devices.c:628 +msgid "off" +msgstr "elŝaltite" + +#: ../cli/src/devices.c:810 +#, c-format +msgid "Error: 'dev status': %s" +msgstr "Eraro: 'dev status': %s" + +#: ../cli/src/devices.c:812 +#, c-format +msgid "Error: 'dev status': %s; allowed fields: %s" +msgstr "Eraro: 'dev status': %s; permesataj kampoj: %s" + +#: ../cli/src/devices.c:819 +msgid "Status of devices" +msgstr "Stato de aparatoj" + +#: ../cli/src/devices.c:847 +#, c-format +msgid "Error: '%s' argument is missing." +msgstr "Eraro: argumento '%s' mankas." + +#: ../cli/src/devices.c:876 ../cli/src/devices.c:1015 +#: ../cli/src/devices.c:1138 +#, c-format +msgid "Error: Device '%s' not found." +msgstr "Eraro: Aparato '%s' ne trovita." + +#: ../cli/src/devices.c:899 +#, c-format +msgid "Success: Device '%s' successfully disconnected." +msgstr "Sukceso: Aparato '%s' sukcese malkonektiĝis." + +#: ../cli/src/devices.c:924 +#, c-format +msgid "Error: Device '%s' (%s) disconnecting failed: %s" +msgstr "Eraro: Aparato '%s' (%s) eraro dum malkonektiĝo: %s" + +#: ../cli/src/devices.c:932 +#, c-format +msgid "Device state: %d (%s)\n" +msgstr "Stato de aparato: %d (%s)\n" + +#: ../cli/src/devices.c:996 +#, c-format +msgid "Error: iface has to be specified." +msgstr "Eraro: 'iface' devas esti specifata." + +#: ../cli/src/devices.c:1114 +#, c-format +msgid "Error: 'dev wifi': %s" +msgstr "Eraro: 'dev wifi': %s" + +#: ../cli/src/devices.c:1116 +#, c-format +msgid "Error: 'dev wifi': %s; allowed fields: %s" +msgstr "Eraro: 'dev wifi': %s; permesataj kampoj: %s" + +#: ../cli/src/devices.c:1123 +msgid "WiFi scan list" +msgstr "WiFi-skanlisto" + +#: ../cli/src/devices.c:1158 ../cli/src/devices.c:1212 +#, c-format +msgid "Error: Access point with hwaddr '%s' not found." +msgstr "Eraro: Retkaptejo kun 'hwaddr' '%s' ne trovita" + +#: ../cli/src/devices.c:1175 +#, c-format +msgid "Error: Device '%s' is not a WiFi device." +msgstr "Eraro: Aparato '%s' ne estas WiFi-aparato." + +#: ../cli/src/devices.c:1239 +#, c-format +msgid "Error: 'dev wifi' command '%s' is not valid." +msgstr "Eraro: 'dev wifi'-komando '%s' ne validas." + +#: ../cli/src/devices.c:1286 +#, c-format +msgid "Error: 'dev' command '%s' is not valid." +msgstr "Eraro: 'dev'-komando '%s' ne validas." + +#: ../cli/src/network-manager.c:35 +msgid "RUNNING" +msgstr "AKTIVA" + +#. 1 +#: ../cli/src/network-manager.c:37 +msgid "NET-ENABLED" +msgstr "RET-ENŜALTITE" + +#. 2 +#: ../cli/src/network-manager.c:38 +msgid "WIFI-HARDWARE" +msgstr "WIFI-APARATARO" + +#. 3 +#: ../cli/src/network-manager.c:39 +msgid "WIFI" +msgstr "WIFI" + +#. 4 +#: ../cli/src/network-manager.c:40 +msgid "WWAN-HARDWARE" +msgstr "WWAN-APARATARO" + +#. 5 +#: ../cli/src/network-manager.c:41 +msgid "WWAN" +msgstr "WWAN" + +#: ../cli/src/network-manager.c:64 +#, c-format +msgid "" +"Usage: nmcli nm { COMMAND | help }\n" +"\n" +" COMMAND := { status | enable | sleep | wifi | wwan }\n" +"\n" +" status\n" +" enable [true|false]\n" +" sleep [true|false]\n" +" wifi [on|off]\n" +" wwan [on|off]\n" +"\n" +msgstr "" +"Uzo: nmcli nm { KOMANDO | help }\n" +"\n" +" KOMANDO := { status | enable | sleep | wifi | wwan }\n" +"\n" +" status\n" +" enable [true|false]\n" +" sleep [true|false]\n" +" wifi [on|off]\n" +" wwan [on|off]\n" +"\n" + +#: ../cli/src/network-manager.c:85 +msgid "asleep" +msgstr "dormas" + +#: ../cli/src/network-manager.c:87 +msgid "connecting" +msgstr "konektas" + +#: ../cli/src/network-manager.c:128 +#, c-format +msgid "Error: 'nm status': %s" +msgstr "Eraro: 'nm status': %s" + +#: ../cli/src/network-manager.c:130 +#, c-format +msgid "Error: 'nm status': %s; allowed fields: %s" +msgstr "Eraro: 'nm status': %s; permesataj kampoj: %s" + +#: ../cli/src/network-manager.c:137 +msgid "NetworkManager status" +msgstr "Stato de NetworkManager" + +#. Print header +#: ../cli/src/network-manager.c:144 ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:146 ../cli/src/network-manager.c:147 +#: ../cli/src/network-manager.c:154 ../cli/src/network-manager.c:247 +#: ../cli/src/network-manager.c:296 ../cli/src/network-manager.c:328 +msgid "enabled" +msgstr "enŝaltita" + +#: ../cli/src/network-manager.c:144 ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:146 ../cli/src/network-manager.c:147 +#: ../cli/src/network-manager.c:154 ../cli/src/network-manager.c:247 +#: ../cli/src/network-manager.c:296 ../cli/src/network-manager.c:328 +msgid "disabled" +msgstr "elŝaltite" + +#: ../cli/src/network-manager.c:152 +msgid "running" +msgstr "aktiva" + +#: ../cli/src/network-manager.c:152 +msgid "not running" +msgstr "neaktiva" + +#: ../cli/src/network-manager.c:175 +#, c-format +msgid "Error: Couldn't connect to system bus: %s" +msgstr "Eraro: Ne povis konekti al sistem-buso: %s." + +#: ../cli/src/network-manager.c:186 +#, c-format +msgid "Error: Couldn't create D-Bus object proxy." +msgstr "Eraro: Ne povis krei D-busan objekt-prokurservilon." + +#: ../cli/src/network-manager.c:192 +#, c-format +msgid "Error in sleep: %s" +msgstr "Eraro dum dormo: %s" + +#: ../cli/src/network-manager.c:237 ../cli/src/network-manager.c:286 +#: ../cli/src/network-manager.c:318 +#, c-format +msgid "Error: '--fields' value '%s' is not valid here; allowed fields: %s" +msgstr "Eraro: valoro '--fields' '%s' ne validas tie ĉi; permesataj kampoj: %s" + +#: ../cli/src/network-manager.c:245 +msgid "Networking enabled" +msgstr "Retkonektado enŝaltita" + +#: ../cli/src/network-manager.c:256 +#, c-format +msgid "Error: invalid 'enable' parameter: '%s'; use 'true' or 'false'." +msgstr "Eraro: nevalida 'enŝalt'-parametro: '%s'; uzu 'true' aŭ 'false'." + +#: ../cli/src/network-manager.c:265 +#, c-format +msgid "Error: Sleeping status is not exported by NetworkManager." +msgstr "Eraro: Dorm-stato ne estas elportite de NetworkManager." + +#: ../cli/src/network-manager.c:273 +#, c-format +msgid "Error: invalid 'sleep' parameter: '%s'; use 'true' or 'false'." +msgstr "Eraro: nevalida 'dorm'-parametro: '%s'; uzu 'true' aŭ 'false'." + +#: ../cli/src/network-manager.c:294 +msgid "WiFi enabled" +msgstr "WiFi enŝaltita" + +#: ../cli/src/network-manager.c:305 +#, c-format +msgid "Error: invalid 'wifi' parameter: '%s'." +msgstr "Eraro: nevalida 'wifi'-parametro: '%s'." + +#: ../cli/src/network-manager.c:326 +msgid "WWAN enabled" +msgstr "WWAN enŝaltita" + +#: ../cli/src/network-manager.c:337 +#, c-format +msgid "Error: invalid 'wwan' parameter: '%s'." +msgstr "Eraro: nevalida 'wwan'-parametro: '%s'." + +#: ../cli/src/network-manager.c:348 +#, c-format +msgid "Error: 'nm' command '%s' is not valid." +msgstr "Eraro: 'nm'-komando '%s' ne validas." + +#: ../cli/src/nmcli.c:69 +#, c-format +msgid "" +"Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" +"\n" +"OPTIONS\n" +" -t[erse] terse output\n" +" -p[retty] pretty output\n" +" -m[ode] tabular|multiline output mode\n" +" -f[ields] <field1,field2,...>|all|common specify fields to output\n" +" -e[scape] yes|no escape columns separators in " +"values\n" +" -v[ersion] show program version\n" +" -h[elp] print this help\n" +"\n" +"OBJECT\n" +" nm NetworkManager status\n" +" con NetworkManager connections\n" +" dev devices managed by NetworkManager\n" +"\n" +msgstr "" +"Uzo: %s [OPCIOJ] OBJEKTO { KOMANDO | help }\n" +"\n" +"OPCIOJ\n" +" -t[erse] konciza eligo\n" +" -p[retty] bela eligo\n" +" -m[ode] tabular|multiline eliga reĝimo\n" +" -f[ields] <field1,field2,...>|all|common specifigi eligo-kampojn\n" +" -e[scape] yes|no eskapaj kolumno-separoj en " +"valoroj\n" +" -v[ersion] montri programversion\n" +" -h[elp] printi tiun ĉi help-paĝon\n" +"\n" +"OBJEKTO\n" +" nm stato de NetworkManager\n" +" con konektoj de NetworkManager\n" +" dev aparatoj mastrumataj de NetworkManager\n" +"\n" + +#: ../cli/src/nmcli.c:113 +#, c-format +msgid "Error: Object '%s' is unknown, try 'nmcli help'." +msgstr "Eraro: Objekto '%s' estas nekonata, provu: 'nmcli help'." + +#: ../cli/src/nmcli.c:143 +#, c-format +msgid "Error: Option '--terse' is specified the second time." +msgstr "Eraro: Opcio '--terse' specifiĝis duan fojon." + +#: ../cli/src/nmcli.c:148 +#, c-format +msgid "Error: Option '--terse' is mutually exclusive with '--pretty'." +msgstr "Eraro: Opcioj '--terse' kaj '--pretty' ekskludas unu la alian." + +#: ../cli/src/nmcli.c:156 +#, c-format +msgid "Error: Option '--pretty' is specified the second time." +msgstr "Eraro: Opcio '--pretty' specifiĝis duan fojon." + +#: ../cli/src/nmcli.c:161 +#, c-format +msgid "Error: Option '--pretty' is mutually exclusive with '--terse'." +msgstr "Eraro: Opcioj '--pretty' kaj '--terse' ekskludas unu la alian." + +#: ../cli/src/nmcli.c:171 ../cli/src/nmcli.c:187 +#, c-format +msgid "Error: missing argument for '%s' option." +msgstr "Eraro: mankas argumento por elektindaĵo '%s'." + +#: ../cli/src/nmcli.c:180 ../cli/src/nmcli.c:196 +#, c-format +msgid "Error: '%s' is not valid argument for '%s' option." +msgstr "Eraro: '%s' ne estas valida argumento por elektindaĵo '%s'." + +#: ../cli/src/nmcli.c:203 +#, c-format +msgid "Error: fields for '%s' options are missing." +msgstr "Eraro: kampoj por elektindaĵoj '%s' mankas." + +#: ../cli/src/nmcli.c:209 +#, c-format +msgid "nmcli tool, version %s\n" +msgstr "ilo 'nmcli', versio %s\n" + +#: ../cli/src/nmcli.c:215 +#, c-format +msgid "Error: Option '%s' is unknown, try 'nmcli -help'." +msgstr "Eraro: Opcio '%s' estas nekonata, provu: 'nmcli -help'." + +#: ../cli/src/nmcli.c:234 +#, c-format +msgid "Caught signal %d, shutting down..." +msgstr "Ricevis signalon '%d', elŝaltas..." + +#: ../cli/src/nmcli.c:259 +#, c-format +msgid "Error: Could not connect to NetworkManager." +msgstr "Eraro: Ne eblis konekti al NetworkManager" + +#: ../cli/src/nmcli.c:275 +msgid "Success" +msgstr "Sukceso" + +#: ../cli/src/settings.c:411 +#, c-format +msgid "%d (hex-ascii-key)" +msgstr "%d (heks-ascii-ŝlosilo)" + +#: ../cli/src/settings.c:413 +#, c-format +msgid "%d (104/128-bit passphrase)" +msgstr "%d (104/128-bita pasvorto)" + +#: ../cli/src/settings.c:416 +#, c-format +msgid "%d (unknown)" +msgstr "%d (nekonata)" + +#: ../cli/src/settings.c:442 +msgid "0 (unknown)" +msgstr "0 (nekonata)" + +#: ../cli/src/settings.c:448 +msgid "any, " +msgstr "ajna, " + +#: ../cli/src/settings.c:450 +msgid "900 MHz, " +msgstr "900 MHz, " + +#: ../cli/src/settings.c:452 +msgid "1800 MHz, " +msgstr "1800 MHz, " + +#: ../cli/src/settings.c:454 +msgid "1900 MHz, " +msgstr "1900 MHz, " + +#: ../cli/src/settings.c:456 +msgid "850 MHz, " +msgstr "850 MHz, " + +#: ../cli/src/settings.c:458 +msgid "WCDMA 3GPP UMTS 2100 MHz, " +msgstr "WCDMA 3GPP UMTS 2100 MHz, " + +#: ../cli/src/settings.c:460 +msgid "WCDMA 3GPP UMTS 1800 MHz, " +msgstr "WCDMA 3GPP UMTS 1800 MHz, " + +#: ../cli/src/settings.c:462 +msgid "WCDMA 3GPP UMTS 1700/2100 MHz, " +msgstr "WCDMA 3GPP UMTS 1700/2100 MHz, " + +#: ../cli/src/settings.c:464 +msgid "WCDMA 3GPP UMTS 800 MHz, " +msgstr "WCDMA 3GPP UMTS 800 MHz, " + +#: ../cli/src/settings.c:466 +msgid "WCDMA 3GPP UMTS 850 MHz, " +msgstr "WCDMA 3GPP UMTS 850 MHz, " + +#: ../cli/src/settings.c:468 +msgid "WCDMA 3GPP UMTS 900 MHz, " +msgstr "WCDMA 3GPP UMTS 900 MHz, " + +#: ../cli/src/settings.c:470 +msgid "WCDMA 3GPP UMTS 1700 MHz, " +msgstr "WCDMA 3GPP UMTS 1700 MHz, " + +#: ../cli/src/settings.c:554 ../cli/src/settings.c:721 +msgid "auto" +msgstr "aŭto" + +#: ../cli/src/settings.c:716 ../cli/src/settings.c:719 +#: ../cli/src/settings.c:720 ../cli/src/utils.c:172 +msgid "not set" +msgstr "neagordita" + +#: ../cli/src/utils.c:124 +#, c-format +msgid "field '%s' has to be alone" +msgstr "kampo '%s' devas esti sola" + +#: ../cli/src/utils.c:127 +#, c-format +msgid "invalid field '%s'" +msgstr "nevalida kampo '%s'" + +#: ../cli/src/utils.c:146 +#, c-format +msgid "Option '--terse' requires specifying '--fields'" +msgstr "Elektindaĵo '--terse' postulas specifigon de '--fields'" + +#: ../cli/src/utils.c:150 +#, c-format +msgid "Option '--terse' requires specific '--fields' option values , not '%s'" +msgstr "" +"Elektindaĵo '--terse' postulas specifajn elektindajn valorojn de '--fields', " +"ne '%s'" + +#: ../libnm-util/crypto.c:121 +#, c-format +msgid "PEM key file had no end tag '%s'." +msgstr "PEM-ŝlosil-dosiero ne havis finan etikedon '%s'." + +#: ../libnm-util/crypto.c:131 +#, c-format +msgid "Doesn't look like a PEM private key file." +msgstr "Tio ĉi ne aspektas kiel privat-ŝlosila PEM-dosiero." + +#: ../libnm-util/crypto.c:139 +#, c-format +msgid "Not enough memory to store PEM file data." +msgstr "Malsufiĉas memoro por stori datenojn de PEM-dosiero." + +#: ../libnm-util/crypto.c:155 +#, c-format +msgid "Malformed PEM file: Proc-Type was not first tag." +msgstr "Misforma PEM-dosiero: 'Proc-Type' ne estas la unua etikedo." + +#: ../libnm-util/crypto.c:163 +#, c-format +msgid "Malformed PEM file: unknown Proc-Type tag '%s'." +msgstr "Misforma PEM-dosiero: nekonata Proc-Type-etikedo \"%s\"." + +#: ../libnm-util/crypto.c:173 +#, c-format +msgid "Malformed PEM file: DEK-Info was not the second tag." +msgstr "Misforma PEM-dosiero: 'DEK-Info' ne estas la dua etikedo." + +#: ../libnm-util/crypto.c:184 +#, c-format +msgid "Malformed PEM file: no IV found in DEK-Info tag." +msgstr "Misforma PEM-dosiero: mi ne trovis IV en la etikedo \"DEK-Info\"." + +#: ../libnm-util/crypto.c:191 +#, c-format +msgid "Malformed PEM file: invalid format of IV in DEK-Info tag." +msgstr "" +"Misforma PEM-dosiero: nevalida struktturo de IV en la etikedo \"DEK-Info\"." + +#: ../libnm-util/crypto.c:204 +#, c-format +msgid "Malformed PEM file: unknown private key cipher '%s'." +msgstr "Misforma PEM-dosiero: nekonata privat-ŝlosila ĉifro \"%s\"." + +#: ../libnm-util/crypto.c:223 +#, c-format +msgid "Could not decode private key." +msgstr "Ne eblis malĉifri la privatan ŝlosilon." + +#: ../libnm-util/crypto.c:268 +#, c-format +msgid "PEM certificate '%s' had no end tag '%s'." +msgstr "La PEM-certigilo \"%s\" ne havas finan etikedon \"%s\"." + +#: ../libnm-util/crypto.c:278 +#, c-format +msgid "Failed to decode certificate." +msgstr "Malsuksesis malĉifri la certigilon." + +#: ../libnm-util/crypto.c:287 +#, c-format +msgid "Not enough memory to store certificate data." +msgstr "Malsufiĉas memoro por stori la datenojn de la certigilo." + +#: ../libnm-util/crypto.c:295 +#, c-format +msgid "Not enough memory to store file data." +msgstr "Malsufiĉas memoro por stori la datenojn de la dosiero." + +#: ../libnm-util/crypto.c:325 +#, c-format +msgid "IV must be an even number of bytes in length." +msgstr "IV nepre amkplesu paran nombron da bajtoj." + +#: ../libnm-util/crypto.c:334 +#, c-format +msgid "Not enough memory to store the IV." +msgstr "Malsufiĉas memoro por stori la IV-on." + +#: ../libnm-util/crypto.c:345 +#, c-format +msgid "IV contains non-hexadecimal digits." +msgstr "IV enhavas nedeksesumajn ciferojn" + +#: ../libnm-util/crypto.c:383 ../libnm-util/crypto_gnutls.c:148 +#: ../libnm-util/crypto_gnutls.c:266 ../libnm-util/crypto_nss.c:171 +#: ../libnm-util/crypto_nss.c:336 +#, c-format +msgid "Private key cipher '%s' was unknown." +msgstr "Privata Cipher-ŝlosilo '%s' estas nekonata." + +#: ../libnm-util/crypto.c:392 +#, c-format +msgid "Not enough memory to decrypt private key." +msgstr "Nesufiĉa memoro por malĉifri privatan ŝlosilon." + +#: ../libnm-util/crypto.c:512 +#, c-format +msgid "Unable to determine private key type." +msgstr "Ne eblas determini la tipon de la privata ŝlosilo." + +#: ../libnm-util/crypto.c:531 +#, c-format +msgid "Not enough memory to store decrypted private key." +msgstr "Nesufiĉa memoro por gardi privatan ŝlosilon malĉifritan." + +#: ../libnm-util/crypto_gnutls.c:49 +msgid "Failed to initialize the crypto engine." +msgstr "Pretigo de la kriptografia maŝino fiaskis." + +#: ../libnm-util/crypto_gnutls.c:93 +#, c-format +msgid "Failed to initialize the MD5 engine: %s / %s." +msgstr "Pretigo de la MD5-maŝino fiaskis: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:156 +#, c-format +msgid "Invalid IV length (must be at least %zd)." +msgstr "Nevalida amplekso por IV (devas esti almenaŭ %zd)." + +#: ../libnm-util/crypto_gnutls.c:165 ../libnm-util/crypto_nss.c:188 +#, c-format +msgid "Not enough memory for decrypted key buffer." +msgstr "Nesufiĉa memoro por bufro de la malĉifrita ŝlosilo." + +#: ../libnm-util/crypto_gnutls.c:173 +#, c-format +msgid "Failed to initialize the decryption cipher context: %s / %s." +msgstr "Fiaskis pravalorizi la malĉifran Cipher-kuntekston: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:182 +#, c-format +msgid "Failed to set symmetric key for decryption: %s / %s." +msgstr "Fiaskis agordi simetrian ŝlosilon por malĉifro: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:191 +#, c-format +msgid "Failed to set IV for decryption: %s / %s." +msgstr "Fiaskis agordi IV por malĉifro: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:200 +#, c-format +msgid "Failed to decrypt the private key: %s / %s." +msgstr "Fiaskis malĉifri la privatan ŝlosilon: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:210 ../libnm-util/crypto_nss.c:267 +#, c-format +msgid "Failed to decrypt the private key: unexpected padding length." +msgstr "Fiaskis malĉifri la privatan ŝlosilon: neatendita ŝtopada longo." + +#: ../libnm-util/crypto_gnutls.c:221 ../libnm-util/crypto_nss.c:278 +#, c-format +msgid "Failed to decrypt the private key." +msgstr "Fiaskis malĉifri la privatan ŝlosilon." + +#: ../libnm-util/crypto_gnutls.c:286 ../libnm-util/crypto_nss.c:356 +#, c-format +msgid "Could not allocate memory for encrypting." +msgstr "Ne eblis rezervi memoron por ĉifrado." + +#: ../libnm-util/crypto_gnutls.c:294 +#, c-format +msgid "Failed to initialize the encryption cipher context: %s / %s." +msgstr "Fiaskis valorizi la ĉifradan kuntekston: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:303 +#, c-format +msgid "Failed to set symmetric key for encryption: %s / %s." +msgstr "Fiaskis agordi simetrian ŝlosilon por ĉifrado: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:313 +#, c-format +msgid "Failed to set IV for encryption: %s / %s." +msgstr "Fiaskis agordi IV por ĉifrado: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:322 +#, c-format +msgid "Failed to encrypt the data: %s / %s." +msgstr "Ĉifrado de datumoj malsukcesis: %s / %s." + +#: ../libnm-util/crypto_gnutls.c:362 +#, c-format +msgid "Error initializing certificate data: %s" +msgstr "Eraro dum pravalorizo de atestilaj datumoj: %s" + +#: ../libnm-util/crypto_gnutls.c:384 +#, c-format +msgid "Couldn't decode certificate: %s" +msgstr "Ne povis malkodi certigilon: %s" + +#: ../libnm-util/crypto_gnutls.c:408 +#, c-format +msgid "Couldn't initialize PKCS#12 decoder: %s" +msgstr "Ne povis pravalorizi PKCS#12-malkodilon: %s" + +#: ../libnm-util/crypto_gnutls.c:421 +#, c-format +msgid "Couldn't decode PKCS#12 file: %s" +msgstr "Ne eblis dekodi PKCS#12-dosieron: %s" + +#: ../libnm-util/crypto_gnutls.c:433 +#, c-format +msgid "Couldn't verify PKCS#12 file: %s" +msgstr "No povis kontroli PKCS#12-dosieron: %s" + +#: ../libnm-util/crypto_nss.c:56 +#, c-format +msgid "Failed to initialize the crypto engine: %d." +msgstr "Pravalorigo de la kriptografia maŝino fiaskis: %d." + +#: ../libnm-util/crypto_nss.c:111 +#, c-format +msgid "Failed to initialize the MD5 context: %d." +msgstr "Fiaskis pravalorizi la MD5-kuntekston: %d." + +#: ../libnm-util/crypto_nss.c:179 +#, c-format +msgid "Invalid IV length (must be at least %d)." +msgstr "Nevalida IV-longo (devas esti almenaŭ %d)." + +#: ../libnm-util/crypto_nss.c:196 +#, c-format +msgid "Failed to initialize the decryption cipher slot." +msgstr "Fiaskis pravalorizi la malĉifran Cipher-foldon." + +#: ../libnm-util/crypto_nss.c:206 +#, c-format +msgid "Failed to set symmetric key for decryption." +msgstr "Fiaskis agordi simetrian ŝlosilon por malĉifrado." + +#: ../libnm-util/crypto_nss.c:216 +#, c-format +msgid "Failed to set IV for decryption." +msgstr "Fiaskis agordi IV por malĉifrado." + +#: ../libnm-util/crypto_nss.c:224 +#, c-format +msgid "Failed to initialize the decryption context." +msgstr "Fiaskis pravalorizi la malĉifran kuntekston." + +#: ../libnm-util/crypto_nss.c:237 +#, c-format +msgid "Failed to decrypt the private key: %d." +msgstr "Fiaskis malĉifri la privatan ŝlosilon: %d." + +#: ../libnm-util/crypto_nss.c:245 +#, c-format +msgid "Failed to decrypt the private key: decrypted data too large." +msgstr "Fiaskis malĉifri la privatan ŝlosilon: malĉifritaj datumoj tro longas." + +#: ../libnm-util/crypto_nss.c:256 +#, c-format +msgid "Failed to finalize decryption of the private key: %d." +msgstr "Fiaskis fini malĉifradon de la privata ŝlosilo: %d." + +#: ../libnm-util/crypto_nss.c:364 +#, c-format +msgid "Failed to initialize the encryption cipher slot." +msgstr "Fiaskis pravalorizi la ĉifran Cipher-foldon." + +#: ../libnm-util/crypto_nss.c:372 +#, c-format +msgid "Failed to set symmetric key for encryption." +msgstr "Fiaskis agordi simetrian ŝlosilon por ĉifrado." + +#: ../libnm-util/crypto_nss.c:380 +#, c-format +msgid "Failed to set IV for encryption." +msgstr "Fiaskis agordi IV por ĉifrado." + +#: ../libnm-util/crypto_nss.c:388 +#, c-format +msgid "Failed to initialize the encryption context." +msgstr "Fiaskis pravalorizi la ĉifradan kuntekston." + +#: ../libnm-util/crypto_nss.c:396 +#, c-format +msgid "Failed to encrypt: %d." +msgstr "Fiaskis ĉifri: %d." + +#: ../libnm-util/crypto_nss.c:404 +#, c-format +msgid "Unexpected amount of data after encrypting." +msgstr "Neatendita nombro da datumoj post ĉifrado." + +#: ../libnm-util/crypto_nss.c:447 +#, c-format +msgid "Couldn't decode certificate: %d" +msgstr "Ne povis malkodigi atestilon: %d" + +#: ../libnm-util/crypto_nss.c:482 +#, c-format +msgid "Couldn't convert password to UCS2: %d" +msgstr "Ne povis konverti pasvorton al UCS2: %d" + +#: ../libnm-util/crypto_nss.c:510 +#, c-format +msgid "Couldn't initialize PKCS#12 decoder: %d" +msgstr "Ne povis pravalorizi PKCS#12-malkodilon: %d" + +#: ../libnm-util/crypto_nss.c:519 +#, c-format +msgid "Couldn't decode PKCS#12 file: %d" +msgstr "Ne povis malkodigi PKCS#12-dosieron: %d" + +#: ../libnm-util/crypto_nss.c:528 +#, c-format +msgid "Couldn't verify PKCS#12 file: %d" +msgstr "Ne povis kontroli PKCS#12-dosieron: %d" + +#: ../libnm-util/crypto_nss.c:557 +msgid "Could not generate random data." +msgstr "Ne povis generi hazardajn datumojn." + +#: ../libnm-util/nm-utils.c:1975 +#, c-format +msgid "Not enough memory to make encryption key." +msgstr "Nesufiĉa memoro por fari ĉifran ŝlosilon." + +#: ../libnm-util/nm-utils.c:2085 +msgid "Could not allocate memory for PEM file creation." +msgstr "Ne povis atribui memoron por kreo de PEM-dosiero." + +#: ../libnm-util/nm-utils.c:2097 +#, c-format +msgid "Could not allocate memory for writing IV to PEM file." +msgstr "Ne povis atribui memoron por konservi IV en PEM-dosieron." + +#: ../libnm-util/nm-utils.c:2109 +#, c-format +msgid "Could not allocate memory for writing encrypted key to PEM file." +msgstr "" +"Ne povis atribui memoron por konservi ĉifritan ŝlosilon en PEM-dosieron." + +#: ../libnm-util/nm-utils.c:2128 +#, c-format +msgid "Could not allocate memory for PEM file data." +msgstr "Ne povis atribui memoron por datumoj de PEM-dosiero." + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:1 +msgid "Connection sharing via a protected WiFi network" +msgstr "Kundivido de konektoj per protektita WiFi-reto" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:2 +msgid "Connection sharing via an open WiFi network" +msgstr "Kundivido de konektoj per malferma WiFi-reto" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:3 +msgid "Modify persistent system hostname" +msgstr "Modifi permanentan sisteman gastigan nomon" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:4 +msgid "Modify system connections" +msgstr "Modifi sistemajn konektojn" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:5 +msgid "System policy prevents modification of system settings" +msgstr "Sistempolico preventas modifadon de sistemagordoj" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:6 +msgid "System policy prevents modification of the persistent system hostname" +msgstr "Sistempolico preventas modifadon de la konstanta sistem-gastnomo" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:7 +msgid "System policy prevents sharing connections via a protected WiFi network" +msgstr "Sistempolico preventas kundividon de konektoj per protektita WiFi-reto" + +#: ../policy/org.freedesktop.network-manager-settings.system.policy.in.h:8 +msgid "System policy prevents sharing connections via an open WiFi network" +msgstr "Sistempolitiko preventas kundividon de konektoj per malferma WiFi-reto" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:1 +msgid "Allow control of network connections" +msgstr "Permesi kontrolon de retkonektoj" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:2 +msgid "Allow use of user-specific connections" +msgstr "Permesi uzon de specifaj konektoj por uzantoj" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:3 +msgid "Enable or disable WiFi devices" +msgstr "Enŝalti aŭ elŝalti WiFi-aparatojn" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:4 +msgid "Enable or disable mobile broadband devices" +msgstr "Enŝalti aŭ elŝalti poŝtelefonajn larĝkapacitajn aparatojn" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:5 +msgid "Enable or disable system networking" +msgstr "Enŝalti aŭ elŝalti sistemretkonektadon" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:6 +msgid "" +"Put NetworkManager to sleep or wake it up (should only be used by system " +"power management)" +msgstr "" +"Dormigi aŭ veki NetworkManager (estu uzata nur de sistema energimastumado)" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:7 +msgid "System policy prevents control of network connections" +msgstr "Sistempolitiko preventas kontrolon de retkonektoj" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:8 +msgid "System policy prevents enabling or disabling WiFi devices" +msgstr "Sistempolitiko preventas enŝalton aŭ malŝalton de WiFi-aparatoj" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:9 +msgid "System policy prevents enabling or disabling mobile broadband devices" +msgstr "" +"Sistempolitiko preventas enŝalton aŭ malŝalton de poŝtelefonaj larĝkapacitaj " +"aparatoj" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:10 +msgid "System policy prevents enabling or disabling system networking" +msgstr "Sistempolitiko preventas enŝalton aŭ malŝalton de sistema retkonektado" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:11 +msgid "System policy prevents putting NetworkManager to sleep or waking it up" +msgstr "Sistempolitiko preventas dormigi aŭ veki NetworkManager" + +#: ../policy/org.freedesktop.NetworkManager.policy.in.h:12 +msgid "System policy prevents use of user-specific connections" +msgstr "Sistempolitiko preventas uzon de uzant-specifaj konektoj" + +#: ../src/nm-netlink-monitor.c:100 ../src/nm-netlink-monitor.c:231 +#: ../src/nm-netlink-monitor.c:653 +#, c-format +msgid "error processing netlink message: %s" +msgstr "eraro dum traktado de netlink-mesaĝo: %s" + +#: ../src/nm-netlink-monitor.c:214 +msgid "error occurred while waiting for data on socket" +msgstr "okazis eraro dum atendado je datumoj sur kontaktoskatolo" + +#: ../src/nm-netlink-monitor.c:254 +#, c-format +msgid "unable to connect to netlink for monitoring link status: %s" +msgstr "ne eblas konekti al netlink por kontroli ligilan staton: %s" + +#: ../src/nm-netlink-monitor.c:265 +#, c-format +msgid "unable to enable netlink handle credential passing: %s" +msgstr "ne povis aktivigi la netlink-tenilan legitimaĵo-pasadon: %s" + +#: ../src/nm-netlink-monitor.c:291 ../src/nm-netlink-monitor.c:353 +#, c-format +msgid "unable to allocate netlink handle for monitoring link status: %s" +msgstr "ne povis atribui retligiltenilon por kontroli ligilstaton: %s" + +#: ../src/nm-netlink-monitor.c:376 +#, c-format +msgid "unable to allocate netlink link cache for monitoring link status: %s" +msgstr "" +"ne povis atribui ligilan kaŝmemoron de netlink por kontroli ligilstaton: %s" + +#: ../src/nm-netlink-monitor.c:502 +#, c-format +msgid "unable to join netlink group: %s" +msgstr "ne eblas membriĝi al retligila grupo: %s" + +#: ../src/nm-netlink-monitor.c:629 ../src/nm-netlink-monitor.c:642 +#, c-format +msgid "error updating link cache: %s" +msgstr "eraro dum ĝisdatigo de ligila kaŝmemoro: %s" + +#: ../src/main.c:502 +#, c-format +msgid "Invalid option. Please use --help to see a list of valid options.\n" +msgstr "" +"Nevalida elektindaĵo. Bonvolu uzi --help por vidi liston da validaj " +"elektindaĵoj.\n" + +#: ../src/main.c:573 +#, c-format +msgid "%s. Please use --help to see a list of valid options.\n" +msgstr "%s. Bovolu uzi --help por vidi liston da validaj elektindaĵoj.\n" + +#: ../src/dhcp-manager/nm-dhcp-dhclient.c:328 +msgid "# Created by NetworkManager\n" +msgstr "# Kreita de NetworkManager\n" + +#: ../src/dhcp-manager/nm-dhcp-dhclient.c:344 +#, c-format +msgid "" +"# Merged from %s\n" +"\n" +msgstr "" +"# Kunfandita el %s\n" +"\n" + +#: ../src/dhcp-manager/nm-dhcp-manager.c:284 +msgid "no usable DHCP client could be found." +msgstr "neniu uzebla DHCP-kliento estis trovebla" + +#: ../src/dhcp-manager/nm-dhcp-manager.c:293 +msgid "'dhclient' could be found." +msgstr "'dhclient' povis esti trovita." + +#: ../src/dhcp-manager/nm-dhcp-manager.c:303 +msgid "'dhcpcd' could be found." +msgstr "'dhcpcd' povis esti trovita." + +#: ../src/dhcp-manager/nm-dhcp-manager.c:311 +#, c-format +msgid "unsupported DHCP client '%s'" +msgstr "nesubtenata DHCP-kliento '%s'" + +#: ../src/logging/nm-logging.c:146 +#, c-format +msgid "Unknown log level '%s'" +msgstr "Nekonata protokolnivelo '%s'" + +#: ../src/logging/nm-logging.c:171 +#, c-format +msgid "Unknown log domain '%s'" +msgstr "Nekonata protokola regiono '%s'" + +#: ../src/dns-manager/nm-dns-manager.c:367 +msgid "NOTE: the libc resolver may not support more than 3 nameservers." +msgstr "NOTO: la libc-solvilo eble ne povus subteni pli ol 3 nomservilojn." + +#: ../src/dns-manager/nm-dns-manager.c:369 +msgid "The nameservers listed below may not be recognized." +msgstr "La sube ligstigitaj nomserviloj eble ne estos rekonataj." + +#: ../src/system-settings/nm-default-wired-connection.c:157 +#, c-format +msgid "Auto %s" +msgstr "Aŭto %s" + +#: ../system-settings/plugins/ifcfg-rh/reader.c:3408 +#: ../system-settings/plugins/ifnet/connection_parser.c:49 +msgid "System" +msgstr "Sistemo" @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: NetworkManager\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=NetworkManager&component=general\n" -"POT-Creation-Date: 2010-08-10 03:25+0000\n" -"PO-Revision-Date: 2010-08-12 01:57+0100\n" +"POT-Creation-Date: 2010-09-20 15:25+0000\n" +"PO-Revision-Date: 2010-12-29 12:23+0100\n" "Last-Translator: Daniel Nylander <po@danielnylander.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" "MIME-Version: 1.0\n" @@ -98,7 +98,12 @@ msgstr "AUTOCONNECT" msgid "READONLY" msgstr "SKRIVSKYDDAD" -#: ../cli/src/connections.c:158 +#. 7 +#: ../cli/src/connections.c:83 +msgid "DBUS-PATH" +msgstr "DBUS-SÖKVÄG" + +#: ../cli/src/connections.c:159 #, c-format msgid "" "Usage: nmcli con { COMMAND | help }\n" @@ -117,45 +122,43 @@ msgstr "" " up id <id> | uuid <id> [iface <gränssnitt>] [ap <hwaddr>] [--nowait] [--timeout <tidsgräns>]\n" " down id <id> | uuid <id>\n" -#: ../cli/src/connections.c:198 -#: ../cli/src/connections.c:537 +#: ../cli/src/connections.c:199 +#: ../cli/src/connections.c:540 #, c-format msgid "Error: 'con list': %s" msgstr "Fel: \"con list\": %s" -#: ../cli/src/connections.c:200 -#: ../cli/src/connections.c:539 +#: ../cli/src/connections.c:201 +#: ../cli/src/connections.c:542 #, c-format msgid "Error: 'con list': %s; allowed fields: %s" msgstr "Fel: \"con list\": %s; tillåtna fält: %s" -#: ../cli/src/connections.c:208 -#| msgid "Connections" +#: ../cli/src/connections.c:209 msgid "Connection details" msgstr "Anslutningsdetaljer" -#: ../cli/src/connections.c:382 -#: ../cli/src/connections.c:602 -#| msgid "System" +#: ../cli/src/connections.c:384 +#: ../cli/src/connections.c:605 msgid "system" msgstr "system" -#: ../cli/src/connections.c:382 -#: ../cli/src/connections.c:602 +#: ../cli/src/connections.c:384 +#: ../cli/src/connections.c:605 msgid "user" msgstr "användare" -#: ../cli/src/connections.c:384 +#: ../cli/src/connections.c:386 msgid "never" msgstr "aldrig" #. "CAPABILITIES" #. Print header #. "WIFI-PROPERTIES" -#: ../cli/src/connections.c:385 -#: ../cli/src/connections.c:386 -#: ../cli/src/connections.c:603 +#: ../cli/src/connections.c:387 +#: ../cli/src/connections.c:388 #: ../cli/src/connections.c:606 +#: ../cli/src/connections.c:609 #: ../cli/src/devices.c:432 #: ../cli/src/devices.c:557 #: ../cli/src/devices.c:583 @@ -190,10 +193,10 @@ msgstr "aldrig" msgid "yes" msgstr "ja" -#: ../cli/src/connections.c:385 -#: ../cli/src/connections.c:386 -#: ../cli/src/connections.c:603 +#: ../cli/src/connections.c:387 +#: ../cli/src/connections.c:388 #: ../cli/src/connections.c:606 +#: ../cli/src/connections.c:609 #: ../cli/src/devices.c:432 #: ../cli/src/devices.c:557 #: ../cli/src/devices.c:583 @@ -229,23 +232,22 @@ msgstr "ja" msgid "no" msgstr "nej" -#: ../cli/src/connections.c:458 -#: ../cli/src/connections.c:501 -#| msgid "System connections:\n" +#: ../cli/src/connections.c:461 +#: ../cli/src/connections.c:504 msgid "System connections" msgstr "systemanslutningar" -#: ../cli/src/connections.c:463 -#: ../cli/src/connections.c:514 +#: ../cli/src/connections.c:466 +#: ../cli/src/connections.c:517 msgid "User connections" msgstr "Användaranslutningar" -#: ../cli/src/connections.c:475 -#: ../cli/src/connections.c:1335 -#: ../cli/src/connections.c:1351 -#: ../cli/src/connections.c:1360 -#: ../cli/src/connections.c:1371 -#: ../cli/src/connections.c:1456 +#: ../cli/src/connections.c:478 +#: ../cli/src/connections.c:1338 +#: ../cli/src/connections.c:1354 +#: ../cli/src/connections.c:1363 +#: ../cli/src/connections.c:1374 +#: ../cli/src/connections.c:1459 #: ../cli/src/devices.c:962 #: ../cli/src/devices.c:972 #: ../cli/src/devices.c:1074 @@ -254,14 +256,14 @@ msgstr "Användaranslutningar" msgid "Error: %s argument is missing." msgstr "Fel: %s-argument saknas." -#: ../cli/src/connections.c:488 +#: ../cli/src/connections.c:491 #, c-format msgid "Error: %s - no such connection." msgstr "Fel: %s - ingen sådan anslutning." -#: ../cli/src/connections.c:520 -#: ../cli/src/connections.c:1384 -#: ../cli/src/connections.c:1474 +#: ../cli/src/connections.c:523 +#: ../cli/src/connections.c:1387 +#: ../cli/src/connections.c:1477 #: ../cli/src/devices.c:785 #: ../cli/src/devices.c:852 #: ../cli/src/devices.c:986 @@ -270,255 +272,254 @@ msgstr "Fel: %s - ingen sådan anslutning." msgid "Unknown parameter: %s\n" msgstr "Okänd parameter: %s\n" -#: ../cli/src/connections.c:529 +#: ../cli/src/connections.c:532 #, c-format msgid "Error: no valid parameter specified." msgstr "Fel: ingen giltig parameter angiven." -#: ../cli/src/connections.c:544 -#: ../cli/src/connections.c:1577 +#: ../cli/src/connections.c:547 +#: ../cli/src/connections.c:1580 #: ../cli/src/devices.c:1293 -#: ../cli/src/network-manager.c:274 +#: ../cli/src/network-manager.c:359 #, c-format msgid "Error: %s." msgstr "Fel: %s." -#: ../cli/src/connections.c:650 +#: ../cli/src/connections.c:653 #, c-format msgid "Error: 'con status': %s" msgstr "Fel: \"con status\": %s" -#: ../cli/src/connections.c:652 +#: ../cli/src/connections.c:655 #, c-format msgid "Error: 'con status': %s; allowed fields: %s" msgstr "Fel: \"con status\": %s; tillåtna fält: %s" -#: ../cli/src/connections.c:659 +#: ../cli/src/connections.c:662 msgid "Active connections" msgstr "Aktiva anslutningar" -#: ../cli/src/connections.c:1027 +#: ../cli/src/connections.c:1030 #, c-format msgid "no active connection on device '%s'" msgstr "ingen aktiv anslutning på enheten \"%s\"" -#: ../cli/src/connections.c:1035 +#: ../cli/src/connections.c:1038 #, c-format msgid "no active connection or device" msgstr "ingen aktiv anslutning eller enhet" -#: ../cli/src/connections.c:1085 +#: ../cli/src/connections.c:1088 #, c-format msgid "device '%s' not compatible with connection '%s'" msgstr "enheten \"%s\" är inte kompatibel med anslutningen \"%s\"" -#: ../cli/src/connections.c:1087 +#: ../cli/src/connections.c:1090 #, c-format -#| msgid "no active connection on device '%s'" msgid "no device found for connection '%s'" msgstr "ingen enhet hittades för anslutningen \"%s\"" -#: ../cli/src/connections.c:1098 +#: ../cli/src/connections.c:1101 msgid "activating" msgstr "aktiverar" -#: ../cli/src/connections.c:1100 +#: ../cli/src/connections.c:1103 msgid "activated" msgstr "aktiverad" -#: ../cli/src/connections.c:1103 -#: ../cli/src/connections.c:1126 -#: ../cli/src/connections.c:1159 +#: ../cli/src/connections.c:1106 +#: ../cli/src/connections.c:1129 +#: ../cli/src/connections.c:1162 #: ../cli/src/devices.c:246 #: ../cli/src/devices.c:558 -#: ../cli/src/network-manager.c:92 -#: ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:94 +#: ../cli/src/network-manager.c:149 #: ../cli/src/settings.c:473 msgid "unknown" msgstr "okänt" -#: ../cli/src/connections.c:1112 +#: ../cli/src/connections.c:1115 msgid "VPN connecting (prepare)" msgstr "VPN ansluter (förbereder)" -#: ../cli/src/connections.c:1114 +#: ../cli/src/connections.c:1117 msgid "VPN connecting (need authentication)" msgstr "VPN ansluter (behöver autentisering)" -#: ../cli/src/connections.c:1116 +#: ../cli/src/connections.c:1119 msgid "VPN connecting" msgstr "VPN ansluter" -#: ../cli/src/connections.c:1118 +#: ../cli/src/connections.c:1121 msgid "VPN connecting (getting IP configuration)" msgstr "VPN ansluter (hämtar IP-konfiguration)" -#: ../cli/src/connections.c:1120 +#: ../cli/src/connections.c:1123 msgid "VPN connected" msgstr "VPN ansluten" -#: ../cli/src/connections.c:1122 +#: ../cli/src/connections.c:1125 msgid "VPN connection failed" msgstr "VPN-anslutning misslyckades" -#: ../cli/src/connections.c:1124 +#: ../cli/src/connections.c:1127 msgid "VPN disconnected" msgstr "VPN frånkopplad" -#: ../cli/src/connections.c:1135 +#: ../cli/src/connections.c:1138 msgid "unknown reason" msgstr "okänd anledning" -#: ../cli/src/connections.c:1137 +#: ../cli/src/connections.c:1140 msgid "none" msgstr "ingen" -#: ../cli/src/connections.c:1139 +#: ../cli/src/connections.c:1142 msgid "the user was disconnected" msgstr "användaren kopplades från" -#: ../cli/src/connections.c:1141 +#: ../cli/src/connections.c:1144 msgid "the base network connection was interrupted" msgstr "basnätverksanslutningen avbröts" -#: ../cli/src/connections.c:1143 +#: ../cli/src/connections.c:1146 msgid "the VPN service stopped unexpectedly" msgstr "VPN-tjänsten stoppades oväntat" -#: ../cli/src/connections.c:1145 +#: ../cli/src/connections.c:1148 msgid "the VPN service returned invalid configuration" msgstr "VPN-tjänsten returnerade en ogiltig konfiguration" -#: ../cli/src/connections.c:1147 +#: ../cli/src/connections.c:1150 msgid "the connection attempt timed out" msgstr "anslutningsförsöket översteg tidsgränsen" -#: ../cli/src/connections.c:1149 +#: ../cli/src/connections.c:1152 msgid "the VPN service did not start in time" msgstr "VPN-tjänsten startade inte i tid" -#: ../cli/src/connections.c:1151 +#: ../cli/src/connections.c:1154 msgid "the VPN service failed to start" msgstr "VPN-tjänsten misslyckades med att starta" -#: ../cli/src/connections.c:1153 +#: ../cli/src/connections.c:1156 msgid "no valid VPN secrets" msgstr "inga giltiga VPN-hemligheter" -#: ../cli/src/connections.c:1155 +#: ../cli/src/connections.c:1158 msgid "invalid VPN secrets" msgstr "ogiltiga VPN-hemligheter" -#: ../cli/src/connections.c:1157 +#: ../cli/src/connections.c:1160 msgid "the connection was removed" msgstr "anslutningen togs bort" -#: ../cli/src/connections.c:1171 +#: ../cli/src/connections.c:1174 #, c-format msgid "state: %s\n" msgstr "tillstånd: %s\n" -#: ../cli/src/connections.c:1174 -#: ../cli/src/connections.c:1200 +#: ../cli/src/connections.c:1177 +#: ../cli/src/connections.c:1203 #, c-format msgid "Connection activated\n" msgstr "Anslutning aktiverad\n" -#: ../cli/src/connections.c:1177 +#: ../cli/src/connections.c:1180 #, c-format msgid "Error: Connection activation failed." msgstr "Fel: Aktivering av anslutning misslyckades." -#: ../cli/src/connections.c:1196 +#: ../cli/src/connections.c:1199 #, c-format msgid "state: %s (%d)\n" msgstr "tillstånd: %s (%d)\n" -#: ../cli/src/connections.c:1206 +#: ../cli/src/connections.c:1209 #, c-format msgid "Error: Connection activation failed: %s." msgstr "Fel: Aktivering av anslutning misslyckades: %s." -#: ../cli/src/connections.c:1223 +#: ../cli/src/connections.c:1226 #: ../cli/src/devices.c:909 #, c-format msgid "Error: Timeout %d sec expired." msgstr "Fel: Tidsgränsen %d sekunder gick ut." -#: ../cli/src/connections.c:1266 +#: ../cli/src/connections.c:1269 #, c-format msgid "Error: Connection activation failed: %s" msgstr "Fel: Aktivering av anslutning misslyckades: %s" -#: ../cli/src/connections.c:1280 +#: ../cli/src/connections.c:1283 #, c-format msgid "Error: Obtaining active connection for '%s' failed." msgstr "Fel: Hämtning av aktiv anslutning för \"%s\" misslyckades." -#: ../cli/src/connections.c:1289 +#: ../cli/src/connections.c:1292 #, c-format msgid "Active connection state: %s\n" msgstr "Tillstånd för aktiv anslutning: %s\n" -#: ../cli/src/connections.c:1290 +#: ../cli/src/connections.c:1293 #, c-format msgid "Active connection path: %s\n" msgstr "Sökväg för aktiv anslutning: %s\n" -#: ../cli/src/connections.c:1344 -#: ../cli/src/connections.c:1465 +#: ../cli/src/connections.c:1347 +#: ../cli/src/connections.c:1468 #, c-format msgid "Error: Unknown connection: %s." msgstr "Fel: Okänd anslutning: %s." -#: ../cli/src/connections.c:1379 +#: ../cli/src/connections.c:1382 #: ../cli/src/devices.c:980 #, c-format msgid "Error: timeout value '%s' is not valid." msgstr "Fel: värdet \"%s\" för tidsgränsen är inte giltigt." -#: ../cli/src/connections.c:1392 -#: ../cli/src/connections.c:1482 +#: ../cli/src/connections.c:1395 +#: ../cli/src/connections.c:1485 #, c-format msgid "Error: id or uuid has to be specified." msgstr "Fel: id eller uuid måste anges." -#: ../cli/src/connections.c:1412 +#: ../cli/src/connections.c:1415 #, c-format msgid "Error: No suitable device found: %s." msgstr "Fel: Ingen lämplig enhet hittades: %s." -#: ../cli/src/connections.c:1414 +#: ../cli/src/connections.c:1417 #, c-format msgid "Error: No suitable device found." msgstr "Fel: Ingen lämplig enhet hittades." -#: ../cli/src/connections.c:1509 +#: ../cli/src/connections.c:1512 #, c-format msgid "Warning: Connection not active\n" msgstr "Varning: Anslutningen är inte aktiv\n" -#: ../cli/src/connections.c:1566 +#: ../cli/src/connections.c:1569 #, c-format msgid "Error: 'con' command '%s' is not valid." msgstr "Fel: \"con\"-kommandot \"%s\" är inte giltigt." -#: ../cli/src/connections.c:1602 +#: ../cli/src/connections.c:1605 #, c-format msgid "Error: could not connect to D-Bus." msgstr "Fel: kunde inte ansluta till D-Bus." -#: ../cli/src/connections.c:1609 +#: ../cli/src/connections.c:1612 #, c-format msgid "Error: Could not get system settings." msgstr "Fel: Kunde inte få systeminställningar." -#: ../cli/src/connections.c:1617 +#: ../cli/src/connections.c:1620 #, c-format msgid "Error: Could not get user settings." msgstr "Fel: Kunde inte få användarinställningar." -#: ../cli/src/connections.c:1627 +#: ../cli/src/connections.c:1630 #, c-format msgid "Error: Can't obtain connections: settings services are not running." msgstr "Fel: Kan inte få anslutningar: inställningstjänster är inte igång." @@ -556,7 +557,6 @@ msgstr "WIFI-EGENSKAPER" #. 2 #: ../cli/src/devices.c:75 -#| msgid "PEAP" msgid "AP" msgstr "AP" @@ -572,7 +572,6 @@ msgstr "IP4-INSTÄLLNINGAR" #. 5 #: ../cli/src/devices.c:78 -#| msgid "DNS" msgid "IP4-DNS" msgstr "IP4-DNS" @@ -583,7 +582,6 @@ msgstr "IP6-INSTÄLLNINGAR" #. 7 #: ../cli/src/devices.c:80 -#| msgid "DNS" msgid "IP6-DNS" msgstr "IP6-DNS" @@ -614,19 +612,16 @@ msgstr "BÄRARE" #. 0 #: ../cli/src/devices.c:122 -#| msgid " WEP" msgid "WEP" msgstr "WEP" #. 1 #: ../cli/src/devices.c:123 -#| msgid " WPA" msgid "WPA" msgstr "WPA" #. 2 #: ../cli/src/devices.c:124 -#| msgid " WPA2" msgid "WPA2" msgstr "WPA2" @@ -637,7 +632,6 @@ msgstr "TKIP" #. 4 #: ../cli/src/devices.c:126 -#| msgid "AES-CCMP" msgid "CCMP" msgstr "CCMP" @@ -667,13 +661,11 @@ msgstr "DNS" #. 0 #: ../cli/src/devices.c:175 -#| msgid "SSID:" msgid "SSID" msgstr "SSID" #. 1 #: ../cli/src/devices.c:176 -#| msgid "BSSID:" msgid "BSSID" msgstr "BSSID" @@ -719,16 +711,6 @@ msgstr "AKTIV" #: ../cli/src/devices.c:208 #, c-format -#| msgid "" -#| "Usage: nmcli dev { COMMAND | help }\n" -#| "\n" -#| " COMMAND := { status | list | disconnect | wifi }\n" -#| "\n" -#| " status\n" -#| " list [iface <iface>]\n" -#| " disconnect iface <iface> [--nowait] [--timeout <timeout>]\n" -#| " wifi [list [iface <iface>] | apinfo iface <iface> hwaddr <hwaddr>]\n" -#| "\n" msgid "" "Usage: nmcli dev { COMMAND | help }\n" "\n" @@ -759,7 +741,7 @@ msgid "unavailable" msgstr "otillgänglig" #: ../cli/src/devices.c:232 -#: ../cli/src/network-manager.c:89 +#: ../cli/src/network-manager.c:91 msgid "disconnected" msgstr "frånkopplad" @@ -780,7 +762,7 @@ msgid "connecting (getting IP configuration)" msgstr "ansluter (hämtar IP-konfiguration)" #: ../cli/src/devices.c:242 -#: ../cli/src/network-manager.c:87 +#: ../cli/src/network-manager.c:89 msgid "connected" msgstr "ansluten" @@ -813,27 +795,22 @@ msgid "%u MB/s" msgstr "%u MB/s" #: ../cli/src/devices.c:403 -#| msgid ", Encrypted: " msgid "Encrypted: " msgstr "Krypterad: " #: ../cli/src/devices.c:408 -#| msgid " WEP" msgid "WEP " msgstr "WEP " #: ../cli/src/devices.c:410 -#| msgid " WPA" msgid "WPA " msgstr "WPA " #: ../cli/src/devices.c:412 -#| msgid " WPA2" msgid "WPA2 " msgstr "WPA2 " #: ../cli/src/devices.c:415 -#| msgid " Enterprise" msgid "Enterprise " msgstr "Företag" @@ -852,12 +829,10 @@ msgstr "Fel: \"dev list\": %s" #: ../cli/src/devices.c:488 #, c-format -#| msgid "Error: Device '%s' (%s) disconnecting failed: %s" msgid "Error: 'dev list': %s; allowed fields: %s" msgstr "Fel: \"dev list\": %s; tillåtna fält: %s" #: ../cli/src/devices.c:497 -#| msgid "Devices" msgid "Device details" msgstr "Enhetsdetaljer" @@ -867,7 +842,6 @@ msgid "(unknown)" msgstr "(okänt)" #: ../cli/src/devices.c:528 -#| msgid "(unknown)" msgid "unknown)" msgstr "okänt)" @@ -934,7 +908,6 @@ msgstr "Fel: gränssnitt (iface) måste anges." #: ../cli/src/devices.c:1112 #, c-format -#| msgid "Error: 'dev wifi' command '%s' is not valid." msgid "Error: 'dev wifi': %s" msgstr "Fel: \"dev wifi\": %s" @@ -974,147 +947,191 @@ msgstr "KÖR" #. 1 #: ../cli/src/network-manager.c:37 -msgid "WIFI-HARDWARE" -msgstr "WIFI-MASKINVARA" +msgid "NET-ENABLED" +msgstr "NÄT-AKTIVERAT" #. 2 #: ../cli/src/network-manager.c:38 -msgid "WIFI" -msgstr "WIFI" +msgid "WIFI-HARDWARE" +msgstr "WIFI-MASKINVARA" #. 3 #: ../cli/src/network-manager.c:39 -msgid "WWAN-HARDWARE" -msgstr "WWAN-MASKINVARA" +msgid "WIFI" +msgstr "WIFI" #. 4 #: ../cli/src/network-manager.c:40 -#| msgid "NM WWAN:" +msgid "WWAN-HARDWARE" +msgstr "WWAN-MASKINVARA" + +#. 5 +#: ../cli/src/network-manager.c:41 msgid "WWAN" msgstr "WWAN" -#: ../cli/src/network-manager.c:62 +#: ../cli/src/network-manager.c:64 #, c-format +#| msgid "" +#| "Usage: nmcli nm { COMMAND | help }\n" +#| "\n" +#| " COMMAND := { status | sleep | wakeup | wifi | wwan }\n" +#| "\n" +#| " status\n" +#| " sleep\n" +#| " wakeup\n" +#| " wifi [on|off]\n" +#| " wwan [on|off]\n" +#| "\n" msgid "" "Usage: nmcli nm { COMMAND | help }\n" "\n" -" COMMAND := { status | sleep | wakeup | wifi | wwan }\n" +" COMMAND := { status | enable | sleep | wifi | wwan }\n" "\n" " status\n" -" sleep\n" -" wakeup\n" +" enable [true|false]\n" +" sleep [true|false]\n" " wifi [on|off]\n" " wwan [on|off]\n" "\n" msgstr "" "Användning: nmcli nm { KOMMANDO | help }\n" "\n" -" KOMMANDO := { status | sleep | wakeup | wifi | wwan }\n" +" KOMMANDO := { status | enable | sleep | wifi | wwan }\n" "\n" " status\n" -" sleep\n" -" wakeup\n" +" enable [true|false]\n" +" sleep [true|false]\n" " wifi [on|off]\n" " wwan [on|off]\n" "\n" -#: ../cli/src/network-manager.c:83 +#: ../cli/src/network-manager.c:85 msgid "asleep" msgstr "sover" -#: ../cli/src/network-manager.c:85 +#: ../cli/src/network-manager.c:87 msgid "connecting" msgstr "ansluter" -#: ../cli/src/network-manager.c:125 +#: ../cli/src/network-manager.c:128 #, c-format msgid "Error: 'nm status': %s" msgstr "Fel: \"nm status\": %s" -#: ../cli/src/network-manager.c:127 +#: ../cli/src/network-manager.c:130 #, c-format msgid "Error: 'nm status': %s; allowed fields: %s" msgstr "Fel: \"nm status\": %s; tillåtna fält: %s" -#: ../cli/src/network-manager.c:134 +#: ../cli/src/network-manager.c:137 msgid "NetworkManager status" msgstr "Status för Nätverkshanterare" #. Print header -#: ../cli/src/network-manager.c:140 -#: ../cli/src/network-manager.c:141 -#: ../cli/src/network-manager.c:142 -#: ../cli/src/network-manager.c:143 -#: ../cli/src/network-manager.c:211 -#: ../cli/src/network-manager.c:243 +#: ../cli/src/network-manager.c:144 +#: ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:146 +#: ../cli/src/network-manager.c:147 +#: ../cli/src/network-manager.c:154 +#: ../cli/src/network-manager.c:247 +#: ../cli/src/network-manager.c:296 +#: ../cli/src/network-manager.c:328 msgid "enabled" msgstr "aktiverad" -#: ../cli/src/network-manager.c:140 -#: ../cli/src/network-manager.c:141 -#: ../cli/src/network-manager.c:142 -#: ../cli/src/network-manager.c:143 -#: ../cli/src/network-manager.c:211 -#: ../cli/src/network-manager.c:243 +#: ../cli/src/network-manager.c:144 +#: ../cli/src/network-manager.c:145 +#: ../cli/src/network-manager.c:146 +#: ../cli/src/network-manager.c:147 +#: ../cli/src/network-manager.c:154 +#: ../cli/src/network-manager.c:247 +#: ../cli/src/network-manager.c:296 +#: ../cli/src/network-manager.c:328 msgid "disabled" msgstr "inaktiverad" -#: ../cli/src/network-manager.c:148 +#: ../cli/src/network-manager.c:152 msgid "running" msgstr "kör" -#: ../cli/src/network-manager.c:148 +#: ../cli/src/network-manager.c:152 msgid "not running" msgstr "kör inte" -#: ../cli/src/network-manager.c:201 -#: ../cli/src/network-manager.c:233 +#: ../cli/src/network-manager.c:175 +#, c-format +#| msgid "Error: could not connect to D-Bus." +msgid "Error: Couldn't connect to system bus: %s" +msgstr "Fel: kunde inte ansluta till systembussen: %s" + +#: ../cli/src/network-manager.c:186 +#, c-format +#| msgid "Error: could not connect to D-Bus." +msgid "Error: Couldn't create D-Bus object proxy." +msgstr "Fel: Kunde inte skapa proxy för D-Bus-objekt." + +#: ../cli/src/network-manager.c:192 +#, c-format +#| msgid "Error: 'con list': %s" +msgid "Error in sleep: %s" +msgstr "Fel i sömn: %s" + +#: ../cli/src/network-manager.c:237 +#: ../cli/src/network-manager.c:286 +#: ../cli/src/network-manager.c:318 #, c-format -#| msgid "Error: timeout value '%s' is not valid." msgid "Error: '--fields' value '%s' is not valid here; allowed fields: %s" msgstr "Fel: värdet \"%s\" för \"--fields\" är inte giltigt här; tillåtna fält: %s" -#: ../cli/src/network-manager.c:209 -#| msgid "enabled" +#: ../cli/src/network-manager.c:245 +#| msgid "WiFi enabled" +msgid "Networking enabled" +msgstr "Nätverk aktiverat" + +#: ../cli/src/network-manager.c:256 +#, c-format +#| msgid "Error: invalid 'wwan' parameter: '%s'." +msgid "Error: invalid 'enable' parameter: '%s'; use 'true' or 'false'." +msgstr "Fel: ogiltig \"enable\"-parameter: \"%s\"; använd \"true\" eller \"false\"." + +#: ../cli/src/network-manager.c:265 +#, c-format +#| msgid "Error: Could not connect to NetworkManager." +msgid "Error: Sleeping status is not exported by NetworkManager." +msgstr "Fel: Sömnstatus exporteras inte av Nätverkshanterare." + +#: ../cli/src/network-manager.c:273 +#, c-format +#| msgid "Error: invalid 'wifi' parameter: '%s'." +msgid "Error: invalid 'sleep' parameter: '%s'; use 'true' or 'false'." +msgstr "Fel: ogiltig \"sleep\"-parameter: \"%s\"; använd \"true\" eller \"false\"." + +#: ../cli/src/network-manager.c:294 msgid "WiFi enabled" msgstr "WiFi aktiverat" -#: ../cli/src/network-manager.c:220 +#: ../cli/src/network-manager.c:305 #, c-format msgid "Error: invalid 'wifi' parameter: '%s'." msgstr "Fel: ogiltig \"wifi\"-parameter: \"%s\"." -#: ../cli/src/network-manager.c:241 -#| msgid "enabled" +#: ../cli/src/network-manager.c:326 msgid "WWAN enabled" msgstr "WWAN aktiverat" -#: ../cli/src/network-manager.c:252 +#: ../cli/src/network-manager.c:337 #, c-format msgid "Error: invalid 'wwan' parameter: '%s'." msgstr "Fel: ogiltig \"wwan\"-parameter: \"%s\"." -#: ../cli/src/network-manager.c:263 +#: ../cli/src/network-manager.c:348 #, c-format msgid "Error: 'nm' command '%s' is not valid." msgstr "Fel: \"nm\"-kommandot \"%s\" är inte giltigt." #: ../cli/src/nmcli.c:69 #, c-format -#| msgid "" -#| "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" -#| "\n" -#| "OPTIONS\n" -#| " -t[erse] terse output\n" -#| " -p[retty] pretty output\n" -#| " -v[ersion] show program version\n" -#| " -h[elp] print this help\n" -#| "\n" -#| "OBJECT\n" -#| " nm NetworkManager status\n" -#| " con NetworkManager connections\n" -#| " dev devices managed by NetworkManager\n" -#| "\n" msgid "" "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" "\n" @@ -1152,7 +1169,6 @@ msgstr "" #: ../cli/src/nmcli.c:113 #, c-format -#| msgid "Object '%s' is unknown, try 'nmcli help'." msgid "Error: Object '%s' is unknown, try 'nmcli help'." msgstr "Fel: Objektet \"%s\" är okänt, prova \"nmcli help\"." @@ -1179,20 +1195,17 @@ msgstr "Fel: Flaggan \"--pretty\" är ömsesidigt uteslutande med \"--terse\"." #: ../cli/src/nmcli.c:171 #: ../cli/src/nmcli.c:187 #, c-format -#| msgid "Error: %s argument is missing." msgid "Error: missing argument for '%s' option." msgstr "Fel: argument för flaggan \"%s\" saknas." #: ../cli/src/nmcli.c:180 #: ../cli/src/nmcli.c:196 #, c-format -#| msgid "Error: '%s' argument is missing." msgid "Error: '%s' is not valid argument for '%s' option." msgstr "Fel: \"%s\" är inte ett giltigt argument för flaggan \"%s\"." #: ../cli/src/nmcli.c:203 #, c-format -#| msgid "Error: '%s' argument is missing." msgid "Error: fields for '%s' options are missing." msgstr "Fel: fält för \"%s\"-flaggor saknas." @@ -1203,7 +1216,6 @@ msgstr "nmcli-verktyg, version %s\n" #: ../cli/src/nmcli.c:215 #, c-format -#| msgid "Option '%s' is unknown, try 'nmcli -help'." msgid "Error: Option '%s' is unknown, try 'nmcli -help'." msgstr "Fel: Flaggan \"%s\" är okänd, prova \"nmcli -help\"." @@ -1228,18 +1240,15 @@ msgstr "%d (hex-ascii-nyckel)" #: ../cli/src/settings.c:413 #, c-format -#| msgid "WEP 128-bit Passphrase" msgid "%d (104/128-bit passphrase)" msgstr "%d (104/128-bitars lösenfras)" #: ../cli/src/settings.c:416 #, c-format -#| msgid "(unknown)" msgid "%d (unknown)" msgstr "%d (okänt)" #: ../cli/src/settings.c:442 -#| msgid "(unknown)" msgid "0 (unknown)" msgstr "0 (okänt)" @@ -1701,7 +1710,6 @@ msgid "System policy prevents sharing connections via an open WiFi network" msgstr "Systemets policy förhindrar delning av anslutningar via ett öppet trådlöst nätverk" #: ../policy/org.freedesktop.NetworkManager.policy.in.h:1 -#| msgid "Wired network connection" msgid "Allow control of network connections" msgstr "Tillåt kontroll av nätverksanslutningar" @@ -1718,7 +1726,6 @@ msgid "Enable or disable mobile broadband devices" msgstr "Aktivera eller inaktivera mobila bredbandsenheter" #: ../policy/org.freedesktop.NetworkManager.policy.in.h:5 -#| msgid "Enable _Networking" msgid "Enable or disable system networking" msgstr "Aktivera eller inaktivera systemnätverk" @@ -1727,12 +1734,10 @@ msgid "Put NetworkManager to sleep or wake it up (should only be used by system msgstr "Försätt Nätverkshanterare i vänteläge eller återställ efter det (bör endast användas av systemets strömhantering)" #: ../policy/org.freedesktop.NetworkManager.policy.in.h:7 -#| msgid "System policy prevents modification of system settings" msgid "System policy prevents control of network connections" msgstr "Systemets policy förhindrar kontroll av nätverksanslutningar" #: ../policy/org.freedesktop.NetworkManager.policy.in.h:8 -#| msgid "System policy prevents sharing connections via an open WiFi network" msgid "System policy prevents enabling or disabling WiFi devices" msgstr "Systemets policy förhindrar aktivering eller inaktivering av WiFi-enheter" @@ -1741,7 +1746,6 @@ msgid "System policy prevents enabling or disabling mobile broadband devices" msgstr "Systemets policy förhindrar aktivering eller inaktivering av mobila bredbandsenheter" #: ../policy/org.freedesktop.NetworkManager.policy.in.h:10 -#| msgid "System policy prevents modification of system settings" msgid "System policy prevents enabling or disabling system networking" msgstr "Systemets policy förhindrar aktivering eller inaktivering av systemnätverk" @@ -1750,7 +1754,6 @@ msgid "System policy prevents putting NetworkManager to sleep or waking it up" msgstr "Systemets policy förhindrar att Nätverkshanterare försätts i vänteläge eller återställs efter det" #: ../policy/org.freedesktop.NetworkManager.policy.in.h:12 -#| msgid "System policy prevents modification of system settings" msgid "System policy prevents use of user-specific connections" msgstr "Systemets policy förhindrar användning av användarspecifika anslutningar" @@ -1772,7 +1775,6 @@ msgstr "kan inte ansluta till netlink för övervakning av länkstatus: %s" #: ../src/nm-netlink-monitor.c:265 #, c-format -#| msgid "unable to allocate netlink handle: %s" msgid "unable to enable netlink handle credential passing: %s" msgstr "kunde inte aktivera behörighetshantering för netlink-handtag: %s" @@ -1798,22 +1800,21 @@ msgstr "kan inte gå med i netlink-grupp: %s" msgid "error updating link cache: %s" msgstr "fel vid uppdatering av länkcache: %s" -#: ../src/main.c:502 +#: ../src/main.c:499 #, c-format msgid "Invalid option. Please use --help to see a list of valid options.\n" msgstr "Ogiltig flagga. Använd --help för att se en lista över giltiga flaggor.\n" -#: ../src/main.c:573 +#: ../src/main.c:570 #, c-format -#| msgid "Invalid option. Please use --help to see a list of valid options.\n" msgid "%s. Please use --help to see a list of valid options.\n" msgstr "%s. Använd --help för att se en lista över giltiga flaggor.\n" -#: ../src/dhcp-manager/nm-dhcp-dhclient.c:324 +#: ../src/dhcp-manager/nm-dhcp-dhclient.c:328 msgid "# Created by NetworkManager\n" msgstr "# Skapad av Nätverkshanterare\n" -#: ../src/dhcp-manager/nm-dhcp-dhclient.c:340 +#: ../src/dhcp-manager/nm-dhcp-dhclient.c:344 #, c-format msgid "" "# Merged from %s\n" @@ -1863,6 +1864,7 @@ msgid "Auto %s" msgstr "Automatisk %s" #: ../system-settings/plugins/ifcfg-rh/reader.c:3412 +#: ../system-settings/plugins/ifnet/connection_parser.c:49 msgid "System" msgstr "System" diff --git a/policy/org.freedesktop.NetworkManager.policy.in b/policy/org.freedesktop.NetworkManager.policy.in index af4b9a15b4..acdee8829c 100644 --- a/policy/org.freedesktop.NetworkManager.policy.in +++ b/policy/org.freedesktop.NetworkManager.policy.in @@ -45,6 +45,15 @@ </defaults> </action> + <action id="org.freedesktop.NetworkManager.enable-disable-wimax"> + <_description>Enable or disable WiMAX mobile broadband devices</_description> + <_message>System policy prevents enabling or disabling WiMAX mobile broadband devices</_message> + <defaults> + <allow_inactive>no</allow_inactive> + <allow_active>yes</allow_active> + </defaults> + </action> + <action id="org.freedesktop.NetworkManager.network-control"> <_description>Allow control of network connections</_description> <_message>System policy prevents control of network connections</_message> diff --git a/src/Makefile.am b/src/Makefile.am index 5f1b63c235..ce3c222c87 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,27 +10,34 @@ SUBDIRS= \ dnsmasq-manager \ modem-manager \ bluez-manager \ - settings \ - . \ - tests + settings -INCLUDES = -I${top_srcdir} \ - -I${top_srcdir}/include \ - -I${top_builddir}/marshallers \ +if WITH_WIMAX +SUBDIRS += wimax +endif + +SUBDIRS += . tests + +INCLUDES = -I${top_srcdir} \ + -I${top_srcdir}/include \ + -I${top_builddir}/marshallers \ -I${top_srcdir}/src/logging \ -I${top_srcdir}/src/dns-manager \ - -I${top_srcdir}/src/vpn-manager \ - -I${top_srcdir}/src/dhcp-manager \ - -I${top_srcdir}/src/ip6-manager \ - -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/src/dnsmasq-manager \ - -I${top_srcdir}/src/modem-manager \ + -I${top_srcdir}/src/vpn-manager \ + -I${top_srcdir}/src/dhcp-manager \ + -I${top_srcdir}/src/ip6-manager \ + -I${top_srcdir}/src/supplicant-manager \ + -I${top_srcdir}/src/dnsmasq-manager \ + -I${top_srcdir}/src/modem-manager \ -I$(top_srcdir)/src/bluez-manager \ -I$(top_srcdir)/src/settings \ -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/libnm-glib \ -I${top_srcdir}/callouts +if WITH_WIMAX +INCLUDES += -I$(top_srcdir)/src/wimax +endif + ########################################### # Test libraries ########################################### @@ -254,6 +261,12 @@ NetworkManager_CPPFLAGS = \ -DNMLOCALEDIR=\"$(datadir)/locale\" \ -DARP_DEBUG + +WIMAX_LIBS= +if WITH_WIMAX +WIMAX_LIBS += ./wimax/libwimax.la +endif + NetworkManager_LDADD = \ $(top_builddir)/marshallers/libmarshallers.la \ ./logging/libnm-logging.la \ @@ -267,6 +280,7 @@ NetworkManager_LDADD = \ ./modem-manager/libmodem-manager.la \ ./bluez-manager/libbluez-manager.la \ ./settings/libsettings.la \ + $(WIMAX_LIBS) \ ./backends/libnmbackend.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(DBUS_LIBS) \ diff --git a/src/backends/NetworkManagerGentoo.c b/src/backends/NetworkManagerGentoo.c index 8d9e68c59c..2854901a56 100644 --- a/src/backends/NetworkManagerGentoo.c +++ b/src/backends/NetworkManagerGentoo.c @@ -30,12 +30,22 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <gio/gio.h> #include "NetworkManagerGeneric.h" #include "nm-system.h" #include "NetworkManagerUtils.h" #include "nm-logging.h" +#define BUFFER_SIZE 512 + +static void openrc_start_lo_if_necessary() +{ + /* No need to run net.lo if it is already running */ + if (nm_spawn_process ("/etc/init.d/net.lo status") != 0) + nm_spawn_process ("/etc/init.d/net.lo start"); +} + /* * nm_system_enable_loopback * @@ -44,9 +54,42 @@ */ void nm_system_enable_loopback (void) { - /* No need to run net.lo if it is already running */ - if (nm_spawn_process ("/etc/init.d/net.lo status") != 0) - nm_spawn_process("/etc/init.d/net.lo start"); + GFile *file; + GFileInputStream *in; + gchar buffer[BUFFER_SIZE]; + gchar *comm, *readed, *tmp; + gssize r; + + file = g_file_new_for_path ("/proc/1/comm"); + in = g_file_read (file, NULL, NULL); + + /* If anything goes wrong trying to open /proc/1/comm, + we will assume OpenRC. */ + if (!in) { + openrc_start_lo_if_necessary (); + return; + } + + comm = g_strdup(""); + while ((r = g_input_stream_read (G_INPUT_STREAM(in), buffer, BUFFER_SIZE, NULL, NULL)) > 0) { + readed = g_strndup (buffer, r); + tmp = g_strconcat (comm, readed, NULL); + g_free (comm); + g_free (readed); + comm = tmp; + } + + if (g_strstr_len (comm, -1, "systemd")) { + /* We use the generic loopback enabler if using systemd. */ + nm_log_info (LOGD_CORE, "NetworkManager is running with systemd..."); + nm_generic_enable_loopback (); + } else { + /* OpenRC otherwise. */ + nm_log_info (LOGD_CORE, "NetworkManager is running with OpenRC..."); + openrc_start_lo_if_necessary(); + } + + g_free (comm); } /* diff --git a/src/dhcp-manager/Makefile.am b/src/dhcp-manager/Makefile.am index e29c6718a3..14ddde0bd2 100644 --- a/src/dhcp-manager/Makefile.am +++ b/src/dhcp-manager/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS=. tests + INCLUDES = \ -I${top_srcdir} \ -I${top_srcdir}/include \ @@ -6,15 +8,40 @@ INCLUDES = \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/src -noinst_LTLIBRARIES = libdhcp-manager.la +noinst_LTLIBRARIES = libdhcp-manager.la libdhcp-dhclient.la + +################## dhclient ################## + +libdhcp_dhclient_la_SOURCES = \ + nm-dhcp-dhclient-utils.h \ + nm-dhcp-dhclient-utils.c \ + nm-dhcp-dhclient.h \ + nm-dhcp-dhclient.c + +libdhcp_dhclient_la_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(GLIB_CFLAGS) \ + -DG_DISABLE_DEPRECATED \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DLOCALSTATEDIR=\"$(localstatedir)\" \ + -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ + -DDHCLIENT_V$(DHCLIENT_VERSION) + +libdhcp_dhclient_la_LIBADD = \ + $(top_builddir)/marshallers/libmarshallers.la \ + $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) + +################## main lib ################## libdhcp_manager_la_SOURCES = \ nm-dhcp-client.c \ nm-dhcp-client.h \ nm-dhcp-manager.c \ nm-dhcp-manager.h \ - nm-dhcp-dhclient.h \ - nm-dhcp-dhclient.c \ nm-dhcp-dhcpcd.h \ nm-dhcp-dhcpcd.c @@ -22,18 +49,15 @@ libdhcp_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ -DG_DISABLE_DEPRECATED \ - -DBINDIR=\"$(bindir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ -DLIBEXECDIR=\"$(libexecdir)\" \ -DLOCALSTATEDIR=\"$(localstatedir)\" \ -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ - -DDHCLIENT_V$(DHCLIENT_VERSION) \ -DDHCPCD_PATH=\"$(DHCPCD_PATH)\" libdhcp_manager_la_LIBADD = \ $(top_builddir)/marshallers/libmarshallers.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(builddir)/libdhcp-dhclient.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index 0c7f3d49b5..c4dfec64d7 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -136,10 +136,10 @@ watch_cleanup (NMDHCPClient *self) } } -static void -stop_process (GPid pid, const char *iface) +void +nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs) { - int i = 15; /* 3 seconds */ + int i = (timeout_secs ? timeout_secs : 3) * 5; /* default 3 seconds */ g_return_if_fail (pid > 0); @@ -156,11 +156,15 @@ stop_process (GPid pid, const char *iface) if (ret == -1) { /* Child already exited */ - if (errno == ECHILD) + if (errno == ECHILD) { + /* Was it really our child and it exited? */ + if (kill (pid, 0) < 0 && errno == ESRCH) + break; + } else { + /* Took too long; shoot it in the head */ + i = 0; break; - /* Took too long; shoot it in the head */ - i = 0; - break; + } } g_usleep (G_USEC_PER_SEC / 5); } @@ -179,7 +183,7 @@ stop_process (GPid pid, const char *iface) } static void -real_stop (NMDHCPClient *self) +real_stop (NMDHCPClient *self, gboolean release) { NMDHCPClientPrivate *priv; @@ -192,7 +196,7 @@ real_stop (NMDHCPClient *self) /* Clean up the watch handler since we're explicitly killing the daemon */ watch_cleanup (self); - stop_process (priv->pid, priv->iface); + nm_dhcp_client_stop_pid (priv->pid, priv->iface, 0); priv->info_only = FALSE; } @@ -372,7 +376,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) exe = proc_contents; if (!strcmp (exe, binary_name)) - stop_process ((GPid) tmp, NULL); + nm_dhcp_client_stop_pid ((GPid) tmp, NULL, 0); } } @@ -383,7 +387,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) } void -nm_dhcp_client_stop (NMDHCPClient *self) +nm_dhcp_client_stop (NMDHCPClient *self, gboolean release) { NMDHCPClientPrivate *priv; @@ -394,7 +398,7 @@ nm_dhcp_client_stop (NMDHCPClient *self) /* Kill the DHCP client */ if (!priv->dead) { - NM_DHCP_CLIENT_GET_CLASS (self)->stop (self); + NM_DHCP_CLIENT_GET_CLASS (self)->stop (self, release); priv->dead = TRUE; nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction, DHCP client pid %d", diff --git a/src/dhcp-manager/nm-dhcp-client.h b/src/dhcp-manager/nm-dhcp-client.h index f357170b9c..19c7365edc 100644 --- a/src/dhcp-manager/nm-dhcp-client.h +++ b/src/dhcp-manager/nm-dhcp-client.h @@ -76,18 +76,19 @@ typedef struct { /* Methods */ - GPid (*ip4_start) (NMDHCPClient *self, - NMSettingIP4Config *s_ip4, - guint8 *anycast_addr, - const char *hostname); + GPid (*ip4_start) (NMDHCPClient *self, + NMSettingIP4Config *s_ip4, + guint8 *anycast_addr, + const char *hostname); - GPid (*ip6_start) (NMDHCPClient *self, - NMSettingIP6Config *s_ip6, - guint8 *anycast_addr, - const char *hostname, - gboolean info_only); + GPid (*ip6_start) (NMDHCPClient *self, + NMSettingIP6Config *s_ip6, + guint8 *anycast_addr, + const char *hostname, + gboolean info_only); - void (*stop) (NMDHCPClient *self); + void (*stop) (NMDHCPClient *self, + gboolean release); /* Signals */ void (*state_changed) (NMDHCPClient *self, NMDHCPState state); @@ -116,7 +117,7 @@ gboolean nm_dhcp_client_start_ip6 (NMDHCPClient *self, const char *hostname, gboolean info_only); -void nm_dhcp_client_stop (NMDHCPClient *self); +void nm_dhcp_client_stop (NMDHCPClient *self, gboolean release); void nm_dhcp_client_new_options (NMDHCPClient *self, GHashTable *options, @@ -133,5 +134,7 @@ NMIP6Config *nm_dhcp_client_get_ip6_config (NMDHCPClient *self, gboolean test) /* Backend helpers */ void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name); +void nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs); + #endif /* NM_DHCP_CLIENT_H */ diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c new file mode 100644 index 0000000000..cc5255ab59 --- /dev/null +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c @@ -0,0 +1,217 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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. + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include <config.h> + +#include <glib.h> +#include <glib/gi18n.h> +#include <string.h> +#include <ctype.h> + +#include "nm-dhcp-dhclient-utils.h" + +#define CLIENTID_TAG "send dhcp-client-identifier" +#define CLIENTID_FORMAT CLIENTID_TAG " \"%s\"; # added by NetworkManager" +#define CLIENTID_FORMAT_OCTETS CLIENTID_TAG " %s; # added by NetworkManager" + +#define HOSTNAME_TAG "send host-name" +#define HOSTNAME_FORMAT HOSTNAME_TAG " \"%s\"; # added by NetworkManager" + +#define ALSOREQ_TAG "also request " + +static void +add_also_request (GPtrArray *array, const char *item) +{ + int i; + + for (i = 0; i < array->len; i++) { + if (!strcmp (g_ptr_array_index (array, i), item)) + return; + } + g_ptr_array_add (array, g_strdup (item)); +} + +char * +nm_dhcp_dhclient_create_config (const char *interface, + NMSettingIP4Config *s_ip4, + guint8 *anycast_addr, + const char *hostname, + const char *orig_path, + const char *orig_contents) +{ + GString *new_contents; + GPtrArray *alsoreq; + int i; + + new_contents = g_string_new (_("# Created by NetworkManager\n")); + alsoreq = g_ptr_array_sized_new (5); + + if (orig_contents) { + char **lines, **line; + gboolean in_alsoreq = FALSE; + + g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); + + lines = g_strsplit_set (orig_contents, "\n\r", 0); + for (line = lines; lines && *line; line++) { + char *p = *line; + + if (!strlen (g_strstrip (p))) + continue; + + /* Override config file "dhcp-client-id" and use one from the + * connection. + */ + if ( s_ip4 + && nm_setting_ip4_config_get_dhcp_client_id (s_ip4) + && !strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) + continue; + + /* Override config file hostname and use one from the connection */ + if (hostname && !strncmp (p, HOSTNAME_TAG, strlen (HOSTNAME_TAG))) + continue; + + /* Check for "also require" */ + if (!strncmp (p, ALSOREQ_TAG, strlen (ALSOREQ_TAG))) { + in_alsoreq = TRUE; + p += strlen (ALSOREQ_TAG); + } + + if (in_alsoreq) { + char **areq, **aiter; + + /* Grab each 'also require' option and save for later */ + areq = g_strsplit_set (p, "\t ,", -1); + for (aiter = areq; aiter && *aiter; aiter++) { + if (!strlen (g_strstrip (*aiter))) + continue; + + if (*aiter[0] == ';') { + /* all done */ + in_alsoreq = FALSE; + break; + } + + if (!isalnum ((*aiter)[0])) + continue; + + if ((*aiter)[strlen (*aiter) - 1] == ';') { + /* Remove the EOL marker */ + (*aiter)[strlen (*aiter) - 1] = '\0'; + in_alsoreq = FALSE; + } + + add_also_request (alsoreq, *aiter); + } + + if (areq) + g_strfreev (areq); + + continue; + } + + /* Existing configuration line is OK, add it to new configuration */ + g_string_append (new_contents, *line); + g_string_append_c (new_contents, '\n'); + } + + if (lines) + g_strfreev (lines); + } else + g_string_append_c (new_contents, '\n'); + + /* Add NM options from connection */ + if (s_ip4) { + const char *tmp; + gboolean added = FALSE; + + tmp = nm_setting_ip4_config_get_dhcp_client_id (s_ip4); + if (tmp) { + gboolean is_octets = TRUE; + const char *p = tmp; + + while (*p) { + if (!isxdigit (*p) && (*p != ':')) { + is_octets = FALSE; + break; + } + p++; + } + + /* If the client ID is just hex digits and : then don't use quotes, + * because dhclient expects either a quoted ASCII string, or a byte + * array formated as hex octets separated by : + */ + if (is_octets) + g_string_append_printf (new_contents, CLIENTID_FORMAT_OCTETS "\n", tmp); + else + g_string_append_printf (new_contents, CLIENTID_FORMAT "\n", tmp); + added = TRUE; + } + + if (hostname) { + g_string_append_printf (new_contents, HOSTNAME_FORMAT "\n", hostname); + added = TRUE; + } + + if (added) + g_string_append_c (new_contents, '\n'); + } + + /* Define options for classless static routes */ + g_string_append (new_contents, + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"); + g_string_append (new_contents, + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"); + /* Web Proxy Auto-Discovery option (bgo #368423) */ + g_string_append (new_contents, "option wpad code 252 = string;\n"); + + g_string_append_c (new_contents, '\n'); + + /* Everything we want to request from the DHCP server */ + add_also_request (alsoreq, "rfc3442-classless-static-routes"); + add_also_request (alsoreq, "ms-classless-static-routes"); + add_also_request (alsoreq, "wpad"); + add_also_request (alsoreq, "ntp-servers"); + + /* And add it to the dhclient configuration */ + for (i = 0; i < alsoreq->len; i++) { + char *t = g_ptr_array_index (alsoreq, i); + + g_string_append_printf (new_contents, "also request %s;\n", t); + g_free (t); + } + g_ptr_array_free (alsoreq, TRUE); + + g_string_append_c (new_contents, '\n'); + + if (anycast_addr) { + g_string_append_printf (new_contents, "interface \"%s\" {\n" + " initial-interval 1; \n" + " anycast-mac ethernet %02x:%02x:%02x:%02x:%02x:%02x;\n" + "}\n", + interface, + anycast_addr[0], anycast_addr[1], + anycast_addr[2], anycast_addr[3], + anycast_addr[4], anycast_addr[5]); + } + + return g_string_free (new_contents, FALSE); +} + diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.h b/src/dhcp-manager/nm-dhcp-dhclient-utils.h new file mode 100644 index 0000000000..77def55182 --- /dev/null +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* 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, 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. + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef NM_DHCP_DHCLIENT_UTILS_H +#define NM_DHCP_DHCLIENT_UTILS_H + +#include <glib.h> +#include <glib-object.h> + +#include <nm-setting-ip4-config.h> + +char *nm_dhcp_dhclient_create_config (const char *interface, + NMSettingIP4Config *s_ip4, + guint8 *anycast_addr, + const char *hostname, + const char *orig_path, + const char *orig_contents); + +#endif /* NM_DHCP_DHCLIENT_UTILS_H */ + diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index d8781524e9..75684459f6 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -39,6 +39,7 @@ #include "nm-dhcp-dhclient.h" #include "nm-utils.h" #include "nm-logging.h" +#include "nm-dhcp-dhclient-utils.h" G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) @@ -302,12 +303,6 @@ out: } -#define DHCP_CLIENT_ID_TAG "send dhcp-client-identifier" -#define DHCP_CLIENT_ID_FORMAT DHCP_CLIENT_ID_TAG " \"%s\"; # added by NetworkManager" -#define DHCP_CLIENT_ID_FORMAT_OCTETS DHCP_CLIENT_ID_TAG " %s; # added by NetworkManager" - -#define DHCP_HOSTNAME_TAG "send host-name" -#define DHCP_HOSTNAME_FORMAT DHCP_HOSTNAME_TAG " \"%s\"; # added by NetworkManager" static gboolean merge_dhclient_config (const char *iface, @@ -318,105 +313,27 @@ merge_dhclient_config (const char *iface, const char *orig_path, GError **error) { - GString *new_contents; - char *orig_contents = NULL; + char *orig = NULL, *new; gboolean success = FALSE; g_return_val_if_fail (iface != NULL, FALSE); g_return_val_if_fail (conf_file != NULL, FALSE); - new_contents = g_string_new (_("# Created by NetworkManager\n")); - if (g_file_test (orig_path, G_FILE_TEST_EXISTS)) { GError *read_error = NULL; - if (!g_file_get_contents (orig_path, &orig_contents, NULL, &read_error)) { + if (!g_file_get_contents (orig_path, &orig, NULL, &read_error)) { nm_log_warn (LOGD_DHCP, "(%s): error reading dhclient configuration %s: %s", iface, orig_path, read_error->message); g_error_free (read_error); } } - /* Add existing options, if any, but ignore stuff NM will replace. */ - if (orig_contents) { - char **lines = NULL, **line; - - g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); - - lines = g_strsplit_set (orig_contents, "\n\r", 0); - for (line = lines; lines && *line; line++) { - gboolean ignore = FALSE; - - if (!strlen (g_strstrip (*line))) - continue; - - if ( s_ip4 - && nm_setting_ip4_config_get_dhcp_client_id (s_ip4) - && !strncmp (*line, DHCP_CLIENT_ID_TAG, strlen (DHCP_CLIENT_ID_TAG))) - ignore = TRUE; - - if ( s_ip4 - && hostname - && !strncmp (*line, DHCP_HOSTNAME_TAG, strlen (DHCP_HOSTNAME_TAG))) - ignore = TRUE; - - if (!ignore) { - g_string_append (new_contents, *line); - g_string_append_c (new_contents, '\n'); - } - } - - if (lines) - g_strfreev (lines); - g_free (orig_contents); - } else - g_string_append_c (new_contents, '\n'); - - /* Add NM options from connection */ - if (s_ip4) { - const char *tmp; - - tmp = nm_setting_ip4_config_get_dhcp_client_id (s_ip4); - if (tmp) { - gboolean is_octets = TRUE; - const char *p = tmp; - - while (*p) { - if (!isxdigit (*p) && (*p != ':')) { - is_octets = FALSE; - break; - } - p++; - } - - /* If the client ID is just hex digits and : then don't use quotes, - * because dhclient expects either a quoted ASCII string, or a byte - * array formated as hex octets separated by : - */ - if (is_octets) - g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT_OCTETS "\n", tmp); - else - g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT "\n", tmp); - } - - if (hostname) - g_string_append_printf (new_contents, DHCP_HOSTNAME_FORMAT "\n", hostname); - } - - if (anycast_addr) { - g_string_append_printf (new_contents, "interface \"%s\" {\n" - " initial-interval 1; \n" - " anycast-mac ethernet %02x:%02x:%02x:%02x:%02x:%02x;\n" - "}\n", - iface, - anycast_addr[0], anycast_addr[1], - anycast_addr[2], anycast_addr[3], - anycast_addr[4], anycast_addr[5]); - } - - success = g_file_set_contents (conf_file, new_contents->str, -1, error); + new = nm_dhcp_dhclient_create_config (iface, s_ip4, anycast_addr, hostname, orig_path, orig); + g_assert (new); + success = g_file_set_contents (conf_file, new, -1, error); + g_free (new); - g_string_free (new_contents, TRUE); return success; } @@ -494,15 +411,15 @@ dhclient_child_setup (gpointer user_data G_GNUC_UNUSED) static GPid dhclient_start (NMDHCPClient *client, - const char *ip_opt, - const char *mode_opt) + const char *mode_opt, + gboolean release) { NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); GPtrArray *argv = NULL; GPid pid = -1; GError *error = NULL; const char *iface, *uuid; - char *binary_name, *cmd_str; + char *binary_name, *cmd_str, *pid_file = NULL; gboolean ipv6; guint log_domain; @@ -519,28 +436,33 @@ dhclient_start (NMDHCPClient *client, nm_log_warn (log_domain, "(%s): ISC dhcp3 does not support IPv6", iface); return -1; } -#else - g_return_val_if_fail (ip_opt != NULL, -1); #endif - priv->pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid", - ipv6 ? "6" : "", - iface); - if (!priv->pid_file) { - nm_log_warn (log_domain, "(%s): not enough memory for dhcpcd options.", iface); + if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) { + nm_log_warn (log_domain, "%s does not exist.", priv->path); return -1; } - if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) { - nm_log_warn (log_domain, "%s does not exist.", priv->path); + pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid", + ipv6 ? "6" : "", + iface); + if (!pid_file) { + nm_log_warn (log_domain, "(%s): not enough memory for dhcpcd options.", iface); return -1; } /* Kill any existing dhclient from the pidfile */ binary_name = g_path_get_basename (priv->path); - nm_dhcp_client_stop_existing (priv->pid_file, binary_name); + nm_dhcp_client_stop_existing (pid_file, binary_name); g_free (binary_name); + if (release) { + /* release doesn't use the pidfile after killing an old client */ + g_free (pid_file); + pid_file = NULL; + } + + g_free (priv->lease_file); priv->lease_file = get_leasefile_for_iface (iface, uuid, ipv6); if (!priv->lease_file) { nm_log_warn (log_domain, "(%s): not enough memory for dhclient options.", iface); @@ -552,17 +474,26 @@ dhclient_start (NMDHCPClient *client, g_ptr_array_add (argv, (gpointer) "-d"); + if (release) + g_ptr_array_add (argv, (gpointer) "-r"); + #if !defined(DHCLIENT_V3) - g_ptr_array_add (argv, (gpointer) ip_opt); - if (mode_opt) - g_ptr_array_add (argv, (gpointer) mode_opt); + if (ipv6) { + g_ptr_array_add (argv, (gpointer) "-6"); + if (mode_opt) + g_ptr_array_add (argv, (gpointer) mode_opt); + } else { + g_ptr_array_add (argv, (gpointer) "-4"); + } #endif g_ptr_array_add (argv, (gpointer) "-sf"); /* Set script file */ g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH ); - g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */ - g_ptr_array_add (argv, (gpointer) priv->pid_file); + if (pid_file) { + g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */ + g_ptr_array_add (argv, (gpointer) pid_file); + } g_ptr_array_add (argv, (gpointer) "-lf"); /* Set lease file */ g_ptr_array_add (argv, (gpointer) priv->lease_file); @@ -584,8 +515,10 @@ dhclient_start (NMDHCPClient *client, nm_log_warn (log_domain, "dhclient failed to start: '%s'", error->message); g_error_free (error); pid = -1; - } else + } else { nm_log_info (log_domain, "dhclient started with pid %d", pid); + priv->pid_file = pid_file; + } g_ptr_array_free (argv, TRUE); return pid; @@ -608,7 +541,7 @@ real_ip4_start (NMDHCPClient *client, return -1; } - return dhclient_start (client, "-4", NULL); + return dhclient_start (client, NULL, FALSE); } static GPid @@ -618,21 +551,34 @@ real_ip6_start (NMDHCPClient *client, const char *hostname, gboolean info_only) { - return dhclient_start (client, "-6", info_only ? "-S" : "-N"); + return dhclient_start (client, info_only ? "-S" : "-N", FALSE); } static void -real_stop (NMDHCPClient *client) +real_stop (NMDHCPClient *client, gboolean release) { NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); /* Chain up to parent */ - NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client); + NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client, release); if (priv->conf_file) remove (priv->conf_file); - if (priv->pid_file) + if (priv->pid_file) { remove (priv->pid_file); + g_free (priv->pid_file); + priv->pid_file = NULL; + } + + if (release) { + GPid rpid; + + rpid = dhclient_start (client, NULL, TRUE); + if (rpid > 0) { + /* Wait a few seconds for the release to happen */ + nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client), 5); + } + } } /***************************************************/ diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index 378a97b611..237661fe47 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -128,6 +128,8 @@ real_ip4_start (NMDHCPClient *client, g_ptr_array_add (argv, (gpointer) "-L"); /* Disable built-in IPv4LL since we use avahi-autoipd */ + g_ptr_array_add (argv, (gpointer) "-G"); /* Let NM handle routing */ + g_ptr_array_add (argv, (gpointer) "-c"); /* Set script file */ g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH ); @@ -168,15 +170,17 @@ real_ip6_start (NMDHCPClient *client, } static void -real_stop (NMDHCPClient *client) +real_stop (NMDHCPClient *client, gboolean release) { NMDHCPDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client); /* Chain up to parent */ - NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client); + NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client, release); if (priv->pid_file) remove (priv->pid_file); + + /* FIXME: implement release... */ } /***************************************************/ diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index a1e3e5e24d..d3c064199c 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -429,7 +429,7 @@ client_start (NMDHCPManager *self, /* Kill any old client instance */ client = get_client_for_iface (self, iface, ipv6); if (client) { - nm_dhcp_client_stop (client); + nm_dhcp_client_stop (client, FALSE); remove_client (self, client); } diff --git a/src/dhcp-manager/tests/Makefile.am b/src/dhcp-manager/tests/Makefile.am new file mode 100644 index 0000000000..b075fd683a --- /dev/null +++ b/src/dhcp-manager/tests/Makefile.am @@ -0,0 +1,28 @@ +INCLUDES = \ + -I$(top_srcdir)/include \ + -I${top_srcdir}/libnm-util \ + -I$(top_srcdir)/src/dhcp-manager + +noinst_PROGRAMS = test-dhcp-dhclient + +####### policy /etc/hosts test ####### + +test_dhcp_dhclient_SOURCES = \ + test-dhcp-dhclient.c + +test_dhcp_dhclient_CPPFLAGS = \ + $(GLIB_CFLAGS) + +test_dhcp_dhclient_LDADD = \ + -ldl \ + $(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) + +if WITH_TESTS + +check-local: test-dhcp-dhclient + $(abs_builddir)/test-dhcp-dhclient + +endif + diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c new file mode 100644 index 0000000000..c1cd6f80c4 --- /dev/null +++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c @@ -0,0 +1,249 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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. + * + * Copyright (C) 2010 Red Hat, Inc. + * + */ + +#include <glib.h> +#include <string.h> + +#include "nm-dhcp-dhclient-utils.h" +#include "nm-utils.h" + +#define DEBUG 0 + +static void +test_config (const char *orig, + const char *expected, + const char *hostname, + const char *dhcp_client_id, + const char *iface, + guint8 *anycast_addr) +{ + NMSettingIP4Config *s_ip4; + char *new; + + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, dhcp_client_id, NULL); + + new = nm_dhcp_dhclient_create_config (iface, + s_ip4, + anycast_addr, + hostname, + "/path/to/dhclient.conf", + orig); + g_assert (new != NULL); + +#if DEBUG + g_message ("\n- NEW ---------------------------------\n" + "%s" + "+ EXPECTED ++++++++++++++++++++++++++++++\n" + "%s" + "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + new, expected); +#endif + g_assert (strlen (new) == strlen (expected)); + g_assert (strcmp (new, expected) == 0); + g_free (new); +} + +/*******************************************/ + +static const char *orig_missing_expected = \ + "# Created by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_orig_missing (void) +{ + test_config (NULL, orig_missing_expected, + NULL, + NULL, + "eth0", + NULL); +} + +/*******************************************/ + +static const char *override_client_id_orig = \ + "send dhcp-client-identifier 00:30:04:20:7A:08;\n"; + +static const char *override_client_id_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send dhcp-client-identifier 11:22:33:44:55:66; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_override_client_id (void) +{ + test_config (override_client_id_orig, override_client_id_expected, + NULL, + "11:22:33:44:55:66", + "eth0", + NULL); +} + +/*******************************************/ + +static const char *override_hostname_orig = \ + "send host-name \"foobar\";\n"; + +static const char *override_hostname_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send host-name \"blahblah\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_override_hostname (void) +{ + test_config (override_hostname_orig, override_hostname_expected, + "blahblah", + NULL, + "eth0", + NULL); +} + +/*******************************************/ + +static const char *existing_alsoreq_orig = \ + "also request something;\n" + "also request another-thing;\n" + ; + +static const char *existing_alsoreq_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request something;\n" + "also request another-thing;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_existing_alsoreq (void) +{ + test_config (existing_alsoreq_orig, existing_alsoreq_expected, + NULL, + NULL, + "eth0", + NULL); +} + +/*******************************************/ + +static const char *existing_multiline_alsoreq_orig = \ + "also request something another-thing yet-another-thing\n" + " foobar baz blah;\n" + ; + +static const char *existing_multiline_alsoreq_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request something;\n" + "also request another-thing;\n" + "also request yet-another-thing;\n" + "also request foobar;\n" + "also request baz;\n" + "also request blah;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_existing_multiline_alsoreq (void) +{ + test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected, + NULL, + NULL, + "eth0", + NULL); +} + +/*******************************************/ + +#if GLIB_CHECK_VERSION(2,25,12) +typedef GTestFixtureFunc TCFunc; +#else +typedef void (*TCFunc)(void); +#endif + +#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL) + +int main (int argc, char **argv) +{ + GTestSuite *suite; + + g_test_init (&argc, &argv, NULL); + + g_type_init (); + + suite = g_test_get_root (); + + g_test_suite_add (suite, TESTCASE (test_orig_missing, NULL)); + g_test_suite_add (suite, TESTCASE (test_override_client_id, NULL)); + g_test_suite_add (suite, TESTCASE (test_override_hostname, NULL)); + g_test_suite_add (suite, TESTCASE (test_existing_alsoreq, NULL)); + g_test_suite_add (suite, TESTCASE (test_existing_multiline_alsoreq, NULL)); + + return g_test_run (); +} + diff --git a/src/dns-manager/Makefile.am b/src/dns-manager/Makefile.am index 1ffe62dcf0..7b5fc4f847 100644 --- a/src/dns-manager/Makefile.am +++ b/src/dns-manager/Makefile.am @@ -14,7 +14,9 @@ libdns_manager_la_SOURCES = \ nm-dns-dnsmasq.h \ nm-dns-dnsmasq.c \ nm-dns-bind.h \ - nm-dns-bind.c + nm-dns-bind.c \ + nm-dns-utils.h \ + nm-dns-utils.c libdns_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 41c8e2a642..9cc019780b 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -33,6 +33,7 @@ #include "nm-logging.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" +#include "nm-dns-utils.h" G_DEFINE_TYPE (NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN) @@ -75,9 +76,11 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) gboolean added = FALSE; if (split) { + char **domains, **iter; + /* FIXME: it appears that dnsmasq can only handle one nameserver - * per domain (at the manpage seems to indicate that) so only use - * the first nameserver here. + * per domain (and the manpage says this too) so only use the first + * nameserver here. */ addr.s_addr = nm_ip4_config_get_nameserver (ip4, 0); memset (&buf[0], 0, sizeof (buf)); @@ -103,6 +106,17 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) added = TRUE; } } + + /* Ensure reverse-DNS works by directing queries for in-addr.arpa + * domains to the split domain's nameserver. + */ + domains = nm_dns_utils_get_ip4_rdns_domains (ip4); + if (domains) { + for (iter = domains; iter && *iter; iter++) + g_string_append_printf (str, "server=/%s/%s\n", *iter, buf); + g_strfreev (domains); + added = TRUE; + } } /* If no searches or domains, just add the namservers */ @@ -216,7 +230,7 @@ update (NMDnsPlugin *plugin, } /* Now add interface configs without split DNS */ - for (iter = (GSList *) dev_configs; iter;iter = g_slist_next (iter)) { + for (iter = (GSList *) dev_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) @@ -224,7 +238,7 @@ update (NMDnsPlugin *plugin, } /* And any other random configs */ - for (iter = (GSList *) other_configs; iter;iter = g_slist_next (iter)) { + for (iter = (GSList *) other_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 7a6fbbc9d9..b0cdcc267d 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -583,6 +583,7 @@ update_dns (NMDnsManager *self, rc.nameservers = g_ptr_array_new (); rc.domain = NULL; rc.searches = g_ptr_array_new (); + rc.nis_domain = NULL; rc.nis_servers = g_ptr_array_new (); if (priv->ip4_vpn_config) diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c new file mode 100644 index 0000000000..615adfd151 --- /dev/null +++ b/src/dns-manager/nm-dns-utils.c @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* 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, 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. + * + * Copyright (C) 2010 Red Hat, Inc. + * + */ + +#include <arpa/inet.h> +#include <string.h> + +#include "nm-dns-utils.h" +#include "nm-utils.h" + +static void +add_ip4_to_rdns_array (guint32 ip, GPtrArray *domains) /* network byte order */ +{ + guint32 defprefix; + guchar *p; + char *str = NULL; + int i; + + defprefix = nm_utils_ip4_get_default_prefix (ip); + + /* Convert to host byte order, mask the host bits, and convert back */ + ip = ntohl (ip); + ip &= 0xFFFFFFFF << (32 - defprefix); + ip = htonl (ip); + p = (guchar *) &ip; + + if (defprefix == 8) + str = g_strdup_printf ("%u.in-addr.arpa", p[0] & 0xFF); + else if (defprefix == 16) + str = g_strdup_printf ("%u.%u.in-addr.arpa", p[1] & 0xFF, p[0] & 0xFF); + else if (defprefix == 24) + str = g_strdup_printf ("%u.%u.%u.in-addr.arpa", p[2] & 0xFF, p[1] & 0xFF, p[0] & 0xFF); + + g_return_if_fail (str != NULL); + + /* Suppress duplicates */ + for (i = 0; i < domains->len; i++) { + if (strcmp (str, g_ptr_array_index (domains, i)) == 0) + break; + } + + if (i == domains->len) + g_ptr_array_add (domains, str); + else + g_free (str); +} + +char ** +nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4) +{ + GPtrArray *domains = NULL; + int i; + + g_return_val_if_fail (ip4 != NULL, NULL); + + domains = g_ptr_array_sized_new (5); + + /* To calculate the reverse DNS domains for this IP4 config, we take + * all the IP addresses and routes in the config, calculate the network + * portion, and convert that to classful, and use the network bits for + * the final domain. FIXME: better handle classless routing, which might + * require us to add multiple domains for each actual network prefix to + * cover all the separate networks in that block. + */ + + for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) { + NMIP4Address *addr = nm_ip4_config_get_address (ip4, i); + + add_ip4_to_rdns_array (nm_ip4_address_get_address (addr), domains); + } + + for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) { + NMIP4Route *route = nm_ip4_config_get_route (ip4, i); + + add_ip4_to_rdns_array (nm_ip4_route_get_dest (route), domains); + } + + /* Terminating NULL so we can use g_strfreev() to free it */ + g_ptr_array_add (domains, NULL); + + /* Free the array and return NULL if the only element was the ending NULL */ + return (char **) g_ptr_array_free (domains, (domains->len == 1)); +} + diff --git a/src/dns-manager/nm-dns-utils.h b/src/dns-manager/nm-dns-utils.h new file mode 100644 index 0000000000..daa6711cce --- /dev/null +++ b/src/dns-manager/nm-dns-utils.h @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* 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, 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. + * + * Copyright (C) 2010 Red Hat, Inc. + * + */ + +#ifndef NM_DNS_UTILS_H +#define NM_DNS_UTILS_H + +#include "nm-ip4-config.h" + +char **nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4); + +#endif /* NM_DNS_UTILS_H */ + diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index f6f6127ce7..ea93f02c02 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -76,6 +76,11 @@ typedef struct { time_t expires; } NMIP6RDNSS; +typedef struct { + char domain[256]; + time_t expires; +} NMIP6DNSSL; + /******************************************************************/ typedef struct { @@ -97,6 +102,9 @@ typedef struct { GArray *rdnss_servers; guint rdnss_timeout_id; + GArray *dnssl_domains; + guint dnssl_timeout_id; + guint ip6flags_poll_id; guint32 ra_flags; @@ -122,6 +130,10 @@ nm_ip6_device_destroy (NMIP6Device *device) g_array_free (device->rdnss_servers, TRUE); if (device->rdnss_timeout_id) g_source_remove (device->rdnss_timeout_id); + if (device->dnssl_domains) + g_array_free (device->dnssl_domains, TRUE); + if (device->dnssl_timeout_id) + g_source_remove (device->dnssl_timeout_id); if (device->ip6flags_poll_id) g_source_remove (device->ip6flags_poll_id); @@ -155,6 +167,8 @@ nm_ip6_device_new (NMIP6Manager *manager, int ifindex) device->rdnss_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); + device->dnssl_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL)); + g_hash_table_replace (priv->devices, GINT_TO_POINTER (device->ifindex), device); /* and the original value of IPv6 enable/disable */ @@ -285,7 +299,7 @@ set_rdnss_timeout (NMIP6Device *device) nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided nameserver %s", device->iface, buf); } - g_array_remove_index_fast (device->rdnss_servers, i--); + g_array_remove_index (device->rdnss_servers, i--); continue; } @@ -300,6 +314,61 @@ set_rdnss_timeout (NMIP6Device *device) } } +static void set_dnssl_timeout (NMIP6Device *device); + +static gboolean +dnssl_expired (gpointer user_data) +{ + NMIP6Device *device = user_data; + CallbackInfo info = { device, IP6_DHCP_OPT_NONE }; + + nm_log_dbg (LOGD_IP6, "(%s): IPv6 DNSSL information expired", device->iface); + + set_dnssl_timeout (device); + emit_config_changed (&info); + return FALSE; +} + +static void +set_dnssl_timeout (NMIP6Device *device) +{ + time_t expires = 0, now = time (NULL); + NMIP6DNSSL *dnssl; + int i; + + if (device->dnssl_timeout_id) { + g_source_remove (device->dnssl_timeout_id); + device->dnssl_timeout_id = 0; + } + + /* Find the soonest expiration time. */ + for (i = 0; i < device->dnssl_domains->len; i++) { + dnssl = &g_array_index (device->dnssl_domains, NMIP6DNSSL, i); + if (dnssl->expires == 0) + continue; + + /* If the entry has already expired, remove it; the "+ 1" is + * because g_timeout_add_seconds() might fudge the timing a + * bit. + */ + if (dnssl->expires <= now + 1) { + nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided domain %s", + device->iface, dnssl->domain); + g_array_remove_index (device->dnssl_domains, i--); + continue; + } + + if (!expires || dnssl->expires < expires) + expires = dnssl->expires; + } + + if (expires) { + device->dnssl_timeout_id = g_timeout_add_seconds (expires - now, + dnssl_expired, + device); + } +} + static CallbackInfo * callback_info_new (NMIP6Device *device, guint dhcp_opts, gboolean success) { @@ -569,13 +638,258 @@ process_prefix (NMIP6Manager *manager, struct nl_msg *msg) */ #define ND_OPT_RDNSS 25 +#define ND_OPT_DNSSL 31 + struct nd_opt_rdnss { uint8_t nd_opt_rdnss_type; uint8_t nd_opt_rdnss_len; uint16_t nd_opt_rdnss_reserved1; uint32_t nd_opt_rdnss_lifetime; /* followed by one or more IPv6 addresses */ -}; +} __attribute__ ((packed)); + +struct nd_opt_dnssl { + uint8_t nd_opt_dnssl_type; + uint8_t nd_opt_dnssl_len; + uint16_t nd_opt_dnssl_reserved1; + uint32_t nd_opt_dnssl_lifetime; + /* followed by one or more suffixes */ +} __attribute__ ((packed)); + +static gboolean +process_nduseropt_rdnss (NMIP6Device *device, struct nd_opt_hdr *opt) +{ + size_t opt_len; + struct nd_opt_rdnss *rdnss_opt; + time_t now = time (NULL); + struct in6_addr *addr; + GArray *new_servers; + NMIP6RDNSS server, *cur_server; + gboolean changed = FALSE; + guint i; + + opt_len = opt->nd_opt_len; + + if (opt_len < 3 || (opt_len & 1) == 0) + return FALSE; + + rdnss_opt = (struct nd_opt_rdnss *) opt; + + new_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); + + /* Pad the DNS server expiry somewhat to give a bit of slack in cases + * where one RA gets lost or something (which can happen on unreliable + * links like WiFi where certain types of frames are not retransmitted). + * Note that 0 has special meaning and is therefore not adjusted. + */ + server.expires = ntohl (rdnss_opt->nd_opt_rdnss_lifetime); + if (server.expires > 0) + server.expires += now + 10; + + for (addr = (struct in6_addr *) (rdnss_opt + 1); opt_len >= 2; addr++, opt_len -= 2) { + char buf[INET6_ADDRSTRLEN + 1]; + + if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf))) + strcpy(buf, "[invalid]"); + + for (i = 0; i < device->rdnss_servers->len; i++) { + cur_server = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i)); + + if (!IN6_ARE_ADDR_EQUAL (addr, &cur_server->addr)) + continue; + + cur_server->expires = server.expires; + + if (server.expires > 0) { + nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided nameserver %s (expires in %d seconds)", + device->iface, buf, + server.expires - now); + break; + } + + nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided nameserver %s on router request", + device->iface, buf); + + g_array_remove_index (device->rdnss_servers, i); + changed = TRUE; + break; + } + + if (server.expires == 0) + continue; + if (i < device->rdnss_servers->len) + continue; + + nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)", + device->iface, buf, server.expires - now); + + server.addr = *addr; + g_array_append_val (new_servers, server); + } + + /* New servers must be added in the order they are listed in the + * RA option and before any existing servers. + * + * Note: This is the place to remove servers if we want to cap the + * number of resolvers. The RFC states that the one to expire + * first of the existing servers should be removed. + */ + if (new_servers->len) { + g_array_prepend_vals (device->rdnss_servers, + new_servers->data, new_servers->len); + changed = TRUE; + } + + g_array_free (new_servers, TRUE); + + /* Timeouts may have changed even if IPs didn't */ + set_rdnss_timeout (device); + + return changed; +} + +static const char * +parse_dnssl_domain (const unsigned char *buffer, size_t maxlen) +{ + static char domain[256]; + size_t label_len; + + domain[0] = '\0'; + + while (maxlen > 0) { + label_len = *buffer; + buffer++; + maxlen--; + + if (label_len == 0) + return domain; + + if (label_len > maxlen) + return NULL; + if ((sizeof (domain) - strlen (domain)) < (label_len + 2)) + return NULL; + + if (domain[0] != '\0') + strcat (domain, "."); + strncat (domain, (const char *)buffer, label_len); + buffer += label_len; + maxlen -= label_len; + } + + return NULL; +} + +static gboolean +process_nduseropt_dnssl (NMIP6Device *device, struct nd_opt_hdr *opt) +{ + size_t opt_len; + struct nd_opt_dnssl *dnssl_opt; + unsigned char *opt_ptr; + time_t now = time (NULL); + GArray *new_domains; + NMIP6DNSSL domain, *cur_domain; + gboolean changed; + guint i; + + opt_len = opt->nd_opt_len; + + if (opt_len < 2) + return FALSE; + + dnssl_opt = (struct nd_opt_dnssl *) opt; + + opt_ptr = (unsigned char *)(dnssl_opt + 1); + opt_len = (opt_len - 1) * 8; /* prefer bytes for later handling */ + + new_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL)); + + changed = FALSE; + + /* Pad the DNS server expiry somewhat to give a bit of slack in cases + * where one RA gets lost or something (which can happen on unreliable + * links like wifi where certain types of frames are not retransmitted). + * Note that 0 has special meaning and is therefore not adjusted. + */ + domain.expires = ntohl (dnssl_opt->nd_opt_dnssl_lifetime); + if (domain.expires > 0) + domain.expires += now + 10; + + while (opt_len) { + const char *domain_str; + + domain_str = parse_dnssl_domain (opt_ptr, opt_len); + if (domain_str == NULL) { + nm_log_dbg (LOGD_IP6, "(%s): invalid DNSSL option, parsing aborted", + device->iface); + break; + } + + /* The DNSSL encoding of domains happen to occupy the same size + * as the length of the resulting string, including terminating + * null. */ + opt_ptr += strlen (domain_str) + 1; + opt_len -= strlen (domain_str) + 1; + + /* Ignore empty domains. They're probably just padding... */ + if (domain_str[0] == '\0') + continue; + + for (i = 0; i < device->dnssl_domains->len; i++) { + cur_domain = &(g_array_index (device->dnssl_domains, NMIP6DNSSL, i)); + + if (strcmp (domain_str, cur_domain->domain) != 0) + continue; + + cur_domain->expires = domain.expires; + + if (domain.expires > 0) { + nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided domain %s (expires in %d seconds)", + device->iface, domain_str, + domain.expires - now); + break; + } + + nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided domain %s on router request", + device->iface, domain_str); + + g_array_remove_index (device->dnssl_domains, i); + changed = TRUE; + break; + } + + if (domain.expires == 0) + continue; + if (i < device->dnssl_domains->len) + continue; + + nm_log_dbg (LOGD_IP6, "(%s): found RA-provided domain %s (expires in %d seconds)", + device->iface, domain_str, domain.expires - now); + + g_assert (strlen (domain_str) < sizeof (domain.domain)); + strcpy (domain.domain, domain_str); + g_array_append_val (new_domains, domain); + } + + /* New domains must be added in the order they are listed in the + * RA option and before any existing domains. + * + * Note: This is the place to remove domains if we want to cap the + * number of domains. The RFC states that the one to expire + * first of the existing domains should be removed. + */ + if (new_domains->len) { + g_array_prepend_vals (device->dnssl_domains, + new_domains->data, new_domains->len); + changed = TRUE; + } + + g_array_free (new_domains, TRUE); + + /* Timeouts may have changed even if domains didn't */ + set_dnssl_timeout (device); + + return changed; +} static NMIP6Device * process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) @@ -583,13 +897,8 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) NMIP6Device *device; struct nduseroptmsg *ndmsg; struct nd_opt_hdr *opt; - guint opts_len, i; - time_t now = time (NULL); - struct nd_opt_rdnss *rdnss_opt; - struct in6_addr *addr; - GArray *servers; - NMIP6RDNSS server, *sa, *sb; - gboolean changed; + guint opts_len; + gboolean changed = FALSE; nm_log_dbg (LOGD_IP6, "processing netlink nduseropt message"); @@ -608,8 +917,6 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) return NULL; } - servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); - opt = (struct nd_opt_hdr *) (ndmsg + 1); opts_len = ndmsg->nduseropt_opts_len; @@ -619,66 +926,19 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) if (nd_opt_len == 0 || opts_len < (nd_opt_len << 3)) break; - if (opt->nd_opt_type != ND_OPT_RDNSS) - goto next; - - if (nd_opt_len < 3 || (nd_opt_len & 1) == 0) - goto next; - - rdnss_opt = (struct nd_opt_rdnss *) opt; - - /* Pad the DNS server expiry somewhat to give a bit of slack in cases - * where one RA gets lost or something (which can happen on unreliable - * links like wifi where certain types of frames are not retransmitted). - */ - server.expires = now + ntohl (rdnss_opt->nd_opt_rdnss_lifetime) + 10; - - for (addr = (struct in6_addr *) (rdnss_opt + 1); nd_opt_len >= 2; addr++, nd_opt_len -= 2) { - char buf[INET6_ADDRSTRLEN + 1]; - - if (inet_ntop (AF_INET6, addr, buf, sizeof (buf))) { - nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)", - device->iface, buf, - ntohl (rdnss_opt->nd_opt_rdnss_lifetime)); - } - - server.addr = *addr; - g_array_append_val (servers, server); + switch (opt->nd_opt_type) { + case ND_OPT_RDNSS: + changed = process_nduseropt_rdnss (device, opt); + break; + case ND_OPT_DNSSL: + changed = process_nduseropt_dnssl (device, opt); + break; } - next: opts_len -= opt->nd_opt_len << 3; opt = (struct nd_opt_hdr *) ((uint8_t *) opt + (opt->nd_opt_len << 3)); } - /* See if anything (other than expiration time) changed */ - if (servers->len != device->rdnss_servers->len) - changed = TRUE; - else { - for (i = 0; i < servers->len; i++) { - sa = &(g_array_index (servers, NMIP6RDNSS, i)); - sb = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i)); - if (IN6_ARE_ADDR_EQUAL (&sa->addr, &sb->addr) == FALSE) { - changed = TRUE; - break; - } - } - changed = FALSE; - } - - if (changed) { - nm_log_dbg (LOGD_IP6, "(%s): RA-provided nameservers changed", device->iface); - } - - /* Always copy in new servers (even if unchanged) to get their updated - * expiration times. - */ - g_array_free (device->rdnss_servers, TRUE); - device->rdnss_servers = servers; - - /* Timeouts may have changed even if IPs didn't */ - set_rdnss_timeout (device); - if (changed) return device; else @@ -1014,6 +1274,14 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) nm_ip6_config_add_nameserver (config, &rdnss[i].addr); } + /* Add DNS domains */ + if (device->dnssl_domains) { + NMIP6DNSSL *dnssl = (NMIP6DNSSL *)(device->dnssl_domains->data); + + for (i = 0; i < device->dnssl_domains->len; i++) + nm_ip6_config_add_domain (config, dnssl[i].domain); + } + return config; } diff --git a/src/logging/nm-logging.c b/src/logging/nm-logging.c index 31a5ab3c78..2d62a3067a 100644 --- a/src/logging/nm-logging.c +++ b/src/logging/nm-logging.c @@ -42,7 +42,8 @@ static guint32 log_domains = \ LOGD_HW | LOGD_RFKILL | LOGD_ETHER | LOGD_WIFI | LOGD_BT | LOGD_MB | \ LOGD_DHCP4 | LOGD_DHCP6 | LOGD_PPP | LOGD_IP4 | LOGD_IP6 | LOGD_AUTOIP4 | \ LOGD_DNS | LOGD_VPN | LOGD_SHARING | LOGD_SUPPLICANT | LOGD_AGENTS | \ - LOGD_SETTINGS | LOGD_SUSPEND | LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH; + LOGD_SETTINGS | LOGD_SUSPEND | LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH | \ + LOGD_WIMAX; typedef struct { guint32 num; @@ -82,6 +83,7 @@ static const LogDesc domain_descs[] = { { LOGD_CORE, "CORE" }, { LOGD_DEVICE, "DEVICE" }, { LOGD_OLPC_MESH, "OLPC" }, + { LOGD_WIMAX, "WIMAX" }, { 0, NULL } }; diff --git a/src/logging/nm-logging.h b/src/logging/nm-logging.h index 8f111e996b..3e8ef696ef 100644 --- a/src/logging/nm-logging.h +++ b/src/logging/nm-logging.h @@ -51,6 +51,7 @@ enum { LOGD_CORE = 0x00100000, /* Core daemon and policy stuff */ LOGD_DEVICE = 0x00200000, /* Device state and activation */ LOGD_OLPC_MESH = 0x00400000, + LOGD_WIMAX = 0x00800000, }; #define LOGD_DHCP (LOGD_DHCP4 | LOGD_DHCP6) diff --git a/src/main.c b/src/main.c index bb67e41275..4e9fd6fd8e 100644 --- a/src/main.c +++ b/src/main.c @@ -49,6 +49,7 @@ #include "nm-netlink-monitor.h" #include "nm-vpn-manager.h" #include "nm-logging.h" +#include "nm-policy-hosts.h" #if !defined(NM_DIST_VERSION) # define NM_DIST_VERSION VERSION @@ -306,6 +307,7 @@ parse_config_file (const char *filename, GError **error) { GKeyFile *config; + gboolean success = FALSE; config = g_key_file_new (); if (!config) { @@ -316,11 +318,11 @@ parse_config_file (const char *filename, g_key_file_set_list_separator (config, ','); if (!g_key_file_load_from_file (config, filename, G_KEY_FILE_NONE, error)) - return FALSE; + goto out; *plugins = g_key_file_get_value (config, "main", "plugins", error); if (*error) - return FALSE; + goto out; *dhcp_client = g_key_file_get_value (config, "main", "dhcp", NULL); *dns_plugins = g_key_file_get_string_list (config, "main", "dns", NULL, NULL); @@ -328,8 +330,11 @@ parse_config_file (const char *filename, *log_level = g_key_file_get_value (config, "logging", "level", NULL); *log_domains = g_key_file_get_value (config, "logging", "domains", NULL); + success = TRUE; + +out: g_key_file_free (config); - return TRUE; + return success; } static gboolean @@ -337,15 +342,17 @@ parse_state_file (const char *filename, gboolean *net_enabled, gboolean *wifi_enabled, gboolean *wwan_enabled, + gboolean *wimax_enabled, GError **error) { GKeyFile *state_file; GError *tmp_error = NULL; - gboolean wifi, net, wwan; + gboolean wifi, net, wwan, wimax; 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); + g_return_val_if_fail (wimax_enabled != NULL, FALSE); state_file = g_key_file_new (); if (!state_file) { @@ -384,6 +391,7 @@ parse_state_file (const char *filename, 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); + g_key_file_set_boolean (state_file, "main", "WimaxEnabled", *wimax_enabled); data = g_key_file_to_data (state_file, &len, NULL); if (data) @@ -426,6 +434,14 @@ parse_state_file (const char *filename, *wwan_enabled = wwan; g_clear_error (&tmp_error); + wimax = g_key_file_get_boolean (state_file, "main", "WimaxEnabled", &tmp_error); + if (tmp_error) { + g_clear_error (error); + g_set_error_literal (error, tmp_error->domain, tmp_error->code, tmp_error->message); + } else + *wimax_enabled = wimax; + g_clear_error (&tmp_error); + g_key_file_free (state_file); return TRUE; @@ -445,7 +461,7 @@ main (int argc, char *argv[]) char *config = NULL, *plugins = NULL, *conf_plugins = NULL; char *log_level = NULL, *log_domains = NULL; char **dns = NULL; - gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE; + gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE, wimax_enabled = TRUE; gboolean success; NMPolicy *policy = NULL; NMVPNManager *vpn_manager = NULL; @@ -581,7 +597,7 @@ main (int argc, char *argv[]) g_free (conf_plugins); /* Parse the state file */ - if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) { + if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &wimax_enabled, &error)) { fprintf (stderr, "State file %s parsing failed: (%d) %s\n", state_file, error ? error->code : -1, @@ -686,6 +702,7 @@ main (int argc, char *argv[]) net_enabled, wifi_enabled, wwan_enabled, + wimax_enabled, &error); if (manager == NULL) { nm_log_err (LOGD_CORE, "failed to initialize the network manager: %s", @@ -721,6 +738,9 @@ main (int argc, char *argv[]) goto done; } + /* Clean leftover "# Added by NetworkManager" entries from /etc/hosts */ + nm_policy_hosts_clean_etc_hosts (); + nm_manager_start (manager); /* Bring up the loopback interface. */ diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 5bba7030ba..1e8d7941d1 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -899,6 +899,12 @@ modem_properties_changed (DBusGProxy *proxy, priv->mm_enabled = g_value_get_boolean (value); g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); } + + value = g_hash_table_lookup (props, "IpMethod"); + if (value && G_VALUE_HOLDS_UINT (value)) { + priv->ip_method = g_value_get_uint (value); + g_object_notify (G_OBJECT (self), NM_MODEM_IP_METHOD); + } } /*****************************************************************************/ diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index e38d58576b..90137b49ac 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -295,7 +295,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) const char *iface; GUdevClient *client; GUdevDevice *dev; - GUdevDevice *parent; + GUdevDevice *parent = NULL; const char *parent_path, *item, *driver; const char *subsystems[] = { "net", NULL }; GDir *dir; diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c index e0a05df95f..f9d0eb4462 100644 --- a/src/nm-device-olpc-mesh.c +++ b/src/nm-device-olpc-mesh.c @@ -696,7 +696,7 @@ dispose (GObject *object) device_cleanup (self); - manager = nm_manager_get (NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL); + manager = nm_manager_get (NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, NULL); if (priv->device_added_id) g_signal_handler_disconnect (manager, priv->device_added_id); g_object_unref (manager); @@ -895,7 +895,7 @@ is_companion (NMDeviceOlpcMesh *self, NMDevice *other) priv->companion = other; /* When we've found the companion, stop listening for other devices */ - manager = nm_manager_get (NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL); + manager = nm_manager_get (NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, NULL); if (priv->device_added_id) { g_signal_handler_disconnect (manager, priv->device_added_id); priv->device_added_id = 0; @@ -950,7 +950,7 @@ check_companion_cb (gpointer user_data) if (priv->device_added_id != 0) return FALSE; - manager = nm_manager_get (NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL); + manager = nm_manager_get (NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, NULL); priv->device_added_id = 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 a86890b917..4a9e50214a 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -166,9 +166,6 @@ static void schedule_scan (NMDeviceWifi *self, gboolean backoff); static void cancel_pending_scan (NMDeviceWifi *self); -static int wireless_qual_to_percent (const struct iw_quality *qual, - const struct iw_quality *max_qual); - static void cleanup_association_attempt (NMDeviceWifi * self, gboolean disconnect); @@ -179,17 +176,13 @@ static void supplicant_iface_state_cb (NMSupplicantInterface *iface, guint32 old_state, gpointer user_data); -static void supplicant_iface_scanned_ap_cb (NMSupplicantInterface * iface, - GHashTable *properties, - NMDeviceWifi * self); - -static void supplicant_iface_scan_request_result_cb (NMSupplicantInterface * iface, - gboolean success, - NMDeviceWifi * self); +static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface, + GHashTable *properties, + NMDeviceWifi * self); -static void supplicant_iface_scan_results_cb (NMSupplicantInterface * iface, - guint32 num_bssids, - NMDeviceWifi * self); +static void supplicant_iface_scan_done_cb (NMSupplicantInterface * iface, + gboolean success, + NMDeviceWifi * self); static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, GParamSpec * pspec, @@ -308,6 +301,107 @@ ipw_rfkill_state_work (gpointer user_data) /*****************************************************************/ /* + * wireless_qual_to_percent + * + * Convert an iw_quality structure from SIOCGIWSTATS into a magical signal + * strength percentage. + * + */ +static int +wireless_qual_to_percent (const struct iw_quality *qual, + const struct iw_quality *max_qual) +{ + int percent = -1; + int level_percent = -1; + + g_return_val_if_fail (qual != NULL, -1); + g_return_val_if_fail (max_qual != NULL, -1); + + nm_log_dbg (LOGD_WIFI, + "QL: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X ** MAX: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X", + (__s8) qual->qual, qual->qual, qual->qual, + (__s8) qual->level, qual->level, qual->level, + (__s8) qual->noise, qual->noise, qual->noise, + qual->updated, + (__s8) max_qual->qual, max_qual->qual, max_qual->qual, + (__s8) max_qual->level, max_qual->level, max_qual->level, + (__s8) max_qual->noise, max_qual->noise, max_qual->noise, + max_qual->updated); + + /* Try using the card's idea of the signal quality first as long as it tells us what the max quality is. + * Drivers that fill in quality values MUST treat them as percentages, ie the "Link Quality" MUST be + * bounded by 0 and max_qual->qual, and MUST change in a linear fashion. Within those bounds, drivers + * are free to use whatever they want to calculate "Link Quality". + */ + if ((max_qual->qual != 0) && !(max_qual->updated & IW_QUAL_QUAL_INVALID) && !(qual->updated & IW_QUAL_QUAL_INVALID)) + percent = (int)(100 * ((double)qual->qual / (double)max_qual->qual)); + + /* If the driver doesn't specify a complete and valid quality, we have two options: + * + * 1) dBm: driver must specify max_qual->level = 0, and have valid values for + * qual->level and (qual->noise OR max_qual->noise) + * 2) raw RSSI: driver must specify max_qual->level > 0, and have valid values for + * qual->level and max_qual->level + * + * This is the WEXT spec. If this interpretation is wrong, I'll fix it. Otherwise, + * If drivers don't conform to it, they are wrong and need to be fixed. + */ + + if ( (max_qual->level == 0) && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ + && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ + && ( ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ + || ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ + ) { + /* Absolute power values (dBm) */ + + /* Reasonable fallbacks for dumb drivers that don't specify either level. */ + #define FALLBACK_NOISE_FLOOR_DBM -90 + #define FALLBACK_SIGNAL_MAX_DBM -20 + int max_level = FALLBACK_SIGNAL_MAX_DBM; + int noise = FALLBACK_NOISE_FLOOR_DBM; + int level = qual->level - 0x100; + + level = CLAMP (level, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); + + if ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID)) + noise = qual->noise - 0x100; + else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) + noise = max_qual->noise - 0x100; + noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); + + /* A sort of signal-to-noise ratio calculation */ + level_percent = (int)(100 - 70 *( + ((double)max_level - (double)level) / + ((double)max_level - (double)noise))); + nm_log_dbg (LOGD_WIFI, "QL1: level_percent is %d. max_level %d, level %d, noise_floor %d.", + level_percent, max_level, level, noise); + } else if ( (max_qual->level != 0) + && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ + && !(qual->updated & IW_QUAL_LEVEL_INVALID)) { + /* Relative power values (RSSI) */ + + int level = qual->level; + + /* Signal level is relavtive (0 -> max_qual->level) */ + level = CLAMP (level, 0, max_qual->level); + level_percent = (int)(100 * ((double)level / (double)max_qual->level)); + nm_log_dbg (LOGD_WIFI, "QL2: level_percent is %d. max_level %d, level %d.", + level_percent, max_qual->level, level); + } else if (percent == -1) { + nm_log_dbg (LOGD_WIFI, "QL: Could not get quality %% value from driver. Driver is probably buggy."); + } + + /* If the quality percent was 0 or doesn't exist, then try to use signal levels instead */ + if ((percent < 1) && (level_percent >= 0)) + percent = level_percent; + + nm_log_dbg (LOGD_WIFI, "QL: Final quality percent is %d (%d).", + percent, CLAMP (percent, 0, 100)); + return (CLAMP (percent, 0, 100)); +} + + +/* * nm_device_wifi_update_signal_strength * * Update the device's idea of the strength of its connection to the @@ -655,26 +749,20 @@ supplicant_interface_acquire (NMDeviceWifi *self) memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids)); id = g_signal_connect (priv->supplicant.iface, - "state", + NM_SUPPLICANT_INTERFACE_STATE, G_CALLBACK (supplicant_iface_state_cb), self); priv->supplicant.sig_ids[i++] = id; id = g_signal_connect (priv->supplicant.iface, - "scanned-ap", - G_CALLBACK (supplicant_iface_scanned_ap_cb), + NM_SUPPLICANT_INTERFACE_NEW_BSS, + G_CALLBACK (supplicant_iface_new_bss_cb), self); priv->supplicant.sig_ids[i++] = id; id = g_signal_connect (priv->supplicant.iface, - "scan-req-result", - G_CALLBACK (supplicant_iface_scan_request_result_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - id = g_signal_connect (priv->supplicant.iface, - "scan-results", - G_CALLBACK (supplicant_iface_scan_results_cb), + NM_SUPPLICANT_INTERFACE_SCAN_DONE, + G_CALLBACK (supplicant_iface_scan_done_cb), self); priv->supplicant.sig_ids[i++] = id; @@ -1692,107 +1780,6 @@ nm_device_wifi_get_frequency (NMDeviceWifi *self) } /* - * wireless_stats_to_percent - * - * Convert an iw_stats structure from a scan or the card into - * a magical signal strength percentage. - * - */ -static int -wireless_qual_to_percent (const struct iw_quality *qual, - const struct iw_quality *max_qual) -{ - int percent = -1; - int level_percent = -1; - - g_return_val_if_fail (qual != NULL, -1); - g_return_val_if_fail (max_qual != NULL, -1); - - nm_log_dbg (LOGD_WIFI, - "QL: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X ** MAX: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X", - (__s8) qual->qual, qual->qual, qual->qual, - (__s8) qual->level, qual->level, qual->level, - (__s8) qual->noise, qual->noise, qual->noise, - qual->updated, - (__s8) max_qual->qual, max_qual->qual, max_qual->qual, - (__s8) max_qual->level, max_qual->level, max_qual->level, - (__s8) max_qual->noise, max_qual->noise, max_qual->noise, - max_qual->updated); - - /* Try using the card's idea of the signal quality first as long as it tells us what the max quality is. - * Drivers that fill in quality values MUST treat them as percentages, ie the "Link Quality" MUST be - * bounded by 0 and max_qual->qual, and MUST change in a linear fashion. Within those bounds, drivers - * are free to use whatever they want to calculate "Link Quality". - */ - if ((max_qual->qual != 0) && !(max_qual->updated & IW_QUAL_QUAL_INVALID) && !(qual->updated & IW_QUAL_QUAL_INVALID)) - percent = (int)(100 * ((double)qual->qual / (double)max_qual->qual)); - - /* If the driver doesn't specify a complete and valid quality, we have two options: - * - * 1) dBm: driver must specify max_qual->level = 0, and have valid values for - * qual->level and (qual->noise OR max_qual->noise) - * 2) raw RSSI: driver must specify max_qual->level > 0, and have valid values for - * qual->level and max_qual->level - * - * This is the WEXT spec. If this interpretation is wrong, I'll fix it. Otherwise, - * If drivers don't conform to it, they are wrong and need to be fixed. - */ - - if ( (max_qual->level == 0) && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ - && ( ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ - || ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ - ) { - /* Absolute power values (dBm) */ - - /* Reasonable fallbacks for dumb drivers that don't specify either level. */ - #define FALLBACK_NOISE_FLOOR_DBM -90 - #define FALLBACK_SIGNAL_MAX_DBM -20 - int max_level = FALLBACK_SIGNAL_MAX_DBM; - int noise = FALLBACK_NOISE_FLOOR_DBM; - int level = qual->level - 0x100; - - level = CLAMP (level, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); - - if ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID)) - noise = qual->noise - 0x100; - else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) - noise = max_qual->noise - 0x100; - noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); - - /* A sort of signal-to-noise ratio calculation */ - level_percent = (int)(100 - 70 *( - ((double)max_level - (double)level) / - ((double)max_level - (double)noise))); - nm_log_dbg (LOGD_WIFI, "QL1: level_percent is %d. max_level %d, level %d, noise_floor %d.", - level_percent, max_level, level, noise); - } else if ( (max_qual->level != 0) - && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID)) { - /* Relative power values (RSSI) */ - - int level = qual->level; - - /* Signal level is relavtive (0 -> max_qual->level) */ - level = CLAMP (level, 0, max_qual->level); - level_percent = (int)(100 * ((double)level / (double)max_qual->level)); - nm_log_dbg (LOGD_WIFI, "QL2: level_percent is %d. max_level %d, level %d.", - level_percent, max_qual->level, level); - } else if (percent == -1) { - nm_log_dbg (LOGD_WIFI, "QL: Could not get quality %% value from driver. Driver is probably buggy."); - } - - /* If the quality percent was 0 or doesn't exist, then try to use signal levels instead */ - if ((percent < 1) && (level_percent >= 0)) - percent = level_percent; - - nm_log_dbg (LOGD_WIFI, "QL: Final quality percent is %d (%d).", - percent, CLAMP (percent, 0, 100)); - return (CLAMP (percent, 0, 100)); -} - - -/* * nm_device_wifi_get_ssid * * If a device is wireless, return the ssid that it is attempting @@ -2101,28 +2088,19 @@ cancel_pending_scan (NMDeviceWifi *self) } } - static void -supplicant_iface_scan_request_result_cb (NMSupplicantInterface *iface, - gboolean success, - NMDeviceWifi *self) +supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, + gboolean success, + NMDeviceWifi *self) { - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan request %s", + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan %s", nm_device_get_iface (NM_DEVICE (self)), success ? "successful" : "failed"); if (check_scanning_allowed (self)) schedule_scan (self, TRUE); -} -static void -supplicant_iface_scan_results_cb (NMSupplicantInterface *iface, - guint32 num_results, - NMDeviceWifi *self) -{ - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan results available (%d APs found)", - nm_device_get_iface (NM_DEVICE (self)), - num_results); +#if 0 if (num_results == 0) { /* ensure that old APs get culled, which otherwise only * happens when there are actual scan results to process. @@ -2130,6 +2108,7 @@ supplicant_iface_scan_results_cb (NMSupplicantInterface *iface, cull_scan_list (self); nm_device_wifi_ap_list_print (self); } +#endif } static gboolean @@ -2349,48 +2328,10 @@ cull_scan_list (NMDeviceWifi *self) removed, total); } -#define SET_QUALITY_MEMBER(qual_item, lc_member, uc_member) \ - if (lc_member != -1) { \ - qual_item.lc_member = lc_member; \ - qual_item.updated |= IW_QUAL_##uc_member##_UPDATED; \ - } else { \ - qual_item.updated |= IW_QUAL_##uc_member##_INVALID; \ - } - static void -set_ap_strength_from_properties (NMDeviceWifi *self, - NMAccessPoint *ap, - GHashTable *properties) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - int qual, level, noise; - struct iw_quality quality; - GValue *value; - gint8 strength; - - value = (GValue *) g_hash_table_lookup (properties, "quality"); - qual = value ? g_value_get_int (value) : -1; - - value = (GValue *) g_hash_table_lookup (properties, "level"); - level = value ? g_value_get_int (value) : -1; - - value = (GValue *) g_hash_table_lookup (properties, "noise"); - noise = value ? g_value_get_int (value) : -1; - - /* Calculate and set the AP's signal quality */ - memset (&quality, 0, sizeof (struct iw_quality)); - SET_QUALITY_MEMBER (quality, qual, QUAL); - SET_QUALITY_MEMBER (quality, level, LEVEL); - SET_QUALITY_MEMBER (quality, noise, NOISE); - - strength = wireless_qual_to_percent (&quality, &priv->max_qual); - nm_ap_set_strength (ap, strength); -} - -static void -supplicant_iface_scanned_ap_cb (NMSupplicantInterface *iface, - GHashTable *properties, - NMDeviceWifi *self) +supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, + GHashTable *properties, + NMDeviceWifi *self) { NMDeviceState state; NMAccessPoint *ap; @@ -2406,8 +2347,6 @@ supplicant_iface_scanned_ap_cb (NMSupplicantInterface *iface, ap = nm_ap_new_from_properties (properties); if (ap) { - set_ap_strength_from_properties (self, ap, properties); - nm_ap_print_self (ap, "AP: "); /* Add the AP to the device's AP list */ @@ -3253,7 +3192,7 @@ real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) /* Hook up error signal handler to capture association errors */ id = g_signal_connect (priv->supplicant.iface, - "connection-error", + NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, G_CALLBACK (supplicant_iface_connection_error_cb), self); priv->supplicant.iface_error_id = id; @@ -3701,12 +3640,11 @@ real_set_enabled (NMDeviceInterface *device, gboolean enabled) /* Wait for some drivers like ipw3945 to come back to life */ success = wireless_get_range (self, &range, NULL); - /* iface should be NULL here, but handle it anyway if it's not */ - g_warn_if_fail (priv->supplicant.iface == NULL); + /* Re-initialize the supplicant interface and wait for it to be ready */ if (priv->supplicant.iface) supplicant_interface_release (self); - supplicant_interface_acquire (self); + nm_log_dbg (LOGD_WIFI, "(%s): enable waiting on supplicant state", nm_device_get_iface (NM_DEVICE (device))); } else { diff --git a/src/nm-device.c b/src/nm-device.c index 7c531c7bdb..c3e5c75b5a 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -184,8 +184,8 @@ static NMActStageReturn dhcp6_start (NMDevice *self, NMDeviceStateReason *reason); static void addrconf6_cleanup (NMDevice *self); -static void dhcp6_cleanup (NMDevice *self, gboolean stop); -static void dhcp4_cleanup (NMDevice *self, gboolean stop); +static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release); +static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release); static void @@ -1614,7 +1614,7 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data) if (!nm_device_get_act_request (device)) return; - nm_dhcp_client_stop (client); + nm_dhcp_client_stop (client, FALSE); if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { if (nm_dhcp_client_get_ipv6 (client)) @@ -1625,15 +1625,87 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data) } static NMActStageReturn +dhcp4_start (NMDevice *self, + NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMSettingConnection *s_con; + NMSettingIP4Config *s_ip4; + guint8 *anycast = NULL; + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert (s_con); + s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + + if (priv->dhcp_anycast_address) + anycast = priv->dhcp_anycast_address->data; + + /* Clear old exported DHCP options */ + if (priv->dhcp4_config) + g_object_unref (priv->dhcp4_config); + priv->dhcp4_config = nm_dhcp4_config_new (); + + /* Begin DHCP on the interface */ + g_warn_if_fail (priv->dhcp4_client == NULL); + priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager, + nm_device_get_ip_iface (self), + nm_setting_connection_get_uuid (s_con), + s_ip4, + priv->dhcp_timeout, + anycast); + if (!priv->dhcp4_client) { + *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client, + "state-changed", + G_CALLBACK (dhcp_state_changed), + self); + priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client, + "timeout", + G_CALLBACK (dhcp_timeout), + self); + + /* DHCP devices will be notified by the DHCP manager when stuff happens */ + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +gboolean +nm_device_dhcp4_renew (NMDevice *self, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason; + NMActRequest *req; + NMConnection *connection; + + g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE); + + /* Terminate old DHCP instance and release the old lease */ + dhcp4_cleanup (self, TRUE, TRUE); + + req = nm_device_get_act_request (self); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); + + /* Start DHCP again on the interface */ + ret = dhcp4_start (self, connection, &reason); + + return (ret != NM_ACT_STAGE_RETURN_FAILURE); +} + +static NMActStageReturn real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; - NMSettingConnection *s_con; NMSettingIP4Config *s_ip4; NMActRequest *req; NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - const char *ip_iface, *method = NULL, *uuid; + const char *ip_iface, *method = NULL; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -1646,9 +1718,6 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason) req = nm_device_get_act_request (self); connection = nm_act_request_get_connection (req); - s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); - g_assert (s_con); - uuid = nm_setting_connection_get_uuid (s_con); s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); @@ -1657,42 +1726,7 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason) method = nm_setting_ip4_config_get_method (s_ip4); if (!s_ip4 || !method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - guint8 *anycast = NULL; - - /* Begin a DHCP transaction on the interface */ - - if (priv->dhcp_anycast_address) - anycast = priv->dhcp_anycast_address->data; - - /* Clear old exported DHCP options */ - if (priv->dhcp4_config) - g_object_unref (priv->dhcp4_config); - priv->dhcp4_config = nm_dhcp4_config_new (); - - priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager, - ip_iface, - uuid, - s_ip4, - priv->dhcp_timeout, - anycast); - if (priv->dhcp4_client) { - priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client, - "state-changed", - G_CALLBACK (dhcp_state_changed), - self); - priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client, - "timeout", - G_CALLBACK (dhcp_timeout), - self); - - /* DHCP devices will be notified by the DHCP manager when - * stuff happens. - */ - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } + ret = dhcp4_start (self, connection, reason); } else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { GError *error = NULL; const char *iface = nm_device_get_iface (self); @@ -2813,7 +2847,7 @@ delayed_transitions_clear (NMDevice *self) } static void -dhcp4_cleanup (NMDevice *self, gboolean stop) +dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -2836,7 +2870,7 @@ dhcp4_cleanup (NMDevice *self, gboolean stop) } if (stop) - nm_dhcp_client_stop (priv->dhcp4_client); + nm_dhcp_client_stop (priv->dhcp4_client, release); g_object_unref (priv->dhcp4_client); priv->dhcp4_client = NULL; @@ -2844,7 +2878,7 @@ dhcp4_cleanup (NMDevice *self, gboolean stop) } static void -dhcp6_cleanup (NMDevice *self, gboolean stop) +dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -2868,7 +2902,7 @@ dhcp6_cleanup (NMDevice *self, gboolean stop) } if (stop) - nm_dhcp_client_stop (priv->dhcp6_client); + nm_dhcp_client_stop (priv->dhcp6_client, release); g_object_unref (priv->dhcp6_client); priv->dhcp6_client = NULL; @@ -2917,8 +2951,8 @@ nm_device_deactivate_quickly (NMDevice *self) /* Clear any delayed transitions */ delayed_transitions_clear (self); - dhcp4_cleanup (self, TRUE); - dhcp6_cleanup (self, TRUE); + dhcp4_cleanup (self, TRUE, FALSE); + dhcp6_cleanup (self, TRUE, FALSE); addrconf6_cleanup (self); dnsmasq_cleanup (self); aipd_cleanup (self); @@ -3460,8 +3494,8 @@ dispose (GObject *object) delayed_transitions_clear (self); /* Clean up and stop DHCP */ - dhcp4_cleanup (self, take_down); - dhcp6_cleanup (self, take_down); + dhcp4_cleanup (self, take_down, FALSE); + dhcp6_cleanup (self, take_down, FALSE); addrconf6_cleanup (self); dnsmasq_cleanup (self); diff --git a/src/nm-device.h b/src/nm-device.h index b96da33024..94c8510be3 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -192,6 +192,8 @@ void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr); void nm_device_clear_autoconnect_inhibit (NMDevice *device); +gboolean nm_device_dhcp4_renew (NMDevice *device, gboolean release); + G_END_DECLS #endif /* NM_DEVICE_H */ diff --git a/src/nm-manager-auth.h b/src/nm-manager-auth.h index df686db440..26195bf069 100644 --- a/src/nm-manager-auth.h +++ b/src/nm-manager-auth.h @@ -33,6 +33,7 @@ #define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake" #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX "org.freedesktop.NetworkManager.enable-disable-wimax" #define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control" #define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED "org.freedesktop.NetworkManager.wifi.share.protected" #define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open" diff --git a/src/nm-manager.c b/src/nm-manager.c index 1067575532..c75b893320 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -38,6 +38,9 @@ #include "nm-device-ethernet.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" +#if WITH_WIMAX +#include "nm-device-wimax.h" +#endif #include "nm-device-cdma.h" #include "nm-device-gsm.h" #include "nm-system.h" @@ -266,6 +269,8 @@ enum { PROP_WIRELESS_HARDWARE_ENABLED, PROP_WWAN_ENABLED, PROP_WWAN_HARDWARE_ENABLED, + PROP_WIMAX_ENABLED, + PROP_WIMAX_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, /* Not exported */ @@ -1390,6 +1395,12 @@ add_device (NMManager *self, NMDevice *device) nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), priv->radio_states[RFKILL_TYPE_WWAN].enabled); */ +#if WITH_WIMAX + } else if (NM_IS_DEVICE_WIMAX (device)) { + nm_manager_rfkill_update (self, RFKILL_TYPE_WIMAX); + enabled = radio_enabled_for_type (self, RFKILL_TYPE_WIMAX); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); +#endif } type_desc = nm_device_get_type_desc (device); @@ -1705,6 +1716,14 @@ udev_device_removed_cb (NMUdevManager *manager, ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); device = find_device_by_ifindex (self, ifindex); + if (!device) { + /* On removal we won't always be able to read properties anymore, as + * they may have already been removed from sysfs. Instead, we just + * have to fall back to the device's interface name. + */ + device = find_device_by_iface (self, g_udev_device_get_name (udev_device)); + } + if (device) priv->devices = remove_one_device (self, priv->devices, device, FALSE); } @@ -2633,6 +2652,7 @@ get_permissions_done_cb (NMAuthChain *chain, get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SLEEP_WAKE); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN); + get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_NETWORK_CONTROL); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN); @@ -2663,6 +2683,7 @@ impl_manager_get_permissions (NMManager *self, nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE); @@ -2919,6 +2940,9 @@ prop_filter (DBusConnection *connection, } else if (!strcmp (propname, "WwanEnabled")) { glib_propname = NM_MANAGER_WWAN_ENABLED; permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN; + } else if (!strcmp (propname, "WimaxEnabled")) { + glib_propname = NM_MANAGER_WIMAX_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX; } else return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -2978,6 +3002,7 @@ nm_manager_get (NMSettings *settings, gboolean initial_net_enabled, gboolean initial_wifi_enabled, gboolean initial_wwan_enabled, + gboolean initial_wimax_enabled, GError **error) { static NMManager *singleton = NULL; @@ -3017,6 +3042,7 @@ nm_manager_get (NMSettings *settings, priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = initial_wifi_enabled; priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = initial_wwan_enabled; + priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = initial_wimax_enabled; g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS, G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); @@ -3112,10 +3138,11 @@ dispose (GObject *object) /* Unregister property filter */ bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - g_assert (bus); - dbus_connection = dbus_g_connection_get_connection (bus); - g_assert (dbus_connection); - dbus_connection_remove_filter (dbus_connection, prop_filter, manager); + if (bus) { + dbus_connection = dbus_g_connection_get_connection (bus); + g_assert (dbus_connection); + dbus_connection_remove_filter (dbus_connection, prop_filter, manager); + } g_object_unref (priv->dbus_mgr); if (priv->bluez_mgr) @@ -3204,6 +3231,11 @@ set_property (GObject *object, guint prop_id, &priv->radio_states[RFKILL_TYPE_WWAN], g_value_get_boolean (value)); break; + case PROP_WIMAX_ENABLED: + manager_radio_user_toggled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WIMAX], + g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3240,6 +3272,12 @@ get_property (GObject *object, guint prop_id, case PROP_WWAN_HARDWARE_ENABLED: g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); break; + case PROP_WIMAX_ENABLED: + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WIMAX)); + break; + case PROP_WIMAX_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WIMAX].hw_enabled); + break; case PROP_ACTIVE_CONNECTIONS: g_value_take_boxed (value, get_active_connections (self, NULL)); break; @@ -3307,8 +3345,8 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = TRUE; priv->radio_states[RFKILL_TYPE_WIMAX].key = "WiMAXEnabled"; - priv->radio_states[RFKILL_TYPE_WIMAX].prop = NULL; - priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NULL; + priv->radio_states[RFKILL_TYPE_WIMAX].prop = NM_MANAGER_WIMAX_ENABLED; + priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NM_MANAGER_WIMAX_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WIMAX].desc = "WiMAX"; priv->radio_states[RFKILL_TYPE_WIMAX].other_enabled_func = NULL; priv->radio_states[RFKILL_TYPE_WIMAX].rtype = RFKILL_TYPE_WIMAX; @@ -3480,6 +3518,22 @@ nm_manager_class_init (NMManagerClass *manager_class) G_PARAM_READABLE)); g_object_class_install_property + (object_class, PROP_WIMAX_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, + "WimaxEnabled", + "Is WiMAX enabled", + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_WIMAX_HARDWARE_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, + "WimaxHardwareEnabled", + "Whether WiMAX 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, "Active connections", diff --git a/src/nm-manager.h b/src/nm-manager.h index c19ac5e874..ba9375488f 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -43,6 +43,8 @@ #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_WIMAX_ENABLED "wimax-enabled" +#define NM_MANAGER_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled" #define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" /* Not exported */ @@ -72,6 +74,7 @@ NMManager *nm_manager_get (NMSettings *settings, gboolean initial_net_enabled, gboolean initial_wifi_enabled, gboolean initial_wwan_enabled, + gboolean initial_wimax_enabled, GError **error); void nm_manager_start (NMManager *manager); diff --git a/src/nm-policy-hostname.c b/src/nm-policy-hostname.c index 42a2e0f9a4..4fe69c5a9b 100644 --- a/src/nm-policy-hostname.c +++ b/src/nm-policy-hostname.c @@ -30,7 +30,6 @@ #include "nm-logging.h" #include "nm-policy-hostname.h" -#include "nm-policy-hosts.h" /************************************************************************/ @@ -206,74 +205,39 @@ hostname_thread_is_dead (HostnameThread *ht) /************************************************************************/ #define FALLBACK_HOSTNAME4 "localhost.localdomain" -#define FALLBACK_HOSTNAME6 "localhost6.localdomain6" gboolean -nm_policy_set_system_hostname (const char *new_hostname, - const char *ip4_addr, - const char *ip6_addr, - const char *msg) +nm_policy_set_system_hostname (const char *new_hostname, const char *msg) { char old_hostname[HOST_NAME_MAX + 1]; - int ret = 0; const char *name; - gboolean set_hostname = TRUE, changed = FALSE, old_valid = TRUE; + int ret; if (new_hostname) g_warn_if_fail (strlen (new_hostname)); - name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; - old_hostname[HOST_NAME_MAX] = '\0'; errno = 0; ret = gethostname (old_hostname, HOST_NAME_MAX); if (ret != 0) { nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s", errno, strerror (errno)); - old_valid = FALSE; } else { /* Don't set the hostname if it isn't actually changing */ if ( (new_hostname && !strcmp (old_hostname, new_hostname)) || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4))) - set_hostname = FALSE; - - if (old_hostname[0] == '\0') - old_valid = FALSE; - } - - if (set_hostname) { - nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg); - ret = sethostname (name, strlen (name)); - if (ret != 0) { - nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", - name, errno, strerror (errno)); return FALSE; - } } - /* But even if the hostname isn't changing, always try updating /etc/hosts - * just in case the hostname changed while NM wasn't running; we need to - * make sure that /etc/hosts has valid mappings for '127.0.0.1' and the - * current system hostname. If those exist, - * nm_policy_hosts_update_etc_hosts() will just return and won't touch - * /etc/hosts at all. - */ - if (!nm_policy_hosts_update_etc_hosts (name, - old_valid ? old_hostname : NULL, - FALLBACK_HOSTNAME4, - FALLBACK_HOSTNAME6, - ip4_addr, - ip6_addr, - &changed)) { - /* error updating /etc/hosts; fallback to localhost.localdomain */ - nm_log_info (LOGD_DNS, "Setting system hostname to '" FALLBACK_HOSTNAME4 "' (error updating /etc/hosts)"); - ret = sethostname (FALLBACK_HOSTNAME4, strlen (FALLBACK_HOSTNAME4)); - if (ret != 0) { - nm_log_warn (LOGD_DNS, "couldn't set the fallback system hostname (%s): (%d) %s", - FALLBACK_HOSTNAME4, errno, strerror (errno)); - } + name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; + + nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg); + ret = sethostname (name, strlen (name)); + if (ret != 0) { + nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", + name, errno, strerror (errno)); } - return changed; + return (ret == 0); } diff --git a/src/nm-policy-hostname.h b/src/nm-policy-hostname.h index 9c76884726..e76713f16d 100644 --- a/src/nm-policy-hostname.h +++ b/src/nm-policy-hostname.h @@ -24,10 +24,7 @@ #include <glib.h> -gboolean nm_policy_set_system_hostname (const char *new_hostname, - const char *ip4_addr, - const char *ip6_addr, - const char *msg); +gboolean nm_policy_set_system_hostname (const char *new_hostname, const char *msg); typedef struct HostnameThread HostnameThread; diff --git a/src/nm-policy-hosts.c b/src/nm-policy-hosts.c index 7f9cff8074..8bbd1d3b5f 100644 --- a/src/nm-policy-hosts.c +++ b/src/nm-policy-hosts.c @@ -20,526 +20,74 @@ #include <config.h> #include <string.h> -#include <unistd.h> -#include <errno.h> -#include <netdb.h> -#include <ctype.h> -#include <arpa/inet.h> #include "nm-policy-hosts.h" #include "nm-logging.h" -#define IP4_LH "127.0.0.1" -#define IP6_LH "::1" - -gboolean -nm_policy_hosts_find_token (const char *line, const char *token) -{ - const char *start = line, *p = line; - - g_return_val_if_fail (line != NULL, FALSE); - g_return_val_if_fail (token != NULL, FALSE); - g_return_val_if_fail (strlen (token) > 0, FALSE); - - /* Walk through the line to find the next whitespace character */ - while (p <= line + strlen (line)) { - if (isblank (*p) || (*p == '\0')) { - /* Token starts with 'start' and ends with 'end' */ - if ((p > start) && *start && (p - start == strlen (token)) && !strncmp (start, token, (p - start))) - return TRUE; /* found */ - - /* not found; advance start and continue looking */ - start = p + 1; - } - p++; - } - - return FALSE; -} - -static gboolean -is_local_mapping (const char *str, gboolean ip6, const char *hostname) -{ - const char *addr = ip6 ? IP6_LH : IP4_LH; - const char *fallback = ip6 ? "localhost6" : "localhost"; - - return ( !strncmp (str, addr, strlen (addr)) - && nm_policy_hosts_find_token (str, hostname ? hostname : fallback)); -} - -static gboolean -is_ip4_addr (const char *str) -{ - struct in_addr found; - char buf[INET_ADDRSTRLEN + 2]; - const char *p = str; - guint32 i = 0; - - memset (buf, 0, sizeof (buf)); - while (*p && !isblank (*p) && (i < sizeof (buf))) - buf[i++] = *p++; - - return inet_pton (AF_INET, buf, &found) == 1 ? TRUE : FALSE; -} - -static gboolean -ip4_addr_matches (const char *str, const char *ip4_addr) -{ - struct in_addr found, given; - char buf[INET_ADDRSTRLEN + 2]; - const char *p = str; - guint32 i = 0; - - g_return_val_if_fail (ip4_addr != NULL, FALSE); - - memset (buf, 0, sizeof (buf)); - while (*p && !isblank (*p) && (i < sizeof (buf))) - buf[i++] = *p++; - - if (inet_pton (AF_INET, buf, &found) != 1) - return FALSE; - if (inet_pton (AF_INET, ip4_addr, &given) != 1) - return FALSE; - - return memcmp (&found, &given, sizeof (found)) == 0; -} - -static gboolean -is_ip6_addr (const char *str) -{ - struct in6_addr found; - char buf[INET6_ADDRSTRLEN + 2]; - const char *p = str; - guint32 i = 0; - - memset (buf, 0, sizeof (buf)); - while (*p && !isblank (*p) && (i < sizeof (buf))) - buf[i++] = *p++; - - return inet_pton (AF_INET6, buf, &found) == 1 ? TRUE : FALSE; -} - -static gboolean -ip6_addr_matches (const char *str, const char *ip6_addr) -{ - struct in6_addr found, given; - char buf[INET6_ADDRSTRLEN + 2]; - const char *p = str; - guint32 i = 0; - - g_return_val_if_fail (ip6_addr != NULL, FALSE); - - memset (buf, 0, sizeof (buf)); - while (*p && !isblank (*p) && (i < sizeof (buf))) - buf[i++] = *p++; - - if (inet_pton (AF_INET6, buf, &found) != 1) - return FALSE; - if (inet_pton (AF_INET6, ip6_addr, &given) != 1) - return FALSE; - - return memcmp (&found, &given, sizeof (found)) == 0; -} - -static char * -get_custom_hostnames (const char *line, - const char *hostname, - const char *old_hostname, - const char *short_hostname, - const char *fallback_hostname) -{ - char **items = NULL, **iter; - guint start = 0; - GString *str = NULL; - char *custom = NULL; - - g_return_val_if_fail (line != NULL, NULL); - - if (!strncmp (line, IP4_LH, strlen (IP4_LH))) - start = strlen (IP4_LH); - else if (!strncmp (line, IP6_LH, strlen (IP6_LH))) - start = strlen (IP6_LH); - - g_return_val_if_fail (start > 0, NULL); - - /* Split the line into tokens */ - items = g_strsplit_set (line + start, " \t", -1); - if (!items) - return NULL; - - str = g_string_sized_new (50); - /* Ignore current & old hostnames, and localhost-anything */ - for (iter = items; iter && *iter; iter++) { - if (*iter[0] == '\0') - continue; - if (hostname && !strcmp (*iter, hostname)) - continue; - if (old_hostname && !strcmp (*iter, old_hostname)) - continue; - if (short_hostname && !strcmp (*iter, short_hostname)) - continue; - if (fallback_hostname && !strcmp (*iter, fallback_hostname)) - continue; - if (!strcmp (*iter, "localhost")) - continue; - if (!strcmp (*iter, "localhost6")) - continue; - if (!strcmp (*iter, "localhost.localdomain")) - continue; - if (!strcmp (*iter, "localhost4.localdomain4")) - continue; - if (!strcmp (*iter, "localhost6.localdomain6")) - continue; - - /* Found a custom hostname */ - g_string_append_c (str, '\t'); - g_string_append (str, *iter); - } - - if (str->len) - custom = g_string_free (str, FALSE); - else - g_string_free (str, TRUE); - - g_strfreev (items); - return custom; -} - #define ADDED_TAG "# Added by NetworkManager" GString * -nm_policy_get_etc_hosts (const char **lines, - gsize existing_len, - const char *hostname, - const char *old_hostname, - const char *fallback_hostname4, - const char *fallback_hostname6, - const char *ip4_addr, - const char *ip6_addr, - GError **error) +nm_policy_get_etc_hosts (const char *contents, gsize contents_len) { - GString *contents = NULL; - const char **line; - gboolean found_localhost4 = FALSE; - gboolean found_localhost6 = FALSE; - gboolean found_host4 = FALSE; - gboolean found_host6 = FALSE; - gboolean found_user_host4 = FALSE; - gboolean found_user_host6 = FALSE; - gboolean initial_comments = TRUE; - gboolean added = FALSE; - gboolean hostname4_is_fallback; - gboolean hostname6_is_fallback; - gboolean host4_before = FALSE; - gboolean host6_before = FALSE; - gboolean no_stale = TRUE; - char *short_hostname = NULL; - char *custom4 = NULL; - char *custom6 = NULL; - - g_return_val_if_fail (lines != NULL, FALSE); - g_return_val_if_fail (hostname != NULL, FALSE); - - hostname4_is_fallback = !strcmp (hostname, fallback_hostname4); - hostname6_is_fallback = !strcmp (hostname, fallback_hostname6); - - /* Find the short hostname, like 'foo' from 'foo.bar.baz'; we want to - * make sure that the entries we add for this host also include the short - * hostname too so that if the resolver does not answer queries for the - * machine's actual hostname/domain, that stuff like 'ping foo' still works. - */ - if (!hostname4_is_fallback || !hostname6_is_fallback) { - char *dot; - - short_hostname = g_strdup (hostname); - dot = strchr (short_hostname, '.'); - if (dot && *(dot+1)) - *dot = '\0'; - else { - g_free (short_hostname); - short_hostname = NULL; - } - } - - /* We need the following in /etc/hosts: - * - * 1) current hostname mapped to current IPv4 addresses if IPv4 is active - * 2) current hostname mapped to current IPv6 addresses if IPv6 is active - * 3) 'localhost' mapped to 127.0.0.1 - * 4) 'localhost6' mapped to ::1 - * - * If all these things exist we don't need to bother updating the file. - */ - - if (!ip4_addr) - host4_before = TRUE; - if (!ip6_addr) - host6_before = TRUE; - - /* Look for the four cases from above */ - for (line = lines; lines && *line; line++) { - gboolean found_hostname = FALSE; - - if ((*line[0] == '\0') || (*line[0] == '#')) - continue; + char **lines = NULL, **iter; + GString *new_contents = NULL; - found_hostname = nm_policy_hosts_find_token (*line, hostname); - if (found_hostname) { - /* Found the current hostname on this line */ - if (ip4_addr && ip4_addr_matches (*line, ip4_addr)) { - found_host4 = TRUE; - if (strstr (*line, ADDED_TAG)) { - if (!host4_before) - host4_before = !found_localhost4; - } else { - found_user_host4 = TRUE; - host4_before = TRUE; /* Ignore if user added mapping manually */ - } - } else if (!ip4_addr && strstr (*line, ADDED_TAG)) { - /* If this is a stale NM-added IPv4 entry we need to remove it, - * so make sure we update /etc/hosts. - */ - if (is_ip4_addr (*line)) - no_stale = FALSE; - } + if (contents_len == 0 || !strstr (contents, ADDED_TAG)) + return NULL; - if (ip6_addr && ip6_addr_matches (*line, ip6_addr)) { - found_host6 = TRUE; - if (strstr (*line, ADDED_TAG)) { - if (!host6_before) - host6_before = !found_localhost6; - } else { - found_user_host6 = TRUE; - host6_before = TRUE; /* Ignore if user added mapping manually */ - } - } else if (!ip6_addr && strstr (*line, ADDED_TAG)) { - /* If this is a stale NM-added IPv6 entry we need to remove it, - * so make sure we update /etc/hosts. - */ - if (is_ip6_addr (*line)) - no_stale = FALSE; - } - } + new_contents = g_string_sized_new (contents_len); - if (is_local_mapping (*line, FALSE, "localhost")) { - /* a 127.0.0.1 line containing 'localhost' */ - found_localhost4 = TRUE; - custom4 = get_custom_hostnames (*line, hostname, old_hostname, short_hostname, fallback_hostname4); - if (!ip4_addr) { - /* If there's no IP-specific mapping for the current hostname - * but that hostname is present on in the local mapping line, - * we've found our IPv4 hostname mapping. If the hostname is - * the fallback *IPv6* hostname it's not going to show up in - * the IPv4 local mapping though, so fake it. - */ - if (hostname6_is_fallback || found_hostname) - found_host4 = TRUE; - } - } else if (is_local_mapping (*line, TRUE, "localhost6")) { - /* a ::1 line containing 'localhost6' */ - found_localhost6 = TRUE; - custom6 = get_custom_hostnames (*line, hostname, old_hostname, short_hostname, fallback_hostname6); - if (!ip6_addr) { - /* If there's no IP-specific mapping for the current hostname - * but that hostname is present on in the local mapping line, - * we've found our IPv6 hostname mapping. If the hostname is - * the fallback *IPv4* hostname it's not going to show up in - * the IPv6 local mapping though, so fake it. - */ - if (hostname4_is_fallback || found_hostname) - found_host6 = TRUE; - } + /* Remove "# Added ..." lines */ + lines = g_strsplit_set (contents, "\n\r", -1); + for (iter = lines; iter && *iter; iter++) { + if (!strstr (*iter, ADDED_TAG)) { + g_string_append (new_contents, *iter); + g_string_append_c (new_contents, '\n'); } - - if ( found_localhost4 - && found_host4 - && found_localhost6 - && found_host6 - && host4_before - && host6_before - && no_stale) - goto out; /* No update required */ - } - - contents = g_string_sized_new (existing_len ? existing_len + 100 : 200); - if (!contents) { - g_set_error_literal (error, 0, 0, "not enough memory"); - goto out; } + g_strfreev (lines); - /* Construct the new hosts file; replace any 127.0.0.1/::1 entry that is - * at the beginning of the file or right after initial comments and contains - * the string 'localhost' (for IPv4) or 'localhost6' (for IPv6). If there - * is no 127.0.0.1 or ::1 entry at the beginning or after initial comments - * that contains 'localhost' or 'localhost6', add one there - * and ignore any other 127.0.0.1/::1 entries that contain 'localhost' or - * 'localhost6'. + /* Remove last blank line at end of file, if one exists; this is + * an artifact of how g_strsplit_set() works. */ - for (line = lines, initial_comments = TRUE; lines && *line; line++) { - /* This is the first line after the initial comments */ - if (strlen (*line) && initial_comments && (*line[0] != '#')) { - initial_comments = FALSE; - - /* If the user added their own mapping for the hostname, just make - * a simple 'localhost' mapping and assume the user knows what they - * are doing with their manual hostname entry. Otherwise if the - * hostname wasn't found somewhere else, add it to the localhost - * mapping line to make sure it's mapped to something. - */ - - /* Add the address mappings first so they take precedence */ - if (!hostname4_is_fallback && ip4_addr && !found_user_host4) { - g_string_append_printf (contents, "%s\t%s", ip4_addr, hostname); - if (short_hostname) - g_string_append_printf (contents, "\t%s", short_hostname); - g_string_append_printf (contents, "\t%s\n", ADDED_TAG); - } - if (!hostname6_is_fallback && ip6_addr && !found_user_host6) { - g_string_append_printf (contents, "%s\t%s", ip6_addr, hostname); - if (short_hostname) - g_string_append_printf (contents, "\t%s", short_hostname); - g_string_append_printf (contents, "\t%s\n", ADDED_TAG); - } + if ( (new_contents->len > 2) + && (new_contents->str[new_contents->len - 1] == '\n')) + g_string_truncate (new_contents, new_contents->len - 1); - /* IPv4 localhost line */ - g_string_append (contents, "127.0.0.1"); - if (!hostname4_is_fallback && !ip4_addr && !found_user_host4) { - g_string_append_printf (contents, "\t%s", hostname); - if (short_hostname) - g_string_append_printf (contents, "\t%s", short_hostname); - } - g_string_append_printf (contents, "\t%s\tlocalhost", fallback_hostname4); - if (custom4) - g_string_append (contents, custom4); - g_string_append_c (contents, '\n'); - - /* IPv6 localhost line */ - g_string_append (contents, "::1"); - if (!hostname6_is_fallback && !hostname4_is_fallback && !ip6_addr && !found_user_host6) { - g_string_append_printf (contents, "\t%s", hostname); - if (short_hostname) - g_string_append_printf (contents, "\t%s", short_hostname); - } - g_string_append_printf (contents, "\t%s\tlocalhost6", fallback_hostname6); - if (custom6) - g_string_append (contents, custom6); - g_string_append_c (contents, '\n'); - - added = TRUE; - } - - /* Don't add the original line if it is a localhost mapping */ - if ( !is_local_mapping (*line, FALSE, "localhost") - && !is_local_mapping (*line, FALSE, fallback_hostname4) - && !is_local_mapping (*line, FALSE, hostname) - && !is_local_mapping (*line, TRUE, "localhost6") - && !is_local_mapping (*line, TRUE, fallback_hostname6) - && !is_local_mapping (*line, TRUE, hostname) - && !strstr (*line, ADDED_TAG)) { - - g_string_append (contents, *line); - /* Only append the new line if this isn't the last line in the file */ - if (*(line+1)) - g_string_append_c (contents, '\n'); - } - } - - /* Hmm, /etc/hosts was empty for some reason */ - if (!added) { - g_string_append (contents, "# Do not remove the following lines, or various programs\n"); - g_string_append (contents, "# that require network functionality will fail.\n"); - - /* Add the address mappings first so they take precedence */ - if (!hostname4_is_fallback && ip4_addr) { - g_string_append_printf (contents, "%s\t%s", ip4_addr, hostname); - if (short_hostname) - g_string_append_printf (contents, "\t%s", short_hostname); - g_string_append_printf (contents, "\t%s\n", ADDED_TAG); - } - if (!hostname6_is_fallback && ip6_addr) { - g_string_append_printf (contents, "%s\t%s", ip6_addr, hostname); - if (short_hostname) - g_string_append_printf (contents, "\t%s", short_hostname); - g_string_append_printf (contents, "\t%s\n", ADDED_TAG); - } - - g_string_append_printf (contents, "127.0.0.1\t%s\tlocalhost\n", fallback_hostname4); - g_string_append_printf (contents, "::1\t%s\tlocalhost6\n", fallback_hostname6); - } - -out: - g_free (custom4); - g_free (custom6); - g_free (short_hostname); - return contents; + return new_contents; } -gboolean -nm_policy_hosts_update_etc_hosts (const char *hostname, - const char *old_hostname, - const char *fallback_hostname4, - const char *fallback_hostname6, - const char *ip4_addr, - const char *ip6_addr, - gboolean *out_changed) +/* remove any leftover "# Added by NetworkManager" lines */ +void +nm_policy_hosts_clean_etc_hosts (void) { char *contents = NULL; - char **lines = NULL; - GError *error = NULL; - GString *new_contents = NULL; gsize contents_len = 0; - gboolean success = FALSE; - - g_return_val_if_fail (hostname != NULL, FALSE); - g_return_val_if_fail (out_changed != NULL, FALSE); + GError *error = NULL; + GString *new; if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) { nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s", error ? error->code : 0, (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); - return FALSE; + return; } - /* Get the new /etc/hosts contents */ - lines = g_strsplit_set (contents, "\n\r", 0); - new_contents = nm_policy_get_etc_hosts ((const char **) lines, - contents_len, - hostname, - old_hostname, - fallback_hostname4, - fallback_hostname6, - ip4_addr, - ip6_addr, - &error); - g_strfreev (lines); - g_free (contents); - - if (new_contents) { - nm_log_info (LOGD_DNS, "Updating /etc/hosts with new system hostname"); + new = nm_policy_get_etc_hosts (contents, contents_len); + if (new && new->len) { + nm_log_info (LOGD_DNS, "Cleaning leftovers from /etc/hosts"); g_clear_error (&error); - /* And actually update /etc/hosts */ - if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) { - nm_log_warn (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s", - error ? error->code : 0, - (error && error->message) ? error->message : "(unknown)"); + if (!g_file_set_contents (SYSCONFDIR "/hosts", new->str, -1, &error)) { + nm_log_dbg (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s", + error ? error->code : 0, + (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); - } else { - success = TRUE; - *out_changed = TRUE; } - - g_string_free (new_contents, TRUE); - } else if (!error) { - /* No change required */ - success = TRUE; - } else { - nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); - g_clear_error (&error); } - return success; + if (new) + g_string_free (new, TRUE); } diff --git a/src/nm-policy-hosts.h b/src/nm-policy-hosts.h index ebaaf0fd41..9f4bf9a9a9 100644 --- a/src/nm-policy-hosts.h +++ b/src/nm-policy-hosts.h @@ -23,26 +23,10 @@ #include <glib.h> -gboolean nm_policy_hosts_update_etc_hosts (const char *hostname, - const char *old_hostname, - const char *fallback_hostname4, - const char *fallback_hostname6, - const char *ip4_addr, - const char *ip6_addr, - gboolean *out_changed); +void nm_policy_hosts_clean_etc_hosts (void); /* Only for testcases; don't use outside of nm-policy-hosts.c */ -gboolean nm_policy_hosts_find_token (const char *line, const char *token); - -GString *nm_policy_get_etc_hosts (const char **lines, - gsize existing_len, - const char *hostname, - const char *old_hostname, - const char *fallback_hostname4, - const char *fallback_hostname6, - const char *ip4_addr, - const char *ip6_addr, - GError **error); +GString *nm_policy_get_etc_hosts (const char *contents, gsize contents_len); #endif /* NM_POLICY_HOSTS_H */ diff --git a/src/nm-policy.c b/src/nm-policy.c index 6ee493cc18..2961389b7a 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -36,13 +36,15 @@ #include "nm-device-wifi.h" #include "nm-device-ethernet.h" #include "nm-device-modem.h" +#if WITH_WIMAX +#include "nm-device-wimax.h" +#endif #include "nm-dbus-manager.h" #include "nm-setting-ip4-config.h" #include "nm-setting-connection.h" #include "nm-system.h" #include "nm-dns-manager.h" #include "nm-vpn-manager.h" -#include "nm-policy-hosts.h" #include "nm-policy-hostname.h" struct NMPolicy { @@ -238,9 +240,6 @@ _set_hostname (NMPolicy *policy, const char *new_hostname, const char *msg) { - char ip4_addr[INET_ADDRSTRLEN + 1]; - char ip6_addr[INET6_ADDRSTRLEN + 1]; - if (change_hostname) { NMDnsManager *dns_mgr; @@ -252,43 +251,7 @@ _set_hostname (NMPolicy *policy, g_object_unref (dns_mgr); } - /* Get the default IPv4 and IPv6 addresses so we can assign - * the hostname to them in /etc/hosts. - */ - memset (ip4_addr, 0, sizeof (ip4_addr)); - if (policy->default_device4) { - NMIP4Config *config = NULL; - NMIP4Address *addr = NULL; - - config = nm_device_get_ip4_config (policy->default_device4); - if (config) - addr = nm_ip4_config_get_address (config, 0); - - if (addr) { - struct in_addr tmp; - - tmp.s_addr = nm_ip4_address_get_address (addr); - inet_ntop (AF_INET, &tmp, ip4_addr, sizeof (ip4_addr)); - } - } - - memset (ip6_addr, 0, sizeof (ip6_addr)); - if (policy->default_device6) { - NMIP6Config *config = NULL; - NMIP6Address *addr = NULL; - - config = nm_device_get_ip6_config (policy->default_device6); - if (config) - addr = nm_ip6_config_get_address (config, 0); - - if (addr) - inet_ntop (AF_INET6, nm_ip6_address_get_address (addr), ip6_addr, sizeof (ip6_addr)); - } - - if (nm_policy_set_system_hostname (policy->cur_hostname, - strlen (ip4_addr) ? ip4_addr : NULL, - strlen (ip6_addr) ? ip6_addr : NULL, - msg)) + if (nm_policy_set_system_hostname (policy->cur_hostname, msg)) nm_utils_call_dispatcher ("hostname", NULL, NULL, NULL); } @@ -977,6 +940,14 @@ wireless_networks_changed (NMDeviceWifi *device, NMAccessPoint *ap, gpointer use schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device), 0); } +#if WITH_WIMAX +static void +nsps_changed (NMDeviceWimax *device, NMWimaxNsp *nsp, gpointer user_data) +{ + schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device), 0); +} +#endif + typedef struct { gulong id; NMDevice *device; @@ -1006,6 +977,11 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data) if (NM_IS_DEVICE_WIFI (device)) { _connect_device_signal (policy, device, "access-point-added", wireless_networks_changed); _connect_device_signal (policy, device, "access-point-removed", wireless_networks_changed); +#if WITH_WIMAX + } else if (NM_IS_DEVICE_WIMAX (device)) { + _connect_device_signal (policy, device, "nsp-added", nsps_changed); + _connect_device_signal (policy, device, "nsp-removed", nsps_changed); +#endif } } @@ -1239,15 +1215,6 @@ nm_policy_destroy (NMPolicy *policy) } g_slist_free (policy->dev_ids); - /* Rewrite /etc/hosts on exit to ensure we don't leave stale IP addresses - * lying around. FIXME: this will take out a valid IP address of an - * ethernet device we're leaving active (ie, a connection we can "assume" - * when NM starts again). - */ - policy->default_device4 = NULL; - policy->default_device6 = NULL; - update_system_hostname (policy, NULL, NULL); - g_free (policy->orig_hostname); g_free (policy->cur_hostname); diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index ff0ef68c81..5e3da0b8d6 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -15,9 +15,10 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2009 - 2010 Red Hat, Inc. + * Copyright (C) 2009 - 2011 Red Hat, Inc. */ +#include <config.h> #include <signal.h> #include <string.h> #include <stdlib.h> @@ -38,6 +39,9 @@ #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" #include "nm-device-ethernet.h" +#if WITH_WIMAX +#include "nm-device-wimax.h" +#endif typedef struct { GUdevClient *client; @@ -335,6 +339,15 @@ is_olpc_mesh (GUdevDevice *device) return (prop != NULL); } +static gboolean +is_wimax (const char *driver) +{ + /* FIXME: check 'DEVTYPE' instead; but since we only support Intel + * WiMAX devices for now this is appropriate. + */ + return g_strcmp0 (driver, "i2400m_usb") == 0; +} + static GObject * device_creator (NMUdevManager *manager, GUdevDevice *udev_device, @@ -387,7 +400,11 @@ device_creator (NMUdevManager *manager, device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver); else if (is_wireless (udev_device)) device = (GObject *) nm_device_wifi_new (path, ifname, driver); - else + else if (is_wimax (driver)) { +#if WITH_WIMAX + device = (GObject *) nm_device_wimax_new (path, ifname, driver); +#endif + } else device = (GObject *) nm_device_ethernet_new (path, ifname, driver); out: diff --git a/src/nm-wifi-ap.c b/src/nm-wifi-ap.c index e596a08b8c..d216ea6a90 100644 --- a/src/nm-wifi-ap.c +++ b/src/nm-wifi-ap.c @@ -22,6 +22,7 @@ #include "wireless-helper.h" #include <string.h> +#include <stdlib.h> #include "nm-wifi-ap.h" #include "nm-wifi-ap-utils.h" @@ -370,10 +371,69 @@ NMAccessPoint *nm_ap_new (void) return (NMAccessPoint *) object; } +static guint32 +pair_to_flags (const char *str) +{ + g_return_val_if_fail (str != NULL, NM_802_11_AP_SEC_NONE); + + if (strcmp (str, "wep40") == 0) + return NM_802_11_AP_SEC_PAIR_WEP40; + if (strcmp (str, "wep104") == 0) + return NM_802_11_AP_SEC_PAIR_WEP104; + if (strcmp (str, "tkip") == 0) + return NM_802_11_AP_SEC_PAIR_TKIP; + if (strcmp (str, "ccmp") == 0) + return NM_802_11_AP_SEC_PAIR_CCMP; + return NM_802_11_AP_SEC_NONE; +} + +static guint32 +group_to_flags (const char *str) +{ + g_return_val_if_fail (str != NULL, NM_802_11_AP_SEC_NONE); + + if (strcmp (str, "wep40") == 0) + return NM_802_11_AP_SEC_GROUP_WEP40; + if (strcmp (str, "wep104") == 0) + return NM_802_11_AP_SEC_GROUP_WEP104; + if (strcmp (str, "tkip") == 0) + return NM_802_11_AP_SEC_GROUP_TKIP; + if (strcmp (str, "ccmp") == 0) + return NM_802_11_AP_SEC_GROUP_CCMP; + return NM_802_11_AP_SEC_NONE; +} -#define IEEE80211_CAP_ESS 0x0001 -#define IEEE80211_CAP_IBSS 0x0002 -#define IEEE80211_CAP_PRIVACY 0x0010 +static guint32 +security_from_dict (GHashTable *security) +{ + GValue *value; + guint32 flags = NM_802_11_AP_SEC_NONE; + const char **items, **iter; + + value = g_hash_table_lookup (security, "KeyMgmt"); + if (value) { + items = g_value_get_boxed (value); + for (iter = items; iter && *iter; iter++) { + if (strcmp (*iter, "wpa-psk") == 0) + flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (strcmp (*iter, "wpa-eap") == 0) + flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; + } + } + + value = g_hash_table_lookup (security, "Pairwise"); + if (value) { + items = g_value_get_boxed (value); + for (iter = items; iter && *iter; iter++) + flags |= pair_to_flags (*iter); + } + + value = g_hash_table_lookup (security, "Group"); + if (value) + flags |= group_to_flags (g_value_get_string (value)); + + return flags; +} static void foreach_property_cb (gpointer key, gpointer value, gpointer user_data) @@ -384,9 +444,9 @@ foreach_property_cb (gpointer key, gpointer value, gpointer user_data) if (G_VALUE_HOLDS_BOXED (variant)) { GArray *array = g_value_get_boxed (variant); - if (!strcmp (key, "ssid")) { + if (!strcmp (key, "SSID")) { guint32 len = MIN (IW_ESSID_MAX_SIZE, array->len); - GByteArray * ssid; + GByteArray *ssid; /* Stupid ieee80211 layer uses <hidden> */ if (((len == 8) || (len == 9)) @@ -400,7 +460,7 @@ foreach_property_cb (gpointer key, gpointer value, gpointer user_data) g_byte_array_append (ssid, (const guint8 *) array->data, len); nm_ap_set_ssid (ap, ssid); g_byte_array_free (ssid, TRUE); - } else if (!strcmp (key, "bssid")) { + } else if (!strcmp (key, "BSSID")) { struct ether_addr addr; if (array->len != ETH_ALEN) @@ -408,43 +468,62 @@ foreach_property_cb (gpointer key, gpointer value, gpointer user_data) memset (&addr, 0, sizeof (struct ether_addr)); memcpy (&addr, array->data, ETH_ALEN); nm_ap_set_address (ap, &addr); - } else if (!strcmp (key, "wpaie")) { - guint8 * ie = (guint8 *) array->data; + } else if (!strcmp (key, "Rates")) { + guint32 maxrate = 0; + int i; + + /* Find the max AP rate */ + for (i = 0; i < array->len; i++) { + guint32 r = g_array_index (array, guint32, i); + + if (r > maxrate) { + maxrate = r; + nm_ap_set_max_bitrate (ap, r / 1000); + } + } + } else if (!strcmp (key, "WPA")) { guint32 flags = nm_ap_get_wpa_flags (ap); - if (array->len <= 0 || array->len > WPA_MAX_IE_LEN) - return; - flags = nm_ap_add_security_from_ie (flags, ie, array->len); + flags |= security_from_dict (g_value_get_boxed (variant)); nm_ap_set_wpa_flags (ap, flags); - } else if (!strcmp (key, "rsnie")) { - guint8 * ie = (guint8 *) array->data; + } else if (!strcmp (key, "RSN")) { guint32 flags = nm_ap_get_rsn_flags (ap); - if (array->len <= 0 || array->len > WPA_MAX_IE_LEN) - return; - flags = nm_ap_add_security_from_ie (flags, ie, array->len); + flags |= security_from_dict (g_value_get_boxed (variant)); nm_ap_set_rsn_flags (ap, flags); } + } else if (G_VALUE_HOLDS_UINT (variant)) { + guint32 val = g_value_get_uint (variant); + + if (!strcmp (key, "Frequency")) + nm_ap_set_freq (ap, val); } else if (G_VALUE_HOLDS_INT (variant)) { - gint32 int_val = g_value_get_int (variant); + gint val = g_value_get_int (variant); + + if (!strcmp (key, "Signal")) { + if (val < 0) { + /* Rough conversion: best = -40, worst = -100 */ + val = abs (CLAMP (val, -100, -40) + 40); + val = 100 - (int) ((100.0 * (double) val) / 60.0); + } else + val /= 100; - if (!strcmp (key, "frequency")) { - nm_ap_set_freq (ap, (guint32) int_val); - } else if (!strcmp (key, "maxrate")) { - /* Supplicant reports as b/s, we use Kb/s internally */ - nm_ap_set_max_bitrate (ap, int_val / 1000); + nm_ap_set_strength (ap, val); } - } else if (G_VALUE_HOLDS_UINT (variant)) { - guint32 val = g_value_get_uint (variant); + } else if (G_VALUE_HOLDS_STRING (variant)) { + const char *val = g_value_get_string (variant); - if (!strcmp (key, "capabilities")) { - if (val & IEEE80211_CAP_ESS) { + if (val && !strcmp (key, "Mode")) { + if (strcmp (val, "infrastructure") == 0) nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); - } else if (val & IEEE80211_CAP_IBSS) { + else if (strcmp (val, "ad-hoc") == 0) nm_ap_set_mode (ap, NM_802_11_MODE_ADHOC); - } + } + } else if (G_VALUE_HOLDS_BOOLEAN (variant)) { + gboolean val = g_value_get_boolean (variant); - if (val & IEEE80211_CAP_PRIVACY) { + if (strcmp (key, "Privacy") == 0) { + if (val) { guint32 flags = nm_ap_get_flags (ap); nm_ap_set_flags (ap, flags | NM_802_11_AP_FLAGS_PRIVACY); } @@ -452,7 +531,6 @@ foreach_property_cb (gpointer key, gpointer value, gpointer user_data) } } - NMAccessPoint * nm_ap_new_from_properties (GHashTable *properties) { @@ -1171,45 +1249,6 @@ void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list) } -guint32 -nm_ap_add_security_from_ie (guint32 flags, - const guint8 *wpa_ie, - guint32 length) -{ - wpa_ie_data * cap_data; - - if (!(cap_data = wpa_parse_wpa_ie (wpa_ie, length))) - return NM_802_11_AP_SEC_NONE; - - /* Pairwise cipher flags */ - if (cap_data->pairwise_cipher & IW_AUTH_CIPHER_WEP40) - flags |= NM_802_11_AP_SEC_PAIR_WEP40; - if (cap_data->pairwise_cipher & IW_AUTH_CIPHER_WEP104) - flags |= NM_802_11_AP_SEC_PAIR_WEP104; - if (cap_data->pairwise_cipher & IW_AUTH_CIPHER_TKIP) - flags |= NM_802_11_AP_SEC_PAIR_TKIP; - if (cap_data->pairwise_cipher & IW_AUTH_CIPHER_CCMP) - flags |= NM_802_11_AP_SEC_PAIR_CCMP; - - /* Group cipher flags */ - if (cap_data->group_cipher & IW_AUTH_CIPHER_WEP40) - flags |= NM_802_11_AP_SEC_GROUP_WEP40; - if (cap_data->group_cipher & IW_AUTH_CIPHER_WEP104) - flags |= NM_802_11_AP_SEC_GROUP_WEP104; - if (cap_data->group_cipher & IW_AUTH_CIPHER_TKIP) - flags |= NM_802_11_AP_SEC_GROUP_TKIP; - if (cap_data->group_cipher & IW_AUTH_CIPHER_CCMP) - flags |= NM_802_11_AP_SEC_GROUP_CCMP; - - if (cap_data->key_mgmt & IW_AUTH_KEY_MGMT_802_1X) - flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; - if (cap_data->key_mgmt & IW_AUTH_KEY_MGMT_PSK) - flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; - - g_slice_free (wpa_ie_data, cap_data); - return flags; -} - gboolean nm_ap_check_compatible (NMAccessPoint *self, NMConnection *connection) diff --git a/src/nm-wifi-ap.h b/src/nm-wifi-ap.h index 62457765f4..2a10d3505d 100644 --- a/src/nm-wifi-ap.h +++ b/src/nm-wifi-ap.h @@ -110,10 +110,6 @@ void nm_ap_set_user_created (NMAccessPoint *ap, gboolean user_created); GSList * nm_ap_get_user_addresses (const NMAccessPoint *ap); void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list); -guint32 nm_ap_add_security_from_ie (guint32 flags, - const guint8 *wpa_ie, - guint32 length); - gboolean nm_ap_check_compatible (NMAccessPoint *self, NMConnection *connection); diff --git a/src/settings/nm-default-wired-connection.c b/src/settings/nm-default-wired-connection.c index b2c22baf3c..63683480e2 100644 --- a/src/settings/nm-default-wired-connection.c +++ b/src/settings/nm-default-wired-connection.c @@ -149,7 +149,7 @@ constructor (GType type, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_READ_ONLY, priv->read_only, - NM_SETTING_CONNECTION_TIMESTAMP, time (NULL), + NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL), NULL); g_free (id); diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index bad8f26634..93807b9360 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -34,23 +34,20 @@ #include "nm-glib-compat.h" #define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" -#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID" +#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS" #define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" #define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface" -#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".ExistsError" +#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists" +G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) -static void wpas_iface_handle_state_change (DBusGProxy *proxy, - const char *str_new_state, - const char *str_old_state, - gpointer user_data); - -static void wpas_iface_handle_scanning (DBusGProxy *proxy, - gboolean scanning, - gpointer user_data); +static void wpas_iface_properties_changed (DBusGProxy *proxy, + GHashTable *props, + gpointer user_data); - -G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) +static void wpas_iface_scan_done (DBusGProxy *proxy, + gboolean success, + gpointer user_data); #define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SUPPLICANT_INTERFACE, \ @@ -60,9 +57,8 @@ G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) enum { STATE, /* change in the interface's state */ REMOVED, /* interface was removed by the supplicant */ - SCANNED_AP, /* interface saw a new access point from a scan */ - SCAN_REQ_RESULT, /* result of a wireless scan request */ - SCAN_RESULTS, /* scan results returned from supplicant */ + NEW_BSS, /* interface saw a new access point from a scan */ + SCAN_DONE, /* wifi scan is complete */ CONNECTION_ERROR, /* an error occurred during a connection request */ LAST_SIGNAL }; @@ -72,7 +68,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; /* Properties */ enum { PROP_0 = 0, - PROP_STATE, PROP_SCANNING, LAST_PROP }; @@ -94,9 +89,10 @@ typedef struct { DBusGProxy * wpas_proxy; DBusGProxy * iface_proxy; - DBusGProxy * net_proxy; + DBusGProxy * props_proxy; + char * net_path; + guint32 blobs_left; - guint scan_results_timeout; guint32 last_scan; NMSupplicantConfig * cfg; @@ -199,143 +195,79 @@ static void bssid_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - GError *err = NULL; - GHashTable *hash = NULL; + GError *error = NULL; + GHashTable *props = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &hash, - G_TYPE_INVALID)) { - if (!strstr (err->message, "The BSSID requested was invalid")) { + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_signal_emit (info->interface, signals[NEW_BSS], 0, props); + g_hash_table_destroy (props); + } else { + if (!strstr (error->message, "The BSSID requested was invalid")) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't retrieve BSSID properties: %s.", - err->message); + error->message); } - g_error_free (err); - } else { - g_signal_emit (info->interface, signals[SCANNED_AP], 0, hash); - g_hash_table_destroy (hash); + g_error_free (error); } } static void -request_bssid_properties (NMSupplicantInterface * self, - const char * op) +request_bss_properties (NMSupplicantInterface *self, + GPtrArray *paths) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - NMSupplicantInfo *info; - DBusGProxy *proxy; - DBusGProxyCall *call; - - proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - op, - WPAS_DBUS_IFACE_BSSID); - info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (proxy, "properties", - bssid_properties_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - g_object_unref (proxy); -} - -static void -scan_results_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - GError *err = NULL; - GPtrArray *array = NULL; - - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &array, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_SUPPLICANT, "could not get scan results: %s.", err->message); - g_error_free (err); - } else { - int i; - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - - /* Notify listeners of the result of the scan */ - g_signal_emit (info->interface, signals[SCAN_RESULTS], 0, array->len); + int i; - /* Fire off a "properties" call for each returned BSSID */ - for (i = 0; i < array->len; i++) { - char *op = g_ptr_array_index (array, i); - - request_bssid_properties (info->interface, op); - g_free (op); - } + /* Fire off a "properties" call for each returned BSSID */ + for (i = 0; i < paths->len; i++) { + NMSupplicantInfo *info; + DBusGProxy *proxy; + DBusGProxyCall *call; - g_ptr_array_free (array, TRUE); + proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + WPAS_DBUS_SERVICE, + g_ptr_array_index (paths, i), + DBUS_INTERFACE_PROPERTIES); + info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (proxy, "GetAll", + bssid_properties_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_STRING, WPAS_DBUS_IFACE_BSS, + G_TYPE_INVALID); + nm_supplicant_info_set_call (info, call); + g_object_unref (proxy); } } -static gboolean -request_scan_results (gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - NMSupplicantInfo *info; - DBusGProxyCall *call; - GTimeVal cur_time; - - priv->scan_results_timeout = 0; - - g_return_val_if_fail (priv->iface_proxy != NULL, FALSE); - - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanResults", - scan_results_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - - g_get_current_time (&cur_time); - priv->last_scan = cur_time.tv_sec; - return FALSE; -} - static void -wpas_iface_query_scan_results (DBusGProxy *proxy, gpointer user_data) +wpas_iface_bss_added (DBusGProxy *proxy, + const char *object_path, + GHashTable *props, + gpointer user_data) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); - GTimeVal cur_time; - - /* Only query scan results if a query is not queued */ - if (priv->scan_results_timeout) - return; - - g_get_current_time (&cur_time); - - /* Only fetch scan results every 4s max, but initially do it right away */ - if (priv->last_scan + 4 < cur_time.tv_sec) { - priv->scan_results_timeout = g_idle_add (request_scan_results, - user_data); - } else { - priv->scan_results_timeout = - g_timeout_add_seconds ((4 - (cur_time.tv_sec - priv->last_scan)), - request_scan_results, user_data); - } + g_signal_emit (NM_SUPPLICANT_INTERFACE (user_data), signals[NEW_BSS], 0, props); } static int wpas_state_string_to_enum (const char *str_state) { - if (!strcmp (str_state, "DISCONNECTED")) + if (!strcmp (str_state, "disconnected")) return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; - else if (!strcmp (str_state, "INACTIVE")) + else if (!strcmp (str_state, "inactive")) return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; - else if (!strcmp (str_state, "SCANNING")) + else if (!strcmp (str_state, "scanning")) return NM_SUPPLICANT_INTERFACE_STATE_SCANNING; - else if (!strcmp (str_state, "ASSOCIATING")) + else if (!strcmp (str_state, "associating")) return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING; - else if (!strcmp (str_state, "ASSOCIATED")) + else if (!strcmp (str_state, "associated")) return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED; - else if (!strcmp (str_state, "4WAY_HANDSHAKE")) + else if (!strcmp (str_state, "4way_handshake")) return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE; - else if (!strcmp (str_state, "GROUP_HANDSHAKE")) + else if (!strcmp (str_state, "group_handshake")) return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE; - else if (!strcmp (str_state, "COMPLETED")) + else if (!strcmp (str_state, "completed")) return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED; return -1; @@ -355,9 +287,9 @@ set_state (NMSupplicantInterface *self, guint32 new_state) /* DOWN is a terminal state */ g_return_if_fail (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DOWN); - /* Cannot regress to READY or INIT from higher states */ - if (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_READY) - g_return_if_fail (new_state > priv->state); + /* Cannot regress to READY, STARTING, or INIT from higher states */ + if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) + g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY); if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { /* Cancel all pending calls when going down */ @@ -372,18 +304,16 @@ set_state (NMSupplicantInterface *self, guint32 new_state) if (priv->iface_proxy) { dbus_g_proxy_disconnect_signal (priv->iface_proxy, - "StateChange", - G_CALLBACK (wpas_iface_handle_state_change), + "PropertiesChanged", + G_CALLBACK (wpas_iface_properties_changed), self); - dbus_g_proxy_disconnect_signal (priv->iface_proxy, - "ScanResultsAvailable", - G_CALLBACK (wpas_iface_query_scan_results), + "ScanDone", + G_CALLBACK (wpas_iface_scan_done), self); - dbus_g_proxy_disconnect_signal (priv->iface_proxy, - "Scanning", - G_CALLBACK (wpas_iface_handle_scanning), + "BSSAdded", + G_CALLBACK (wpas_iface_bss_added), self); } } @@ -392,123 +322,125 @@ set_state (NMSupplicantInterface *self, guint32 new_state) g_signal_emit (self, signals[STATE], 0, priv->state, old_state); } -/* Supplicant state signal handler */ static void -wpas_iface_handle_state_change (DBusGProxy *proxy, - const char *str_new_state, - const char *str_old_state, - gpointer user_data) +set_state_from_string (NMSupplicantInterface *self, const char *new_state) { - int enum_state = wpas_state_string_to_enum (str_new_state); - - g_return_if_fail (enum_state > 0); + int state; - set_state (NM_SUPPLICANT_INTERFACE (user_data), (guint32) enum_state); + state = wpas_state_string_to_enum (new_state); + g_warn_if_fail (state > 0); + if (state > 0) + set_state (self, (guint32) state); } -/* Explicit state request reply handler */ static void -iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +set_scanning (NMSupplicantInterface *self, gboolean new_scanning) { - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - GError *err = NULL; - char *state_str = NULL; - int enum_state; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + GTimeVal cur_time; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_STRING, &state_str, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_SUPPLICANT, "could not get interface state: %s.", err->message); - g_error_free (err); - } else { - enum_state = wpas_state_string_to_enum (state_str); - g_warn_if_fail (enum_state > 0); + if (priv->scanning != new_scanning) { + priv->scanning = new_scanning; + + /* Cache time of last scan completion */ + if (priv->scanning == FALSE) { + g_get_current_time (&cur_time); + priv->last_scan = cur_time.tv_sec; + } - if (enum_state > 0) - set_state (info->interface, (guint32) enum_state); - g_free (state_str); + g_object_notify (G_OBJECT (self), "scanning"); } } +gboolean +nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) +{ + NMSupplicantInterfacePrivate *priv; + + g_return_val_if_fail (self != NULL, FALSE); + + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + if (priv->scanning) + return TRUE; + if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) + return TRUE; + return FALSE; +} + static void -wpas_iface_get_state (NMSupplicantInterface *self) +wpas_iface_scan_done (DBusGProxy *proxy, + gboolean success, + gpointer user_data) { + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - NMSupplicantInfo *info; - DBusGProxyCall *call; + GTimeVal cur_time; - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "state", - iface_state_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); + /* Cache last scan completed time */ + g_get_current_time (&cur_time); + priv->last_scan = cur_time.tv_sec; + + g_signal_emit (self, signals[SCAN_DONE], 0, success); +} + +static void +wpas_iface_properties_changed (DBusGProxy *proxy, + GHashTable *props, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + GValue *value; + + value = g_hash_table_lookup (props, "Scanning"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) + set_scanning (self, g_value_get_boolean (value)); + + value = g_hash_table_lookup (props, "State"); + if (value && G_VALUE_HOLDS_STRING (value)) + set_state_from_string (self, g_value_get_string (value)); + + value = g_hash_table_lookup (props, "BSSs"); + if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH)) + request_bss_properties (self, g_value_get_boxed (value)); } static void -iface_scanning_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +iface_get_props_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - gboolean scanning = FALSE; + GHashTable *props = NULL; + GError *error = NULL; - if (dbus_g_proxy_end_call (proxy, call_id, NULL, - G_TYPE_BOOLEAN, &scanning, - G_TYPE_INVALID)) { - if (scanning != priv->scanning) { - priv->scanning = scanning; - g_object_notify (G_OBJECT (info->interface), "scanning"); - } + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + wpas_iface_properties_changed (NULL, props, info->interface); + g_hash_table_destroy (props); + } else { + nm_log_warn (LOGD_SUPPLICANT, "could not get interface properties: %s.", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); } } static void -wpas_iface_get_scanning (NMSupplicantInterface *self) +wpas_iface_get_props (NMSupplicantInterface *self) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); NMSupplicantInfo *info; DBusGProxyCall *call; - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanning", - iface_scanning_cb, + info = nm_supplicant_info_new (self, priv->props_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", + iface_get_props_cb, info, nm_supplicant_info_destroy, + G_TYPE_STRING, WPAS_DBUS_IFACE_INTERFACE, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } static void -wpas_iface_handle_scanning (DBusGProxy *proxy, - gboolean scanning, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (scanning != priv->scanning) { - priv->scanning = scanning; - g_object_notify (G_OBJECT (self), "scanning"); - } -} - -gboolean -nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_val_if_fail (self != NULL, FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (priv->scanning) - return TRUE; - if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) - return TRUE; - return FALSE; -} - -static void interface_add_done (NMSupplicantInterface *self, char *path) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); @@ -522,31 +454,38 @@ interface_add_done (NMSupplicantInterface *self, char *path) path, WPAS_DBUS_IFACE_INTERFACE); - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING, + dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, + DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->iface_proxy, "StateChange", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->iface_proxy, "StateChange", - G_CALLBACK (wpas_iface_handle_state_change), - self, - NULL); - - dbus_g_proxy_add_signal (priv->iface_proxy, "ScanResultsAvailable", G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanResultsAvailable", - G_CALLBACK (wpas_iface_query_scan_results), + dbus_g_proxy_add_signal (priv->iface_proxy, "PropertiesChanged", + DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "PropertiesChanged", + G_CALLBACK (wpas_iface_properties_changed), + self, NULL); + + dbus_g_proxy_add_signal (priv->iface_proxy, "ScanDone", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanDone", + G_CALLBACK (wpas_iface_scan_done), self, NULL); - dbus_g_proxy_add_signal (priv->iface_proxy, "Scanning", G_TYPE_BOOLEAN, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->iface_proxy, "Scanning", - G_CALLBACK (wpas_iface_handle_scanning), + 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->iface_proxy, "BSSAdded", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "BSSAdded", + G_CALLBACK (wpas_iface_bss_added), self, NULL); - /* Interface added to the supplicant; get its initial state. */ - wpas_iface_get_state (self); - wpas_iface_get_scanning (self); + priv->props_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + WPAS_DBUS_SERVICE, + path, + DBUS_INTERFACE_PROPERTIES); + /* Get initial properties */ + wpas_iface_get_props (self); set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); } @@ -566,9 +505,10 @@ interface_get_cb (DBusGProxy *proxy, G_TYPE_INVALID)) { interface_add_done (info->interface, path); } else { - nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", + nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message); g_clear_error (&error); + set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } } @@ -580,7 +520,7 @@ interface_get (NMSupplicantInterface *self) DBusGProxyCall *call; info = nm_supplicant_info_new (self, priv->wpas_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->wpas_proxy, "getInterface", + call = dbus_g_proxy_begin_call (priv->wpas_proxy, "GetInterface", interface_get_cb, info, nm_supplicant_info_destroy, @@ -607,9 +547,19 @@ interface_add_cb (DBusGProxy *proxy, if (dbus_g_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { /* Interface already added, just get its object path */ interface_get (info->interface); + } else if ( g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN) + || dbus_g_error_has_name (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { + /* Supplicant wasn't running and could be launched via service + * activation. Wait for it to start by moving back to the INIT + * state. + */ + nm_log_dbg (LOGD_SUPPLICANT, "(%s): failed to activate supplicant: %s", + priv->dev, error->message); + set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_INIT); } else { nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", priv->dev, error->message); + set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } g_clear_error (&error); } @@ -622,7 +572,7 @@ interface_add (NMSupplicantInterface *self, gboolean is_wireless) DBusGProxyCall *call; NMSupplicantInfo *info; GHashTable *hash; - GValue *driver; + GValue *driver, *ifname; /* Can only start the interface from INIT state */ g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT); @@ -639,24 +589,30 @@ interface_add (NMSupplicantInterface *self, gboolean is_wireless) info = nm_supplicant_info_new (self, priv->wpas_proxy, priv->other_pcalls); + hash = g_hash_table_new (g_str_hash, g_str_equal); + driver = g_new0 (GValue, 1); g_value_init (driver, G_TYPE_STRING); - g_value_set_string (driver, is_wireless ? "wext" : "wired"); + g_value_set_string (driver, is_wireless ? "nl80211,wext" : "wired"); + g_hash_table_insert (hash, "Driver", driver); - hash = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (hash, "driver", driver); + ifname = g_new0 (GValue, 1); + g_value_init (ifname, G_TYPE_STRING); + g_value_set_string (ifname, priv->dev); + g_hash_table_insert (hash, "Ifname", ifname); - call = dbus_g_proxy_begin_call (priv->wpas_proxy, "addInterface", + call = dbus_g_proxy_begin_call (priv->wpas_proxy, "CreateInterface", interface_add_cb, info, nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, DBUS_TYPE_G_MAP_OF_VARIANT, hash, G_TYPE_INVALID); g_hash_table_destroy (hash); g_value_unset (driver); g_free (driver); + g_value_unset (ifname); + g_free (ifname); nm_supplicant_info_set_call (info, call); } @@ -684,26 +640,24 @@ smgr_avail_cb (NMSupplicantManager *smgr, static void remove_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { - GError *err = NULL; - guint tmp; + GError *error = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { nm_log_dbg (LOGD_SUPPLICANT, "Couldn't remove network from supplicant interface: %s.", - err->message); - g_error_free (err); + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); } } static void disconnect_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { - GError *err = NULL; - guint tmp; + GError *error = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't disconnect supplicant interface: %s.", - err->message); - g_error_free (err); + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); } } @@ -728,26 +682,23 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) /* Don't try to disconnect if the supplicant interface is already disconnected */ if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED || priv->state == NM_SUPPLICANT_INTERFACE_STATE_INACTIVE) { - if (priv->net_proxy) { - g_object_unref (priv->net_proxy); - priv->net_proxy = NULL; - } + g_free (priv->net_path); + priv->net_path = NULL; return; } /* Remove any network that was added by NetworkManager */ - if (priv->net_proxy) { - dbus_g_proxy_begin_call (priv->iface_proxy, "removeNetwork", + if (priv->net_path) { + dbus_g_proxy_begin_call (priv->iface_proxy, "RemoveNetwork", remove_network_cb, NULL, NULL, - DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (priv->net_proxy), + DBUS_TYPE_G_OBJECT_PATH, priv->net_path, G_TYPE_INVALID); - - g_object_unref (priv->net_proxy); - priv->net_proxy = NULL; + g_free (priv->net_path); + priv->net_path = NULL; } - dbus_g_proxy_begin_call (priv->iface_proxy, "disconnect", + dbus_g_proxy_begin_call (priv->iface_proxy, "Disconnect", disconnect_cb, NULL, NULL, G_TYPE_INVALID); @@ -758,9 +709,8 @@ select_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_dat { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; GError *err = NULL; - guint tmp; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't select network config: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); @@ -768,161 +718,86 @@ select_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_dat } static void -set_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +call_select_network (NMSupplicantInterface *self) { - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GError *err = NULL; - guint tmp; - - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { - nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network config: %s.", err->message); - emit_error_helper (info->interface, err); - g_error_free (err); - } else { - DBusGProxyCall *call; - - info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "selectNetwork", - select_network_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (proxy), - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - } -} - -static void -call_set_network (NMSupplicantInfo *info) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GHashTable *config_hash; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); DBusGProxyCall *call; + NMSupplicantInfo *info; - config_hash = nm_supplicant_config_get_hash (priv->cfg); - call = dbus_g_proxy_begin_call (priv->net_proxy, "set", - set_network_cb, + /* We only select the network after all blobs (if any) have been set */ + if (priv->blobs_left > 0) + return; + + info = nm_supplicant_info_new (self, priv->iface_proxy, priv->assoc_pcalls); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "SelectNetwork", + select_network_cb, info, nm_supplicant_info_destroy, - DBUS_TYPE_G_MAP_OF_VARIANT, config_hash, + DBUS_TYPE_G_OBJECT_PATH, priv->net_path, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); - g_hash_table_destroy (config_hash); } static void -set_blobs_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +add_blob_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; guint tmp; + priv->blobs_left--; + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network certificates: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); - } else { - info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); - call_set_network (info); - } -} - -static GValue * -byte_array_to_gvalue (const GByteArray *array) -{ - GValue *val; - - val = g_slice_new0 (GValue); - g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY); - g_value_set_boxed (val, array); - - return val; -} - -static void -blob_free (GValue *val) -{ - g_value_unset (val); - g_slice_free (GValue, val); -} - -static void -convert_blob (const char *key, const GByteArray *value, GHashTable *hash) -{ - GValue *val; - - val = byte_array_to_gvalue (value); - g_hash_table_insert (hash, g_strdup (key), val); -} - -static void -call_set_blobs (NMSupplicantInfo *info, GHashTable *orig_blobs) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - DBusGProxyCall *call; - GHashTable *blobs; - - blobs = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) blob_free); - if (!blobs) { - const char *msg = "Not enough memory to create blob table."; - - nm_log_warn (LOGD_SUPPLICANT, "%s", msg); - g_signal_emit (info->interface, signals[CONNECTION_ERROR], 0, "SendBlobError", msg); - return; - } - - g_hash_table_foreach (orig_blobs, (GHFunc) convert_blob, blobs); - - call = dbus_g_proxy_begin_call (priv->iface_proxy, "setBlobs", - set_blobs_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_MAP_OF_VARIANT, blobs, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - g_hash_table_destroy (blobs); + } else + call_select_network (info->interface); } static void add_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; - char *path = NULL; + GHashTable *blobs; + GHashTableIter iter; + gpointer name, data; + DBusGProxyCall *call; + NMSupplicantInfo *blob_info; + + g_free (priv->net_path); + priv->net_path = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_OBJECT_PATH, &path, + DBUS_TYPE_G_OBJECT_PATH, &priv->net_path, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't add a network to the supplicant interface: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); - } else { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GHashTable *blobs; - - priv->net_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - path, - WPAS_DBUS_IFACE_NETWORK); - g_free (path); - - info = nm_supplicant_info_new (info->interface, - priv->net_proxy, - priv->assoc_pcalls); - /* Send any blobs first; if there aren't any jump to sending the - * config settings. - */ - blobs = nm_supplicant_config_get_blobs (priv->cfg); - if (g_hash_table_size (blobs) > 0) - call_set_blobs (info, blobs); - else - call_set_network (info); + return; } + + /* Send blobs first; otherwise jump to sending the config settings */ + blobs = nm_supplicant_config_get_blobs (priv->cfg); + priv->blobs_left = g_hash_table_size (blobs); + g_hash_table_iter_init (&iter, blobs); + while (g_hash_table_iter_next (&iter, &name, &data)) { + blob_info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "AddBlob", + add_blob_cb, + blob_info, + nm_supplicant_info_destroy, + DBUS_TYPE_STRING, name, + DBUS_TYPE_G_UCHAR_ARRAY, blobs, + G_TYPE_INVALID); + nm_supplicant_info_set_call (blob_info, call); + } + + call_select_network (info->interface); } static void @@ -931,10 +806,10 @@ set_ap_scan_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; - guint32 tmp; DBusGProxyCall *call; + GHashTable *config_hash; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't send AP scan mode to the supplicant interface: %s.", err->message); emit_error_helper (info->interface, err); @@ -945,12 +820,15 @@ set_ap_scan_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d", nm_supplicant_config_get_ap_scan (priv->cfg)); - info = nm_supplicant_info_new (info->interface, proxy, info->store); - call = dbus_g_proxy_begin_call (proxy, "addNetwork", + info = nm_supplicant_info_new (info->interface, priv->iface_proxy, info->store); + config_hash = nm_supplicant_config_get_hash (priv->cfg); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "AddNetwork", add_network_cb, info, nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, config_hash, G_TYPE_INVALID); + g_hash_table_destroy (config_hash); nm_supplicant_info_set_call (info, call); } @@ -961,7 +839,7 @@ nm_supplicant_interface_set_config (NMSupplicantInterface * self, NMSupplicantInterfacePrivate *priv; NMSupplicantInfo *info; DBusGProxyCall *call; - guint32 ap_scan; + GValue value = { 0, }; g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); @@ -978,16 +856,21 @@ nm_supplicant_interface_set_config (NMSupplicantInterface * self, g_object_ref (priv->cfg); - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - ap_scan = nm_supplicant_config_get_ap_scan (priv->cfg); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "setAPScan", + g_value_init (&value, G_TYPE_UINT); + g_value_set_uint (&value, nm_supplicant_config_get_ap_scan (priv->cfg)); + + info = nm_supplicant_info_new (self, priv->props_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->props_proxy, "Set", set_ap_scan_cb, info, nm_supplicant_info_destroy, - G_TYPE_UINT, ap_scan, + G_TYPE_STRING, WPAS_DBUS_IFACE_INTERFACE, + G_TYPE_STRING, "ApScan", + G_TYPE_VALUE, &value, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); + g_value_unset (&value); return call != NULL; } @@ -996,17 +879,31 @@ scan_request_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; GError *err = NULL; - guint32 success = 0; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_UINT, &success, - G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", err->message); - g_error_free (err); } + g_signal_emit (info->interface, signals[SCAN_DONE], 0, err ? FALSE : TRUE); + g_clear_error (&err); +} - /* Notify listeners of the result of the scan */ - g_signal_emit (info->interface, signals[SCAN_REQ_RESULT], 0, !!success); +static void +destroy_gvalue (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +static GValue * +string_to_gvalue (const char *str) +{ + GValue *val = g_slice_new0 (GValue); + + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, str); + return val; } gboolean @@ -1015,17 +912,24 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface * self) NMSupplicantInterfacePrivate *priv; NMSupplicantInfo *info; DBusGProxyCall *call; + GHashTable *hash; g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + /* Scan parameters */ + hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, destroy_gvalue); + g_hash_table_insert (hash, "Type", string_to_gvalue ("active")); + info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scan", + call = dbus_g_proxy_begin_call (priv->iface_proxy, "Scan", scan_request_cb, info, nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, hash, G_TYPE_INVALID); + g_hash_table_destroy (hash); nm_supplicant_info_set_call (info, call); return call != NULL; @@ -1174,9 +1078,6 @@ get_property (GObject *object, GParamSpec *pspec) { switch (prop_id) { - case PROP_STATE: - g_value_set_uint (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->state); - break; case PROP_SCANNING: g_value_set_boolean (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->scanning); break; @@ -1204,18 +1105,17 @@ dispose (GObject *object) cancel_all_callbacks (priv->assoc_pcalls); nm_call_store_destroy (priv->assoc_pcalls); + if (priv->props_proxy) + g_object_unref (priv->props_proxy); + if (priv->iface_proxy) g_object_unref (priv->iface_proxy); - if (priv->net_proxy) - g_object_unref (priv->net_proxy); + g_free (priv->net_path); if (priv->wpas_proxy) g_object_unref (priv->wpas_proxy); - if (priv->scan_results_timeout) - g_source_remove (priv->scan_results_timeout); - if (priv->smgr) { if (priv->smgr_avail_id) g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id); @@ -1248,15 +1148,6 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) object_class->get_property = get_property; /* Properties */ - g_object_class_install_property (object_class, PROP_STATE, - g_param_spec_uint ("state", - "State", - "State of the supplicant interface", - NM_SUPPLICANT_INTERFACE_STATE_INIT, - NM_SUPPLICANT_INTERFACE_STATE_LAST - 1, - NM_SUPPLICANT_INTERFACE_STATE_INIT, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, PROP_SCANNING, g_param_spec_boolean ("scanning", "Scanning", @@ -1266,7 +1157,7 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) /* Signals */ signals[STATE] = - g_signal_new ("state", + g_signal_new (NM_SUPPLICANT_INTERFACE_STATE, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state), @@ -1275,7 +1166,7 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); signals[REMOVED] = - g_signal_new ("removed", + g_signal_new (NM_SUPPLICANT_INTERFACE_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed), @@ -1283,35 +1174,26 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - signals[SCANNED_AP] = - g_signal_new ("scanned-ap", + signals[NEW_BSS] = + g_signal_new (NM_SUPPLICANT_INTERFACE_NEW_BSS, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scanned_ap), + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, new_bss), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - signals[SCAN_REQ_RESULT] = - g_signal_new ("scan-req-result", + signals[SCAN_DONE] = + g_signal_new (NM_SUPPLICANT_INTERFACE_SCAN_DONE, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_req_result), + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_done), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - signals[SCAN_RESULTS] = - g_signal_new ("scan-results", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_results), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals[CONNECTION_ERROR] = - g_signal_new ("connection-error", + g_signal_new (NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error), diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 9471bd771b..44c92f19c6 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -53,6 +53,12 @@ enum { #define NM_IS_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_INTERFACE)) #define NM_SUPPLICANT_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass)) +#define NM_SUPPLICANT_INTERFACE_STATE "state" +#define NM_SUPPLICANT_INTERFACE_REMOVED "removed" +#define NM_SUPPLICANT_INTERFACE_NEW_BSS "new-bss" +#define NM_SUPPLICANT_INTERFACE_SCAN_DONE "scan-done" +#define NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR "connection-error" + struct _NMSupplicantInterface { GObject parent; }; @@ -70,18 +76,14 @@ typedef struct { /* interface was removed by the supplicant */ void (*removed) (NMSupplicantInterface * iface); - /* interface saw a new access point from a scan */ - void (*scanned_ap) (NMSupplicantInterface * iface, - DBusMessage * message); + /* interface saw a new BSS */ + void (*new_bss) (NMSupplicantInterface *iface, + GHashTable *props); - /* result of a wireless scan request */ - void (*scan_req_result) (NMSupplicantInterface * iface, + /* wireless scan is done */ + void (*scan_done) (NMSupplicantInterface *iface, gboolean success); - /* scan results returned from supplicant */ - void (*scan_results) (NMSupplicantInterface * iface, - guint num_bssids); - /* an error occurred during a connection request */ void (*connection_error) (NMSupplicantInterface * iface, const char * name, diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index e1330fd7bf..8209da21d2 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -114,7 +114,7 @@ nm_supplicant_manager_iface_release (NMSupplicantManager *self, /* Ask wpa_supplicant to remove this interface */ op = nm_supplicant_interface_get_object_path (iface); if (priv->running && priv->proxy && op) { - dbus_g_proxy_call_no_reply (priv->proxy, "removeInterface", + dbus_g_proxy_call_no_reply (priv->proxy, "RemoveInterface", DBUS_TYPE_G_OBJECT_PATH, op, G_TYPE_INVALID); } diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h index e9c31a997b..9e2f3b21b1 100644 --- a/src/supplicant-manager/nm-supplicant-manager.h +++ b/src/supplicant-manager/nm-supplicant-manager.h @@ -26,9 +26,9 @@ #include "nm-supplicant-types.h" #include "nm-device.h" -#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant" -#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant" -#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant" +#define WPAS_DBUS_SERVICE "fi.w1.wpa_supplicant1" +#define WPAS_DBUS_PATH "/fi/w1/wpa_supplicant1" +#define WPAS_DBUS_INTERFACE "fi.w1.wpa_supplicant1" G_BEGIN_DECLS diff --git a/src/tests/test-policy-hosts.c b/src/tests/test-policy-hosts.c index 8865c4264e..62862e756f 100644 --- a/src/tests/test-policy-hosts.c +++ b/src/tests/test-policy-hosts.c @@ -23,41 +23,17 @@ #include "nm-policy-hosts.h" -#define FALLBACK_HOSTNAME4 "localhost.localdomain" -#define FALLBACK_HOSTNAME6 "localhost6.localdomain6" - -#define DEBUG 0 +#define DEBUG 1 static void -test_generic (const char *before, - const char *after, - const char *hostname, - const char *ip4_addr, - const char *ip6_addr, - gboolean expect_error) +test_generic (const char *before, const char *after) { - char **lines; GString *newc; - GError *error = NULL; /* Get the new /etc/hosts contents */ - lines = g_strsplit_set (before, "\n\r", 0); - newc = nm_policy_get_etc_hosts ((const char **) lines, - strlen (before), - hostname, - NULL, - FALLBACK_HOSTNAME4, - FALLBACK_HOSTNAME6, - ip4_addr, - ip6_addr, - &error); - g_strfreev (lines); + newc = nm_policy_get_etc_hosts (before, strlen (before)); - if (expect_error) { - g_assert (newc == NULL); - g_assert (error != NULL); - g_clear_error (&error); - } else if (after == NULL) { + if (after == NULL) { /* No change to /etc/hosts required */ #if DEBUG if (newc != NULL) { @@ -68,10 +44,8 @@ test_generic (const char *before, } #endif g_assert (newc == NULL); - g_assert (error == NULL); } else { g_assert (newc != NULL); - g_assert (error == NULL); #if DEBUG g_message ("\n- NEW ---------------------------------\n" @@ -81,7 +55,6 @@ test_generic (const char *before, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", newc->str, after); #endif - g_assert (strlen (newc->str) == strlen (after)); g_assert (strcmp (newc->str, after) == 0); g_string_free (newc, TRUE); } @@ -99,7 +72,7 @@ static const char *generic_before = \ static void test_hosts_generic (void) { - test_generic (generic_before, NULL, "localhost.localdomain", NULL, NULL, FALSE); + test_generic (generic_before, NULL); } /*******************************************/ @@ -112,311 +85,25 @@ static const char *generic_no_boilerplate_before = \ static void test_hosts_generic_no_boilerplate (void) { - test_generic (generic_no_boilerplate_before, NULL, "localhost.localdomain", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *generic_no_boilerplate_no_lh_before = \ - "127.0.0.1 localhost.localdomain\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *generic_no_boilerplate_no_lh_after = \ - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_generic_no_boilerplate_no_lh (void) -{ - test_generic (generic_no_boilerplate_no_lh_before, - generic_no_boilerplate_no_lh_after, - "localhost.localdomain", - NULL, - NULL, - FALSE); -} - -/*******************************************/ - - -static const char *generic_no_boilerplate_no_lh_no_host_before = \ - "127.0.0.1 localhost.localdomain\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *generic_no_boilerplate_no_lh_no_host_after = \ - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_generic_no_boilerplate_no_lh_no_host (void) -{ - test_generic (generic_no_boilerplate_no_lh_no_host_before, - generic_no_boilerplate_no_lh_no_host_after, - "comet", - NULL, - NULL, - FALSE); -} - -/*******************************************/ -static const char *named_generic_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 playboy localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *named_generic_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 playboy localhost.localdomain localhost\n" - "::1 playboy localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named_generic (void) -{ - test_generic (named_generic_before, named_generic_after, "playboy", NULL, NULL, FALSE); + test_generic (generic_no_boilerplate_before, NULL); } /*******************************************/ -static const char *named4_non127_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 tomcat localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "192.168.1.2 tomcat\n"; - -static void -test_hosts_named4_non127 (void) -{ - test_generic (named4_non127_before, NULL, "tomcat", "192.168.1.2", NULL, FALSE); -} - -/*******************************************/ - -static const char *named6_non127_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 tomcat localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "3001:abba::3234 tomcat\n"; - -static void -test_hosts_named6_non127 (void) -{ - test_generic (named6_non127_before, NULL, "tomcat", NULL, "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named4_non127_more_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 tomcat localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "192.168.1.2 tomcat\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "127.0.0.1 srx.main.ebayrtm.com\n" - "127.0.0.1 cdn5.tribalfusion.com\n"; - -static void -test_hosts_named4_non127_more (void) -{ - test_generic (named4_non127_more_before, NULL, "tomcat", "192.168.1.2", NULL, FALSE); -} - -/*******************************************/ - -static const char *named6_non127_more_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 tomcat localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "3001:abba::3234 tomcat\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "127.0.0.1 srx.main.ebayrtm.com\n" - "127.0.0.1 cdn5.tribalfusion.com\n"; - -static void -test_hosts_named6_non127_more (void) -{ - test_generic (named6_non127_more_before, NULL, "tomcat", NULL, "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named_no_lh_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "192.168.1.2 tomcat\n"; - -static const char *named_no_lh_after = \ +static const char *leftover_before = \ "# Do not remove the following line, or various programs\n" "# that require network functionality will fail.\n" + "192.168.1.2 comet # Added by NetworkManager\n" "127.0.0.1 localhost.localdomain localhost\n" - "::1 tomcat localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "192.168.1.2 tomcat\n"; - -static void -test_hosts_named_no_localhost (void) -{ - test_generic (named_no_lh_before, named_no_lh_after, "tomcat", "192.168.1.2", NULL, FALSE); -} - -/*******************************************/ - -static const char *no_lh_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 tomcat\n" - "::1 localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *no_lh_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 tomcat localhost.localdomain localhost\n" - "::1 tomcat localhost6.localdomain6 localhost6\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_no_localhost (void) -{ - test_generic (no_lh_before, no_lh_after, "tomcat", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *named_last_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 sparcbook.ausil.us\n" - "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 sparcbook.ausil.us\n"; - -static void -test_hosts_named_last (void) -{ - test_generic (named_last_before, NULL, "sparcbook.ausil.us", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *no_host4_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "::1 localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "127.0.0.1 srx.main.ebayrtm.com\n" - "127.0.0.1 cdn5.tribalfusion.com\n" - "127.0.0.1 a.tribalfusion.com\n"; - -static const char *no_host4_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "127.0.0.1 srx.main.ebayrtm.com\n" - "127.0.0.1 cdn5.tribalfusion.com\n" - "127.0.0.1 a.tribalfusion.com\n"; - -static void -test_hosts_no_host4 (void) -{ - test_generic (no_host4_before, no_host4_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *no_host6_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *no_host6_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_no_host6 (void) -{ - test_generic (no_host6_before, no_host6_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *named46_non127_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.2 comet\n" - "3001:abba::3234 comet\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named46_non127 (void) -{ - test_generic (named46_non127_before, NULL, "comet", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named46_non127_long_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.2 comet.space comet\n" - "3001:abba::3234 comet.space comet\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named46_non127_long (void) -{ - test_generic (named46_non127_long_before, NULL, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named46_non127_other4_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" "::1 localhost6.localdomain6 localhost6\n" "192.168.1.3 comet\n" "3001:abba::3234 comet\n" "\n" "127.0.0.1 lcmd.us.intellitxt.com\n"; -static const char *named46_non127_other4_after = \ +static const char *leftover_after = \ "# Do not remove the following line, or various programs\n" "# that require network functionality will fail.\n" - "192.168.1.2 comet # Added by NetworkManager\n" "127.0.0.1 localhost.localdomain localhost\n" "::1 localhost6.localdomain6 localhost6\n" "192.168.1.3 comet\n" @@ -425,416 +112,44 @@ static const char *named46_non127_other4_after = \ "127.0.0.1 lcmd.us.intellitxt.com\n"; static void -test_hosts_named46_non127_other4 (void) +test_hosts_leftover (void) { - test_generic (named46_non127_other4_before, named46_non127_other4_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE); + test_generic (leftover_before, leftover_after); } /*******************************************/ -static const char *named46_non127_other4_long_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.3 comet.space\n" - "3001:abba::3234 comet.space\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *named46_non127_other4_long_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "192.168.1.2 comet.space comet # Added by NetworkManager\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.3 comet.space\n" - "3001:abba::3234 comet.space\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named46_non127_other4_long (void) -{ - test_generic (named46_non127_other4_long_before, named46_non127_other4_long_after, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named46_non127_other6_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.2 comet\n" - "3001:abba::9675 comet\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *named46_non127_other6_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "3001:abba::3234 comet # Added by NetworkManager\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.2 comet\n" - "3001:abba::9675 comet\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named46_non127_other6 (void) -{ - test_generic (named46_non127_other6_before, named46_non127_other6_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named46_non127_other6_long_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.2 comet.space\n" - "3001:abba::9675 comet.space\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *named46_non127_other6_long_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "3001:abba::3234 comet.space comet # Added by NetworkManager\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.2 comet.space\n" - "3001:abba::9675 comet.space\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named46_non127_other6_long (void) -{ - test_generic (named46_non127_other6_long_before, named46_non127_other6_long_after, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *unnamed46_non127_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *unnamed46_non127_after = \ +static const char *leftover_double_newline_before = \ "# Do not remove the following line, or various programs\n" "# that require network functionality will fail.\n" "192.168.1.2 comet # Added by NetworkManager\n" - "3001:abba::3234 comet # Added by NetworkManager\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_unnamed46_non127 (void) -{ - test_generic (unnamed46_non127_before, unnamed46_non127_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *unnamed46_non127_long_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static const char *unnamed46_non127_long_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "192.168.1.2 comet.space comet # Added by NetworkManager\n" - "3001:abba::3234 comet.space comet # Added by NetworkManager\n" "127.0.0.1 localhost.localdomain localhost\n" "::1 localhost6.localdomain6 localhost6\n" + "192.168.1.3 comet\n" + "3001:abba::3234 comet\n" "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_unnamed46_non127_long (void) -{ - test_generic (unnamed46_non127_long_before, unnamed46_non127_long_after, "comet.space", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *named46_non127_wrong_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n" - "192.168.1.3 comet # Added by NetworkManager\n" - "3001:abba::9876 comet # Added by NetworkManager\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; + "127.0.0.1 lcmd.us.intellitxt.com\n" + "\n"; -static const char *named46_non127_wrong_after = \ +static const char *leftover_double_newline_after = \ "# Do not remove the following line, or various programs\n" "# that require network functionality will fail.\n" - "192.168.1.2 comet # Added by NetworkManager\n" - "3001:abba::3234 comet # Added by NetworkManager\n" "127.0.0.1 localhost.localdomain localhost\n" "::1 localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n"; - -static void -test_hosts_named46_non127_wrong (void) -{ - test_generic (named46_non127_wrong_before, named46_non127_wrong_after, "comet", "192.168.1.2", "3001:abba::3234", FALSE); -} - -/*******************************************/ - -static const char *long_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost comet\n" - "::1 localhost6.localdomain6 localhost6\n" - "\n" - "127.0.0.1 lcmd.us.intellitxt.com\n" - "127.0.0.1 adserver.adtech.de\n" - "127.0.0.1 a.as-us.falkag.net\n" - "127.0.0.1 a.as-eu.falkag.net\n" - "127.0.0.1 ads.doubleclick.com\n" - "\n" - "# random comment\n" - "127.0.0.1 m1.2mdn.net\n" - "127.0.0.1 ds.serving-sys.com\n" - "127.0.0.1 pagead2.googlesyndication.com\n" - "127.0.0.1 ad.doubleclick.com\n" - "127.0.0.1 ad.doubleclick.net\n" - "127.0.0.1 oascentral.movietickets.com\n" - "127.0.0.1 view.atdmt.com\n" - "127.0.0.1 ads.chumcity.com\n"; - -static const char *long_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n" + "192.168.1.3 comet\n" + "3001:abba::3234 comet\n" "\n" "127.0.0.1 lcmd.us.intellitxt.com\n" - "127.0.0.1 adserver.adtech.de\n" - "127.0.0.1 a.as-us.falkag.net\n" - "127.0.0.1 a.as-eu.falkag.net\n" - "127.0.0.1 ads.doubleclick.com\n" - "\n" - "# random comment\n" - "127.0.0.1 m1.2mdn.net\n" - "127.0.0.1 ds.serving-sys.com\n" - "127.0.0.1 pagead2.googlesyndication.com\n" - "127.0.0.1 ad.doubleclick.com\n" - "127.0.0.1 ad.doubleclick.net\n" - "127.0.0.1 oascentral.movietickets.com\n" - "127.0.0.1 view.atdmt.com\n" - "127.0.0.1 ads.chumcity.com\n"; - -static void -test_hosts_long (void) -{ - test_generic (long_before, long_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *custom4_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost pintglass\n" - "::1 localhost6.localdomain6 localhost6\n"; - -static const char *custom4_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost pintglass\n" - "::1 comet localhost6.localdomain6 localhost6\n"; - -static void -test_hosts_custom4 (void) -{ - test_generic (custom4_before, custom4_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *custom6_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6 pintglass\n"; - -static const char *custom6_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6 pintglass\n"; - -static void -test_hosts_custom6 (void) -{ - test_generic (custom6_before, custom6_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *custom46_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost shotglass\n" - "::1 localhost6.localdomain6 localhost6 pintglass\n"; - -static const char *custom46_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost shotglass\n" - "::1 comet localhost6.localdomain6 localhost6 pintglass\n"; - -static void -test_hosts_custom46 (void) -{ - test_generic (custom46_before, custom46_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *custom46_mixed_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 localhost.localdomain localhost shotglass\n" - "::1 localhost6.localdomain6 localhost6 pintglass\n"; - -static const char *custom46_mixed_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost shotglass\n" - "::1 comet localhost6.localdomain6 localhost6 pintglass\n"; - -static void -test_hosts_custom46_mixed (void) -{ - test_generic (custom46_mixed_before, custom46_mixed_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *stale4_removed_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "1.2.3.4 comet # Added by NetworkManager\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n"; - -static const char *stale4_removed_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n"; + "\n"; static void -test_hosts_stale4_removed (void) +test_hosts_leftover_double_newline (void) { - test_generic (stale4_removed_before, stale4_removed_after, "comet", NULL, NULL, FALSE); + test_generic (leftover_double_newline_before, leftover_double_newline_after); } /*******************************************/ -static const char *stale6_removed_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "3001:abba::3234 comet # Added by NetworkManager\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n"; - -static const char *stale6_removed_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n"; - -static void -test_hosts_stale6_removed (void) -{ - test_generic (stale6_removed_before, stale6_removed_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -static const char *stale46_removed_before = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "1.2.3.4 comet # Added by NetworkManager\n" - "3001:abba::3234 comet # Added by NetworkManager\n" - "127.0.0.1 localhost.localdomain localhost\n" - "::1 localhost6.localdomain6 localhost6\n"; - -static const char *stale46_removed_after = \ - "# Do not remove the following line, or various programs\n" - "# that require network functionality will fail.\n" - "127.0.0.1 comet localhost.localdomain localhost\n" - "::1 comet localhost6.localdomain6 localhost6\n"; - -static void -test_hosts_stale46_removed (void) -{ - test_generic (stale46_removed_before, stale46_removed_after, "comet", NULL, NULL, FALSE); -} - -/*******************************************/ - -typedef struct { - const char *line; - const char *token; - gboolean expected; -} Foo; - -static Foo foo[] = { - /* Using \t here to easily differentiate tabs vs. spaces for testing */ - { "127.0.0.1\tfoobar\tblah", "blah", TRUE }, - { "", "blah", FALSE }, - { "1.1.1.1\tbork\tfoo", "blah", FALSE }, - { "127.0.0.1 foobar\tblah", "blah", TRUE }, - { "127.0.0.1 foobar blah", "blah", TRUE }, - { "127.0.0.1 localhost", "localhost.localdomain", FALSE }, - { "192.168.1.1 blah borkbork", "blah", TRUE }, - { "192.168.1.1 foobar\tblah borkbork", "blah", TRUE }, - { "192.168.1.1\tfoobar\tblah\tborkbork", "blah", TRUE }, - { "192.168.1.1 \tfoobar \tblah \tborkbork\t ", "blah", TRUE }, - { "\t\t\t\t \t\t\tasdfadf a\t\t\t\t\t \t\t\t\t\t ", "blah", FALSE }, - { NULL, NULL, FALSE } -}; - -static void -test_find_token (void) -{ - Foo *iter = &foo[0]; - - while (iter->line) { - gboolean found; - - found = nm_policy_hosts_find_token (iter->line, iter->token); - if (found != iter->expected) { - g_warning ("find-token: unexpected token result %d for '%s' <= '%s' (expected %d)", - found, iter->line, iter->token, iter->expected); - } - g_assert (found == iter->expected); - iter++; - } -} - #if GLIB_CHECK_VERSION(2,25,12) typedef GTestFixtureFunc TCFunc; #else @@ -851,38 +166,10 @@ int main (int argc, char **argv) suite = g_test_get_root (); - g_test_suite_add (suite, TESTCASE (test_find_token, NULL)); g_test_suite_add (suite, TESTCASE (test_hosts_generic, NULL)); g_test_suite_add (suite, TESTCASE (test_hosts_generic_no_boilerplate, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_generic_no_boilerplate_no_lh, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_generic_no_boilerplate_no_lh_no_host, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named_generic, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named4_non127, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named6_non127, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named4_non127_more, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named6_non127_more, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_long, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other4, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other4_long, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other6, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_other6_long, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named46_non127_wrong, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_unnamed46_non127, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_unnamed46_non127_long, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named_no_localhost, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_no_localhost, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_named_last, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_no_host4, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_no_host6, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_long, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_custom4, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_custom6, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_custom46, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_custom46_mixed, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_stale4_removed, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_stale6_removed, NULL)); - g_test_suite_add (suite, TESTCASE (test_hosts_stale46_removed, NULL)); + g_test_suite_add (suite, TESTCASE (test_hosts_leftover, NULL)); + g_test_suite_add (suite, TESTCASE (test_hosts_leftover_double_newline, NULL)); return g_test_run (); } diff --git a/src/wimax/Makefile.am b/src/wimax/Makefile.am new file mode 100644 index 0000000000..91f1dc4e07 --- /dev/null +++ b/src/wimax/Makefile.am @@ -0,0 +1,40 @@ +INCLUDES = \ + -I${top_srcdir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/include \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/marshallers + +noinst_LTLIBRARIES = libwimax.la + +libwimax_la_SOURCES = \ + nm-device-wimax.c \ + nm-device-wimax.h \ + nm-wimax-nsp.c \ + nm-wimax-nsp.h \ + nm-wimax-types.h \ + nm-wimax-util.c \ + nm-wimax-util.h \ + iwmxsdk.c \ + iwmxsdk.h + +libwimax_la_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(IWMX_SDK_CFLAGS) + +libwimax_la_LIBADD = \ + $(DBUS_LIBS) \ + $(IWMX_SDK_LIBS) \ + $(top_builddir)/marshallers/libmarshallers.la + +nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml + dbus-binding-tool --prefix=nm_wimax_nsp --mode=glib-server --output=$@ $< + +nm-device-wimax-glue.h: $(top_srcdir)/introspection/nm-device-wimax.xml + dbus-binding-tool --prefix=nm_device_wimax --mode=glib-server --output=$@ $< + +BUILT_SOURCES = \ + nm-wimax-nsp-glue.h \ + nm-device-wimax-glue.h + +CLEANFILES = $(BUILT_SOURCES) diff --git a/src/wimax/iwmxsdk.c b/src/wimax/iwmxsdk.c new file mode 100644 index 0000000000..0c0bc1377e --- /dev/null +++ b/src/wimax/iwmxsdk.c @@ -0,0 +1,1462 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <net/if.h> + +#include <glib.h> + +#include <WiMaxType.h> +#include <WiMaxAPI.h> +#include <WiMaxAPIEx.h> + +#include "logging/nm-logging.h" +#include "iwmxsdk.h" + +static WIMAX_API_DEVICE_ID g_api; +static GStaticMutex add_remove_mutex = G_STATIC_MUTEX_INIT; + +/* Misc utilities */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/* Misc values */ +enum { + /* + * WARNING!!!!! + * + * ONLY ONE DEVICE SUPPORTED + * + * - on removal, there is no way to know which device was + * removed (the removed device is removed from the list and + * the callback doesn't have any more information than the + * index in the list that getlistdevice would return -- racy + * as hell). + * + * - on insertion, there is not enough information provided. + */ + IWMX_SDK_DEV_MAX = 1, +}; + +/* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX */ +static struct wmxsdk *g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX]; + +static struct wmxsdk *deviceid_to_wmxsdk(WIMAX_API_DEVICE_ID *device_id) +{ + unsigned cnt; + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && + wmxsdk->device_id.deviceIndex == device_id->deviceIndex) + return wmxsdk; + } + return NULL; +} + +struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface) +{ + unsigned cnt; + + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && !strcmp(wmxsdk->ifname, iface)) + return wmxsdk; + } + return NULL; +} + +/* + * FIXME: pulled it it out of some hole + * + * the cinr to percentage computation comes from the L3/L4 doc + * + * But some other places (L4 code) have a more complex, seemingly + * logarithmical computation. + * + * Oh well... + * + */ +static int cinr_to_percentage(int cinr) +{ + int strength; + if (cinr <= -5) + strength = 0; + else if (cinr >= 25) + strength = 100; + else /* Calc percentage on the value from -5 to 25 */ + strength = ((100UL * (cinr - -5)) / (25 - -5)); + return strength; +} + +/**************************************************************/ + +typedef struct { + WimaxNewWmxsdkFunc callback; + void *user_data; +} NewSdkCallback; + +GStaticMutex new_callbacks_mutex = G_STATIC_MUTEX_INIT; +static GSList *new_callbacks = NULL; + +void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data) +{ + NewSdkCallback *cb; + + cb = g_malloc0 (sizeof (NewSdkCallback)); + g_assert (cb); + cb->callback = callback; + cb->user_data = user_data; + + g_static_mutex_lock (&new_callbacks_mutex); + new_callbacks = g_slist_append (new_callbacks, cb); + g_static_mutex_unlock (&new_callbacks_mutex); +} + +void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data) +{ + GSList *iter; + NewSdkCallback *found = NULL; + + g_static_mutex_lock (&new_callbacks_mutex); + for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { + NewSdkCallback *cb = iter->data; + + if (cb->callback == callback && cb->user_data == user_data) { + found = cb; + break; + } + } + + if (found) { + new_callbacks = g_slist_remove (new_callbacks, found); + g_free (found); + } + g_static_mutex_unlock (&new_callbacks_mutex); +} + +static void iwmx_sdk_call_new_callbacks(struct wmxsdk *wmxsdk) +{ + GSList *iter; + + g_static_mutex_lock (&new_callbacks_mutex); + for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { + NewSdkCallback *cb = iter->data; + + cb->callback (wmxsdk, cb->user_data); + } + g_static_mutex_unlock (&new_callbacks_mutex); +} + +/****************************************************************/ + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_DEVICE_STATUS new_status; + WIMAX_API_DEVICE_STATUS old_status; + WIMAX_API_STATUS_REASON reason; +} StateChangeInfo; + +static gboolean +state_change_handler(gpointer user_data) +{ + StateChangeInfo *info = user_data; + + if (info->wmxsdk->state_change_cb) { + info->wmxsdk->state_change_cb(info->wmxsdk, + info->new_status, + info->old_status, + info->reason, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_state_change(struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason) +{ + StateChangeInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->new_status = new_status; + info->old_status = old_status; + info->reason = reason; + + wmxsdk_ref(wmxsdk); + g_idle_add(state_change_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_MEDIA_STATUS media_status; +} MediaStatusInfo; + +static gboolean +media_status_change_handler(gpointer user_data) +{ + MediaStatusInfo *info = user_data; + + if (info->wmxsdk->media_status_cb) { + info->wmxsdk->media_status_cb(info->wmxsdk, + info->media_status, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_media_status_change(struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS media_status) +{ + MediaStatusInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->media_status = media_status; + + wmxsdk_ref(wmxsdk); + g_idle_add(media_status_change_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_NETWORK_CONNECTION_RESP result; +} ConnectResultInfo; + +static gboolean +connect_result_handler(gpointer user_data) +{ + ConnectResultInfo *info = user_data; + + if (info->wmxsdk->connect_result_cb) { + info->wmxsdk->connect_result_cb(info->wmxsdk, + info->result, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_connect_result(struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + ConnectResultInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->result = resp; + + wmxsdk_ref(wmxsdk); + g_idle_add(connect_result_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_NSP_INFO_EX *nsps; + guint num_nsps; +} ScanResultInfo; + +static gboolean +scan_result_handler(gpointer user_data) +{ + ScanResultInfo *info = user_data; + + if (info->wmxsdk->scan_result_cb) { + info->wmxsdk->scan_result_cb(info->wmxsdk, + info->nsps, + info->num_nsps, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + free(info->nsps); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_scan_result(struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps) +{ + ScanResultInfo *info; + size_t nsps_size; + int i, tmp; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + + nsps_size = num_nsps * sizeof (WIMAX_API_NSP_INFO_EX); + info->nsps = malloc(nsps_size); + memcpy(info->nsps, nsps, nsps_size); + info->num_nsps = num_nsps; + + /* CAPI may report link quality as zero -- if it does check if it is a bug + * by computing it based on CINR. If it is different, use the computed one. + */ + for (i = 0; i < num_nsps; i++) { + WIMAX_API_NSP_INFO_EX *nsp = &info->nsps[i]; + + if (nsp->linkQuality == 0) { + tmp = cinr_to_percentage(nsp->CINR - 10); + if (tmp != nsp->linkQuality) + nsp->linkQuality = tmp; + } + } + + wmxsdk_ref(wmxsdk); + g_idle_add(scan_result_handler, info); +} + +static gboolean +removed_handler(gpointer user_data) +{ + struct wmxsdk *wmxsdk = user_data; + + if (wmxsdk->removed_cb) + wmxsdk->removed_cb(wmxsdk, wmxsdk->callback_data); + wmxsdk_unref(wmxsdk); + return FALSE; +} + +static void +_schedule_removed(struct wmxsdk *wmxsdk) +{ + wmxsdk_ref(wmxsdk); + g_idle_add(removed_handler, wmxsdk); +} + +/****************************************************************/ + +/* + * Convert a WiMAX API status to an string. + */ +const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status) +{ + switch (status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + return "uninitialized"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + return "rf off"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + return "rf off (hard-block)"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + return "rf off (soft-block)"; + case WIMAX_API_DEVICE_STATUS_Ready: + return "ready"; + case WIMAX_API_DEVICE_STATUS_Scanning: + return "scanning"; + case WIMAX_API_DEVICE_STATUS_Connecting: + return "connecting"; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + return "connected"; + default: + return "unknown"; + } +} + +const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason) +{ + switch (reason) { + case WIMAX_API_STATUS_REASON_Normal: + return "normal"; + + /**< Failed to complete NW entry with the selected operator (unspecified reason). */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_to_NW: + return "unspecified failure"; + + /**< Failed to complete ranging */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_Ranging: + return "ranging failed"; + + /**< SBC phase failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_SBC: + return "sbc failed"; + + /**< Security error. EAP authentication failed device level */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_Device: + return "EAP device auth failed"; + + /**< Security error. EAP authentication failed user level */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_user: + return "EAP user auth failed"; + + /**< Security error. Handshake failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_3_Way_Handshake: + return "3 way handshake failed"; + + /**< Registration failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_REG: + return "registration failed"; + + /**< Failed to initialize the data path (failed to perform DSA to one UL and one DL SFs). */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_datapath: + return "datapath failed"; + + default: + return "unknown"; + } +} + +const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status) +{ + switch (status) { + case WIMAX_API_MEDIA_STATUS_LINK_UP: + return "link-up"; + case WIMAX_API_MEDIA_STATUS_LINK_DOWN: + return "link-down"; + case WIMAX_API_MEDIA_STATUS_LINK_RENEW: + return "link-renew"; + default: + return "unknown"; + } +} + +/* + * Get the device's status from the device + * + * Does NOT cache the result + * Does NOT trigger a state change in NetworkManager + * + * Returns < 0 errno code on error, status code if ok. + */ +static WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk) +{ + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + WIMAX_API_DEVICE_STATUS dev_status; + WIMAX_API_CONNECTION_PROGRESS_INFO pi; + + r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot read device state: %d (%s)", r, errstr); + dev_status = -EIO; + } + return dev_status; +} + +/* + * Get the device's status from the device but return a string describing it + * + * Same conditions as iwmx_sdk_get_device_status(). + */ +static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk) +{ + const char *result; + WIMAX_API_DEVICE_STATUS dev_status; + + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) + result = "cannot read device state"; + else + result = iwmx_sdk_dev_status_to_str(dev_status); + return result; +} + +/* + * If the device is connected but we don't know about the network, + * create the knowledge of it. + * + * Asks the WiMAX API to report which NSP we are connected to and we + * create/update a network_el in the device's network list. Then + * return it. + * + * Returns NULL on error. + * + */ +WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk) +{ + WIMAX_API_CONNECTED_NSP_INFO_EX *nsp_info = NULL; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + nsp_info = malloc(sizeof (*nsp_info)); + if (!nsp_info) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate NSP info"); + return NULL; + } + + r = GetConnectedNSPEx(&wmxsdk->device_id, nsp_info); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get connected NSP info: %d (%s)", r, errstr); + free (nsp_info); + nsp_info = NULL; + } else { + /* Migth be 0 sometimes; fix that up */ + if (nsp_info->linkQuality == 0) { + int linkq_expected = cinr_to_percentage(nsp_info->CINR - 10); + if (linkq_expected != nsp_info->linkQuality) + nsp_info->linkQuality = linkq_expected; + } + } + + return nsp_info; +} + +/* + * Asks the WiMAX API to report current link statistics. + * + * Returns NULL on error. + * + */ +WIMAX_API_LINK_STATUS_INFO_EX *iwmx_sdk_get_link_status_info(struct wmxsdk *wmxsdk) +{ + WIMAX_API_LINK_STATUS_INFO_EX *stats = NULL; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + /* Only report if connected */ + if (iwmxsdk_status_get(wmxsdk) < WIMAX_API_DEVICE_STATUS_Connecting) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot get link status info unless connected"); + return NULL; + } + + stats = malloc(sizeof (*stats)); + if (!stats) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate links status info"); + return NULL; + } + + r = GetLinkStatusEx(&wmxsdk->device_id, stats); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get link status info: %d (%s)", r, errstr); + free (stats); + stats = NULL; + } + + return stats; +} + +/* + * Callback for a RF State command + * + * Called by the WiMAX API when a command sent to change the RF state + * is completed. This is just a confirmation of what happened with the + * command. + * + * We don't do anything, as when the device changes state, the state + * change callback is called and that will fiddle with the NetworkManager + * internals. + */ +static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_RF_STATE rf_state) +{ + nm_log_dbg(LOGD_WIMAX, "rf_state changed to %d", rf_state); +} + +/* + * Turn the radio on or off + * + * First it checks that we are in the right state before doing + * anything; there might be no need to do anything. + * + * Issue a command to the WiMAX API, wait for a callback confirming it + * is done. Sometimes the callback is missed -- in that case, do force + * a state change evaluation. + * + * Frustration note: + * + * Geezoos efing Xist, they make difficult even the most simple + * of the operations + * + * This thing is definitely a pain. If the radio is ON already + * and you switch it on again...well, there is no way to tell + * because you don't get a callback saying it basically + * suceeded. But on the other hand, if the thing was in a + * different state and action needs to be taken, you have to wait + * for a callback to confirm it's done. However, there is also an + * state change callback, which is almost the same, so now you + * have to handle things in two "unrelated" threads of execution. + * + * How the shpx are you expected to tell the difference? Check + * status first? On timeout? Nice gap (eighteen wheeler size) for + * race conditions. + */ +int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state) +{ + int result; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF); + + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot turn on radio: hw switch is off"); + result = -EPERM; + goto error_cant_do; + break; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + if (rf_state == WIMAX_API_RF_OFF) { + result = 0; + nm_log_dbg(LOGD_WIMAX, "radio is already off"); + goto out_done; + } + break; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + if (rf_state == WIMAX_API_RF_ON) { + result = 0; + nm_log_dbg(LOGD_WIMAX, "radio is already on"); + goto out_done; + } + break; + default: + g_assert(1); + } + /* Ok, flip the radio */ + r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot flip radio to %d: %d (%s) [device is in state %s]", + rf_state, r, errstr, iwmx_sdk_get_device_status_str(wmxsdk)); + result = -EIO; + } else + result = -EINPROGRESS; +out_done: +error_cant_do: +error_get_status: + return result; +} + +/* + * Read the cached device status + */ +WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk) +{ + WIMAX_API_DEVICE_STATUS status; + + g_mutex_lock(wmxsdk->status_mutex); + status = wmxsdk->status; + g_mutex_unlock(wmxsdk->status_mutex); + return status; +} + +/* + * Callback for a Connect command + * + * Called by the WiMAX API when a command sent to connect is + * completed. This is just a confirmation of what happened with the + * command. + * + * WE DON'T DO MUCH HERE -- the real meat happens when a state change + * callback is sent, where we detect we move to connected state (or + * from disconnecting to something else); the state change callback is + * called and that will fiddle with the NetworkManager internals. + */ +static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + WIMAX_API_DEVICE_STATUS status; + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + status = iwmxsdk_status_get(wmxsdk); + if (resp == WIMAX_API_CONNECTION_SUCCESS) { + if (status != WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_err(LOGD_WIMAX, "wmxsdk: error: connect worked, but state" + " didn't change (now it is %d [%s])", + status, + iwmx_sdk_dev_status_to_str(status)); + } + } else { + nm_log_err(LOGD_WIMAX, "wmxsdk: failed to connect (status %d: %s)", + status, iwmx_sdk_dev_status_to_str(status)); + } + + _schedule_connect_result(wmxsdk, resp); +} + +/* + * Connect to a network + * + * This function starts the connection process to a given network; + * when the device changes status, the status change callback will + * tell NetworkManager if the network is finally connected or not. + * + * One of the reasons it is done like that is to allow external tools + * to control the device and the plugin just passing the status so + * NetworkManager displays the right info. + */ +int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name) +{ + int result = 0; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + char sdk_name[MAX_SIZE_OF_NSP_NAME]; + + g_mutex_lock(wmxsdk->connect_mutex); + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmxsdk_status_get(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect: radio is off"); + result = -EPERM; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + break; + case WIMAX_API_DEVICE_STATUS_Connecting: + nm_log_dbg(LOGD_WIMAX, "Connect already pending, waiting for it"); + result = -EINPROGRESS; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + nm_log_err(LOGD_WIMAX, "wmxsdk: BUG? need to disconnect?"); + result = -EINVAL; + goto error_cant_do; + default: + g_assert(1); + } + + /* The SDK treats the network name as wchar_t* while the contents are + * actually just UTF-8... WTF? Hand it a full buffer to work around + * boundary cases where the NSP name contains an odd # of characters. + */ + memset(sdk_name, 0, sizeof (sdk_name)); + memcpy(sdk_name, nsp_name, strlen (nsp_name)); + + /* Ok, do the connection, wait for a callback */ + r = CmdConnectToNetwork(&wmxsdk->device_id, &sdk_name[0], 0, 0); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect to network %s: %d (%s) - device is in state '%s'", + nsp_name, r, errstr, + iwmx_sdk_get_device_status_str(wmxsdk)); + result = -EIO; + } + +error_cant_do: +error_get_status: + g_mutex_unlock(wmxsdk->connect_mutex); + return result; +} + +/* + * Callback for a Disconnect command + * + * Called by the WiMAX API when a command sent to connect is + * completed. This is just a confirmation of what happened with the + * command. + * + * When the device changes state, the state change callback is called + * and that will fiddle with the NetworkManager internals. + * + * We just update the result of the command and wake up anybody who is + * waiting for this conditional variable. + */ +static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + WIMAX_API_DEVICE_STATUS status; + + status = iwmxsdk_status_get(wmxsdk); + if (resp == WIMAX_API_CONNECTION_SUCCESS) { + if (status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_err(LOGD_WIMAX, "wmxsdk: error: disconnect worked, " + "but state didn't change (now it is %d [%s])", status, + iwmx_sdk_dev_status_to_str(status)); + } + } else + nm_log_err(LOGD_WIMAX, "wmxsdk: failed to disconnect (status %d: %s)", + status, iwmx_sdk_dev_status_to_str(status)); +} + +/* + * Disconnect from a network + * + * This function tells the device to disconnect; the state change + * callback will take care of inform NetworkManager's internals. + */ +int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk) +{ + int result; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_mutex_lock(wmxsdk->connect_mutex); + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, radio is off; ignoring"); + result = 0; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, already disconnected; ignoring"); + result = 0; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + break; + default: + g_assert(1); + } + /* Ok, flip the radio */ + r = CmdDisconnectFromNetwork(&wmxsdk->device_id); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot disconnect from network: %d (%s)", r, errstr); + result = -EIO; + } else + result = -EINPROGRESS; +error_cant_do: +error_get_status: + g_mutex_unlock(wmxsdk->connect_mutex); + return result; +} + +/* + * Turn fast reconnect capability on/off + * + * This function tells wimaxd to turn fast reconnect on or off. + */ +int iwmx_sdk_set_fast_reconnect_enabled(struct wmxsdk *wmxsdk, int enabled) +{ + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = SetFastReconnectCapabilityStatus(&wmxsdk->device_id, !!enabled); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set fast reconnect to %d: %d (%s)", + enabled, r, errstr); + return -EIO; + } + return 0; +} + +static void __iwmx_sdk_media_status_update_cb (WIMAX_API_DEVICE_ID_P device_id, + WIMAX_API_MEDIA_STATUS mediaStatus) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + /* Ignore redundant LINK_UP events */ + if ( mediaStatus == WIMAX_API_MEDIA_STATUS_LINK_UP + && wmxsdk->media_status == WIMAX_API_MEDIA_STATUS_LINK_UP) + return; + + wmxsdk->media_status = mediaStatus; + + nm_log_dbg(LOGD_WIMAX, "wmxsdk: media status change to (%d) %s", + mediaStatus, iwmx_sdk_media_status_to_str (mediaStatus)); + + _schedule_media_status_change(wmxsdk, mediaStatus); +} + +/* + * Callback for state change messages + * + * Just pass them to the state transition handler + */ +static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_DEVICE_STATUS status, + WIMAX_API_STATUS_REASON reason, + WIMAX_API_CONNECTION_PROGRESS_INFO pi) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + WIMAX_API_DEVICE_STATUS old_status; + + nm_log_dbg(LOGD_WIMAX, "wmxsdk: state change to (%d) %s reason (%d) %s", + status, iwmx_sdk_dev_status_to_str (status), + reason, iwmx_sdk_reason_to_str (reason)); + + g_mutex_lock(wmxsdk->status_mutex); + old_status = wmxsdk->status; + wmxsdk->status = status; + g_mutex_unlock(wmxsdk->status_mutex); + + _schedule_state_change(wmxsdk, status, old_status, reason); +} + +/* + * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results + * are available. + * + * From here we update NetworkManager's idea of which networks are available. + */ +static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + g_static_mutex_lock(&wmxsdk->network_mutex); + _schedule_scan_result(wmxsdk, nsp_list, nsp_list_size); + g_static_mutex_unlock(&wmxsdk->network_mutex); +} + +/* + * Called by the WiMAX API when we get a wide scan result + * + * We treat them same as wide, so we just call that. + */ +static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size) +{ + __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); +} + +/* + * Called by the WiMAX API when we get a normal (non wide) scan result + * + * We treat them same as wide, so we just call that. + */ +static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size, UINT32 searchProgress) +{ + __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); +} + +/* + * Called to ask the device to scan for networks + * + * We don't really scan as the WiMAX SDK daemon scans in the + * background for us. We just get the results and hand them back via + * the scan_result_cb callback. + */ +int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk) +{ + int result; + + UINT32 nsp_list_length = 10; + WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */ + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get network list: %d (%s)", r, errstr); + result = -EIO; + goto error_scan; + } + + if (nsp_list_length == 0) { + nm_log_dbg(LOGD_WIMAX, "no networks"); + } else + __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list, + nsp_list_length); + result = 0; +error_scan: + return result; +} + +/* + * Initialize the WiMAX API, register with it, setup callbacks + * + */ +static int iwmx_sdk_setup(struct wmxsdk *wmxsdk) +{ + int result, status; + + WIMAX_API_RET r; + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + result = -ENFILE; + + /* device_id initialized by iwmx_sdk_dev_add */ + + r = WiMaxDeviceOpen(&wmxsdk->device_id); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot open device: %d (%s)", r, errstr); + goto error_wimaxdeviceopen; + } + + /* + * We scan in auto mode (in the background) + * + * Otherwise is messy -- if we have NetworkManager triggering a scan + * when we call iwmx_nm_scan() -> iwmx_sdk_scan(), most of the + * times that causes a race condition when the UI asks for a + * scan right before displaying the network menu. As there is + * no way to cancel an ongoing scan before connecting, we are + * stuck. So we do auto bg and have iwmx_sdk_scan() just return + * the current network list. + */ + r = SetConnectionMode(&wmxsdk->device_id, + WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set connectin mode to manual: %d (%s)", r, errstr); + goto error_connection_mode; + } + + r = SubscribeControlPowerManagement(&wmxsdk->device_id, + __iwmx_sdk_rf_state_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to radio change events: %u (%s)", r, errstr); + result = -EIO; + goto error_subscribe_rf_state; + } + + r = SubscribeDeviceStatusChange(&wmxsdk->device_id, + __iwmx_sdk_state_change_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to state chaneg events: %d (%s)", r, errstr); + goto error_subscribe_state_change; + } + + r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id, + __iwmx_sdk_wide_scan_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to wide scan events: %d (%s)", r, errstr); + goto error_subscribe_wide_scan; + } + r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to scan events: %d (%s)", r, errstr); + goto error_subscribe_scan; + } + + r = SubscribeConnectToNetwork(&wmxsdk->device_id, + __iwmx_sdk_connect_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to connect events: %d (%s)", r, errstr); + goto error_subscribe_connect; + } + + r = SubscribeDisconnectToNetwork(&wmxsdk->device_id, + __iwmx_sdk_disconnect_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to disconnect events: %d (%s)", r, errstr); + goto error_subscribe_disconnect; + } + + r = SubscribeMediaStatusUpdate(&wmxsdk->device_id, __iwmx_sdk_media_status_update_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to media status events: %d (%s)", r, errstr); + goto error_subscribe_media_status; + } + + status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) status < 0) + status = WIMAX_API_DEVICE_STATUS_UnInitialized; + + g_mutex_lock(wmxsdk->status_mutex); + wmxsdk->status = status; + g_mutex_unlock(wmxsdk->status_mutex); + + _schedule_state_change(wmxsdk, + status, + WIMAX_API_DEVICE_STATUS_UnInitialized, + WIMAX_API_STATUS_REASON_Normal); + + return 0; + + UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); +error_subscribe_media_status: + UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); +error_subscribe_disconnect: + UnsubscribeConnectToNetwork(&wmxsdk->device_id); +error_subscribe_connect: + UnsubscribeNetworkSearchEx(&wmxsdk->device_id); +error_subscribe_scan: + UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); +error_subscribe_wide_scan: + UnsubscribeDeviceStatusChange(&wmxsdk->device_id); +error_subscribe_state_change: + UnsubscribeControlPowerManagement(&wmxsdk->device_id); +error_subscribe_rf_state: +error_connection_mode: + WiMaxDeviceClose(&wmxsdk->device_id); +error_wimaxdeviceopen: + return result; +} + +/* + * Called when a device is torn down + * + * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks, + * unregister from the WiMAX API. + */ +static void iwmx_sdk_remove(struct wmxsdk *wmxsdk) +{ + UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); + UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); + UnsubscribeConnectToNetwork(&wmxsdk->device_id); + UnsubscribeNetworkSearchEx(&wmxsdk->device_id); + UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); + UnsubscribeDeviceStatusChange(&wmxsdk->device_id); + UnsubscribeControlPowerManagement(&wmxsdk->device_id); + WiMaxDeviceClose(&wmxsdk->device_id); +} + +void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, + WimaxStateChangeFunc state_change_cb, + WimaxMediaStatusFunc media_status_cb, + WimaxConnectResultFunc connect_result_cb, + WimaxScanResultFunc scan_result_cb, + WimaxRemovedFunc removed_cb, + void *user_data) +{ + wmxsdk->state_change_cb = state_change_cb; + wmxsdk->media_status_cb = media_status_cb; + wmxsdk->connect_result_cb = connect_result_cb; + wmxsdk->scan_result_cb = scan_result_cb; + wmxsdk->removed_cb = removed_cb; + wmxsdk->callback_data = user_data; +} + +/* Initialize a [zeroed] struct wmxsdk */ +static struct wmxsdk *wmxsdk_new(void) +{ + struct wmxsdk *wmxsdk; + + wmxsdk = malloc(sizeof(*wmxsdk)); + if (wmxsdk) { + memset(wmxsdk, 0, sizeof(*wmxsdk)); + + wmxsdk->refcount = 1; + g_static_mutex_init(&wmxsdk->network_mutex); + + wmxsdk->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + wmxsdk->status_mutex = g_mutex_new(); + g_assert(wmxsdk->status_mutex); + + wmxsdk->connect_mutex = g_mutex_new(); + g_assert(wmxsdk->connect_mutex); + } + return wmxsdk; +} + +struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk) +{ + g_atomic_int_add(&wmxsdk->refcount, 1); + return wmxsdk; +} + +void wmxsdk_unref(struct wmxsdk *wmxsdk) +{ + if (g_atomic_int_dec_and_test(&wmxsdk->refcount)) { + g_mutex_free(wmxsdk->status_mutex); + g_mutex_free(wmxsdk->connect_mutex); + memset(wmxsdk, 0, sizeof(*wmxsdk)); + free(wmxsdk); + } +} + +static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name) +{ + int ifindex; + struct wmxsdk *wmxsdk; + const char *s; + + if (idx >= IWMX_SDK_DEV_MAX) { + nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); + goto error_bug; + } + if (g_iwmx_sdk_devs[idx] != NULL) { + nm_log_err(LOGD_WIMAX, "BUG! device index %u already enumerated?", idx); + goto error_bug; + } + + wmxsdk = wmxsdk_new(); + if (wmxsdk == NULL) { + nm_log_err(LOGD_WIMAX, "Can't allocate %zu bytes", sizeof(*wmxsdk)); + goto error_bug; + } + + /* + * This depends on a hack in the WiMAX Network Service; it has + * to return, as part of the device name, a string "if:IFNAME" + * where the OS's device name is stored. + */ + s = strstr(name, "if:"); + if (s == NULL + || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) { + nm_log_err(LOGD_WIMAX, "Cannot extract network interface name off '%s'", + name); + goto error_noifname; + } + nm_log_dbg(LOGD_WIMAX, "network interface name: '%s'", wmxsdk->ifname); + + ifindex = if_nametoindex(wmxsdk->ifname); + if (ifindex <= 0) { + nm_log_err(LOGD_WIMAX, "wxmsdk: %s: cannot find interface index", wmxsdk->ifname); + goto error_noifname; + } + + strncpy(wmxsdk->name, name, sizeof(wmxsdk->name)); + wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; + wmxsdk->device_id.deviceIndex = api_idx; + + if (iwmx_sdk_setup(wmxsdk) != 0) { + nm_log_err(LOGD_WIMAX, "wxmsdk: %s: cannot set up interface", wmxsdk->ifname); + goto error_setup; + } + + g_iwmx_sdk_devs[idx] = wmxsdk; + + /* Notify listeners of new devices */ + iwmx_sdk_call_new_callbacks (wmxsdk); + return; + +error_setup: +error_noifname: + wmxsdk_unref(wmxsdk); +error_bug: + return; +} + +static void iwmx_sdk_dev_rm(unsigned idx) +{ + struct wmxsdk *wmxsdk; + + if (idx >= IWMX_SDK_DEV_MAX) { + nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); + return; + } + + wmxsdk = g_iwmx_sdk_devs[idx]; + _schedule_removed(wmxsdk); + iwmx_sdk_remove(wmxsdk); + wmxsdk_unref(wmxsdk); + g_iwmx_sdk_devs[idx] = NULL; +} + +static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid, + BOOL presence) +{ + unsigned int cnt; + WIMAX_API_RET r; + WIMAX_API_HW_DEVICE_ID device_id_list[5]; + UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + g_static_mutex_lock(&add_remove_mutex); + + nm_log_dbg(LOGD_WIMAX, "cb: handle %u index #%u is %d", devid->sdkHandle, + devid->deviceIndex, presence); + + r = GetListDevice(devid, device_id_list, &device_id_list_size); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(devid, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); + goto out; + } + + if (device_id_list_size == 0) { + nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); + } else { + for (cnt = 0; cnt < device_id_list_size; cnt++) { + WIMAX_API_HW_DEVICE_ID *dev = + device_id_list + cnt; + nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, + dev->deviceIndex, dev->deviceName); + } + } + + if (device_id_list_size < devid->deviceIndex) { + nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", + devid->deviceIndex, device_id_list_size); + goto out; + } + + if (presence) { + WIMAX_API_HW_DEVICE_ID *dev = + device_id_list + devid->deviceIndex; + iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex, + dev->deviceName); + } else { + iwmx_sdk_dev_rm(devid->deviceIndex); + } + +out: + g_static_mutex_unlock(&add_remove_mutex); +} + +/* + * Initialize the WiMAX API, register with it, setup callbacks for + * device coming up / dissapearing + */ +int iwmx_sdk_api_init(void) +{ + int result; + unsigned int cnt; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + WIMAX_API_HW_DEVICE_ID device_id_list[5]; + UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); + + memset(&g_api, 0, sizeof(g_api)); + g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; + + result = -EIO; + r = WiMaxAPIOpen(&g_api); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIOpen failed with %d (%s)", r, errstr); + goto error_wimaxapiopen; + } + + r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: insert/remove subscribe failed with %d (%s)", r, errstr); + goto error_close; + } + + r = GetListDevice(&g_api, device_id_list, &device_id_list_size); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); + goto error_close; + } + if (device_id_list_size < g_api.deviceIndex) { + nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", + g_api.deviceIndex, device_id_list_size); + } + + if (device_id_list_size == 0) { + nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); + } else { + for (cnt = 0; cnt < device_id_list_size; cnt++) { + WIMAX_API_HW_DEVICE_ID *dev = device_id_list + cnt; + nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, dev->deviceIndex, dev->deviceName); + iwmx_sdk_dev_add(cnt, dev->deviceIndex, dev->deviceName); + } + } + return 0; + +error_close: + WiMaxAPIClose(&g_api); +error_wimaxapiopen: + return result; +} + +void iwmx_sdk_api_exit(void) +{ + WIMAX_API_RET r; + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = WiMaxAPIClose(&g_api); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIClose failed with %d (%s)", r, errstr); + } + return; +} diff --git a/src/wimax/iwmxsdk.h b/src/wimax/iwmxsdk.h new file mode 100644 index 0000000000..bd55679ab2 --- /dev/null +++ b/src/wimax/iwmxsdk.h @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef IWMXSDK_H +#define IWMXSDK_H + +#include <wimax/WiMaxType.h> +#include <wimax/WiMaxTypesEx.h> +#include <wimax/WiMaxAPIEx.h> + +struct wmxsdk; + +typedef void (*WimaxNewWmxsdkFunc) (struct wmxsdk *wmxsdk, void *user_data); + +typedef void (*WimaxStateChangeFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + void *user_data); + +typedef void (*WimaxMediaStatusFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS media_status, + void *user_data); + +typedef void (*WimaxConnectResultFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP resp, + void *user_data); + +typedef void (*WimaxScanResultFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps, + void *user_data); + +typedef void (*WimaxRemovedFunc) (struct wmxsdk *wmxsdk, void *user_data); + +struct wmxsdk { + gint refcount; + + WIMAX_API_DEVICE_ID device_id; + + WimaxStateChangeFunc state_change_cb; + WimaxMediaStatusFunc media_status_cb; + WimaxConnectResultFunc connect_result_cb; + WimaxScanResultFunc scan_result_cb; + WimaxRemovedFunc removed_cb; + void *callback_data; + + GStaticMutex network_mutex; + + WIMAX_API_DEVICE_STATUS status; + WIMAX_API_MEDIA_STATUS media_status; + GMutex *status_mutex; + + GMutex *connect_mutex; + + char name[100]; + char ifname[16]; +}; + +struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface); + +struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk); +void wmxsdk_unref(struct wmxsdk *wmxsdk); + +/* Register/unregister callbacks when a new wmxsdk is set up */ +void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data); +void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data); + +void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, + WimaxStateChangeFunc state_change_cb, + WimaxMediaStatusFunc media_status_func, + WimaxConnectResultFunc connect_result_cb, + WimaxScanResultFunc scan_result_cb, + WimaxRemovedFunc removed_cb, + void *user_data); + +WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk); +int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name); +int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk); +int iwmx_sdk_set_fast_reconnect_enabled(struct wmxsdk *wmxsdk, int enabled); +WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk); +WIMAX_API_LINK_STATUS_INFO_EX *iwmx_sdk_get_link_status_info(struct wmxsdk *wmxsdk); +const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status); +const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason); +const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status); +int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state); +int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk); +int iwmx_sdk_api_init(void); +void iwmx_sdk_api_exit(void); + +#endif /* IWMXSDK_H */ diff --git a/src/wimax/nm-device-wimax.c b/src/wimax/nm-device-wimax.c new file mode 100644 index 0000000000..fba108f5be --- /dev/null +++ b/src/wimax/nm-device-wimax.c @@ -0,0 +1,1444 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2010 - 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <net/ethernet.h> +#include <net/if.h> + +#include <WiMaxAPI.h> +#include <WiMaxAPIEx.h> + +#include "nm-device-wimax.h" +#include "nm-wimax-util.h" +#include "nm-logging.h" +#include "nm-device-interface.h" +#include "nm-device-private.h" +#include "nm-system.h" +#include "NetworkManagerUtils.h" +#include "nm-properties-changed-signal.h" +#include "nm-connection.h" +#include "nm-setting-connection.h" +#include "nm-setting-wimax.h" +#include "nm-utils.h" +#include "nm-rfkill.h" +#include "iwmxsdk.h" + +static gboolean impl_device_get_nsp_list (NMDeviceWimax *device, GPtrArray **list, GError **error); + +#include "nm-device-wimax-glue.h" + +static void device_interface_init (NMDeviceInterface *iface_class); + +G_DEFINE_TYPE_EXTENDED (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_ACTIVE_NSP, + PROP_CENTER_FREQ, + PROP_RSSI, + PROP_CINR, + PROP_TX_POWER, + PROP_BSID, + + LAST_PROP +}; + +enum { + NSP_ADDED, + NSP_REMOVED, + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_DEVICE_WIMAX, \ + NMDeviceWimaxPrivate)) + +typedef struct { + gboolean disposed; + + struct wmxsdk *sdk; + WIMAX_API_DEVICE_STATUS status; + gboolean connect_failed; + + gboolean enabled; + gboolean wimaxd_enabled; + struct ether_addr hw_addr; + guint activation_timeout_id; + + guint sdk_action_defer_id; + + guint link_timeout_id; + guint poll_id; + + GSList *nsp_list; + NMWimaxNsp *current_nsp; + + /* interesting stuff when connected */ + guint center_freq; + gint rssi; + gint cinr; + gint tx_power; + char *bsid; +} NMDeviceWimaxPrivate; + +/***********************************************************/ + +typedef enum +{ + NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX = 0, + NM_WIMAX_ERROR_CONNECTION_INVALID, + NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, +} NMWimaxError; + +#define NM_WIMAX_ERROR (nm_wimax_error_quark ()) +#define NM_TYPE_WIMAX_ERROR (nm_wimax_error_get_type ()) + +static GQuark +nm_wimax_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-wimax-error"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +static GType +nm_wimax_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Connection was not a wired connection. */ + ENUM_ENTRY (NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, "ConnectionNotWimax"), + /* Connection was not a valid wired connection. */ + ENUM_ENTRY (NM_WIMAX_ERROR_CONNECTION_INVALID, "ConnectionInvalid"), + /* Connection does not apply to this device. */ + ENUM_ENTRY (NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMWimaxError", values); + } + return etype; +} + +/***********************************************************/ + +void +nm_device_wimax_get_hw_address (NMDeviceWimax *self, struct ether_addr *addr) +{ + NMDeviceWimaxPrivate *priv; + + g_return_if_fail (NM_IS_DEVICE_WIMAX (self)); + g_return_if_fail (addr != NULL); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr)); +} + +guint32 +nm_device_wimax_get_center_frequency (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->center_freq; +} + +gint +nm_device_wimax_get_rssi (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->rssi; +} + +gint +nm_device_wimax_get_cinr (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->cinr; +} + +gint +nm_device_wimax_get_tx_power (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->tx_power; +} + +const char * +nm_device_wimax_get_bsid (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), NULL); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->bsid; +} + +static gboolean +impl_device_get_nsp_list (NMDeviceWimax *self, GPtrArray **nsps, GError **error) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + + *nsps = g_ptr_array_sized_new (g_slist_length (priv->nsp_list)); + for (iter = priv->nsp_list; iter; iter = iter->next) { + const char *path; + + path = nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)); + if (path) + g_ptr_array_add (*nsps, g_strdup (path)); + } + + return TRUE; +} + +static void +set_current_nsp (NMDeviceWimax *self, NMWimaxNsp *new_nsp) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMWimaxNsp *old_nsp; + char *old_path = NULL; + + old_nsp = priv->current_nsp; + if (old_nsp) { + old_path = g_strdup (nm_wimax_nsp_get_dbus_path (old_nsp)); + priv->current_nsp = NULL; + } + + if (new_nsp) + priv->current_nsp = g_object_ref (new_nsp); + + if (old_nsp) + g_object_unref (old_nsp); + + /* Only notify if it's really changed */ + if ( (!old_path && new_nsp) + || (old_path && !new_nsp) + || (old_path && new_nsp && strcmp (old_path, nm_wimax_nsp_get_dbus_path (new_nsp)))) + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); + + g_free (old_path); +} + +NMWimaxNsp * +nm_device_wimax_get_active_nsp (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), NULL); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->current_nsp; +} + +static gboolean +activation_timed_out (gpointer data) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (data); + + priv->activation_timeout_id = 0; + nm_device_state_changed (NM_DEVICE (data), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + + return FALSE; +} + +static void +remove_all_nsps (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + while (g_slist_length (priv->nsp_list)) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data); + + priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); + g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); + g_object_unref (nsp); + } + + g_slist_free (priv->nsp_list); + priv->nsp_list = NULL; +} + +static NMWimaxNsp * +get_nsp_by_name (NMDeviceWimax *self, const char *name) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), name)) + return nsp; + } + + return NULL; +} + +static gboolean +update_availability (NMDeviceWimax *self, gboolean old_available) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceState state; + gboolean new_available, changed = FALSE; + + new_available = nm_device_is_available (device); + if (new_available == old_available) + return FALSE; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (state == NM_DEVICE_STATE_UNAVAILABLE) { + if (new_available == TRUE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + changed = TRUE; + } + } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { + if (new_available == FALSE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + changed = TRUE; + } + } + + return changed; +} + +/* NMDeviceInterface interface */ + +static void +real_set_enabled (NMDeviceInterface *device, gboolean enabled) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + gboolean old_available; + int ret; + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + + nm_log_dbg (LOGD_WIMAX, "(%s): setting radio enabled %d -> %d", + iface, priv->enabled, enabled); + if (priv->enabled == enabled) + return; + + old_available = nm_device_is_available (NM_DEVICE (device)); + priv->enabled = enabled; + + nm_log_dbg (LOGD_WIMAX, "(%s): radio now %s", + iface, priv->enabled ? "enabled" : "disabled"); + + /* Set the WiMAX device RF state to the current user-specified enabled state */ + if (priv->sdk) { + ret = iwmx_sdk_rf_state_set (priv->sdk, + enabled ? WIMAX_API_RF_ON : WIMAX_API_RF_OFF); + if (ret < 0 && ret != -EINPROGRESS) { + nm_log_warn (LOGD_WIMAX, "(%s): failed to %s radio", + iface, priv->enabled ? "enable" : "disable"); + } + } + + update_availability (self, old_available); +} + +/* NMDevice methods */ + +static void +real_take_down (NMDevice *device) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + + set_current_nsp (self, NULL); + remove_all_nsps (self); +} + +static gboolean +real_hw_is_up (NMDevice *device) +{ + return nm_system_device_is_up (device); +} + +static gboolean +real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (dev); + + if (!priv->enabled || !priv->wimaxd_enabled) + return FALSE; + + return nm_system_device_set_up_down (dev, TRUE, no_firmware); +} + +static void +real_hw_take_down (NMDevice *dev) +{ + nm_system_device_set_up_down (dev, FALSE, NULL); +} + +static void +real_update_hw_address (NMDevice *dev) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (dev); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + struct ifreq req; + int fd; + const char *iface; + + iface = nm_device_get_iface (dev); + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_warn (LOGD_HW, "(%s): couldn't open control socket.", iface); + return; + } + + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); + + errno = 0; + if (ioctl (fd, SIOCGIFHWADDR, &req) < 0) { + nm_log_err (LOGD_HW | LOGD_WIMAX, + "(%s): failed to read hardware address (error %d)", + iface, errno); + } else { + memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, ETH_ALEN); + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_HW_ADDRESS); + } + + close (fd); +} + +static gboolean +real_check_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + NMSettingConnection *s_con; + NMSettingWimax *s_wimax; + const char *connection_type; + const GByteArray *mac; + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + + connection_type = nm_setting_connection_get_connection_type (s_con); + if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) { + g_set_error (error, + NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, + "The connection was not a WiMAX connection."); + return FALSE; + } + + s_wimax = (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX); + if (!s_wimax) { + g_set_error (error, + NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INVALID, + "The connection was not a valid WiMAX connection."); + return FALSE; + } + + mac = nm_setting_wimax_get_mac_address (s_wimax); + if (mac && memcmp (mac->data, &(priv->hw_addr.ether_addr_octet), ETH_ALEN)) { + g_set_error (error, + NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, + "The connection's MAC address did not match this device."); + return FALSE; + } + + return TRUE; +} + +static NMConnection * +real_get_best_auto_connection (NMDevice *device, + GSList *connections, + char **specific_object) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + GSList *iter; + + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + NMSettingConnection *s_con; + NMSettingWimax *s_wimax; + const char *connection_type; + const GByteArray *mac; + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert (s_con); + + if (!nm_setting_connection_get_autoconnect (s_con)) + continue; + + connection_type = nm_setting_connection_get_connection_type (s_con); + if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) + continue; + + s_wimax = (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX); + if (!s_wimax) + continue; + + mac = nm_setting_wimax_get_mac_address (s_wimax); + if (mac && memcmp (mac->data, priv->hw_addr.ether_addr_octet, ETH_ALEN)) + continue; + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + if (nm_wimax_nsp_check_compatible (nsp, connection)) { + *specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp); + return connection; + } + } + } + + return NULL; +} + +static guint32 +real_get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_NM_SUPPORTED; +} + +static gboolean +real_is_available (NMDevice *device) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + const char *iface = nm_device_get_iface (device); + + if (!priv->enabled) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled", iface); + return FALSE; + } + + if (!priv->wimaxd_enabled) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled in wimaxd", iface); + return FALSE; + } + + if (!nm_wimax_util_sdk_is_initialized ()) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because WiMAX SDK not initialized", iface); + return FALSE; + } + + if (!priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not known to WiMAX SDK", iface); + return FALSE; + } + + return iwmxsdk_status_get (priv->sdk) >= WIMAX_API_DEVICE_STATUS_Ready; +} + +static void +clear_activation_timeout (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->activation_timeout_id) { + g_source_remove (priv->activation_timeout_id); + priv->activation_timeout_id = 0; + } + + priv->connect_failed = FALSE; +} + +static void +clear_link_timeout (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->link_timeout_id) { + g_source_remove (priv->link_timeout_id); + priv->link_timeout_id = 0; + } +} + +static void +clear_connected_poll (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->poll_id) { + g_source_remove (priv->poll_id); + priv->poll_id = 0; + } +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + NMActRequest *req; + GSList *iter; + const char *path; + + clear_link_timeout (NM_DEVICE_WIMAX (device)); + + req = nm_device_get_act_request (device); + if (!req) + goto err; + + path = nm_act_request_get_specific_object (req); + if (!path) + goto err; + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + if (!strcmp (path, nm_wimax_nsp_get_dbus_path (nsp))) { + set_current_nsp (NM_DEVICE_WIMAX (device), nsp); + return NM_ACT_STAGE_RETURN_SUCCESS; + } + } + + err: + *reason = NM_DEVICE_STATE_REASON_NONE; + return NM_ACT_STAGE_RETURN_FAILURE; +} + +static NMActStageReturn +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + NMConnection *connection; + NMSettingWimax *s_wimax; + const char *nsp; + int ret; + + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + g_assert (connection); + + s_wimax = NM_SETTING_WIMAX (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX)); + g_assert (s_wimax); + + nsp = nm_setting_wimax_get_network_name (s_wimax); + g_assert (nsp); + + priv->connect_failed = FALSE; + ret = iwmx_sdk_connect (priv->sdk, nsp); + if (ret < 0 && ret != -EINPROGRESS) { + nm_log_err (LOGD_WIMAX, "(%s): failed to connect to NSP '%s'", + nm_device_get_iface (device), nsp); + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* FIXME: Is 40 seconds good estimation? I have no idea */ + priv->activation_timeout_id = g_timeout_add_seconds (40, activation_timed_out, device); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static void +force_disconnect (NMDeviceWimax *self, struct wmxsdk *sdk) +{ + WIMAX_API_DEVICE_STATUS status; + int ret; + const char *iface; + + g_return_if_fail (sdk != NULL); + + iface = nm_device_get_iface (NM_DEVICE (self)); + + status = iwmxsdk_status_get (sdk); + if ((int) status < 0) { + nm_log_err (LOGD_WIMAX, "(%s): failed to read WiMAX device status: %d", + iface, status); + return; + } + + if ( status == WIMAX_API_DEVICE_STATUS_Connecting + || status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_dbg (LOGD_WIMAX, "(%s): requesting disconnect", iface); + ret = iwmx_sdk_disconnect (sdk); + if (ret < 0 && ret != -EINPROGRESS) { + nm_log_err (LOGD_WIMAX, "(%s): failed to disconnect WiMAX device: %d", + iface, ret); + } + } +} + +static void +real_deactivate_quickly (NMDevice *device) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + clear_activation_timeout (self); + clear_link_timeout (self); + clear_connected_poll (self); + + set_current_nsp (self, NULL); + + if (priv->sdk) { + /* Read explicit status here just to make sure we have the most + * up-to-date status and to ensure we disconnect if needed. + */ + force_disconnect (self, priv->sdk); + } +} + +/*************************************************************************/ + +static void +wmx_state_change_cb (struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + const char *iface; + gboolean old_available = FALSE; + const char *nsp_name = NULL; + + if (new_status == old_status) + return; + + iface = nm_device_get_iface (NM_DEVICE (self)); + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + old_available = nm_device_is_available (NM_DEVICE (self)); + + priv->status = new_status; + if (priv->current_nsp) + nsp_name = nm_wimax_nsp_get_name (priv->current_nsp); + + nm_log_dbg (LOGD_WIMAX, "(%s): wimax state change %s -> %s (reason %d)", + iface, + iwmx_sdk_dev_status_to_str (old_status), + iwmx_sdk_dev_status_to_str (new_status), + reason); + + switch (new_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + if (priv->wimaxd_enabled) { + priv->wimaxd_enabled = FALSE; + if (update_availability (self, old_available)) + return; + } + break; + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + /* If for some reason we're initially connected, force a disconnect here */ + if (state < NM_DEVICE_STATE_DISCONNECTED) + force_disconnect (self, wmxsdk); + /* Fall through */ + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + if (priv->wimaxd_enabled == FALSE) { + priv->wimaxd_enabled = TRUE; + if (update_availability (self, old_available)) + return; + } + break; + default: + nm_log_warn (LOGD_WIMAX, "(%s): unhandled WiMAX device state %d", + iface, new_status); + break; + } + + /* Handle activation success and failure */ + if (IS_ACTIVATING_STATE (state)) { + if (new_status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + /* Success */ + clear_activation_timeout (self); + + nm_log_info (LOGD_WIMAX, "(%s): connected to '%s'", + iface, nsp_name); + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); + return; + } + + if (priv->connect_failed) { + /* Connection attempt failed */ + nm_log_info (LOGD_WIMAX, "(%s): connection to '%s' failed: (%d) %s", + iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } + } + + /* Handle disconnection */ + if (state == NM_DEVICE_STATE_ACTIVATED) { + if ( old_status == WIMAX_API_DEVICE_STATUS_Data_Connected + && new_status < WIMAX_API_DEVICE_STATUS_Connecting) { + + nm_log_info (LOGD_WIMAX, "(%s): disconnected from '%s': (%d) %s", + iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } + } +} + +static gboolean +link_timeout_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + priv->link_timeout_id = 0; + + nm_log_dbg (LOGD_WIMAX, "(%s): link timed out", nm_device_get_iface (NM_DEVICE (self))); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CARRIER); + + return FALSE; +} + +static void +wmx_media_status_cb (struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS new_status, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + + nm_log_dbg (LOGD_WIMAX, "(%s): media status change to %s", + iface, iwmx_sdk_media_status_to_str (new_status)); + + /* We only care about media events while activated */ + if (state != NM_DEVICE_STATE_ACTIVATED) + return; + + clear_link_timeout (self); + + switch (new_status) { + case WIMAX_API_MEDIA_STATUS_LINK_UP: + break; + case WIMAX_API_MEDIA_STATUS_LINK_DOWN: + nm_log_dbg (LOGD_WIMAX, "(%s): starting link timeout", iface); + priv->link_timeout_id = g_timeout_add (15, link_timeout_cb, self); + break; + case WIMAX_API_MEDIA_STATUS_LINK_RENEW: + nm_log_dbg (LOGD_WIMAX, "(%s): renewing DHCP lease", iface); + if (!nm_device_dhcp4_renew (NM_DEVICE (self), TRUE)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_FAILED); + } + break; + default: + nm_log_err (LOGD_WIMAX, "(%s): unhandled media status %d", iface, new_status); + break; + } +} + +static void +wmx_connect_result_cb (struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP result, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (IS_ACTIVATING_STATE (state)) { + priv->connect_failed = (result == WIMAX_API_CONNECTION_SUCCESS); + /* Wait for the state change so we can get the reason code; we + * cache the connect failure so we don't have to wait for the + * activation timeout. + */ + } +} + +static void +remove_outdated_nsps (NMDeviceWimax *self, + WIMAX_API_NSP_INFO_EX *nsp_list, + guint32 list_size) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + GSList *to_remove = NULL; + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + gboolean found = FALSE; + int i; + + for (i = 0; i < list_size; i++) { + WIMAX_API_NSP_INFO_EX *info = &nsp_list[i]; + + if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), (char *) info->NSPName)) { + found = TRUE; + break; + } + } + + if (!found) + to_remove = g_slist_prepend (to_remove, nsp); + } + + for (iter = to_remove; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); + priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); + g_object_unref (nsp); + } + + g_slist_free (to_remove); +} + +static void +wmx_scan_result_cb (struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + int i; + + remove_outdated_nsps (self, nsps, num_nsps); + + /* Add new NSPs and update existing ones */ + for (i = 0; i < num_nsps; i++) { + WIMAX_API_NSP_INFO_EX *sdk_nsp = &nsps[i]; + const char *nsp_name = (const char *) sdk_nsp->NSPName; + NMWimaxNspNetworkType net_type; + guint signalq; + NMWimaxNsp *nsp; + gboolean new_nsp; + + nsp = get_nsp_by_name (self, nsp_name); + new_nsp = (nsp == NULL); + if (new_nsp) { + nsp = nm_wimax_nsp_new (nsp_name); + nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX NSP '%s'", iface, nsp_name); + } + + net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); + if (net_type != nm_wimax_nsp_get_network_type (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_NETWORK_TYPE, net_type, NULL); + + signalq = sdk_nsp->linkQuality; + if (signalq != nm_wimax_nsp_get_signal_quality (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_SIGNAL_QUALITY, signalq, NULL); + + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", + iface, nsp_name, sdk_nsp->linkQuality, net_type); + + if (new_nsp) { + priv->nsp_list = g_slist_append (priv->nsp_list, nsp); + nm_wimax_nsp_export_to_dbus (nsp); + g_signal_emit (self, signals[NSP_ADDED], 0, nsp); + } + } +} + +static void +wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->sdk) { + /* Clear callbacks just in case we don't hold the last reference */ + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); + + wmxsdk_unref (priv->sdk); + priv->sdk = NULL; + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } +} + +/*************************************************************************/ + +static inline gint +sdk_rssi_to_dbm (guint raw_rssi) +{ + /* Values range from 0x00 to 0x53, where -123dBm is encoded as 0x00 and + * -40dBm encoded as 0x53 in 1dB increments. + */ + return raw_rssi - 123; +} + +static inline gint +sdk_cinr_to_db (guint raw_cinr) +{ + /* Values range from 0x00 to 0x3F, where -10dB is encoded as 0x00 and + * 53dB encoded as 0x3F in 1dB increments. + */ + return raw_cinr - 10; +} + +static inline gint +sdk_tx_pow_to_dbm (guint raw_tx_pow) +{ + /* Values range from 0x00 to 0xFF, where -84dBm is encoded as 0x00 and + * 43.5dBm is encoded as 0xFF in 0.5dB increments. Normalize so that + * 0 dBm == 0. + */ + return (int) (((double) raw_tx_pow / 2.0) - 84) * 2; +} + +static void +set_link_status (NMDeviceWimax *self, WIMAX_API_LINK_STATUS_INFO_EX *link_status) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + guint center_freq = 0; + gint conv_rssi = 0, conv_cinr = 0, conv_tx_pow = 0; + char *new_bsid = NULL; + + if (link_status) { + center_freq = link_status->centerFrequency; + conv_rssi = sdk_rssi_to_dbm (link_status->RSSI); + conv_cinr = sdk_cinr_to_db (link_status->CINR); + conv_tx_pow = sdk_tx_pow_to_dbm (link_status->txPWR); + new_bsid = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", + link_status->bsId[0], link_status->bsId[1], + link_status->bsId[2], link_status->bsId[3], + link_status->bsId[4], link_status->bsId[5]); + } + + if (priv->center_freq != center_freq) { + priv->center_freq = center_freq; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_CENTER_FREQUENCY); + } + + if (priv->rssi != conv_rssi) { + priv->rssi = conv_rssi; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_RSSI); + } + + if (priv->cinr != conv_cinr) { + priv->cinr = conv_cinr; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_CINR); + } + + if (priv->tx_power != conv_tx_pow) { + priv->tx_power = conv_tx_pow; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_TX_POWER); + } + + if (g_strcmp0 (priv->bsid, new_bsid) != 0) { + g_free (priv->bsid); + priv->bsid = new_bsid; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_BSID); + } else + g_free (new_bsid); +} + +static gboolean +connected_poll_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + WIMAX_API_CONNECTED_NSP_INFO_EX *sdk_nsp; + WIMAX_API_LINK_STATUS_INFO_EX *link_status; + + g_return_val_if_fail (priv->sdk != NULL, FALSE); + + /* Get details of the connected NSP */ + sdk_nsp = iwmx_sdk_get_connected_network (priv->sdk); + if (sdk_nsp) { + const char *nsp_name = (const char *) sdk_nsp->NSPName; + NMWimaxNsp *nsp; + + nsp = get_nsp_by_name (self, nsp_name); + if (nsp) { + NMWimaxNspNetworkType net_type; + guint signalq; + + net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); + if (net_type != nm_wimax_nsp_get_network_type (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_NETWORK_TYPE, net_type, NULL); + + signalq = sdk_nsp->linkQuality; + if (signalq != nm_wimax_nsp_get_signal_quality (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_SIGNAL_QUALITY, signalq, NULL); + + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", + nm_device_get_iface (NM_DEVICE (self)), + nsp_name, sdk_nsp->linkQuality, net_type); + } + free (sdk_nsp); + } + + /* Get details of the current radio link */ + link_status = iwmx_sdk_get_link_status_info (priv->sdk); + if (link_status) { + set_link_status (self, link_status); + free (link_status); + } + + return TRUE; /* reschedule */ +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (new_state < NM_DEVICE_STATE_DISCONNECTED) + remove_all_nsps (self); + + /* Request initial NSP list */ + if ( new_state == NM_DEVICE_STATE_DISCONNECTED + && old_state < NM_DEVICE_STATE_DISCONNECTED) { + if (priv->sdk) + iwmx_sdk_get_networks (priv->sdk); + } + + if (new_state == NM_DEVICE_STATE_FAILED || new_state <= NM_DEVICE_STATE_DISCONNECTED) + clear_activation_timeout (self); + + if (new_state == NM_DEVICE_STATE_ACTIVATED) { + /* poll link quality and BSID */ + clear_connected_poll (self); + priv->poll_id = g_timeout_add_seconds (10, connected_poll_cb, self); + connected_poll_cb (self); + } else { + clear_link_timeout (self); + clear_connected_poll (self); + set_link_status (self, NULL); + } +} + +/*************************************************************************/ + +static gboolean +sdk_action_defer_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + gboolean old_available = nm_device_is_available (NM_DEVICE (self)); + + NM_DEVICE_WIMAX_GET_PRIVATE (self)->sdk_action_defer_id = 0; + update_availability (self, old_available); + return FALSE; +} + +static void +wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + /* If we now have the SDK, schedule an idle handler to start the device up */ + if (!priv->sdk) { + priv->sdk = wmxsdk_ref (sdk); + iwmx_sdk_set_callbacks(priv->sdk, + wmx_state_change_cb, + wmx_media_status_cb, + wmx_connect_result_cb, + wmx_scan_result_cb, + wmx_removed_cb, + self); + iwmx_sdk_set_fast_reconnect_enabled (priv->sdk, 0); + + if (!priv->sdk_action_defer_id) + priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self); + } +} + +/*************************************************************************/ + +NMDevice * +nm_device_wimax_new (const char *udi, + const char *iface, + const char *driver) +{ + NMDevice *device; + + g_return_val_if_fail (udi != NULL, NULL); + g_return_val_if_fail (iface != NULL, NULL); + g_return_val_if_fail (driver != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIMAX, + NM_DEVICE_INTERFACE_UDI, udi, + NM_DEVICE_INTERFACE_IFACE, iface, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_TYPE_DESC, "WiMAX", + NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_WIMAX, + NM_DEVICE_INTERFACE_RFKILL_TYPE, RFKILL_TYPE_WIMAX, + NULL); + if (device) { + struct wmxsdk *sdk; + + nm_wimax_util_sdk_ref (); + g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), NULL); + + /* See if the SDK already knows about this interface */ + sdk = iwmx_sdk_get_wmxsdk_for_iface (iface); + if (sdk) + wmx_new_sdk_cb (sdk, device); + + /* If it doesn't, we want to be notified when it does */ + iwmx_sdk_new_callback_register (wmx_new_sdk_cb, device); + } + + return device; +} + +static void +device_interface_init (NMDeviceInterface *iface_class) +{ + iface_class->set_enabled = real_set_enabled; +} + +static void +nm_device_wimax_init (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + struct ether_addr hw_addr; + + switch (prop_id) { + case PROP_HW_ADDRESS: + nm_device_wimax_get_hw_address (self, &hw_addr); + g_value_take_string (value, nm_ether_ntop (&hw_addr)); + break; + case PROP_ACTIVE_NSP: + if (priv->current_nsp) + g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_CENTER_FREQ: + g_value_set_uint (value, priv->center_freq); + break; + case PROP_RSSI: + g_value_set_int (value, priv->rssi); + break; + case PROP_CINR: + g_value_set_int (value, priv->cinr); + break; + case PROP_TX_POWER: + g_value_set_int (value, priv->tx_power); + break; + case PROP_BSID: + g_value_set_string (value, priv->bsid); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->disposed) + goto done; + + priv->disposed = TRUE; + + clear_activation_timeout (self); + clear_link_timeout (self); + clear_connected_poll (self); + + if (priv->sdk_action_defer_id) + g_source_remove (priv->sdk_action_defer_id); + + if (priv->sdk) { + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); + wmxsdk_unref (priv->sdk); + } + + g_free (priv->bsid); + + set_current_nsp (self, NULL); + + g_slist_foreach (priv->nsp_list, (GFunc) g_object_unref, NULL); + g_slist_free (priv->nsp_list); + + iwmx_sdk_new_callback_unregister (wmx_new_sdk_cb, self); + nm_wimax_util_sdk_unref (); + +done: + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); +} + +static void +nm_device_wimax_class_init (NMDeviceWimaxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceWimaxPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + + device_class->take_down = real_take_down; + device_class->hw_is_up = real_hw_is_up; + device_class->hw_bring_up = real_hw_bring_up; + device_class->hw_take_down = real_hw_take_down; + device_class->update_hw_address = real_update_hw_address; + device_class->check_connection_compatible = real_check_connection_compatible; + device_class->get_best_auto_connection = real_get_best_auto_connection; + device_class->get_generic_capabilities = real_get_generic_capabilities; + device_class->is_available = real_is_available; + device_class->act_stage1_prepare = real_act_stage1_prepare; + device_class->act_stage2_config = real_act_stage2_config; + device_class->deactivate_quickly = real_deactivate_quickly; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIMAX_HW_ADDRESS, + "MAC Address", + "Hardware MAC address", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_ACTIVE_NSP, + g_param_spec_boxed (NM_DEVICE_WIMAX_ACTIVE_NSP, + "Active NSP", + "Currently active NSP", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CENTER_FREQ, + g_param_spec_uint (NM_DEVICE_WIMAX_CENTER_FREQUENCY, + "Center frequency", + "Center frequency", + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_RSSI, + g_param_spec_int (NM_DEVICE_WIMAX_RSSI, + "RSSI", + "RSSI", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CINR, + g_param_spec_int (NM_DEVICE_WIMAX_CINR, + "CINR", + "CINR", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_TX_POWER, + g_param_spec_int (NM_DEVICE_WIMAX_TX_POWER, + "TX Power", + "TX Power", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_BSID, + g_param_spec_string (NM_DEVICE_WIMAX_BSID, + "BSID", + "BSID", + NULL, + G_PARAM_READABLE)); + + /* Signals */ + signals[NSP_ADDED] = + g_signal_new ("nsp-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[NSP_REMOVED] = + g_signal_new ("nsp-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, G_STRUCT_OFFSET (NMDeviceWimaxClass, properties_changed)); + + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_wimax_object_info); + + dbus_g_error_domain_register (NM_WIMAX_ERROR, NULL, NM_TYPE_WIMAX_ERROR); +} diff --git a/src/wimax/nm-device-wimax.h b/src/wimax/nm-device-wimax.h new file mode 100644 index 0000000000..d70380acc8 --- /dev/null +++ b/src/wimax/nm-device-wimax.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2010 - 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_DEVICE_WIMAX_H +#define NM_DEVICE_WIMAX_H + +#include <net/ethernet.h> +#include "nm-device.h" +#include "nm-wimax-nsp.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) +#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) +#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) +#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIMAX)) +#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) + +#define NM_DEVICE_WIMAX_HW_ADDRESS "hw-address" +#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" +#define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency" +#define NM_DEVICE_WIMAX_RSSI "rssi" +#define NM_DEVICE_WIMAX_CINR "cinr" +#define NM_DEVICE_WIMAX_TX_POWER "tx-power" +#define NM_DEVICE_WIMAX_BSID "bsid" + +typedef struct { + NMDevice parent; +} NMDeviceWimax; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*nsp_added) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); + void (*nsp_removed) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); + void (*properties_changed) (NMDeviceWimax *wimax, GHashTable *properties); +} NMDeviceWimaxClass; + +GType nm_device_wimax_get_type (void); + +NMDevice *nm_device_wimax_new (const char *udi, + const char *iface, + const char *driver); + +void nm_device_wimax_get_hw_address (NMDeviceWimax *self, + struct ether_addr *addr); + +NMWimaxNsp *nm_device_wimax_get_active_nsp (NMDeviceWimax *self); + +guint nm_device_wimax_get_center_frequency (NMDeviceWimax *self); + +gint nm_device_wimax_get_rssi (NMDeviceWimax *self); + +gint nm_device_wimax_get_cinr (NMDeviceWimax *self); + +gint nm_device_wimax_get_tx_power (NMDeviceWimax *self); + +const char *nm_device_wimax_get_bsid (NMDeviceWimax *self); + +G_END_DECLS + +#endif /* NM_DEVICE_WIMAX_H */ diff --git a/src/wimax/nm-wimax-nsp.c b/src/wimax/nm-wimax-nsp.c new file mode 100644 index 0000000000..d9e905b1fc --- /dev/null +++ b/src/wimax/nm-wimax-nsp.c @@ -0,0 +1,249 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#include "nm-wimax-nsp.h" +#include "NetworkManager.h" +#include "nm-dbus-manager.h" +#include "nm-setting-wimax.h" +#include "nm-properties-changed-signal.h" +#include "nm-wimax-nsp-glue.h" +#include "nm-utils.h" + +G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, G_TYPE_OBJECT) + +enum { + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_NAME, + PROP_SIGNAL_QUALITY, + PROP_NETWORK_TYPE, + + LAST_PROP +}; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) + +typedef struct { + char *dbus_path; + + char *name; + guint32 signal_quality; + NMWimaxNspNetworkType network_type; +} NMWimaxNspPrivate; + +NMWimaxNsp * +nm_wimax_nsp_new (const char *name) +{ + g_return_val_if_fail (name != NULL, NULL); + + return NM_WIMAX_NSP (g_object_new (NM_TYPE_WIMAX_NSP, + NM_WIMAX_NSP_NAME, name, + NULL)); +} + +const char * +nm_wimax_nsp_get_name (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); + + return GET_PRIVATE (self)->name; +} + +guint32 +nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); + + return GET_PRIVATE (self)->signal_quality; +} + +NMWimaxNspNetworkType +nm_wimax_nsp_get_network_type (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); + + return GET_PRIVATE (self)->network_type; +} + +void +nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self) +{ + NMWimaxNspPrivate *priv; + NMDBusManager *mgr; + DBusGConnection *g_connection; + static guint32 counter = 0; + + g_return_if_fail (NM_IS_WIMAX_NSP (self)); + + priv = GET_PRIVATE (self); + + if (priv->dbus_path) { + nm_warning ("NSP already exported."); + return; + } + + mgr = nm_dbus_manager_get (); + g_assert (mgr); + + g_connection = nm_dbus_manager_get_connection (mgr); + g_assert (g_connection); + + priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_WIMAX_NSP "/%d", counter++); + dbus_g_connection_register_g_object (g_connection, priv->dbus_path, G_OBJECT (self)); + + g_object_unref (mgr); +} + +const char * +nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); + + return GET_PRIVATE (self)->dbus_path; +} + +gboolean +nm_wimax_nsp_check_compatible (NMWimaxNsp *self, + NMConnection *connection) +{ + NMWimaxNspPrivate *priv; + NMSettingWimax *s_wimax; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + priv = GET_PRIVATE (self); + + s_wimax = NM_SETTING_WIMAX (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX)); + if (!s_wimax) + return FALSE; + + return g_strcmp0 (nm_wimax_nsp_get_name (self), nm_setting_wimax_get_network_name (s_wimax)) == 0; +} + +static void +nm_wimax_nsp_init (NMWimaxNsp *self) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMWimaxNspPrivate *priv = GET_PRIVATE (object); + guint32 quality; + guint network_type; + + switch (prop_id) { + case PROP_NAME: + /* Construct only */ + priv->name = g_value_dup_string (value); + break; + case PROP_SIGNAL_QUALITY: + quality = g_value_get_uint (value); + if (quality != priv->signal_quality) { + priv->signal_quality = quality; + g_object_notify (object, NM_WIMAX_NSP_SIGNAL_QUALITY); + } + break; + case PROP_NETWORK_TYPE: + network_type = g_value_get_uint (value); + if (network_type != priv->network_type) { + priv->network_type = network_type; + g_object_notify (object, NM_WIMAX_NSP_NETWORK_TYPE); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMWimaxNsp *self = NM_WIMAX_NSP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_wimax_nsp_get_name (self)); + break; + case PROP_SIGNAL_QUALITY: + g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (self)); + break; + case PROP_NETWORK_TYPE: + g_value_set_uint (value, nm_wimax_nsp_get_network_type (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMWimaxNspPrivate *priv = GET_PRIVATE (object); + + g_free (priv->name); + g_free (priv->dbus_path); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); +} + +static void +nm_wimax_nsp_class_init (NMWimaxNspClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMWimaxNspPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_WIMAX_NSP_NAME, + "Name", + "Name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SIGNAL_QUALITY, + g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, + "SignalQuality", + "SignalQuality", + 0, + 100, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_uint (NM_WIMAX_NSP_NETWORK_TYPE, + "NetworkType", + "NetworkType", + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + G_PARAM_READWRITE)); + + /* Signals */ + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMWimaxNspClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_wimax_nsp_object_info); +} diff --git a/src/wimax/nm-wimax-nsp.h b/src/wimax/nm-wimax-nsp.h new file mode 100644 index 0000000000..a74b68a79d --- /dev/null +++ b/src/wimax/nm-wimax-nsp.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_NSP_H +#define NM_WIMAX_NSP_H + +#include <glib-object.h> +#include "nm-wimax-types.h" +#include "nm-connection.h" + +#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) +#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) +#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) +#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIMAX_NSP)) +#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) + +#define NM_WIMAX_NSP_NAME "name" +#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" +#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" + +typedef struct { + GObject parent; +} NMWimaxNsp; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*properties_changed) (NMWimaxNsp *nsp, GHashTable *properties); +} NMWimaxNspClass; + +GType nm_wimax_nsp_get_type (void); + +NMWimaxNsp *nm_wimax_nsp_new (const char *name); +const char *nm_wimax_nsp_get_name (NMWimaxNsp *self); +guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self); +NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *self); + +void nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self); +const char *nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self); + +gboolean nm_wimax_nsp_check_compatible (NMWimaxNsp *self, + NMConnection *connection); + +#endif /* NM_WIMAX_NSP_H */ diff --git a/src/wimax/nm-wimax-types.h b/src/wimax/nm-wimax-types.h new file mode 100644 index 0000000000..8c807fd8a4 --- /dev/null +++ b/src/wimax/nm-wimax-types.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_TYPES_H +#define NM_WIMAX_TYPES_H + +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + NM_WIMAX_NSP_NETWORK_TYPE_HOME, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER +} NMWimaxNspNetworkType; + +#endif /* NM_WIMAX_TYPES_H */ diff --git a/src/wimax/nm-wimax-util.c b/src/wimax/nm-wimax-util.c new file mode 100644 index 0000000000..bca25a1dbf --- /dev/null +++ b/src/wimax/nm-wimax-util.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#include <WiMaxAPI.h> +#include "nm-wimax-util.h" +#include "nm-utils.h" +#include "iwmxsdk.h" +#include "nm-logging.h" + +static guint sdk_refcount = 0; + +void +nm_wimax_util_sdk_ref (void) +{ + int ret = 0; + + if (sdk_refcount == 0) { + ret = iwmx_sdk_api_init (); + if (ret != 0) { + nm_log_warn (LOGD_WIMAX, "Failed to initialize WiMAX: %d", ret); + return; + } + } + sdk_refcount++; +} + +gboolean +nm_wimax_util_sdk_is_initialized (void) +{ + return sdk_refcount > 0; +} + +void +nm_wimax_util_sdk_unref (void) +{ + g_return_if_fail (sdk_refcount > 0); + + sdk_refcount--; + if (sdk_refcount == 0) + iwmx_sdk_api_exit (); +} + +NMWimaxNspNetworkType +nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type) +{ + NMWimaxNspNetworkType type; + + switch (wimax_network_type) { + case WIMAX_API_HOME: + type = NM_WIMAX_NSP_NETWORK_TYPE_HOME; + break; + case WIMAX_API_PARTNER: + type = NM_WIMAX_NSP_NETWORK_TYPE_PARTNER; + break; + case WIMAX_API_ROAMING_PARTNER: + type = NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER; + break; + default: + type = NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN; + break; + } + + return type; +} + diff --git a/src/wimax/nm-wimax-util.h b/src/wimax/nm-wimax-util.h new file mode 100644 index 0000000000..71f5aa29d2 --- /dev/null +++ b/src/wimax/nm-wimax-util.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_UTIL_H +#define NM_WIMAX_UTIL_H + +#include <glib.h> + +#include <WiMaxType.h> +#include <WiMaxError.h> +#include "nm-wimax-types.h" + +void nm_wimax_util_sdk_ref (void); + +gboolean nm_wimax_util_sdk_is_initialized (void); + +void nm_wimax_util_sdk_unref (void); + +NMWimaxNspNetworkType nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type); + +#endif /* NM_WIMAX_UTIL_H */ diff --git a/system-settings/plugins/ifcfg-rh/plugin.c b/system-settings/plugins/ifcfg-rh/plugin.c index 8ebe196499..24a4d115dc 100644 --- a/system-settings/plugins/ifcfg-rh/plugin.c +++ b/system-settings/plugins/ifcfg-rh/plugin.c @@ -149,7 +149,6 @@ _internal_new_connection (SCPluginIfcfg *self, if (nm_ifcfg_connection_get_unmanaged_spec (connection)) { PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its " "device due to NM_CONTROLLED/BRIDGE/VLAN.", cid); - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } else { /* Wait for the connection to become unmanaged once it knows the * hardware IDs of its device, if/when the device gets plugged in. @@ -245,9 +244,13 @@ connection_new_or_changed (SCPluginIfcfg *self, if (!existing) { /* Completely new connection */ new = _internal_new_connection (self, path, NULL, NULL); - if (new && !nm_ifcfg_connection_get_unmanaged_spec (new)) { - /* Only managed connections are announced to the settings service */ - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new); + if (new) { + if (nm_ifcfg_connection_get_unmanaged_spec (new)) { + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + } else { + /* Only managed connections are announced to the settings service */ + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new); + } } return; } diff --git a/system-settings/plugins/ifcfg-rh/reader.c b/system-settings/plugins/ifcfg-rh/reader.c index 68f7141cf5..14086f231b 100644 --- a/system-settings/plugins/ifcfg-rh/reader.c +++ b/system-settings/plugins/ifcfg-rh/reader.c @@ -683,12 +683,7 @@ read_one_ip4_route (shvarFile *ifcfg, /* Next hop */ if (!read_ip4_address (ifcfg, gw_tag, &tmp, error)) goto out; - if (!tmp) { - g_set_error (error, IFCFG_PLUGIN_ERROR, 0, - "Missing or invalid IP4 gateway address '%d'", - tmp); - goto out; - } + /* No need to check tmp, because we don't make distinction between missing GATEWAY IP and 0.0.0.0 */ nm_ip4_route_set_next_hop (route, tmp); /* Prefix */ @@ -1167,6 +1162,7 @@ make_ip4_setting (shvarFile *ifcfg, if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp")) method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; else if (!g_ascii_strcasecmp (value, "ibft")) { + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, NULL); /* iSCSI Boot Firmware Table: need to read values from the iSCSI * firmware for this device and create the IP4 setting using those. */ diff --git a/system-settings/plugins/ifnet/Makefile.am b/system-settings/plugins/ifnet/Makefile.am index 52056ffda2..9bf8a79a18 100644 --- a/system-settings/plugins/ifnet/Makefile.am +++ b/system-settings/plugins/ifnet/Makefile.am @@ -21,11 +21,10 @@ libnm_settings_plugin_ifnet_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GUDEV_CFLAGS) \ -DG_DISABLE_DEPRECATED \ - -DSYSCONFDIR=\"$(sysconfdir)\"\ - -g - + -DSYSCONFDIR=\"$(sysconfdir)\" libnm_settings_plugin_ifnet_la_LDFLAGS = -module -avoid-version + libnm_settings_plugin_ifnet_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ $(top_builddir)/libnm-glib/libnm-glib.la \ @@ -50,12 +49,9 @@ lib_ifnet_io_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ -DG_DISABLE_DEPRECATED \ -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DSBINDIR=\"$(sbindir)\"\ - -g + -DSBINDIR=\"$(sbindir)\" lib_ifnet_io_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ $(GLIB_LIBS)\ $(GIO_LIBS) - - diff --git a/system-settings/plugins/ifnet/net_utils.c b/system-settings/plugins/ifnet/net_utils.c index eecb5d74d3..338ead25dd 100644 --- a/system-settings/plugins/ifnet/net_utils.c +++ b/system-settings/plugins/ifnet/net_utils.c @@ -19,7 +19,6 @@ * Copyright (C) 1999-2010 Gentoo Foundation, Inc. */ -#include <config.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -188,6 +187,32 @@ ifnet_plugin_error_quark (void) return error_quark; } +static char * +find_default_gateway_str (char *str) +{ + char *tmp; + + if ((tmp = strstr (str, "default via ")) != NULL) { + return tmp + strlen ("default via "); + } else if ((tmp = strstr (str, "default gw ")) != NULL) { + return tmp + strlen ("default gw "); + } + return NULL; +} + +static char * +find_gateway_str (char *str) +{ + char *tmp; + + if ((tmp = strstr (str, "via ")) != NULL) { + return tmp + strlen ("via "); + } else if ((tmp = strstr (str, "gw ")) != NULL) { + return tmp + strlen ("gw "); + } + return NULL; +} + gboolean reload_parsers (void) { @@ -357,10 +382,8 @@ has_default_route (const char *conn_name, gboolean (*check_fn) (const char *)) routes = g_strdup (ifnet_get_data (conn_name, "routes")); if (!routes) return FALSE; - - tmp = strstr (routes, "default via "); + tmp = find_default_gateway_str (routes); if (tmp) { - tmp += strlen ("default via "); g_strstrip (tmp); if ((end = strstr (tmp, "\"")) != NULL) *end = '\0'; @@ -476,8 +499,13 @@ get_ip4_gateway (gchar * gateway) if (!gateway) return 0; - tmp = strstr (gateway, "via "); - tmp = g_strdup (tmp + strlen ("via ")); + tmp = find_gateway_str (gateway); + if (!tmp) { + PLUGIN_WARN (IFNET_PLUGIN_NAME, + "Couldn't obtain gateway in \"%s\"", gateway); + return 0; + } + tmp = g_strdup (tmp); strip_string (tmp, ' '); strip_string (tmp, '"'); if ((split = strstr (tmp, "\"")) != NULL) @@ -502,8 +530,13 @@ get_ip6_next_hop (gchar * next_hop) if (!next_hop) return 0; - tmp = strstr (next_hop, "via "); - tmp = g_strdup (tmp + strlen ("via ")); + tmp = find_gateway_str (next_hop); + if (!tmp) { + PLUGIN_WARN (IFNET_PLUGIN_NAME, + "Couldn't obtain next_hop in \"%s\"", next_hop); + return 0; + } + tmp = g_strdup (tmp); strip_string (tmp, ' '); strip_string (tmp, '"'); g_strstrip (tmp); @@ -668,8 +701,8 @@ convert_ip4_routes_block (const char *conn_name) length = g_strv_length (ipset); for (i = 0; i < length; i++) { ip = ipset[i]; - if (strstr (ip, "default via ") || strstr (ip, "::") - || !strstr (ip, "via")) + if (find_default_gateway_str (ip) || strstr (ip, "::") + || !find_gateway_str (ip)) continue; ip = strip_string (ip, '"'); iblock = create_ip4_block (ip); @@ -709,9 +742,7 @@ convert_ip6_routes_block (const char *conn_name) ip = strip_string (ip, '"'); if (ip[0] == '\0') continue; - printf ("ip:%s\n", ip); - if ((tmp_addr = strstr (ip, "default via ")) != NULL) { - tmp_addr += strlen ("default via "); + if ((tmp_addr = find_default_gateway_str (ip)) != NULL) { if (!is_ip6_address (tmp_addr)) continue; else { @@ -868,9 +899,9 @@ get_dhcp_hostname_and_client_id (char **hostname, char **client_id) gchar **all_lines; guint line_num, i; - dhcp_client = ifnet_get_global_setting ("main", "dhcp"); *hostname = NULL; *client_id = NULL; + dhcp_client = ifnet_get_global_setting ("main", "dhcp"); if (dhcp_client) { if (!strcmp (dhcp_client, "dhclient")) g_file_get_contents (dhclient_conf, &contents, NULL, diff --git a/system-settings/plugins/ifnet/plugin.c b/system-settings/plugins/ifnet/plugin.c index c0077c8757..710b9b5b5f 100644 --- a/system-settings/plugins/ifnet/plugin.c +++ b/system-settings/plugins/ifnet/plugin.c @@ -40,7 +40,7 @@ #include "connection_parser.h" #define IFNET_PLUGIN_NAME_PRINT "ifnet" -#define IFNET_PLUGIN_INFO "(C) 1999-2010 Gentoo Foundation, Inc. To report bugs please use bugs.gentoo.org with [networkmanager] or [dagger] prefix." +#define IFNET_PLUGIN_INFO "(C) 1999-2010 Gentoo Foundation, Inc. To report bugs please use bugs.gentoo.org with [networkmanager] or [qiaomuf] prefix." #define IFNET_SYSTEM_HOSTNAME_FILE "/etc/conf.d/hostname" #define IFNET_MANAGE_WELL_KNOWN_DEFAULT TRUE #define IFNET_KEY_FILE_KEY_MANAGED "managed" diff --git a/system-settings/plugins/ifnet/tests/Makefile.am b/system-settings/plugins/ifnet/tests/Makefile.am index 42a91d60c1..a351f31ce5 100644 --- a/system-settings/plugins/ifnet/tests/Makefile.am +++ b/system-settings/plugins/ifnet/tests/Makefile.am @@ -6,8 +6,7 @@ INCLUDES=-I$(top_srcdir)/system-settings/plugins/ifnet\ TESTS = check_ifnet check_PROGRAMS = check_ifnet check_ifnet_SOURCES = test_all.c -check_ifnet_LDFLAGS = -g -check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS) -g +check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS) check_ifnet_LDADD = $(top_srcdir)/libnm-util/libnm-util.la\ $(top_srcdir)/system-settings/plugins/ifnet/lib-ifnet-io.la\ $(CHECK_LIBS)\ diff --git a/system-settings/plugins/ifnet/tests/test_all.c b/system-settings/plugins/ifnet/tests/test_all.c index 1f6b9f5a21..2e9de7a21a 100644 --- a/system-settings/plugins/ifnet/tests/test_all.c +++ b/system-settings/plugins/ifnet/tests/test_all.c @@ -58,17 +58,22 @@ test_read_hostname () "get hostname", "hostname is not correctly read, read:%s, expected: gentoo", hostname); + g_free (hostname); } static void test_write_hostname () { gchar *hostname = read_hostname ("hostname"); + gchar *tmp; write_hostname ("gentoo-nm", "hostname"); - ASSERT (strcmp (read_hostname ("hostname"), "gentoo-nm") == 0, + tmp = read_hostname ("hostname"); + ASSERT (strcmp (tmp, "gentoo-nm") == 0, "write hostname", "write hostname error"); write_hostname (hostname, "hostname"); + g_free (tmp); + g_free (hostname); } static void @@ -85,14 +90,13 @@ test_is_static () static void test_has_default_route () { - ASSERT (has_default_ip4_route ("eth0"), "has default route", - "eth0 should have a default ipv4 route"); - ASSERT (has_default_ip6_route ("eth4"), "has default route", - "eth4 should have a default ipv6 route"); - + ASSERT (has_default_ip4_route ("eth0"), + "has default route", "eth0 should have a default ipv4 route"); + ASSERT (has_default_ip6_route ("eth4"), + "has default route", "eth4 should have a default ipv6 route"); ASSERT (!has_default_ip4_route ("eth5") - && !has_default_ip6_route ("eth5"), "has default route", - "eth5 shouldn't have a default route"); + && !has_default_ip6_route ("eth5"), + "has default route", "eth5 shouldn't have a default route"); } static void @@ -138,8 +142,8 @@ check_ip_block (ip_block * iblock, gchar * ip, gchar * netmask, gchar * gateway) str = malloc (INET_ADDRSTRLEN); tmp_ip4_addr.s_addr = iblock->ip; inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN); - ASSERT (strcmp (ip, str) == 0, "check ip", "ip expected:%s, find:%s", - ip, str); + ASSERT (strcmp (ip, str) == 0, "check ip", + "ip expected:%s, find:%s", ip, str); tmp_ip4_addr.s_addr = iblock->netmask; inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN); ASSERT (strcmp (netmask, str) == 0, "check netmask", @@ -170,8 +174,8 @@ test_convert_ipv4_config_block () destroy_ip_block (iblock); iblock = convert_ip4_config_block ("eth2"); ASSERT (iblock != NULL - && iblock->next == NULL, "convert error IPv4 address", - "should only get one address"); + && iblock->next == NULL, + "convert error IPv4 address", "should only get one address"); check_ip_block (iblock, "192.168.4.121", "255.255.255.0", "0.0.0.0"); destroy_ip_block (iblock); iblock = convert_ip4_config_block ("eth3"); @@ -182,7 +186,6 @@ test_convert_ipv4_config_block () ASSERT (iblock != NULL, "convert config_block", "convert error configuration"); destroy_ip_block (iblock); - } static void @@ -209,10 +212,13 @@ test_wpa_parser () ASSERT (exist_ssid ("static-wep-test"), "exist_ssid", "ssid static-wep-test is not found"); value = wpa_get_value ("static-wep-test", "key_mgmt"); - ASSERT (value && strcmp (value, "NONE") == 0, "get wpa data", + ASSERT (value + && strcmp (value, "NONE") == 0, "get wpa data", "key_mgmt of static-wep-test should be NONE, find %s", value); value = wpa_get_value ("static-wep-test", "wep_key0"); - ASSERT (value && strcmp (value, "\"abcde\"") == 0, "get wpa data", + ASSERT (value + && strcmp (value, "\"abcde\"") == 0, + "get wpa data", "wep_key0 of static-wep-test should be abcde, find %s", value); ASSERT (exist_ssid ("leap-example"), "get wsec", "ssid leap-example is not found"); @@ -228,8 +234,9 @@ test_strip_string () result = strip_string (result, '('); result = strip_string (result, ')'); result = strip_string (result, '"'); - ASSERT (strcmp (result, "default via 202.117.16.1") == 0, - "strip_string", "string isn't stripped, result is: %s", result); + ASSERT (strcmp (result, "default via 202.117.16.1") == + 0, "strip_string", + "string isn't stripped, result is: %s", result); g_free (result_b); } @@ -265,7 +272,6 @@ test_new_connection () "new connection failed: %s", error && (*error) ? (*error)->message : "NONE"); g_object_unref (connection); - } static void @@ -286,10 +292,10 @@ test_update_connection () NULL, error); ASSERT (success, "update connection", "update connection failed %s", "eth0"); + g_object_unref (connection); connection = ifnet_update_connection_from_config_block ("0xab3ace", error); - ASSERT (connection != NULL, "get connection", - "get connection failed: %s", + ASSERT (connection != NULL, "get connection", "get connection failed: %s", error == NULL ? "None" : (*error)->message); success = ifnet_update_parsers_by_connection (connection, "0xab3ace", @@ -297,8 +303,8 @@ test_update_connection () "wpa_supplicant.conf.generate", NULL, error); - ASSERT (success, "update connection", - "update connection failed %s", "0xab3ace"); + ASSERT (success, "update connection", "update connection failed %s", "0xab3ace"); + g_object_unref (connection); } static void @@ -309,14 +315,17 @@ test_add_connection () connection = ifnet_update_connection_from_config_block ("eth0", error); ASSERT (ifnet_add_new_connection - (connection, "net.generate", "wpa_supplicant.conf.generate", - error), "add connection", "add connection failed: %s", "eth0"); + (connection, "net.generate", + "wpa_supplicant.conf.generate", error), + "add connection", "add connection failed: %s", "eth0"); + g_object_unref (connection); connection = ifnet_update_connection_from_config_block ("myxjtu2", error); ASSERT (ifnet_add_new_connection - (connection, "net.generate", "wpa_supplicant.conf.generate", - error), "add connection", "add connection failed: %s", - "myxjtu2"); + (connection, "net.generate", + "wpa_supplicant.conf.generate", error), + "add connection", "add connection failed: %s", "myxjtu2"); + g_object_unref (connection); } static void @@ -330,16 +339,20 @@ test_delete_connection () "get connection failed: %s", error == NULL ? "None" : (*error)->message); ASSERT (ifnet_delete_connection_in_parsers - ("eth7", "net.generate", "wpa_supplicant.conf.generate"), + ("eth7", "net.generate", + "wpa_supplicant.conf.generate"), "delete connection", "delete connection failed: %s", "eth7"); + g_object_unref (connection); connection = ifnet_update_connection_from_config_block ("qiaomuf", error); ASSERT (connection != NULL, "get connection", "get connection failed: %s", error == NULL ? "None" : (*error)->message); ASSERT (ifnet_delete_connection_in_parsers - ("qiaomuf", "net.generate", "wpa_supplicant.conf.generate"), + ("qiaomuf", "net.generate", + "wpa_supplicant.conf.generate"), "delete connection", "delete connection failed: %s", "qiaomuf"); + g_object_unref (connection); } static void @@ -377,10 +390,8 @@ main (void) wpa_parser_destroy (); ifnet_init ("net"); wpa_parser_init ("wpa_supplicant.conf"); - printf("Initialization complete\n"); - + printf ("Initialization complete\n"); run_all (TRUE); - ifnet_destroy (); wpa_parser_destroy (); return 0; diff --git a/system-settings/plugins/ifupdown/plugin.c b/system-settings/plugins/ifupdown/plugin.c index 0acdf0eafb..389d6d9738 100644 --- a/system-settings/plugins/ifupdown/plugin.c +++ b/system-settings/plugins/ifupdown/plugin.c @@ -362,12 +362,55 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) while (block) { if(!strcmp ("auto", block->type) || !strcmp ("allow-hotplug", block->type)) g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1)); - else if (!strcmp ("iface", block->type) && strcmp ("lo", block->name)) { + else if (!strcmp ("iface", block->type)) { NMIfupdownConnection *exported; + /* Bridge configuration */ + if(!strncmp ("br", block->name, 2)) { + /* Try to find bridge ports */ + const char *ports = ifparser_getkey (block, "bridge_ports"); + if (ports) { + int i; + int state = 0; + char **port_ifaces; + + PLUGIN_PRINT("SCPlugin-Ifupdown", "found bridge ports %s for %s", ports, block->name); + + port_ifaces = g_strsplit_set (ports, " \t", -1); + for (i = 0; i < g_strv_length (port_ifaces); i++) { + char *token = port_ifaces[i]; + /* Skip crazy stuff like regex or all */ + if (!strcmp ("all", token)) { + continue; + } + /* Small SM to skip everything inside regex */ + if (!strcmp ("regex", token)) { + state++; + continue; + } + if (!strcmp ("noregex", token)) { + state--; + continue; + } + if (state == 0 && strlen (token) > 0) { + PLUGIN_PRINT("SCPlugin-Ifupdown", "adding bridge port %s to well_known_interfaces", token); + g_hash_table_insert (priv->well_known_interfaces, g_strdup (token), "known"); + } + } + g_strfreev (port_ifaces); + } + goto next; + } + + /* Skip loopback configuration */ + if(!strcmp ("lo", block->name)) { + goto next; + } + /* Remove any connection for this block that was previously found */ exported = g_hash_table_lookup (priv->iface_connections, block->name); if (exported) { + PLUGIN_PRINT("SCPlugin-Ifupdown", "deleting %s from iface_connections", block->name); nm_sysconfig_connection_delete (NM_SYSCONFIG_CONNECTION (exported), ignore_cb, NULL); @@ -377,12 +420,16 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) /* add the new connection */ exported = nm_ifupdown_connection_new (block); if (exported) { + PLUGIN_PRINT("SCPlugin-Ifupdown", "adding %s to iface_connections", block->name); g_hash_table_insert (priv->iface_connections, block->name, exported); - g_hash_table_insert (priv->well_known_interfaces, block->name, "known"); } + PLUGIN_PRINT("SCPlugin-Ifupdown", "adding iface %s to well_known_interfaces", block->name); + g_hash_table_insert (priv->well_known_interfaces, block->name, "known"); } else if (!strcmp ("mapping", block->type)) { g_hash_table_insert (priv->well_known_interfaces, block->name, "known"); + PLUGIN_PRINT("SCPlugin-Ifupdown", "adding mapping %s to well_known_interfaces", block->name); } + next: block = block->next; } diff --git a/system-settings/plugins/keyfile/plugin.c b/system-settings/plugins/keyfile/plugin.c index 5dddf494bf..a1c654245c 100644 --- a/system-settings/plugins/keyfile/plugin.c +++ b/system-settings/plugins/keyfile/plugin.c @@ -23,6 +23,7 @@ #include <sys/stat.h> #include <unistd.h> #include <sys/types.h> +#include <netinet/ether.h> #include <string.h> #include <gmodule.h> @@ -442,8 +443,23 @@ get_unmanaged_specs (NMSystemConfigInterface *config) udis = g_strsplit (str, ";", -1); g_free (str); - for (i = 0; udis[i] != NULL; i++) - specs = g_slist_append (specs, udis[i]); + for (i = 0; udis[i] != NULL; i++) { + /* Verify unmanaged specification and add it to the list */ + if (strlen (udis[i]) > 4 && !strncmp (udis[i], "mac:", 4) && ether_aton (udis[i] + 4)) { + char *p = udis[i]; + + /* To accept uppercase MACs in configuration file, we have to convert values to lowercase here. + * Unmanaged MACs in specs are always in lowercase. */ + while (*p) { + *p = g_ascii_tolower (*p); + p++; + } + specs = g_slist_append (specs, udis[i]); + } else { + g_warning ("Error in file '%s': invalid unmanaged-devices entry: '%s'", priv->conf_file, udis[i]); + g_free (udis[i]); + } + } g_free (udis); /* Yes, g_free, not g_strfreev because we need the strings in the list */ } diff --git a/test/nm-tool.c b/test/nm-tool.c index 922bb63b1e..65546e48e5 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* nm-tool - information tool for NetworkManager * * Dan Williams <dcbw@redhat.com> @@ -16,10 +17,11 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2005 - 2010 Red Hat, Inc. + * (C) Copyright 2005 - 2011 Red Hat, Inc. * (C) Copyright 2007 Novell, Inc. */ +#include <config.h> #include <glib.h> #include <dbus/dbus.h> #include <dbus/dbus-glib.h> @@ -38,6 +40,9 @@ #include <nm-gsm-device.h> #include <nm-cdma-device.h> #include <nm-device-bt.h> +#if WITH_WIMAX +#include <nm-device-wimax.h> +#endif #include <nm-utils.h> #include <nm-setting-ip4-config.h> #include <nm-setting-ip6-config.h> @@ -192,6 +197,48 @@ detail_access_point (gpointer data, gpointer user_data) g_free (tmp); } +#if WITH_WIMAX +static const char * +wimax_network_type_to_str (NMWimaxNspNetworkType type) +{ + switch (type) { + case NM_WIMAX_NSP_NETWORK_TYPE_HOME: + return "Home"; + case NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: + return "Partner"; + case NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: + return "Roaming"; + default: + return "Unknown"; + } +} + +static void +detail_nsp (gpointer data, gpointer user_data) +{ + NMWimaxNsp *nsp = NM_WIMAX_NSP (data); + const char *active_name = (const char *) user_data; + const char *name; + char *label; + char *data_str; + gboolean active = FALSE; + + name = nm_wimax_nsp_get_name (nsp); + + if (active_name) + active = g_strcmp0 (active_name, name) == 0; + + label = g_strdup_printf (" %s%s", active ? "*" : "", name); + data_str = g_strdup_printf ("%d%% (%s)", + nm_wimax_nsp_get_signal_quality (nsp), + wimax_network_type_to_str (nm_wimax_nsp_get_network_type (nsp))); + + print_string (label, data_str); + g_free (label); + g_free (data_str); +} +#endif + static gchar * ip4_address_as_string (guint32 ip) { @@ -329,6 +376,10 @@ detail_device (gpointer data, gpointer user_data) print_string ("Type", "Mobile Broadband (CDMA)"); else if (NM_IS_DEVICE_BT (device)) print_string ("Type", "Bluetooth"); +#if WITH_WIMAX + else if (NM_IS_DEVICE_WIMAX (device)) + print_string ("Type", "WiMAX"); +#endif print_string ("Driver", nm_device_get_driver (device) ? nm_device_get_driver (device) : "(unknown)"); @@ -344,6 +395,10 @@ detail_device (gpointer data, gpointer user_data) tmp = g_strdup (nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device))); else if (NM_IS_DEVICE_WIFI (device)) tmp = g_strdup (nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device))); +#if WITH_WIMAX + else if (NM_IS_DEVICE_WIMAX (device)) + tmp = g_strdup (nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device))); +#endif if (tmp) { print_string ("HW Address", tmp); @@ -409,6 +464,68 @@ detail_device (gpointer data, gpointer user_data) print_string (" Carrier", "on"); else print_string (" Carrier", "off"); +#if WITH_WIMAX + } else if (NM_IS_DEVICE_WIMAX (device)) { + NMDeviceWimax *wimax = NM_DEVICE_WIMAX (device); + NMWimaxNsp *active_nsp = NULL; + const char *active_name = NULL; + const GPtrArray *nsps; + + if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) { + guint tmp_uint; + gint tmp_int; + const char *tmp_str; + + active_nsp = nm_device_wimax_get_active_nsp (wimax); + active_name = active_nsp ? nm_wimax_nsp_get_name (active_nsp) : NULL; + + printf ("\n Link Status\n"); + + tmp_uint = nm_device_wimax_get_center_frequency (wimax); + if (tmp_uint) + tmp = g_strdup_printf ("%'.1f MHz", (double) tmp_uint / 1000.0); + else + tmp = g_strdup ("(unknown)"); + print_string (" Center Freq.", tmp); + g_free (tmp); + + tmp_int = nm_device_wimax_get_rssi (wimax); + if (tmp_int) + tmp = g_strdup_printf ("%d dBm", tmp_int); + else + tmp = g_strdup ("(unknown)"); + print_string (" RSSI", tmp); + g_free (tmp); + + tmp_int = nm_device_wimax_get_cinr (wimax); + if (tmp_int) + tmp = g_strdup_printf ("%d dB", tmp_int); + else + tmp = g_strdup ("(unknown)"); + print_string (" CINR", tmp); + g_free (tmp); + + tmp_int = nm_device_wimax_get_tx_power (wimax); + if (tmp_int) + tmp = g_strdup_printf ("%'.2f dBm", (float) tmp_int / 2.0); + else + tmp = g_strdup ("(unknown)"); + print_string (" TX Power", tmp); + g_free (tmp); + + tmp_str = nm_device_wimax_get_bsid (wimax); + if (tmp_str) + print_string (" BSID", tmp_str); + else + print_string (" BSID", "(unknown)"); + } + + printf ("\n WiMAX NSPs %s\n", active_nsp ? "(* current NSP)" : ""); + + nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device)); + if (nsps && nsps->len) + g_ptr_array_foreach ((GPtrArray *) nsps, detail_nsp, (gpointer) active_name); +#endif } /* IP Setup info */ |