2
* This file is part of the Main Menu.
4
* Copyright (c) 2006 Novell, Inc.
6
* The Main Menu is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License as published by the Free
8
* Software Foundation; either version 2 of the License, or (at your option)
11
* The Main Menu is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16
* You should have received a copy of the GNU General Public License along with
17
* the Main Menu; if not, write to the Free Software Foundation, Inc., 51
18
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include "network-status-agent.h"
24
#include <nm-client.h>
25
#include <NetworkManager.h>
26
#include <nm-device-wifi.h>
27
#include <nm-device-ethernet.h>
28
#include <nm-gsm-device.h>
29
#include <nm-cdma-device.h>
30
#include <nm-setting-ip4-config.h>
32
#include <arpa/inet.h>
33
#include <dbus/dbus.h>
34
#include <dbus/dbus-glib.h>
35
#include <dbus/dbus-glib-lowlevel.h>
37
#include <glibtop/netlist.h>
38
#include <glibtop/netload.h>
39
#include <libslab/slab.h>
45
} NetworkStatusAgentPrivate;
47
#define NETWORK_STATUS_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NETWORK_STATUS_AGENT_TYPE, NetworkStatusAgentPrivate))
49
static void network_status_agent_dispose (GObject *);
51
static void init_nm_connection (NetworkStatusAgent *);
53
static NetworkStatusInfo *nm_get_first_active_device_info (NetworkStatusAgent *);
54
static NetworkStatusInfo *nm_get_device_info (NetworkStatusAgent *, NMDevice *);
56
static void nm_state_change_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data);
58
static NetworkStatusInfo *gtop_get_first_active_device_info (void);
66
static guint network_status_agent_signals[LAST_SIGNAL] = { 0 };
68
G_DEFINE_TYPE (NetworkStatusAgent, network_status_agent, G_TYPE_OBJECT)
70
static void network_status_agent_class_init (NetworkStatusAgentClass * this_class)
72
GObjectClass *g_obj_class = (GObjectClass *) this_class;
74
g_obj_class->dispose = network_status_agent_dispose;
76
network_status_agent_signals[STATUS_CHANGED] = g_signal_new ("status-changed",
77
G_TYPE_FROM_CLASS (this_class),
78
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
79
G_STRUCT_OFFSET (NetworkStatusAgentClass, status_changed),
80
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
82
g_type_class_add_private (this_class, sizeof (NetworkStatusAgentPrivate));
86
network_status_agent_init (NetworkStatusAgent * agent)
88
NetworkStatusAgentPrivate *priv = NETWORK_STATUS_AGENT_GET_PRIVATE (agent);
90
agent->nm_present = FALSE;
92
priv->nm_client = NULL;
97
network_status_agent_new ()
99
return g_object_new (NETWORK_STATUS_AGENT_TYPE, NULL);
103
network_status_agent_get_first_active_device_info (NetworkStatusAgent * agent)
105
NetworkStatusAgentPrivate *priv = NETWORK_STATUS_AGENT_GET_PRIVATE (agent);
106
NetworkStatusInfo *info = NULL;
108
if (!priv->nm_client)
109
init_nm_connection (agent);
111
if (agent->nm_present)
112
info = nm_get_first_active_device_info (agent);
114
info = gtop_get_first_active_device_info ();
120
network_status_agent_dispose (GObject * obj)
122
NetworkStatusAgentPrivate *priv = NETWORK_STATUS_AGENT_GET_PRIVATE (obj);
123
if (priv->nm_client) {
124
g_object_unref (priv->nm_client);
125
priv->nm_client = NULL;
130
init_nm_connection (NetworkStatusAgent * agent)
132
NetworkStatusAgentPrivate *priv = NETWORK_STATUS_AGENT_GET_PRIVATE (agent);
134
priv->nm_client = nm_client_new();
136
if (!(priv->nm_client && nm_client_get_manager_running (priv->nm_client)))
138
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "nm_client_new failed");
140
agent->nm_present = FALSE;
145
agent->nm_present = TRUE;
148
static NetworkStatusInfo *
149
nm_get_first_active_device_info (NetworkStatusAgent * agent)
151
NetworkStatusAgentPrivate *priv = NETWORK_STATUS_AGENT_GET_PRIVATE (agent);
153
NetworkStatusInfo *info = NULL;
155
const GPtrArray *devices;
158
if (!priv->nm_client)
161
devices = nm_client_get_devices (priv->nm_client);
163
for (i = 0; devices && i < devices->len; i++)
167
nm_device = NM_DEVICE (g_ptr_array_index (devices, i));
168
info = nm_get_device_info (agent, nm_device);
172
g_signal_connect (nm_device, "notify::state", G_CALLBACK (nm_state_change_cb), agent);
176
g_object_unref (info);
186
ip4_address_as_string (guint32 ip)
188
struct in_addr tmp_addr;
191
tmp_addr.s_addr = ip;
192
ip_string = inet_ntoa (tmp_addr);
194
return g_strdup (ip_string);
197
static NetworkStatusInfo *
198
nm_get_device_info (NetworkStatusAgent * agent, NMDevice * device)
200
NetworkStatusInfo *info = g_object_new (NETWORK_STATUS_INFO_TYPE, NULL);
202
const GSList *addresses;
203
NMIP4Address *def_addr;
204
guint32 address, netmask, hostmask, network, bcast;
206
info->iface = g_strdup (nm_device_get_iface (device));
207
info->driver = g_strdup (nm_device_get_driver (device));
208
info->active = (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) ? TRUE : FALSE;
211
NMIP4Config * cfg = nm_device_get_ip4_config (device);
212
//According to the documentation this should not be NULL if the device is active but on resume from suspend it is (BNC#463712), so check for now
215
addresses = nm_ip4_config_get_addresses (cfg);
217
def_addr = addresses->data;
219
address = nm_ip4_address_get_address (def_addr);
220
netmask = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (def_addr));
221
network = ntohl (address) & ntohl (netmask);
222
hostmask = ~ntohl (netmask);
223
bcast = htonl (network | hostmask);
225
info->ip4_addr = ip4_address_as_string (address);
226
info->subnet_mask = ip4_address_as_string (netmask);
227
info->route = ip4_address_as_string (nm_ip4_address_get_gateway (def_addr));
228
info->broadcast = ip4_address_as_string (bcast);
231
info->primary_dns = NULL;
232
info->secondary_dns = NULL;
233
array = nm_ip4_config_get_nameservers (cfg);
237
info->primary_dns = ip4_address_as_string (g_array_index (array, guint32, 0));
239
info->secondary_dns = ip4_address_as_string (g_array_index (array, guint32, 1));
243
if (NM_IS_DEVICE_WIFI(device))
245
NMAccessPoint * activeap = NULL;
246
const GByteArray * ssid;
248
info->type = DEVICE_TYPE_802_11_WIRELESS;
249
info->speed_mbs = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI(device));
250
info->hw_addr = g_strdup (nm_device_wifi_get_hw_address (NM_DEVICE_WIFI(device)));
252
activeap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI(device));
255
ssid = nm_access_point_get_ssid (NM_ACCESS_POINT (activeap));
257
info->essid = g_strdup (nm_utils_escape_ssid (ssid->data, ssid->len));
261
info->essid = g_strdup ("(none)");
263
else if (NM_IS_DEVICE_ETHERNET (device))
265
info->type = DEVICE_TYPE_802_3_ETHERNET;
266
info->speed_mbs = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET(device));
267
info->hw_addr = g_strdup (nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET(device)));
269
else if (NM_IS_GSM_DEVICE (device))
271
info->type = DEVICE_TYPE_GSM;
273
info->hw_addr = NULL;
275
else if (NM_IS_CDMA_DEVICE (device))
277
info->type = DEVICE_TYPE_CDMA;
279
info->hw_addr = NULL;
286
nm_state_change_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
288
NetworkStatusAgent *this = NETWORK_STATUS_AGENT (user_data);
289
NetworkStatusAgentPrivate *priv = NETWORK_STATUS_AGENT_GET_PRIVATE (this);
292
state = nm_device_get_state (device);
294
if (priv->state_curr == state)
297
priv->state_curr = state;
299
g_signal_emit (this, network_status_agent_signals [STATUS_CHANGED], 0);
302
#define CHECK_FLAG(flags, offset) (((flags) & (1 << (offset))) ? TRUE : FALSE)
304
static NetworkStatusInfo *
305
gtop_get_first_active_device_info ()
307
NetworkStatusInfo *info = NULL;
309
glibtop_netlist net_list;
312
glibtop_netload net_load;
315
wireless_config wl_cfg;
320
networks = glibtop_get_netlist (&net_list);
322
for (i = 0; i < net_list.number; ++i)
324
glibtop_get_netload (&net_load, networks[i]);
326
if (CHECK_FLAG (net_load.if_flags, GLIBTOP_IF_FLAGS_RUNNING)
327
&& !CHECK_FLAG (net_load.if_flags, GLIBTOP_IF_FLAGS_LOOPBACK)
330
sock_fd = iw_sockets_open ();
334
g_warning ("error opening socket\n");
340
info = g_object_new (NETWORK_STATUS_INFO_TYPE, NULL);
342
ret = iw_get_basic_config (sock_fd, networks[i], &wl_cfg);
346
info->type = DEVICE_TYPE_802_11_WIRELESS;
347
info->essid = g_strdup (wl_cfg.essid);
348
info->iface = g_strdup (networks[i]);
354
info->type = DEVICE_TYPE_802_3_ETHERNET;
356
info->iface = g_strdup (networks[i]);
363
g_strfreev (networks);