device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-util / nm-setting-olpc-mesh.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2007 - 2013 Red Hat, Inc.
19  * Copyright 2007 - 2008 Novell, Inc.
20  * Copyright 2009 One Laptop per Child
21  */
22
23 #include "nm-default.h"
24
25 #include <string.h>
26 #include <netinet/ether.h>
27 #include <dbus/dbus-glib.h>
28
29 #include "NetworkManager.h"
30 #include "nm-setting-olpc-mesh.h"
31 #include "nm-param-spec-specialized.h"
32 #include "nm-utils.h"
33 #include "nm-dbus-glib-types.h"
34 #include "nm-utils-private.h"
35 #include "nm-setting-private.h"
36
37 GQuark
38 nm_setting_olpc_mesh_error_quark (void)
39 {
40         static GQuark quark;
41
42         if (G_UNLIKELY (!quark))
43                 quark = g_quark_from_static_string ("nm-setting-olpc-mesh-error-quark");
44         return quark;
45 }
46
47 static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting);
48
49 G_DEFINE_TYPE_WITH_CODE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING,
50                          _nm_register_setting (NM_SETTING_OLPC_MESH_SETTING_NAME,
51                                                g_define_type_id,
52                                                1,
53                                                NM_SETTING_OLPC_MESH_ERROR))
54 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OLPC_MESH)
55
56 #define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate))
57
58 typedef struct {
59         GByteArray *ssid;
60         guint32 channel;
61         GByteArray *dhcp_anycast_addr;
62 } NMSettingOlpcMeshPrivate;
63
64 enum {
65         PROP_0,
66         PROP_SSID,
67         PROP_CHANNEL,
68         PROP_DHCP_ANYCAST_ADDRESS,
69
70         LAST_PROP
71 };
72
73 /**
74  * nm_setting_olpc_mesh_new:
75  *
76  * Creates a new #NMSettingOlpcMesh object with default values.
77  *
78  * Returns: the new empty #NMSettingOlpcMesh object
79  **/
80 NMSetting *nm_setting_olpc_mesh_new (void)
81 {
82         return (NMSetting *) g_object_new (NM_TYPE_SETTING_OLPC_MESH, NULL);
83 }
84
85 static void
86 nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting)
87 {
88 }
89
90 const GByteArray *
91 nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting)
92 {
93         g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL);
94
95         return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->ssid;
96 }
97
98 guint32
99 nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting)
100 {
101         g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), 0);
102
103         return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->channel;
104 }
105
106 const GByteArray *
107 nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting)
108 {
109         g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL);
110
111         return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->dhcp_anycast_addr;
112 }
113
114 static gboolean
115 verify (NMSetting *setting, GSList *all_settings, GError **error)
116 {
117         NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (setting);
118
119         if (!priv->ssid) {
120                 g_set_error_literal (error,
121                                      NM_SETTING_OLPC_MESH_ERROR,
122                                      NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY,
123                                      _("property is missing"));
124                 g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_SSID);
125                 return FALSE;
126         }
127
128         if (!priv->ssid->len || priv->ssid->len > 32) {
129                 g_set_error_literal (error,
130                                      NM_SETTING_OLPC_MESH_ERROR,
131                                      NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
132                                      _("SSID length is out of range <1-32> bytes"));
133                 g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_SSID);
134                 return FALSE;
135         }
136
137         if (priv->channel == 0 || priv->channel > 13) {
138                 g_set_error (error,
139                              NM_SETTING_OLPC_MESH_ERROR,
140                              NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
141                              _("'%d' is not a valid channel"),
142                              priv->channel);
143                 g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_CHANNEL);
144                 return FALSE;
145         }
146
147         if (priv->dhcp_anycast_addr && priv->dhcp_anycast_addr->len != ETH_ALEN) {
148                 g_set_error_literal (error,
149                                      NM_SETTING_OLPC_MESH_ERROR,
150                                      NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
151                                      _("property is invalid"));
152                 g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS);
153                 return FALSE;
154         }
155
156         return TRUE;
157 }
158
159 static void
160 finalize (GObject *object)
161 {
162         NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object);
163
164         if (priv->ssid)
165                 g_byte_array_free (priv->ssid, TRUE);
166         if (priv->dhcp_anycast_addr)
167                 g_byte_array_free (priv->dhcp_anycast_addr, TRUE);
168
169         G_OBJECT_CLASS (nm_setting_olpc_mesh_parent_class)->finalize (object);
170 }
171
172 static void
173 set_property (GObject *object, guint prop_id,
174               const GValue *value, GParamSpec *pspec)
175 {
176         NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object);
177
178         switch (prop_id) {
179         case PROP_SSID:
180                 if (priv->ssid)
181                         g_byte_array_free (priv->ssid, TRUE);
182                 priv->ssid = g_value_dup_boxed (value);
183                 break;
184         case PROP_CHANNEL:
185                 priv->channel = g_value_get_uint (value);
186                 break;
187         case PROP_DHCP_ANYCAST_ADDRESS:
188                 if (priv->dhcp_anycast_addr)
189                         g_byte_array_free (priv->dhcp_anycast_addr, TRUE);
190                 priv->dhcp_anycast_addr = g_value_dup_boxed (value);
191                 break;
192         default:
193                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
194                 break;
195         }
196 }
197
198 static void
199 get_property (GObject *object, guint prop_id,
200               GValue *value, GParamSpec *pspec)
201 {
202         NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH (object);
203
204         switch (prop_id) {
205         case PROP_SSID:
206                 g_value_set_boxed (value, nm_setting_olpc_mesh_get_ssid (setting));
207                 break;
208         case PROP_CHANNEL:
209                 g_value_set_uint (value, nm_setting_olpc_mesh_get_channel (setting));
210                 break;
211         case PROP_DHCP_ANYCAST_ADDRESS:
212                 g_value_set_boxed (value, nm_setting_olpc_mesh_get_dhcp_anycast_address (setting));
213                 break;
214         default:
215                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216                 break;
217         }
218 }
219
220 static void
221 nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
222 {
223         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
224         NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
225
226         g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate));
227
228         /* virtual methods */
229         object_class->set_property = set_property;
230         object_class->get_property = get_property;
231         object_class->finalize     = finalize;
232         parent_class->verify       = verify;
233
234         /* Properties */
235         /**
236          * NMSettingOlpcMesh:ssid:
237          *
238          * SSID of the mesh network to join.
239          **/
240         g_object_class_install_property
241                 (object_class, PROP_SSID,
242                  _nm_param_spec_specialized (NM_SETTING_OLPC_MESH_SSID, "", "",
243                                              DBUS_TYPE_G_UCHAR_ARRAY,
244                                              G_PARAM_READWRITE |
245                                              NM_SETTING_PARAM_INFERRABLE |
246                                              G_PARAM_STATIC_STRINGS));
247
248         /**
249          * NMSettingOlpcMesh:channel:
250          *
251          * Channel on which the mesh network to join is located.
252          **/
253         g_object_class_install_property
254                 (object_class, PROP_CHANNEL,
255                  g_param_spec_uint (NM_SETTING_OLPC_MESH_CHANNEL, "", "",
256                                     0, G_MAXUINT32, 0,
257                                     G_PARAM_READWRITE |
258                                     G_PARAM_CONSTRUCT |
259                                     NM_SETTING_PARAM_INFERRABLE |
260                                     G_PARAM_STATIC_STRINGS));
261
262         /**
263          * NMSettingOlpcMesh:dhcp-anycast-address:
264          *
265          * Anycast DHCP MAC address used when requesting an IP address via DHCP.
266          * The specific anycast address used determines which DHCP server class
267          * answers the request.
268          **/
269         g_object_class_install_property
270                 (object_class, PROP_DHCP_ANYCAST_ADDRESS,
271                  _nm_param_spec_specialized (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, "", "",
272                                              DBUS_TYPE_G_UCHAR_ARRAY,
273                                              G_PARAM_READWRITE |
274                                              G_PARAM_STATIC_STRINGS));
275 }