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;
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) == TRUE) {
67 struct gateway_data *data = value;
69 if (data->ipv4_gateway != NULL && data->index == index &&
70 g_str_equal(data->ipv4_gateway->gateway,
72 return data->ipv4_gateway;
74 if (data->ipv6_gateway != NULL && data->index == index &&
75 g_str_equal(data->ipv6_gateway->gateway,
77 return data->ipv6_gateway;
83 static int del_routes(struct gateway_data *data,
84 enum connman_ipconfig_type type)
86 int status4 = 0, status6 = 0;
87 int do_ipv4 = FALSE, do_ipv6 = FALSE;
89 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
91 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
94 do_ipv4 = do_ipv6 = TRUE;
96 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) {
97 if (data->ipv4_gateway->vpn == TRUE) {
98 status4 = connman_inet_clear_gateway_address(
100 data->ipv4_gateway->vpn_ip);
102 } else if (g_strcmp0(data->ipv4_gateway->gateway,
104 status4 = connman_inet_clear_gateway_interface(
107 connman_inet_del_host_route(data->index,
108 data->ipv4_gateway->gateway);
109 status4 = connman_inet_clear_gateway_address(
111 data->ipv4_gateway->gateway);
115 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) {
116 if (data->ipv6_gateway->vpn == TRUE) {
117 status6 = connman_inet_clear_ipv6_gateway_address(
119 data->ipv6_gateway->vpn_ip);
121 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
122 status6 = connman_inet_clear_ipv6_gateway_interface(
125 connman_inet_del_ipv6_host_route(data->index,
126 data->ipv6_gateway->gateway);
127 status6 = connman_inet_clear_ipv6_gateway_address(
129 data->ipv6_gateway->gateway);
133 return (status4 < 0 ? status4 : status6);
136 static int disable_gateway(struct gateway_data *data,
137 enum connman_ipconfig_type type)
139 gboolean active = FALSE;
141 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
142 if (data->ipv4_gateway != NULL)
143 active = data->ipv4_gateway->active;
144 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
145 if (data->ipv6_gateway != NULL)
146 active = data->ipv6_gateway->active;
150 DBG("type %d active %d", type, active);
153 return del_routes(data, type);
158 static struct gateway_data *add_gateway(struct connman_service *service,
159 int index, const char *gateway,
160 enum connman_ipconfig_type type)
162 struct gateway_data *data, *old;
163 struct gateway_config *config;
165 if (gateway == NULL || strlen(gateway) == 0)
168 data = g_try_new0(struct gateway_data, 1);
174 config = g_try_new0(struct gateway_config, 1);
175 if (config == NULL) {
180 config->gateway = g_strdup(gateway);
181 config->vpn_ip = NULL;
182 config->vpn_phy_ip = NULL;
184 config->vpn_phy_index = -1;
185 config->active = FALSE;
187 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
188 data->ipv4_gateway = config;
189 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
190 data->ipv6_gateway = config;
192 g_free(config->gateway);
198 data->service = service;
200 data->order = __connman_service_get_order(service);
203 * If the service is already in the hash, then we
204 * must not replace it blindly but disable the gateway
205 * of the type we are replacing and take the other type
206 * from old gateway settings.
208 old = g_hash_table_lookup(gateway_hash, service);
210 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
211 old->ipv4_gateway, old->ipv6_gateway);
212 disable_gateway(old, type);
213 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
214 data->ipv6_gateway = old->ipv6_gateway;
215 old->ipv6_gateway = NULL;
216 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
217 data->ipv4_gateway = old->ipv4_gateway;
218 old->ipv4_gateway = NULL;
222 * Only take a ref if we are adding new stuff to hash.
224 connman_service_ref(service);
227 g_hash_table_replace(gateway_hash, service, data);
232 static void connection_newgateway(int index, const char *gateway)
234 struct gateway_config *config;
236 DBG("index %d gateway %s", index, gateway);
238 config = find_gateway(index, gateway);
242 config->active = TRUE;
245 static void set_default_gateway(struct gateway_data *data,
246 enum connman_ipconfig_type type)
249 int status4 = 0, status6 = 0;
250 int do_ipv4 = FALSE, do_ipv6 = FALSE;
252 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
254 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
257 do_ipv4 = do_ipv6 = TRUE;
259 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
262 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
263 data->ipv4_gateway->vpn == TRUE) {
264 connman_inet_set_gateway_address(data->index,
265 data->ipv4_gateway->vpn_ip);
266 data->ipv4_gateway->active = TRUE;
268 DBG("set %p index %d vpn %s index %d phy %s",
269 data, data->index, data->ipv4_gateway->vpn_ip,
270 data->ipv4_gateway->vpn_phy_index,
271 data->ipv4_gateway->vpn_phy_ip);
273 __connman_service_indicate_default(data->service);
278 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
279 data->ipv6_gateway->vpn == TRUE) {
280 connman_inet_set_ipv6_gateway_address(data->index,
281 data->ipv6_gateway->vpn_ip);
282 data->ipv6_gateway->active = TRUE;
284 DBG("set %p index %d vpn %s index %d phy %s",
285 data, data->index, data->ipv6_gateway->vpn_ip,
286 data->ipv6_gateway->vpn_phy_index,
287 data->ipv6_gateway->vpn_phy_ip);
289 __connman_service_indicate_default(data->service);
294 index = __connman_service_get_index(data->service);
296 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
297 g_strcmp0(data->ipv4_gateway->gateway,
299 if (connman_inet_set_gateway_interface(index) < 0)
304 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
305 g_strcmp0(data->ipv6_gateway->gateway,
307 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
312 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
313 status6 = connman_inet_set_ipv6_gateway_address(index,
314 data->ipv6_gateway->gateway);
316 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
317 status4 = connman_inet_set_gateway_address(index,
318 data->ipv4_gateway->gateway);
320 if (status4 < 0 || status6 < 0)
324 __connman_service_indicate_default(data->service);
327 static void unset_default_gateway(struct gateway_data *data,
328 enum connman_ipconfig_type type)
331 int do_ipv4 = FALSE, do_ipv6 = FALSE;
333 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
335 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
338 do_ipv4 = do_ipv6 = TRUE;
340 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
343 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
344 data->ipv4_gateway->vpn == TRUE) {
345 connman_inet_del_host_route(data->index,
346 data->ipv4_gateway->vpn_ip);
347 connman_inet_clear_gateway_address(data->index,
348 data->ipv4_gateway->vpn_ip);
349 data->ipv4_gateway->active = FALSE;
351 DBG("unset %p index %d vpn %s index %d phy %s",
352 data, data->index, data->ipv4_gateway->vpn_ip,
353 data->ipv4_gateway->vpn_phy_index,
354 data->ipv4_gateway->vpn_phy_ip);
359 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
360 data->ipv6_gateway->vpn == TRUE) {
361 connman_inet_del_ipv6_host_route(data->index,
362 data->ipv6_gateway->vpn_ip);
363 connman_inet_clear_ipv6_gateway_address(data->index,
364 data->ipv6_gateway->vpn_ip);
365 data->ipv6_gateway->active = FALSE;
367 DBG("unset %p index %d vpn %s index %d phy %s",
368 data, data->index, data->ipv6_gateway->vpn_ip,
369 data->ipv6_gateway->vpn_phy_index,
370 data->ipv6_gateway->vpn_phy_ip);
375 index = __connman_service_get_index(data->service);
377 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
378 g_strcmp0(data->ipv4_gateway->gateway,
380 connman_inet_clear_gateway_interface(index);
384 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
385 g_strcmp0(data->ipv6_gateway->gateway,
387 connman_inet_clear_ipv6_gateway_interface(index);
391 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
392 connman_inet_clear_ipv6_gateway_address(index,
393 data->ipv6_gateway->gateway);
395 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
396 connman_inet_clear_gateway_address(index,
397 data->ipv4_gateway->gateway);
400 static struct gateway_data *find_default_gateway(void)
402 struct gateway_data *found = NULL;
403 unsigned int order = 0;
407 g_hash_table_iter_init(&iter, gateway_hash);
409 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
410 struct gateway_data *data = value;
412 if (found == NULL || data->order > order) {
416 DBG("default %p order %d", found, order);
423 static void remove_gateway(gpointer user_data)
425 struct gateway_data *data = user_data;
427 DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
429 if (data->ipv4_gateway != NULL) {
430 g_free(data->ipv4_gateway->gateway);
431 g_free(data->ipv4_gateway->vpn_ip);
432 g_free(data->ipv4_gateway->vpn_phy_ip);
433 g_free(data->ipv4_gateway);
436 if (data->ipv6_gateway != NULL) {
437 g_free(data->ipv6_gateway->gateway);
438 g_free(data->ipv6_gateway->vpn_ip);
439 g_free(data->ipv6_gateway->vpn_phy_ip);
440 g_free(data->ipv6_gateway);
446 static void connection_delgateway(int index, const char *gateway)
448 struct gateway_config *config;
449 struct gateway_data *data;
451 DBG("index %d gateway %s", index, gateway);
453 config = find_gateway(index, gateway);
455 config->active = FALSE;
457 data = find_default_gateway();
459 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
462 static struct connman_rtnl connection_rtnl = {
463 .name = "connection",
464 .newgateway = connection_newgateway,
465 .delgateway = connection_delgateway,
468 static struct gateway_data *find_active_gateway(void)
475 g_hash_table_iter_init(&iter, gateway_hash);
477 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
478 struct gateway_data *data = value;
480 if (data->ipv4_gateway != NULL &&
481 data->ipv4_gateway->active == TRUE)
484 if (data->ipv6_gateway != NULL &&
485 data->ipv6_gateway->active == TRUE)
492 static void update_order(void)
499 g_hash_table_iter_init(&iter, gateway_hash);
501 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
502 struct gateway_data *data = value;
504 data->order = __connman_service_get_order(data->service);
508 void __connman_connection_gateway_activate(struct connman_service *service,
509 enum connman_ipconfig_type type)
511 struct gateway_data *data = NULL;
513 data = g_hash_table_lookup(gateway_hash, service);
517 DBG("gateway %p/%p type %d", data->ipv4_gateway,
518 data->ipv6_gateway, type);
520 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
521 data->ipv4_gateway->active = TRUE;
522 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
523 data->ipv6_gateway->active = TRUE;
526 int __connman_connection_gateway_add(struct connman_service *service,
528 enum connman_ipconfig_type type,
531 struct gateway_data *active_gateway = NULL;
532 struct gateway_data *new_gateway = NULL;
533 enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
534 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
537 index = __connman_service_get_index(service);
540 * If gateway is NULL, it's a point to point link and the default
541 * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
544 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
547 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
550 DBG("service %p index %d gateway %s vpn ip %s type %d",
551 service, index, gateway, peer, type);
553 new_gateway = add_gateway(service, index, gateway, type);
554 if (new_gateway == NULL)
557 active_gateway = find_active_gateway();
559 DBG("active %p index %d new %p", active_gateway,
560 active_gateway ? active_gateway->index : -1, new_gateway);
562 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
563 new_gateway->ipv6_gateway != NULL &&
564 g_strcmp0(new_gateway->ipv6_gateway->gateway,
566 connman_inet_add_ipv6_host_route(index,
567 new_gateway->ipv6_gateway->gateway,
570 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
571 new_gateway->ipv4_gateway != NULL &&
572 g_strcmp0(new_gateway->ipv4_gateway->gateway,
574 connman_inet_add_host_route(index,
575 new_gateway->ipv4_gateway->gateway,
578 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
579 new_gateway->ipv4_gateway != NULL) {
580 __connman_service_nameserver_add_routes(service,
581 new_gateway->ipv4_gateway->gateway);
582 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
585 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
586 new_gateway->ipv6_gateway != NULL) {
587 __connman_service_nameserver_add_routes(service,
588 new_gateway->ipv6_gateway->gateway);
589 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
592 if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_VPN) {
593 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
594 new_gateway->ipv4_gateway != NULL) {
595 new_gateway->ipv4_gateway->vpn = TRUE;
597 new_gateway->ipv4_gateway->vpn_ip =
599 else if (gateway != NULL)
600 new_gateway->ipv4_gateway->vpn_ip =
602 if (active_gateway) {
603 const char *new_ipv4_gateway;
606 active_gateway->ipv4_gateway->gateway;
607 if (new_ipv4_gateway != NULL &&
608 g_strcmp0(new_ipv4_gateway,
610 new_gateway->ipv4_gateway->vpn_phy_ip =
611 g_strdup(new_ipv4_gateway);
613 new_gateway->ipv4_gateway->vpn_phy_index =
614 active_gateway->index;
617 DBG("vpn %s phy %s index %d",
618 new_gateway->ipv4_gateway->vpn_ip,
619 new_gateway->ipv4_gateway->vpn_phy_ip,
620 new_gateway->ipv4_gateway->vpn_phy_index);
622 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
623 new_gateway->ipv6_gateway != NULL) {
624 new_gateway->ipv6_gateway->vpn = TRUE;
626 new_gateway->ipv6_gateway->vpn_ip =
628 else if (gateway != NULL)
629 new_gateway->ipv6_gateway->vpn_ip =
631 if (active_gateway) {
632 const char *new_ipv6_gateway;
635 active_gateway->ipv6_gateway->gateway;
636 if (new_ipv6_gateway != NULL &&
637 g_strcmp0(new_ipv6_gateway, "::") != 0)
638 new_gateway->ipv6_gateway->vpn_phy_ip =
639 g_strdup(new_ipv6_gateway);
641 new_gateway->ipv6_gateway->vpn_phy_index =
642 active_gateway->index;
645 DBG("vpn %s phy %s index %d",
646 new_gateway->ipv6_gateway->vpn_ip,
647 new_gateway->ipv6_gateway->vpn_phy_ip,
648 new_gateway->ipv6_gateway->vpn_phy_index);
651 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
652 new_gateway->ipv4_gateway != NULL)
653 new_gateway->ipv4_gateway->vpn = FALSE;
655 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
656 new_gateway->ipv6_gateway != NULL)
657 new_gateway->ipv6_gateway->vpn = FALSE;
660 if (active_gateway == NULL) {
661 set_default_gateway(new_gateway, type);
665 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
666 new_gateway->ipv4_gateway != NULL &&
667 new_gateway->ipv4_gateway->vpn == TRUE) {
668 connman_inet_add_host_route(active_gateway->index,
669 new_gateway->ipv4_gateway->gateway,
670 active_gateway->ipv4_gateway->gateway);
671 connman_inet_clear_gateway_address(active_gateway->index,
672 active_gateway->ipv4_gateway->gateway);
675 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
676 new_gateway->ipv6_gateway != NULL &&
677 new_gateway->ipv6_gateway->vpn == TRUE) {
678 connman_inet_add_ipv6_host_route(active_gateway->index,
679 new_gateway->ipv6_gateway->gateway,
680 active_gateway->ipv6_gateway->gateway);
681 connman_inet_clear_ipv6_gateway_address(active_gateway->index,
682 active_gateway->ipv6_gateway->gateway);
686 if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
687 __connman_service_ipconfig_indicate_state(service,
688 CONNMAN_SERVICE_STATE_READY,
689 CONNMAN_IPCONFIG_TYPE_IPV4);
691 if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
692 __connman_service_ipconfig_indicate_state(service,
693 CONNMAN_SERVICE_STATE_READY,
694 CONNMAN_IPCONFIG_TYPE_IPV6);
698 void __connman_connection_gateway_remove(struct connman_service *service,
699 enum connman_ipconfig_type type)
701 struct gateway_data *data = NULL;
702 gboolean set_default4 = FALSE, set_default6 = FALSE;
703 int do_ipv4 = FALSE, do_ipv6 = FALSE;
706 DBG("service %p type %d", service, type);
708 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
710 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
713 do_ipv4 = do_ipv6 = TRUE;
715 __connman_service_nameserver_del_routes(service, type);
717 data = g_hash_table_lookup(gateway_hash, service);
721 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
722 set_default4 = data->ipv4_gateway->vpn;
724 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
725 set_default6 = data->ipv6_gateway->vpn;
727 DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
728 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
729 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
730 set_default4, set_default6);
732 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
733 data->ipv4_gateway->vpn == TRUE && data->index >= 0)
734 connman_inet_del_host_route(data->index,
735 data->ipv4_gateway->gateway);
737 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
738 data->ipv6_gateway->vpn == TRUE && data->index >= 0)
739 connman_inet_del_ipv6_host_route(data->index,
740 data->ipv6_gateway->gateway);
742 err = disable_gateway(data, type);
745 * We remove the service from the hash only if all the gateway
746 * settings are to be removed.
748 if (do_ipv4 == do_ipv6 ||
749 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
750 && do_ipv4 == TRUE) ||
751 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
754 connman_service_unref(service);
755 g_hash_table_remove(gateway_hash, service);
757 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
758 data->ipv4_gateway, do_ipv4,
759 data->ipv6_gateway, do_ipv6);
761 /* with vpn this will be called after the network was deleted,
762 * we need to call set_default here because we will not recieve any
763 * gateway delete notification.
764 * We hit the same issue if remove_gateway() fails.
766 if (set_default4 || set_default6 || err < 0) {
767 data = find_default_gateway();
769 set_default_gateway(data, type);
773 gboolean __connman_connection_update_gateway(void)
775 struct gateway_data *active_gateway, *default_gateway;
776 gboolean updated = FALSE;
778 if (gateway_hash == NULL)
781 active_gateway = find_active_gateway();
785 default_gateway = find_default_gateway();
787 DBG("active %p default %p", active_gateway, default_gateway);
789 if (active_gateway && active_gateway != default_gateway) {
792 if (active_gateway->ipv4_gateway)
793 unset_default_gateway(active_gateway,
794 CONNMAN_IPCONFIG_TYPE_IPV4);
796 if (active_gateway->ipv6_gateway)
797 unset_default_gateway(active_gateway,
798 CONNMAN_IPCONFIG_TYPE_IPV6);
800 if (default_gateway) {
801 if (default_gateway->ipv4_gateway)
802 set_default_gateway(default_gateway,
803 CONNMAN_IPCONFIG_TYPE_IPV4);
805 if (default_gateway->ipv6_gateway)
806 set_default_gateway(default_gateway,
807 CONNMAN_IPCONFIG_TYPE_IPV6);
814 int __connman_connection_init(void)
820 gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
821 NULL, remove_gateway);
823 err = connman_rtnl_register(&connection_rtnl);
825 connman_error("Failed to setup RTNL gateway driver");
830 void __connman_connection_cleanup(void)
837 connman_rtnl_unregister(&connection_rtnl);
839 g_hash_table_iter_init(&iter, gateway_hash);
841 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
842 struct gateway_data *data = value;
844 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
847 g_hash_table_destroy(gateway_hash);