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
35 struct connman_element *element;
43 static GSList *gateway_list = NULL;
45 static struct gateway_data *find_gateway(int index, const char *gateway)
52 for (list = gateway_list; list; list = list->next) {
53 struct gateway_data *data = list->data;
55 if (data->gateway == NULL)
58 if (data->index == index &&
59 g_str_equal(data->gateway, gateway) == TRUE)
66 static int del_routes(struct gateway_data *data)
70 connman_inet_del_host_route(data->index, data->gateway);
73 address = data->vpn_ip;
75 address = data->gateway;
77 return connman_inet_clear_gateway_address(data->index, address);
80 static void find_element(struct connman_element *element, gpointer user_data)
82 struct gateway_data *data = user_data;
84 DBG("element %p name %s", element, element->name);
86 if (data->element != NULL)
89 if (element->index != data->index)
92 data->element = element;
95 static struct gateway_data *add_gateway(int index, const char *gateway)
97 struct gateway_data *data;
98 struct connman_service *service;
100 data = g_try_new0(struct gateway_data, 1);
105 data->gateway = g_strdup(gateway);
106 data->active = FALSE;
107 data->element = NULL;
111 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION,
114 service = __connman_element_get_service(data->element);
115 data->order = __connman_service_get_order(service);
117 gateway_list = g_slist_append(gateway_list, data);
122 static void connection_newgateway(int index, const char *gateway)
124 struct gateway_data *data;
126 DBG("index %d gateway %s", index, gateway);
128 data = find_gateway(index, gateway);
135 static void set_default_gateway(struct gateway_data *data)
137 struct connman_element *element = data->element;
138 struct connman_service *service = NULL;
141 DBG("gateway %s", data->gateway);
143 if (data->vpn == TRUE) {
144 connman_inet_set_gateway_address(data->index, data->vpn_ip);
146 /* vpn gateway going away no changes in services */
150 ifflags = connman_inet_ifflags(element->index);
152 connman_error("Fail to get network interface flags");
156 if (ifflags & IFF_POINTOPOINT) {
157 if (connman_inet_set_gateway_interface(element->index) < 0)
162 connman_inet_add_host_route(element->index, data->gateway);
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 void remove_gateway(struct gateway_data *data)
192 DBG("gateway %s", data->gateway);
194 gateway_list = g_slist_remove(gateway_list, data);
196 if (data->active == TRUE)
199 g_free(data->gateway);
200 g_free(data->vpn_ip);
204 static void connection_delgateway(int index, const char *gateway)
206 struct gateway_data *data;
208 DBG("index %d gateway %s", index, gateway);
210 data = find_gateway(index, gateway);
212 data->active = FALSE;
214 data = find_default_gateway();
216 set_default_gateway(data);
219 static struct connman_rtnl connection_rtnl = {
220 .name = "connection",
221 .newgateway = connection_newgateway,
222 .delgateway = connection_delgateway,
225 static struct gateway_data *find_active_gateway(void)
231 for (list = gateway_list; list; list = list->next) {
232 struct gateway_data *data = list->data;
233 if (data->active == TRUE)
240 static int connection_probe(struct connman_element *element)
242 struct connman_service *service = NULL;
243 const char *gateway = NULL;
244 const char *vpn_ip = NULL;
245 struct gateway_data *active_gateway = NULL;
246 struct gateway_data *new_gateway = NULL;
248 DBG("element %p name %s", element, element->name);
250 if (element->parent == NULL)
253 /* FIXME: Remove temporarily for the static gateway support */
254 /* if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
257 connman_element_get_value(element,
258 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
260 connman_element_get_value(element,
261 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &vpn_ip);
263 DBG("gateway %s", gateway);
265 service = __connman_element_get_service(element);
266 __connman_service_indicate_state(service,
267 CONNMAN_SERVICE_STATE_READY);
269 connman_element_set_enabled(element, TRUE);
274 active_gateway = find_active_gateway();
275 new_gateway = add_gateway(element->index, gateway);
277 if (service == NULL) {
278 new_gateway->vpn = TRUE;
279 new_gateway->vpn_ip = g_strdup(vpn_ip);
280 /* make sure vpn gateway are at higher priority */
281 new_gateway->order = 10;
283 new_gateway->vpn = FALSE;
285 if (active_gateway == NULL) {
286 set_default_gateway(new_gateway);
290 if (new_gateway->vpn == TRUE) {
291 connman_inet_add_host_route_vpn(active_gateway->index,
292 active_gateway->gateway,
293 new_gateway->gateway);
295 connman_inet_set_gateway_address(new_gateway->index,
296 new_gateway->gateway);
299 if (new_gateway->order >= active_gateway->order) {
300 del_routes(active_gateway);
307 static void connection_remove(struct connman_element *element)
309 struct connman_service *service;
310 const char *gateway = NULL;
311 struct gateway_data *data = NULL;
312 gboolean set_default = FALSE;
314 DBG("element %p name %s", element, element->name);
316 service = __connman_element_get_service(element);
317 __connman_service_indicate_state(service,
318 CONNMAN_SERVICE_STATE_DISCONNECT);
320 connman_element_set_enabled(element, FALSE);
322 connman_element_get_value(element,
323 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
325 DBG("gateway %s", gateway);
330 data = find_gateway(element->index, gateway);
334 set_default = data->vpn;
336 if (data->vpn == TRUE)
337 connman_inet_del_host_route(data->index, data->gateway);
339 remove_gateway(data);
341 /* with vpn this will be called after the network was deleted,
342 * we need to call set_default here because we will not recieve any
343 * gateway delete notification.
346 data = find_default_gateway();
348 set_default_gateway(data);
352 static struct connman_driver connection_driver = {
353 .name = "connection",
354 .type = CONNMAN_ELEMENT_TYPE_CONNECTION,
355 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
356 .probe = connection_probe,
357 .remove = connection_remove,
360 int __connman_connection_init(void)
364 if (connman_rtnl_register(&connection_rtnl) < 0)
365 connman_error("Failed to setup RTNL gateway driver");
367 return connman_driver_register(&connection_driver);
370 void __connman_connection_cleanup(void)
376 connman_driver_unregister(&connection_driver);
378 connman_rtnl_unregister(&connection_rtnl);
380 for (list = gateway_list; list; list = list->next) {
381 struct gateway_data *data = list->data;
383 DBG("index %d gateway %s", data->index, data->gateway);
385 g_free(data->gateway);
390 g_slist_free(gateway_list);
394 static void update_order(void)
398 for (list = gateway_list; list; list = list->next) {
399 struct gateway_data *data = list->data;
400 struct connman_service *service;
402 /* vpn gataway is not attached to a service. */
406 service = __connman_element_get_service(data->element);
407 data->order = __connman_service_get_order(service);
411 gboolean __connman_connection_update_gateway(void)
413 struct gateway_data *active_gateway, *default_gateway;
414 gboolean updated = FALSE;
418 active_gateway = find_active_gateway();
419 default_gateway = find_default_gateway();
421 if (active_gateway && active_gateway != default_gateway) {
422 del_routes(active_gateway);