diff options
Diffstat (limited to 'src/session.c')
-rw-r--r-- | src/session.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/src/session.c b/src/session.c index 26cbf878..808931a8 100644 --- a/src/session.c +++ b/src/session.c @@ -28,8 +28,6 @@ #include <gdbus.h> -#include <connman/session.h> - #include "connman.h" static DBusConnection *connection; @@ -65,7 +63,9 @@ struct connman_session { struct firewall_context *fw; uint32_t mark; int index; + char *addr; char *gateway; + unsigned char prefixlen; bool policy_routing; bool snat_enabled; }; @@ -79,6 +79,7 @@ struct fw_snat { GSList *sessions; int id; int index; + char *addr; struct firewall_context *fw; }; @@ -203,7 +204,7 @@ static char *service2bearer(enum connman_service_type type) return ""; } -static struct fw_snat *fw_snat_lookup(int index) +static struct fw_snat *fw_snat_lookup(int index, const char *addr) { struct fw_snat *fw_snat; GSList *list; @@ -211,8 +212,11 @@ static struct fw_snat *fw_snat_lookup(int index) for (list = fw_snat_list; list; list = list->next) { fw_snat = list->data; - if (fw_snat->index == index) + if (fw_snat->index == index) { + if (g_strcmp0(addr, fw_snat->addr) != 0) + continue; return fw_snat; + } } return NULL; } @@ -227,6 +231,7 @@ static int fw_snat_create(struct connman_session *session, fw_snat->fw = __connman_firewall_create(); fw_snat->index = index; + fw_snat->addr = g_strdup(addr); fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw, index, ifname, addr); @@ -241,6 +246,7 @@ static int fw_snat_create(struct connman_session *session, return 0; err: __connman_firewall_destroy(fw_snat->fw); + g_free(fw_snat->addr); g_free(fw_snat); return err; } @@ -353,13 +359,17 @@ static void del_default_route(struct connman_session *session) if (!session->gateway) return; - DBG("index %d routing table %d default gateway %s", - session->index, session->mark, session->gateway); + DBG("index %d routing table %d default gateway %s/%u", + session->index, session->mark, session->gateway, session->prefixlen); + + __connman_inet_del_subnet_from_table(session->mark, + session->index, session->gateway, session->prefixlen); __connman_inet_del_default_from_table(session->mark, session->index, session->gateway); g_free(session->gateway); session->gateway = NULL; + session->prefixlen = 0; session->index = -1; } @@ -379,13 +389,20 @@ static void add_default_route(struct connman_session *session) if (!session->gateway) session->gateway = g_strdup(inet_ntoa(addr)); - DBG("index %d routing table %d default gateway %s", - session->index, session->mark, session->gateway); + session->prefixlen = __connman_ipconfig_get_prefixlen(ipconfig); + + DBG("index %d routing table %d default gateway %s/%u", + session->index, session->mark, session->gateway, session->prefixlen); err = __connman_inet_add_default_to_table(session->mark, session->index, session->gateway); if (err < 0) DBG("session %p %s", session, strerror(-err)); + + err = __connman_inet_add_subnet_to_table(session->mark, + session->index, session->gateway, session->prefixlen); + if (err < 0) + DBG("session add subnet route %p %s", session, strerror(-err)); } static void del_nat_rules(struct connman_session *session) @@ -396,7 +413,7 @@ static void del_nat_rules(struct connman_session *session) return; session->snat_enabled = false; - fw_snat = fw_snat_lookup(session->index); + fw_snat = fw_snat_lookup(session->index, session->addr); if (!fw_snat) return; @@ -423,8 +440,11 @@ static void add_nat_rules(struct connman_session *session) if (!addr) return; + g_free(session->addr); + session->addr = g_strdup(addr); + session->snat_enabled = true; - fw_snat = fw_snat_lookup(index); + fw_snat = fw_snat_lookup(index, session->addr); if (fw_snat) { fw_snat_ref(session, fw_snat); return; @@ -496,6 +516,9 @@ static void free_session(struct connman_session *session) if (session->notify_watch > 0) g_dbus_remove_watch(connection, session->notify_watch); + g_dbus_unregister_interface(connection, session->session_path, + CONNMAN_SESSION_INTERFACE); + destroy_policy_config(session); g_slist_free(session->info->config.allowed_bearers); g_free(session->info->config.allowed_interface); @@ -505,6 +528,7 @@ static void free_session(struct connman_session *session) g_free(session->info); g_free(session->info_last); g_free(session->gateway); + g_free(session->addr); g_free(session); } @@ -551,6 +575,7 @@ struct creation_data { GSList *allowed_bearers; char *allowed_interface; bool source_ip_rule; + char *context_identifier; }; static void cleanup_creation_data(struct creation_data *creation_data) @@ -560,6 +585,8 @@ static void cleanup_creation_data(struct creation_data *creation_data) if (creation_data->pending) dbus_message_unref(creation_data->pending); + if (creation_data->context_identifier) + g_free(creation_data->context_identifier); g_slist_free(creation_data->allowed_bearers); g_free(creation_data->allowed_interface); @@ -930,6 +957,17 @@ static void append_notify(DBusMessageIter *dict, } if (session->append_all || + info->config.context_identifier != info_last->config.context_identifier) { + char *ifname = info->config.context_identifier; + if (!ifname) + ifname = ""; + connman_dbus_dict_append_basic(dict, "ContextIdentifier", + DBUS_TYPE_STRING, + &ifname); + info_last->config.context_identifier = info->config.context_identifier; + } + + if (session->append_all || info->config.source_ip_rule != info_last->config.source_ip_rule) { dbus_bool_t source_ip_rule = FALSE; if (info->config.source_ip_rule) @@ -1375,7 +1413,7 @@ static int session_policy_config_cb(struct connman_session *session, connman_error("Failed to register %s", session->session_path); g_hash_table_remove(session_hash, session->session_path); err = -EINVAL; - goto err; + goto err_notify; } reply = g_dbus_create_reply(creation_data->pending, @@ -1400,11 +1438,13 @@ static int session_policy_config_cb(struct connman_session *session, return 0; err: + cleanup_session(session); + +err_notify: reply = __connman_error_failed(creation_data->pending, -err); g_dbus_send_message(connection, reply); creation_data->pending = NULL; - cleanup_session(session); cleanup_creation_data(creation_data); return err; @@ -1477,6 +1517,9 @@ int __connman_session_create(DBusMessage *msg) connman_session_parse_connection_type(val); user_connection_type = true; + } else if (g_str_equal(key, "ContextIdentifier")) { + dbus_message_iter_get_basic(&value, &val); + creation_data->context_identifier = g_strdup(val); } else if (g_str_equal(key, "AllowedInterface")) { dbus_message_iter_get_basic(&value, &val); creation_data->allowed_interface = g_strdup(val); @@ -1675,7 +1718,7 @@ static void update_session_state(struct connman_session *session) enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED; if (session->service) { - service_state = __connman_service_get_state(session->service); + service_state = connman_service_get_state(session->service); state = service_to_session_state(service_state); session->info->state = state; } @@ -1770,7 +1813,7 @@ static void session_activate(struct connman_session *session) while (g_hash_table_iter_next(&iter, &key, &value)) { struct connman_service_info *info = value; - state = __connman_service_get_state(info->service); + state = connman_service_get_state(info->service); if (is_session_connected(session, state)) service_list = g_slist_prepend(service_list, @@ -1799,7 +1842,7 @@ static void session_activate(struct connman_session *session) struct connman_service_info *info = value; enum connman_service_state state; - state = __connman_service_get_state(info->service); + state = connman_service_get_state(info->service); if (is_session_connected(session, state) && session_match_service(session, info->service)) { @@ -1961,7 +2004,7 @@ static void ipconfig_changed(struct connman_service *service, } } -static struct connman_notifier session_notifier = { +static const struct connman_notifier session_notifier = { .name = "session", .service_state_changed = service_state_changed, .ipconfig_changed = ipconfig_changed, |