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)
239 * If VPN server is on same subnet as we are, skip adding
242 if (connman_inet_compare_subnet(active_gateway->index,
246 DBG("active gw %s", active_gateway->ipv4_gateway->gateway);
248 if (g_strcmp0(active_gateway->ipv4_gateway->gateway,
250 dest = active_gateway->ipv4_gateway->gateway;
254 connman_inet_add_host_route(active_gateway->index, gateway,
257 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
259 if (!active_gateway->ipv6_gateway)
262 if (connman_inet_compare_ipv6_subnet(active_gateway->index,
266 DBG("active gw %s", active_gateway->ipv6_gateway->gateway);
268 if (g_strcmp0(active_gateway->ipv6_gateway->gateway,
270 dest = active_gateway->ipv6_gateway->gateway;
274 connman_inet_add_ipv6_host_route(active_gateway->index,
279 static int del_routes(struct gateway_data *data,
280 enum connman_ipconfig_type type)
282 int status4 = 0, status6 = 0;
283 bool do_ipv4 = false, do_ipv6 = false;
285 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
287 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
290 do_ipv4 = do_ipv6 = true;
292 if (do_ipv4 && data->ipv4_gateway) {
293 if (data->ipv4_gateway->vpn) {
294 status4 = connman_inet_clear_gateway_address(
296 data->ipv4_gateway->vpn_ip);
298 } else if (g_strcmp0(data->ipv4_gateway->gateway,
300 status4 = connman_inet_clear_gateway_interface(
303 connman_inet_del_host_route(data->index,
304 data->ipv4_gateway->gateway);
305 status4 = connman_inet_clear_gateway_address(
307 data->ipv4_gateway->gateway);
311 if (do_ipv6 && data->ipv6_gateway) {
312 if (data->ipv6_gateway->vpn) {
313 status6 = connman_inet_clear_ipv6_gateway_address(
315 data->ipv6_gateway->vpn_ip);
317 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
318 status6 = connman_inet_clear_ipv6_gateway_interface(
321 connman_inet_del_ipv6_host_route(data->index,
322 data->ipv6_gateway->gateway);
323 status6 = connman_inet_clear_ipv6_gateway_address(
325 data->ipv6_gateway->gateway);
329 return (status4 < 0 ? status4 : status6);
332 static int disable_gateway(struct gateway_data *data,
333 enum connman_ipconfig_type type)
337 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
338 if (data->ipv4_gateway)
339 active = data->ipv4_gateway->active;
340 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
341 if (data->ipv6_gateway)
342 active = data->ipv6_gateway->active;
346 DBG("type %d active %d", type, active);
349 return del_routes(data, type);
354 static struct gateway_data *add_gateway(struct connman_service *service,
355 int index, const char *gateway,
356 enum connman_ipconfig_type type)
358 struct gateway_data *data, *old;
359 struct gateway_config *config;
361 if (!gateway || strlen(gateway) == 0)
364 data = g_try_new0(struct gateway_data, 1);
370 config = g_try_new0(struct gateway_config, 1);
376 config->gateway = g_strdup(gateway);
377 config->vpn_ip = NULL;
378 config->vpn_phy_ip = NULL;
380 config->vpn_phy_index = -1;
381 config->active = false;
383 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
384 data->ipv4_gateway = config;
385 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
386 data->ipv6_gateway = config;
388 g_free(config->gateway);
394 data->service = service;
397 * If the service is already in the hash, then we
398 * must not replace it blindly but disable the gateway
399 * of the type we are replacing and take the other type
400 * from old gateway settings.
402 old = g_hash_table_lookup(gateway_hash, service);
404 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
405 old->ipv4_gateway, old->ipv6_gateway);
406 disable_gateway(old, type);
407 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
408 data->ipv6_gateway = old->ipv6_gateway;
409 old->ipv6_gateway = NULL;
410 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
411 data->ipv4_gateway = old->ipv4_gateway;
412 old->ipv4_gateway = NULL;
416 connman_service_ref(data->service);
417 g_hash_table_replace(gateway_hash, service, data);
422 static void set_default_gateway(struct gateway_data *data,
423 enum connman_ipconfig_type type)
426 int status4 = 0, status6 = 0;
427 bool do_ipv4 = false, do_ipv6 = false;
429 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
431 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
434 do_ipv4 = do_ipv6 = true;
436 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
439 if (do_ipv4 && data->ipv4_gateway &&
440 data->ipv4_gateway->vpn) {
441 connman_inet_set_gateway_interface(data->index);
442 data->ipv4_gateway->active = true;
444 DBG("set %p index %d vpn %s index %d phy %s",
445 data, data->index, data->ipv4_gateway->vpn_ip,
446 data->ipv4_gateway->vpn_phy_index,
447 data->ipv4_gateway->vpn_phy_ip);
449 __connman_service_indicate_default(data->service);
454 if (do_ipv6 && data->ipv6_gateway &&
455 data->ipv6_gateway->vpn) {
456 connman_inet_set_ipv6_gateway_interface(data->index);
457 data->ipv6_gateway->active = true;
459 DBG("set %p index %d vpn %s index %d phy %s",
460 data, data->index, data->ipv6_gateway->vpn_ip,
461 data->ipv6_gateway->vpn_phy_index,
462 data->ipv6_gateway->vpn_phy_ip);
464 __connman_service_indicate_default(data->service);
469 index = __connman_service_get_index(data->service);
471 if (do_ipv4 && data->ipv4_gateway &&
472 g_strcmp0(data->ipv4_gateway->gateway,
474 if (connman_inet_set_gateway_interface(index) < 0)
476 data->ipv4_gateway->active = true;
480 if (do_ipv6 && data->ipv6_gateway &&
481 g_strcmp0(data->ipv6_gateway->gateway,
483 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
485 data->ipv6_gateway->active = true;
489 if (do_ipv6 && data->ipv6_gateway)
490 status6 = __connman_inet_add_default_to_table(RT_TABLE_MAIN,
491 index, data->ipv6_gateway->gateway);
493 if (do_ipv4 && data->ipv4_gateway)
494 status4 = __connman_inet_add_default_to_table(RT_TABLE_MAIN,
495 index, data->ipv4_gateway->gateway);
497 if (status4 < 0 || status6 < 0)
501 __connman_service_indicate_default(data->service);
504 static void unset_default_gateway(struct gateway_data *data,
505 enum connman_ipconfig_type type)
508 bool do_ipv4 = false, do_ipv6 = false;
510 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
512 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
515 do_ipv4 = do_ipv6 = true;
517 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
520 if (do_ipv4 && data->ipv4_gateway &&
521 data->ipv4_gateway->vpn) {
522 connman_inet_clear_gateway_interface(data->index);
523 data->ipv4_gateway->active = false;
525 DBG("unset %p index %d vpn %s index %d phy %s",
526 data, data->index, data->ipv4_gateway->vpn_ip,
527 data->ipv4_gateway->vpn_phy_index,
528 data->ipv4_gateway->vpn_phy_ip);
533 if (do_ipv6 && data->ipv6_gateway &&
534 data->ipv6_gateway->vpn) {
535 connman_inet_clear_ipv6_gateway_interface(data->index);
536 data->ipv6_gateway->active = false;
538 DBG("unset %p index %d vpn %s index %d phy %s",
539 data, data->index, data->ipv6_gateway->vpn_ip,
540 data->ipv6_gateway->vpn_phy_index,
541 data->ipv6_gateway->vpn_phy_ip);
546 index = __connman_service_get_index(data->service);
548 if (do_ipv4 && data->ipv4_gateway &&
549 g_strcmp0(data->ipv4_gateway->gateway,
551 connman_inet_clear_gateway_interface(index);
552 data->ipv4_gateway->active = false;
556 if (do_ipv6 && data->ipv6_gateway &&
557 g_strcmp0(data->ipv6_gateway->gateway,
559 connman_inet_clear_ipv6_gateway_interface(index);
560 data->ipv6_gateway->active = false;
564 if (do_ipv6 && data->ipv6_gateway)
565 connman_inet_clear_ipv6_gateway_address(index,
566 data->ipv6_gateway->gateway);
568 if (do_ipv4 && data->ipv4_gateway)
569 connman_inet_clear_gateway_address(index,
570 data->ipv4_gateway->gateway);
573 static struct gateway_data *find_default_gateway(void)
575 struct connman_service *service;
577 service = connman_service_get_default();
581 return g_hash_table_lookup(gateway_hash, service);
584 static bool choose_default_gateway(struct gateway_data *data,
585 struct gateway_data *candidate)
587 bool downgraded = false;
590 * If the current default is not active, then we mark
591 * this one as default. If the other one is already active
592 * we mark this one as non default.
594 if (data->ipv4_gateway && candidate->ipv4_gateway) {
596 if (!candidate->ipv4_gateway->active) {
597 DBG("ipv4 downgrading %p", candidate);
598 unset_default_gateway(candidate,
599 CONNMAN_IPCONFIG_TYPE_IPV4);
602 if (candidate->ipv4_gateway->active &&
603 __connman_service_compare(candidate->service,
604 data->service) < 0) {
605 DBG("ipv4 downgrading this %p", data);
606 unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
611 if (data->ipv6_gateway && candidate->ipv6_gateway) {
612 if (!candidate->ipv6_gateway->active) {
613 DBG("ipv6 downgrading %p", candidate);
614 unset_default_gateway(candidate,
615 CONNMAN_IPCONFIG_TYPE_IPV6);
618 if (candidate->ipv6_gateway->active &&
619 __connman_service_compare(candidate->service,
620 data->service) < 0) {
621 DBG("ipv6 downgrading this %p", data);
622 unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
630 static void connection_newgateway(int index, const char *gateway)
632 struct gateway_config *config;
633 struct gateway_data *data;
638 DBG("index %d gateway %s", index, gateway);
640 config = find_gateway(index, gateway);
644 config->active = true;
647 * It is possible that we have two default routes atm
648 * if there are two gateways waiting rtnl activation at the
651 data = lookup_gateway_data(config);
655 if (data->default_checked)
659 * The next checks are only done once, otherwise setting
660 * the default gateway could lead into rtnl forever loop.
663 g_hash_table_iter_init(&iter, gateway_hash);
665 while (g_hash_table_iter_next(&iter, &key, &value)) {
666 struct gateway_data *candidate = value;
668 if (candidate == data)
671 found = choose_default_gateway(data, candidate);
677 #if defined TIZEN_EXT
678 if (data->ipv4_gateway != NULL){
679 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
680 connman_check_proxy_setup_and_wispr_start(data->service);
683 if (data->ipv4_gateway)
684 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
687 if (data->ipv6_gateway)
688 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
691 data->default_checked = true;
694 static void remove_gateway(gpointer user_data)
696 struct gateway_data *data = user_data;
698 DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
700 if (data->ipv4_gateway) {
701 g_free(data->ipv4_gateway->gateway);
702 g_free(data->ipv4_gateway->vpn_ip);
703 g_free(data->ipv4_gateway->vpn_phy_ip);
704 g_free(data->ipv4_gateway);
707 if (data->ipv6_gateway) {
708 g_free(data->ipv6_gateway->gateway);
709 g_free(data->ipv6_gateway->vpn_ip);
710 g_free(data->ipv6_gateway->vpn_phy_ip);
711 g_free(data->ipv6_gateway);
714 connman_service_unref(data->service);
719 static void connection_delgateway(int index, const char *gateway)
721 struct gateway_config *config;
722 struct gateway_data *data;
724 DBG("index %d gateway %s", index, gateway);
726 config = find_gateway(index, gateway);
728 config->active = false;
730 data = find_default_gateway();
732 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
735 static struct connman_rtnl connection_rtnl = {
736 .name = "connection",
737 .newgateway = connection_newgateway,
738 .delgateway = connection_delgateway,
741 static struct gateway_data *find_active_gateway(void)
748 g_hash_table_iter_init(&iter, gateway_hash);
750 while (g_hash_table_iter_next(&iter, &key, &value)) {
751 struct gateway_data *data = value;
753 if (data->ipv4_gateway &&
754 data->ipv4_gateway->active)
757 if (data->ipv6_gateway &&
758 data->ipv6_gateway->active)
765 static void add_host_route(int family, int index, const char *gateway,
766 enum connman_service_type service_type)
770 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
772 * We must not set route to the phy dev gateway in
773 * VPN link. The packets to VPN link might be routed
774 * back to itself and not routed into phy link gateway.
776 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
777 connman_inet_add_host_route(index, gateway,
781 * Add host route to P-t-P link so that services can
782 * be moved around and we can have some link to P-t-P
783 * network (although those P-t-P links have limited
784 * usage if default route is not directed to them)
787 if (connman_inet_get_dest_addr(index, &dest) == 0) {
788 connman_inet_add_host_route(index, dest, NULL);
795 if (g_strcmp0(gateway, "::") != 0) {
796 if (service_type != CONNMAN_SERVICE_TYPE_VPN)
797 connman_inet_add_ipv6_host_route(index,
800 /* P-t-P link, add route to destination */
802 if (connman_inet_ipv6_get_dest_addr(index,
804 connman_inet_add_ipv6_host_route(index, dest,
813 #if defined TIZEN_EXT
814 static bool __connman_service_is_not_cellular_internet_profile(
815 struct connman_service *cellular)
819 const char internet_suffix[] = "_1";
820 const char prepaid_internet_suffix[] = "_3";
822 if (connman_service_get_type(cellular) != CONNMAN_SERVICE_TYPE_CELLULAR)
825 path = __connman_service_get_path(cellular);
827 suffix = strrchr(path, '_');
829 if (g_strcmp0(suffix, internet_suffix) != 0 &&
830 g_strcmp0(suffix, prepaid_internet_suffix) != 0) {
831 DBG("not internet service profile: %s", path);
839 int __connman_connection_gateway_add(struct connman_service *service,
841 enum connman_ipconfig_type type,
844 struct gateway_data *active_gateway = NULL;
845 struct gateway_data *new_gateway = NULL;
846 enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
847 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
848 enum connman_service_type service_type =
849 connman_service_get_type(service);
852 index = __connman_service_get_index(service);
855 * If gateway is NULL, it's a point to point link and the default
856 * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
859 if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV4)
862 if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6)
865 #if defined TIZEN_EXT
866 if (__connman_service_is_not_cellular_internet_profile(service) == TRUE) {
867 /* not internet service should not be default gateway */
869 DBG("no internet service %p index %d gateway %s vpn ip %s type %d",
870 service, index, gateway, peer, type);
872 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
873 add_host_route(AF_INET, index, gateway, service_type);
874 __connman_service_nameserver_add_routes(service, gateway);
875 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
878 if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
879 add_host_route(AF_INET6, index, gateway, service_type);
880 __connman_service_nameserver_add_routes(service, gateway);
881 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
887 DBG("service %p index %d gateway %s vpn ip %s type %d",
888 service, index, gateway, peer, type);
890 new_gateway = add_gateway(service, index, gateway, type);
894 active_gateway = find_active_gateway();
896 DBG("active %p index %d new %p", active_gateway,
897 active_gateway ? active_gateway->index : -1, new_gateway);
899 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
900 new_gateway->ipv4_gateway) {
901 add_host_route(AF_INET, index, gateway, service_type);
902 __connman_service_nameserver_add_routes(service,
903 new_gateway->ipv4_gateway->gateway);
904 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
907 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
908 new_gateway->ipv6_gateway) {
909 add_host_route(AF_INET6, index, gateway, service_type);
910 __connman_service_nameserver_add_routes(service,
911 new_gateway->ipv6_gateway->gateway);
912 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
915 if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
917 set_vpn_routes(new_gateway, service, gateway, type, peer,
921 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
922 new_gateway->ipv4_gateway)
923 new_gateway->ipv4_gateway->vpn = false;
925 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
926 new_gateway->ipv6_gateway)
927 new_gateway->ipv6_gateway->vpn = false;
930 if (!active_gateway) {
931 #if defined TIZEN_EXT
932 if(new_gateway->ipv4_gateway)
933 DBG("ConnMan, Set default gateway[%s], active[%d]",
934 new_gateway->ipv4_gateway->gateway,
935 new_gateway->ipv4_gateway->active);
937 set_default_gateway(new_gateway, type);
941 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
942 new_gateway->ipv4_gateway &&
943 new_gateway->ipv4_gateway->vpn) {
944 if (!__connman_service_is_split_routing(new_gateway->service))
945 connman_inet_clear_gateway_address(
946 active_gateway->index,
947 active_gateway->ipv4_gateway->gateway);
950 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
951 new_gateway->ipv6_gateway &&
952 new_gateway->ipv6_gateway->vpn) {
953 if (!__connman_service_is_split_routing(new_gateway->service))
954 connman_inet_clear_ipv6_gateway_address(
955 active_gateway->index,
956 active_gateway->ipv6_gateway->gateway);
960 if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
961 __connman_service_ipconfig_indicate_state(service,
962 CONNMAN_SERVICE_STATE_READY,
963 CONNMAN_IPCONFIG_TYPE_IPV4);
965 if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
966 __connman_service_ipconfig_indicate_state(service,
967 CONNMAN_SERVICE_STATE_READY,
968 CONNMAN_IPCONFIG_TYPE_IPV6);
972 void __connman_connection_gateway_remove(struct connman_service *service,
973 enum connman_ipconfig_type type)
975 struct gateway_data *data = NULL;
976 bool set_default4 = false, set_default6 = false;
977 bool do_ipv4 = false, do_ipv6 = false;
980 DBG("service %p type %d", service, type);
982 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
984 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
987 do_ipv4 = do_ipv6 = true;
989 __connman_service_nameserver_del_routes(service, type);
991 data = g_hash_table_lookup(gateway_hash, service);
995 if (do_ipv4 && data->ipv4_gateway)
996 set_default4 = data->ipv4_gateway->vpn;
998 if (do_ipv6 && data->ipv6_gateway)
999 set_default6 = data->ipv6_gateway->vpn;
1001 DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
1002 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
1003 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
1004 set_default4, set_default6);
1006 if (do_ipv4 && data->ipv4_gateway &&
1007 data->ipv4_gateway->vpn && data->index >= 0)
1008 connman_inet_del_host_route(data->ipv4_gateway->vpn_phy_index,
1009 data->ipv4_gateway->gateway);
1011 if (do_ipv6 && data->ipv6_gateway &&
1012 data->ipv6_gateway->vpn && data->index >= 0)
1013 connman_inet_del_ipv6_host_route(
1014 data->ipv6_gateway->vpn_phy_index,
1015 data->ipv6_gateway->gateway);
1017 err = disable_gateway(data, type);
1020 * We remove the service from the hash only if all the gateway
1021 * settings are to be removed.
1023 if (do_ipv4 == do_ipv6 ||
1024 (data->ipv4_gateway && !data->ipv6_gateway
1026 (data->ipv6_gateway && !data->ipv4_gateway
1028 g_hash_table_remove(gateway_hash, service);
1030 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
1031 data->ipv4_gateway, do_ipv4,
1032 data->ipv6_gateway, do_ipv6);
1034 /* with vpn this will be called after the network was deleted,
1035 * we need to call set_default here because we will not receive any
1036 * gateway delete notification.
1037 * We hit the same issue if remove_gateway() fails.
1039 if (set_default4 || set_default6 || err < 0) {
1040 data = find_default_gateway();
1042 set_default_gateway(data, type);
1046 bool __connman_connection_update_gateway(void)
1048 struct gateway_data *default_gateway;
1049 bool updated = false;
1050 GHashTableIter iter;
1051 gpointer value, key;
1052 #if defined TIZEN_EXT
1053 static struct gateway_data *old_default = NULL;
1059 default_gateway = find_default_gateway();
1061 DBG("default %p", default_gateway);
1064 * There can be multiple active gateways so we need to
1067 g_hash_table_iter_init(&iter, gateway_hash);
1069 while (g_hash_table_iter_next(&iter, &key, &value)) {
1070 struct gateway_data *active_gateway = value;
1072 if (active_gateway == default_gateway)
1075 if (active_gateway->ipv4_gateway &&
1076 active_gateway->ipv4_gateway->active) {
1078 unset_default_gateway(active_gateway,
1079 CONNMAN_IPCONFIG_TYPE_IPV4);
1083 if (active_gateway->ipv6_gateway &&
1084 active_gateway->ipv6_gateway->active) {
1086 unset_default_gateway(active_gateway,
1087 CONNMAN_IPCONFIG_TYPE_IPV6);
1092 #if defined TIZEN_EXT
1093 if (updated == false && old_default != default_gateway) {
1095 old_default = default_gateway;
1099 * Set default gateway if it has been updated or if it has not been
1100 * set as active yet.
1102 if (default_gateway) {
1103 if (default_gateway->ipv4_gateway &&
1104 (updated || !default_gateway->ipv4_gateway->active))
1105 set_default_gateway(default_gateway,
1106 CONNMAN_IPCONFIG_TYPE_IPV4);
1108 if (default_gateway->ipv6_gateway &&
1109 (updated || !default_gateway->ipv6_gateway->active))
1110 set_default_gateway(default_gateway,
1111 CONNMAN_IPCONFIG_TYPE_IPV6);
1117 int __connman_connection_get_vpn_index(int phy_index)
1119 GHashTableIter iter;
1120 gpointer value, key;
1122 g_hash_table_iter_init(&iter, gateway_hash);
1124 while (g_hash_table_iter_next(&iter, &key, &value)) {
1125 struct gateway_data *data = value;
1127 if (data->ipv4_gateway &&
1128 data->ipv4_gateway->vpn_phy_index == phy_index)
1131 if (data->ipv6_gateway &&
1132 data->ipv6_gateway->vpn_phy_index == phy_index)
1139 int __connman_connection_init(void)
1145 gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1146 NULL, remove_gateway);
1148 err = connman_rtnl_register(&connection_rtnl);
1150 connman_error("Failed to setup RTNL gateway driver");
1155 void __connman_connection_cleanup(void)
1157 GHashTableIter iter;
1158 gpointer value, key;
1162 connman_rtnl_unregister(&connection_rtnl);
1164 g_hash_table_iter_init(&iter, gateway_hash);
1166 while (g_hash_table_iter_next(&iter, &key, &value)) {
1167 struct gateway_data *data = value;
1169 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1172 g_hash_table_destroy(gateway_hash);
1173 gateway_hash = NULL;