5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
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.
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.
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
36 struct connman_element *element;
45 static GSList *gateway_list = NULL;
47 static struct gateway_data *find_gateway(int index, const char *gateway)
54 for (list = gateway_list; list; list = list->next) {
55 struct gateway_data *data = list->data;
57 if (data->gateway == NULL)
60 if (data->index == index &&
61 g_str_equal(data->gateway, gateway) == TRUE)
68 static int del_routes(struct gateway_data *data)
71 if (data->vpn_phy_index >= 0)
72 connman_inet_del_host_route(data->vpn_phy_index,
74 return connman_inet_clear_gateway_address(data->index,
76 } else if (g_strcmp0(data->gateway, "0.0.0.0") == 0) {
77 return connman_inet_clear_gateway_interface(data->index);
79 connman_inet_del_host_route(data->index, data->gateway);
80 return connman_inet_clear_gateway_address(data->index,
85 static void find_element(struct connman_element *element, gpointer user_data)
87 struct gateway_data *data = user_data;
89 DBG("element %p name %s", element, element->name);
91 if (data->element != NULL)
94 if (element->index != data->index)
97 data->element = element;
100 static struct gateway_data *add_gateway(int index, const char *gateway)
102 struct gateway_data *data;
103 struct connman_service *service;
105 if (strlen(gateway) == 0)
108 data = g_try_new0(struct gateway_data, 1);
113 data->gateway = g_strdup(gateway);
114 data->active = FALSE;
115 data->element = NULL;
118 data->vpn_phy_index = -1;
120 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION,
123 service = __connman_element_get_service(data->element);
124 data->order = __connman_service_get_order(service);
126 gateway_list = g_slist_append(gateway_list, data);
131 static void connection_newgateway(int index, const char *gateway)
133 struct gateway_data *data;
135 DBG("index %d gateway %s", index, gateway);
137 data = find_gateway(index, gateway);
144 static void set_default_gateway(struct gateway_data *data)
146 struct connman_element *element = data->element;
147 struct connman_service *service = NULL;
149 DBG("gateway %s", data->gateway);
151 if (data->vpn == TRUE) {
152 connman_inet_set_gateway_address(data->index, data->vpn_ip);
154 /* vpn gateway going away no changes in services */
158 if (g_strcmp0(data->gateway, "0.0.0.0") == 0) {
159 if (connman_inet_set_gateway_interface(element->index) < 0)
164 if (connman_inet_set_gateway_address(element->index, data->gateway) < 0)
168 service = __connman_element_get_service(element);
169 __connman_service_indicate_default(service);
172 static struct gateway_data *find_default_gateway(void)
174 struct gateway_data *found = NULL;
175 unsigned int order = 0;
178 for (list = gateway_list; list; list = list->next) {
179 struct gateway_data *data = list->data;
181 if (found == NULL || data->order > order) {
190 static int remove_gateway(struct gateway_data *data)
194 DBG("gateway %s", data->gateway);
196 gateway_list = g_slist_remove(gateway_list, data);
198 if (data->active == TRUE)
199 err = del_routes(data);
203 g_free(data->gateway);
204 g_free(data->vpn_ip);
210 static void connection_delgateway(int index, const char *gateway)
212 struct gateway_data *data;
214 DBG("index %d gateway %s", index, gateway);
216 data = find_gateway(index, gateway);
218 data->active = FALSE;
220 data = find_default_gateway();
222 set_default_gateway(data);
225 static struct connman_rtnl connection_rtnl = {
226 .name = "connection",
227 .newgateway = connection_newgateway,
228 .delgateway = connection_delgateway,
231 static struct gateway_data *find_active_gateway(void)
237 for (list = gateway_list; list; list = list->next) {
238 struct gateway_data *data = list->data;
240 if (data->active == TRUE)
247 static int connection_probe(struct connman_element *element)
249 struct connman_service *service = NULL;
250 const char *gateway = NULL;
251 const char *vpn_ip = NULL;
252 struct gateway_data *active_gateway = NULL;
253 struct gateway_data *new_gateway = NULL;
255 DBG("element %p name %s", element, element->name);
257 if (element->parent == NULL)
260 /* FIXME: Remove temporarily for the static gateway support */
261 /* if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
264 connman_element_get_value(element,
265 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
267 connman_element_get_value(element,
268 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &vpn_ip);
270 DBG("gateway %s", gateway);
273 * If gateway is NULL, it's a point to point link and the default
274 * gateway is 0.0.0.0, meaning the interface.
276 if (gateway == NULL) {
278 element->ipv4.gateway = g_strdup(gateway);
281 connman_element_set_enabled(element, TRUE);
283 active_gateway = find_active_gateway();
284 new_gateway = add_gateway(element->index, gateway);
285 if (new_gateway == NULL)
288 service = __connman_element_get_service(element);
290 connman_inet_add_host_route(element->index,
291 new_gateway->gateway, NULL);
292 __connman_service_nameserver_add_routes(service,
293 new_gateway->gateway);
295 __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
297 if (service == NULL) {
298 new_gateway->vpn = TRUE;
299 new_gateway->vpn_ip = g_strdup(vpn_ip);
300 /* make sure vpn gateway are at higher priority */
301 new_gateway->order = 10;
303 new_gateway->vpn_phy_index = active_gateway->index;
305 new_gateway->vpn = FALSE;
307 if (active_gateway == NULL) {
308 set_default_gateway(new_gateway);
312 if (new_gateway->vpn == TRUE) {
313 connman_inet_add_host_route(active_gateway->index,
314 new_gateway->gateway,
315 active_gateway->gateway);
318 if (new_gateway->order >= active_gateway->order) {
319 del_routes(active_gateway);
326 static void connection_remove(struct connman_element *element)
328 struct connman_service *service;
329 const char *gateway = NULL;
330 struct gateway_data *data = NULL;
331 gboolean set_default = FALSE;
334 DBG("element %p name %s", element, element->name);
336 service = __connman_element_get_service(element);
337 __connman_service_nameserver_del_routes(service);
338 __connman_service_indicate_state(service,
339 CONNMAN_SERVICE_STATE_DISCONNECT);
341 connman_element_set_enabled(element, FALSE);
343 connman_element_get_value(element,
344 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
346 DBG("gateway %s", gateway);
351 data = find_gateway(element->index, gateway);
355 set_default = data->vpn;
357 if (data->vpn == TRUE && data->vpn_phy_index >= 0)
358 connman_inet_del_host_route(data->vpn_phy_index, data->gateway);
360 err = remove_gateway(data);
362 /* with vpn this will be called after the network was deleted,
363 * we need to call set_default here because we will not recieve any
364 * gateway delete notification.
365 * We hit the same issue if remove_gateway() fails.
367 if (set_default || err < 0) {
368 data = find_default_gateway();
370 set_default_gateway(data);
374 static struct connman_driver connection_driver = {
375 .name = "connection",
376 .type = CONNMAN_ELEMENT_TYPE_CONNECTION,
377 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
378 .probe = connection_probe,
379 .remove = connection_remove,
382 int __connman_connection_init(void)
386 if (connman_rtnl_register(&connection_rtnl) < 0)
387 connman_error("Failed to setup RTNL gateway driver");
389 return connman_driver_register(&connection_driver);
392 void __connman_connection_cleanup(void)
398 connman_driver_unregister(&connection_driver);
400 connman_rtnl_unregister(&connection_rtnl);
402 for (list = gateway_list; list; list = list->next) {
403 struct gateway_data *data = list->data;
405 DBG("index %d gateway %s", data->index, data->gateway);
407 g_free(data->gateway);
412 g_slist_free(gateway_list);
416 static void update_order(void)
420 for (list = gateway_list; list; list = list->next) {
421 struct gateway_data *data = list->data;
422 struct connman_service *service;
424 /* vpn gataway is not attached to a service. */
428 service = __connman_element_get_service(data->element);
429 data->order = __connman_service_get_order(service);
433 gboolean __connman_connection_update_gateway(void)
435 struct gateway_data *active_gateway, *default_gateway;
436 gboolean updated = FALSE;
440 active_gateway = find_active_gateway();
441 default_gateway = find_default_gateway();
443 if (active_gateway && active_gateway != default_gateway) {
444 del_routes(active_gateway);