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