5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * Copyright (C) 2011 BMW Car IT GmbH. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 struct gateway_config {
48 struct connman_service *service;
50 struct gateway_config *ipv4_gateway;
51 struct gateway_config *ipv6_gateway;
52 connman_bool_t default_checked;
55 static GHashTable *gateway_hash = NULL;
57 static struct gateway_config *find_gateway(int index, const char *gateway)
65 g_hash_table_iter_init(&iter, gateway_hash);
67 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
68 struct gateway_data *data = value;
70 if (data->ipv4_gateway != NULL && data->index == index &&
71 g_str_equal(data->ipv4_gateway->gateway,
73 return data->ipv4_gateway;
75 if (data->ipv6_gateway != NULL && data->index == index &&
76 g_str_equal(data->ipv6_gateway->gateway,
78 return data->ipv6_gateway;
84 static struct gateway_data *lookup_gateway_data(struct gateway_config *config)
92 g_hash_table_iter_init(&iter, gateway_hash);
94 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
95 struct gateway_data *data = value;
97 if (data->ipv4_gateway != NULL &&
98 data->ipv4_gateway == config)
101 if (data->ipv6_gateway != NULL &&
102 data->ipv6_gateway == config)
110 * Find the gateway that is serving the VPN link
112 static struct gateway_data *find_phy_gateway(int index, const char *gateway)
120 g_hash_table_iter_init(&iter, gateway_hash);
122 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
123 struct gateway_data *data = value;
125 if (data->ipv4_gateway != NULL && data->index != index &&
126 g_str_equal(data->ipv4_gateway->gateway,
130 if (data->ipv6_gateway != NULL && data->index != index &&
131 g_str_equal(data->ipv6_gateway->gateway,
139 static void set_vpn_routes(struct gateway_config *config,
140 struct connman_service *service,
142 enum connman_ipconfig_type type,
145 struct gateway_data *data;
146 struct connman_ipconfig *ipconfig;
151 config->vpn_ip = g_strdup(peer);
152 else if (gateway != NULL)
153 config->vpn_ip = g_strdup(gateway);
155 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
156 ipconfig = __connman_service_get_ip4config(service);
157 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
158 ipconfig = __connman_service_get_ip6config(service);
162 index = __connman_ipconfig_get_index(ipconfig);
163 data = find_phy_gateway(index, gateway);
167 * data->service points now to original
168 * service that is serving the VPN link
170 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
172 __connman_service_get_ip4config(data->service);
173 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
175 __connman_service_get_ip6config(data->service);
179 if (ipconfig != NULL) {
182 address = __connman_ipconfig_get_local(ipconfig);
183 config->vpn_phy_ip = g_strdup(address);
186 config->vpn_phy_index = data->index;
189 DBG("vpn %s phy %s index %d", config->vpn_ip,
190 config->vpn_phy_ip, config->vpn_phy_index);
193 static int del_routes(struct gateway_data *data,
194 enum connman_ipconfig_type type)
196 int status4 = 0, status6 = 0;
197 int do_ipv4 = FALSE, do_ipv6 = FALSE;
199 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
201 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
204 do_ipv4 = do_ipv6 = TRUE;
206 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) {
207 if (data->ipv4_gateway->vpn == TRUE) {
208 status4 = connman_inet_clear_gateway_address(
210 data->ipv4_gateway->vpn_ip);
212 } else if (g_strcmp0(data->ipv4_gateway->gateway,
214 status4 = connman_inet_clear_gateway_interface(
217 connman_inet_del_host_route(data->index,
218 data->ipv4_gateway->gateway);
219 status4 = connman_inet_clear_gateway_address(
221 data->ipv4_gateway->gateway);
225 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) {
226 if (data->ipv6_gateway->vpn == TRUE) {
227 status6 = connman_inet_clear_ipv6_gateway_address(
229 data->ipv6_gateway->vpn_ip);
231 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
232 status6 = connman_inet_clear_ipv6_gateway_interface(
235 connman_inet_del_ipv6_host_route(data->index,
236 data->ipv6_gateway->gateway);
237 status6 = connman_inet_clear_ipv6_gateway_address(
239 data->ipv6_gateway->gateway);
243 return (status4 < 0 ? status4 : status6);
246 static int disable_gateway(struct gateway_data *data,
247 enum connman_ipconfig_type type)
249 gboolean active = FALSE;
251 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
252 if (data->ipv4_gateway != NULL)
253 active = data->ipv4_gateway->active;
254 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
255 if (data->ipv6_gateway != NULL)
256 active = data->ipv6_gateway->active;
260 DBG("type %d active %d", type, active);
263 return del_routes(data, type);
268 static struct gateway_data *add_gateway(struct connman_service *service,
269 int index, const char *gateway,
270 enum connman_ipconfig_type type)
272 struct gateway_data *data, *old;
273 struct gateway_config *config;
275 if (gateway == NULL || strlen(gateway) == 0)
278 data = g_try_new0(struct gateway_data, 1);
284 config = g_try_new0(struct gateway_config, 1);
285 if (config == NULL) {
290 config->gateway = g_strdup(gateway);
291 config->vpn_ip = NULL;
292 config->vpn_phy_ip = NULL;
294 config->vpn_phy_index = -1;
295 config->active = FALSE;
297 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
298 data->ipv4_gateway = config;
299 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
300 data->ipv6_gateway = config;
302 g_free(config->gateway);
308 data->service = service;
310 data->order = __connman_service_get_order(service);
313 * If the service is already in the hash, then we
314 * must not replace it blindly but disable the gateway
315 * of the type we are replacing and take the other type
316 * from old gateway settings.
318 old = g_hash_table_lookup(gateway_hash, service);
320 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
321 old->ipv4_gateway, old->ipv6_gateway);
322 disable_gateway(old, type);
323 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
324 data->ipv6_gateway = old->ipv6_gateway;
325 old->ipv6_gateway = NULL;
326 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
327 data->ipv4_gateway = old->ipv4_gateway;
328 old->ipv4_gateway = NULL;
332 * Only take a ref if we are adding new stuff to hash.
334 connman_service_ref(service);
337 g_hash_table_replace(gateway_hash, service, data);
342 static void set_default_gateway(struct gateway_data *data,
343 enum connman_ipconfig_type type)
346 int status4 = 0, status6 = 0;
347 int do_ipv4 = FALSE, do_ipv6 = FALSE;
349 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
351 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
354 do_ipv4 = do_ipv6 = TRUE;
356 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
359 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
360 data->ipv4_gateway->vpn == TRUE) {
361 connman_inet_set_gateway_address(data->index,
362 data->ipv4_gateway->vpn_ip);
363 connman_inet_add_host_route(data->index,
364 data->ipv4_gateway->vpn_ip, NULL);
365 data->ipv4_gateway->active = TRUE;
367 DBG("set %p index %d vpn %s index %d phy %s",
368 data, data->index, data->ipv4_gateway->vpn_ip,
369 data->ipv4_gateway->vpn_phy_index,
370 data->ipv4_gateway->vpn_phy_ip);
372 __connman_service_indicate_default(data->service);
377 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
378 data->ipv6_gateway->vpn == TRUE) {
379 connman_inet_set_ipv6_gateway_address(data->index,
380 data->ipv6_gateway->vpn_ip);
381 connman_inet_add_ipv6_host_route(data->index,
382 data->ipv6_gateway->vpn_ip, NULL);
383 data->ipv6_gateway->active = TRUE;
385 DBG("set %p index %d vpn %s index %d phy %s",
386 data, data->index, data->ipv6_gateway->vpn_ip,
387 data->ipv6_gateway->vpn_phy_index,
388 data->ipv6_gateway->vpn_phy_ip);
390 __connman_service_indicate_default(data->service);
395 index = __connman_service_get_index(data->service);
397 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
398 g_strcmp0(data->ipv4_gateway->gateway,
400 if (connman_inet_set_gateway_interface(index) < 0)
405 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
406 g_strcmp0(data->ipv6_gateway->gateway,
408 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
413 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
414 status6 = connman_inet_set_ipv6_gateway_address(index,
415 data->ipv6_gateway->gateway);
417 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
418 status4 = connman_inet_set_gateway_address(index,
419 data->ipv4_gateway->gateway);
421 if (status4 < 0 || status6 < 0)
425 __connman_service_indicate_default(data->service);
428 static void unset_default_gateway(struct gateway_data *data,
429 enum connman_ipconfig_type type)
432 int do_ipv4 = FALSE, do_ipv6 = FALSE;
434 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
436 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
439 do_ipv4 = do_ipv6 = TRUE;
441 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
444 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
445 data->ipv4_gateway->vpn == TRUE) {
446 connman_inet_del_host_route(data->index,
447 data->ipv4_gateway->vpn_ip);
448 connman_inet_clear_gateway_address(data->index,
449 data->ipv4_gateway->vpn_ip);
450 data->ipv4_gateway->active = FALSE;
452 DBG("unset %p index %d vpn %s index %d phy %s",
453 data, data->index, data->ipv4_gateway->vpn_ip,
454 data->ipv4_gateway->vpn_phy_index,
455 data->ipv4_gateway->vpn_phy_ip);
460 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
461 data->ipv6_gateway->vpn == TRUE) {
462 connman_inet_del_ipv6_host_route(data->index,
463 data->ipv6_gateway->vpn_ip);
464 connman_inet_clear_ipv6_gateway_address(data->index,
465 data->ipv6_gateway->vpn_ip);
466 data->ipv6_gateway->active = FALSE;
468 DBG("unset %p index %d vpn %s index %d phy %s",
469 data, data->index, data->ipv6_gateway->vpn_ip,
470 data->ipv6_gateway->vpn_phy_index,
471 data->ipv6_gateway->vpn_phy_ip);
476 index = __connman_service_get_index(data->service);
478 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
479 g_strcmp0(data->ipv4_gateway->gateway,
481 connman_inet_clear_gateway_interface(index);
485 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
486 g_strcmp0(data->ipv6_gateway->gateway,
488 connman_inet_clear_ipv6_gateway_interface(index);
492 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
493 connman_inet_clear_ipv6_gateway_address(index,
494 data->ipv6_gateway->gateway);
496 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
497 connman_inet_clear_gateway_address(index,
498 data->ipv4_gateway->gateway);
501 static struct gateway_data *find_default_gateway(void)
503 struct gateway_data *found = NULL;
504 unsigned int order = 0;
508 g_hash_table_iter_init(&iter, gateway_hash);
510 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
511 struct gateway_data *data = value;
513 if (found == NULL || data->order > order) {
517 DBG("default %p order %d", found, order);
524 static gboolean choose_default_gateway(struct gateway_data *data,
525 struct gateway_data *candidate)
527 gboolean downgraded = FALSE;
530 * If the current default is not active, then we mark
531 * this one as default. If the other one is already active
532 * we mark this one as non default.
534 if (data->ipv4_gateway != NULL) {
535 if (candidate->ipv4_gateway != NULL &&
536 candidate->ipv4_gateway->active == FALSE) {
537 DBG("ipv4 downgrading %p", candidate);
538 unset_default_gateway(candidate,
539 CONNMAN_IPCONFIG_TYPE_IPV4);
541 if (candidate->ipv4_gateway != NULL &&
542 candidate->ipv4_gateway->active == TRUE &&
543 candidate->order > data->order) {
544 DBG("ipv4 downgrading this %p", data);
545 unset_default_gateway(data,
546 CONNMAN_IPCONFIG_TYPE_IPV4);
551 if (data->ipv6_gateway != NULL) {
552 if (candidate->ipv6_gateway != NULL &&
553 candidate->ipv6_gateway->active == FALSE) {
554 DBG("ipv6 downgrading %p", candidate);
555 unset_default_gateway(candidate,
556 CONNMAN_IPCONFIG_TYPE_IPV6);
559 if (candidate->ipv6_gateway != NULL &&
560 candidate->ipv6_gateway->active == TRUE &&
561 candidate->order > data->order) {
562 DBG("ipv6 downgrading this %p", data);
563 unset_default_gateway(data,
564 CONNMAN_IPCONFIG_TYPE_IPV6);
572 static void connection_newgateway(int index, const char *gateway)
574 struct gateway_config *config;
575 struct gateway_data *data;
578 gboolean found = FALSE;
580 DBG("index %d gateway %s", index, gateway);
582 config = find_gateway(index, gateway);
586 config->active = TRUE;
589 * It is possible that we have two default routes atm
590 * if there are two gateways waiting rtnl activation at the
593 data = lookup_gateway_data(config);
597 if (data->default_checked == TRUE)
601 * The next checks are only done once, otherwise setting
602 * the default gateway could lead into rtnl forever loop.
605 g_hash_table_iter_init(&iter, gateway_hash);
607 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
608 struct gateway_data *candidate = value;
610 if (candidate == data)
613 found = choose_default_gateway(data, candidate);
618 if (found == FALSE) {
619 if (data->ipv4_gateway != NULL)
620 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
622 if (data->ipv6_gateway != NULL)
623 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
626 data->default_checked = TRUE;
629 static void remove_gateway(gpointer user_data)
631 struct gateway_data *data = user_data;
633 DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
635 if (data->ipv4_gateway != NULL) {
636 g_free(data->ipv4_gateway->gateway);
637 g_free(data->ipv4_gateway->vpn_ip);
638 g_free(data->ipv4_gateway->vpn_phy_ip);
639 g_free(data->ipv4_gateway);
642 if (data->ipv6_gateway != NULL) {
643 g_free(data->ipv6_gateway->gateway);
644 g_free(data->ipv6_gateway->vpn_ip);
645 g_free(data->ipv6_gateway->vpn_phy_ip);
646 g_free(data->ipv6_gateway);
652 static void connection_delgateway(int index, const char *gateway)
654 struct gateway_config *config;
655 struct gateway_data *data;
657 DBG("index %d gateway %s", index, gateway);
659 config = find_gateway(index, gateway);
661 config->active = FALSE;
663 data = find_default_gateway();
665 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
668 static struct connman_rtnl connection_rtnl = {
669 .name = "connection",
670 .newgateway = connection_newgateway,
671 .delgateway = connection_delgateway,
674 static struct gateway_data *find_active_gateway(void)
681 g_hash_table_iter_init(&iter, gateway_hash);
683 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
684 struct gateway_data *data = value;
686 if (data->ipv4_gateway != NULL &&
687 data->ipv4_gateway->active == TRUE)
690 if (data->ipv6_gateway != NULL &&
691 data->ipv6_gateway->active == TRUE)
698 static void update_order(void)
705 g_hash_table_iter_init(&iter, gateway_hash);
707 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
708 struct gateway_data *data = value;
710 data->order = __connman_service_get_order(data->service);
714 void __connman_connection_gateway_activate(struct connman_service *service,
715 enum connman_ipconfig_type type)
717 struct gateway_data *data = NULL;
719 data = g_hash_table_lookup(gateway_hash, service);
723 DBG("gateway %p/%p type %d", data->ipv4_gateway,
724 data->ipv6_gateway, type);
726 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
727 data->ipv4_gateway->active = TRUE;
728 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
729 data->ipv6_gateway->active = TRUE;
732 static void add_host_route(int family, int index, const char *gateway,
733 enum connman_service_type service_type)
737 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
739 * We must not set route to the phy dev gateway in
740 * VPN link. The packets to VPN link might be routed
741 * back to itself and not routed into phy link gateway.
743 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
744 connman_inet_add_host_route(index, gateway,
748 * Add host route to P-t-P link so that services can
749 * be moved around and we can have some link to P-t-P
750 * network (although those P-t-P links have limited
751 * usage if default route is not directed to them)
754 if (connman_inet_get_dest_addr(index, &dest) == 0) {
755 connman_inet_add_host_route(index, dest, NULL);
762 if (g_strcmp0(gateway, "::") != 0) {
763 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
764 connman_inet_add_ipv6_host_route(index,
767 /* P-t-P link, add route to destination */
769 if (connman_inet_ipv6_get_dest_addr(index,
771 connman_inet_add_ipv6_host_route(index, dest,
780 int __connman_connection_gateway_add(struct connman_service *service,
782 enum connman_ipconfig_type type,
785 struct gateway_data *active_gateway = NULL;
786 struct gateway_data *new_gateway = NULL;
787 enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
788 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
789 enum connman_service_type service_type =
790 connman_service_get_type(service);
793 index = __connman_service_get_index(service);
796 * If gateway is NULL, it's a point to point link and the default
797 * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
800 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
803 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
806 DBG("service %p index %d gateway %s vpn ip %s type %d",
807 service, index, gateway, peer, type);
809 new_gateway = add_gateway(service, index, gateway, type);
810 if (new_gateway == NULL)
813 active_gateway = find_active_gateway();
815 DBG("active %p index %d new %p", active_gateway,
816 active_gateway ? active_gateway->index : -1, new_gateway);
818 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
819 new_gateway->ipv4_gateway != NULL) {
820 add_host_route(AF_INET, index, gateway, service_type);
821 __connman_service_nameserver_add_routes(service,
822 new_gateway->ipv4_gateway->gateway);
823 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
826 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
827 new_gateway->ipv6_gateway != NULL) {
828 add_host_route(AF_INET6, index, gateway, service_type);
829 __connman_service_nameserver_add_routes(service,
830 new_gateway->ipv6_gateway->gateway);
831 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
834 if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
835 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
836 new_gateway->ipv4_gateway != NULL)
837 set_vpn_routes(new_gateway->ipv4_gateway,
838 service, gateway, type, peer);
840 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
841 new_gateway->ipv6_gateway != NULL)
842 set_vpn_routes(new_gateway->ipv6_gateway,
843 service, gateway, type, peer);
846 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
847 new_gateway->ipv4_gateway != NULL)
848 new_gateway->ipv4_gateway->vpn = FALSE;
850 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
851 new_gateway->ipv6_gateway != NULL)
852 new_gateway->ipv6_gateway->vpn = FALSE;
855 if (active_gateway == NULL) {
856 set_default_gateway(new_gateway, type);
860 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
861 new_gateway->ipv4_gateway != NULL &&
862 new_gateway->ipv4_gateway->vpn == TRUE) {
863 if (__connman_service_is_split_routing(new_gateway->service) ==
865 connman_inet_clear_gateway_address(
866 active_gateway->index,
867 active_gateway->ipv4_gateway->gateway);
870 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
871 new_gateway->ipv6_gateway != NULL &&
872 new_gateway->ipv6_gateway->vpn == TRUE) {
873 if (__connman_service_is_split_routing(new_gateway->service) ==
875 connman_inet_clear_ipv6_gateway_address(
876 active_gateway->index,
877 active_gateway->ipv6_gateway->gateway);
881 if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
882 __connman_service_ipconfig_indicate_state(service,
883 CONNMAN_SERVICE_STATE_READY,
884 CONNMAN_IPCONFIG_TYPE_IPV4);
886 if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
887 __connman_service_ipconfig_indicate_state(service,
888 CONNMAN_SERVICE_STATE_READY,
889 CONNMAN_IPCONFIG_TYPE_IPV6);
893 void __connman_connection_gateway_remove(struct connman_service *service,
894 enum connman_ipconfig_type type)
896 struct gateway_data *data = NULL;
897 gboolean set_default4 = FALSE, set_default6 = FALSE;
898 int do_ipv4 = FALSE, do_ipv6 = FALSE;
901 DBG("service %p type %d", service, type);
903 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
905 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
908 do_ipv4 = do_ipv6 = TRUE;
910 __connman_service_nameserver_del_routes(service, type);
912 data = g_hash_table_lookup(gateway_hash, service);
916 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
917 set_default4 = data->ipv4_gateway->vpn;
919 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
920 set_default6 = data->ipv6_gateway->vpn;
922 DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
923 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
924 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
925 set_default4, set_default6);
927 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
928 data->ipv4_gateway->vpn == TRUE && data->index >= 0)
929 connman_inet_del_host_route(data->index,
930 data->ipv4_gateway->gateway);
932 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
933 data->ipv6_gateway->vpn == TRUE && data->index >= 0)
934 connman_inet_del_ipv6_host_route(data->index,
935 data->ipv6_gateway->gateway);
937 err = disable_gateway(data, type);
940 * We remove the service from the hash only if all the gateway
941 * settings are to be removed.
943 if (do_ipv4 == do_ipv6 ||
944 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
945 && do_ipv4 == TRUE) ||
946 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
949 connman_service_unref(service);
950 g_hash_table_remove(gateway_hash, service);
952 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
953 data->ipv4_gateway, do_ipv4,
954 data->ipv6_gateway, do_ipv6);
956 /* with vpn this will be called after the network was deleted,
957 * we need to call set_default here because we will not recieve any
958 * gateway delete notification.
959 * We hit the same issue if remove_gateway() fails.
961 if (set_default4 || set_default6 || err < 0) {
962 data = find_default_gateway();
964 set_default_gateway(data, type);
968 gboolean __connman_connection_update_gateway(void)
970 struct gateway_data *default_gateway;
971 gboolean updated = FALSE;
975 if (gateway_hash == NULL)
980 default_gateway = find_default_gateway();
982 __connman_service_update_ordering();
984 DBG("default %p", default_gateway);
987 * There can be multiple active gateways so we need to
990 g_hash_table_iter_init(&iter, gateway_hash);
992 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
993 struct gateway_data *active_gateway = value;
995 if (active_gateway == default_gateway)
998 if (active_gateway->ipv4_gateway != NULL &&
999 active_gateway->ipv4_gateway->active == TRUE) {
1001 unset_default_gateway(active_gateway,
1002 CONNMAN_IPCONFIG_TYPE_IPV4);
1006 if (active_gateway->ipv6_gateway != NULL &&
1007 active_gateway->ipv6_gateway->active == TRUE) {
1009 unset_default_gateway(active_gateway,
1010 CONNMAN_IPCONFIG_TYPE_IPV6);
1015 if (updated && default_gateway != NULL) {
1016 if (default_gateway->ipv4_gateway)
1017 set_default_gateway(default_gateway,
1018 CONNMAN_IPCONFIG_TYPE_IPV4);
1020 if (default_gateway->ipv6_gateway)
1021 set_default_gateway(default_gateway,
1022 CONNMAN_IPCONFIG_TYPE_IPV6);
1028 int __connman_connection_get_vpn_index(int phy_index)
1030 GHashTableIter iter;
1031 gpointer value, key;
1033 g_hash_table_iter_init(&iter, gateway_hash);
1035 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1036 struct gateway_data *data = value;
1038 if (data->ipv4_gateway != NULL &&
1039 data->ipv4_gateway->vpn_phy_index == phy_index)
1042 if (data->ipv6_gateway != NULL &&
1043 data->ipv6_gateway->vpn_phy_index == phy_index)
1050 int __connman_connection_init(void)
1056 gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1057 NULL, remove_gateway);
1059 err = connman_rtnl_register(&connection_rtnl);
1061 connman_error("Failed to setup RTNL gateway driver");
1066 void __connman_connection_cleanup(void)
1068 GHashTableIter iter;
1069 gpointer value, key;
1073 connman_rtnl_unregister(&connection_rtnl);
1075 g_hash_table_iter_init(&iter, gateway_hash);
1077 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1078 struct gateway_data *data = value;
1080 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1083 g_hash_table_destroy(gateway_hash);
1084 gateway_hash = NULL;