Imported Upstream version 1.35
[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                 goto done;
464         }
465
466         if (do_ipv6 && data->ipv6_gateway &&
467                         g_strcmp0(data->ipv6_gateway->gateway,
468                                                         "::") == 0) {
469                 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
470                         return;
471                 goto done;
472         }
473
474         if (do_ipv6 && data->ipv6_gateway)
475                 status6 = __connman_inet_add_default_to_table(RT_TABLE_MAIN,
476                                         index, data->ipv6_gateway->gateway);
477
478         if (do_ipv4 && data->ipv4_gateway)
479                 status4 = __connman_inet_add_default_to_table(RT_TABLE_MAIN,
480                                         index, data->ipv4_gateway->gateway);
481
482         if (status4 < 0 || status6 < 0)
483                 return;
484
485 done:
486         __connman_service_indicate_default(data->service);
487 }
488
489 static void unset_default_gateway(struct gateway_data *data,
490                                 enum connman_ipconfig_type type)
491 {
492         int index;
493         bool do_ipv4 = false, do_ipv6 = false;
494
495         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
496                 do_ipv4 = true;
497         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
498                 do_ipv6 = true;
499         else
500                 do_ipv4 = do_ipv6 = true;
501
502         DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
503                                                 data->ipv6_gateway);
504
505         if (do_ipv4 && data->ipv4_gateway &&
506                                         data->ipv4_gateway->vpn) {
507                 connman_inet_clear_gateway_interface(data->index);
508                 data->ipv4_gateway->active = false;
509
510                 DBG("unset %p index %d vpn %s index %d phy %s",
511                         data, data->index, data->ipv4_gateway->vpn_ip,
512                         data->ipv4_gateway->vpn_phy_index,
513                         data->ipv4_gateway->vpn_phy_ip);
514
515                 return;
516         }
517
518         if (do_ipv6 && data->ipv6_gateway &&
519                                         data->ipv6_gateway->vpn) {
520                 connman_inet_clear_ipv6_gateway_interface(data->index);
521                 data->ipv6_gateway->active = false;
522
523                 DBG("unset %p index %d vpn %s index %d phy %s",
524                         data, data->index, data->ipv6_gateway->vpn_ip,
525                         data->ipv6_gateway->vpn_phy_index,
526                         data->ipv6_gateway->vpn_phy_ip);
527
528                 return;
529         }
530
531         index = __connman_service_get_index(data->service);
532
533         if (do_ipv4 && data->ipv4_gateway &&
534                         g_strcmp0(data->ipv4_gateway->gateway,
535                                                         "0.0.0.0") == 0) {
536                 connman_inet_clear_gateway_interface(index);
537                 return;
538         }
539
540         if (do_ipv6 && data->ipv6_gateway &&
541                         g_strcmp0(data->ipv6_gateway->gateway,
542                                                         "::") == 0) {
543                 connman_inet_clear_ipv6_gateway_interface(index);
544                 return;
545         }
546
547         if (do_ipv6 && data->ipv6_gateway)
548                 connman_inet_clear_ipv6_gateway_address(index,
549                                                 data->ipv6_gateway->gateway);
550
551         if (do_ipv4 && data->ipv4_gateway)
552                 connman_inet_clear_gateway_address(index,
553                                                 data->ipv4_gateway->gateway);
554 }
555
556 static struct gateway_data *find_default_gateway(void)
557 {
558         struct connman_service *service;
559
560         service = __connman_service_get_default();
561         if (!service)
562                 return NULL;
563
564         return g_hash_table_lookup(gateway_hash, service);
565 }
566
567 static bool choose_default_gateway(struct gateway_data *data,
568                                         struct gateway_data *candidate)
569 {
570         bool downgraded = false;
571
572         /*
573          * If the current default is not active, then we mark
574          * this one as default. If the other one is already active
575          * we mark this one as non default.
576          */
577         if (data->ipv4_gateway && candidate->ipv4_gateway) {
578
579                 if (!candidate->ipv4_gateway->active) {
580                         DBG("ipv4 downgrading %p", candidate);
581                         unset_default_gateway(candidate,
582                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
583                 }
584
585                 if (candidate->ipv4_gateway->active &&
586                                 __connman_service_compare(candidate->service,
587                                                         data->service) < 0) {
588                         DBG("ipv4 downgrading this %p", data);
589                         unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
590                         downgraded = true;
591                 }
592         }
593
594         if (data->ipv6_gateway && candidate->ipv6_gateway) {
595                 if (!candidate->ipv6_gateway->active) {
596                         DBG("ipv6 downgrading %p", candidate);
597                         unset_default_gateway(candidate,
598                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
599                 }
600
601                 if (candidate->ipv6_gateway->active &&
602                         __connman_service_compare(candidate->service,
603                                                 data->service) < 0) {
604                         DBG("ipv6 downgrading this %p", data);
605                         unset_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
606                         downgraded = true;
607                 }
608         }
609
610         return downgraded;
611 }
612
613 static void connection_newgateway(int index, const char *gateway)
614 {
615         struct gateway_config *config;
616         struct gateway_data *data;
617         GHashTableIter iter;
618         gpointer value, key;
619         bool found = false;
620
621         DBG("index %d gateway %s", index, gateway);
622
623         config = find_gateway(index, gateway);
624         if (!config)
625                 return;
626
627         config->active = true;
628
629         /*
630          * It is possible that we have two default routes atm
631          * if there are two gateways waiting rtnl activation at the
632          * same time.
633          */
634         data = lookup_gateway_data(config);
635         if (!data)
636                 return;
637
638         if (data->default_checked)
639                 return;
640
641         /*
642          * The next checks are only done once, otherwise setting
643          * the default gateway could lead into rtnl forever loop.
644          */
645
646         g_hash_table_iter_init(&iter, gateway_hash);
647
648         while (g_hash_table_iter_next(&iter, &key, &value)) {
649                 struct gateway_data *candidate = value;
650
651                 if (candidate == data)
652                         continue;
653
654                 found = choose_default_gateway(data, candidate);
655                 if (found)
656                         break;
657         }
658
659         if (!found) {
660                 if (data->ipv4_gateway)
661                         set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
662
663                 if (data->ipv6_gateway)
664                         set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
665         }
666
667         data->default_checked = true;
668 }
669
670 static void remove_gateway(gpointer user_data)
671 {
672         struct gateway_data *data = user_data;
673
674         DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
675
676         if (data->ipv4_gateway) {
677                 g_free(data->ipv4_gateway->gateway);
678                 g_free(data->ipv4_gateway->vpn_ip);
679                 g_free(data->ipv4_gateway->vpn_phy_ip);
680                 g_free(data->ipv4_gateway);
681         }
682
683         if (data->ipv6_gateway) {
684                 g_free(data->ipv6_gateway->gateway);
685                 g_free(data->ipv6_gateway->vpn_ip);
686                 g_free(data->ipv6_gateway->vpn_phy_ip);
687                 g_free(data->ipv6_gateway);
688         }
689
690         connman_service_unref(data->service);
691
692         g_free(data);
693 }
694
695 static void connection_delgateway(int index, const char *gateway)
696 {
697         struct gateway_config *config;
698         struct gateway_data *data;
699
700         DBG("index %d gateway %s", index, gateway);
701
702         config = find_gateway(index, gateway);
703         if (config)
704                 config->active = false;
705
706         data = find_default_gateway();
707         if (data)
708                 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
709 }
710
711 static struct connman_rtnl connection_rtnl = {
712         .name           = "connection",
713         .newgateway     = connection_newgateway,
714         .delgateway     = connection_delgateway,
715 };
716
717 static struct gateway_data *find_active_gateway(void)
718 {
719         GHashTableIter iter;
720         gpointer value, key;
721
722         DBG("");
723
724         g_hash_table_iter_init(&iter, gateway_hash);
725
726         while (g_hash_table_iter_next(&iter, &key, &value)) {
727                 struct gateway_data *data = value;
728
729                 if (data->ipv4_gateway &&
730                                 data->ipv4_gateway->active)
731                         return data;
732
733                 if (data->ipv6_gateway &&
734                                 data->ipv6_gateway->active)
735                         return data;
736         }
737
738         return NULL;
739 }
740
741 static void add_host_route(int family, int index, const char *gateway,
742                         enum connman_service_type service_type)
743 {
744         switch (family) {
745         case AF_INET:
746                 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
747                         /*
748                          * We must not set route to the phy dev gateway in
749                          * VPN link. The packets to VPN link might be routed
750                          * back to itself and not routed into phy link gateway.
751                          */
752                         if (service_type != CONNMAN_SERVICE_TYPE_VPN)
753                                 connman_inet_add_host_route(index, gateway,
754                                                                         NULL);
755                 } else {
756                         /*
757                          * Add host route to P-t-P link so that services can
758                          * be moved around and we can have some link to P-t-P
759                          * network (although those P-t-P links have limited
760                          * usage if default route is not directed to them)
761                          */
762                         char *dest;
763                         if (connman_inet_get_dest_addr(index, &dest) == 0) {
764                                 connman_inet_add_host_route(index, dest, NULL);
765                                 g_free(dest);
766                         }
767                 }
768                 break;
769
770         case AF_INET6:
771                 if (g_strcmp0(gateway, "::") != 0) {
772                         if (service_type != CONNMAN_SERVICE_TYPE_VPN)
773                                 connman_inet_add_ipv6_host_route(index,
774                                                                 gateway, NULL);
775                 } else {
776                         /* P-t-P link, add route to destination */
777                         char *dest;
778                         if (connman_inet_ipv6_get_dest_addr(index,
779                                                                 &dest) == 0) {
780                                 connman_inet_add_ipv6_host_route(index, dest,
781                                                                 NULL);
782                                 g_free(dest);
783                         }
784                 }
785                 break;
786         }
787 }
788
789 int __connman_connection_gateway_add(struct connman_service *service,
790                                         const char *gateway,
791                                         enum connman_ipconfig_type type,
792                                         const char *peer)
793 {
794         struct gateway_data *active_gateway = NULL;
795         struct gateway_data *new_gateway = NULL;
796         enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
797                 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
798         enum connman_service_type service_type =
799                                         connman_service_get_type(service);
800         int index;
801
802         index = __connman_service_get_index(service);
803
804         /*
805          * If gateway is NULL, it's a point to point link and the default
806          * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
807          * interface
808          */
809         if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV4)
810                 gateway = "0.0.0.0";
811
812         if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6)
813                 gateway = "::";
814
815         DBG("service %p index %d gateway %s vpn ip %s type %d",
816                 service, index, gateway, peer, type);
817
818         new_gateway = add_gateway(service, index, gateway, type);
819         if (!new_gateway)
820                 return -EINVAL;
821
822         active_gateway = find_active_gateway();
823
824         DBG("active %p index %d new %p", active_gateway,
825                 active_gateway ? active_gateway->index : -1, new_gateway);
826
827         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
828                                 new_gateway->ipv4_gateway) {
829                 add_host_route(AF_INET, index, gateway, service_type);
830                 __connman_service_nameserver_add_routes(service,
831                                         new_gateway->ipv4_gateway->gateway);
832                 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
833         }
834
835         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
836                                 new_gateway->ipv6_gateway) {
837                 add_host_route(AF_INET6, index, gateway, service_type);
838                 __connman_service_nameserver_add_routes(service,
839                                         new_gateway->ipv6_gateway->gateway);
840                 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
841         }
842
843         if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
844
845                 set_vpn_routes(new_gateway, service, gateway, type, peer,
846                                                         active_gateway);
847
848         } else {
849                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
850                                         new_gateway->ipv4_gateway)
851                         new_gateway->ipv4_gateway->vpn = false;
852
853                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
854                                         new_gateway->ipv6_gateway)
855                         new_gateway->ipv6_gateway->vpn = false;
856         }
857
858         if (!active_gateway) {
859                 set_default_gateway(new_gateway, type);
860                 goto done;
861         }
862
863         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
864                                 new_gateway->ipv4_gateway &&
865                                 new_gateway->ipv4_gateway->vpn) {
866                 if (!__connman_service_is_split_routing(new_gateway->service))
867                         connman_inet_clear_gateway_address(
868                                         active_gateway->index,
869                                         active_gateway->ipv4_gateway->gateway);
870         }
871
872         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
873                                 new_gateway->ipv6_gateway &&
874                                 new_gateway->ipv6_gateway->vpn) {
875                 if (!__connman_service_is_split_routing(new_gateway->service))
876                         connman_inet_clear_ipv6_gateway_address(
877                                         active_gateway->index,
878                                         active_gateway->ipv6_gateway->gateway);
879         }
880
881 done:
882         if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
883                 __connman_service_ipconfig_indicate_state(service,
884                                                 CONNMAN_SERVICE_STATE_READY,
885                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
886
887         if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
888                 __connman_service_ipconfig_indicate_state(service,
889                                                 CONNMAN_SERVICE_STATE_READY,
890                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
891         return 0;
892 }
893
894 void __connman_connection_gateway_remove(struct connman_service *service,
895                                         enum connman_ipconfig_type type)
896 {
897         struct gateway_data *data = NULL;
898         bool set_default4 = false, set_default6 = false;
899         bool do_ipv4 = false, do_ipv6 = false;
900         int err;
901
902         DBG("service %p type %d", service, type);
903
904         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
905                 do_ipv4 = true;
906         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
907                 do_ipv6 = true;
908         else
909                 do_ipv4 = do_ipv6 = true;
910
911         __connman_service_nameserver_del_routes(service, type);
912
913         data = g_hash_table_lookup(gateway_hash, service);
914         if (!data)
915                 return;
916
917         if (do_ipv4 && data->ipv4_gateway)
918                 set_default4 = data->ipv4_gateway->vpn;
919
920         if (do_ipv6 && data->ipv6_gateway)
921                 set_default6 = data->ipv6_gateway->vpn;
922
923         DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
924                 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
925                 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
926                 set_default4, set_default6);
927
928         if (do_ipv4 && data->ipv4_gateway &&
929                         data->ipv4_gateway->vpn && data->index >= 0)
930                 connman_inet_del_host_route(data->ipv4_gateway->vpn_phy_index,
931                                                 data->ipv4_gateway->gateway);
932
933         if (do_ipv6 && data->ipv6_gateway &&
934                         data->ipv6_gateway->vpn && data->index >= 0)
935                 connman_inet_del_ipv6_host_route(
936                                         data->ipv6_gateway->vpn_phy_index,
937                                                 data->ipv6_gateway->gateway);
938
939         err = disable_gateway(data, type);
940
941         /*
942          * We remove the service from the hash only if all the gateway
943          * settings are to be removed.
944          */
945         if (do_ipv4 == do_ipv6 ||
946                 (data->ipv4_gateway && !data->ipv6_gateway
947                         && do_ipv4) ||
948                 (data->ipv6_gateway && !data->ipv4_gateway
949                         && do_ipv6)) {
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)
964                         set_default_gateway(data, type);
965         }
966 }
967
968 bool __connman_connection_update_gateway(void)
969 {
970         struct gateway_data *default_gateway;
971         bool updated = false;
972         GHashTableIter iter;
973         gpointer value, key;
974
975         if (!gateway_hash)
976                 return updated;
977
978         default_gateway = find_default_gateway();
979
980         DBG("default %p", default_gateway);
981
982         /*
983          * There can be multiple active gateways so we need to
984          * check them all.
985          */
986         g_hash_table_iter_init(&iter, gateway_hash);
987
988         while (g_hash_table_iter_next(&iter, &key, &value)) {
989                 struct gateway_data *active_gateway = value;
990
991                 if (active_gateway == default_gateway)
992                         continue;
993
994                 if (active_gateway->ipv4_gateway &&
995                                 active_gateway->ipv4_gateway->active) {
996
997                         unset_default_gateway(active_gateway,
998                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
999                         updated = true;
1000                 }
1001
1002                 if (active_gateway->ipv6_gateway &&
1003                                 active_gateway->ipv6_gateway->active) {
1004
1005                         unset_default_gateway(active_gateway,
1006                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1007                         updated = true;
1008                 }
1009         }
1010
1011         if (updated && default_gateway) {
1012                 if (default_gateway->ipv4_gateway)
1013                         set_default_gateway(default_gateway,
1014                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1015
1016                 if (default_gateway->ipv6_gateway)
1017                         set_default_gateway(default_gateway,
1018                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1019         }
1020
1021         return updated;
1022 }
1023
1024 int __connman_connection_get_vpn_index(int phy_index)
1025 {
1026         GHashTableIter iter;
1027         gpointer value, key;
1028
1029         g_hash_table_iter_init(&iter, gateway_hash);
1030
1031         while (g_hash_table_iter_next(&iter, &key, &value)) {
1032                 struct gateway_data *data = value;
1033
1034                 if (data->ipv4_gateway &&
1035                                 data->ipv4_gateway->vpn_phy_index == phy_index)
1036                         return data->index;
1037
1038                 if (data->ipv6_gateway &&
1039                                 data->ipv6_gateway->vpn_phy_index == phy_index)
1040                         return data->index;
1041         }
1042
1043         return -1;
1044 }
1045
1046 int __connman_connection_init(void)
1047 {
1048         int err;
1049
1050         DBG("");
1051
1052         gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1053                                                         NULL, remove_gateway);
1054
1055         err = connman_rtnl_register(&connection_rtnl);
1056         if (err < 0)
1057                 connman_error("Failed to setup RTNL gateway driver");
1058
1059         return err;
1060 }
1061
1062 void __connman_connection_cleanup(void)
1063 {
1064         GHashTableIter iter;
1065         gpointer value, key;
1066
1067         DBG("");
1068
1069         connman_rtnl_unregister(&connection_rtnl);
1070
1071         g_hash_table_iter_init(&iter, gateway_hash);
1072
1073         while (g_hash_table_iter_next(&iter, &key, &value)) {
1074                 struct gateway_data *data = value;
1075
1076                 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1077         }
1078
1079         g_hash_table_destroy(gateway_hash);
1080         gateway_hash = NULL;
1081 }