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