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