diff options
author | Daniel Drake <dsd@laptop.org> | 2009-08-05 16:34:02 -0400 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2009-08-05 16:34:02 -0400 |
commit | ff88cf12c2de43081f1a7c93a2565658119b7894 (patch) | |
tree | d5f1b8788ab3667935d944d3c34ac4ab96544d93 | |
parent | 4bab33405be01fd263373e530d712f3eb8d01d0d (diff) |
olpc: add mesh device logic and config setting
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | callouts/77-nm-olpc-mesh.rules | 6 | ||||
-rw-r--r-- | callouts/Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | include/NetworkManager.h | 3 | ||||
-rw-r--r-- | introspection/Makefile.am | 1 | ||||
-rw-r--r-- | introspection/nm-device-olpc-mesh.xml | 32 | ||||
-rw-r--r-- | libnm-util/Makefile.am | 2 | ||||
-rw-r--r-- | libnm-util/libnm-util.ver | 4 | ||||
-rw-r--r-- | libnm-util/nm-connection.c | 6 | ||||
-rw-r--r-- | libnm-util/nm-setting-olpc-mesh.c | 265 | ||||
-rw-r--r-- | libnm-util/nm-setting-olpc-mesh.h | 52 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/nm-device-olpc-mesh.c | 979 | ||||
-rw-r--r-- | src/nm-device-olpc-mesh.h | 85 | ||||
-rw-r--r-- | src/nm-manager.c | 3 | ||||
-rw-r--r-- | src/nm-udev-manager.c | 12 |
17 files changed, 1467 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index a61200f2db..3e2fec99f4 100644 --- a/Makefile.am +++ b/Makefile.am | |||
@@ -27,7 +27,7 @@ EXTRA_DIST = \ | |||
27 | intltool-merge.in \ | 27 | intltool-merge.in \ |
28 | intltool-update.in | 28 | intltool-update.in |
29 | 29 | ||
30 | DISTCHECK_CONFIGURE_FLAGS = --with-tests=yes --with-docs=yes | 30 | DISTCHECK_CONFIGURE_FLAGS = --with-tests=yes --with-docs=yes --with-udev-dir=$$dc_install_base/lib/udev |
31 | 31 | ||
32 | DISTCLEANFILES = intltool-extract intltool-merge intltool-update | 32 | DISTCLEANFILES = intltool-extract intltool-merge intltool-update |
33 | 33 | ||
diff --git a/callouts/77-nm-olpc-mesh.rules b/callouts/77-nm-olpc-mesh.rules new file mode 100644 index 0000000000..a1a1554c2b --- /dev/null +++ b/callouts/77-nm-olpc-mesh.rules | |||
@@ -0,0 +1,6 @@ | |||
1 | # do not edit this file, it will be overwritten on update | ||
2 | |||
3 | # The fact that this device is driven by libertas is not currently exposed | ||
4 | # in the sysfs tree..? | ||
5 | KERNEL=="msh*", SUBSYSTEM=="net", DRIVERS=="usb", ATTRS{idVendor}=="1286", ATTRS{idProduct}=="2001", ENV{ID_NM_OLPC_MESH}="1" | ||
6 | |||
diff --git a/callouts/Makefile.am b/callouts/Makefile.am index d77fea5880..385537ef62 100644 --- a/callouts/Makefile.am +++ b/callouts/Makefile.am | |||
@@ -62,6 +62,9 @@ nm_dispatcher_action_LDADD = \ | |||
62 | nm-dispatcher-glue.h: nm-dispatcher.xml | 62 | nm-dispatcher-glue.h: nm-dispatcher.xml |
63 | dbus-binding-tool --prefix=nm_dispatcher --mode=glib-server --output=$@ $< | 63 | dbus-binding-tool --prefix=nm_dispatcher --mode=glib-server --output=$@ $< |
64 | 64 | ||
65 | udevrulesdir = $(UDEV_BASE_DIR)/rules.d | ||
66 | udevrules_DATA = 77-nm-olpc-mesh.rules | ||
67 | |||
65 | dbusactivationdir = $(datadir)/dbus-1/system-services | 68 | dbusactivationdir = $(datadir)/dbus-1/system-services |
66 | dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in | 69 | dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in |
67 | dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service) | 70 | dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service) |
@@ -85,6 +88,7 @@ CLEANFILES = $(BUILT_SOURCES) $(dbusactivation_DATA) | |||
85 | 88 | ||
86 | EXTRA_DIST = \ | 89 | EXTRA_DIST = \ |
87 | $(dbusservice_DATA) \ | 90 | $(dbusservice_DATA) \ |
91 | $(udevrules_DATA) \ | ||
88 | $(dbusactivation_in_files) \ | 92 | $(dbusactivation_in_files) \ |
89 | nm-dispatcher.xml | 93 | nm-dispatcher.xml |
90 | 94 | ||
diff --git a/configure.ac b/configure.ac index adaf2e040f..320f51a6a6 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -193,6 +193,14 @@ PKG_CHECK_MODULES(GUDEV, gudev-1.0) | |||
193 | AC_SUBST(GUDEV_CFLAGS) | 193 | AC_SUBST(GUDEV_CFLAGS) |
194 | AC_SUBST(GUDEV_LIBS) | 194 | AC_SUBST(GUDEV_LIBS) |
195 | 195 | ||
196 | AC_ARG_WITH(udev-dir, AS_HELP_STRING([--with-udev-dir=DIR], [where the udev base directory is])) | ||
197 | if test -n "$with_udev_dir" ; then | ||
198 | UDEV_BASE_DIR="$with_udev_dir" | ||
199 | else | ||
200 | UDEV_BASE_DIR="/lib/udev" | ||
201 | fi | ||
202 | AC_SUBST(UDEV_BASE_DIR) | ||
203 | |||
196 | PKG_CHECK_EXISTS(gio-2.0,[have_gio=yes],[have_gio=no]) | 204 | PKG_CHECK_EXISTS(gio-2.0,[have_gio=yes],[have_gio=no]) |
197 | if test x"$have_gio" = "xno"; then | 205 | if test x"$have_gio" = "xno"; then |
198 | AC_DEFINE([NO_GIO],[1],[Define if you don't have GIO]) | 206 | AC_DEFINE([NO_GIO],[1],[Define if you don't have GIO]) |
diff --git a/include/NetworkManager.h b/include/NetworkManager.h index fcef15bc7f..d48552bc07 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h | |||
@@ -77,7 +77,8 @@ typedef enum NMDeviceType | |||
77 | NM_DEVICE_TYPE_WIFI, | 77 | NM_DEVICE_TYPE_WIFI, |
78 | NM_DEVICE_TYPE_GSM, | 78 | NM_DEVICE_TYPE_GSM, |
79 | NM_DEVICE_TYPE_CDMA, | 79 | NM_DEVICE_TYPE_CDMA, |
80 | NM_DEVICE_TYPE_BT /* Bluetooth */ | 80 | NM_DEVICE_TYPE_BT, /* Bluetooth */ |
81 | NM_DEVICE_TYPE_OLPC_MESH | ||
81 | } NMDeviceType; | 82 | } NMDeviceType; |
82 | 83 | ||
83 | /* DEPRECATED TYPE NAMES */ | 84 | /* DEPRECATED TYPE NAMES */ |
diff --git a/introspection/Makefile.am b/introspection/Makefile.am index eee9eb1891..0dc286a9cd 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am | |||
@@ -6,6 +6,7 @@ EXTRA_DIST = \ | |||
6 | nm-access-point.xml \ | 6 | nm-access-point.xml \ |
7 | nm-device-bt.xml \ | 7 | nm-device-bt.xml \ |
8 | nm-device-wifi.xml \ | 8 | nm-device-wifi.xml \ |
9 | nm-device-olpc-mesh.xml \ | ||
9 | nm-device-ethernet.xml \ | 10 | nm-device-ethernet.xml \ |
10 | nm-device-cdma.xml \ | 11 | nm-device-cdma.xml \ |
11 | nm-device-gsm.xml \ | 12 | nm-device-gsm.xml \ |
diff --git a/introspection/nm-device-olpc-mesh.xml b/introspection/nm-device-olpc-mesh.xml new file mode 100644 index 0000000000..7d326b6b95 --- /dev/null +++ b/introspection/nm-device-olpc-mesh.xml | |||
@@ -0,0 +1,32 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> | ||
4 | <interface name="org.freedesktop.NetworkManager.Device.OlpcMesh"> | ||
5 | <property name="HwAddress" type="s" access="read"> | ||
6 | <tp:docstring> | ||
7 | The hardware address of the device. | ||
8 | </tp:docstring> | ||
9 | </property> | ||
10 | <property name="Companion" type="s" access="read"> | ||
11 | <tp:docstring> | ||
12 | The object path of the companion device. | ||
13 | </tp:docstring> | ||
14 | </property> | ||
15 | <property name="ActiveChannel" type="o" access="read"> | ||
16 | <tp:docstring> | ||
17 | The currently active channel. | ||
18 | </tp:docstring> | ||
19 | </property> | ||
20 | |||
21 | <signal name="PropertiesChanged"> | ||
22 | <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> | ||
23 | <tp:docstring> | ||
24 | A dictionary containing the FIXME: check changed parameters. | ||
25 | </tp:docstring> | ||
26 | </arg> | ||
27 | <tp:docstring> | ||
28 | Emitted when the wireless device's properties changed. | ||
29 | </tp:docstring> | ||
30 | </signal> | ||
31 | </interface> | ||
32 | </node> | ||
diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am index 1a5a94eb3f..cbf6de36cb 100644 --- a/libnm-util/Makefile.am +++ b/libnm-util/Makefile.am | |||
@@ -23,6 +23,7 @@ libnm_util_include_HEADERS = \ | |||
23 | nm-setting-serial.h \ | 23 | nm-setting-serial.h \ |
24 | nm-setting-gsm.h \ | 24 | nm-setting-gsm.h \ |
25 | nm-setting-cdma.h \ | 25 | nm-setting-cdma.h \ |
26 | nm-setting-olpc-mesh.h \ | ||
26 | nm-setting-wired.h \ | 27 | nm-setting-wired.h \ |
27 | nm-setting-wireless.h \ | 28 | nm-setting-wireless.h \ |
28 | nm-setting-wireless-security.h \ | 29 | nm-setting-wireless-security.h \ |
@@ -46,6 +47,7 @@ libnm_util_la_SOURCES= \ | |||
46 | nm-setting-serial.c \ | 47 | nm-setting-serial.c \ |
47 | nm-setting-gsm.c \ | 48 | nm-setting-gsm.c \ |
48 | nm-setting-cdma.c \ | 49 | nm-setting-cdma.c \ |
50 | nm-setting-olpc-mesh.c \ | ||
49 | nm-setting-wired.c \ | 51 | nm-setting-wired.c \ |
50 | nm-setting-wireless.c \ | 52 | nm-setting-wireless.c \ |
51 | nm-setting-wireless-security.c \ | 53 | nm-setting-wireless-security.c \ |
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index 92228f5257..5a89a71581 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver | |||
@@ -303,6 +303,10 @@ global: | |||
303 | nm_setting_wireless_security_remove_pairwise; | 303 | nm_setting_wireless_security_remove_pairwise; |
304 | nm_setting_wireless_security_remove_proto; | 304 | nm_setting_wireless_security_remove_proto; |
305 | nm_setting_wireless_security_set_wep_key; | 305 | nm_setting_wireless_security_set_wep_key; |
306 | nm_setting_olpc_mesh_get_type; | ||
307 | nm_setting_olpc_mesh_get_ssid; | ||
308 | nm_setting_olpc_mesh_get_channel; | ||
309 | nm_setting_olpc_mesh_get_dhcp_anycast_address; | ||
306 | nm_utils_deinit; | 310 | nm_utils_deinit; |
307 | nm_utils_escape_ssid; | 311 | nm_utils_escape_ssid; |
308 | nm_utils_gvalue_hash_dup; | 312 | nm_utils_gvalue_hash_dup; |
diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index 810032ae54..1d186a6e91 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "nm-setting-wireless.h" | 41 | #include "nm-setting-wireless.h" |
42 | #include "nm-setting-wireless-security.h" | 42 | #include "nm-setting-wireless-security.h" |
43 | #include "nm-setting-vpn.h" | 43 | #include "nm-setting-vpn.h" |
44 | #include "nm-setting-olpc-mesh.h" | ||
44 | 45 | ||
45 | #include "nm-setting-serial.h" | 46 | #include "nm-setting-serial.h" |
46 | #include "nm-setting-gsm.h" | 47 | #include "nm-setting-gsm.h" |
@@ -216,6 +217,11 @@ register_default_settings (void) | |||
216 | NM_SETTING_WIRELESS_ERROR, | 217 | NM_SETTING_WIRELESS_ERROR, |
217 | 1); | 218 | 1); |
218 | 219 | ||
220 | register_one_setting (NM_SETTING_OLPC_MESH_SETTING_NAME, | ||
221 | NM_TYPE_SETTING_OLPC_MESH, | ||
222 | NM_SETTING_OLPC_MESH_ERROR, | ||
223 | 1); | ||
224 | |||
219 | register_one_setting (NM_SETTING_GSM_SETTING_NAME, | 225 | register_one_setting (NM_SETTING_GSM_SETTING_NAME, |
220 | NM_TYPE_SETTING_GSM, | 226 | NM_TYPE_SETTING_GSM, |
221 | NM_SETTING_GSM_ERROR, | 227 | NM_SETTING_GSM_ERROR, |
diff --git a/libnm-util/nm-setting-olpc-mesh.c b/libnm-util/nm-setting-olpc-mesh.c new file mode 100644 index 0000000000..dd0e1d64ce --- /dev/null +++ b/libnm-util/nm-setting-olpc-mesh.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ | ||
2 | |||
3 | /* | ||
4 | * Dan Williams <dcbw@redhat.com> | ||
5 | * Tambet Ingo <tambet@gmail.com> | ||
6 | * Sjoerd Simons <sjoerd.simons@collabora.co.uk> | ||
7 | * Daniel Drake <dsd@laptop.org> | ||
8 | * | ||
9 | * This library is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public | ||
11 | * License as published by the Free Software Foundation; either | ||
12 | * version 2 of the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This library is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this library; if not, write to the | ||
21 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
22 | * Boston, MA 02110-1301 USA. | ||
23 | * | ||
24 | * (C) Copyright 2007 - 2008 Red Hat, Inc. | ||
25 | * (C) Copyright 2007 - 2008 Novell, Inc. | ||
26 | * (C) Copyright 2009 One Laptop per Child | ||
27 | */ | ||
28 | |||
29 | #include <string.h> | ||
30 | #include <netinet/ether.h> | ||
31 | #include <dbus/dbus-glib.h> | ||
32 | |||
33 | #include "NetworkManager.h" | ||
34 | #include "nm-setting-olpc-mesh.h" | ||
35 | #include "nm-param-spec-specialized.h" | ||
36 | #include "nm-utils.h" | ||
37 | #include "nm-dbus-glib-types.h" | ||
38 | #include "nm-utils-private.h" | ||
39 | |||
40 | GQuark | ||
41 | nm_setting_olpc_mesh_error_quark (void) | ||
42 | { | ||
43 | static GQuark quark; | ||
44 | |||
45 | if (G_UNLIKELY (!quark)) | ||
46 | quark = g_quark_from_static_string ("nm-setting-wireless-mesh-error-quark"); | ||
47 | return quark; | ||
48 | } | ||
49 | |||
50 | /* This should really be standard. */ | ||
51 | #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } | ||
52 | |||
53 | GType | ||
54 | nm_setting_olpc_mesh_error_get_type (void) | ||
55 | { | ||
56 | static GType etype = 0; | ||
57 | |||
58 | if (etype == 0) { | ||
59 | static const GEnumValue values[] = { | ||
60 | /* Unknown error. */ | ||
61 | ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_UNKNOWN, "UnknownError"), | ||
62 | /* The specified property was invalid. */ | ||
63 | ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, "InvalidProperty"), | ||
64 | /* The specified property was missing and is required. */ | ||
65 | ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY, "MissingProperty"), | ||
66 | { 0, 0, 0 } | ||
67 | }; | ||
68 | etype = g_enum_register_static ("NMSettingWirelessError", values); | ||
69 | } | ||
70 | return etype; | ||
71 | } | ||
72 | |||
73 | static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting); | ||
74 | |||
75 | G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) | ||
76 | |||
77 | #define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) | ||
78 | |||
79 | typedef struct { | ||
80 | GByteArray *ssid; | ||
81 | guint32 channel; | ||
82 | GByteArray *dhcp_anycast_addr; | ||
83 | } NMSettingOlpcMeshPrivate; | ||
84 | |||
85 | enum { | ||
86 | PROP_0, | ||
87 | PROP_SSID, | ||
88 | PROP_CHANNEL, | ||
89 | PROP_DHCP_ANYCAST_ADDRESS, | ||
90 | |||
91 | LAST_PROP | ||
92 | }; | ||
93 | |||
94 | static void | ||
95 | nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting) | ||
96 | { | ||
97 | g_object_set (setting, NM_SETTING_NAME, NM_SETTING_OLPC_MESH_SETTING_NAME, NULL); | ||
98 | } | ||
99 | |||
100 | const GByteArray * | ||
101 | nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting) | ||
102 | { | ||
103 | g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL); | ||
104 | |||
105 | return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->ssid; | ||
106 | } | ||
107 | |||
108 | guint32 | ||
109 | nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting) | ||
110 | { | ||
111 | g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), 0); | ||
112 | |||
113 | return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->channel; | ||
114 | } | ||
115 | |||
116 | const GByteArray * | ||
117 | nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting) | ||
118 | { | ||
119 | g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL); | ||
120 | |||
121 | return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->dhcp_anycast_addr; | ||
122 | } | ||
123 | |||
124 | static gboolean | ||
125 | verify (NMSetting *setting, GSList *all_settings, GError **error) | ||
126 | { | ||
127 | NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (setting); | ||
128 | |||
129 | if (!priv->ssid) { | ||
130 | g_set_error (error, | ||
131 | NM_SETTING_OLPC_MESH_ERROR, | ||
132 | NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY, | ||
133 | NM_SETTING_OLPC_MESH_SSID); | ||
134 | return FALSE; | ||
135 | } | ||
136 | |||
137 | if (!priv->ssid->len || priv->ssid->len > 32) { | ||
138 | g_set_error (error, | ||
139 | NM_SETTING_OLPC_MESH_ERROR, | ||
140 | NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, | ||
141 | NM_SETTING_OLPC_MESH_SSID); | ||
142 | return FALSE; | ||
143 | } | ||
144 | |||
145 | if (priv->channel == 0 || priv->channel > 13) { | ||
146 | g_set_error (error, | ||
147 | NM_SETTING_OLPC_MESH_ERROR, | ||
148 | NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, | ||
149 | NM_SETTING_OLPC_MESH_CHANNEL); | ||
150 | return FALSE; | ||
151 | } | ||
152 | |||
153 | if (priv->dhcp_anycast_addr && priv->dhcp_anycast_addr->len != ETH_ALEN) { | ||
154 | g_set_error (error, | ||
155 | NM_SETTING_OLPC_MESH_ERROR, | ||
156 | NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, | ||
157 | NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS); | ||
158 | return FALSE; | ||
159 | } | ||
160 | |||
161 | return TRUE; | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | finalize (GObject *object) | ||
166 | { | ||
167 | NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object); | ||
168 | |||
169 | if (priv->ssid) | ||
170 | g_byte_array_free (priv->ssid, TRUE); | ||
171 | if (priv->dhcp_anycast_addr) | ||
172 | g_byte_array_free (priv->dhcp_anycast_addr, TRUE); | ||
173 | |||
174 | G_OBJECT_CLASS (nm_setting_olpc_mesh_parent_class)->finalize (object); | ||
175 | } | ||
176 | |||
177 | static void | ||
178 | set_property (GObject *object, guint prop_id, | ||
179 | const GValue *value, GParamSpec *pspec) | ||
180 | { | ||
181 | NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object); | ||
182 | |||
183 | switch (prop_id) { | ||
184 | case PROP_SSID: | ||
185 | if (priv->ssid) | ||
186 | g_byte_array_free (priv->ssid, TRUE); | ||
187 | priv->ssid = g_value_dup_boxed (value); | ||
188 | break; | ||
189 | case PROP_CHANNEL: | ||
190 | priv->channel = g_value_get_uint (value); | ||
191 | break; | ||
192 | case PROP_DHCP_ANYCAST_ADDRESS: | ||
193 | if (priv->dhcp_anycast_addr) | ||
194 | g_byte_array_free (priv->dhcp_anycast_addr, TRUE); | ||
195 | priv->dhcp_anycast_addr = g_value_dup_boxed (value); | ||
196 | break; | ||
197 | default: | ||
198 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
199 | break; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void | ||
204 | get_property (GObject *object, guint prop_id, | ||
205 | GValue *value, GParamSpec *pspec) | ||
206 | { | ||
207 | NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH (object); | ||
208 | |||
209 | switch (prop_id) { | ||
210 | case PROP_SSID: | ||
211 | g_value_set_boxed (value, nm_setting_olpc_mesh_get_ssid (setting)); | ||
212 | break; | ||
213 | case PROP_CHANNEL: | ||
214 | g_value_set_uint (value, nm_setting_olpc_mesh_get_channel (setting)); | ||
215 | break; | ||
216 | case PROP_DHCP_ANYCAST_ADDRESS: | ||
217 | g_value_set_boxed (value, nm_setting_olpc_mesh_get_dhcp_anycast_address (setting)); | ||
218 | break; | ||
219 | default: | ||
220 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static void | ||
226 | nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class) | ||
227 | { | ||
228 | GObjectClass *object_class = G_OBJECT_CLASS (setting_class); | ||
229 | NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); | ||
230 | |||
231 | g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate)); | ||
232 | |||
233 | /* virtual methods */ | ||
234 | object_class->set_property = set_property; | ||
235 | object_class->get_property = get_property; | ||
236 | object_class->finalize = finalize; | ||
237 | parent_class->verify = verify; | ||
238 | |||
239 | /* Properties */ | ||
240 | g_object_class_install_property | ||
241 | (object_class, PROP_SSID, | ||
242 | _nm_param_spec_specialized (NM_SETTING_OLPC_MESH_SSID, | ||
243 | "SSID", | ||
244 | "SSID", | ||
245 | DBUS_TYPE_G_UCHAR_ARRAY, | ||
246 | G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); | ||
247 | |||
248 | g_object_class_install_property | ||
249 | (object_class, PROP_CHANNEL, | ||
250 | g_param_spec_uint (NM_SETTING_OLPC_MESH_CHANNEL, | ||
251 | "Channel", | ||
252 | "Channel", | ||
253 | 0, G_MAXUINT32, 0, | ||
254 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); | ||
255 | |||
256 | |||
257 | g_object_class_install_property | ||
258 | (object_class, PROP_DHCP_ANYCAST_ADDRESS, | ||
259 | _nm_param_spec_specialized (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, | ||
260 | "Anycast DHCP MAC address", | ||
261 | "Anycast DHCP MAC address", | ||
262 | DBUS_TYPE_G_UCHAR_ARRAY, | ||
263 | G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); | ||
264 | |||
265 | } | ||
diff --git a/libnm-util/nm-setting-olpc-mesh.h b/libnm-util/nm-setting-olpc-mesh.h new file mode 100644 index 0000000000..173853d3f7 --- /dev/null +++ b/libnm-util/nm-setting-olpc-mesh.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ | ||
2 | |||
3 | #ifndef NM_SETTING_OLPC_MESH_H | ||
4 | #define NM_SETTING_OLPC_MESH_H | ||
5 | |||
6 | #include <nm-setting.h> | ||
7 | |||
8 | G_BEGIN_DECLS | ||
9 | |||
10 | #define NM_TYPE_SETTING_OLPC_MESH (nm_setting_olpc_mesh_get_type ()) | ||
11 | #define NM_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMesh)) | ||
12 | #define NM_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) | ||
13 | #define NM_IS_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH)) | ||
14 | #define NM_IS_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH)) | ||
15 | #define NM_SETTING_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) | ||
16 | |||
17 | #define NM_SETTING_OLPC_MESH_SETTING_NAME "802-11-olpc-mesh" | ||
18 | |||
19 | typedef enum | ||
20 | { | ||
21 | NM_SETTING_OLPC_MESH_ERROR_UNKNOWN = 0, | ||
22 | NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, | ||
23 | NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY | ||
24 | } NMSettingOlpcMeshError; | ||
25 | |||
26 | #define NM_TYPE_SETTING_OLPC_MESH_ERROR (nm_setting_olpc_mesh_error_get_type ()) | ||
27 | GType nm_setting_olpc_mesh_error_get_type (void); | ||
28 | |||
29 | #define NM_SETTING_OLPC_MESH_ERROR nm_setting_olpc_mesh_error_quark () | ||
30 | GQuark nm_setting_olpc_mesh_error_quark (void); | ||
31 | |||
32 | #define NM_SETTING_OLPC_MESH_SSID "ssid" | ||
33 | #define NM_SETTING_OLPC_MESH_CHANNEL "channel" | ||
34 | #define NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS "dhcp-anycast-address" | ||
35 | |||
36 | typedef struct { | ||
37 | NMSetting parent; | ||
38 | } NMSettingOlpcMesh; | ||
39 | |||
40 | typedef struct { | ||
41 | NMSettingClass parent; | ||
42 | } NMSettingOlpcMeshClass; | ||
43 | |||
44 | GType nm_setting_olpc_mesh_get_type (void); | ||
45 | |||
46 | const GByteArray *nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting); | ||
47 | guint32 nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting); | ||
48 | const GByteArray *nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting); | ||
49 | |||
50 | G_END_DECLS | ||
51 | |||
52 | #endif /* NM_SETTING_OLPC_MESH_H */ | ||
diff --git a/src/Makefile.am b/src/Makefile.am index d8878e05df..915e972daa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -68,6 +68,8 @@ NetworkManager_SOURCES = \ | |||
68 | nm-device-ethernet.h \ | 68 | nm-device-ethernet.h \ |
69 | nm-device-wifi.c \ | 69 | nm-device-wifi.c \ |
70 | nm-device-wifi.h \ | 70 | nm-device-wifi.h \ |
71 | nm-device-olpc-mesh.c \ | ||
72 | nm-device-olpc-mesh.h \ | ||
71 | nm-device-bt.c \ | 73 | nm-device-bt.c \ |
72 | nm-device-bt.h \ | 74 | nm-device-bt.h \ |
73 | NetworkManagerAP.c \ | 75 | NetworkManagerAP.c \ |
@@ -128,6 +130,9 @@ nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml | |||
128 | nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml | 130 | nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml |
129 | dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< | 131 | dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< |
130 | 132 | ||
133 | nm-device-olpc-mesh-glue.h: $(top_srcdir)/introspection/nm-device-olpc-mesh.xml | ||
134 | dbus-binding-tool --prefix=nm_device_olpc_mesh --mode=glib-server --output=$@ $< | ||
135 | |||
131 | nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml | 136 | nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml |
132 | dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $< | 137 | dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $< |
133 | 138 | ||
@@ -146,6 +151,7 @@ BUILT_SOURCES = \ | |||
146 | nm-device-interface-glue.h \ | 151 | nm-device-interface-glue.h \ |
147 | nm-device-ethernet-glue.h \ | 152 | nm-device-ethernet-glue.h \ |
148 | nm-device-wifi-glue.h \ | 153 | nm-device-wifi-glue.h \ |
154 | nm-device-olpc-mesh-glue.h \ | ||
149 | nm-device-bt-glue.h \ | 155 | nm-device-bt-glue.h \ |
150 | nm-ip4-config-glue.h \ | 156 | nm-ip4-config-glue.h \ |
151 | nm-ip6-config-glue.h \ | 157 | nm-ip6-config-glue.h \ |
diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c new file mode 100644 index 0000000000..743f47cdf7 --- /dev/null +++ b/src/nm-device-olpc-mesh.c | |||
@@ -0,0 +1,979 @@ | |||
1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ | ||
2 | /* NetworkManager -- Network link manager | ||
3 | * | ||
4 | * Dan Williams <dcbw@redhat.com> | ||
5 | * Sjoerd Simons <sjoerd.simons@collabora.co.uk> | ||
6 | * Daniel Drake <dsd@laptop.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | * (C) Copyright 2005 - 2008 Red Hat, Inc. | ||
23 | * (C) Copyright 2008 Collabora Ltd. | ||
24 | * (C) Copyright 2009 One Laptop per Child | ||
25 | */ | ||
26 | |||
27 | #include <glib.h> | ||
28 | #include <glib/gi18n.h> | ||
29 | #include <dbus/dbus.h> | ||
30 | #include <netinet/in.h> | ||
31 | #include <string.h> | ||
32 | #include <net/ethernet.h> | ||
33 | #include <iwlib.h> | ||
34 | #include <sys/stat.h> | ||
35 | #include <sys/wait.h> | ||
36 | #include <signal.h> | ||
37 | #include <unistd.h> | ||
38 | |||
39 | #include "nm-device.h" | ||
40 | #include "nm-device-wifi.h" | ||
41 | #include "nm-device-olpc-mesh.h" | ||
42 | #include "nm-device-interface.h" | ||
43 | #include "nm-device-private.h" | ||
44 | #include "nm-utils.h" | ||
45 | #include "NetworkManagerUtils.h" | ||
46 | #include "NetworkManagerPolicy.h" | ||
47 | #include "nm-activation-request.h" | ||
48 | #include "nm-properties-changed-signal.h" | ||
49 | #include "nm-setting-connection.h" | ||
50 | #include "nm-setting-olpc-mesh.h" | ||
51 | #include "NetworkManagerSystem.h" | ||
52 | #include "nm-manager.h" | ||
53 | |||
54 | #include "nm-device-olpc-mesh-glue.h" | ||
55 | |||
56 | static void nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid); | ||
57 | |||
58 | G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) | ||
59 | |||
60 | #define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate)) | ||
61 | |||
62 | |||
63 | enum { | ||
64 | PROP_0, | ||
65 | PROP_HW_ADDRESS, | ||
66 | PROP_COMPANION, | ||
67 | PROP_ACTIVE_CHANNEL, | ||
68 | PROP_IFINDEX, | ||
69 | |||
70 | LAST_PROP | ||
71 | }; | ||
72 | |||
73 | enum { | ||
74 | PROPERTIES_CHANGED, | ||
75 | |||
76 | LAST_SIGNAL | ||
77 | }; | ||
78 | |||
79 | static guint signals[LAST_SIGNAL] = { 0 }; | ||
80 | |||
81 | typedef enum | ||
82 | { | ||
83 | NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH = 0, | ||
84 | NM_OLPC_MESH_ERROR_CONNECTION_INVALID, | ||
85 | NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, | ||
86 | } NMOlpcMeshError; | ||
87 | |||
88 | #define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ()) | ||
89 | #define NM_TYPE_OLPC_MESH_ERROR (nm_olpc_mesh_error_get_type ()) | ||
90 | |||
91 | |||
92 | struct _NMDeviceOlpcMeshPrivate | ||
93 | { | ||
94 | gboolean dispose_has_run; | ||
95 | |||
96 | struct ether_addr hw_addr; | ||
97 | guint32 ifindex; | ||
98 | |||
99 | GByteArray * ssid; | ||
100 | |||
101 | gint8 num_freqs; | ||
102 | guint32 freqs[IW_MAX_FREQUENCIES]; | ||
103 | |||
104 | guint8 we_version; | ||
105 | gboolean up; | ||
106 | |||
107 | NMDevice * companion; | ||
108 | gboolean stage1_waiting; | ||
109 | guint device_added_cb; | ||
110 | }; | ||
111 | |||
112 | static GQuark | ||
113 | nm_olpc_mesh_error_quark (void) | ||
114 | { | ||
115 | static GQuark quark = 0; | ||
116 | if (!quark) | ||
117 | quark = g_quark_from_static_string ("nm-mesh-error"); | ||
118 | return quark; | ||
119 | } | ||
120 | |||
121 | /* This should really be standard. */ | ||
122 | #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } | ||
123 | |||
124 | static GType | ||
125 | nm_olpc_mesh_error_get_type (void) | ||
126 | { | ||
127 | static GType etype = 0; | ||
128 | |||
129 | if (etype == 0) { | ||
130 | static const GEnumValue values[] = { | ||
131 | /* Connection was not a wireless connection. */ | ||
132 | ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, "ConnectionNotMesh"), | ||
133 | /* Connection was not a valid wireless connection. */ | ||
134 | ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_INVALID, "ConnectionInvalid"), | ||
135 | /* Connection does not apply to this device. */ | ||
136 | ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"), | ||
137 | { 0, 0, 0 } | ||
138 | }; | ||
139 | etype = g_enum_register_static ("NMOlpcMeshError", values); | ||
140 | } | ||
141 | return etype; | ||
142 | } | ||
143 | |||
144 | static guint32 | ||
145 | real_get_generic_capabilities (NMDevice *dev) | ||
146 | { | ||
147 | int fd; | ||
148 | guint32 caps = NM_DEVICE_CAP_NONE; | ||
149 | struct iw_range range; | ||
150 | struct iwreq wrq; | ||
151 | const char *iface = nm_device_get_iface (dev); | ||
152 | |||
153 | /* Check for Wireless Extensions support >= 16 for wireless devices */ | ||
154 | |||
155 | fd = socket (PF_INET, SOCK_DGRAM, 0); | ||
156 | if (fd < 0) { | ||
157 | nm_warning ("couldn't open control socket."); | ||
158 | goto out; | ||
159 | } | ||
160 | |||
161 | memset (&wrq, 0, sizeof (struct iwreq)); | ||
162 | memset (&range, 0, sizeof (struct iw_range)); | ||
163 | strncpy (wrq.ifr_name, iface, IFNAMSIZ); | ||
164 | wrq.u.data.pointer = (caddr_t) ⦥ | ||
165 | wrq.u.data.length = sizeof (struct iw_range); | ||
166 | |||
167 | if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0) { | ||
168 | nm_warning ("couldn't get driver range information."); | ||
169 | goto out; | ||
170 | } | ||
171 | |||
172 | if ((wrq.u.data.length < 300) || (range.we_version_compiled < 16)) { | ||
173 | nm_warning ("%s: driver's Wireless Extensions version (%d) is too old.", | ||
174 | iface, range.we_version_compiled); | ||
175 | goto out; | ||
176 | } else { | ||
177 | caps |= NM_DEVICE_CAP_NM_SUPPORTED; | ||
178 | } | ||
179 | |||
180 | out: | ||
181 | if (fd >= 0) | ||
182 | close (fd); | ||
183 | return caps; | ||
184 | } | ||
185 | |||
186 | static void | ||
187 | nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) | ||
188 | { | ||
189 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
190 | |||
191 | priv->dispose_has_run = FALSE; | ||
192 | priv->we_version = 0; | ||
193 | priv->companion = NULL; | ||
194 | priv->stage1_waiting = FALSE; | ||
195 | |||
196 | memset (&(priv->hw_addr), 0, sizeof (struct ether_addr)); | ||
197 | } | ||
198 | |||
199 | static guint32 iw_freq_to_uint32 (struct iw_freq *freq) | ||
200 | { | ||
201 | if (freq->e == 0) { | ||
202 | /* Some drivers report channel not frequency. Convert to a | ||
203 | * frequency; but this assumes that the device is in b/g mode. | ||
204 | */ | ||
205 | if ((freq->m >= 1) && (freq->m <= 13)) | ||
206 | return 2407 + (5 * freq->m); | ||
207 | else if (freq->m == 14) | ||
208 | return 2484; | ||
209 | } | ||
210 | |||
211 | return (guint32) (((double) freq->m) * pow (10, freq->e) / 1000000); | ||
212 | } | ||
213 | |||
214 | |||
215 | /* Until a new wireless-tools comes out that has the defs and the structure, | ||
216 | * need to copy them here. | ||
217 | */ | ||
218 | /* Scan capability flags - in (struct iw_range *)->scan_capa */ | ||
219 | #define NM_IW_SCAN_CAPA_NONE 0x00 | ||
220 | #define NM_IW_SCAN_CAPA_ESSID 0x01 | ||
221 | |||
222 | struct iw_range_with_scan_capa | ||
223 | { | ||
224 | guint32 throughput; | ||
225 | guint32 min_nwid; | ||
226 | guint32 max_nwid; | ||
227 | guint16 old_num_channels; | ||
228 | guint8 old_num_frequency; | ||
229 | |||
230 | guint8 scan_capa; | ||
231 | /* don't need the rest... */ | ||
232 | }; | ||
233 | |||
234 | |||
235 | |||
236 | |||
237 | static GObject* | ||
238 | constructor (GType type, | ||
239 | guint n_construct_params, | ||
240 | GObjectConstructParam *construct_params) | ||
241 | { | ||
242 | GObject *object; | ||
243 | GObjectClass *klass; | ||
244 | NMDeviceOlpcMesh *self; | ||
245 | NMDeviceOlpcMeshPrivate *priv; | ||
246 | const char *iface; | ||
247 | int fd; | ||
248 | struct iw_range range; | ||
249 | struct iwreq wrq; | ||
250 | int i; | ||
251 | |||
252 | klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); | ||
253 | object = klass->constructor (type, n_construct_params, construct_params); | ||
254 | if (!object) | ||
255 | return NULL; | ||
256 | |||
257 | self = NM_DEVICE_OLPC_MESH (object); | ||
258 | priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
259 | |||
260 | iface = nm_device_get_iface (NM_DEVICE (self)); | ||
261 | fd = socket (PF_INET, SOCK_DGRAM, 0); | ||
262 | if (fd < 0) | ||
263 | goto error; | ||
264 | |||
265 | memset (&wrq, 0, sizeof (struct iwreq)); | ||
266 | memset (&range, 0, sizeof (struct iw_range)); | ||
267 | strncpy (wrq.ifr_name, iface, IFNAMSIZ); | ||
268 | wrq.u.data.pointer = (caddr_t) ⦥ | ||
269 | wrq.u.data.length = sizeof (struct iw_range); | ||
270 | |||
271 | if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0) | ||
272 | goto error; | ||
273 | |||
274 | priv->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES); | ||
275 | for (i = 0; i < priv->num_freqs; i++) | ||
276 | priv->freqs[i] = iw_freq_to_uint32 (&range.freq[i]); | ||
277 | |||
278 | priv->we_version = range.we_version_compiled; | ||
279 | |||
280 | close (fd); | ||
281 | |||
282 | /* shorter timeout for mesh connectivity */ | ||
283 | nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); | ||
284 | return object; | ||
285 | |||
286 | error: | ||
287 | if (fd >= 0) | ||
288 | close (fd); | ||
289 | g_object_unref (object); | ||
290 | return NULL; | ||
291 | } | ||
292 | |||
293 | static gboolean | ||
294 | real_hw_is_up (NMDevice *device) | ||
295 | { | ||
296 | return nm_system_device_is_up (device); | ||
297 | } | ||
298 | |||
299 | static gboolean | ||
300 | real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) | ||
301 | { | ||
302 | return nm_system_device_set_up_down (dev, TRUE, no_firmware); | ||
303 | } | ||
304 | |||
305 | static void | ||
306 | real_hw_take_down (NMDevice *dev) | ||
307 | { | ||
308 | nm_system_device_set_up_down (dev, FALSE, NULL); | ||
309 | } | ||
310 | |||
311 | static gboolean | ||
312 | real_is_up (NMDevice *device) | ||
313 | { | ||
314 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); | ||
315 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
316 | |||
317 | return priv->up; | ||
318 | } | ||
319 | |||
320 | static gboolean | ||
321 | real_bring_up (NMDevice *dev) | ||
322 | { | ||
323 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); | ||
324 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
325 | |||
326 | priv->up = TRUE; | ||
327 | return TRUE; | ||
328 | } | ||
329 | |||
330 | static void | ||
331 | device_cleanup (NMDeviceOlpcMesh *self) | ||
332 | { | ||
333 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
334 | |||
335 | if (priv->ssid) { | ||
336 | g_byte_array_free (priv->ssid, TRUE); | ||
337 | priv->ssid = NULL; | ||
338 | } | ||
339 | priv->up = FALSE; | ||
340 | } | ||
341 | |||
342 | static void | ||
343 | real_take_down (NMDevice *dev) | ||
344 | { | ||
345 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); | ||
346 | |||
347 | device_cleanup (self); | ||
348 | } | ||
349 | |||
350 | static gboolean | ||
351 | real_check_connection_compatible (NMDevice *device, | ||
352 | NMConnection *connection, | ||
353 | GError **error) | ||
354 | { | ||
355 | NMSettingConnection *s_con; | ||
356 | NMSettingOlpcMesh *s_mesh; | ||
357 | |||
358 | s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); | ||
359 | g_assert (s_con); | ||
360 | |||
361 | if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME)) { | ||
362 | g_set_error (error, | ||
363 | NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, | ||
364 | "The connection was not a Mesh connection."); | ||
365 | return FALSE; | ||
366 | } | ||
367 | |||
368 | s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH)); | ||
369 | if (!s_mesh) { | ||
370 | g_set_error (error, | ||
371 | NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_INVALID, | ||
372 | "The connection was not a valid Mesh connection."); | ||
373 | return FALSE; | ||
374 | } | ||
375 | |||
376 | return TRUE; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * nm_device_olpc_mesh_get_address | ||
381 | * | ||
382 | * Get a device's hardware address | ||
383 | * | ||
384 | */ | ||
385 | static void | ||
386 | nm_device_olpc_mesh_get_address (NMDeviceOlpcMesh *self, | ||
387 | struct ether_addr *addr) | ||
388 | { | ||
389 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
390 | g_return_if_fail (self != NULL); | ||
391 | g_return_if_fail (addr != NULL); | ||
392 | |||
393 | memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr)); | ||
394 | } | ||
395 | |||
396 | static int | ||
397 | create_socket_with_request (NMDevice *self, struct iwreq *req) | ||
398 | { | ||
399 | int sk; | ||
400 | const char * iface; | ||
401 | |||
402 | g_return_val_if_fail (self != NULL, -1); | ||
403 | |||
404 | sk = socket (AF_INET, SOCK_DGRAM, 0); | ||
405 | if (!sk) { | ||
406 | nm_error ("Couldn't create socket: %d.", errno); | ||
407 | return -1; | ||
408 | } | ||
409 | |||
410 | memset (req, 0, sizeof (struct iwreq)); | ||
411 | iface = nm_device_get_iface (NM_DEVICE (self)); | ||
412 | strncpy (req->ifr_name, iface, IFNAMSIZ); | ||
413 | |||
414 | return sk; | ||
415 | } | ||
416 | |||
417 | static guint32 | ||
418 | nm_device_olpc_mesh_get_channel (NMDeviceOlpcMesh *self) | ||
419 | { | ||
420 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
421 | int sk; | ||
422 | struct iwreq req; | ||
423 | int ret = 0; | ||
424 | int i; | ||
425 | guint32 freq; | ||
426 | |||
427 | sk = create_socket_with_request (NM_DEVICE (self), &req); | ||
428 | if (sk == -1) | ||
429 | return 0; | ||
430 | |||
431 | if ((ioctl (sk, SIOCGIWFREQ, &req)) != 0) { | ||
432 | nm_warning ("%s: failed to get channel (errno: %d))", | ||
433 | nm_device_get_iface (NM_DEVICE (self)), errno); | ||
434 | goto out; | ||
435 | } | ||
436 | |||
437 | freq = iw_freq_to_uint32 (&req.u.freq); | ||
438 | |||
439 | for (i = 0 ; i < priv->num_freqs; i++) { | ||
440 | if (freq == priv->freqs[i]) | ||
441 | break; | ||
442 | } | ||
443 | if (i < priv->num_freqs) | ||
444 | ret = i + 1; | ||
445 | |||
446 | out: | ||
447 | if (sk >= 0) | ||
448 | close (sk); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static void | ||
453 | nm_device_olpc_mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) | ||
454 | { | ||
455 | int sk; | ||
456 | struct iwreq req; | ||
457 | |||
458 | if (nm_device_olpc_mesh_get_channel (self) == channel) | ||
459 | return; | ||
460 | |||
461 | sk = create_socket_with_request (NM_DEVICE (self), &req); | ||
462 | if (sk < 0) | ||
463 | return; | ||
464 | |||
465 | if (channel > 0) { | ||
466 | req.u.freq.flags = IW_FREQ_FIXED; | ||
467 | req.u.freq.e = 0; | ||
468 | req.u.freq.m = channel; | ||
469 | } | ||
470 | |||
471 | if (ioctl (sk, SIOCSIWFREQ, &req) != 0) | ||
472 | nm_warning ("%s: failed to set to channel %d (errno: %d))", | ||
473 | nm_device_get_iface (NM_DEVICE (self)), channel, errno); | ||
474 | else | ||
475 | g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL); | ||
476 | |||
477 | close (sk); | ||
478 | } | ||
479 | |||
480 | static void | ||
481 | nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid) | ||
482 | { | ||
483 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
484 | int sk; | ||
485 | struct iwreq wrq; | ||
486 | const char * iface; | ||
487 | guint32 len = 0; | ||
488 | char buf[IW_ESSID_MAX_SIZE + 1]; | ||
489 | |||
490 | g_return_if_fail (self != NULL); | ||
491 | |||
492 | sk = socket (AF_INET, SOCK_DGRAM, 0); | ||
493 | if (!sk) { | ||
494 | nm_error ("Couldn't create socket: %d.", errno); | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | iface = nm_device_get_iface (NM_DEVICE (self)); | ||
499 | |||
500 | memset (buf, 0, sizeof (buf)); | ||
501 | if (ssid) { | ||
502 | len = ssid->len; | ||
503 | memcpy (buf, ssid->data, MIN (sizeof (buf) - 1, len)); | ||
504 | } | ||
505 | wrq.u.essid.pointer = (caddr_t) buf; | ||
506 | |||
507 | if (priv->we_version < 21) { | ||
508 | /* For historic reasons, set SSID length to include one extra | ||
509 | * character, C string nul termination, even though SSID is | ||
510 | * really an octet string that should not be presented as a C | ||
511 | * string. Some Linux drivers decrement the length by one and | ||
512 | * can thus end up missing the last octet of the SSID if the | ||
513 | * length is not incremented here. WE-21 changes this to | ||
514 | * explicitly require the length _not_ to include nul | ||
515 | * termination. */ | ||
516 | if (len) | ||
517 | len++; | ||
518 | } | ||
519 | wrq.u.essid.length = len; | ||
520 | wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ | ||
521 | |||
522 | strncpy (wrq.ifr_name, iface, IFNAMSIZ); | ||
523 | |||
524 | if (ioctl (sk, SIOCSIWESSID, &wrq) < 0) { | ||
525 | if (errno != ENODEV) { | ||
526 | nm_warning ("error setting SSID to '%s' for device %s: %s", | ||
527 | ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(null)", | ||
528 | iface, strerror (errno)); | ||
529 | } | ||
530 | } | ||
531 | |||
532 | close (sk); | ||
533 | } | ||
534 | |||
535 | |||
536 | guint32 | ||
537 | nm_device_olpc_mesh_get_ifindex (NMDeviceOlpcMesh *self) | ||
538 | { | ||
539 | g_return_val_if_fail (self != NULL, FALSE); | ||
540 | |||
541 | return NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->ifindex; | ||
542 | } | ||
543 | |||
544 | /****************************************************************************/ | ||
545 | |||
546 | static void | ||
547 | real_update_hw_address (NMDevice *dev) | ||
548 | { | ||
549 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); | ||
550 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
551 | struct ifreq req; | ||
552 | int ret, fd; | ||
553 | |||
554 | fd = socket (PF_INET, SOCK_DGRAM, 0); | ||
555 | if (fd < 0) { | ||
556 | g_warning ("could not open control socket."); | ||
557 | return; | ||
558 | } | ||
559 | |||
560 | memset (&req, 0, sizeof (struct ifreq)); | ||
561 | strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); | ||
562 | ret = ioctl (fd, SIOCGIFHWADDR, &req); | ||
563 | if (ret) { | ||
564 | nm_warning ("%s: (%s) error getting hardware address: %d", | ||
565 | __func__, nm_device_get_iface (dev), errno); | ||
566 | goto out; | ||
567 | } | ||
568 | |||
569 | if (memcmp (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr))) { | ||
570 | memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr)); | ||
571 | g_object_notify (G_OBJECT (dev), NM_DEVICE_OLPC_MESH_HW_ADDRESS); | ||
572 | } | ||
573 | |||
574 | out: | ||
575 | close (fd); | ||
576 | } | ||
577 | |||
578 | |||
579 | static NMActStageReturn | ||
580 | real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) | ||
581 | { | ||
582 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (dev); | ||
583 | gboolean scanning; | ||
584 | |||
585 | /* disconnect companion device, if it is connected */ | ||
586 | if (nm_device_get_act_request (NM_DEVICE (priv->companion))) { | ||
587 | nm_warning ("disconnecting companion device"); | ||
588 | nm_device_state_changed (NM_DEVICE (priv->companion), | ||
589 | NM_DEVICE_STATE_DISCONNECTED, | ||
590 | NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); | ||
591 | nm_warning ("companion disconnected"); | ||
592 | } | ||
593 | |||
594 | |||
595 | /* wait with continuing configuration untill the companion device is done | ||
596 | * scanning */ | ||
597 | g_object_get (priv->companion, "scanning", &scanning, NULL); | ||
598 | if (scanning) { | ||
599 | priv->stage1_waiting = TRUE; | ||
600 | return NM_ACT_STAGE_RETURN_POSTPONE; | ||
601 | } | ||
602 | |||
603 | return NM_ACT_STAGE_RETURN_SUCCESS; | ||
604 | } | ||
605 | |||
606 | static NMActStageReturn | ||
607 | real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) | ||
608 | { | ||
609 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); | ||
610 | NMConnection *connection; | ||
611 | NMSettingOlpcMesh *s_mesh; | ||
612 | NMActRequest *req; | ||
613 | guint32 channel; | ||
614 | const GByteArray *anycast_addr_array; | ||
615 | guint8 *anycast_addr = NULL; | ||
616 | |||
617 | req = nm_device_get_act_request (dev); | ||
618 | g_assert (req); | ||
619 | |||
620 | connection = nm_act_request_get_connection (req); | ||
621 | g_assert (connection); | ||
622 | |||
623 | s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH)); | ||
624 | g_assert (s_mesh); | ||
625 | |||
626 | channel = nm_setting_olpc_mesh_get_channel (s_mesh); | ||
627 | if (channel != 0) | ||
628 | nm_device_olpc_mesh_set_channel (self, channel); | ||
629 | nm_device_olpc_mesh_set_ssid (self, nm_setting_olpc_mesh_get_ssid (s_mesh)); | ||
630 | |||
631 | anycast_addr_array = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh); | ||
632 | if (anycast_addr_array) | ||
633 | anycast_addr = anycast_addr_array->data; | ||
634 | |||
635 | nm_device_set_dhcp_anycast_address (dev, anycast_addr); | ||
636 | return NM_ACT_STAGE_RETURN_SUCCESS; | ||
637 | } | ||
638 | |||
639 | static NMActStageReturn | ||
640 | real_act_stage4_ip4_config_timeout (NMDevice *dev, | ||
641 | NMIP4Config **config, | ||
642 | NMDeviceStateReason *reason) | ||
643 | { | ||
644 | return NM_ACT_STAGE_RETURN_FAILURE; | ||
645 | } | ||
646 | |||
647 | |||
648 | static void | ||
649 | nm_device_olpc_mesh_dispose (GObject *object) | ||
650 | { | ||
651 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); | ||
652 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
653 | |||
654 | if (priv->dispose_has_run) { | ||
655 | G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); | ||
656 | return; | ||
657 | } | ||
658 | |||
659 | priv->dispose_has_run = TRUE; | ||
660 | |||
661 | device_cleanup (self); | ||
662 | |||
663 | if (priv->device_added_cb != 0) | ||
664 | g_source_remove (priv->device_added_cb); | ||
665 | |||
666 | priv->device_added_cb = 0; | ||
667 | |||
668 | G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); | ||
669 | } | ||
670 | |||
671 | static void | ||
672 | get_property (GObject *object, guint prop_id, | ||
673 | GValue *value, GParamSpec *pspec) | ||
674 | { | ||
675 | NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); | ||
676 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); | ||
677 | struct ether_addr hw_addr; | ||
678 | |||
679 | switch (prop_id) { | ||
680 | case PROP_HW_ADDRESS: | ||
681 | nm_device_olpc_mesh_get_address (device, &hw_addr); | ||
682 | g_value_take_string (value, nm_ether_ntop (&hw_addr)); | ||
683 | break; | ||
684 | case PROP_COMPANION: | ||
685 | g_value_set_string (value, nm_device_get_path (priv->companion)); | ||
686 | break; | ||
687 | case PROP_ACTIVE_CHANNEL: | ||
688 | g_value_set_uint (value, nm_device_olpc_mesh_get_channel (device)); | ||
689 | break; | ||
690 | case PROP_IFINDEX: | ||
691 | g_value_set_uint (value, nm_device_olpc_mesh_get_ifindex (device)); | ||
692 | break; | ||
693 | default: | ||
694 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
695 | break; | ||
696 | } | ||
697 | } | ||
698 | |||
699 | static void | ||
700 | set_property (GObject *object, guint prop_id, | ||
701 | const GValue *value, GParamSpec *pspec) | ||
702 | { | ||
703 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); | ||
704 | |||
705 | switch (prop_id) { | ||
706 | case PROP_IFINDEX: | ||
707 | /* construct-only */ | ||
708 | priv->ifindex = g_value_get_uint (value); | ||
709 | break; | ||
710 | default: | ||
711 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
712 | break; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | static void | ||
717 | nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) | ||
718 | { | ||
719 | GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||
720 | NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); | ||
721 | |||
722 | g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate)); | ||
723 | |||
724 | object_class->constructor = constructor; | ||
725 | object_class->get_property = get_property; | ||
726 | object_class->set_property = set_property; | ||
727 | object_class->dispose = nm_device_olpc_mesh_dispose; | ||
728 | |||
729 | parent_class->get_type_capabilities = NULL; | ||
730 | parent_class->get_generic_capabilities = real_get_generic_capabilities; | ||
731 | parent_class->hw_is_up = real_hw_is_up; | ||
732 | parent_class->hw_bring_up = real_hw_bring_up; | ||
733 | parent_class->hw_take_down = real_hw_take_down; | ||
734 | parent_class->is_up = real_is_up; | ||
735 | parent_class->bring_up = real_bring_up; | ||
736 | parent_class->take_down = real_take_down; | ||
737 | parent_class->update_hw_address = real_update_hw_address; | ||
738 | parent_class->check_connection_compatible = real_check_connection_compatible; | ||
739 | |||
740 | parent_class->act_stage1_prepare = real_act_stage1_prepare; | ||
741 | parent_class->act_stage2_config = real_act_stage2_config; | ||
742 | parent_class->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout; | ||
743 | |||
744 | /* Properties */ | ||
745 | g_object_class_install_property | ||
746 | (object_class, PROP_HW_ADDRESS, | ||
747 | g_param_spec_string (NM_DEVICE_OLPC_MESH_HW_ADDRESS, | ||
748 | "MAC Address", | ||
749 | "Hardware MAC address", | ||
750 | NULL, | ||
751 | G_PARAM_READABLE)); | ||
752 | g_object_class_install_property | ||
753 | (object_class, PROP_COMPANION, | ||
754 | g_param_spec_string (NM_DEVICE_OLPC_MESH_COMPANION, | ||
755 | "Companion device", | ||
756 | "Companion device object path", | ||
757 | NULL, | ||
758 | G_PARAM_READABLE)); | ||
759 | g_object_class_install_property | ||
760 | (object_class, PROP_ACTIVE_CHANNEL, | ||
761 | g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, | ||
762 | "Active channel", | ||
763 | "Active channel", | ||
764 | 0, G_MAXUINT32, 0, | ||
765 | G_PARAM_READABLE)); | ||
766 | |||
767 | g_object_class_install_property (object_class, PROP_IFINDEX, | ||
768 | g_param_spec_uint (NM_DEVICE_OLPC_MESH_IFINDEX, | ||
769 | "Ifindex", | ||
770 | "Interface index", | ||
771 | 0, G_MAXUINT32, 0, | ||
772 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); | ||
773 | |||
774 | signals[PROPERTIES_CHANGED] = | ||
775 | nm_properties_changed_signal_new (object_class, | ||
776 | G_STRUCT_OFFSET (NMDeviceOlpcMeshClass, properties_changed)); | ||
777 | |||
778 | dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_olpc_mesh_object_info); | ||
779 | |||
780 | dbus_g_error_domain_register (NM_OLPC_MESH_ERROR, NULL, | ||
781 | NM_TYPE_OLPC_MESH_ERROR); | ||
782 | } | ||
783 | |||
784 | static void | ||
785 | companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data) | ||
786 | { | ||
787 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); | ||
788 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
789 | gboolean scanning; | ||
790 | |||
791 | if (!priv->stage1_waiting) | ||
792 | return; | ||
793 | |||
794 | g_object_get (companion, "scanning", &scanning, NULL); | ||
795 | |||
796 | if (!scanning) { | ||
797 | priv->stage1_waiting = FALSE; | ||
798 | nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); | ||
799 | } | ||
800 | } | ||
801 | |||
802 | /* disconnect from mesh if someone starts using the companion */ | ||
803 | static void | ||
804 | companion_state_changed_cb (NMDeviceWifi *companion, NMDeviceState state, NMDeviceState old_state, NMDeviceStateReason reason, gpointer user_data) | ||
805 | { | ||
806 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); | ||
807 | NMDeviceState self_state = nm_device_get_state (NM_DEVICE (self)); | ||
808 | |||
809 | if ( self_state < NM_DEVICE_STATE_PREPARE | ||
810 | || self_state > NM_DEVICE_STATE_ACTIVATED | ||
811 | || state < NM_DEVICE_STATE_PREPARE | ||
812 | || state > NM_DEVICE_STATE_ACTIVATED) | ||
813 | return; | ||
814 | |||
815 | nm_debug ("disconnecting mesh due to companion connectivity"); | ||
816 | nm_device_state_changed (NM_DEVICE (self), | ||
817 | NM_DEVICE_STATE_DISCONNECTED, | ||
818 | NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); | ||
819 | } | ||
820 | |||
821 | static gboolean | ||
822 | companion_scan_allowed_cb (NMDeviceWifi *companion, gpointer user_data) | ||
823 | { | ||
824 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); | ||
825 | NMDeviceState state; | ||
826 | |||
827 | g_object_get (G_OBJECT (self), NM_DEVICE_INTERFACE_STATE, &state, NULL); | ||
828 | |||
829 | /* Don't allow the companion to scan while configure the mesh interface */ | ||
830 | return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_IP_CONFIG); | ||
831 | } | ||
832 | |||
833 | static gboolean | ||
834 | companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data) | ||
835 | { | ||
836 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); | ||
837 | NMDeviceState state; | ||
838 | |||
839 | g_object_get (G_OBJECT (self), NM_DEVICE_INTERFACE_STATE, &state, NULL); | ||
840 | |||
841 | /* Don't allow the companion to autoconnect while a mesh connection is | ||
842 | * active */ | ||
843 | return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_ACTIVATED); | ||
844 | } | ||
845 | |||
846 | static gboolean | ||
847 | is_companion (NMDeviceOlpcMesh *self, NMDevice *other) | ||
848 | { | ||
849 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
850 | struct ether_addr their_addr; | ||
851 | |||
852 | if (!NM_IS_DEVICE_WIFI (other)) | ||
853 | return FALSE; | ||
854 | |||
855 | nm_device_wifi_get_address (NM_DEVICE_WIFI (other), &their_addr); | ||
856 | |||
857 | if (memcmp (priv->hw_addr.ether_addr_octet, | ||
858 | their_addr.ether_addr_octet, ETH_ALEN) != 0) { | ||
859 | return FALSE; | ||
860 | } | ||
861 | |||
862 | /* FIXME detect when our companion leaves */ | ||
863 | priv->companion = other; | ||
864 | |||
865 | g_source_remove (priv->device_added_cb); | ||
866 | priv->device_added_cb = 0; | ||
867 | |||
868 | nm_device_state_changed (NM_DEVICE (self), | ||
869 | NM_DEVICE_STATE_DISCONNECTED, | ||
870 | NM_DEVICE_STATE_REASON_NONE); | ||
871 | |||
872 | nm_debug ("Found companion device: %s", nm_device_get_iface (other)); | ||
873 | |||
874 | g_signal_connect (G_OBJECT (other), "state-changed", | ||
875 | G_CALLBACK (companion_state_changed_cb), self); | ||
876 | g_signal_connect (G_OBJECT (other), "notify::scanning", | ||
877 | G_CALLBACK (companion_notify_cb), self); | ||
878 | g_signal_connect (G_OBJECT (other), "scanning-allowed", | ||
879 | G_CALLBACK (companion_scan_allowed_cb), self); | ||
880 | g_signal_connect (G_OBJECT (other), "autoconnect-allowed", | ||
881 | G_CALLBACK (companion_autoconnect_allowed_cb), self); | ||
882 | |||
883 | return TRUE; | ||
884 | } | ||
885 | |||
886 | static void | ||
887 | device_added_cb (NMDevice *other, gpointer user_data) | ||
888 | { | ||
889 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); | ||
890 | |||
891 | is_companion (self, other); | ||
892 | } | ||
893 | |||
894 | static gboolean | ||
895 | check_companion_cb (gpointer user_data) | ||
896 | { | ||
897 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); | ||
898 | NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); | ||
899 | NMManager *manager; | ||
900 | GSList *list; | ||
901 | |||
902 | if (priv->companion != NULL) { | ||
903 | nm_device_state_changed (NM_DEVICE (user_data), | ||
904 | NM_DEVICE_STATE_DISCONNECTED, | ||
905 | NM_DEVICE_STATE_REASON_NONE); | ||
906 | return FALSE; | ||
907 | } | ||
908 | |||
909 | if (priv->device_added_cb != 0) | ||
910 | return FALSE; | ||
911 | |||
912 | manager = nm_manager_get (NULL, NULL, NULL); | ||
913 | |||
914 | priv->device_added_cb = g_signal_connect (manager, "device-added", | ||
915 | G_CALLBACK (device_added_cb), self); | ||
916 | |||
917 | list = nm_manager_get_devices (manager); | ||
918 | for (; list != NULL ; list = list->next) | ||
919 | if (is_companion (self, NM_DEVICE (list->data))) | ||
920 | break; | ||
921 | |||
922 | g_object_unref (manager); | ||
923 | |||
924 | return FALSE; | ||
925 | } | ||
926 | |||
927 | static void | ||
928 | state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data) | ||
929 | { | ||
930 | NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); | ||
931 | |||
932 | switch (state) { | ||
933 | case NM_DEVICE_STATE_UNMANAGED: | ||
934 | break; | ||
935 | case NM_DEVICE_STATE_UNAVAILABLE: | ||
936 | /* If transitioning to UNAVAILBLE and the companion device is known then | ||
937 | * transition to DISCONNECTED otherwise wait for our companion. | ||
938 | */ | ||
939 | g_idle_add (check_companion_cb, self); | ||
940 | break; | ||
941 | case NM_DEVICE_STATE_ACTIVATED: | ||
942 | break; | ||
943 | case NM_DEVICE_STATE_FAILED: | ||
944 | break; | ||
945 | case NM_DEVICE_STATE_DISCONNECTED: | ||
946 | break; | ||
947 | default: | ||
948 | break; | ||
949 | } | ||
950 | } | ||
951 | |||
952 | |||
953 | NMDevice * | ||
954 | nm_device_olpc_mesh_new (const char *udi, | ||
955 | const char *iface, | ||
956 | const char *driver, | ||
957 | guint32 ifindex) | ||
958 | { | ||
959 | GObject *obj; | ||
960 | |||
961 | g_return_val_if_fail (udi != NULL, NULL); | ||
962 | g_return_val_if_fail (iface != NULL, NULL); | ||
963 | g_return_val_if_fail (driver != NULL, NULL); | ||
964 | |||
965 | obj = g_object_new (NM_TYPE_DEVICE_OLPC_MESH, | ||
966 | NM_DEVICE_INTERFACE_UDI, udi, | ||
967 | NM_DEVICE_INTERFACE_IFACE, iface, | ||
968 | NM_DEVICE_INTERFACE_DRIVER, driver, | ||
969 | NM_DEVICE_OLPC_MESH_IFINDEX, ifindex, | ||
970 | NM_DEVICE_INTERFACE_TYPE_DESC, "802.11 OLPC Mesh", | ||
971 | NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, | ||
972 | NULL); | ||
973 | if (obj == NULL) | ||
974 | return NULL; | ||
975 | |||
976 | g_signal_connect (obj, "state-changed", G_CALLBACK (state_changed_cb), NULL); | ||
977 | |||
978 | return NM_DEVICE (obj); | ||
979 | } | ||
diff --git a/src/nm-device-olpc-mesh.h b/src/nm-device-olpc-mesh.h new file mode 100644 index 0000000000..9ec051f468 --- /dev/null +++ b/src/nm-device-olpc-mesh.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ | ||
2 | |||
3 | /* NetworkManager -- Network link manager | ||
4 | * | ||
5 | * Dan Williams <dcbw@redhat.com> | ||
6 | * Sjoerd Simons <sjoerd.simons@collabora.co.uk> | ||
7 | * Daniel Drake <dsd@laptop.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | * | ||
23 | * (C) Copyright 2005 Red Hat, Inc. | ||
24 | * (C) Copyright 2008 Collabora Ltd. | ||
25 | * (C) Copyright 2009 One Laptop per Child | ||
26 | */ | ||
27 | |||
28 | #ifndef NM_DEVICE_OLPC_MESH_H | ||
29 | #define NM_DEVICE_OLPC_MESH_H | ||
30 | |||
31 | #include <glib-object.h> | ||
32 | #include <dbus/dbus.h> | ||
33 | |||
34 | #include "nm-device.h" | ||
35 | |||
36 | G_BEGIN_DECLS | ||
37 | |||
38 | #define NM_TYPE_DEVICE_OLPC_MESH (nm_device_olpc_mesh_get_type ()) | ||
39 | #define NM_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh)) | ||
40 | #define NM_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) | ||
41 | #define NM_IS_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH)) | ||
42 | #define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OLPC_MESH)) | ||
43 | #define NM_DEVICE_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) | ||
44 | |||
45 | #define NM_DEVICE_OLPC_MESH_HW_ADDRESS "hw-address" | ||
46 | #define NM_DEVICE_OLPC_MESH_COMPANION "companion" | ||
47 | #define NM_DEVICE_OLPC_MESH_BITRATE "bitrate" | ||
48 | #define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel" | ||
49 | #define NM_DEVICE_OLPC_MESH_IFINDEX "ifindex" | ||
50 | |||
51 | #ifndef NM_DEVICE_OLPC_MESH_DEFINED | ||
52 | #define NM_DEVICE_OLPC_MESH_DEFINED | ||
53 | typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh; | ||
54 | #endif | ||
55 | |||
56 | typedef struct _NMDeviceOlpcMeshClass NMDeviceOlpcMeshClass; | ||
57 | typedef struct _NMDeviceOlpcMeshPrivate NMDeviceOlpcMeshPrivate; | ||
58 | |||
59 | struct _NMDeviceOlpcMesh | ||
60 | { | ||
61 | NMDevice parent; | ||
62 | }; | ||
63 | |||
64 | struct _NMDeviceOlpcMeshClass | ||
65 | { | ||
66 | NMDeviceClass parent; | ||
67 | |||
68 | /* Signals */ | ||
69 | void (*properties_changed) (NMDeviceOlpcMesh *device, | ||
70 | GHashTable *properties); | ||
71 | }; | ||
72 | |||
73 | |||
74 | GType nm_device_olpc_mesh_get_type (void); | ||
75 | |||
76 | NMDevice *nm_device_olpc_mesh_new (const char *udi, | ||
77 | const char *iface, | ||
78 | const char *driver, | ||
79 | guint32 ifindex); | ||
80 | |||
81 | guint32 nm_device_olpc_mesh_get_ifindex (NMDeviceOlpcMesh *self); | ||
82 | |||
83 | G_END_DECLS | ||
84 | |||
85 | #endif /* NM_DEVICE_OLPC_MESH_H */ | ||
diff --git a/src/nm-manager.c b/src/nm-manager.c index 07be3e3071..cdab19fb77 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "nm-device-private.h" | 35 | #include "nm-device-private.h" |
36 | #include "nm-device-ethernet.h" | 36 | #include "nm-device-ethernet.h" |
37 | #include "nm-device-wifi.h" | 37 | #include "nm-device-wifi.h" |
38 | #include "nm-device-olpc-mesh.h" | ||
38 | #include "NetworkManagerSystem.h" | 39 | #include "NetworkManagerSystem.h" |
39 | #include "nm-properties-changed-signal.h" | 40 | #include "nm-properties-changed-signal.h" |
40 | #include "nm-setting-bluetooth.h" | 41 | #include "nm-setting-bluetooth.h" |
@@ -1392,6 +1393,8 @@ find_device_by_ifindex (NMManager *self, guint32 ifindex) | |||
1392 | candidate_idx = nm_device_ethernet_get_ifindex (NM_DEVICE_ETHERNET (device)); | 1393 | candidate_idx = nm_device_ethernet_get_ifindex (NM_DEVICE_ETHERNET (device)); |
1393 | else if (NM_IS_DEVICE_WIFI (device)) | 1394 | else if (NM_IS_DEVICE_WIFI (device)) |
1394 | candidate_idx = nm_device_wifi_get_ifindex (NM_DEVICE_WIFI (device)); | 1395 | candidate_idx = nm_device_wifi_get_ifindex (NM_DEVICE_WIFI (device)); |
1396 | else if (NM_IS_DEVICE_OLPC_MESH (device)) | ||
1397 | candidate_idx = nm_device_olpc_mesh_get_ifindex (NM_DEVICE_OLPC_MESH (device)); | ||
1395 | 1398 | ||
1396 | if (candidate_idx == ifindex) | 1399 | if (candidate_idx == ifindex) |
1397 | return device; | 1400 | return device; |
diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index c9a184d8f6..191ba4f145 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "nm-utils.h" | 36 | #include "nm-utils.h" |
37 | #include "NetworkManagerUtils.h" | 37 | #include "NetworkManagerUtils.h" |
38 | #include "nm-device-wifi.h" | 38 | #include "nm-device-wifi.h" |
39 | #include "nm-device-olpc-mesh.h" | ||
39 | #include "nm-device-ethernet.h" | 40 | #include "nm-device-ethernet.h" |
40 | 41 | ||
41 | typedef struct { | 42 | typedef struct { |
@@ -271,6 +272,13 @@ is_wireless (GUdevDevice *device) | |||
271 | return is_wifi; | 272 | return is_wifi; |
272 | } | 273 | } |
273 | 274 | ||
275 | static gboolean | ||
276 | is_olpc_mesh (GUdevDevice *device) | ||
277 | { | ||
278 | const gchar *prop = g_udev_device_get_property (device, "ID_NM_OLPC_MESH"); | ||
279 | return (prop != NULL); | ||
280 | } | ||
281 | |||
274 | static GObject * | 282 | static GObject * |
275 | device_creator (NMUdevManager *manager, | 283 | device_creator (NMUdevManager *manager, |
276 | GUdevDevice *udev_device, | 284 | GUdevDevice *udev_device, |
@@ -311,7 +319,9 @@ device_creator (NMUdevManager *manager, | |||
311 | return NULL; | 319 | return NULL; |
312 | } | 320 | } |
313 | 321 | ||
314 | if (is_wireless (udev_device)) | 322 | if (is_olpc_mesh (udev_device)) /* must be before is_wireless */ |
323 | device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver, ifindex); | ||
324 | else if (is_wireless (udev_device)) | ||
315 | device = (GObject *) nm_device_wifi_new (path, ifname, driver, ifindex); | 325 | device = (GObject *) nm_device_wifi_new (path, ifname, driver, ifindex); |
316 | else | 326 | else |
317 | device = (GObject *) nm_device_ethernet_new (path, ifname, driver, ifindex); | 327 | device = (GObject *) nm_device_ethernet_new (path, ifname, driver, ifindex); |