c7b1f62053c20a0a2520075cfd93ed47a7f35620
[platform/upstream/connman.git] / src / connection.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <errno.h>
28 #include <string.h>
29 #include <net/if.h>
30
31 #include <gdbus.h>
32
33 #include "connman.h"
34
35 struct gateway_config {
36         gboolean active;
37         char *gateway;
38
39         /* VPN extra data */
40         gboolean vpn;
41         char *vpn_ip;
42         int vpn_phy_index;
43         char *vpn_phy_ip;
44 };
45
46 struct gateway_data {
47         int index;
48         struct connman_service *service;
49         unsigned int order;
50         struct gateway_config *ipv4_gateway;
51         struct gateway_config *ipv6_gateway;
52         connman_bool_t default_checked;
53 };
54
55 static GHashTable *gateway_hash = NULL;
56
57 static struct gateway_config *find_gateway(int index, const char *gateway)
58 {
59         GHashTableIter iter;
60         gpointer value, key;
61
62         if (gateway == NULL)
63                 return NULL;
64
65         g_hash_table_iter_init(&iter, gateway_hash);
66
67         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
68                 struct gateway_data *data = value;
69
70                 if (data->ipv4_gateway != NULL && data->index == index &&
71                                 g_str_equal(data->ipv4_gateway->gateway,
72                                         gateway) == TRUE)
73                         return data->ipv4_gateway;
74
75                 if (data->ipv6_gateway != NULL && data->index == index &&
76                                 g_str_equal(data->ipv6_gateway->gateway,
77                                         gateway) == TRUE)
78                         return data->ipv6_gateway;
79         }
80
81         return NULL;
82 }
83
84 static struct gateway_data *lookup_gateway_data(struct gateway_config *config)
85 {
86         GHashTableIter iter;
87         gpointer value, key;
88
89         if (config == NULL)
90                 return NULL;
91
92         g_hash_table_iter_init(&iter, gateway_hash);
93
94         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
95                 struct gateway_data *data = value;
96
97                 if (data->ipv4_gateway != NULL &&
98                                 data->ipv4_gateway == config)
99                         return data;
100
101                 if (data->ipv6_gateway != NULL &&
102                                 data->ipv6_gateway == config)
103                         return data;
104         }
105
106         return NULL;
107 }
108
109 static struct gateway_data *find_vpn_gateway(int index, const char *gateway)
110 {
111         GHashTableIter iter;
112         gpointer value, key;
113
114         if (gateway == NULL)
115                 return NULL;
116
117         g_hash_table_iter_init(&iter, gateway_hash);
118
119         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
120                 struct gateway_data *data = value;
121
122                 if (data->ipv4_gateway != NULL && data->index == index &&
123                                 g_str_equal(data->ipv4_gateway->gateway,
124                                         gateway) == TRUE)
125                         return data;
126
127                 if (data->ipv6_gateway != NULL && data->index == index &&
128                                 g_str_equal(data->ipv6_gateway->gateway,
129                                         gateway) == TRUE)
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 == NULL) {
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 != NULL) {
203                 int index = __connman_ipconfig_get_index(ipconfig);
204                 struct get_gateway_params *params;
205
206                 config->vpn = TRUE;
207                 if (peer != NULL)
208                         config->vpn_ip = g_strdup(peer);
209                 else if (gateway != NULL)
210                         config->vpn_ip = g_strdup(gateway);
211
212                 params = g_try_malloc(sizeof(struct get_gateway_params));
213                 if (params == NULL)
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 == NULL)
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 == NULL)
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 == NULL)
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         int 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 == TRUE && data->ipv4_gateway != NULL) {
281                 if (data->ipv4_gateway->vpn == TRUE) {
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 == TRUE && data->ipv6_gateway != NULL) {
300                 if (data->ipv6_gateway->vpn == TRUE) {
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         gboolean active = FALSE;
324
325         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
326                 if (data->ipv4_gateway != NULL)
327                         active = data->ipv4_gateway->active;
328         } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
329                 if (data->ipv6_gateway != NULL)
330                         active = data->ipv6_gateway->active;
331         } else
332                 active = TRUE;
333
334         DBG("type %d active %d", type, active);
335
336         if (active == TRUE)
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 == NULL || strlen(gateway) == 0)
350                 return NULL;
351
352         data = g_try_new0(struct gateway_data, 1);
353         if (data == NULL)
354                 return NULL;
355
356         data->index = index;
357
358         config = g_try_new0(struct gateway_config, 1);
359         if (config == NULL) {
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 != NULL) {
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         } else {
405                 /*
406                  * Only take a ref if we are adding new stuff to hash.
407                  */
408                 connman_service_ref(service);
409         }
410
411         g_hash_table_replace(gateway_hash, service, data);
412
413         return data;
414 }
415
416 static void set_default_gateway(struct gateway_data *data,
417                                 enum connman_ipconfig_type type)
418 {
419         int index;
420         int status4 = 0, status6 = 0;
421         int do_ipv4 = FALSE, do_ipv6 = FALSE;
422
423         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
424                 do_ipv4 = TRUE;
425         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
426                 do_ipv6 = TRUE;
427         else
428                 do_ipv4 = do_ipv6 = TRUE;
429
430         DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
431                                                 data->ipv6_gateway);
432
433         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
434                                         data->ipv4_gateway->vpn == TRUE) {
435                 connman_inet_set_gateway_interface(data->index);
436                 data->ipv4_gateway->active = TRUE;
437
438                 DBG("set %p index %d vpn %s index %d phy %s",
439                         data, data->index, data->ipv4_gateway->vpn_ip,
440                         data->ipv4_gateway->vpn_phy_index,
441                         data->ipv4_gateway->vpn_phy_ip);
442
443                 __connman_service_indicate_default(data->service);
444
445                 return;
446         }
447
448         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
449                                         data->ipv6_gateway->vpn == TRUE) {
450                 connman_inet_set_ipv6_gateway_interface(data->index);
451                 data->ipv6_gateway->active = TRUE;
452
453                 DBG("set %p index %d vpn %s index %d phy %s",
454                         data, data->index, data->ipv6_gateway->vpn_ip,
455                         data->ipv6_gateway->vpn_phy_index,
456                         data->ipv6_gateway->vpn_phy_ip);
457
458                 __connman_service_indicate_default(data->service);
459
460                 return;
461         }
462
463         index = __connman_service_get_index(data->service);
464
465         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
466                         g_strcmp0(data->ipv4_gateway->gateway,
467                                                         "0.0.0.0") == 0) {
468                 if (connman_inet_set_gateway_interface(index) < 0)
469                         return;
470                 goto done;
471         }
472
473         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
474                         g_strcmp0(data->ipv6_gateway->gateway,
475                                                         "::") == 0) {
476                 if (connman_inet_set_ipv6_gateway_interface(index) < 0)
477                         return;
478                 goto done;
479         }
480
481         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
482                 status6 = connman_inet_set_ipv6_gateway_address(index,
483                                                 data->ipv6_gateway->gateway);
484
485         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
486                 status4 = connman_inet_set_gateway_address(index,
487                                                 data->ipv4_gateway->gateway);
488
489         if (status4 < 0 || status6 < 0)
490                 return;
491
492 done:
493         __connman_service_indicate_default(data->service);
494 }
495
496 static void unset_default_gateway(struct gateway_data *data,
497                                 enum connman_ipconfig_type type)
498 {
499         int index;
500         int do_ipv4 = FALSE, do_ipv6 = FALSE;
501
502         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
503                 do_ipv4 = TRUE;
504         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
505                 do_ipv6 = TRUE;
506         else
507                 do_ipv4 = do_ipv6 = TRUE;
508
509         DBG("type %d gateway ipv4 %p ipv6 %p", type, data->ipv4_gateway,
510                                                 data->ipv6_gateway);
511
512         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
513                                         data->ipv4_gateway->vpn == TRUE) {
514                 connman_inet_clear_gateway_interface(data->index);
515                 data->ipv4_gateway->active = FALSE;
516
517                 DBG("unset %p index %d vpn %s index %d phy %s",
518                         data, data->index, data->ipv4_gateway->vpn_ip,
519                         data->ipv4_gateway->vpn_phy_index,
520                         data->ipv4_gateway->vpn_phy_ip);
521
522                 return;
523         }
524
525         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
526                                         data->ipv6_gateway->vpn == TRUE) {
527                 connman_inet_clear_ipv6_gateway_interface(data->index);
528                 data->ipv6_gateway->active = FALSE;
529
530                 DBG("unset %p index %d vpn %s index %d phy %s",
531                         data, data->index, data->ipv6_gateway->vpn_ip,
532                         data->ipv6_gateway->vpn_phy_index,
533                         data->ipv6_gateway->vpn_phy_ip);
534
535                 return;
536         }
537
538         index = __connman_service_get_index(data->service);
539
540         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
541                         g_strcmp0(data->ipv4_gateway->gateway,
542                                                         "0.0.0.0") == 0) {
543                 connman_inet_clear_gateway_interface(index);
544                 return;
545         }
546
547         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
548                         g_strcmp0(data->ipv6_gateway->gateway,
549                                                         "::") == 0) {
550                 connman_inet_clear_ipv6_gateway_interface(index);
551                 return;
552         }
553
554         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
555                 connman_inet_clear_ipv6_gateway_address(index,
556                                                 data->ipv6_gateway->gateway);
557
558         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
559                 connman_inet_clear_gateway_address(index,
560                                                 data->ipv4_gateway->gateway);
561 }
562
563 static struct gateway_data *find_default_gateway(void)
564 {
565         struct gateway_data *found = NULL;
566         unsigned int order = 0;
567         GHashTableIter iter;
568         gpointer value, key;
569
570         g_hash_table_iter_init(&iter, gateway_hash);
571
572         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
573                 struct gateway_data *data = value;
574
575                 if (found == NULL || data->order > order) {
576                         found = data;
577                         order = data->order;
578
579                         DBG("default %p order %d", found, order);
580                 }
581         }
582
583         return found;
584 }
585
586 static gboolean choose_default_gateway(struct gateway_data *data,
587                                         struct gateway_data *candidate)
588 {
589         gboolean downgraded = FALSE;
590
591         /*
592          * If the current default is not active, then we mark
593          * this one as default. If the other one is already active
594          * we mark this one as non default.
595          */
596         if (data->ipv4_gateway != NULL) {
597                 if (candidate->ipv4_gateway != NULL &&
598                                 candidate->ipv4_gateway->active == FALSE) {
599                         DBG("ipv4 downgrading %p", candidate);
600                         unset_default_gateway(candidate,
601                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
602                 }
603                 if (candidate->ipv4_gateway != NULL &&
604                                 candidate->ipv4_gateway->active == TRUE &&
605                                 candidate->order > data->order) {
606                         DBG("ipv4 downgrading this %p", data);
607                         unset_default_gateway(data,
608                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
609                         downgraded = TRUE;
610                 }
611         }
612
613         if (data->ipv6_gateway != NULL) {
614                 if (candidate->ipv6_gateway != NULL &&
615                                 candidate->ipv6_gateway->active == FALSE) {
616                         DBG("ipv6 downgrading %p", candidate);
617                         unset_default_gateway(candidate,
618                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
619                 }
620
621                 if (candidate->ipv6_gateway != NULL &&
622                                 candidate->ipv6_gateway->active == TRUE &&
623                                 candidate->order > data->order) {
624                         DBG("ipv6 downgrading this %p", data);
625                         unset_default_gateway(data,
626                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
627                         downgraded = TRUE;
628                 }
629         }
630
631         return downgraded;
632 }
633
634 static void connection_newgateway(int index, const char *gateway)
635 {
636         struct gateway_config *config;
637         struct gateway_data *data;
638         GHashTableIter iter;
639         gpointer value, key;
640         gboolean found = FALSE;
641
642         DBG("index %d gateway %s", index, gateway);
643
644         config = find_gateway(index, gateway);
645         if (config == NULL)
646                 return;
647
648         config->active = TRUE;
649
650         /*
651          * It is possible that we have two default routes atm
652          * if there are two gateways waiting rtnl activation at the
653          * same time.
654          */
655         data = lookup_gateway_data(config);
656         if (data == NULL)
657                 return;
658
659         if (data->default_checked == TRUE)
660                 return;
661
662         /*
663          * The next checks are only done once, otherwise setting
664          * the default gateway could lead into rtnl forever loop.
665          */
666
667         g_hash_table_iter_init(&iter, gateway_hash);
668
669         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
670                 struct gateway_data *candidate = value;
671
672                 if (candidate == data)
673                         continue;
674
675                 found = choose_default_gateway(data, candidate);
676                 if (found == TRUE)
677                         break;
678         }
679
680         if (found == FALSE) {
681                 if (data->ipv4_gateway != NULL)
682                         set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
683
684                 if (data->ipv6_gateway != NULL)
685                         set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
686         }
687
688         data->default_checked = TRUE;
689 }
690
691 static void remove_gateway(gpointer user_data)
692 {
693         struct gateway_data *data = user_data;
694
695         DBG("gateway ipv4 %p ipv6 %p", data->ipv4_gateway, data->ipv6_gateway);
696
697         if (data->ipv4_gateway != NULL) {
698                 g_free(data->ipv4_gateway->gateway);
699                 g_free(data->ipv4_gateway->vpn_ip);
700                 g_free(data->ipv4_gateway->vpn_phy_ip);
701                 g_free(data->ipv4_gateway);
702         }
703
704         if (data->ipv6_gateway != NULL) {
705                 g_free(data->ipv6_gateway->gateway);
706                 g_free(data->ipv6_gateway->vpn_ip);
707                 g_free(data->ipv6_gateway->vpn_phy_ip);
708                 g_free(data->ipv6_gateway);
709         }
710
711         g_free(data);
712 }
713
714 static void connection_delgateway(int index, const char *gateway)
715 {
716         struct gateway_config *config;
717         struct gateway_data *data;
718
719         DBG("index %d gateway %s", index, gateway);
720
721         config = find_gateway(index, gateway);
722         if (config != NULL)
723                 config->active = FALSE;
724
725         data = find_default_gateway();
726         if (data != NULL)
727                 set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
728 }
729
730 static struct connman_rtnl connection_rtnl = {
731         .name           = "connection",
732         .newgateway     = connection_newgateway,
733         .delgateway     = connection_delgateway,
734 };
735
736 static struct gateway_data *find_active_gateway(void)
737 {
738         GHashTableIter iter;
739         gpointer value, key;
740
741         DBG("");
742
743         g_hash_table_iter_init(&iter, gateway_hash);
744
745         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
746                 struct gateway_data *data = value;
747
748                 if (data->ipv4_gateway != NULL &&
749                                 data->ipv4_gateway->active == TRUE)
750                         return data;
751
752                 if (data->ipv6_gateway != NULL &&
753                                 data->ipv6_gateway->active == TRUE)
754                         return data;
755         }
756
757         return NULL;
758 }
759
760 static void update_order(void)
761 {
762         GHashTableIter iter;
763         gpointer value, key;
764
765         DBG("");
766
767         g_hash_table_iter_init(&iter, gateway_hash);
768
769         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
770                 struct gateway_data *data = value;
771
772                 data->order = __connman_service_get_order(data->service);
773         }
774 }
775
776 void __connman_connection_gateway_activate(struct connman_service *service,
777                                         enum connman_ipconfig_type type)
778 {
779         struct gateway_data *data = NULL;
780
781         data = g_hash_table_lookup(gateway_hash, service);
782         if (data == NULL)
783                 return;
784
785         DBG("gateway %p/%p type %d", data->ipv4_gateway,
786                                         data->ipv6_gateway, type);
787
788         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
789                 data->ipv4_gateway->active = TRUE;
790         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
791                 data->ipv6_gateway->active = TRUE;
792 }
793
794 static void add_host_route(int family, int index, const char *gateway,
795                         enum connman_service_type service_type)
796 {
797         switch (family) {
798         case AF_INET:
799                 if (g_strcmp0(gateway, "0.0.0.0") != 0) {
800                         /*
801                          * We must not set route to the phy dev gateway in
802                          * VPN link. The packets to VPN link might be routed
803                          * back to itself and not routed into phy link gateway.
804                          */
805                         if (service_type != CONNMAN_SERVICE_TYPE_VPN)
806                                 connman_inet_add_host_route(index, gateway,
807                                                                         NULL);
808                 } else {
809                         /*
810                          * Add host route to P-t-P link so that services can
811                          * be moved around and we can have some link to P-t-P
812                          * network (although those P-t-P links have limited
813                          * usage if default route is not directed to them)
814                          */
815                         char *dest;
816                         if (connman_inet_get_dest_addr(index, &dest) == 0) {
817                                 connman_inet_add_host_route(index, dest, NULL);
818                                 g_free(dest);
819                         }
820                 }
821                 break;
822
823         case AF_INET6:
824                 if (g_strcmp0(gateway, "::") != 0) {
825                         if (service_type != CONNMAN_SERVICE_TYPE_VPN)
826                                 connman_inet_add_ipv6_host_route(index,
827                                                                 gateway, NULL);
828                 } else {
829                         /* P-t-P link, add route to destination */
830                         char *dest;
831                         if (connman_inet_ipv6_get_dest_addr(index,
832                                                                 &dest) == 0) {
833                                 connman_inet_add_ipv6_host_route(index, dest,
834                                                                 NULL);
835                                 g_free(dest);
836                         }
837                 }
838                 break;
839         }
840 }
841
842 int __connman_connection_gateway_add(struct connman_service *service,
843                                         const char *gateway,
844                                         enum connman_ipconfig_type type,
845                                         const char *peer)
846 {
847         struct gateway_data *active_gateway = NULL;
848         struct gateway_data *new_gateway = NULL;
849         enum connman_ipconfig_type type4 = CONNMAN_IPCONFIG_TYPE_UNKNOWN,
850                 type6 = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
851         enum connman_service_type service_type =
852                                         connman_service_get_type(service);
853         int index;
854
855         index = __connman_service_get_index(service);
856
857         /*
858          * If gateway is NULL, it's a point to point link and the default
859          * gateway for ipv4 is 0.0.0.0 and for ipv6 is ::, meaning the
860          * interface
861          */
862         if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV4)
863                 gateway = "0.0.0.0";
864
865         if (gateway == NULL && type == CONNMAN_IPCONFIG_TYPE_IPV6)
866                 gateway = "::";
867
868         DBG("service %p index %d gateway %s vpn ip %s type %d",
869                 service, index, gateway, peer, type);
870
871         new_gateway = add_gateway(service, index, gateway, type);
872         if (new_gateway == NULL)
873                 return -EINVAL;
874
875         active_gateway = find_active_gateway();
876
877         DBG("active %p index %d new %p", active_gateway,
878                 active_gateway ? active_gateway->index : -1, new_gateway);
879
880         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
881                                 new_gateway->ipv4_gateway != NULL) {
882                 add_host_route(AF_INET, index, gateway, service_type);
883                 __connman_service_nameserver_add_routes(service,
884                                         new_gateway->ipv4_gateway->gateway);
885                 type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
886         }
887
888         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
889                                 new_gateway->ipv6_gateway != NULL) {
890                 add_host_route(AF_INET6, index, gateway, service_type);
891                 __connman_service_nameserver_add_routes(service,
892                                         new_gateway->ipv6_gateway->gateway);
893                 type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
894         }
895
896         if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
897
898                 set_vpn_routes(new_gateway, service, gateway, type, peer,
899                                                         active_gateway);
900
901         } else {
902                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
903                                         new_gateway->ipv4_gateway != NULL)
904                         new_gateway->ipv4_gateway->vpn = FALSE;
905
906                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
907                                         new_gateway->ipv6_gateway != NULL)
908                         new_gateway->ipv6_gateway->vpn = FALSE;
909         }
910
911         if (active_gateway == NULL) {
912                 set_default_gateway(new_gateway, type);
913                 goto done;
914         }
915
916         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
917                                 new_gateway->ipv4_gateway != NULL &&
918                                 new_gateway->ipv4_gateway->vpn == TRUE) {
919                 if (__connman_service_is_split_routing(new_gateway->service) ==
920                                                                         FALSE)
921                         connman_inet_clear_gateway_address(
922                                         active_gateway->index,
923                                         active_gateway->ipv4_gateway->gateway);
924         }
925
926         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
927                                 new_gateway->ipv6_gateway != NULL &&
928                                 new_gateway->ipv6_gateway->vpn == TRUE) {
929                 if (__connman_service_is_split_routing(new_gateway->service) ==
930                                                                         FALSE)
931                         connman_inet_clear_ipv6_gateway_address(
932                                         active_gateway->index,
933                                         active_gateway->ipv6_gateway->gateway);
934         }
935
936 done:
937         if (type4 == CONNMAN_IPCONFIG_TYPE_IPV4)
938                 __connman_service_ipconfig_indicate_state(service,
939                                                 CONNMAN_SERVICE_STATE_READY,
940                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
941
942         if (type6 == CONNMAN_IPCONFIG_TYPE_IPV6)
943                 __connman_service_ipconfig_indicate_state(service,
944                                                 CONNMAN_SERVICE_STATE_READY,
945                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
946         return 0;
947 }
948
949 void __connman_connection_gateway_remove(struct connman_service *service,
950                                         enum connman_ipconfig_type type)
951 {
952         struct gateway_data *data = NULL;
953         gboolean set_default4 = FALSE, set_default6 = FALSE;
954         int do_ipv4 = FALSE, do_ipv6 = FALSE;
955         int err;
956
957         DBG("service %p type %d", service, type);
958
959         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
960                 do_ipv4 = TRUE;
961         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
962                 do_ipv6 = TRUE;
963         else
964                 do_ipv4 = do_ipv6 = TRUE;
965
966         __connman_service_nameserver_del_routes(service, type);
967
968         data = g_hash_table_lookup(gateway_hash, service);
969         if (data == NULL)
970                 return;
971
972         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL)
973                 set_default4 = data->ipv4_gateway->vpn;
974
975         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL)
976                 set_default6 = data->ipv6_gateway->vpn;
977
978         DBG("ipv4 gateway %s ipv6 gateway %s vpn %d/%d",
979                 data->ipv4_gateway ? data->ipv4_gateway->gateway : "<null>",
980                 data->ipv6_gateway ? data->ipv6_gateway->gateway : "<null>",
981                 set_default4, set_default6);
982
983         if (do_ipv4 == TRUE && data->ipv4_gateway != NULL &&
984                         data->ipv4_gateway->vpn == TRUE && data->index >= 0)
985                 connman_inet_del_host_route(data->index,
986                                                 data->ipv4_gateway->gateway);
987
988         if (do_ipv6 == TRUE && data->ipv6_gateway != NULL &&
989                         data->ipv6_gateway->vpn == TRUE && data->index >= 0)
990                 connman_inet_del_ipv6_host_route(data->index,
991                                                 data->ipv6_gateway->gateway);
992
993         err = disable_gateway(data, type);
994
995         /*
996          * We remove the service from the hash only if all the gateway
997          * settings are to be removed.
998          */
999         if (do_ipv4 == do_ipv6 ||
1000                 (data->ipv4_gateway != NULL && data->ipv6_gateway == NULL
1001                         && do_ipv4 == TRUE) ||
1002                 (data->ipv6_gateway != NULL && data->ipv4_gateway == NULL
1003                         && do_ipv6 == TRUE)
1004                 ) {
1005                 connman_service_unref(service);
1006                 g_hash_table_remove(gateway_hash, service);
1007         } else
1008                 DBG("Not yet removing gw ipv4 %p/%d ipv6 %p/%d",
1009                         data->ipv4_gateway, do_ipv4,
1010                         data->ipv6_gateway, do_ipv6);
1011
1012         /* with vpn this will be called after the network was deleted,
1013          * we need to call set_default here because we will not recieve any
1014          * gateway delete notification.
1015          * We hit the same issue if remove_gateway() fails.
1016          */
1017         if (set_default4 || set_default6 || err < 0) {
1018                 data = find_default_gateway();
1019                 if (data != NULL)
1020                         set_default_gateway(data, type);
1021         }
1022 }
1023
1024 gboolean __connman_connection_update_gateway(void)
1025 {
1026         struct gateway_data *default_gateway;
1027         gboolean updated = FALSE;
1028         GHashTableIter iter;
1029         gpointer value, key;
1030
1031         if (gateway_hash == NULL)
1032                 return updated;
1033
1034         update_order();
1035
1036         default_gateway = find_default_gateway();
1037
1038         __connman_service_update_ordering();
1039
1040         DBG("default %p", default_gateway);
1041
1042         /*
1043          * There can be multiple active gateways so we need to
1044          * check them all.
1045          */
1046         g_hash_table_iter_init(&iter, gateway_hash);
1047
1048         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1049                 struct gateway_data *active_gateway = value;
1050
1051                 if (active_gateway == default_gateway)
1052                         continue;
1053
1054                 if (active_gateway->ipv4_gateway != NULL &&
1055                                 active_gateway->ipv4_gateway->active == TRUE) {
1056
1057                         unset_default_gateway(active_gateway,
1058                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1059                         updated = TRUE;
1060                 }
1061
1062                 if (active_gateway->ipv6_gateway != NULL &&
1063                                 active_gateway->ipv6_gateway->active == TRUE) {
1064
1065                         unset_default_gateway(active_gateway,
1066                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1067                         updated = TRUE;
1068                 }
1069         }
1070
1071         if (updated && default_gateway != NULL) {
1072                 if (default_gateway->ipv4_gateway)
1073                         set_default_gateway(default_gateway,
1074                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1075
1076                 if (default_gateway->ipv6_gateway)
1077                         set_default_gateway(default_gateway,
1078                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1079         }
1080
1081         return updated;
1082 }
1083
1084 int __connman_connection_get_vpn_index(int phy_index)
1085 {
1086         GHashTableIter iter;
1087         gpointer value, key;
1088
1089         g_hash_table_iter_init(&iter, gateway_hash);
1090
1091         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1092                 struct gateway_data *data = value;
1093
1094                 if (data->ipv4_gateway != NULL &&
1095                                 data->ipv4_gateway->vpn_phy_index == phy_index)
1096                         return data->index;
1097
1098                 if (data->ipv6_gateway != NULL &&
1099                                 data->ipv6_gateway->vpn_phy_index == phy_index)
1100                         return data->index;
1101         }
1102
1103         return -1;
1104 }
1105
1106 int __connman_connection_init(void)
1107 {
1108         int err;
1109
1110         DBG("");
1111
1112         gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1113                                                         NULL, remove_gateway);
1114
1115         err = connman_rtnl_register(&connection_rtnl);
1116         if (err < 0)
1117                 connman_error("Failed to setup RTNL gateway driver");
1118
1119         return err;
1120 }
1121
1122 void __connman_connection_cleanup(void)
1123 {
1124         GHashTableIter iter;
1125         gpointer value, key;
1126
1127         DBG("");
1128
1129         connman_rtnl_unregister(&connection_rtnl);
1130
1131         g_hash_table_iter_init(&iter, gateway_hash);
1132
1133         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1134                 struct gateway_data *data = value;
1135
1136                 disable_gateway(data, CONNMAN_IPCONFIG_TYPE_ALL);
1137         }
1138
1139         g_hash_table_destroy(gateway_hash);
1140         gateway_hash = NULL;
1141 }