summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2009-08-05 16:34:02 -0400
committerDan Williams <dcbw@redhat.com>2009-08-05 16:34:02 -0400
commitff88cf12c2de43081f1a7c93a2565658119b7894 (patch)
treed5f1b8788ab3667935d944d3c34ac4ab96544d93
parent4bab33405be01fd263373e530d712f3eb8d01d0d (diff)
olpc: add mesh device logic and config setting
-rw-r--r--Makefile.am2
-rw-r--r--callouts/77-nm-olpc-mesh.rules6
-rw-r--r--callouts/Makefile.am4
-rw-r--r--configure.ac8
-rw-r--r--include/NetworkManager.h3
-rw-r--r--introspection/Makefile.am1
-rw-r--r--introspection/nm-device-olpc-mesh.xml32
-rw-r--r--libnm-util/Makefile.am2
-rw-r--r--libnm-util/libnm-util.ver4
-rw-r--r--libnm-util/nm-connection.c6
-rw-r--r--libnm-util/nm-setting-olpc-mesh.c265
-rw-r--r--libnm-util/nm-setting-olpc-mesh.h52
-rw-r--r--src/Makefile.am6
-rw-r--r--src/nm-device-olpc-mesh.c979
-rw-r--r--src/nm-device-olpc-mesh.h85
-rw-r--r--src/nm-manager.c3
-rw-r--r--src/nm-udev-manager.c12
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
30DISTCHECK_CONFIGURE_FLAGS = --with-tests=yes --with-docs=yes 30DISTCHECK_CONFIGURE_FLAGS = --with-tests=yes --with-docs=yes --with-udev-dir=$$dc_install_base/lib/udev
31 31
32DISTCLEANFILES = intltool-extract intltool-merge intltool-update 32DISTCLEANFILES = 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..?
5KERNEL=="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 = \
62nm-dispatcher-glue.h: nm-dispatcher.xml 62nm-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
65udevrulesdir = $(UDEV_BASE_DIR)/rules.d
66udevrules_DATA = 77-nm-olpc-mesh.rules
67
65dbusactivationdir = $(datadir)/dbus-1/system-services 68dbusactivationdir = $(datadir)/dbus-1/system-services
66dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in 69dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in
67dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service) 70dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service)
@@ -85,6 +88,7 @@ CLEANFILES = $(BUILT_SOURCES) $(dbusactivation_DATA)
85 88
86EXTRA_DIST = \ 89EXTRA_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)
193AC_SUBST(GUDEV_CFLAGS) 193AC_SUBST(GUDEV_CFLAGS)
194AC_SUBST(GUDEV_LIBS) 194AC_SUBST(GUDEV_LIBS)
195 195
196AC_ARG_WITH(udev-dir, AS_HELP_STRING([--with-udev-dir=DIR], [where the udev base directory is]))
197if test -n "$with_udev_dir" ; then
198 UDEV_BASE_DIR="$with_udev_dir"
199else
200 UDEV_BASE_DIR="/lib/udev"
201fi
202AC_SUBST(UDEV_BASE_DIR)
203
196PKG_CHECK_EXISTS(gio-2.0,[have_gio=yes],[have_gio=no]) 204PKG_CHECK_EXISTS(gio-2.0,[have_gio=yes],[have_gio=no])
197if test x"$have_gio" = "xno"; then 205if 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
40GQuark
41nm_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
53GType
54nm_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
73static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting);
74
75G_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
79typedef struct {
80 GByteArray *ssid;
81 guint32 channel;
82 GByteArray *dhcp_anycast_addr;
83} NMSettingOlpcMeshPrivate;
84
85enum {
86 PROP_0,
87 PROP_SSID,
88 PROP_CHANNEL,
89 PROP_DHCP_ANYCAST_ADDRESS,
90
91 LAST_PROP
92};
93
94static void
95nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting)
96{
97 g_object_set (setting, NM_SETTING_NAME, NM_SETTING_OLPC_MESH_SETTING_NAME, NULL);
98}
99
100const GByteArray *
101nm_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
108guint32
109nm_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
116const GByteArray *
117nm_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
124static gboolean
125verify (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
164static void
165finalize (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
177static void
178set_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
203static void
204get_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
225static void
226nm_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
8G_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
19typedef 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 ())
27GType nm_setting_olpc_mesh_error_get_type (void);
28
29#define NM_SETTING_OLPC_MESH_ERROR nm_setting_olpc_mesh_error_quark ()
30GQuark 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
36typedef struct {
37 NMSetting parent;
38} NMSettingOlpcMesh;
39
40typedef struct {
41 NMSettingClass parent;
42} NMSettingOlpcMeshClass;
43
44GType nm_setting_olpc_mesh_get_type (void);
45
46const GByteArray *nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting);
47guint32 nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting);
48const GByteArray *nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting);
49
50G_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
128nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml 130nm-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
133nm-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
131nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml 136nm-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
56static void nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid);
57
58G_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
63enum {
64 PROP_0,
65 PROP_HW_ADDRESS,
66 PROP_COMPANION,
67 PROP_ACTIVE_CHANNEL,
68 PROP_IFINDEX,
69
70 LAST_PROP
71};
72
73enum {
74 PROPERTIES_CHANGED,
75
76 LAST_SIGNAL
77};
78
79static guint signals[LAST_SIGNAL] = { 0 };
80
81typedef 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
92struct _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
112static GQuark
113nm_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
124static GType
125nm_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
144static guint32
145real_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) &range;
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
180out:
181 if (fd >= 0)
182 close (fd);
183 return caps;
184}
185
186static void
187nm_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
199static 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
222struct 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
237static GObject*
238constructor (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) &range;
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
286error:
287 if (fd >= 0)
288 close (fd);
289 g_object_unref (object);
290 return NULL;
291}
292
293static gboolean
294real_hw_is_up (NMDevice *device)
295{
296 return nm_system_device_is_up (device);
297}
298
299static gboolean
300real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
301{
302 return nm_system_device_set_up_down (dev, TRUE, no_firmware);
303}
304
305static void
306real_hw_take_down (NMDevice *dev)
307{
308 nm_system_device_set_up_down (dev, FALSE, NULL);
309}
310
311static gboolean
312real_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
320static gboolean
321real_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
330static void
331device_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
342static void
343real_take_down (NMDevice *dev)
344{
345 NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev);
346
347 device_cleanup (self);
348}
349
350static gboolean
351real_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 */
385static void
386nm_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
396static int
397create_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
417static guint32
418nm_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
446out:
447 if (sk >= 0)
448 close (sk);
449 return ret;
450}
451
452static void
453nm_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
480static void
481nm_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
536guint32
537nm_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
546static void
547real_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
574out:
575 close (fd);
576}
577
578
579static NMActStageReturn
580real_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
606static NMActStageReturn
607real_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
639static NMActStageReturn
640real_act_stage4_ip4_config_timeout (NMDevice *dev,
641 NMIP4Config **config,
642 NMDeviceStateReason *reason)
643{
644 return NM_ACT_STAGE_RETURN_FAILURE;
645}
646
647
648static void
649nm_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
671static void
672get_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
699static void
700set_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
716static void
717nm_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
784static void
785companion_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 */
803static void
804companion_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
821static gboolean
822companion_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
833static gboolean
834companion_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
846static gboolean
847is_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
886static void
887device_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
894static gboolean
895check_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
927static void
928state_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
953NMDevice *
954nm_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
36G_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
53typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh;
54#endif
55
56typedef struct _NMDeviceOlpcMeshClass NMDeviceOlpcMeshClass;
57typedef struct _NMDeviceOlpcMeshPrivate NMDeviceOlpcMeshPrivate;
58
59struct _NMDeviceOlpcMesh
60{
61 NMDevice parent;
62};
63
64struct _NMDeviceOlpcMeshClass
65{
66 NMDeviceClass parent;
67
68 /* Signals */
69 void (*properties_changed) (NMDeviceOlpcMesh *device,
70 GHashTable *properties);
71};
72
73
74GType nm_device_olpc_mesh_get_type (void);
75
76NMDevice *nm_device_olpc_mesh_new (const char *udi,
77 const char *iface,
78 const char *driver,
79 guint32 ifindex);
80
81guint32 nm_device_olpc_mesh_get_ifindex (NMDeviceOlpcMesh *self);
82
83G_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
41typedef struct { 42typedef struct {
@@ -271,6 +272,13 @@ is_wireless (GUdevDevice *device)
271 return is_wifi; 272 return is_wifi;
272} 273}
273 274
275static gboolean
276is_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
274static GObject * 282static GObject *
275device_creator (NMUdevManager *manager, 283device_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);