connection: Set proper gateway for ppp links
[framework/connectivity/connman.git] / src / connection.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
7  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <errno.h>
28 #include <string.h>
29 #include <net/if.h>
30
31 #include <gdbus.h>
32
33 #include "connman.h"
34
35 struct gateway_config {
36         gboolean active;
37         char *gateway;
38
39         /* VPN extra data */
40         gboolean vpn;
41         char *vpn_ip;
42         int vpn_phy_index;
43 };
44
45 struct gateway_data {
46         int index;
47         struct connman_service *service;
48         unsigned int order;
49         struct gateway_config *ipv4_gateway;
50         struct gateway_config *ipv6_gateway;
51 };
52
53 static GHashTable *gateway_hash = NULL;
54
55 static struct gateway_config *find_gateway(int index, const char *gateway)
56 {
57         GHashTableIter iter;
58         gpointer value, key;
59
60         if (gateway == NULL)
61                 return NULL;
62
63         g_hash_table_iter_init(&iter, gateway_hash);
64
65         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
66                 struct gateway_data *data = value;
67
68                 if (data->ipv4_gateway != NULL && data->index == index &&
69                                 g_str_equal(data->ipv4_gateway->gateway,
70                                         gateway) == TRUE)
71                         return data->ipv4_gateway;
72
73                 if (data->ipv6_gateway != NULL && data->index == index &&
74                                 g_str_equal(data->ipv6_gateway->gateway,
75                                         gateway) == TRUE)
76                         return data->ipv6_gateway;
77         }
78
79         return NULL;
80 }
81
82 static int del_routes(struct gateway_data *data,
83                         enum connman_ipconfig_type type)
84 {
85         int status4 = 0, status6 = 0;
86         int do_ipv4 = FALSE, do_ipv6 = FALSE;
87
88         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
89                 do_ipv4 = TRUE;
90         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
91                 do_ipv6 = TRUE;
92         else
93                 do_ipv4 = do_ipv6 = TRUE;
94
95         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) {
96                 if (data->ipv4_gateway->vpn == TRUE) {
97                         if (data->ipv4_gateway->vpn_phy_index >= 0)
98                                 connman_inet_del_host_route(
99                                         data->ipv4_gateway->vpn_phy_index,
100                                         data->ipv4_gateway->gateway);
101
102                         status4 = connman_inet_clear_gateway_address(
103                                                 data->index,
104                                                 data->ipv4_gateway->vpn_ip);
105
106                 } else if (g_strcmp0(data->ipv4_gateway->gateway,
107                                                         "0.0.0.0") == 0) {
108                         status4 = connman_inet_clear_gateway_interface(
109                                                                 data->index);
110                 } else {
111                         connman_inet_del_host_route(data->index,
112                                                 data->ipv4_gateway->gateway);
113                         status4 = connman_inet_clear_gateway_address(
114                                                 data->index,
115                                                 data->ipv4_gateway->gateway);
116                 }
117         }
118
119         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) {
120                 if (data->ipv6_gateway->vpn == TRUE) {
121                         if (data->ipv6_gateway->vpn_phy_index >= 0)
122                                 connman_inet_del_host_route(
123                                         data->ipv6_gateway->vpn_phy_index,
124                                         data->ipv6_gateway->gateway);
125
126                         status6 = connman_inet_clear_ipv6_gateway_address(
127                                                 data->index,
128                                                 data->ipv6_gateway->vpn_ip);
129
130                 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
131                         status6 = connman_inet_clear_ipv6_gateway_interface(
132                                                                 data->index);
133                 } else {
134                         connman_inet_del_ipv6_host_route(data->index,
135                                                 data->ipv6_gateway->gateway);
136                         status6 = connman_inet_clear_ipv6_gateway_address(
137                                                 data->index,
138                                                 data->ipv6_gateway->gateway);
139                 }
140         }
141
142         return (status4 < 0 ? status4 : status6);
143 }
144
145 static int disable_gateway(struct gateway_data *data,
146                         enum connman_ipconfig_type type)
147 {
148         gboolean active = FALSE;
149
150         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
151                 if (data->ipv4_gateway != NULL)
152                         active = data->ipv4_gateway->active;
153         } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
154                 if (data->ipv6_gateway != NULL)
155                         active = data->ipv6_gateway->active;
156         } else
157                 active = TRUE;
158
159         DBG("type %d active %d", type, active);
160
161         if (active == TRUE)
162                 return del_routes(data, type);
163
164         return 0;
165 }
166
167 static struct gateway_data *add_gateway(struct connman_service *service,
168                                         int index, const char *gateway,
169                                         enum connman_ipconfig_type type)
170 {
171         struct gateway_data *data, *old;
172         struct gateway_config *config;
173
174         if (gateway == NULL || strlen(gateway) == 0)
175                 return NULL;
176
177         data = g_try_new0(struct gateway_data, 1);
178         if (data == NULL)
179                 return NULL;
180
181         data->index = index;
182
183         config = g_try_new0(struct gateway_config, 1);
184         if (config == NULL) {
185                 g_free(data);
186                 return NULL;
187         }
188
189         config->gateway = g_strdup(gateway);
190         config->vpn_ip = NULL;
191         config->vpn = FALSE;
192         config->vpn_phy_index = -1;
193         config->active = FALSE;
194
195         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
196                 data->ipv4_gateway = config;
197         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
198                 data->ipv6_gateway = config;
199         else {
200                 g_free(config->gateway);
201                 g_free(config);
202                 g_free(data);
203                 return NULL;
204         }
205
206         data->service = service;
207
208         data->order = __connman_service_get_order(service);
209
210         /*
211          * If the service is already in the hash, then we
212          * must not replace it blindly but disable the gateway
213          * of the type we are replacing and take the other type
214          * from old gateway settings.
215          */
216         old = g_hash_table_lookup(gateway_hash, service);
217         if (old != NULL) {
218                 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
219                         old->ipv4_gateway, old->ipv6_gateway);
220                 disable_gateway(old, type);
221                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
222                         data->ipv6_gateway = old->ipv6_gateway;
223                         old->ipv6_gateway = NULL;
224                 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
225                         data->ipv4_gateway = old->ipv4_gateway;
226                         old->ipv4_gateway = NULL;
227                 }
228         }
229
230         g_hash_table_replace(gateway_hash, service, data);
231
232         return data;
233 }
234
235 static void connection_newgateway(int index, const char *gateway)
236 {
237         struct gateway_config *config;
238
239         DBG("index %d gateway %s", index, gateway);
240
241         config = find_gateway(index, gateway);
242         if (config == NULL)
243                 return;
244
245         config->active = TRUE;
246 }
247
248 static void set_default_gateway(struct gateway_data *data,
249                                 enum connman_ipconfig_type type)
250 {
251         int index;
252         int status4 = 0, status6 = 0;
253         int do_ipv4 = FALSE, do_ipv6 = FALSE;
254
255         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
256                 do_ipv4 = TRUE;
257         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
258                 do_ipv6 = TRUE;
259         else
260                 do_ipv4 = do_ipv6 = TRUE;
261
262         DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
263                                                 data->ipv6_gateway);
264
265         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
266                                         data->ipv4_gateway->vpn == TRUE) {
267                 connman_inet_set_gateway_address(data->index,
268                                                 data->ipv4_gateway->vpn_ip);
269                 data->ipv4_gateway->active = TRUE;
270
271                 __connman_service_indicate_default(data->service);
272
273                 return;
274         }
275
276         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
277                                         data->ipv6_gateway->vpn == TRUE) {
278                 connman_inet_set_ipv6_gateway_address(data->index,
279                                                 data->ipv6_gateway->vpn_ip);
280                 data->ipv6_gateway->active = TRUE;
281
282                 __connman_service_indicate_default(data->service);
283
284                 return;
285         }
286
287         index = __connman_service_get_index(data->service);
288
289         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
290                         g_strcmp0(data->ipv4_gateway->gateway,
291                                                         "0.0.0.0") == 0) {
292                 if (connman_inet_set_gateway_interface(index) < 0)
293                         return;
294                 goto done;
295         }
296
297         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
298                         g_strcmp0(data->ipv6_gateway->gateway,
299                                                         "::") == 0) {
300                 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
301                         return;
302                 goto done;
303         }
304
305         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
306                 status6 = connman_inet_set_ipv6_gateway_address(index,
307                                                 data->ipv6_gateway->gateway);
308
309         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
310                 status4 = connman_inet_set_gateway_address(index,
311                                                 data->ipv4_gateway->gateway);
312
313         if (status4 < 0 || status6 < 0)
314                 return;
315
316 done:
317         __connman_service_indicate_default(data->service);
318 }
319
320 static struct gateway_data *find_default_gateway(void)
321 {
322         struct gateway_data *found = NULL;
323         unsigned int order = 0;
324         GHashTableIter iter;
325         gpointer value, key;
326
327         g_hash_table_iter_init(&iter, gateway_hash);
328
329         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
330                 struct gateway_data *data = value;
331
332                 if (found == NULL || data->order > order) {
333                         found = data;
334                         order = data->order;
335                 }
336         }
337
338         return found;
339 }
340
341 static void remove_gateway(gpointer user_data)
342 {
343         struct gateway_data *data = user_data;
344
345         DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
346
347         if (data->ipv4_gateway != NULL) {
348                 g_free(data->ipv4_gateway->gateway);
349                 g_free(data->ipv4_gateway->vpn_ip);
350                 g_free(data->ipv4_gateway);
351         }
352
353         if (data->ipv6_gateway != NULL) {
354                 g_free(data->ipv6_gateway->gateway);
355                 g_free(data->ipv6_gateway->vpn_ip);
356                 g_free(data->ipv6_gateway);
357         }
358
359         g_free(data);
360 }
361
362 static void connection_delgateway(int index, const char *gateway)
363 {
364         struct gateway_config *config;
365         struct gateway_data *data;
366
367         DBG("index %d gateway %s", index, gateway);
368
369         config = find_gateway(index, gateway);
370         if (config != NULL)
371                 config->active = FALSE;
372
373         data = find_default_gateway();
374         if (data != NULL)
375                 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
376 }
377
378 static struct connman_rtnl connection_rtnl = {
379         .name           = "connection",
380         .newgateway     = connection_newgateway,
381         .delgateway     = connection_delgateway,
382 };
383
384 static struct gateway_data *find_active_gateway(void)
385 {
386         GHashTableIter iter;
387         gpointer value, key;
388
389         DBG("");
390
391         g_hash_table_iter_init(&iter, gateway_hash);
392
393         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
394                 struct gateway_data *data = value;
395
396                 if (data->ipv4_gateway != NULL &&
397                                 data->ipv4_gateway->active == TRUE)
398                         return data;
399
400                 if (data->ipv6_gateway != NULL &&
401                                 data->ipv6_gateway->active == TRUE)
402                         return data;
403         }
404
405         return NULL;
406 }
407
408 static void update_order(void)
409 {
410         GHashTableIter iter;
411         gpointer value, key;
412
413         DBG("");
414
415         g_hash_table_iter_init(&iter, gateway_hash);
416
417         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
418                 struct gateway_data *data = value;
419
420                 data->order = __connman_service_get_order(data->service);
421         }
422 }
423
424 void __connman_connection_gateway_activate(struct connman_service *service,
425                                         enum connman_ipconfig_type type)
426 {
427         struct gateway_data *data = NULL;
428
429         data = g_hash_table_lookup(gateway_hash, service);
430         if (data == NULL)
431                 return;
432
433         DBG("gateway %p/%p type %d", data->ipv4_gateway,
434                                         data->ipv6_gateway, type);
435
436         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
437                 data->ipv4_gateway->active = TRUE;
438         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
439                 data->ipv6_gateway->active = TRUE;
440 }
441
442 int __connman_connection_gateway_add(struct connman_service *service,
443                                         const char *gateway,
444                                         enum connman_ipconfig_type type,
445                                         const char *peer)
446 {
447         struct gateway_data *active_gateway = NULL;
448         struct gateway_data *new_gateway = NULL;
449         int index;
450
451         index = __connman_service_get_index(service);
452
453         DBG("service %p index %d gateway %s vpn ip %s type %d",
454                 service, index, gateway, peer, type);
455
456         /*
457          * If gateway is NULL, it's a point to point link and the default
458          * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
459          * interface
460          */
461         if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
462                 gateway = "0.0.0.0";
463
464         if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
465                 gateway = "::";
466
467         active_gateway = find_active_gateway();
468         new_gateway = add_gateway(service, index, gateway, type);
469         if (new_gateway == NULL)
470                 return -EINVAL;
471
472         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
473                         new_gateway->ipv6_gateway != NULL &&
474                         g_strcmp0(new_gateway->ipv6_gateway->gateway,
475                                                                 "::") != 0)
476                 connman_inet_add_ipv6_host_route(index,
477                                         new_gateway->ipv6_gateway->gateway,
478                                         NULL);
479
480         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
481                         new_gateway->ipv4_gateway != NULL &&
482                         g_strcmp0(new_gateway->ipv4_gateway->gateway,
483                                                         "0.0.0.0") != 0)
484                 connman_inet_add_host_route(index,
485                                         new_gateway->ipv4_gateway->gateway,
486                                         NULL);
487
488         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
489                                 new_gateway->ipv4_gateway != NULL) {
490                 __connman_service_nameserver_add_routes(service,
491                                         new_gateway->ipv4_gateway->gateway);
492                 __connman_service_ipconfig_indicate_state(service,
493                                                 CONNMAN_SERVICE_STATE_READY,
494                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
495         }
496
497         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
498                                 new_gateway->ipv6_gateway != NULL) {
499                 __connman_service_nameserver_add_routes(service,
500                                         new_gateway->ipv6_gateway->gateway);
501                 __connman_service_ipconfig_indicate_state(service,
502                                                 CONNMAN_SERVICE_STATE_READY,
503                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
504         }
505
506         if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_VPN) {
507                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
508                                         new_gateway->ipv4_gateway != NULL) {
509                         new_gateway->ipv4_gateway->vpn = TRUE;
510                         if (peer != NULL)
511                                 new_gateway->ipv4_gateway->vpn_ip =
512                                                         g_strdup(peer);
513                         else if (gateway != NULL)
514                                 new_gateway->ipv4_gateway->vpn_ip =
515                                                         g_strdup(gateway);
516                         if (active_gateway)
517                                 new_gateway->ipv4_gateway->vpn_phy_index =
518                                                         active_gateway->index;
519
520                 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
521                                         new_gateway->ipv6_gateway != NULL) {
522                         new_gateway->ipv6_gateway->vpn = TRUE;
523                         if (peer != NULL)
524                                 new_gateway->ipv6_gateway->vpn_ip =
525                                                         g_strdup(peer);
526                         else if (gateway != NULL)
527                                 new_gateway->ipv6_gateway->vpn_ip =
528                                                         g_strdup(gateway);
529                         if (active_gateway)
530                                 new_gateway->ipv6_gateway->vpn_phy_index =
531                                                         active_gateway->index;
532                 }
533         } else {
534                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
535                                         new_gateway->ipv4_gateway != NULL)
536                         new_gateway->ipv4_gateway->vpn = FALSE;
537
538                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
539                                         new_gateway->ipv6_gateway != NULL)
540                         new_gateway->ipv6_gateway->vpn = FALSE;
541         }
542
543         if (active_gateway == NULL) {
544                 set_default_gateway(new_gateway, type);
545                 return 0;
546         }
547
548         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
549                                 new_gateway->ipv4_gateway != NULL &&
550                                 new_gateway->ipv4_gateway->vpn == TRUE) {
551                 connman_inet_add_host_route(active_gateway->index,
552                                         new_gateway->ipv4_gateway->gateway,
553                                         active_gateway->ipv4_gateway->gateway);
554                 connman_inet_clear_gateway_address(active_gateway->index,
555                                         active_gateway->ipv4_gateway->gateway);
556         }
557
558         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
559                                 new_gateway->ipv6_gateway != NULL &&
560                                 new_gateway->ipv6_gateway->vpn == TRUE) {
561                 connman_inet_add_ipv6_host_route(active_gateway->index,
562                                         new_gateway->ipv6_gateway->gateway,
563                                         active_gateway->ipv6_gateway->gateway);
564                 connman_inet_clear_ipv6_gateway_address(active_gateway->index,
565                                         active_gateway->ipv6_gateway->gateway);
566         }
567
568         return 0;
569 }
570
571 void __connman_connection_gateway_remove(struct connman_service *service,
572                                         enum connman_ipconfig_type type)
573 {
574         struct gateway_data *data = NULL;
575         gboolean set_default4 = FALSE, set_default6 = FALSE;
576         int do_ipv4 = FALSE, do_ipv6 = FALSE;
577         int err;
578
579         DBG("service %p type %d", service, type);
580
581         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
582                 do_ipv4 = TRUE;
583         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
584                 do_ipv6 = TRUE;
585         else
586                 do_ipv4 = do_ipv6 = TRUE;
587
588         __connman_service_nameserver_del_routes(service);
589
590         data = g_hash_table_lookup(gateway_hash, service);
591         if (data == NULL)
592                 return;
593
594         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
595                 set_default4 = data->ipv4_gateway->vpn;
596
597         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
598                 set_default6 = data->ipv6_gateway->vpn;
599
600         DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
601                 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
602                 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
603                 set_default4, set_default6);
604
605         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
606                         data->ipv4_gateway->vpn == TRUE && data->index >= 0)
607                 connman_inet_del_host_route(data->index,
608                                                 data->ipv4_gateway->gateway);
609
610         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
611                         data->ipv6_gateway->vpn == TRUE && data->index >= 0)
612                 connman_inet_del_ipv6_host_route(data->index,
613                                                 data->ipv6_gateway->gateway);
614
615         __connman_service_nameserver_del_routes(service);
616
617         err = disable_gateway(data, type);
618
619         /*
620          * We remove the service from the hash only if all the gateway
621          * settings are to be removed.
622          */
623         if (do_ipv4 == do_ipv6 ||
624                 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
625                         && do_ipv4 == TRUE) ||
626                 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
627                         && do_ipv6 == TRUE)
628                 )
629                 g_hash_table_remove(gateway_hash, service);
630         else
631                 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
632                         data->ipv4_gateway, do_ipv4,
633                         data->ipv6_gateway, do_ipv6);
634
635         /* with vpn this will be called after the network was deleted,
636          * we need to call set_default here because we will not recieve any
637          * gateway delete notification.
638          * We hit the same issue if remove_gateway() fails.
639          */
640         if (set_default4 || set_default6 || err < 0) {
641                 data = find_default_gateway();
642                 if (data != NULL)
643                         set_default_gateway(data, type);
644         }
645 }
646
647 gboolean __connman_connection_update_gateway(void)
648 {
649         struct gateway_data *active_gateway, *default_gateway;
650         gboolean updated = FALSE;
651
652         if (gateway_hash == NULL)
653                 return updated;
654
655         update_order();
656
657         active_gateway = find_active_gateway();
658         default_gateway = find_default_gateway();
659
660         if (active_gateway && active_gateway != default_gateway)
661                 updated = TRUE;
662
663         return updated;
664 }
665
666 int __connman_connection_init(void)
667 {
668         int err;
669
670         DBG("");
671
672         gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
673                                                         NULL, remove_gateway);
674
675         err = connman_rtnl_register(&connection_rtnl);
676         if (err < 0)
677                 connman_error("Failed to setup RTNL gateway driver");
678
679         return err;
680 }
681
682 void __connman_connection_cleanup(void)
683 {
684         GHashTableIter iter;
685         gpointer value, key;
686
687         DBG("");
688
689         connman_rtnl_unregister(&connection_rtnl);
690
691         g_hash_table_iter_init(&iter, gateway_hash);
692
693         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
694                 struct gateway_data *data = value;
695
696                 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
697         }
698
699         g_hash_table_destroy(gateway_hash);
700         gateway_hash = NULL;
701 }