Add skeletons for IP operation callbacks
[platform/upstream/connman.git] / src / ipconfig.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <net/if.h>
27
28 #ifndef IFF_LOWER_UP
29 #define IFF_LOWER_UP    0x10000
30 #endif
31
32 #include <gdbus.h>
33
34 #include "connman.h"
35
36 struct connman_ipaddress {
37         unsigned char prefixlen;
38         char *address;
39 };
40
41 struct connman_ipconfig {
42         gint refcount;
43         int index;
44         char *interface;
45         unsigned short type;
46         unsigned int flags;
47
48         struct connman_ipconfig_ops *ops;
49         void *ops_data;
50
51         enum connman_ipconfig_method method;
52         GSList *address_list;
53         char *gateway;
54 };
55
56 static void free_address_list(struct connman_ipconfig *ipconfig)
57 {
58         GSList *list;
59
60         for (list = ipconfig->address_list; list; list = list->next) {
61                 struct connman_ipaddress *ipaddress = list->data;
62
63                 g_free(ipaddress->address);
64                 g_free(ipaddress);
65                 list->data = NULL;
66         }
67
68         g_slist_free(ipconfig->address_list);
69         ipconfig->address_list = NULL;
70 }
71
72 static struct connman_ipaddress *find_ipaddress(struct connman_ipconfig *ipconfig,
73                                 unsigned char prefixlen, const char *address)
74 {
75         GSList *list;
76
77         for (list = ipconfig->address_list; list; list = list->next) {
78                 struct connman_ipaddress *ipaddress = list->data;
79
80                 if (g_strcmp0(ipaddress->address, address) == 0 &&
81                                         ipaddress->prefixlen == prefixlen)
82                         return ipaddress;
83         }
84
85         return NULL;
86 }
87
88 /**
89  * connman_ipconfig_create:
90  *
91  * Allocate a new ipconfig structure.
92  *
93  * Returns: a newly-allocated #connman_ipconfig structure
94  */
95 struct connman_ipconfig *connman_ipconfig_create(int index)
96 {
97         struct connman_ipconfig *ipconfig;
98
99         DBG("");
100
101         ipconfig = g_try_new0(struct connman_ipconfig, 1);
102         if (ipconfig == NULL)
103                 return NULL;
104
105         ipconfig->refcount = 1;
106
107         ipconfig->index = index;
108         ipconfig->interface = connman_inet_ifname(index);
109
110         DBG("ipconfig %p", ipconfig);
111
112         connman_info("%s {create} index %d", ipconfig->interface,
113                                                         ipconfig->index);
114
115         return ipconfig;
116 }
117
118 /**
119  * connman_ipconfig_ref:
120  * @ipconfig: ipconfig structure
121  *
122  * Increase reference counter of ipconfig
123  */
124 struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig)
125 {
126         g_atomic_int_inc(&ipconfig->refcount);
127
128         return ipconfig;
129 }
130
131 /**
132  * connman_ipconfig_unref:
133  * @ipconfig: ipconfig structure
134  *
135  * Decrease reference counter of ipconfig
136  */
137 void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
138 {
139         if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
140                 connman_info("%s {remove} index %d", ipconfig->interface,
141                                                         ipconfig->index);
142
143                 g_free(ipconfig->gateway);
144
145                 free_address_list(ipconfig);
146
147                 g_free(ipconfig->interface);
148                 g_free(ipconfig);
149         }
150 }
151
152 /**
153  * connman_ipconfig_get_data:
154  * @ipconfig: ipconfig structure
155  *
156  * Get private data pointer
157  */
158 void *connman_ipconfig_get_data(struct connman_ipconfig *ipconfig)
159 {
160         return ipconfig->ops_data;
161 }
162
163 /**
164  * connman_ipconfig_set_data:
165  * @ipconfig: ipconfig structure
166  * @data: data pointer
167  *
168  * Set private data pointer
169  */
170 void connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data)
171 {
172         ipconfig->ops_data = data;
173 }
174
175 /**
176  * connman_ipconfig_set_ops:
177  * @ipconfig: ipconfig structure
178  * @ops: operation callbacks
179  *
180  * Set the operation callbacks
181  */
182 void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
183                                         struct connman_ipconfig_ops *ops)
184 {
185         ipconfig->ops = ops;
186 }
187
188 /**
189  * connman_ipconfig_set_method:
190  * @ipconfig: ipconfig structure
191  * @method: configuration method
192  *
193  * Set the configuration method
194  */
195 int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
196                                         enum connman_ipconfig_method method)
197 {
198         ipconfig->method = method;
199
200         return 0;
201 }
202
203 int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
204 {
205         return ipconfig->index;
206 }
207
208 unsigned short __connman_ipconfig_get_type(struct connman_ipconfig *ipconfig)
209 {
210         return ipconfig->type;
211 }
212
213 unsigned int __connman_ipconfig_get_flags(struct connman_ipconfig *ipconfig)
214 {
215         return ipconfig->flags;
216 }
217
218 const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig)
219 {
220         return ipconfig->gateway;
221 }
222
223 void __connman_ipconfig_update_link(struct connman_ipconfig *ipconfig,
224                                         unsigned flags, unsigned change)
225 {
226         GString *str;
227
228         if (flags == ipconfig->flags)
229                 return;
230
231         ipconfig->flags = flags;
232
233         str = g_string_new(NULL);
234         if (str == NULL)
235                 return;
236
237         if (flags & IFF_UP)
238                 g_string_append(str, "UP");
239         else
240                 g_string_append(str, "DOWN");
241
242         if (flags & IFF_RUNNING)
243                 g_string_append(str, ",RUNNING");
244
245         if (flags & IFF_LOWER_UP)
246                 g_string_append(str, ",LOWER_UP");
247
248         connman_info("%s {update} flags %u change %u <%s>",
249                                 ipconfig->interface, flags, change, str->str);
250
251         g_string_free(str, TRUE);
252 }
253
254 void __connman_ipconfig_add_address(struct connman_ipconfig *ipconfig,
255                                 const char *label, unsigned char prefixlen,
256                                 const char *address, const char *broadcast)
257 {
258         struct connman_ipaddress *ipaddress;
259
260         ipaddress = g_try_new0(struct connman_ipaddress, 1);
261         if (ipaddress == NULL)
262                 return;
263
264         ipaddress->prefixlen = prefixlen;
265         ipaddress->address = g_strdup(address);
266
267         ipconfig->address_list = g_slist_append(ipconfig->address_list,
268                                                                 ipaddress);
269
270         connman_info("%s {add} address %s/%u label %s", ipconfig->interface,
271                                                 address, prefixlen, label);
272 }
273
274 void __connman_ipconfig_del_address(struct connman_ipconfig *ipconfig,
275                                 const char *label, unsigned char prefixlen,
276                                 const char *address, const char *broadcast)
277 {
278         struct connman_ipaddress *ipaddress;
279
280         ipaddress = find_ipaddress(ipconfig, prefixlen, address);
281         if (ipaddress == NULL)
282                 return;
283
284         ipconfig->address_list = g_slist_remove(ipconfig->address_list,
285                                                                 ipaddress);
286
287         g_free(ipaddress->address);
288         g_free(ipaddress);
289
290         connman_info("%s {del} address %s/%u label %s", ipconfig->interface,
291                                                 address, prefixlen, label);
292 }
293
294 static const char *scope2str(unsigned char scope)
295 {
296         switch (scope) {
297         case 0:
298                 return "UNIVERSE";
299         case 253:
300                 return "LINK";
301         }
302
303         return "";
304 }
305
306 void __connman_ipconfig_add_route(struct connman_ipconfig *ipconfig,
307                                 unsigned char scope, const char *destination,
308                                                         const char *gateway)
309 {
310         if (scope == 0 && g_strcmp0(destination, "0.0.0.0") == 0) {
311                 g_free(ipconfig->gateway);
312                 ipconfig->gateway = g_strdup(gateway);
313         }
314
315         connman_info("%s {add} route %s gw %s scope %u <%s>",
316                                         ipconfig->interface, destination,
317                                         gateway, scope, scope2str(scope));
318 }
319
320 void __connman_ipconfig_del_route(struct connman_ipconfig *ipconfig,
321                                 unsigned char scope, const char *destination,
322                                                         const char *gateway)
323 {
324         if (scope == 0 && g_strcmp0(destination, "0.0.0.0") == 0) {
325                 g_free(ipconfig->gateway);
326                 ipconfig->gateway = NULL;
327         }
328
329         connman_info("%s {del} route %s gw %s scope %u <%s>",
330                                         ipconfig->interface, destination,
331                                         gateway, scope, scope2str(scope));
332 }
333
334 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
335 {
336         switch (method) {
337         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
338                 break;
339         case CONNMAN_IPCONFIG_METHOD_OFF:
340                 return "off";
341         case CONNMAN_IPCONFIG_METHOD_STATIC:
342                 return "static";
343         case CONNMAN_IPCONFIG_METHOD_DHCP:
344                 return "dhcp";
345         }
346
347         return NULL;
348 }
349
350 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
351 {
352         if (g_strcmp0(method, "off") == 0)
353                 return CONNMAN_IPCONFIG_METHOD_OFF;
354         else if (g_strcmp0(method, "static") == 0)
355                 return CONNMAN_IPCONFIG_METHOD_STATIC;
356         else if (g_strcmp0(method, "dhcp") == 0)
357                 return CONNMAN_IPCONFIG_METHOD_DHCP;
358         else
359                 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
360 }
361
362 static void append_variant(DBusMessageIter *iter, const char *prefix,
363                                         const char *key, int type, void *val)
364 {
365         char *str;
366
367         if (prefix == NULL) {
368                 connman_dbus_dict_append_variant(iter, key, type, val);
369                 return;
370         }
371
372         str = g_strdup_printf("%s%s", prefix, key);
373         if (str != NULL)
374                 connman_dbus_dict_append_variant(iter, str, type, val);
375
376         g_free(str);
377 }
378
379 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
380                                 DBusMessageIter *iter, const char *prefix)
381 {
382         const char *str;
383
384         str = __connman_ipconfig_method2string(ipconfig->method);
385         if (str == NULL)
386                 return;
387
388         append_variant(iter, prefix, "Method", DBUS_TYPE_STRING, &str);
389 }
390
391 int __connman_ipconfig_set_ipv4(struct connman_ipconfig *ipconfig,
392                                 const char *key, DBusMessageIter *value)
393 {
394         int type = dbus_message_iter_get_arg_type(value);
395
396         DBG("ipconfig %p key %s type %d", ipconfig, key, type);
397
398         if (g_strcmp0(key, "Method") == 0) {
399                 const char *method;
400
401                 if (type != DBUS_TYPE_STRING)
402                         return -EINVAL;
403
404                 dbus_message_iter_get_basic(value, &method);
405
406                 ipconfig->method = __connman_ipconfig_string2method(method);
407         } else
408                 return -EINVAL;
409
410         return 0;
411 }
412
413 int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
414                 GKeyFile *keyfile, const char *identifier, const char *prefix)
415 {
416         DBG("ipconfig %p identifier %s", ipconfig, identifier);
417
418         return 0;
419 }
420
421 int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
422                 GKeyFile *keyfile, const char *identifier, const char *prefix)
423 {
424         DBG("ipconfig %p identifier %s", ipconfig, identifier);
425
426         return 0;
427 }
428
429 static GSList *driver_list = NULL;
430
431 static gint compare_priority(gconstpointer a, gconstpointer b)
432 {
433         const struct connman_ipconfig_driver *driver1 = a;
434         const struct connman_ipconfig_driver *driver2 = b;
435
436         return driver2->priority - driver1->priority;
437 }
438
439 /**
440  * connman_ipconfig_driver_register:
441  * @driver: IP configuration driver
442  *
443  * Register a new IP configuration driver
444  *
445  * Returns: %0 on success
446  */
447 int connman_ipconfig_driver_register(struct connman_ipconfig_driver *driver)
448 {
449         DBG("driver %p name %s", driver, driver->name);
450
451         driver_list = g_slist_insert_sorted(driver_list, driver,
452                                                         compare_priority);
453
454         return 0;
455 }
456
457 /**
458  * connman_ipconfig_driver_unregister:
459  * @driver: IP configuration driver
460  *
461  * Remove a previously registered IP configuration driver.
462  */
463 void connman_ipconfig_driver_unregister(struct connman_ipconfig_driver *driver)
464 {
465         DBG("driver %p name %s", driver, driver->name);
466
467         driver_list = g_slist_remove(driver_list, driver);
468 }