[connman] Added Tizen Wi-Fi Mesh
[platform/upstream/connman.git] / src / session.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2014  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
29 #include <gdbus.h>
30
31 #include <connman/session.h>
32
33 #include "connman.h"
34
35 static DBusConnection *connection;
36 static GHashTable *session_hash;
37 static GHashTable *service_hash;
38 static struct connman_session *ecall_session;
39 static uint32_t session_mark = 256;
40
41 struct session_info {
42         struct connman_session_config config;
43         enum connman_session_state state;
44 };
45
46 struct connman_session {
47         char *owner;
48         char *session_path;
49         char *notify_path;
50         guint notify_watch;
51
52         bool active;
53         bool append_all;
54         struct session_info *info;
55         struct session_info *info_last;
56         struct connman_service *service;
57         struct connman_service *service_last;
58         struct connman_session_config *policy_config;
59         GSList *user_allowed_bearers;
60         char *user_allowed_interface;
61
62         bool ecall;
63
64         enum connman_session_id_type id_type;
65         struct firewall_context *fw;
66         uint32_t mark;
67         int index;
68         char *gateway;
69         bool policy_routing;
70         bool snat_enabled;
71 };
72
73 struct connman_service_info {
74         struct connman_service *service;
75         GSList *sessions;
76 };
77
78 struct fw_snat {
79         GSList *sessions;
80         int id;
81         int index;
82         struct firewall_context *fw;
83 };
84
85 GSList *fw_snat_list;
86
87 static struct connman_session_policy *policy;
88 static void session_activate(struct connman_session *session);
89 static void session_deactivate(struct connman_session *session);
90 static void update_session_state(struct connman_session *session);
91
92 static void cleanup_service(gpointer data)
93 {
94         struct connman_service_info *info = data;
95
96         g_slist_free(info->sessions);
97         g_free(info);
98 }
99
100 static const char *state2string(enum connman_session_state state)
101 {
102         switch (state) {
103         case CONNMAN_SESSION_STATE_DISCONNECTED:
104                 return "disconnected";
105         case CONNMAN_SESSION_STATE_CONNECTED:
106                 return "connected";
107         case CONNMAN_SESSION_STATE_ONLINE:
108                 return "online";
109         }
110
111         return NULL;
112 }
113
114 static const char *type2string(enum connman_session_type type)
115 {
116         switch (type) {
117         case CONNMAN_SESSION_TYPE_UNKNOWN:
118                 return "";
119         case CONNMAN_SESSION_TYPE_ANY:
120                 return "any";
121         case CONNMAN_SESSION_TYPE_LOCAL:
122                 return "local";
123         case CONNMAN_SESSION_TYPE_INTERNET:
124                 return "internet";
125         }
126
127         return NULL;
128 }
129
130 enum connman_session_roaming_policy connman_session_parse_roaming_policy(const char *policy)
131 {
132         if (g_strcmp0(policy, "default") == 0)
133                 return CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
134         else if (g_strcmp0(policy, "always") == 0)
135                 return CONNMAN_SESSION_ROAMING_POLICY_ALWAYS;
136         else if (g_strcmp0(policy, "forbidden") == 0)
137                 return CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN;
138         else if (g_strcmp0(policy, "national") == 0)
139                 return CONNMAN_SESSION_ROAMING_POLICY_NATIONAL;
140         else if (g_strcmp0(policy, "international") == 0)
141                 return CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL;
142         else
143                 return CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN;
144 }
145
146 enum connman_session_type connman_session_parse_connection_type(const char *type)
147 {
148         if (g_strcmp0(type, "any") == 0)
149                 return CONNMAN_SESSION_TYPE_ANY;
150         if (g_strcmp0(type, "local") == 0)
151                 return CONNMAN_SESSION_TYPE_LOCAL;
152         else if (g_strcmp0(type, "internet") == 0)
153                 return CONNMAN_SESSION_TYPE_INTERNET;
154
155         return CONNMAN_SESSION_TYPE_UNKNOWN;
156 }
157
158 static int bearer2service(const char *bearer, enum connman_service_type *type)
159 {
160         if (g_strcmp0(bearer, "ethernet") == 0)
161                 *type = CONNMAN_SERVICE_TYPE_ETHERNET;
162         else if (g_strcmp0(bearer, "wifi") == 0)
163                 *type = CONNMAN_SERVICE_TYPE_WIFI;
164         else if (g_strcmp0(bearer, "gadget") == 0)
165                 *type = CONNMAN_SERVICE_TYPE_GADGET;
166         else if (g_strcmp0(bearer, "bluetooth") == 0)
167                 *type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
168         else if (g_strcmp0(bearer, "cellular") == 0)
169                 *type = CONNMAN_SERVICE_TYPE_CELLULAR;
170         else if (g_strcmp0(bearer, "vpn") == 0)
171                 *type = CONNMAN_SERVICE_TYPE_VPN;
172         else
173                 return -EINVAL;
174
175         return 0;
176 }
177
178 static char *service2bearer(enum connman_service_type type)
179 {
180         switch (type) {
181         case CONNMAN_SERVICE_TYPE_ETHERNET:
182                 return "ethernet";
183         case CONNMAN_SERVICE_TYPE_GADGET:
184                 return "gadget";
185         case CONNMAN_SERVICE_TYPE_WIFI:
186                 return "wifi";
187         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
188                 return "bluetooth";
189         case CONNMAN_SERVICE_TYPE_CELLULAR:
190                 return "cellular";
191         case CONNMAN_SERVICE_TYPE_VPN:
192                 return "vpn";
193         case CONNMAN_SERVICE_TYPE_SYSTEM:
194         case CONNMAN_SERVICE_TYPE_GPS:
195         case CONNMAN_SERVICE_TYPE_P2P:
196         case CONNMAN_SERVICE_TYPE_UNKNOWN:
197 #if defined TIZEN_EXT_WIFI_MESH
198         case CONNMAN_SERVICE_TYPE_MESH:
199 #endif
200                 return "";
201         }
202
203         return "";
204 }
205
206 static struct fw_snat *fw_snat_lookup(int index)
207 {
208         struct fw_snat *fw_snat;
209         GSList *list;
210
211         for (list = fw_snat_list; list; list = list->next) {
212                 fw_snat = list->data;
213
214                 if (fw_snat->index == index)
215                         return fw_snat;
216         }
217         return NULL;
218 }
219
220 static int fw_snat_create(struct connman_session *session,
221                                 int index, const char *ifname, const char *addr)
222 {
223         struct fw_snat *fw_snat;
224         int err;
225
226         fw_snat = g_new0(struct fw_snat, 1);
227
228         fw_snat->fw = __connman_firewall_create();
229         fw_snat->index = index;
230
231         fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw,
232                                                 index, ifname, addr);
233         if (fw_snat->id < 0) {
234                 err = fw_snat->id;
235                 goto err;
236         }
237
238         fw_snat_list = g_slist_prepend(fw_snat_list, fw_snat);
239         fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
240
241         return 0;
242 err:
243         __connman_firewall_destroy(fw_snat->fw);
244         g_free(fw_snat);
245         return err;
246 }
247
248 static void fw_snat_ref(struct connman_session *session,
249                                 struct fw_snat *fw_snat)
250 {
251         if (g_slist_find(fw_snat->sessions, session))
252                 return;
253         fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
254 }
255
256 static void fw_snat_unref(struct connman_session *session,
257                                 struct fw_snat *fw_snat)
258 {
259         fw_snat->sessions = g_slist_remove(fw_snat->sessions, session);
260         if (fw_snat->sessions)
261                 return;
262
263         fw_snat_list = g_slist_remove(fw_snat_list, fw_snat);
264
265         __connman_firewall_disable_snat(fw_snat->fw);
266         __connman_firewall_destroy(fw_snat->fw);
267         g_free(fw_snat);
268 }
269
270 static int init_firewall_session(struct connman_session *session)
271 {
272         struct firewall_context *fw;
273         int err;
274         struct connman_ipconfig *ipconfig = NULL;
275         const char *addr = NULL;
276
277         if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
278                         !session->info->config.source_ip_rule)
279                 return 0;
280
281         DBG("");
282
283         if (session->info->config.source_ip_rule) {
284                 ipconfig = __connman_service_get_ip4config(session->service);
285                 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN && !ipconfig)
286                         return 0;
287         }
288
289         fw = __connman_firewall_create();
290         if (!fw)
291                 return -ENOMEM;
292
293         if (session->info->config.source_ip_rule && ipconfig) {
294                 addr = __connman_ipconfig_get_local(ipconfig);
295         }
296
297         err =__connman_firewall_enable_marking(fw,
298                                         session->policy_config->id_type,
299                                         session->policy_config->id,
300                                         addr, session->mark);
301         if (err < 0) {
302                 __connman_firewall_destroy(fw);
303                 return err;
304         }
305         session->id_type = session->policy_config->id_type;
306         session->fw = fw;
307
308         return 0;
309 }
310
311 static void cleanup_firewall_session(struct connman_session *session)
312 {
313         if (!session->fw)
314                 return;
315
316         __connman_firewall_disable_marking(session->fw);
317         __connman_firewall_disable_snat(session->fw);
318         __connman_firewall_destroy(session->fw);
319
320         session->fw = NULL;
321 }
322
323 static int init_routing_table(struct connman_session *session)
324 {
325         int err;
326
327         if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
328                         !session->info->config.source_ip_rule)
329                 return 0;
330
331         if (!session->service)
332                 return 0;
333
334         DBG("");
335
336         err = __connman_inet_add_fwmark_rule(session->mark,
337                                                 AF_INET, session->mark);
338         if (err < 0)
339                 return err;
340
341         err = __connman_inet_add_fwmark_rule(session->mark,
342                                                 AF_INET6, session->mark);
343         if (err < 0)
344                 __connman_inet_del_fwmark_rule(session->mark,
345                                                 AF_INET, session->mark);
346         session->policy_routing = true;
347
348         return err;
349 }
350
351 static void del_default_route(struct connman_session *session)
352 {
353         if (!session->gateway)
354                 return;
355
356         DBG("index %d routing table %d default gateway %s",
357                 session->index, session->mark, session->gateway);
358
359         __connman_inet_del_default_from_table(session->mark,
360                                         session->index, session->gateway);
361         g_free(session->gateway);
362         session->gateway = NULL;
363         session->index = -1;
364 }
365
366 static void add_default_route(struct connman_session *session)
367 {
368         struct connman_ipconfig *ipconfig;
369         int err;
370         struct in_addr addr = { INADDR_ANY };
371
372         if (!session->service)
373                 return;
374
375         ipconfig = __connman_service_get_ip4config(session->service);
376         session->index = __connman_ipconfig_get_index(ipconfig);
377         session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
378
379         if (!session->gateway)
380                 session->gateway = g_strdup(inet_ntoa(addr));
381
382         DBG("index %d routing table %d default gateway %s",
383                 session->index, session->mark, session->gateway);
384
385         err = __connman_inet_add_default_to_table(session->mark,
386                                         session->index, session->gateway);
387         if (err < 0)
388                 DBG("session %p %s", session, strerror(-err));
389 }
390
391 static void del_nat_rules(struct connman_session *session)
392 {
393         struct fw_snat *fw_snat;
394
395         if (!session->snat_enabled)
396                 return;
397
398         session->snat_enabled = false;
399         fw_snat = fw_snat_lookup(session->index);
400
401         if (!fw_snat)
402                 return;
403
404         fw_snat_unref(session, fw_snat);
405 }
406
407 static void add_nat_rules(struct connman_session *session)
408 {
409         struct connman_ipconfig *ipconfig;
410         struct fw_snat *fw_snat;
411         const char *addr;
412         int index, err;
413         char *ifname;
414
415         if (!session->service)
416                 return;
417
418         ipconfig = __connman_service_get_ip4config(session->service);
419         index = __connman_ipconfig_get_index(ipconfig);
420         ifname = connman_inet_ifname(index);
421         addr = __connman_ipconfig_get_local(ipconfig);
422
423         if (!addr)
424                 return;
425
426         session->snat_enabled = true;
427         fw_snat = fw_snat_lookup(index);
428         if (fw_snat) {
429                 fw_snat_ref(session, fw_snat);
430                 return;
431         }
432
433         err = fw_snat_create(session, index, ifname, addr);
434         if (err < 0) {
435                 DBG("failed to add SNAT rule");
436                 session->snat_enabled = false;
437         }
438
439         g_free(ifname);
440 }
441
442 uint32_t connman_session_firewall_get_fwmark(struct connman_session *session)
443 {
444         return session->mark;
445 }
446
447 static void cleanup_routing_table(struct connman_session *session)
448 {
449         DBG("");
450
451         if (session->policy_routing) {
452                 __connman_inet_del_fwmark_rule(session->mark,
453                                         AF_INET6, session->mark);
454
455                 __connman_inet_del_fwmark_rule(session->mark,
456                                         AF_INET, session->mark);
457                 session->policy_routing = false;
458         }
459
460         del_default_route(session);
461 }
462
463 static void update_firewall(struct connman_session *session)
464 {
465         cleanup_firewall_session(session);
466         init_firewall_session(session);
467 }
468
469 static void update_routing_table(struct connman_session *session)
470 {
471         cleanup_routing_table(session);
472         init_routing_table(session);
473         add_default_route(session);
474 }
475
476 static void cleanup_nat_rules(struct connman_session *session)
477 {
478         del_nat_rules(session);
479 }
480
481 static void destroy_policy_config(struct connman_session *session)
482 {
483         if (!policy) {
484                 g_free(session->policy_config);
485                 return;
486         }
487
488         policy->destroy(session);
489 }
490
491 static void free_session(struct connman_session *session)
492 {
493         if (!session)
494                 return;
495
496         if (session->notify_watch > 0)
497                 g_dbus_remove_watch(connection, session->notify_watch);
498
499         destroy_policy_config(session);
500         g_slist_free(session->info->config.allowed_bearers);
501         g_free(session->info->config.allowed_interface);
502         g_free(session->owner);
503         g_free(session->session_path);
504         g_free(session->notify_path);
505         g_free(session->info);
506         g_free(session->info_last);
507         g_free(session->gateway);
508
509         g_free(session);
510 }
511
512 static void set_active_session(struct connman_session *session, bool enable)
513 {
514
515         if (policy && policy->session_changed)
516                 policy->session_changed(session, enable,
517                                         session->info->config.allowed_bearers);
518
519         __connman_service_set_active_session(enable,
520                                 session->info->config.allowed_bearers);
521 }
522
523 static void cleanup_session(gpointer user_data)
524 {
525         struct connman_session *session = user_data;
526
527         DBG("remove %s", session->session_path);
528
529         cleanup_nat_rules(session);
530         cleanup_routing_table(session);
531         cleanup_firewall_session(session);
532
533         if (session->active)
534                 set_active_session(session, false);
535
536         session_deactivate(session);
537         update_session_state(session);
538
539         g_slist_free(session->user_allowed_bearers);
540         g_free(session->user_allowed_interface);
541
542         free_session(session);
543 }
544
545 struct creation_data {
546         DBusMessage *pending;
547         struct connman_session *session;
548
549         /* user config */
550         enum connman_session_type type;
551         GSList *allowed_bearers;
552         char *allowed_interface;
553         bool source_ip_rule;
554 };
555
556 static void cleanup_creation_data(struct creation_data *creation_data)
557 {
558         if (!creation_data)
559                 return;
560
561         if (creation_data->pending)
562                 dbus_message_unref(creation_data->pending);
563
564         g_slist_free(creation_data->allowed_bearers);
565         g_free(creation_data->allowed_interface);
566         g_free(creation_data);
567 }
568
569 static int create_policy_config(struct connman_session *session,
570                                 connman_session_config_func_t cb,
571                                 struct creation_data *creation_data)
572 {
573         struct connman_session_config *config;
574
575         if (!policy) {
576                 config = connman_session_create_default_config();
577                 if (!config) {
578                         free_session(session);
579                         cleanup_creation_data(creation_data);
580                         return -ENOMEM;
581                 }
582
583                 return cb(session, config, creation_data, 0);
584         }
585
586         return policy->create(session, cb, creation_data);
587 }
588
589 int connman_session_policy_register(struct connman_session_policy *plugin)
590 {
591         if (policy)
592                 return -EINVAL;
593
594         if (!plugin->create || !plugin->destroy)
595                 return -EINVAL;
596
597         DBG("name %s", plugin->name);
598
599         policy = plugin;
600
601         return 0;
602 }
603
604 void connman_session_policy_unregister(struct connman_session_policy *plugin)
605 {
606         if (plugin != policy)
607                 return;
608
609         DBG("name %s", policy->name);
610
611         policy = NULL;
612 }
613
614 static int default_bearers[] = {
615         CONNMAN_SERVICE_TYPE_ETHERNET,
616         CONNMAN_SERVICE_TYPE_WIFI,
617         CONNMAN_SERVICE_TYPE_BLUETOOTH,
618         CONNMAN_SERVICE_TYPE_CELLULAR,
619         CONNMAN_SERVICE_TYPE_GADGET,
620 };
621
622 static void add_default_bearer_types(GSList **list)
623 {
624         unsigned int i;
625
626         for (i = 0; i < G_N_ELEMENTS(default_bearers); i++)
627                 *list = g_slist_append(*list,
628                                 GINT_TO_POINTER(default_bearers[i]));
629 }
630
631 void connman_session_set_default_config(struct connman_session_config *config)
632 {
633         config->id_type = CONNMAN_SESSION_ID_TYPE_UNKNOWN;
634         g_free(config->id);
635         config->id = NULL;
636
637         config->priority = FALSE;
638         config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
639         config->type = CONNMAN_SESSION_TYPE_ANY;
640         config->ecall = FALSE;
641
642         g_slist_free(config->allowed_bearers);
643         config->allowed_bearers = NULL;
644         add_default_bearer_types(&config->allowed_bearers);
645 }
646
647 struct connman_session_config *connman_session_create_default_config(void)
648 {
649         struct connman_session_config *config;
650
651         config = g_new0(struct connman_session_config, 1);
652         connman_session_set_default_config(config);
653
654         return config;
655 }
656
657 static enum connman_session_type apply_policy_on_type(
658                         enum connman_session_type policy,
659                         enum connman_session_type type)
660 {
661         if (type == CONNMAN_SESSION_TYPE_UNKNOWN)
662                 return CONNMAN_SESSION_TYPE_UNKNOWN;
663
664         if (policy == CONNMAN_SESSION_TYPE_ANY)
665                 return type;
666
667         if (policy == CONNMAN_SESSION_TYPE_LOCAL)
668                 return CONNMAN_SESSION_TYPE_LOCAL;
669
670         return CONNMAN_SESSION_TYPE_INTERNET;
671 }
672
673 int connman_session_parse_bearers(const char *token, GSList **list)
674 {
675         enum connman_service_type bearer;
676         int err;
677
678         if (g_strcmp0(token, "") == 0)
679                 return 0;
680
681         if (g_strcmp0(token, "*") == 0) {
682                 add_default_bearer_types(list);
683                 return 0;
684         }
685
686         err = bearer2service(token, &bearer);
687         if (err < 0)
688                 return err;
689
690         *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
691
692         return 0;
693 }
694
695 static int parse_bearers(DBusMessageIter *iter, GSList **list)
696 {
697         DBusMessageIter array;
698         int type, err;
699
700         dbus_message_iter_recurse(iter, &array);
701
702         *list = NULL;
703
704         while ((type = dbus_message_iter_get_arg_type(&array)) !=
705                         DBUS_TYPE_INVALID) {
706                 char *bearer_name = NULL;
707
708                 if (type != DBUS_TYPE_STRING) {
709                         g_slist_free(*list);
710                         *list = NULL;
711                         return -EINVAL;
712                 }
713
714                 dbus_message_iter_get_basic(&array, &bearer_name);
715
716                 err = connman_session_parse_bearers(bearer_name, list);
717                 if (err < 0) {
718                         g_slist_free(*list);
719                         *list = NULL;
720                         return err;
721                 }
722
723                 dbus_message_iter_next(&array);
724         }
725
726         return 0;
727 }
728
729 static void filter_bearer(GSList *bearers,
730                                 enum connman_service_type policy,
731                                 GSList **list)
732 {
733         enum connman_service_type bearer;
734         GSList *it;
735
736         if (!bearers)
737                 return;
738
739         for (it = bearers; it; it = it->next) {
740                 bearer = GPOINTER_TO_INT(it->data);
741
742                 if (policy != bearer)
743                         continue;
744
745                 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
746                 return;
747         }
748 }
749
750 static void apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers,
751                                 GSList **list)
752 {
753         enum connman_service_type policy_bearer;
754         GSList *it;
755
756         *list = NULL;
757
758         for (it = policy_bearers; it; it = it->next) {
759                 policy_bearer = GPOINTER_TO_INT(it->data);
760
761                 filter_bearer(bearers, policy_bearer, list);
762         }
763 }
764
765 static char * apply_policy_on_interface(const char *policy_interface,
766                                 const char *user_interface)
767 {
768         if (policy_interface)
769                 return g_strdup(policy_interface);
770         else if (user_interface)
771                 return g_strdup(user_interface);
772         else
773                 return NULL;
774 }
775
776 const char *connman_session_get_owner(struct connman_session *session)
777 {
778         return session->owner;
779 }
780
781 static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
782 {
783         struct session_info *info = user_data;
784         GSList *list;
785
786         for (list = info->config.allowed_bearers;
787                         list; list = list->next) {
788                 enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
789                 const char *name = __connman_service_type2string(bearer);
790
791                 if (!name)
792                         name = "";
793
794                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
795                                                 &name);
796         }
797 }
798
799 static void append_ipconfig_ipv4(DBusMessageIter *iter, void *user_data)
800 {
801         struct connman_service *service = user_data;
802         struct connman_ipconfig *ipconfig_ipv4;
803
804         if (!service)
805                 return;
806
807         if (!__connman_service_is_connected_state(service,
808                                                 CONNMAN_IPCONFIG_TYPE_IPV4))
809                 return;
810
811         ipconfig_ipv4 = __connman_service_get_ip4config(service);
812         if (!ipconfig_ipv4)
813                 return;
814
815         __connman_ipconfig_append_ipv4(ipconfig_ipv4, iter);
816 }
817
818 static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data)
819 {
820         struct connman_service *service = user_data;
821         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
822
823         if (!service)
824                 return;
825
826         if (!__connman_service_is_connected_state(service,
827                                                 CONNMAN_IPCONFIG_TYPE_IPV6))
828                 return;
829
830         ipconfig_ipv4 = __connman_service_get_ip4config(service);
831         ipconfig_ipv6 = __connman_service_get_ip6config(service);
832         if (!ipconfig_ipv6)
833                 return;
834
835         __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4);
836 }
837
838 static void append_notify(DBusMessageIter *dict,
839                                         struct connman_session *session)
840 {
841         struct session_info *info = session->info;
842         struct session_info *info_last = session->info_last;
843         struct connman_service *service;
844         enum connman_service_type type;
845         const char *name, *bearer;
846         char *ifname;
847         int idx;
848
849         if (session->append_all || info->state != info_last->state) {
850                 const char *state = state2string(info->state);
851
852                 connman_dbus_dict_append_basic(dict, "State",
853                                                 DBUS_TYPE_STRING,
854                                                 &state);
855                 info_last->state = info->state;
856         }
857
858         if (session->append_all || session->service != session->service_last) {
859                 if (session->service) {
860                         service = session->service;
861                         name = __connman_service_get_name(service);
862                         idx = __connman_service_get_index(service);
863
864                         ifname = connman_inet_ifname(idx);
865                         if (!ifname)
866                                 ifname = g_strdup("");
867
868                         type = connman_service_get_type(service);
869                         bearer = service2bearer(type);
870                 } else {
871                         service = NULL;
872                         name = "";
873                         ifname = g_strdup("");
874                         bearer = "";
875                 }
876
877                 connman_dbus_dict_append_basic(dict, "Name",
878                                                 DBUS_TYPE_STRING,
879                                                 &name);
880
881                 connman_dbus_dict_append_dict(dict, "IPv4",
882                                                 append_ipconfig_ipv4,
883                                                 service);
884
885                 connman_dbus_dict_append_dict(dict, "IPv6",
886                                                 append_ipconfig_ipv6,
887                                                 service);
888
889                 connman_dbus_dict_append_basic(dict, "Interface",
890                                                 DBUS_TYPE_STRING,
891                                                 &ifname);
892
893                 connman_dbus_dict_append_basic(dict, "Bearer",
894                                                 DBUS_TYPE_STRING,
895                                                 &bearer);
896
897                 g_free(ifname);
898
899                 session->service_last = session->service;
900         }
901
902         if (session->append_all ||
903                         info->config.type != info_last->config.type) {
904                 const char *type = type2string(info->config.type);
905
906                 connman_dbus_dict_append_basic(dict, "ConnectionType",
907                                                 DBUS_TYPE_STRING,
908                                                 &type);
909                 info_last->config.type = info->config.type;
910         }
911
912         if (session->append_all ||
913                         info->config.allowed_bearers != info_last->config.allowed_bearers) {
914                 connman_dbus_dict_append_array(dict, "AllowedBearers",
915                                                 DBUS_TYPE_STRING,
916                                                 append_allowed_bearers,
917                                                 info);
918                 info_last->config.allowed_bearers = info->config.allowed_bearers;
919         }
920
921         if (session->append_all ||
922                         info->config.allowed_interface != info_last->config.allowed_interface) {
923                 char *ifname = info->config.allowed_interface;
924                 if (!ifname)
925                         ifname = "*";
926                 connman_dbus_dict_append_basic(dict, "AllowedInterface",
927                                                 DBUS_TYPE_STRING,
928                                                 &ifname);
929                 info_last->config.allowed_interface = info->config.allowed_interface;
930         }
931
932         if (session->append_all ||
933                         info->config.source_ip_rule != info_last->config.source_ip_rule) {
934                 dbus_bool_t source_ip_rule = FALSE;
935                 if (info->config.source_ip_rule)
936                         source_ip_rule = TRUE;
937                 connman_dbus_dict_append_basic(dict, "SourceIPRule",
938                                                 DBUS_TYPE_BOOLEAN,
939                                                 &source_ip_rule);
940                 info_last->config.source_ip_rule = info->config.source_ip_rule;
941         }
942
943         session->append_all = false;
944 }
945
946 static bool compute_notifiable_changes(struct connman_session *session)
947 {
948         struct session_info *info_last = session->info_last;
949         struct session_info *info = session->info;
950
951         if (session->append_all)
952                 return true;
953
954         if (info->state != info_last->state)
955                 return true;
956
957         if (session->service != session->service_last &&
958                         info->state >= CONNMAN_SESSION_STATE_CONNECTED)
959                 return true;
960
961         if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
962                         info->config.type != info_last->config.type ||
963                         info->config.allowed_interface != info_last->config.allowed_interface ||
964                         info->config.source_ip_rule != info_last->config.source_ip_rule)
965                 return true;
966
967         return false;
968 }
969
970 static gboolean session_notify(gpointer user_data)
971 {
972         struct connman_session *session = user_data;
973         DBusMessage *msg;
974         DBusMessageIter array, dict;
975
976         if (!compute_notifiable_changes(session))
977                 return FALSE;
978
979         DBG("session %p owner %s notify_path %s", session,
980                 session->owner, session->notify_path);
981
982         msg = dbus_message_new_method_call(session->owner, session->notify_path,
983                                                 CONNMAN_NOTIFICATION_INTERFACE,
984                                                 "Update");
985         if (!msg)
986                 return FALSE;
987
988         dbus_message_iter_init_append(msg, &array);
989         connman_dbus_dict_open(&array, &dict);
990
991         append_notify(&dict, session);
992
993         connman_dbus_dict_close(&array, &dict);
994
995         g_dbus_send_message(connection, msg);
996
997         return FALSE;
998 }
999
1000 static void ipconfig_ipv4_changed(struct connman_session *session)
1001 {
1002         connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1003                                                 "IPv4", append_ipconfig_ipv4,
1004                                                 session->service);
1005 }
1006
1007 static void ipconfig_ipv6_changed(struct connman_session *session)
1008 {
1009         connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1010                                                 "IPv6", append_ipconfig_ipv6,
1011                                                 session->service);
1012 }
1013
1014 int connman_session_config_update(struct connman_session *session)
1015 {
1016         struct session_info *info = session->info;
1017         GSList *allowed_bearers;
1018         char *allowed_interface;
1019         int err;
1020
1021         DBG("session %p", session);
1022
1023         /*
1024          * We update all configuration even though only one entry
1025          * might have changed. We can still optimize this later.
1026          */
1027
1028         if (session->id_type != session->policy_config->id_type) {
1029                 cleanup_firewall_session(session);
1030                 err = init_firewall_session(session);
1031                 if (err < 0) {
1032                         connman_session_destroy(session);
1033                         return err;
1034                 }
1035
1036                 session->id_type = session->policy_config->id_type;
1037         }
1038
1039         apply_policy_on_bearers(
1040                 session->policy_config->allowed_bearers,
1041                 session->user_allowed_bearers,
1042                 &allowed_bearers);
1043
1044         allowed_interface = apply_policy_on_interface(
1045                 session->policy_config->allowed_interface,
1046                 session->user_allowed_interface);
1047
1048         if (session->active)
1049                 set_active_session(session, false);
1050
1051         session->active = false;
1052         session_deactivate(session);
1053
1054         g_slist_free(info->config.allowed_bearers);
1055         info->config.allowed_bearers = allowed_bearers;
1056
1057         g_free(info->config.allowed_interface);
1058         info->config.allowed_interface = allowed_interface;
1059
1060         session_activate(session);
1061
1062         info->config.type = apply_policy_on_type(
1063                                 session->policy_config->type,
1064                                 info->config.type);
1065
1066         info->config.roaming_policy = session->policy_config->roaming_policy;
1067
1068         info->config.ecall = session->policy_config->ecall;
1069         if (info->config.ecall)
1070                 ecall_session = session;
1071
1072         info->config.priority = session->policy_config->priority;
1073
1074         session_notify(session);
1075
1076         return 0;
1077 }
1078
1079 static DBusMessage *connect_session(DBusConnection *conn,
1080                                         DBusMessage *msg, void *user_data)
1081 {
1082         struct connman_session *session = user_data;
1083
1084         DBG("session %p", session);
1085
1086         if (ecall_session) {
1087                 if (ecall_session->ecall && ecall_session != session)
1088                         return __connman_error_failed(msg, EBUSY);
1089
1090                 session->ecall = true;
1091         }
1092
1093         if (!session->active) {
1094                 session->active = true;
1095                 set_active_session(session, true);
1096         }
1097
1098         session_activate(session);
1099
1100         __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1101
1102         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1103 }
1104
1105 static DBusMessage *disconnect_session(DBusConnection *conn,
1106                                         DBusMessage *msg, void *user_data)
1107 {
1108         struct connman_session *session = user_data;
1109
1110         DBG("session %p", session);
1111
1112         if (ecall_session) {
1113                 if (ecall_session->ecall && ecall_session != session)
1114                         return __connman_error_failed(msg, EBUSY);
1115
1116                 session->ecall = false;
1117         }
1118
1119         if (session->active) {
1120                 session->active = false;
1121                 set_active_session(session, false);
1122         }
1123
1124         session_deactivate(session);
1125         update_session_state(session);
1126
1127         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1128 }
1129
1130 static DBusMessage *change_session(DBusConnection *conn,
1131                                         DBusMessage *msg, void *user_data)
1132 {
1133         struct connman_session *session = user_data;
1134         struct session_info *info = session->info;
1135         DBusMessageIter iter, value;
1136         const char *name;
1137         const char *val;
1138         GSList *allowed_bearers;
1139         int err;
1140
1141         DBG("session %p", session);
1142         if (!dbus_message_iter_init(msg, &iter))
1143                 return __connman_error_invalid_arguments(msg);
1144
1145         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1146                 return __connman_error_invalid_arguments(msg);
1147
1148         dbus_message_iter_get_basic(&iter, &name);
1149         dbus_message_iter_next(&iter);
1150
1151         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1152                 return __connman_error_invalid_arguments(msg);
1153
1154         dbus_message_iter_recurse(&iter, &value);
1155
1156         switch (dbus_message_iter_get_arg_type(&value)) {
1157         case DBUS_TYPE_ARRAY:
1158                 if (g_str_equal(name, "AllowedBearers")) {
1159                         err = parse_bearers(&value, &allowed_bearers);
1160                         if (err < 0)
1161                                 return __connman_error_failed(msg, -err);
1162
1163                         if (session->active)
1164                                 set_active_session(session, false);
1165
1166                         session->active = false;
1167                         session_deactivate(session);
1168                         update_session_state(session);
1169
1170                         g_slist_free(info->config.allowed_bearers);
1171                         session->user_allowed_bearers = allowed_bearers;
1172
1173                         apply_policy_on_bearers(
1174                                         session->policy_config->allowed_bearers,
1175                                         session->user_allowed_bearers,
1176                                         &info->config.allowed_bearers);
1177
1178                         session_activate(session);
1179                 } else {
1180                         goto err;
1181                 }
1182                 break;
1183         case DBUS_TYPE_STRING:
1184                 if (g_str_equal(name, "ConnectionType")) {
1185                         dbus_message_iter_get_basic(&value, &val);
1186                         info->config.type = apply_policy_on_type(
1187                                 session->policy_config->type,
1188                                 connman_session_parse_connection_type(val));
1189                 } else if (g_str_equal(name, "AllowedInterface")) {
1190                         dbus_message_iter_get_basic(&value, &val);
1191                         if (session->active)
1192                                 set_active_session(session, false);
1193
1194                         session->active = false;
1195                         session_deactivate(session);
1196                         update_session_state(session);
1197
1198                         g_free(session->user_allowed_interface);
1199                         /* empty string means allow any interface */
1200                         if (!g_strcmp0(val, ""))
1201                                 session->user_allowed_interface = NULL;
1202                         else
1203                                 session->user_allowed_interface = g_strdup(val);
1204
1205                         info->config.allowed_interface = apply_policy_on_interface(
1206                                 session->policy_config->allowed_interface,
1207                                 session->user_allowed_interface);
1208
1209                         session_activate(session);
1210                 } else {
1211                         goto err;
1212                 }
1213                 break;
1214         case DBUS_TYPE_BOOLEAN:
1215                 if (g_str_equal(name, "SourceIPRule")) {
1216                         dbus_bool_t source_ip_rule;
1217                         dbus_message_iter_get_basic(&value, &source_ip_rule);
1218
1219                         info->config.source_ip_rule = source_ip_rule;
1220                         update_session_state(session);
1221                 } else {
1222                         goto err;
1223                 }
1224                 break;
1225         default:
1226                 goto err;
1227         }
1228
1229         session_notify(session);
1230
1231         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1232
1233 err:
1234         return __connman_error_invalid_arguments(msg);
1235 }
1236
1237 static void release_session(gpointer key, gpointer value, gpointer user_data)
1238 {
1239         struct connman_session *session = value;
1240         DBusMessage *message;
1241
1242         DBG("owner %s path %s", session->owner, session->notify_path);
1243
1244         if (session->notify_watch > 0)
1245                 g_dbus_remove_watch(connection, session->notify_watch);
1246
1247         g_dbus_unregister_interface(connection, session->session_path,
1248                                                 CONNMAN_SESSION_INTERFACE);
1249
1250         message = dbus_message_new_method_call(session->owner,
1251                                                 session->notify_path,
1252                                                 CONNMAN_NOTIFICATION_INTERFACE,
1253                                                 "Release");
1254         if (!message)
1255                 return;
1256
1257         dbus_message_set_no_reply(message, TRUE);
1258
1259         g_dbus_send_message(connection, message);
1260 }
1261
1262 static int session_disconnect(struct connman_session *session)
1263 {
1264         DBG("session %p, %s", session, session->owner);
1265
1266         if (session->notify_watch > 0)
1267                 g_dbus_remove_watch(connection, session->notify_watch);
1268
1269         g_dbus_unregister_interface(connection, session->session_path,
1270                                                 CONNMAN_SESSION_INTERFACE);
1271
1272         g_hash_table_remove(session_hash, session->session_path);
1273
1274         return 0;
1275 }
1276
1277 static void owner_disconnect(DBusConnection *conn, void *user_data)
1278 {
1279         struct connman_session *session = user_data;
1280
1281         DBG("session %p, %s died", session, session->owner);
1282
1283         session_disconnect(session);
1284 }
1285
1286 static DBusMessage *destroy_session(DBusConnection *conn,
1287                                         DBusMessage *msg, void *user_data)
1288 {
1289         struct connman_session *session = user_data;
1290
1291         DBG("session %p", session);
1292
1293         if (ecall_session && ecall_session != session)
1294                 return __connman_error_failed(msg, EBUSY);
1295
1296         session_disconnect(session);
1297
1298         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1299 }
1300
1301 static const GDBusMethodTable session_methods[] = {
1302         { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
1303         { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
1304         { GDBUS_METHOD("Disconnect", NULL, NULL,
1305                         disconnect_session ) },
1306         { GDBUS_METHOD("Change",
1307                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1308                         NULL, change_session) },
1309         { },
1310 };
1311
1312 static int session_policy_config_cb(struct connman_session *session,
1313                                 struct connman_session_config *config,
1314                                 void *user_data, int err)
1315 {
1316         struct creation_data *creation_data = user_data;
1317         struct session_info *info, *info_last;
1318         DBusMessage *reply;
1319
1320         DBG("session %p config %p", session, config);
1321
1322         if (err < 0)
1323                 goto err;
1324
1325         session->policy_config = config;
1326         session->info->config.source_ip_rule = creation_data->source_ip_rule;
1327
1328         session->mark = session_mark++;
1329         session->index = -1;
1330
1331         err = init_firewall_session(session);
1332         if (err < 0)
1333                 goto err;
1334
1335         err = init_routing_table(session);
1336         if (err < 0)
1337                 goto err;
1338
1339         info = session->info;
1340         info_last = session->info_last;
1341
1342         if (session->policy_config->ecall)
1343                 ecall_session = session;
1344
1345         info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1346         info->config.type = apply_policy_on_type(
1347                                 session->policy_config->type,
1348                                 creation_data->type);
1349         info->config.priority = session->policy_config->priority;
1350         info->config.roaming_policy = session->policy_config->roaming_policy;
1351
1352         session->user_allowed_bearers = creation_data->allowed_bearers;
1353         creation_data->allowed_bearers = NULL;
1354
1355         session->user_allowed_interface = creation_data->allowed_interface;
1356         creation_data->allowed_interface = NULL;
1357
1358         apply_policy_on_bearers(
1359                         session->policy_config->allowed_bearers,
1360                         session->user_allowed_bearers,
1361                         &info->config.allowed_bearers);
1362
1363         info->config.allowed_interface = apply_policy_on_interface(
1364                 session->policy_config->allowed_interface,
1365                 session->user_allowed_interface);
1366
1367         g_hash_table_replace(session_hash, session->session_path, session);
1368
1369         DBG("add %s", session->session_path);
1370
1371         if (!g_dbus_register_interface(connection, session->session_path,
1372                                         CONNMAN_SESSION_INTERFACE,
1373                                         session_methods, NULL, NULL,
1374                                         session, NULL)) {
1375                 connman_error("Failed to register %s", session->session_path);
1376                 g_hash_table_remove(session_hash, session->session_path);
1377                 err = -EINVAL;
1378                 goto err;
1379         }
1380
1381         reply = g_dbus_create_reply(creation_data->pending,
1382                                 DBUS_TYPE_OBJECT_PATH, &session->session_path,
1383                                 DBUS_TYPE_INVALID);
1384         g_dbus_send_message(connection, reply);
1385         creation_data->pending = NULL;
1386
1387         info_last->state = info->state;
1388         info_last->config.priority = info->config.priority;
1389         info_last->config.roaming_policy = info->config.roaming_policy;
1390         info_last->config.allowed_bearers = info->config.allowed_bearers;
1391         info_last->config.allowed_interface = info->config.allowed_interface;
1392         info_last->config.source_ip_rule = info->config.source_ip_rule;
1393
1394         session->append_all = true;
1395
1396         cleanup_creation_data(creation_data);
1397
1398         session_activate(session);
1399
1400         return 0;
1401
1402 err:
1403         reply = __connman_error_failed(creation_data->pending, -err);
1404         g_dbus_send_message(connection, reply);
1405         creation_data->pending = NULL;
1406
1407         cleanup_session(session);
1408         cleanup_creation_data(creation_data);
1409
1410         return err;
1411 }
1412
1413 int __connman_session_create(DBusMessage *msg)
1414 {
1415         const char *owner, *notify_path;
1416         char *session_path = NULL;
1417         DBusMessageIter iter, array;
1418         struct connman_session *session = NULL;
1419         struct creation_data *creation_data = NULL;
1420         bool user_allowed_bearers = false;
1421         bool user_connection_type = false;
1422         int err, i;
1423         char *str;
1424
1425         owner = dbus_message_get_sender(msg);
1426
1427         DBG("owner %s", owner);
1428
1429         if (ecall_session && ecall_session->ecall) {
1430                 /*
1431                  * If there is an emergency call already going on,
1432                  * ignore session creation attempt
1433                  */
1434                 err = -EBUSY;
1435                 goto err;
1436         }
1437
1438         creation_data = g_try_new0(struct creation_data, 1);
1439         if (!creation_data) {
1440                 err = -ENOMEM;
1441                 goto err;
1442         }
1443
1444         creation_data->pending = dbus_message_ref(msg);
1445
1446         dbus_message_iter_init(msg, &iter);
1447         dbus_message_iter_recurse(&iter, &array);
1448
1449         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1450                 DBusMessageIter entry, value;
1451                 const char *key, *val;
1452
1453                 dbus_message_iter_recurse(&array, &entry);
1454                 dbus_message_iter_get_basic(&entry, &key);
1455
1456                 dbus_message_iter_next(&entry);
1457                 dbus_message_iter_recurse(&entry, &value);
1458
1459                 switch (dbus_message_iter_get_arg_type(&value)) {
1460                 case DBUS_TYPE_ARRAY:
1461                         if (g_str_equal(key, "AllowedBearers")) {
1462                                 err = parse_bearers(&value,
1463                                         &creation_data->allowed_bearers);
1464                                 if (err < 0)
1465                                         goto err;
1466
1467                                 user_allowed_bearers = true;
1468                         } else {
1469                                 err = -EINVAL;
1470                                 goto err;
1471                         }
1472                         break;
1473                 case DBUS_TYPE_STRING:
1474                         if (g_str_equal(key, "ConnectionType")) {
1475                                 dbus_message_iter_get_basic(&value, &val);
1476                                 creation_data->type =
1477                                         connman_session_parse_connection_type(val);
1478
1479                                 user_connection_type = true;
1480                         } else if (g_str_equal(key, "AllowedInterface")) {
1481                                 dbus_message_iter_get_basic(&value, &val);
1482                                 creation_data->allowed_interface = g_strdup(val);
1483                         } else {
1484                                 err = -EINVAL;
1485                                 goto err;
1486                         }
1487                         break;
1488                 case DBUS_TYPE_BOOLEAN:
1489                         if (g_str_equal(key, "SourceIPRule")) {
1490                                 dbus_bool_t source_ip_rule;
1491                                 dbus_message_iter_get_basic(&value, &source_ip_rule);
1492                                 creation_data->source_ip_rule = source_ip_rule;
1493                         } else {
1494                                 err = -EINVAL;
1495                                 goto err;
1496                         }
1497                         break;
1498                 default:
1499                         err = -EINVAL;
1500                         goto err;
1501                 }
1502
1503                 dbus_message_iter_next(&array);
1504         }
1505
1506         /*
1507          * If the user hasn't provided a configuration, we set
1508          * the default configuration.
1509          *
1510          * For AllowedBearers this is '*', ...
1511          */
1512         if (!user_allowed_bearers) {
1513                 add_default_bearer_types(&creation_data->allowed_bearers);
1514                 if (!creation_data->allowed_bearers) {
1515                         err = -ENOMEM;
1516                         goto err;
1517                 }
1518         }
1519
1520         /* ... and for ConnectionType it is 'any'. */
1521         if (!user_connection_type)
1522                 creation_data->type = CONNMAN_SESSION_TYPE_ANY;
1523
1524         dbus_message_iter_next(&iter);
1525         dbus_message_iter_get_basic(&iter, &notify_path);
1526
1527         if (!notify_path) {
1528                 err = -EINVAL;
1529                 goto err;
1530         }
1531
1532         str = g_strdup(owner);
1533         for (i = 0; str[i] != '\0'; i++)
1534                 if (str[i] == ':' || str[i] == '.')
1535                         str[i] = '_';
1536         session_path = g_strdup_printf("/sessions/%s%s", str, notify_path);
1537         g_free(str);
1538
1539         if (!session_path) {
1540                 err = -ENOMEM;
1541                 goto err;
1542         }
1543
1544         session = g_hash_table_lookup(session_hash, session_path);
1545         if (session) {
1546                 g_free(session_path);
1547                 session = NULL;
1548                 err = -EEXIST;
1549                 goto err;
1550         }
1551
1552         session = g_try_new0(struct connman_session, 1);
1553         if (!session) {
1554                 g_free(session_path);
1555                 err = -ENOMEM;
1556                 goto err;
1557         }
1558
1559         creation_data->session = session;
1560         session->session_path = session_path;
1561
1562         session->info = g_try_new0(struct session_info, 1);
1563         if (!session->info) {
1564                 err = -ENOMEM;
1565                 goto err;
1566         }
1567
1568         session->info_last = g_try_new0(struct session_info, 1);
1569         if (!session->info_last) {
1570                 err = -ENOMEM;
1571                 goto err;
1572         }
1573
1574         session->owner = g_strdup(owner);
1575         session->notify_path = g_strdup(notify_path);
1576         session->notify_watch =
1577                 g_dbus_add_disconnect_watch(connection, session->owner,
1578                                         owner_disconnect, session, NULL);
1579
1580         err = create_policy_config(session, session_policy_config_cb,
1581                                         creation_data);
1582         if (err < 0 && err != -EINPROGRESS)
1583                 return err;
1584
1585         return -EINPROGRESS;
1586
1587 err:
1588         connman_error("Failed to create session");
1589
1590         free_session(session);
1591
1592         cleanup_creation_data(creation_data);
1593         return err;
1594 }
1595
1596 bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason)
1597 {
1598         if (!policy || !policy->autoconnect)
1599                 return true;
1600
1601         return policy->autoconnect(reason);
1602 }
1603
1604 void connman_session_destroy(struct connman_session *session)
1605 {
1606         DBG("session %p", session);
1607
1608         session_disconnect(session);
1609 }
1610
1611 int __connman_session_destroy(DBusMessage *msg)
1612 {
1613         const char *owner, *session_path;
1614         struct connman_session *session;
1615
1616         owner = dbus_message_get_sender(msg);
1617
1618         DBG("owner %s", owner);
1619
1620         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path,
1621                                                         DBUS_TYPE_INVALID);
1622         if (!session_path)
1623                 return -EINVAL;
1624
1625         session = g_hash_table_lookup(session_hash, session_path);
1626         if (!session)
1627                 return -EINVAL;
1628
1629         if (g_strcmp0(owner, session->owner) != 0)
1630                 return -EACCES;
1631
1632         connman_session_destroy(session);
1633
1634         return 0;
1635 }
1636
1637 int connman_session_connect(struct connman_service *service)
1638 {
1639         DBG("service %p name %s", service, __connman_service_get_name(service));
1640
1641         return __connman_service_connect(service,
1642                                 CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1643 }
1644
1645 int connman_session_disconnect(struct connman_service *service)
1646 {
1647         DBG("service %p", service);
1648
1649         return __connman_service_disconnect(service);
1650 }
1651
1652 static enum connman_session_state service_to_session_state(
1653                                         enum connman_service_state state)
1654 {
1655         switch (state) {
1656         case CONNMAN_SERVICE_STATE_UNKNOWN:
1657         case CONNMAN_SERVICE_STATE_IDLE:
1658         case CONNMAN_SERVICE_STATE_ASSOCIATION:
1659         case CONNMAN_SERVICE_STATE_CONFIGURATION:
1660         case CONNMAN_SERVICE_STATE_DISCONNECT:
1661         case CONNMAN_SERVICE_STATE_FAILURE:
1662                 break;
1663         case CONNMAN_SERVICE_STATE_READY:
1664                 return CONNMAN_SESSION_STATE_CONNECTED;
1665         case CONNMAN_SERVICE_STATE_ONLINE:
1666                 return CONNMAN_SESSION_STATE_ONLINE;
1667         }
1668
1669         return CONNMAN_SESSION_STATE_DISCONNECTED;
1670 }
1671
1672 static void update_session_state(struct connman_session *session)
1673 {
1674         enum connman_service_state service_state;
1675         enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1676
1677         if (session->service) {
1678                 service_state = __connman_service_get_state(session->service);
1679                 state = service_to_session_state(service_state);
1680                 session->info->state = state;
1681         }
1682         session->info->state = state;
1683
1684         DBG("session %p state %s", session, state2string(state));
1685
1686         update_firewall(session);
1687         del_nat_rules(session);
1688         update_routing_table(session);
1689         add_nat_rules(session);
1690
1691         if (policy && policy->update_session_state)
1692                 policy->update_session_state(session, state);
1693
1694         session_notify(session);
1695 }
1696
1697 static bool session_match_service(struct connman_session *session,
1698                                 struct connman_service *service)
1699 {
1700         enum connman_service_type bearer_type;
1701         enum connman_service_type service_type;
1702         enum connman_service_type current_service_type;
1703         GSList *list;
1704         char *ifname;
1705
1706         if (policy && policy->allowed)
1707                 return policy->allowed(session, service);
1708
1709         current_service_type = connman_service_get_type(session->service);
1710
1711         for (list = session->info->config.allowed_bearers; list; list = list->next) {
1712                 bearer_type = GPOINTER_TO_INT(list->data);
1713                 service_type = connman_service_get_type(service);
1714                 ifname = connman_service_get_interface(service);
1715
1716                 if (bearer_type == current_service_type)
1717                         return false;
1718
1719                 if (bearer_type == service_type &&
1720                         (session->info->config.allowed_interface == NULL ||
1721                         !g_strcmp0(session->info->config.allowed_interface, "*") ||
1722                         !g_strcmp0(session->info->config.allowed_interface, ifname))) {
1723                                 g_free(ifname);
1724                                 return true;
1725                 }
1726                 g_free(ifname);
1727         }
1728
1729         return false;
1730 }
1731
1732 static bool is_session_connected(struct connman_session *session,
1733                                 enum connman_service_state state)
1734
1735 {
1736         switch (state) {
1737         case CONNMAN_SERVICE_STATE_UNKNOWN:
1738         case CONNMAN_SERVICE_STATE_IDLE:
1739         case CONNMAN_SERVICE_STATE_ASSOCIATION:
1740         case CONNMAN_SERVICE_STATE_CONFIGURATION:
1741         case CONNMAN_SERVICE_STATE_DISCONNECT:
1742         case CONNMAN_SERVICE_STATE_FAILURE:
1743                           break;
1744         case CONNMAN_SERVICE_STATE_READY:
1745                 if (session->info->config.type == CONNMAN_SESSION_TYPE_INTERNET)
1746                         return false;
1747                 /* fall through */
1748         case CONNMAN_SERVICE_STATE_ONLINE:
1749                 return true;
1750         }
1751
1752         return false;
1753 }
1754
1755 static void session_activate(struct connman_session *session)
1756 {
1757         GHashTableIter iter;
1758         gpointer key, value;
1759
1760         if (!service_hash)
1761                 return;
1762
1763         if (policy && policy->get_service_for_session) {
1764                 struct connman_service *service;
1765                 struct connman_service_info *info;
1766                 GSList *service_list = NULL;
1767                 enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1768
1769                 g_hash_table_iter_init(&iter, service_hash);
1770
1771                 while (g_hash_table_iter_next(&iter, &key, &value)) {
1772                         struct connman_service_info *info = value;
1773                         state = __connman_service_get_state(info->service);
1774
1775                         if (is_session_connected(session, state))
1776                                 service_list = g_slist_prepend(service_list,
1777                                                                info->service);
1778                 }
1779
1780                 service_list = g_slist_reverse(service_list);
1781                 service = policy->get_service_for_session(session, service_list);
1782
1783                 if (service) {
1784                         info = g_hash_table_lookup(service_hash, service);
1785                         DBG("session %p add service %p", session, info->service);
1786
1787                         info->sessions = g_slist_prepend(info->sessions,
1788                                                         session);
1789                         session->service = info->service;
1790                         update_session_state(session);
1791                 }
1792
1793                 g_slist_free(service_list);
1794                 return;
1795         }
1796
1797         g_hash_table_iter_init(&iter, service_hash);
1798         while (g_hash_table_iter_next(&iter, &key, &value)) {
1799                 struct connman_service_info *info = value;
1800                 enum connman_service_state state;
1801
1802                 state = __connman_service_get_state(info->service);
1803
1804                 if (is_session_connected(session, state) &&
1805                                 session_match_service(session, info->service)) {
1806                         DBG("session %p add service %p", session, info->service);
1807
1808                         info->sessions = g_slist_prepend(info->sessions,
1809                                                         session);
1810                         session->service = info->service;
1811                         update_session_state(session);
1812
1813                         return;
1814                 }
1815         }
1816
1817         session_notify(session);
1818 }
1819
1820 static void session_deactivate(struct connman_session *session)
1821 {
1822         struct connman_service_info *info;
1823
1824         if (!service_hash)
1825                 return;
1826
1827         if (!session->service)
1828                 return;
1829
1830         info = g_hash_table_lookup(service_hash, session->service);
1831         if (!info)
1832                 return;
1833
1834         info->sessions = g_slist_remove(info->sessions, session);
1835         session->service = NULL;
1836
1837         session->info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1838 }
1839
1840 static void handle_service_state_online(struct connman_service *service,
1841                                         enum connman_service_state state,
1842                                         struct connman_service_info *info)
1843 {
1844         GHashTableIter iter;
1845         gpointer key, value;
1846
1847         g_hash_table_iter_init(&iter, session_hash);
1848         while (g_hash_table_iter_next(&iter, &key, &value)) {
1849                 struct connman_session *session = value;
1850                 bool connected;
1851
1852                 connected = is_session_connected(session, state);
1853
1854                 if (session->service == service) {
1855                         if (!connected) {
1856                                 DBG("session %p remove service %p", session, service);
1857                                 info->sessions = g_slist_remove(info->sessions,
1858                                                         session);
1859                                 session->service = NULL;
1860                                 update_session_state(session);
1861                         }
1862                 } else if (connected && session_match_service(session, service)) {
1863                         DBG("session %p add service %p", session, service);
1864
1865                         info->sessions = g_slist_prepend(info->sessions,
1866                                                         session);
1867                         session->service = service;
1868                         update_session_state(session);
1869                 }
1870         }
1871 }
1872
1873 static void handle_service_state_offline(struct connman_service *service,
1874                                         struct connman_service_info *info)
1875 {
1876         GSList *list;
1877
1878         for (list = info->sessions; list; list = list->next) {
1879                 struct connman_session *session = list->data;
1880
1881                 if (session->service != service) {
1882                         connman_warn("session %p should have session %p assigned",
1883                                         session, service);
1884                         continue;
1885                 }
1886
1887                 DBG("session %p remove service %p", session, service);
1888
1889                 session->service = NULL;
1890                 update_session_state(session);
1891                 session_activate(session);
1892         }
1893 }
1894
1895 static void service_state_changed(struct connman_service *service,
1896                                 enum connman_service_state state)
1897 {
1898         struct connman_service_info *info;
1899
1900         DBG("service %p state %d", service, state);
1901
1902         info = g_hash_table_lookup(service_hash, service);
1903
1904         switch (state) {
1905         case CONNMAN_SERVICE_STATE_UNKNOWN:
1906         case CONNMAN_SERVICE_STATE_IDLE:
1907         case CONNMAN_SERVICE_STATE_ASSOCIATION:
1908         case CONNMAN_SERVICE_STATE_CONFIGURATION:
1909         case CONNMAN_SERVICE_STATE_FAILURE:
1910         case CONNMAN_SERVICE_STATE_DISCONNECT:
1911                 if (!info)
1912                         return;
1913
1914                 handle_service_state_offline(service, info);
1915
1916                 g_hash_table_remove(service_hash, service);
1917
1918                 return;
1919         case CONNMAN_SERVICE_STATE_READY:
1920         case CONNMAN_SERVICE_STATE_ONLINE:
1921                 if (!info) {
1922                         info = g_new0(struct connman_service_info, 1);
1923                         g_hash_table_replace(service_hash, service, info);
1924                 }
1925
1926                 info->service = service;
1927                 handle_service_state_online(service, state, info);
1928         }
1929 }
1930
1931 static void ipconfig_changed(struct connman_service *service,
1932                                 struct connman_ipconfig *ipconfig)
1933 {
1934         GHashTableIter iter;
1935         gpointer key, value;
1936         struct connman_session *session;
1937         struct session_info *info;
1938         enum connman_ipconfig_type type;
1939
1940         DBG("service %p ipconfig %p", service, ipconfig);
1941
1942         type = __connman_ipconfig_get_config_type(ipconfig);
1943
1944         g_hash_table_iter_init(&iter, session_hash);
1945
1946         while (g_hash_table_iter_next(&iter, &key, &value)) {
1947                 session = value;
1948                 info = session->info;
1949
1950                 if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
1951                         continue;
1952
1953                 if (session->service && session->service == service) {
1954                         update_session_state(session);
1955
1956                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1957                                 ipconfig_ipv4_changed(session);
1958                         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1959                                 ipconfig_ipv6_changed(session);
1960                 }
1961         }
1962 }
1963
1964 static struct connman_notifier session_notifier = {
1965         .name                   = "session",
1966         .service_state_changed  = service_state_changed,
1967         .ipconfig_changed       = ipconfig_changed,
1968 };
1969
1970 int __connman_session_init(void)
1971 {
1972         int err;
1973
1974         DBG("");
1975
1976         connection = connman_dbus_get_connection();
1977         if (!connection)
1978                 return -1;
1979
1980         err = connman_notifier_register(&session_notifier);
1981         if (err < 0) {
1982                 dbus_connection_unref(connection);
1983                 return err;
1984         }
1985
1986         session_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1987                                                 NULL, cleanup_session);
1988
1989         service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1990                                                 NULL, cleanup_service);
1991         return 0;
1992 }
1993
1994 void __connman_session_cleanup(void)
1995 {
1996         DBG("");
1997
1998         if (!connection)
1999                 return;
2000
2001         connman_notifier_unregister(&session_notifier);
2002
2003         g_hash_table_foreach(session_hash, release_session, NULL);
2004         g_hash_table_destroy(session_hash);
2005         session_hash = NULL;
2006         g_hash_table_destroy(service_hash);
2007         service_hash = NULL;
2008
2009         dbus_connection_unref(connection);
2010 }