5 * Copyright (C) 2007-2012 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_data *new_gateway,
140 struct connman_service *service,
142 enum connman_ipconfig_type type,
144 struct gateway_data *active_gateway)
146 struct gateway_config *config;
147 struct gateway_data *data;
148 struct connman_ipconfig *ipconfig;
152 DBG("new %p service %p gw %s type %d peer %s active %p",
153 new_gateway, service, gateway, type, peer, active_gateway);
155 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
156 ipconfig = __connman_service_get_ip4config(service);
157 config = new_gateway->ipv4_gateway;
158 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
159 ipconfig = __connman_service_get_ip6config(service);
160 config = new_gateway->ipv6_gateway;
169 config->vpn_ip = g_strdup(peer);
170 else if (gateway != NULL)
171 config->vpn_ip = g_strdup(gateway);
173 index = __connman_ipconfig_get_index(ipconfig);
174 data = find_phy_gateway(index, gateway);
180 * data->service points now to original
181 * service that is serving the VPN link
183 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
184 ipconfig = __connman_service_get_ip4config(data->service);
185 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
186 ipconfig = __connman_service_get_ip6config(data->service);
190 if (ipconfig != NULL) {
193 address = __connman_ipconfig_get_local(ipconfig);
194 config->vpn_phy_ip = g_strdup(address);
197 config->vpn_phy_index = data->index;
199 DBG("vpn %s phy %s index %d", config->vpn_ip,
200 config->vpn_phy_ip, config->vpn_phy_index);
203 if (active_gateway == NULL)
206 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
208 * Special route to VPN server via gateway. This
209 * is needed so that we can access hosts behind
210 * the VPN. The route might already exist depending
211 * on network topology.
213 if (active_gateway->ipv4_gateway == NULL)
216 DBG("active gw %s", active_gateway->ipv4_gateway->gateway);
218 if (g_strcmp0(active_gateway->ipv4_gateway->gateway,
220 dest = active_gateway->ipv4_gateway->gateway;
224 connman_inet_add_host_route(active_gateway->index, gateway,
227 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
229 if (active_gateway->ipv6_gateway == NULL)
232 DBG("active gw %s", active_gateway->ipv6_gateway->gateway);
234 if (g_strcmp0(active_gateway->ipv6_gateway->gateway,
236 dest = active_gateway->ipv6_gateway->gateway;
240 connman_inet_add_ipv6_host_route(active_gateway->index,
245 static int del_routes(struct gateway_data *data,
246 enum connman_ipconfig_type type)
248 int status4 = 0, status6 = 0;
249 int do_ipv4 = FALSE, do_ipv6 = FALSE;
251 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
253 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
256 do_ipv4 = do_ipv6 = TRUE;
258 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) {
259 if (data->ipv4_gateway->vpn == TRUE) {
260 status4 = connman_inet_clear_gateway_address(
262 data->ipv4_gateway->vpn_ip);
264 } else if (g_strcmp0(data->ipv4_gateway->gateway,
266 status4 = connman_inet_clear_gateway_interface(
269 connman_inet_del_host_route(data->index,
270 data->ipv4_gateway->gateway);
271 status4 = connman_inet_clear_gateway_address(
273 data->ipv4_gateway->gateway);
277 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) {
278 if (data->ipv6_gateway->vpn == TRUE) {
279 status6 = connman_inet_clear_ipv6_gateway_address(
281 data->ipv6_gateway->vpn_ip);
283 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
284 status6 = connman_inet_clear_ipv6_gateway_interface(
287 connman_inet_del_ipv6_host_route(data->index,
288 data->ipv6_gateway->gateway);
289 status6 = connman_inet_clear_ipv6_gateway_address(
291 data->ipv6_gateway->gateway);
295 return (status4 < 0 ? status4 : status6);
298 static int disable_gateway(struct gateway_data *data,
299 enum connman_ipconfig_type type)
301 gboolean active = FALSE;
303 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
304 if (data->ipv4_gateway != NULL)
305 active = data->ipv4_gateway->active;
306 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
307 if (data->ipv6_gateway != NULL)
308 active = data->ipv6_gateway->active;
312 DBG("type %d active %d", type, active);
315 return del_routes(data, type);
320 static struct gateway_data *add_gateway(struct connman_service *service,
321 int index, const char *gateway,
322 enum connman_ipconfig_type type)
324 struct gateway_data *data, *old;
325 struct gateway_config *config;
327 if (gateway == NULL || strlen(gateway) == 0)
330 data = g_try_new0(struct gateway_data, 1);
336 config = g_try_new0(struct gateway_config, 1);
337 if (config == NULL) {
342 config->gateway = g_strdup(gateway);
343 config->vpn_ip = NULL;
344 config->vpn_phy_ip = NULL;
346 config->vpn_phy_index = -1;
347 config->active = FALSE;
349 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
350 data->ipv4_gateway = config;
351 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
352 data->ipv6_gateway = config;
354 g_free(config->gateway);
360 data->service = service;
362 data->order = __connman_service_get_order(service);
365 * If the service is already in the hash, then we
366 * must not replace it blindly but disable the gateway
367 * of the type we are replacing and take the other type
368 * from old gateway settings.
370 old = g_hash_table_lookup(gateway_hash, service);
372 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
373 old->ipv4_gateway, old->ipv6_gateway);
374 disable_gateway(old, type);
375 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
376 data->ipv6_gateway = old->ipv6_gateway;
377 old->ipv6_gateway = NULL;
378 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
379 data->ipv4_gateway = old->ipv4_gateway;
380 old->ipv4_gateway = NULL;
384 * Only take a ref if we are adding new stuff to hash.
386 connman_service_ref(service);
389 g_hash_table_replace(gateway_hash, service, data);
394 static void set_default_gateway(struct gateway_data *data,
395 enum connman_ipconfig_type type)
398 int status4 = 0, status6 = 0;
399 int do_ipv4 = FALSE, do_ipv6 = FALSE;
401 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
403 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
406 do_ipv4 = do_ipv6 = TRUE;
408 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
411 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
412 data->ipv4_gateway->vpn == TRUE) {
413 connman_inet_set_gateway_interface(data->index);
414 data->ipv4_gateway->active = TRUE;
416 DBG("set %p index %d vpn %s index %d phy %s",
417 data, data->index, data->ipv4_gateway->vpn_ip,
418 data->ipv4_gateway->vpn_phy_index,
419 data->ipv4_gateway->vpn_phy_ip);
421 __connman_service_indicate_default(data->service);
426 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
427 data->ipv6_gateway->vpn == TRUE) {
428 connman_inet_set_ipv6_gateway_interface(data->index);
429 data->ipv6_gateway->active = TRUE;
431 DBG("set %p index %d vpn %s index %d phy %s",
432 data, data->index, data->ipv6_gateway->vpn_ip,
433 data->ipv6_gateway->vpn_phy_index,
434 data->ipv6_gateway->vpn_phy_ip);
436 __connman_service_indicate_default(data->service);
441 index = __connman_service_get_index(data->service);
443 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
444 g_strcmp0(data->ipv4_gateway->gateway,
446 if (connman_inet_set_gateway_interface(index) < 0)
451 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
452 g_strcmp0(data->ipv6_gateway->gateway,
454 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
459 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
460 status6 = connman_inet_set_ipv6_gateway_address(index,
461 data->ipv6_gateway->gateway);
463 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
464 status4 = connman_inet_set_gateway_address(index,
465 data->ipv4_gateway->gateway);
467 if (status4 < 0 || status6 < 0)
471 __connman_service_indicate_default(data->service);
474 static void unset_default_gateway(struct gateway_data *data,
475 enum connman_ipconfig_type type)
478 int do_ipv4 = FALSE, do_ipv6 = FALSE;
480 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
482 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
485 do_ipv4 = do_ipv6 = TRUE;
487 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
490 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
491 data->ipv4_gateway->vpn == TRUE) {
492 connman_inet_clear_gateway_interface(data->index);
493 data->ipv4_gateway->active = FALSE;
495 DBG("unset %p index %d vpn %s index %d phy %s",
496 data, data->index, data->ipv4_gateway->vpn_ip,
497 data->ipv4_gateway->vpn_phy_index,
498 data->ipv4_gateway->vpn_phy_ip);
503 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
504 data->ipv6_gateway->vpn == TRUE) {
505 connman_inet_clear_ipv6_gateway_interface(data->index);
506 data->ipv6_gateway->active = FALSE;
508 DBG("unset %p index %d vpn %s index %d phy %s",
509 data, data->index, data->ipv6_gateway->vpn_ip,
510 data->ipv6_gateway->vpn_phy_index,
511 data->ipv6_gateway->vpn_phy_ip);
516 index = __connman_service_get_index(data->service);
518 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
519 g_strcmp0(data->ipv4_gateway->gateway,
521 connman_inet_clear_gateway_interface(index);
525 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
526 g_strcmp0(data->ipv6_gateway->gateway,
528 connman_inet_clear_ipv6_gateway_interface(index);
532 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
533 connman_inet_clear_ipv6_gateway_address(index,
534 data->ipv6_gateway->gateway);
536 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
537 connman_inet_clear_gateway_address(index,
538 data->ipv4_gateway->gateway);
541 static struct gateway_data *find_default_gateway(void)
543 struct gateway_data *found = NULL;
544 unsigned int order = 0;
548 g_hash_table_iter_init(&iter, gateway_hash);
550 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
551 struct gateway_data *data = value;
553 if (found == NULL || data->order > order) {
557 DBG("default %p order %d", found, order);
564 static gboolean choose_default_gateway(struct gateway_data *data,
565 struct gateway_data *candidate)
567 gboolean downgraded = FALSE;
570 * If the current default is not active, then we mark
571 * this one as default. If the other one is already active
572 * we mark this one as non default.
574 if (data->ipv4_gateway != NULL) {
575 if (candidate->ipv4_gateway != NULL &&
576 candidate->ipv4_gateway->active == FALSE) {
577 DBG("ipv4 downgrading %p", candidate);
578 unset_default_gateway(candidate,
579 CONNMAN_IPCONFIG_TYPE_IPV4);
581 if (candidate->ipv4_gateway != NULL &&
582 candidate->ipv4_gateway->active == TRUE &&
583 candidate->order > data->order) {
584 DBG("ipv4 downgrading this %p", data);
585 unset_default_gateway(data,
586 CONNMAN_IPCONFIG_TYPE_IPV4);
591 if (data->ipv6_gateway != NULL) {
592 if (candidate->ipv6_gateway != NULL &&
593 candidate->ipv6_gateway->active == FALSE) {
594 DBG("ipv6 downgrading %p", candidate);
595 unset_default_gateway(candidate,
596 CONNMAN_IPCONFIG_TYPE_IPV6);
599 if (candidate->ipv6_gateway != NULL &&
600 candidate->ipv6_gateway->active == TRUE &&
601 candidate->order > data->order) {
602 DBG("ipv6 downgrading this %p", data);
603 unset_default_gateway(data,
604 CONNMAN_IPCONFIG_TYPE_IPV6);
612 static void connection_newgateway(int index, const char *gateway)
614 struct gateway_config *config;
615 struct gateway_data *data;
618 gboolean found = FALSE;
620 DBG("index %d gateway %s", index, gateway);
622 config = find_gateway(index, gateway);
626 config->active = TRUE;
629 * It is possible that we have two default routes atm
630 * if there are two gateways waiting rtnl activation at the
633 data = lookup_gateway_data(config);
637 if (data->default_checked == TRUE)
641 * The next checks are only done once, otherwise setting
642 * the default gateway could lead into rtnl forever loop.
645 g_hash_table_iter_init(&iter, gateway_hash);
647 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
648 struct gateway_data *candidate = value;
650 if (candidate == data)
653 found = choose_default_gateway(data, candidate);
658 if (found == FALSE) {
659 if (data->ipv4_gateway != NULL)
660 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
662 if (data->ipv6_gateway != NULL)
663 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
666 data->default_checked = TRUE;
669 static void remove_gateway(gpointer user_data)
671 struct gateway_data *data = user_data;
673 DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
675 if (data->ipv4_gateway != NULL) {
676 g_free(data->ipv4_gateway->gateway);
677 g_free(data->ipv4_gateway->vpn_ip);
678 g_free(data->ipv4_gateway->vpn_phy_ip);
679 g_free(data->ipv4_gateway);
682 if (data->ipv6_gateway != NULL) {
683 g_free(data->ipv6_gateway->gateway);
684 g_free(data->ipv6_gateway->vpn_ip);
685 g_free(data->ipv6_gateway->vpn_phy_ip);
686 g_free(data->ipv6_gateway);
692 static void connection_delgateway(int index, const char *gateway)
694 struct gateway_config *config;
695 struct gateway_data *data;
697 DBG("index %d gateway %s", index, gateway);
699 config = find_gateway(index, gateway);
701 config->active = FALSE;
703 data = find_default_gateway();
705 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
708 static struct connman_rtnl connection_rtnl = {
709 .name = "connection",
710 .newgateway = connection_newgateway,
711 .delgateway = connection_delgateway,
714 static struct gateway_data *find_active_gateway(void)
721 g_hash_table_iter_init(&iter, gateway_hash);
723 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
724 struct gateway_data *data = value;
726 if (data->ipv4_gateway != NULL &&
727 data->ipv4_gateway->active == TRUE)
730 if (data->ipv6_gateway != NULL &&
731 data->ipv6_gateway->active == TRUE)
738 static void update_order(void)
745 g_hash_table_iter_init(&iter, gateway_hash);
747 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
748 struct gateway_data *data = value;
750 data->order = __connman_service_get_order(data->service);
754 void __connman_connection_gateway_activate(struct connman_service *service,
755 enum connman_ipconfig_type type)
757 struct gateway_data *data = NULL;
759 data = g_hash_table_lookup(gateway_hash, service);
763 DBG("gateway %p/%p type %d", data->ipv4_gateway,
764 data->ipv6_gateway, type);
766 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
767 data->ipv4_gateway->active = TRUE;
768 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
769 data->ipv6_gateway->active = TRUE;
772 static void add_host_route(int family, int index, const char *gateway,
773 enum connman_service_type service_type)
777 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
779 * We must not set route to the phy dev gateway in
780 * VPN link. The packets to VPN link might be routed
781 * back to itself and not routed into phy link gateway.
783 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
784 connman_inet_add_host_route(index, gateway,
788 * Add host route to P-t-P link so that services can
789 * be moved around and we can have some link to P-t-P
790 * network (although those P-t-P links have limited
791 * usage if default route is not directed to them)
794 if (connman_inet_get_dest_addr(index, &dest) == 0) {
795 connman_inet_add_host_route(index, dest, NULL);
802 if (g_strcmp0(gateway, "::") != 0) {
803 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
804 connman_inet_add_ipv6_host_route(index,
807 /* P-t-P link, add route to destination */
809 if (connman_inet_ipv6_get_dest_addr(index,
811 connman_inet_add_ipv6_host_route(index, dest,
820 int __connman_connection_gateway_add(struct connman_service *service,
822 enum connman_ipconfig_type type,
825 struct gateway_data *active_gateway = NULL;
826 struct gateway_data *new_gateway = NULL;
827 enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
828 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
829 enum connman_service_type service_type =
830 connman_service_get_type(service);
833 index = __connman_service_get_index(service);
836 * If gateway is NULL, it's a point to point link and the default
837 * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
840 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
843 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
846 DBG("service %p index %d gateway %s vpn ip %s type %d",
847 service, index, gateway, peer, type);
849 new_gateway = add_gateway(service, index, gateway, type);
850 if (new_gateway == NULL)
853 active_gateway = find_active_gateway();
855 DBG("active %p index %d new %p", active_gateway,
856 active_gateway ? active_gateway->index : -1, new_gateway);
858 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
859 new_gateway->ipv4_gateway != NULL) {
860 add_host_route(AF_INET, index, gateway, service_type);
861 __connman_service_nameserver_add_routes(service,
862 new_gateway->ipv4_gateway->gateway);
863 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
866 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
867 new_gateway->ipv6_gateway != NULL) {
868 add_host_route(AF_INET6, index, gateway, service_type);
869 __connman_service_nameserver_add_routes(service,
870 new_gateway->ipv6_gateway->gateway);
871 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
874 if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
876 set_vpn_routes(new_gateway, service, gateway, type, peer,
880 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
881 new_gateway->ipv4_gateway != NULL)
882 new_gateway->ipv4_gateway->vpn = FALSE;
884 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
885 new_gateway->ipv6_gateway != NULL)
886 new_gateway->ipv6_gateway->vpn = FALSE;
889 if (active_gateway == NULL) {
890 set_default_gateway(new_gateway, type);
894 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
895 new_gateway->ipv4_gateway != NULL &&
896 new_gateway->ipv4_gateway->vpn == TRUE) {
897 if (__connman_service_is_split_routing(new_gateway->service) ==
899 connman_inet_clear_gateway_address(
900 active_gateway->index,
901 active_gateway->ipv4_gateway->gateway);
904 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
905 new_gateway->ipv6_gateway != NULL &&
906 new_gateway->ipv6_gateway->vpn == TRUE) {
907 if (__connman_service_is_split_routing(new_gateway->service) ==
909 connman_inet_clear_ipv6_gateway_address(
910 active_gateway->index,
911 active_gateway->ipv6_gateway->gateway);
915 if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
916 __connman_service_ipconfig_indicate_state(service,
917 CONNMAN_SERVICE_STATE_READY,
918 CONNMAN_IPCONFIG_TYPE_IPV4);
920 if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
921 __connman_service_ipconfig_indicate_state(service,
922 CONNMAN_SERVICE_STATE_READY,
923 CONNMAN_IPCONFIG_TYPE_IPV6);
927 void __connman_connection_gateway_remove(struct connman_service *service,
928 enum connman_ipconfig_type type)
930 struct gateway_data *data = NULL;
931 gboolean set_default4 = FALSE, set_default6 = FALSE;
932 int do_ipv4 = FALSE, do_ipv6 = FALSE;
935 DBG("service %p type %d", service, type);
937 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
939 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
942 do_ipv4 = do_ipv6 = TRUE;
944 __connman_service_nameserver_del_routes(service, type);
946 data = g_hash_table_lookup(gateway_hash, service);
950 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
951 set_default4 = data->ipv4_gateway->vpn;
953 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
954 set_default6 = data->ipv6_gateway->vpn;
956 DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
957 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
958 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
959 set_default4, set_default6);
961 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
962 data->ipv4_gateway->vpn == TRUE && data->index >= 0)
963 connman_inet_del_host_route(data->index,
964 data->ipv4_gateway->gateway);
966 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
967 data->ipv6_gateway->vpn == TRUE && data->index >= 0)
968 connman_inet_del_ipv6_host_route(data->index,
969 data->ipv6_gateway->gateway);
971 err = disable_gateway(data, type);
974 * We remove the service from the hash only if all the gateway
975 * settings are to be removed.
977 if (do_ipv4 == do_ipv6 ||
978 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
979 && do_ipv4 == TRUE) ||
980 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
983 connman_service_unref(service);
984 g_hash_table_remove(gateway_hash, service);
986 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
987 data->ipv4_gateway, do_ipv4,
988 data->ipv6_gateway, do_ipv6);
990 /* with vpn this will be called after the network was deleted,
991 * we need to call set_default here because we will not recieve any
992 * gateway delete notification.
993 * We hit the same issue if remove_gateway() fails.
995 if (set_default4 || set_default6 || err < 0) {
996 data = find_default_gateway();
998 set_default_gateway(data, type);
1002 gboolean __connman_connection_update_gateway(void)
1004 struct gateway_data *default_gateway;
1005 gboolean updated = FALSE;
1006 GHashTableIter iter;
1007 gpointer value, key;
1009 if (gateway_hash == NULL)
1014 default_gateway = find_default_gateway();
1016 __connman_service_update_ordering();
1018 DBG("default %p", default_gateway);
1021 * There can be multiple active gateways so we need to
1024 g_hash_table_iter_init(&iter, gateway_hash);
1026 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1027 struct gateway_data *active_gateway = value;
1029 if (active_gateway == default_gateway)
1032 if (active_gateway->ipv4_gateway != NULL &&
1033 active_gateway->ipv4_gateway->active == TRUE) {
1035 unset_default_gateway(active_gateway,
1036 CONNMAN_IPCONFIG_TYPE_IPV4);
1040 if (active_gateway->ipv6_gateway != NULL &&
1041 active_gateway->ipv6_gateway->active == TRUE) {
1043 unset_default_gateway(active_gateway,
1044 CONNMAN_IPCONFIG_TYPE_IPV6);
1049 if (updated && default_gateway != NULL) {
1050 if (default_gateway->ipv4_gateway)
1051 set_default_gateway(default_gateway,
1052 CONNMAN_IPCONFIG_TYPE_IPV4);
1054 if (default_gateway->ipv6_gateway)
1055 set_default_gateway(default_gateway,
1056 CONNMAN_IPCONFIG_TYPE_IPV6);
1062 int __connman_connection_get_vpn_index(int phy_index)
1064 GHashTableIter iter;
1065 gpointer value, key;
1067 g_hash_table_iter_init(&iter, gateway_hash);
1069 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1070 struct gateway_data *data = value;
1072 if (data->ipv4_gateway != NULL &&
1073 data->ipv4_gateway->vpn_phy_index == phy_index)
1076 if (data->ipv6_gateway != NULL &&
1077 data->ipv6_gateway->vpn_phy_index == phy_index)
1084 int __connman_connection_init(void)
1090 gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1091 NULL, remove_gateway);
1093 err = connman_rtnl_register(&connection_rtnl);
1095 connman_error("Failed to setup RTNL gateway driver");
1100 void __connman_connection_cleanup(void)
1102 GHashTableIter iter;
1103 gpointer value, key;
1107 connman_rtnl_unregister(&connection_rtnl);
1109 g_hash_table_iter_init(&iter, gateway_hash);
1111 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1112 struct gateway_data *data = value;
1114 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1117 g_hash_table_destroy(gateway_hash);
1118 gateway_hash = NULL;