provider: Disconnect VPN when phy service is disconnected
[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         char *vpn_phy_ip;
44 };
45
46 struct gateway_data {
47         int index;
48         struct connman_service *service;
49         unsigned int order;
50         struct gateway_config *ipv4_gateway;
51         struct gateway_config *ipv6_gateway;
52         connman_bool_t default_checked;
53 };
54
55 static GHashTable *gateway_hash = NULL;
56
57 static struct gateway_config *find_gateway(int index, const char *gateway)
58 {
59         GHashTableIter iter;
60         gpointer value, key;
61
62         if (gateway == NULL)
63                 return NULL;
64
65         g_hash_table_iter_init(&iter, gateway_hash);
66
67         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
68                 struct gateway_data *data = value;
69
70                 if (data->ipv4_gateway != NULL && data->index == index &&
71                                 g_str_equal(data->ipv4_gateway->gateway,
72                                         gateway) == TRUE)
73                         return data->ipv4_gateway;
74
75                 if (data->ipv6_gateway != NULL && data->index == index &&
76                                 g_str_equal(data->ipv6_gateway->gateway,
77                                         gateway) == TRUE)
78                         return data->ipv6_gateway;
79         }
80
81         return NULL;
82 }
83
84 static struct gateway_data *lookup_gateway_data(struct gateway_config *config)
85 {
86         GHashTableIter iter;
87         gpointer value, key;
88
89         if (config == NULL)
90                 return NULL;
91
92         g_hash_table_iter_init(&iter, gateway_hash);
93
94         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
95                 struct gateway_data *data = value;
96
97                 if (data->ipv4_gateway != NULL &&
98                                 data->ipv4_gateway == config)
99                         return data;
100
101                 if (data->ipv6_gateway != NULL &&
102                                 data->ipv6_gateway == config)
103                         return data;
104         }
105
106         return NULL;
107 }
108
109 /*
110  * Find the gateway that is serving the VPN link
111  */
112 static struct gateway_data *find_phy_gateway(int index, const char *gateway)
113 {
114         GHashTableIter iter;
115         gpointer value, key;
116
117         if (gateway == NULL)
118                 return NULL;
119
120         g_hash_table_iter_init(&iter, gateway_hash);
121
122         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
123                 struct gateway_data *data = value;
124
125                 if (data->ipv4_gateway != NULL && data->index != index &&
126                                 g_str_equal(data->ipv4_gateway->gateway,
127                                         gateway) == TRUE)
128                         return data;
129
130                 if (data->ipv6_gateway != NULL && data->index != index &&
131                                 g_str_equal(data->ipv6_gateway->gateway,
132                                         gateway) == TRUE)
133                         return data;
134         }
135
136         return NULL;
137 }
138
139 static void set_vpn_routes(struct gateway_config *config,
140                         struct connman_service *service,
141                         const char *gateway,
142                         enum connman_ipconfig_type type,
143                         const char *peer)
144 {
145         struct gateway_data *data;
146         struct connman_ipconfig *ipconfig;
147         int index;
148
149         config->vpn = TRUE;
150         if (peer != NULL)
151                 config->vpn_ip = g_strdup(peer);
152         else if (gateway != NULL)
153                 config->vpn_ip = g_strdup(gateway);
154
155         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
156                 ipconfig = __connman_service_get_ip4config(service);
157         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
158                 ipconfig = __connman_service_get_ip6config(service);
159         else
160                 return;
161
162         index = __connman_ipconfig_get_index(ipconfig);
163         data = find_phy_gateway(index, gateway);
164
165         if (data != NULL) {
166                 /*
167                  * data->service points now to original
168                  * service that is serving the VPN link
169                  */
170                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
171                         ipconfig =
172                                 __connman_service_get_ip4config(data->service);
173                 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
174                         ipconfig =
175                                 __connman_service_get_ip6config(data->service);
176                 else
177                         return;
178
179                 if (ipconfig != NULL) {
180                         const char *address;
181
182                         address = __connman_ipconfig_get_local(ipconfig);
183                         config->vpn_phy_ip = g_strdup(address);
184                 }
185
186                 config->vpn_phy_index = data->index;
187         }
188
189         DBG("vpn %s phy %s index %d", config->vpn_ip,
190                 config->vpn_phy_ip, config->vpn_phy_index);
191 }
192
193 static int del_routes(struct gateway_data *data,
194                         enum connman_ipconfig_type type)
195 {
196         int status4 = 0, status6 = 0;
197         int do_ipv4 = FALSE, do_ipv6 = FALSE;
198
199         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
200                 do_ipv4 = TRUE;
201         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
202                 do_ipv6 = TRUE;
203         else
204                 do_ipv4 = do_ipv6 = TRUE;
205
206         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) {
207                 if (data->ipv4_gateway->vpn == TRUE) {
208                         status4 = connman_inet_clear_gateway_address(
209                                                 data->index,
210                                                 data->ipv4_gateway->vpn_ip);
211
212                 } else if (g_strcmp0(data->ipv4_gateway->gateway,
213                                                         "0.0.0.0") == 0) {
214                         status4 = connman_inet_clear_gateway_interface(
215                                                                 data->index);
216                 } else {
217                         connman_inet_del_host_route(data->index,
218                                                 data->ipv4_gateway->gateway);
219                         status4 = connman_inet_clear_gateway_address(
220                                                 data->index,
221                                                 data->ipv4_gateway->gateway);
222                 }
223         }
224
225         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) {
226                 if (data->ipv6_gateway->vpn == TRUE) {
227                         status6 = connman_inet_clear_ipv6_gateway_address(
228                                                 data->index,
229                                                 data->ipv6_gateway->vpn_ip);
230
231                 } else if (g_strcmp0(data->ipv6_gateway->gateway, "::") == 0) {
232                         status6 = connman_inet_clear_ipv6_gateway_interface(
233                                                                 data->index);
234                 } else {
235                         connman_inet_del_ipv6_host_route(data->index,
236                                                 data->ipv6_gateway->gateway);
237                         status6 = connman_inet_clear_ipv6_gateway_address(
238                                                 data->index,
239                                                 data->ipv6_gateway->gateway);
240                 }
241         }
242
243         return (status4 < 0 ? status4 : status6);
244 }
245
246 static int disable_gateway(struct gateway_data *data,
247                         enum connman_ipconfig_type type)
248 {
249         gboolean active = FALSE;
250
251         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
252                 if (data->ipv4_gateway != NULL)
253                         active = data->ipv4_gateway->active;
254         } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
255                 if (data->ipv6_gateway != NULL)
256                         active = data->ipv6_gateway->active;
257         } else
258                 active = TRUE;
259
260         DBG("type %d active %d", type, active);
261
262         if (active == TRUE)
263                 return del_routes(data, type);
264
265         return 0;
266 }
267
268 static struct gateway_data *add_gateway(struct connman_service *service,
269                                         int index, const char *gateway,
270                                         enum connman_ipconfig_type type)
271 {
272         struct gateway_data *data, *old;
273         struct gateway_config *config;
274
275         if (gateway == NULL || strlen(gateway) == 0)
276                 return NULL;
277
278         data = g_try_new0(struct gateway_data, 1);
279         if (data == NULL)
280                 return NULL;
281
282         data->index = index;
283
284         config = g_try_new0(struct gateway_config, 1);
285         if (config == NULL) {
286                 g_free(data);
287                 return NULL;
288         }
289
290         config->gateway = g_strdup(gateway);
291         config->vpn_ip = NULL;
292         config->vpn_phy_ip = NULL;
293         config->vpn = FALSE;
294         config->vpn_phy_index = -1;
295         config->active = FALSE;
296
297         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
298                 data->ipv4_gateway = config;
299         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
300                 data->ipv6_gateway = config;
301         else {
302                 g_free(config->gateway);
303                 g_free(config);
304                 g_free(data);
305                 return NULL;
306         }
307
308         data->service = service;
309
310         data->order = __connman_service_get_order(service);
311
312         /*
313          * If the service is already in the hash, then we
314          * must not replace it blindly but disable the gateway
315          * of the type we are replacing and take the other type
316          * from old gateway settings.
317          */
318         old = g_hash_table_lookup(gateway_hash, service);
319         if (old != NULL) {
320                 DBG("Replacing gw %p ipv4 %p ipv6 %p", old,
321                         old->ipv4_gateway, old->ipv6_gateway);
322                 disable_gateway(old, type);
323                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
324                         data->ipv6_gateway = old->ipv6_gateway;
325                         old->ipv6_gateway = NULL;
326                 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
327                         data->ipv4_gateway = old->ipv4_gateway;
328                         old->ipv4_gateway = NULL;
329                 }
330         } else {
331                 /*
332                  * Only take a ref if we are adding new stuff to hash.
333                  */
334                 connman_service_ref(service);
335         }
336
337         g_hash_table_replace(gateway_hash, service, data);
338
339         return data;
340 }
341
342 static void set_default_gateway(struct gateway_data *data,
343                                 enum connman_ipconfig_type type)
344 {
345         int index;
346         int status4 = 0, status6 = 0;
347         int do_ipv4 = FALSE, do_ipv6 = FALSE;
348
349         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
350                 do_ipv4 = TRUE;
351         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
352                 do_ipv6 = TRUE;
353         else
354                 do_ipv4 = do_ipv6 = TRUE;
355
356         DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
357                                                 data->ipv6_gateway);
358
359         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
360                                         data->ipv4_gateway->vpn == TRUE) {
361                 connman_inet_set_gateway_address(data->index,
362                                                 data->ipv4_gateway->vpn_ip);
363                 connman_inet_add_host_route(data->index,
364                                         data->ipv4_gateway->vpn_ip, NULL);
365                 data->ipv4_gateway->active = TRUE;
366
367                 DBG("set %p index %d vpn %s index %d phy %s",
368                         data, data->index, data->ipv4_gateway->vpn_ip,
369                         data->ipv4_gateway->vpn_phy_index,
370                         data->ipv4_gateway->vpn_phy_ip);
371
372                 __connman_service_indicate_default(data->service);
373
374                 return;
375         }
376
377         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
378                                         data->ipv6_gateway->vpn == TRUE) {
379                 connman_inet_set_ipv6_gateway_address(data->index,
380                                                 data->ipv6_gateway->vpn_ip);
381                 connman_inet_add_ipv6_host_route(data->index,
382                                         data->ipv6_gateway->vpn_ip, NULL);
383                 data->ipv6_gateway->active = TRUE;
384
385                 DBG("set %p index %d vpn %s index %d phy %s",
386                         data, data->index, data->ipv6_gateway->vpn_ip,
387                         data->ipv6_gateway->vpn_phy_index,
388                         data->ipv6_gateway->vpn_phy_ip);
389
390                 __connman_service_indicate_default(data->service);
391
392                 return;
393         }
394
395         index = __connman_service_get_index(data->service);
396
397         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
398                         g_strcmp0(data->ipv4_gateway->gateway,
399                                                         "0.0.0.0") == 0) {
400                 if (connman_inet_set_gateway_interface(index) < 0)
401                         return;
402                 goto done;
403         }
404
405         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
406                         g_strcmp0(data->ipv6_gateway->gateway,
407                                                         "::") == 0) {
408                 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
409                         return;
410                 goto done;
411         }
412
413         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
414                 status6 = connman_inet_set_ipv6_gateway_address(index,
415                                                 data->ipv6_gateway->gateway);
416
417         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
418                 status4 = connman_inet_set_gateway_address(index,
419                                                 data->ipv4_gateway->gateway);
420
421         if (status4 < 0 || status6 < 0)
422                 return;
423
424 done:
425         __connman_service_indicate_default(data->service);
426 }
427
428 static void unset_default_gateway(struct gateway_data *data,
429                                 enum connman_ipconfig_type type)
430 {
431         int index;
432         int do_ipv4 = FALSE, do_ipv6 = FALSE;
433
434         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
435                 do_ipv4 = TRUE;
436         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
437                 do_ipv6 = TRUE;
438         else
439                 do_ipv4 = do_ipv6 = TRUE;
440
441         DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
442                                                 data->ipv6_gateway);
443
444         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
445                                         data->ipv4_gateway->vpn == TRUE) {
446                 connman_inet_del_host_route(data->index,
447                                                 data->ipv4_gateway->vpn_ip);
448                 connman_inet_clear_gateway_address(data->index,
449                                                 data->ipv4_gateway->vpn_ip);
450                 data->ipv4_gateway->active = FALSE;
451
452                 DBG("unset %p index %d vpn %s index %d phy %s",
453                         data, data->index, data->ipv4_gateway->vpn_ip,
454                         data->ipv4_gateway->vpn_phy_index,
455                         data->ipv4_gateway->vpn_phy_ip);
456
457                 return;
458         }
459
460         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
461                                         data->ipv6_gateway->vpn == TRUE) {
462                 connman_inet_del_ipv6_host_route(data->index,
463                                                 data->ipv6_gateway->vpn_ip);
464                 connman_inet_clear_ipv6_gateway_address(data->index,
465                                                 data->ipv6_gateway->vpn_ip);
466                 data->ipv6_gateway->active = FALSE;
467
468                 DBG("unset %p index %d vpn %s index %d phy %s",
469                         data, data->index, data->ipv6_gateway->vpn_ip,
470                         data->ipv6_gateway->vpn_phy_index,
471                         data->ipv6_gateway->vpn_phy_ip);
472
473                 return;
474         }
475
476         index = __connman_service_get_index(data->service);
477
478         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
479                         g_strcmp0(data->ipv4_gateway->gateway,
480                                                         "0.0.0.0") == 0) {
481                 connman_inet_clear_gateway_interface(index);
482                 return;
483         }
484
485         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
486                         g_strcmp0(data->ipv6_gateway->gateway,
487                                                         "::") == 0) {
488                 connman_inet_clear_ipv6_gateway_interface(index);
489                 return;
490         }
491
492         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
493                 connman_inet_clear_ipv6_gateway_address(index,
494                                                 data->ipv6_gateway->gateway);
495
496         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
497                 connman_inet_clear_gateway_address(index,
498                                                 data->ipv4_gateway->gateway);
499 }
500
501 static struct gateway_data *find_default_gateway(void)
502 {
503         struct gateway_data *found = NULL;
504         unsigned int order = 0;
505         GHashTableIter iter;
506         gpointer value, key;
507
508         g_hash_table_iter_init(&iter, gateway_hash);
509
510         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
511                 struct gateway_data *data = value;
512
513                 if (found == NULL || data->order > order) {
514                         found = data;
515                         order = data->order;
516
517                         DBG("default %p order %d", found, order);
518                 }
519         }
520
521         return found;
522 }
523
524 static gboolean choose_default_gateway(struct gateway_data *data,
525                                         struct gateway_data *candidate)
526 {
527         gboolean downgraded = FALSE;
528
529         /*
530          * If the current default is not active, then we mark
531          * this one as default. If the other one is already active
532          * we mark this one as non default.
533          */
534         if (data->ipv4_gateway != NULL) {
535                 if (candidate->ipv4_gateway != NULL &&
536                                 candidate->ipv4_gateway->active == FALSE) {
537                         DBG("ipv4 downgrading %p", candidate);
538                         unset_default_gateway(candidate,
539                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
540                 }
541                 if (candidate->ipv4_gateway != NULL &&
542                                 candidate->ipv4_gateway->active == TRUE &&
543                                 candidate->order > data->order) {
544                         DBG("ipv4 downgrading this %p", data);
545                         unset_default_gateway(data,
546                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
547                         downgraded = TRUE;
548                 }
549         }
550
551         if (data->ipv6_gateway != NULL) {
552                 if (candidate->ipv6_gateway != NULL &&
553                                 candidate->ipv6_gateway->active == FALSE) {
554                         DBG("ipv6 downgrading %p", candidate);
555                         unset_default_gateway(candidate,
556                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
557                 }
558
559                 if (candidate->ipv6_gateway != NULL &&
560                                 candidate->ipv6_gateway->active == TRUE &&
561                                 candidate->order > data->order) {
562                         DBG("ipv6 downgrading this %p", data);
563                         unset_default_gateway(data,
564                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
565                         downgraded = TRUE;
566                 }
567         }
568
569         return downgraded;
570 }
571
572 static void connection_newgateway(int index, const char *gateway)
573 {
574         struct gateway_config *config;
575         struct gateway_data *data;
576         GHashTableIter iter;
577         gpointer value, key;
578         gboolean found = FALSE;
579
580         DBG("index %d gateway %s", index, gateway);
581
582         config = find_gateway(index, gateway);
583         if (config == NULL)
584                 return;
585
586         config->active = TRUE;
587
588         /*
589          * It is possible that we have two default routes atm
590          * if there are two gateways waiting rtnl activation at the
591          * same time.
592          */
593         data = lookup_gateway_data(config);
594         if (data == NULL)
595                 return;
596
597         if (data->default_checked == TRUE)
598                 return;
599
600         /*
601          * The next checks are only done once, otherwise setting
602          * the default gateway could lead into rtnl forever loop.
603          */
604
605         g_hash_table_iter_init(&iter, gateway_hash);
606
607         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
608                 struct gateway_data *candidate = value;
609
610                 if (candidate == data)
611                         continue;
612
613                 found = choose_default_gateway(data, candidate);
614                 if (found == TRUE)
615                         break;
616         }
617
618         if (found == FALSE) {
619                 if (data->ipv4_gateway != NULL)
620                         set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
621
622                 if (data->ipv6_gateway != NULL)
623                         set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
624         }
625
626         data->default_checked = TRUE;
627 }
628
629 static void remove_gateway(gpointer user_data)
630 {
631         struct gateway_data *data = user_data;
632
633         DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
634
635         if (data->ipv4_gateway != NULL) {
636                 g_free(data->ipv4_gateway->gateway);
637                 g_free(data->ipv4_gateway->vpn_ip);
638                 g_free(data->ipv4_gateway->vpn_phy_ip);
639                 g_free(data->ipv4_gateway);
640         }
641
642         if (data->ipv6_gateway != NULL) {
643                 g_free(data->ipv6_gateway->gateway);
644                 g_free(data->ipv6_gateway->vpn_ip);
645                 g_free(data->ipv6_gateway->vpn_phy_ip);
646                 g_free(data->ipv6_gateway);
647         }
648
649         g_free(data);
650 }
651
652 static void connection_delgateway(int index, const char *gateway)
653 {
654         struct gateway_config *config;
655         struct gateway_data *data;
656
657         DBG("index %d gateway %s", index, gateway);
658
659         config = find_gateway(index, gateway);
660         if (config != NULL)
661                 config->active = FALSE;
662
663         data = find_default_gateway();
664         if (data != NULL)
665                 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
666 }
667
668 static struct connman_rtnl connection_rtnl = {
669         .name           = "connection",
670         .newgateway     = connection_newgateway,
671         .delgateway     = connection_delgateway,
672 };
673
674 static struct gateway_data *find_active_gateway(void)
675 {
676         GHashTableIter iter;
677         gpointer value, key;
678
679         DBG("");
680
681         g_hash_table_iter_init(&iter, gateway_hash);
682
683         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
684                 struct gateway_data *data = value;
685
686                 if (data->ipv4_gateway != NULL &&
687                                 data->ipv4_gateway->active == TRUE)
688                         return data;
689
690                 if (data->ipv6_gateway != NULL &&
691                                 data->ipv6_gateway->active == TRUE)
692                         return data;
693         }
694
695         return NULL;
696 }
697
698 static void update_order(void)
699 {
700         GHashTableIter iter;
701         gpointer value, key;
702
703         DBG("");
704
705         g_hash_table_iter_init(&iter, gateway_hash);
706
707         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
708                 struct gateway_data *data = value;
709
710                 data->order = __connman_service_get_order(data->service);
711         }
712 }
713
714 void __connman_connection_gateway_activate(struct connman_service *service,
715                                         enum connman_ipconfig_type type)
716 {
717         struct gateway_data *data = NULL;
718
719         data = g_hash_table_lookup(gateway_hash, service);
720         if (data == NULL)
721                 return;
722
723         DBG("gateway %p/%p type %d", data->ipv4_gateway,
724                                         data->ipv6_gateway, type);
725
726         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
727                 data->ipv4_gateway->active = TRUE;
728         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
729                 data->ipv6_gateway->active = TRUE;
730 }
731
732 static void add_host_route(int family, int index, const char *gateway,
733                         enum connman_service_type service_type)
734 {
735         switch (family) {
736         case AF_INET:
737                 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
738                         /*
739                          * We must not set route to the phy dev gateway in
740                          * VPN link. The packets to VPN link might be routed
741                          * back to itself and not routed into phy link gateway.
742                          */
743                         if (service_type != CONNMAN_SERVICE_TYPE_VPN)
744                                 connman_inet_add_host_route(index, gateway,
745                                                                         NULL);
746                 } else {
747                         /*
748                          * Add host route to P-t-P link so that services can
749                          * be moved around and we can have some link to P-t-P
750                          * network (although those P-t-P links have limited
751                          * usage if default route is not directed to them)
752                          */
753                         char *dest;
754                         if (connman_inet_get_dest_addr(index, &dest) == 0) {
755                                 connman_inet_add_host_route(index, dest, NULL);
756                                 g_free(dest);
757                         }
758                 }
759                 break;
760
761         case AF_INET6:
762                 if (g_strcmp0(gateway, "::") != 0) {
763                         if (service_type != CONNMAN_SERVICE_TYPE_VPN)
764                                 connman_inet_add_ipv6_host_route(index,
765                                                                 gateway, NULL);
766                 } else {
767                         /* P-t-P link, add route to destination */
768                         char *dest;
769                         if (connman_inet_ipv6_get_dest_addr(index,
770                                                                 &dest) == 0) {
771                                 connman_inet_add_ipv6_host_route(index, dest,
772                                                                 NULL);
773                                 g_free(dest);
774                         }
775                 }
776                 break;
777         }
778 }
779
780 int __connman_connection_gateway_add(struct connman_service *service,
781                                         const char *gateway,
782                                         enum connman_ipconfig_type type,
783                                         const char *peer)
784 {
785         struct gateway_data *active_gateway = NULL;
786         struct gateway_data *new_gateway = NULL;
787         enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
788                 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
789         enum connman_service_type service_type =
790                                         connman_service_get_type(service);
791         int index;
792
793         index = __connman_service_get_index(service);
794
795         /*
796          * If gateway is NULL, it's a point to point link and the default
797          * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
798          * interface
799          */
800         if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
801                 gateway = "0.0.0.0";
802
803         if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
804                 gateway = "::";
805
806         DBG("service %p index %d gateway %s vpn ip %s type %d",
807                 service, index, gateway, peer, type);
808
809         new_gateway = add_gateway(service, index, gateway, type);
810         if (new_gateway == NULL)
811                 return -EINVAL;
812
813         active_gateway = find_active_gateway();
814
815         DBG("active %p index %d new %p", active_gateway,
816                 active_gateway ? active_gateway->index : -1, new_gateway);
817
818         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
819                                 new_gateway->ipv4_gateway != NULL) {
820                 add_host_route(AF_INET, index, gateway, service_type);
821                 __connman_service_nameserver_add_routes(service,
822                                         new_gateway->ipv4_gateway->gateway);
823                 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
824         }
825
826         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
827                                 new_gateway->ipv6_gateway != NULL) {
828                 add_host_route(AF_INET6, index, gateway, service_type);
829                 __connman_service_nameserver_add_routes(service,
830                                         new_gateway->ipv6_gateway->gateway);
831                 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
832         }
833
834         if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
835                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
836                                         new_gateway->ipv4_gateway != NULL)
837                         set_vpn_routes(new_gateway->ipv4_gateway,
838                                 service, gateway, type, peer);
839
840                 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
841                                         new_gateway->ipv6_gateway != NULL)
842                         set_vpn_routes(new_gateway->ipv6_gateway,
843                                 service, gateway, type, peer);
844
845         } else {
846                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
847                                         new_gateway->ipv4_gateway != NULL)
848                         new_gateway->ipv4_gateway->vpn = FALSE;
849
850                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
851                                         new_gateway->ipv6_gateway != NULL)
852                         new_gateway->ipv6_gateway->vpn = FALSE;
853         }
854
855         if (active_gateway == NULL) {
856                 set_default_gateway(new_gateway, type);
857                 goto done;
858         }
859
860         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
861                                 new_gateway->ipv4_gateway != NULL &&
862                                 new_gateway->ipv4_gateway->vpn == TRUE) {
863                 if (__connman_service_is_split_routing(new_gateway->service) ==
864                                                                         FALSE)
865                         connman_inet_clear_gateway_address(
866                                         active_gateway->index,
867                                         active_gateway->ipv4_gateway->gateway);
868         }
869
870         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
871                                 new_gateway->ipv6_gateway != NULL &&
872                                 new_gateway->ipv6_gateway->vpn == TRUE) {
873                 if (__connman_service_is_split_routing(new_gateway->service) ==
874                                                                         FALSE)
875                         connman_inet_clear_ipv6_gateway_address(
876                                         active_gateway->index,
877                                         active_gateway->ipv6_gateway->gateway);
878         }
879
880 done:
881         if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
882                 __connman_service_ipconfig_indicate_state(service,
883                                                 CONNMAN_SERVICE_STATE_READY,
884                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
885
886         if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
887                 __connman_service_ipconfig_indicate_state(service,
888                                                 CONNMAN_SERVICE_STATE_READY,
889                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
890         return 0;
891 }
892
893 void __connman_connection_gateway_remove(struct connman_service *service,
894                                         enum connman_ipconfig_type type)
895 {
896         struct gateway_data *data = NULL;
897         gboolean set_default4 = FALSE, set_default6 = FALSE;
898         int do_ipv4 = FALSE, do_ipv6 = FALSE;
899         int err;
900
901         DBG("service %p type %d", service, type);
902
903         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
904                 do_ipv4 = TRUE;
905         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
906                 do_ipv6 = TRUE;
907         else
908                 do_ipv4 = do_ipv6 = TRUE;
909
910         __connman_service_nameserver_del_routes(service, type);
911
912         data = g_hash_table_lookup(gateway_hash, service);
913         if (data == NULL)
914                 return;
915
916         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
917                 set_default4 = data->ipv4_gateway->vpn;
918
919         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
920                 set_default6 = data->ipv6_gateway->vpn;
921
922         DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
923                 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
924                 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
925                 set_default4, set_default6);
926
927         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
928                         data->ipv4_gateway->vpn == TRUE && data->index >= 0)
929                 connman_inet_del_host_route(data->index,
930                                                 data->ipv4_gateway->gateway);
931
932         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
933                         data->ipv6_gateway->vpn == TRUE && data->index >= 0)
934                 connman_inet_del_ipv6_host_route(data->index,
935                                                 data->ipv6_gateway->gateway);
936
937         err = disable_gateway(data, type);
938
939         /*
940          * We remove the service from the hash only if all the gateway
941          * settings are to be removed.
942          */
943         if (do_ipv4 == do_ipv6 ||
944                 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
945                         && do_ipv4 == TRUE) ||
946                 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
947                         && do_ipv6 == TRUE)
948                 ) {
949                 connman_service_unref(service);
950                 g_hash_table_remove(gateway_hash, service);
951         } else
952                 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
953                         data->ipv4_gateway, do_ipv4,
954                         data->ipv6_gateway, do_ipv6);
955
956         /* with vpn this will be called after the network was deleted,
957          * we need to call set_default here because we will not recieve any
958          * gateway delete notification.
959          * We hit the same issue if remove_gateway() fails.
960          */
961         if (set_default4 || set_default6 || err < 0) {
962                 data = find_default_gateway();
963                 if (data != NULL)
964                         set_default_gateway(data, type);
965         }
966 }
967
968 gboolean __connman_connection_update_gateway(void)
969 {
970         struct gateway_data *default_gateway;
971         gboolean updated = FALSE;
972         GHashTableIter iter;
973         gpointer value, key;
974
975         if (gateway_hash == NULL)
976                 return updated;
977
978         update_order();
979
980         default_gateway = find_default_gateway();
981
982         __connman_service_update_ordering();
983
984         DBG("default %p", default_gateway);
985
986         /*
987          * There can be multiple active gateways so we need to
988          * check them all.
989          */
990         g_hash_table_iter_init(&iter, gateway_hash);
991
992         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
993                 struct gateway_data *active_gateway = value;
994
995                 if (active_gateway == default_gateway)
996                         continue;
997
998                 if (active_gateway->ipv4_gateway != NULL &&
999                                 active_gateway->ipv4_gateway->active == TRUE) {
1000
1001                         unset_default_gateway(active_gateway,
1002                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1003                         updated = TRUE;
1004                 }
1005
1006                 if (active_gateway->ipv6_gateway != NULL &&
1007                                 active_gateway->ipv6_gateway->active == TRUE) {
1008
1009                         unset_default_gateway(active_gateway,
1010                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1011                         updated = TRUE;
1012                 }
1013         }
1014
1015         if (updated && default_gateway != NULL) {
1016                 if (default_gateway->ipv4_gateway)
1017                         set_default_gateway(default_gateway,
1018                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1019
1020                 if (default_gateway->ipv6_gateway)
1021                         set_default_gateway(default_gateway,
1022                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1023         }
1024
1025         return updated;
1026 }
1027
1028 int __connman_connection_get_vpn_index(int phy_index)
1029 {
1030         GHashTableIter iter;
1031         gpointer value, key;
1032
1033         g_hash_table_iter_init(&iter, gateway_hash);
1034
1035         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1036                 struct gateway_data *data = value;
1037
1038                 if (data->ipv4_gateway != NULL &&
1039                                 data->ipv4_gateway->vpn_phy_index == phy_index)
1040                         return data->index;
1041
1042                 if (data->ipv6_gateway != NULL &&
1043                                 data->ipv6_gateway->vpn_phy_index == phy_index)
1044                         return data->index;
1045         }
1046
1047         return -1;
1048 }
1049
1050 int __connman_connection_init(void)
1051 {
1052         int err;
1053
1054         DBG("");
1055
1056         gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1057                                                         NULL, remove_gateway);
1058
1059         err = connman_rtnl_register(&connection_rtnl);
1060         if (err < 0)
1061                 connman_error("Failed to setup RTNL gateway driver");
1062
1063         return err;
1064 }
1065
1066 void __connman_connection_cleanup(void)
1067 {
1068         GHashTableIter iter;
1069         gpointer value, key;
1070
1071         DBG("");
1072
1073         connman_rtnl_unregister(&connection_rtnl);
1074
1075         g_hash_table_iter_init(&iter, gateway_hash);
1076
1077         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1078                 struct gateway_data *data = value;
1079
1080                 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1081         }
1082
1083         g_hash_table_destroy(gateway_hash);
1084         gateway_hash = NULL;
1085 }