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