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