5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
6 * Copyright (C) 2011-2014 BMW Car IT GmbH.
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;
49 struct gateway_config *ipv4_gateway;
50 struct gateway_config *ipv6_gateway;
54 static GHashTable *gateway_hash = NULL;
56 static struct gateway_config *find_gateway(int index, const char *gateway)
64 g_hash_table_iter_init(&iter, gateway_hash);
66 while (g_hash_table_iter_next(&iter, &key, &value)) {
67 struct gateway_data *data = value;
69 if (data->ipv4_gateway && data->index == index &&
70 g_str_equal(data->ipv4_gateway->gateway,
72 return data->ipv4_gateway;
74 if (data->ipv6_gateway && data->index == index &&
75 g_str_equal(data->ipv6_gateway->gateway,
77 return data->ipv6_gateway;
83 static struct gateway_data *lookup_gateway_data(struct gateway_config *config)
91 g_hash_table_iter_init(&iter, gateway_hash);
93 while (g_hash_table_iter_next(&iter, &key, &value)) {
94 struct gateway_data *data = value;
96 if (data->ipv4_gateway &&
97 data->ipv4_gateway == config)
100 if (data->ipv6_gateway &&
101 data->ipv6_gateway == config)
108 static struct gateway_data *find_vpn_gateway(int index, const char *gateway)
116 g_hash_table_iter_init(&iter, gateway_hash);
118 while (g_hash_table_iter_next(&iter, &key, &value)) {
119 struct gateway_data *data = value;
121 if (data->ipv4_gateway && data->index == index &&
122 g_str_equal(data->ipv4_gateway->gateway,
126 if (data->ipv6_gateway && data->index == index &&
127 g_str_equal(data->ipv6_gateway->gateway,
135 struct get_gateway_params {
140 static void get_gateway_cb(const char *gateway, int index, void *user_data)
142 struct gateway_config *config;
143 struct gateway_data *data;
144 struct get_gateway_params *params = user_data;
150 DBG("phy index %d phy gw %s vpn index %d vpn gw %s", index, gateway,
151 params->vpn_index, params->vpn_gateway);
153 data = find_vpn_gateway(params->vpn_index, params->vpn_gateway);
155 DBG("Cannot find VPN link route, index %d addr %s",
156 params->vpn_index, params->vpn_gateway);
160 family = connman_inet_check_ipaddress(params->vpn_gateway);
162 if (family == AF_INET)
163 config = data->ipv4_gateway;
164 else if (family == AF_INET6)
165 config = data->ipv6_gateway;
169 config->vpn_phy_index = index;
171 DBG("vpn %s phy index %d", config->vpn_ip, config->vpn_phy_index);
174 g_free(params->vpn_gateway);
178 static void set_vpn_routes(struct gateway_data *new_gateway,
179 struct connman_service *service,
181 enum connman_ipconfig_type type,
183 struct gateway_data *active_gateway)
185 struct gateway_config *config;
186 struct connman_ipconfig *ipconfig;
189 DBG("new %p service %p gw %s type %d peer %s active %p",
190 new_gateway, service, gateway, type, peer, active_gateway);
192 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
193 ipconfig = __connman_service_get_ip4config(service);
194 config = new_gateway->ipv4_gateway;
195 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
196 ipconfig = __connman_service_get_ip6config(service);
197 config = new_gateway->ipv6_gateway;
202 int index = __connman_ipconfig_get_index(ipconfig);
203 struct get_gateway_params *params;
207 config->vpn_ip = g_strdup(peer);
209 config->vpn_ip = g_strdup(gateway);
211 params = g_try_malloc(sizeof(struct get_gateway_params));
215 params->vpn_index = index;
216 params->vpn_gateway = g_strdup(gateway);
219 * Find the gateway that is serving the VPN link
221 __connman_inet_get_route(gateway, get_gateway_cb, params);
227 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
229 * Special route to VPN server via gateway. This
230 * is needed so that we can access hosts behind
231 * the VPN. The route might already exist depending
232 * on network topology.
234 if (!active_gateway->ipv4_gateway)
237 DBG("active gw %s", active_gateway->ipv4_gateway->gateway);
239 if (g_strcmp0(active_gateway->ipv4_gateway->gateway,
241 dest = active_gateway->ipv4_gateway->gateway;
245 connman_inet_add_host_route(active_gateway->index, gateway,
248 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
250 if (!active_gateway->ipv6_gateway)
253 DBG("active gw %s", active_gateway->ipv6_gateway->gateway);
255 if (g_strcmp0(active_gateway->ipv6_gateway->gateway,
257 dest = active_gateway->ipv6_gateway->gateway;
261 connman_inet_add_ipv6_host_route(active_gateway->index,
266 static int del_routes(struct gateway_data *data,
267 enum connman_ipconfig_type type)
269 int status4 = 0, status6 = 0;
270 bool do_ipv4 = false, do_ipv6 = false;
272 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
274 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
277 do_ipv4 = do_ipv6 = true;
279 if (do_ipv4 && data->ipv4_gateway) {
280 if (data->ipv4_gateway->vpn) {
281 status4 = connman_inet_clear_gateway_address(
283 data->ipv4_gateway->vpn_ip);
285 } else if (g_strcmp0(data->ipv4_gateway->gateway,
287 status4 = connman_inet_clear_gateway_interface(
290 connman_inet_del_host_route(data->index,
291 data->ipv4_gateway->gateway);
292 status4 = connman_inet_clear_gateway_address(
294 data->ipv4_gateway->gateway);
298 if (do_ipv6 && data->ipv6_gateway) {
299 if (data->ipv6_gateway->vpn) {
300 status6 = connman_inet_clear_ipv6_gateway_address(
302 data->ipv6_gateway->vpn_ip);
304 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
305 status6 = connman_inet_clear_ipv6_gateway_interface(
308 connman_inet_del_ipv6_host_route(data->index,
309 data->ipv6_gateway->gateway);
310 status6 = connman_inet_clear_ipv6_gateway_address(
312 data->ipv6_gateway->gateway);
316 return (status4 < 0 ? status4 : status6);
319 static int disable_gateway(struct gateway_data *data,
320 enum connman_ipconfig_type type)
324 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
325 if (data->ipv4_gateway)
326 active = data->ipv4_gateway->active;
327 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
328 if (data->ipv6_gateway)
329 active = data->ipv6_gateway->active;
333 DBG("type %d active %d", type, active);
336 return del_routes(data, type);
341 static struct gateway_data *add_gateway(struct connman_service *service,
342 int index, const char *gateway,
343 enum connman_ipconfig_type type)
345 struct gateway_data *data, *old;
346 struct gateway_config *config;
348 if (!gateway || strlen(gateway) == 0)
351 data = g_try_new0(struct gateway_data, 1);
357 config = g_try_new0(struct gateway_config, 1);
363 config->gateway = g_strdup(gateway);
364 config->vpn_ip = NULL;
365 config->vpn_phy_ip = NULL;
367 config->vpn_phy_index = -1;
368 config->active = false;
370 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
371 data->ipv4_gateway = config;
372 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
373 data->ipv6_gateway = config;
375 g_free(config->gateway);
381 data->service = service;
384 * If the service is already in the hash, then we
385 * must not replace it blindly but disable the gateway
386 * of the type we are replacing and take the other type
387 * from old gateway settings.
389 old = g_hash_table_lookup(gateway_hash, service);
391 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
392 old->ipv4_gateway, old->ipv6_gateway);
393 disable_gateway(old, type);
394 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
395 data->ipv6_gateway = old->ipv6_gateway;
396 old->ipv6_gateway = NULL;
397 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
398 data->ipv4_gateway = old->ipv4_gateway;
399 old->ipv4_gateway = NULL;
403 connman_service_ref(data->service);
404 g_hash_table_replace(gateway_hash, service, data);
409 static void set_default_gateway(struct gateway_data *data,
410 enum connman_ipconfig_type type)
413 int status4 = 0, status6 = 0;
414 bool do_ipv4 = false, do_ipv6 = false;
416 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
418 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
421 do_ipv4 = do_ipv6 = true;
423 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
426 if (do_ipv4 && data->ipv4_gateway &&
427 data->ipv4_gateway->vpn) {
428 connman_inet_set_gateway_interface(data->index);
429 data->ipv4_gateway->active = true;
431 DBG("set %p index %d vpn %s index %d phy %s",
432 data, data->index, data->ipv4_gateway->vpn_ip,
433 data->ipv4_gateway->vpn_phy_index,
434 data->ipv4_gateway->vpn_phy_ip);
436 __connman_service_indicate_default(data->service);
441 if (do_ipv6 && data->ipv6_gateway &&
442 data->ipv6_gateway->vpn) {
443 connman_inet_set_ipv6_gateway_interface(data->index);
444 data->ipv6_gateway->active = true;
446 DBG("set %p index %d vpn %s index %d phy %s",
447 data, data->index, data->ipv6_gateway->vpn_ip,
448 data->ipv6_gateway->vpn_phy_index,
449 data->ipv6_gateway->vpn_phy_ip);
451 __connman_service_indicate_default(data->service);
456 index = __connman_service_get_index(data->service);
458 if (do_ipv4 && data->ipv4_gateway &&
459 g_strcmp0(data->ipv4_gateway->gateway,
461 if (connman_inet_set_gateway_interface(index) < 0)
463 data->ipv4_gateway->active = true;
467 if (do_ipv6 && data->ipv6_gateway &&
468 g_strcmp0(data->ipv6_gateway->gateway,
470 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
472 data->ipv6_gateway->active = true;
476 if (do_ipv6 && data->ipv6_gateway)
477 status6 = __connman_inet_add_default_to_table(RT_TABLE_MAIN,
478 index, data->ipv6_gateway->gateway);
480 if (do_ipv4 && data->ipv4_gateway)
481 status4 = __connman_inet_add_default_to_table(RT_TABLE_MAIN,
482 index, data->ipv4_gateway->gateway);
484 if (status4 < 0 || status6 < 0)
488 __connman_service_indicate_default(data->service);
491 static void unset_default_gateway(struct gateway_data *data,
492 enum connman_ipconfig_type type)
495 bool do_ipv4 = false, do_ipv6 = false;
497 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
499 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
502 do_ipv4 = do_ipv6 = true;
504 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
507 if (do_ipv4 && data->ipv4_gateway &&
508 data->ipv4_gateway->vpn) {
509 connman_inet_clear_gateway_interface(data->index);
510 data->ipv4_gateway->active = false;
512 DBG("unset %p index %d vpn %s index %d phy %s",
513 data, data->index, data->ipv4_gateway->vpn_ip,
514 data->ipv4_gateway->vpn_phy_index,
515 data->ipv4_gateway->vpn_phy_ip);
520 if (do_ipv6 && data->ipv6_gateway &&
521 data->ipv6_gateway->vpn) {
522 connman_inet_clear_ipv6_gateway_interface(data->index);
523 data->ipv6_gateway->active = false;
525 DBG("unset %p index %d vpn %s index %d phy %s",
526 data, data->index, data->ipv6_gateway->vpn_ip,
527 data->ipv6_gateway->vpn_phy_index,
528 data->ipv6_gateway->vpn_phy_ip);
533 index = __connman_service_get_index(data->service);
535 if (do_ipv4 && data->ipv4_gateway &&
536 g_strcmp0(data->ipv4_gateway->gateway,
538 connman_inet_clear_gateway_interface(index);
539 data->ipv4_gateway->active = false;
543 if (do_ipv6 && data->ipv6_gateway &&
544 g_strcmp0(data->ipv6_gateway->gateway,
546 connman_inet_clear_ipv6_gateway_interface(index);
547 data->ipv6_gateway->active = false;
551 if (do_ipv6 && data->ipv6_gateway)
552 connman_inet_clear_ipv6_gateway_address(index,
553 data->ipv6_gateway->gateway);
555 if (do_ipv4 && data->ipv4_gateway)
556 connman_inet_clear_gateway_address(index,
557 data->ipv4_gateway->gateway);
560 static struct gateway_data *find_default_gateway(void)
562 struct connman_service *service;
564 service = connman_service_get_default();
568 return g_hash_table_lookup(gateway_hash, service);
571 static bool choose_default_gateway(struct gateway_data *data,
572 struct gateway_data *candidate)
574 bool downgraded = false;
577 * If the current default is not active, then we mark
578 * this one as default. If the other one is already active
579 * we mark this one as non default.
581 if (data->ipv4_gateway && candidate->ipv4_gateway) {
583 if (!candidate->ipv4_gateway->active) {
584 DBG("ipv4 downgrading %p", candidate);
585 unset_default_gateway(candidate,
586 CONNMAN_IPCONFIG_TYPE_IPV4);
589 if (candidate->ipv4_gateway->active &&
590 __connman_service_compare(candidate->service,
591 data->service) < 0) {
592 DBG("ipv4 downgrading this %p", data);
593 unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
598 if (data->ipv6_gateway && candidate->ipv6_gateway) {
599 if (!candidate->ipv6_gateway->active) {
600 DBG("ipv6 downgrading %p", candidate);
601 unset_default_gateway(candidate,
602 CONNMAN_IPCONFIG_TYPE_IPV6);
605 if (candidate->ipv6_gateway->active &&
606 __connman_service_compare(candidate->service,
607 data->service) < 0) {
608 DBG("ipv6 downgrading this %p", data);
609 unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
617 static void connection_newgateway(int index, const char *gateway)
619 struct gateway_config *config;
620 struct gateway_data *data;
625 DBG("index %d gateway %s", index, gateway);
627 config = find_gateway(index, gateway);
631 config->active = true;
634 * It is possible that we have two default routes atm
635 * if there are two gateways waiting rtnl activation at the
638 data = lookup_gateway_data(config);
642 if (data->default_checked)
646 * The next checks are only done once, otherwise setting
647 * the default gateway could lead into rtnl forever loop.
650 g_hash_table_iter_init(&iter, gateway_hash);
652 while (g_hash_table_iter_next(&iter, &key, &value)) {
653 struct gateway_data *candidate = value;
655 if (candidate == data)
658 found = choose_default_gateway(data, candidate);
664 #if defined TIZEN_EXT
665 if (data->ipv4_gateway != NULL){
666 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
667 connman_check_proxy_setup_and_wispr_start(data->service);
670 if (data->ipv4_gateway)
671 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
674 if (data->ipv6_gateway)
675 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
678 data->default_checked = true;
681 static void remove_gateway(gpointer user_data)
683 struct gateway_data *data = user_data;
685 DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
687 if (data->ipv4_gateway) {
688 g_free(data->ipv4_gateway->gateway);
689 g_free(data->ipv4_gateway->vpn_ip);
690 g_free(data->ipv4_gateway->vpn_phy_ip);
691 g_free(data->ipv4_gateway);
694 if (data->ipv6_gateway) {
695 g_free(data->ipv6_gateway->gateway);
696 g_free(data->ipv6_gateway->vpn_ip);
697 g_free(data->ipv6_gateway->vpn_phy_ip);
698 g_free(data->ipv6_gateway);
701 connman_service_unref(data->service);
706 static void connection_delgateway(int index, const char *gateway)
708 struct gateway_config *config;
709 struct gateway_data *data;
711 DBG("index %d gateway %s", index, gateway);
713 config = find_gateway(index, gateway);
715 config->active = false;
717 data = find_default_gateway();
719 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
722 static struct connman_rtnl connection_rtnl = {
723 .name = "connection",
724 .newgateway = connection_newgateway,
725 .delgateway = connection_delgateway,
728 static struct gateway_data *find_active_gateway(void)
735 g_hash_table_iter_init(&iter, gateway_hash);
737 while (g_hash_table_iter_next(&iter, &key, &value)) {
738 struct gateway_data *data = value;
740 if (data->ipv4_gateway &&
741 data->ipv4_gateway->active)
744 if (data->ipv6_gateway &&
745 data->ipv6_gateway->active)
752 static void add_host_route(int family, int index, const char *gateway,
753 enum connman_service_type service_type)
757 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
759 * We must not set route to the phy dev gateway in
760 * VPN link. The packets to VPN link might be routed
761 * back to itself and not routed into phy link gateway.
763 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
764 connman_inet_add_host_route(index, gateway,
768 * Add host route to P-t-P link so that services can
769 * be moved around and we can have some link to P-t-P
770 * network (although those P-t-P links have limited
771 * usage if default route is not directed to them)
774 if (connman_inet_get_dest_addr(index, &dest) == 0) {
775 connman_inet_add_host_route(index, dest, NULL);
782 if (g_strcmp0(gateway, "::") != 0) {
783 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
784 connman_inet_add_ipv6_host_route(index,
787 /* P-t-P link, add route to destination */
789 if (connman_inet_ipv6_get_dest_addr(index,
791 connman_inet_add_ipv6_host_route(index, dest,
800 #if defined TIZEN_EXT
801 static bool __connman_service_is_not_cellular_internet_profile(
802 struct connman_service *cellular)
806 const char internet_suffix[] = "_1";
807 const char prepaid_internet_suffix[] = "_3";
809 if (connman_service_get_type(cellular) != CONNMAN_SERVICE_TYPE_CELLULAR)
812 path = __connman_service_get_path(cellular);
814 suffix = strrchr(path, '_');
816 if (g_strcmp0(suffix, internet_suffix) != 0 &&
817 g_strcmp0(suffix, prepaid_internet_suffix) != 0) {
818 DBG("not internet service profile: %s", path);
826 int __connman_connection_gateway_add(struct connman_service *service,
828 enum connman_ipconfig_type type,
831 struct gateway_data *active_gateway = NULL;
832 struct gateway_data *new_gateway = NULL;
833 enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
834 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
835 enum connman_service_type service_type =
836 connman_service_get_type(service);
839 index = __connman_service_get_index(service);
842 * If gateway is NULL, it's a point to point link and the default
843 * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
846 if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV4)
849 if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6)
852 #if defined TIZEN_EXT
853 if (__connman_service_is_not_cellular_internet_profile(service) == TRUE) {
854 /* not internet service should not be default gateway */
856 DBG("no internet service %p index %d gateway %s vpn ip %s type %d",
857 service, index, gateway, peer, type);
859 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
860 add_host_route(AF_INET, index, gateway, service_type);
861 __connman_service_nameserver_add_routes(service, gateway);
862 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
865 if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
866 add_host_route(AF_INET6, index, gateway, service_type);
867 __connman_service_nameserver_add_routes(service, gateway);
868 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
874 DBG("service %p index %d gateway %s vpn ip %s type %d",
875 service, index, gateway, peer, type);
877 new_gateway = add_gateway(service, index, gateway, type);
881 active_gateway = find_active_gateway();
883 DBG("active %p index %d new %p", active_gateway,
884 active_gateway ? active_gateway->index : -1, new_gateway);
886 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
887 new_gateway->ipv4_gateway) {
888 add_host_route(AF_INET, index, gateway, service_type);
889 __connman_service_nameserver_add_routes(service,
890 new_gateway->ipv4_gateway->gateway);
891 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
894 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
895 new_gateway->ipv6_gateway) {
896 add_host_route(AF_INET6, index, gateway, service_type);
897 __connman_service_nameserver_add_routes(service,
898 new_gateway->ipv6_gateway->gateway);
899 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
902 if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
904 set_vpn_routes(new_gateway, service, gateway, type, peer,
908 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
909 new_gateway->ipv4_gateway)
910 new_gateway->ipv4_gateway->vpn = false;
912 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
913 new_gateway->ipv6_gateway)
914 new_gateway->ipv6_gateway->vpn = false;
917 if (!active_gateway) {
918 #if defined TIZEN_EXT
919 if(new_gateway->ipv4_gateway)
920 DBG("ConnMan, Set default gateway[%s], active[%d]",
921 new_gateway->ipv4_gateway->gateway,
922 new_gateway->ipv4_gateway->active);
924 set_default_gateway(new_gateway, type);
928 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
929 new_gateway->ipv4_gateway &&
930 new_gateway->ipv4_gateway->vpn) {
931 if (!__connman_service_is_split_routing(new_gateway->service))
932 connman_inet_clear_gateway_address(
933 active_gateway->index,
934 active_gateway->ipv4_gateway->gateway);
937 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
938 new_gateway->ipv6_gateway &&
939 new_gateway->ipv6_gateway->vpn) {
940 if (!__connman_service_is_split_routing(new_gateway->service))
941 connman_inet_clear_ipv6_gateway_address(
942 active_gateway->index,
943 active_gateway->ipv6_gateway->gateway);
947 if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
948 __connman_service_ipconfig_indicate_state(service,
949 CONNMAN_SERVICE_STATE_READY,
950 CONNMAN_IPCONFIG_TYPE_IPV4);
952 if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
953 __connman_service_ipconfig_indicate_state(service,
954 CONNMAN_SERVICE_STATE_READY,
955 CONNMAN_IPCONFIG_TYPE_IPV6);
959 void __connman_connection_gateway_remove(struct connman_service *service,
960 enum connman_ipconfig_type type)
962 struct gateway_data *data = NULL;
963 bool set_default4 = false, set_default6 = false;
964 bool do_ipv4 = false, do_ipv6 = false;
967 DBG("service %p type %d", service, type);
969 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
971 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
974 do_ipv4 = do_ipv6 = true;
976 __connman_service_nameserver_del_routes(service, type);
978 data = g_hash_table_lookup(gateway_hash, service);
982 if (do_ipv4 && data->ipv4_gateway)
983 set_default4 = data->ipv4_gateway->vpn;
985 if (do_ipv6 && data->ipv6_gateway)
986 set_default6 = data->ipv6_gateway->vpn;
988 DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
989 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
990 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
991 set_default4, set_default6);
993 if (do_ipv4 && data->ipv4_gateway &&
994 data->ipv4_gateway->vpn && data->index >= 0)
995 connman_inet_del_host_route(data->ipv4_gateway->vpn_phy_index,
996 data->ipv4_gateway->gateway);
998 if (do_ipv6 && data->ipv6_gateway &&
999 data->ipv6_gateway->vpn && data->index >= 0)
1000 connman_inet_del_ipv6_host_route(
1001 data->ipv6_gateway->vpn_phy_index,
1002 data->ipv6_gateway->gateway);
1004 err = disable_gateway(data, type);
1007 * We remove the service from the hash only if all the gateway
1008 * settings are to be removed.
1010 if (do_ipv4 == do_ipv6 ||
1011 (data->ipv4_gateway && !data->ipv6_gateway
1013 (data->ipv6_gateway && !data->ipv4_gateway
1015 g_hash_table_remove(gateway_hash, service);
1017 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
1018 data->ipv4_gateway, do_ipv4,
1019 data->ipv6_gateway, do_ipv6);
1021 /* with vpn this will be called after the network was deleted,
1022 * we need to call set_default here because we will not recieve any
1023 * gateway delete notification.
1024 * We hit the same issue if remove_gateway() fails.
1026 if (set_default4 || set_default6 || err < 0) {
1027 data = find_default_gateway();
1029 set_default_gateway(data, type);
1033 bool __connman_connection_update_gateway(void)
1035 struct gateway_data *default_gateway;
1036 bool updated = false;
1037 GHashTableIter iter;
1038 gpointer value, key;
1039 #if defined TIZEN_EXT
1040 static struct gateway_data *old_default = NULL;
1046 default_gateway = find_default_gateway();
1048 DBG("default %p", default_gateway);
1051 * There can be multiple active gateways so we need to
1054 g_hash_table_iter_init(&iter, gateway_hash);
1056 while (g_hash_table_iter_next(&iter, &key, &value)) {
1057 struct gateway_data *active_gateway = value;
1059 if (active_gateway == default_gateway)
1062 if (active_gateway->ipv4_gateway &&
1063 active_gateway->ipv4_gateway->active) {
1065 unset_default_gateway(active_gateway,
1066 CONNMAN_IPCONFIG_TYPE_IPV4);
1070 if (active_gateway->ipv6_gateway &&
1071 active_gateway->ipv6_gateway->active) {
1073 unset_default_gateway(active_gateway,
1074 CONNMAN_IPCONFIG_TYPE_IPV6);
1079 #if defined TIZEN_EXT
1080 if (updated == false && old_default != default_gateway) {
1082 old_default = default_gateway;
1086 * Set default gateway if it has been updated or if it has not been
1087 * set as active yet.
1089 if (default_gateway) {
1090 if (default_gateway->ipv4_gateway &&
1091 (updated || !default_gateway->ipv4_gateway->active))
1092 set_default_gateway(default_gateway,
1093 CONNMAN_IPCONFIG_TYPE_IPV4);
1095 if (default_gateway->ipv6_gateway &&
1096 (updated || !default_gateway->ipv6_gateway->active))
1097 set_default_gateway(default_gateway,
1098 CONNMAN_IPCONFIG_TYPE_IPV6);
1104 int __connman_connection_get_vpn_index(int phy_index)
1106 GHashTableIter iter;
1107 gpointer value, key;
1109 g_hash_table_iter_init(&iter, gateway_hash);
1111 while (g_hash_table_iter_next(&iter, &key, &value)) {
1112 struct gateway_data *data = value;
1114 if (data->ipv4_gateway &&
1115 data->ipv4_gateway->vpn_phy_index == phy_index)
1118 if (data->ipv6_gateway &&
1119 data->ipv6_gateway->vpn_phy_index == phy_index)
1126 int __connman_connection_init(void)
1132 gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1133 NULL, remove_gateway);
1135 err = connman_rtnl_register(&connection_rtnl);
1137 connman_error("Failed to setup RTNL gateway driver");
1142 void __connman_connection_cleanup(void)
1144 GHashTableIter iter;
1145 gpointer value, key;
1149 connman_rtnl_unregister(&connection_rtnl);
1151 g_hash_table_iter_init(&iter, gateway_hash);
1153 while (g_hash_table_iter_next(&iter, &key, &value)) {
1154 struct gateway_data *data = value;
1156 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1159 g_hash_table_destroy(gateway_hash);
1160 gateway_hash = NULL;