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