Fix issues with hashing of RTNL interfaces and their flags
[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_ipconfig {
37         gint refcount;
38         int index;
39         char *interface;
40         unsigned int flags;
41         enum connman_ipconfig_method method;
42 };
43
44 /**
45  * connman_ipconfig_create:
46  *
47  * Allocate a new ipconfig structure.
48  *
49  * Returns: a newly-allocated #connman_ipconfig structure
50  */
51 struct connman_ipconfig *connman_ipconfig_create(int index)
52 {
53         struct connman_ipconfig *ipconfig;
54
55         DBG("");
56
57         ipconfig = g_try_new0(struct connman_ipconfig, 1);
58         if (ipconfig == NULL)
59                 return NULL;
60
61         ipconfig->refcount = 1;
62
63         ipconfig->index = index;
64         ipconfig->interface = connman_inet_ifname(index);
65
66         DBG("ipconfig %p", ipconfig);
67
68         //__connman_rtnl_register_ipconfig(ipconfig);
69
70         connman_info("%s {create} index %d", ipconfig->interface,
71                                                         ipconfig->index);
72
73         return ipconfig;
74 }
75
76 /**
77  * connman_ipconfig_ref:
78  * @ipconfig: ipconfig structure
79  *
80  * Increase reference counter of ipconfig
81  */
82 struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig)
83 {
84         g_atomic_int_inc(&ipconfig->refcount);
85
86         return ipconfig;
87 }
88
89 /**
90  * connman_ipconfig_unref:
91  * @ipconfig: ipconfig structure
92  *
93  * Decrease reference counter of ipconfig
94  */
95 void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
96 {
97         if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
98                 //__connman_rtnl_unregister_ipconfig(ipconfig);
99
100                 connman_info("%s {remove} index %d", ipconfig->interface,
101                                                         ipconfig->index);
102
103                 g_free(ipconfig->interface);
104                 g_free(ipconfig);
105         }
106 }
107
108 /**
109  * connman_ipconfig_set_method:
110  * @ipconfig: ipconfig structure
111  * @method: configuration method
112  *
113  * Set the configuration method
114  */
115 int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
116                                         enum connman_ipconfig_method method)
117 {
118         ipconfig->method = method;
119
120         return 0;
121 }
122
123 int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
124 {
125         return ipconfig->index;
126 }
127
128 void __connman_ipconfig_update_link(struct connman_ipconfig *ipconfig,
129                                         unsigned flags, unsigned change)
130 {
131         GString *str;
132
133         if (flags == ipconfig->flags)
134                 return;
135
136         ipconfig->flags = flags;
137
138         str = g_string_new(NULL);
139         if (str == NULL)
140                 return;
141
142         if (flags & IFF_UP)
143                 g_string_append(str, "UP");
144         else
145                 g_string_append(str, "DOWN");
146
147         if (flags & IFF_RUNNING)
148                 g_string_append(str, ",RUNNING");
149
150         if (flags & IFF_LOWER_UP)
151                 g_string_append(str, ",LOWER_UP");
152
153         connman_info("%s {update} flags %u change %u <%s>",
154                                 ipconfig->interface, flags, change, str->str);
155
156         g_string_free(str, TRUE);
157 }
158
159 void __connman_ipconfig_add_address(struct connman_ipconfig *ipconfig,
160                                 const char *label, unsigned char prefixlen,
161                                 const char *address, const char *broadcast)
162 {
163         connman_info("%s {add} address %s/%u label %s", ipconfig->interface,
164                                                 address, prefixlen, label);
165 }
166
167 void __connman_ipconfig_del_address(struct connman_ipconfig *ipconfig,
168                                 const char *label, unsigned char prefixlen,
169                                 const char *address, const char *broadcast)
170 {
171         connman_info("%s {del} address %s/%u label %s", ipconfig->interface,
172                                                 address, prefixlen, label);
173 }
174
175 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
176 {
177         switch (method) {
178         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
179                 break;
180         case CONNMAN_IPCONFIG_METHOD_OFF:
181                 return "off";
182         case CONNMAN_IPCONFIG_METHOD_STATIC:
183                 return "static";
184         case CONNMAN_IPCONFIG_METHOD_DHCP:
185                 return "dhcp";
186         }
187
188         return NULL;
189 }
190
191 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
192 {
193         if (g_strcmp0(method, "off") == 0)
194                 return CONNMAN_IPCONFIG_METHOD_OFF;
195         else if (g_strcmp0(method, "static") == 0)
196                 return CONNMAN_IPCONFIG_METHOD_STATIC;
197         else if (g_strcmp0(method, "dhcp") == 0)
198                 return CONNMAN_IPCONFIG_METHOD_DHCP;
199         else
200                 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
201 }
202
203 static void append_variant(DBusMessageIter *iter, const char *prefix,
204                                         const char *key, int type, void *val)
205 {
206         char *str;
207
208         if (prefix == NULL) {
209                 connman_dbus_dict_append_variant(iter, key, type, val);
210                 return;
211         }
212
213         str = g_strdup_printf("%s%s", prefix, key);
214         if (str != NULL)
215                 connman_dbus_dict_append_variant(iter, str, type, val);
216
217         g_free(str);
218 }
219
220 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
221                                 DBusMessageIter *iter, const char *prefix)
222 {
223         const char *str;
224
225         str = __connman_ipconfig_method2string(ipconfig->method);
226         if (str == NULL)
227                 return;
228
229         append_variant(iter, prefix, "Method", DBUS_TYPE_STRING, &str);
230 }
231
232 int __connman_ipconfig_set_ipv4(struct connman_ipconfig *ipconfig,
233                                 const char *key, DBusMessageIter *value)
234 {
235         int type = dbus_message_iter_get_arg_type(value);
236
237         DBG("ipconfig %p key %s type %d", ipconfig, key, type);
238
239         if (g_strcmp0(key, "Method") == 0) {
240                 const char *method;
241
242                 if (type != DBUS_TYPE_STRING)
243                         return -EINVAL;
244
245                 dbus_message_iter_get_basic(value, &method);
246
247                 ipconfig->method = __connman_ipconfig_string2method(method);
248         } else
249                 return -EINVAL;
250
251         return 0;
252 }
253
254 int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
255                 GKeyFile *keyfile, const char *identifier, const char *prefix)
256 {
257         DBG("ipconfig %p identifier %s", ipconfig, identifier);
258
259         return 0;
260 }
261
262 int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
263                 GKeyFile *keyfile, const char *identifier, const char *prefix)
264 {
265         DBG("ipconfig %p identifier %s", ipconfig, identifier);
266
267         return 0;
268 }
269
270 static GSList *driver_list = NULL;
271
272 static gint compare_priority(gconstpointer a, gconstpointer b)
273 {
274         const struct connman_ipconfig_driver *driver1 = a;
275         const struct connman_ipconfig_driver *driver2 = b;
276
277         return driver2->priority - driver1->priority;
278 }
279
280 /**
281  * connman_ipconfig_driver_register:
282  * @driver: IP configuration driver
283  *
284  * Register a new IP configuration driver
285  *
286  * Returns: %0 on success
287  */
288 int connman_ipconfig_driver_register(struct connman_ipconfig_driver *driver)
289 {
290         DBG("driver %p name %s", driver, driver->name);
291
292         driver_list = g_slist_insert_sorted(driver_list, driver,
293                                                         compare_priority);
294
295         return 0;
296 }
297
298 /**
299  * connman_ipconfig_driver_unregister:
300  * @driver: IP configuration driver
301  *
302  * Remove a previously registered IP configuration driver.
303  */
304 void connman_ipconfig_driver_unregister(struct connman_ipconfig_driver *driver)
305 {
306         DBG("driver %p name %s", driver, driver->name);
307
308         driver_list = g_slist_remove(driver_list, driver);
309 }