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;
84 * Find the gateway that is serving the VPN link
86 static struct gateway_data *find_phy_gateway(int index, const char *gateway)
94 g_hash_table_iter_init(&iter, gateway_hash);
96 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
97 struct gateway_data *data = value;
99 if (data->ipv4_gateway != NULL && data->index != index &&
100 g_str_equal(data->ipv4_gateway->gateway,
104 if (data->ipv6_gateway != NULL && data->index != index &&
105 g_str_equal(data->ipv6_gateway->gateway,
113 static void set_vpn_routes(struct gateway_config *config,
114 struct connman_service *service,
116 enum connman_ipconfig_type type,
119 struct gateway_data *data;
120 struct connman_ipconfig *ipconfig;
125 config->vpn_ip = g_strdup(peer);
126 else if (gateway != NULL)
127 config->vpn_ip = g_strdup(gateway);
129 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
130 ipconfig = __connman_service_get_ip4config(service);
131 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
132 ipconfig = __connman_service_get_ip6config(service);
136 index = __connman_ipconfig_get_index(ipconfig);
137 data = find_phy_gateway(index, gateway);
141 * data->service points now to original
142 * service that is serving the VPN link
144 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
146 __connman_service_get_ip4config(data->service);
147 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
149 __connman_service_get_ip6config(data->service);
153 if (ipconfig != NULL) {
156 address = __connman_ipconfig_get_local(ipconfig);
157 config->vpn_phy_ip = g_strdup(address);
160 config->vpn_phy_index = data->index;
163 DBG("vpn %s phy %s index %d", config->vpn_ip,
164 config->vpn_phy_ip, config->vpn_phy_index);
167 static int del_routes(struct gateway_data *data,
168 enum connman_ipconfig_type type)
170 int status4 = 0, status6 = 0;
171 int do_ipv4 = FALSE, do_ipv6 = FALSE;
173 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
175 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
178 do_ipv4 = do_ipv6 = TRUE;
180 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) {
181 if (data->ipv4_gateway->vpn == TRUE) {
182 status4 = connman_inet_clear_gateway_address(
184 data->ipv4_gateway->vpn_ip);
186 } else if (g_strcmp0(data->ipv4_gateway->gateway,
188 status4 = connman_inet_clear_gateway_interface(
191 connman_inet_del_host_route(data->index,
192 data->ipv4_gateway->gateway);
193 status4 = connman_inet_clear_gateway_address(
195 data->ipv4_gateway->gateway);
199 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) {
200 if (data->ipv6_gateway->vpn == TRUE) {
201 status6 = connman_inet_clear_ipv6_gateway_address(
203 data->ipv6_gateway->vpn_ip);
205 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
206 status6 = connman_inet_clear_ipv6_gateway_interface(
209 connman_inet_del_ipv6_host_route(data->index,
210 data->ipv6_gateway->gateway);
211 status6 = connman_inet_clear_ipv6_gateway_address(
213 data->ipv6_gateway->gateway);
217 return (status4 < 0 ? status4 : status6);
220 static int disable_gateway(struct gateway_data *data,
221 enum connman_ipconfig_type type)
223 gboolean active = FALSE;
225 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
226 if (data->ipv4_gateway != NULL)
227 active = data->ipv4_gateway->active;
228 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
229 if (data->ipv6_gateway != NULL)
230 active = data->ipv6_gateway->active;
234 DBG("type %d active %d", type, active);
237 return del_routes(data, type);
242 static struct gateway_data *add_gateway(struct connman_service *service,
243 int index, const char *gateway,
244 enum connman_ipconfig_type type)
246 struct gateway_data *data, *old;
247 struct gateway_config *config;
249 if (gateway == NULL || strlen(gateway) == 0)
252 data = g_try_new0(struct gateway_data, 1);
258 config = g_try_new0(struct gateway_config, 1);
259 if (config == NULL) {
264 config->gateway = g_strdup(gateway);
265 config->vpn_ip = NULL;
266 config->vpn_phy_ip = NULL;
268 config->vpn_phy_index = -1;
269 config->active = FALSE;
271 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
272 data->ipv4_gateway = config;
273 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
274 data->ipv6_gateway = config;
276 g_free(config->gateway);
282 data->service = service;
284 data->order = __connman_service_get_order(service);
287 * If the service is already in the hash, then we
288 * must not replace it blindly but disable the gateway
289 * of the type we are replacing and take the other type
290 * from old gateway settings.
292 old = g_hash_table_lookup(gateway_hash, service);
294 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
295 old->ipv4_gateway, old->ipv6_gateway);
296 disable_gateway(old, type);
297 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
298 data->ipv6_gateway = old->ipv6_gateway;
299 old->ipv6_gateway = NULL;
300 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
301 data->ipv4_gateway = old->ipv4_gateway;
302 old->ipv4_gateway = NULL;
306 * Only take a ref if we are adding new stuff to hash.
308 connman_service_ref(service);
311 g_hash_table_replace(gateway_hash, service, data);
316 static void connection_newgateway(int index, const char *gateway)
318 struct gateway_config *config;
320 DBG("index %d gateway %s", index, gateway);
322 config = find_gateway(index, gateway);
326 config->active = TRUE;
329 static void set_default_gateway(struct gateway_data *data,
330 enum connman_ipconfig_type type)
333 int status4 = 0, status6 = 0;
334 int do_ipv4 = FALSE, do_ipv6 = FALSE;
336 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
338 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
341 do_ipv4 = do_ipv6 = TRUE;
343 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
346 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
347 data->ipv4_gateway->vpn == TRUE) {
348 connman_inet_set_gateway_address(data->index,
349 data->ipv4_gateway->vpn_ip);
350 data->ipv4_gateway->active = TRUE;
352 DBG("set %p index %d vpn %s index %d phy %s",
353 data, data->index, data->ipv4_gateway->vpn_ip,
354 data->ipv4_gateway->vpn_phy_index,
355 data->ipv4_gateway->vpn_phy_ip);
357 __connman_service_indicate_default(data->service);
362 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
363 data->ipv6_gateway->vpn == TRUE) {
364 connman_inet_set_ipv6_gateway_address(data->index,
365 data->ipv6_gateway->vpn_ip);
366 data->ipv6_gateway->active = TRUE;
368 DBG("set %p index %d vpn %s index %d phy %s",
369 data, data->index, data->ipv6_gateway->vpn_ip,
370 data->ipv6_gateway->vpn_phy_index,
371 data->ipv6_gateway->vpn_phy_ip);
373 __connman_service_indicate_default(data->service);
378 index = __connman_service_get_index(data->service);
380 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
381 g_strcmp0(data->ipv4_gateway->gateway,
383 if (connman_inet_set_gateway_interface(index) < 0)
388 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
389 g_strcmp0(data->ipv6_gateway->gateway,
391 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
396 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
397 status6 = connman_inet_set_ipv6_gateway_address(index,
398 data->ipv6_gateway->gateway);
400 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
401 status4 = connman_inet_set_gateway_address(index,
402 data->ipv4_gateway->gateway);
404 if (status4 < 0 || status6 < 0)
408 __connman_service_indicate_default(data->service);
411 static void unset_default_gateway(struct gateway_data *data,
412 enum connman_ipconfig_type type)
415 int do_ipv4 = FALSE, do_ipv6 = FALSE;
417 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
419 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
422 do_ipv4 = do_ipv6 = TRUE;
424 DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
427 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
428 data->ipv4_gateway->vpn == TRUE) {
429 connman_inet_del_host_route(data->index,
430 data->ipv4_gateway->vpn_ip);
431 connman_inet_clear_gateway_address(data->index,
432 data->ipv4_gateway->vpn_ip);
433 data->ipv4_gateway->active = FALSE;
435 DBG("unset %p index %d vpn %s index %d phy %s",
436 data, data->index, data->ipv4_gateway->vpn_ip,
437 data->ipv4_gateway->vpn_phy_index,
438 data->ipv4_gateway->vpn_phy_ip);
443 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
444 data->ipv6_gateway->vpn == TRUE) {
445 connman_inet_del_ipv6_host_route(data->index,
446 data->ipv6_gateway->vpn_ip);
447 connman_inet_clear_ipv6_gateway_address(data->index,
448 data->ipv6_gateway->vpn_ip);
449 data->ipv6_gateway->active = FALSE;
451 DBG("unset %p index %d vpn %s index %d phy %s",
452 data, data->index, data->ipv6_gateway->vpn_ip,
453 data->ipv6_gateway->vpn_phy_index,
454 data->ipv6_gateway->vpn_phy_ip);
459 index = __connman_service_get_index(data->service);
461 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
462 g_strcmp0(data->ipv4_gateway->gateway,
464 connman_inet_clear_gateway_interface(index);
468 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
469 g_strcmp0(data->ipv6_gateway->gateway,
471 connman_inet_clear_ipv6_gateway_interface(index);
475 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
476 connman_inet_clear_ipv6_gateway_address(index,
477 data->ipv6_gateway->gateway);
479 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
480 connman_inet_clear_gateway_address(index,
481 data->ipv4_gateway->gateway);
484 static struct gateway_data *find_default_gateway(void)
486 struct gateway_data *found = NULL;
487 unsigned int order = 0;
491 g_hash_table_iter_init(&iter, gateway_hash);
493 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
494 struct gateway_data *data = value;
496 if (found == NULL || data->order > order) {
500 DBG("default %p order %d", found, order);
507 static void remove_gateway(gpointer user_data)
509 struct gateway_data *data = user_data;
511 DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
513 if (data->ipv4_gateway != NULL) {
514 g_free(data->ipv4_gateway->gateway);
515 g_free(data->ipv4_gateway->vpn_ip);
516 g_free(data->ipv4_gateway->vpn_phy_ip);
517 g_free(data->ipv4_gateway);
520 if (data->ipv6_gateway != NULL) {
521 g_free(data->ipv6_gateway->gateway);
522 g_free(data->ipv6_gateway->vpn_ip);
523 g_free(data->ipv6_gateway->vpn_phy_ip);
524 g_free(data->ipv6_gateway);
530 static void connection_delgateway(int index, const char *gateway)
532 struct gateway_config *config;
533 struct gateway_data *data;
535 DBG("index %d gateway %s", index, gateway);
537 config = find_gateway(index, gateway);
539 config->active = FALSE;
541 data = find_default_gateway();
543 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
546 static struct connman_rtnl connection_rtnl = {
547 .name = "connection",
548 .newgateway = connection_newgateway,
549 .delgateway = connection_delgateway,
552 static struct gateway_data *find_active_gateway(void)
559 g_hash_table_iter_init(&iter, gateway_hash);
561 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
562 struct gateway_data *data = value;
564 if (data->ipv4_gateway != NULL &&
565 data->ipv4_gateway->active == TRUE)
568 if (data->ipv6_gateway != NULL &&
569 data->ipv6_gateway->active == TRUE)
576 static void update_order(void)
583 g_hash_table_iter_init(&iter, gateway_hash);
585 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
586 struct gateway_data *data = value;
588 data->order = __connman_service_get_order(data->service);
592 void __connman_connection_gateway_activate(struct connman_service *service,
593 enum connman_ipconfig_type type)
595 struct gateway_data *data = NULL;
597 data = g_hash_table_lookup(gateway_hash, service);
601 DBG("gateway %p/%p type %d", data->ipv4_gateway,
602 data->ipv6_gateway, type);
604 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
605 data->ipv4_gateway->active = TRUE;
606 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
607 data->ipv6_gateway->active = TRUE;
610 int __connman_connection_gateway_add(struct connman_service *service,
612 enum connman_ipconfig_type type,
615 struct gateway_data *active_gateway = NULL;
616 struct gateway_data *new_gateway = NULL;
617 enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
618 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
621 index = __connman_service_get_index(service);
624 * If gateway is NULL, it's a point to point link and the default
625 * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
628 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
631 if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
634 DBG("service %p index %d gateway %s vpn ip %s type %d",
635 service, index, gateway, peer, type);
637 new_gateway = add_gateway(service, index, gateway, type);
638 if (new_gateway == NULL)
641 active_gateway = find_active_gateway();
643 DBG("active %p index %d new %p", active_gateway,
644 active_gateway ? active_gateway->index : -1, new_gateway);
646 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
647 new_gateway->ipv6_gateway != NULL &&
648 g_strcmp0(new_gateway->ipv6_gateway->gateway,
650 connman_inet_add_ipv6_host_route(index,
651 new_gateway->ipv6_gateway->gateway,
654 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
655 new_gateway->ipv4_gateway != NULL &&
656 g_strcmp0(new_gateway->ipv4_gateway->gateway,
658 connman_inet_add_host_route(index,
659 new_gateway->ipv4_gateway->gateway,
662 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
663 new_gateway->ipv4_gateway != NULL) {
664 __connman_service_nameserver_add_routes(service,
665 new_gateway->ipv4_gateway->gateway);
666 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
669 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
670 new_gateway->ipv6_gateway != NULL) {
671 __connman_service_nameserver_add_routes(service,
672 new_gateway->ipv6_gateway->gateway);
673 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
676 if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_VPN) {
677 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
678 new_gateway->ipv4_gateway != NULL)
679 set_vpn_routes(new_gateway->ipv4_gateway,
680 service, gateway, type, peer);
682 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
683 new_gateway->ipv6_gateway != NULL)
684 set_vpn_routes(new_gateway->ipv6_gateway,
685 service, gateway, type, peer);
688 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
689 new_gateway->ipv4_gateway != NULL)
690 new_gateway->ipv4_gateway->vpn = FALSE;
692 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
693 new_gateway->ipv6_gateway != NULL)
694 new_gateway->ipv6_gateway->vpn = FALSE;
697 if (active_gateway == NULL) {
698 set_default_gateway(new_gateway, type);
702 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
703 new_gateway->ipv4_gateway != NULL &&
704 new_gateway->ipv4_gateway->vpn == TRUE) {
705 connman_inet_clear_gateway_address(active_gateway->index,
706 active_gateway->ipv4_gateway->gateway);
709 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
710 new_gateway->ipv6_gateway != NULL &&
711 new_gateway->ipv6_gateway->vpn == TRUE) {
712 connman_inet_clear_ipv6_gateway_address(active_gateway->index,
713 active_gateway->ipv6_gateway->gateway);
717 if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
718 __connman_service_ipconfig_indicate_state(service,
719 CONNMAN_SERVICE_STATE_READY,
720 CONNMAN_IPCONFIG_TYPE_IPV4);
722 if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
723 __connman_service_ipconfig_indicate_state(service,
724 CONNMAN_SERVICE_STATE_READY,
725 CONNMAN_IPCONFIG_TYPE_IPV6);
729 void __connman_connection_gateway_remove(struct connman_service *service,
730 enum connman_ipconfig_type type)
732 struct gateway_data *data = NULL;
733 gboolean set_default4 = FALSE, set_default6 = FALSE;
734 int do_ipv4 = FALSE, do_ipv6 = FALSE;
737 DBG("service %p type %d", service, type);
739 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
741 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
744 do_ipv4 = do_ipv6 = TRUE;
746 __connman_service_nameserver_del_routes(service, type);
748 data = g_hash_table_lookup(gateway_hash, service);
752 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
753 set_default4 = data->ipv4_gateway->vpn;
755 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
756 set_default6 = data->ipv6_gateway->vpn;
758 DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
759 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
760 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
761 set_default4, set_default6);
763 if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
764 data->ipv4_gateway->vpn == TRUE && data->index >= 0)
765 connman_inet_del_host_route(data->index,
766 data->ipv4_gateway->gateway);
768 if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
769 data->ipv6_gateway->vpn == TRUE && data->index >= 0)
770 connman_inet_del_ipv6_host_route(data->index,
771 data->ipv6_gateway->gateway);
773 err = disable_gateway(data, type);
776 * We remove the service from the hash only if all the gateway
777 * settings are to be removed.
779 if (do_ipv4 == do_ipv6 ||
780 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
781 && do_ipv4 == TRUE) ||
782 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
785 connman_service_unref(service);
786 g_hash_table_remove(gateway_hash, service);
788 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
789 data->ipv4_gateway, do_ipv4,
790 data->ipv6_gateway, do_ipv6);
792 /* with vpn this will be called after the network was deleted,
793 * we need to call set_default here because we will not recieve any
794 * gateway delete notification.
795 * We hit the same issue if remove_gateway() fails.
797 if (set_default4 || set_default6 || err < 0) {
798 data = find_default_gateway();
800 set_default_gateway(data, type);
804 gboolean __connman_connection_update_gateway(void)
806 struct gateway_data *default_gateway;
807 gboolean updated = FALSE;
811 if (gateway_hash == NULL)
816 default_gateway = find_default_gateway();
818 DBG("default %p", default_gateway);
821 * There can be multiple active gateways so we need to
824 g_hash_table_iter_init(&iter, gateway_hash);
826 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
827 struct gateway_data *active_gateway = value;
829 if (active_gateway == default_gateway)
832 if (active_gateway->ipv4_gateway != NULL &&
833 active_gateway->ipv4_gateway->active == TRUE) {
835 unset_default_gateway(active_gateway,
836 CONNMAN_IPCONFIG_TYPE_IPV4);
840 if (active_gateway->ipv6_gateway != NULL &&
841 active_gateway->ipv6_gateway->active == TRUE) {
843 unset_default_gateway(active_gateway,
844 CONNMAN_IPCONFIG_TYPE_IPV6);
849 if (updated && default_gateway != NULL) {
850 if (default_gateway->ipv4_gateway)
851 set_default_gateway(default_gateway,
852 CONNMAN_IPCONFIG_TYPE_IPV4);
854 if (default_gateway->ipv6_gateway)
855 set_default_gateway(default_gateway,
856 CONNMAN_IPCONFIG_TYPE_IPV6);
862 int __connman_connection_init(void)
868 gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
869 NULL, remove_gateway);
871 err = connman_rtnl_register(&connection_rtnl);
873 connman_error("Failed to setup RTNL gateway driver");
878 void __connman_connection_cleanup(void)
885 connman_rtnl_unregister(&connection_rtnl);
887 g_hash_table_iter_init(&iter, gateway_hash);
889 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
890 struct gateway_data *data = value;
892 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
895 g_hash_table_destroy(gateway_hash);