Send connman mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."


Today's Topics:

   1. [PATCH 0/5] session: add per-interface routing
      ([email protected])
   2. [PATCH 1/5] session: fix default route for ppp services
      ([email protected])
   3. [PATCH 2/5] session: add allowed interface config parameter
      ([email protected])
   4. [PATCH 3/5] client: add session allowed interface config
      ([email protected])
   5. [PATCH 4/5] session: add source ip rule ([email protected])


----------------------------------------------------------------------

Message: 1
Date: Mon, 12 Dec 2016 18:35:03 +0000
From: [email protected]
To: [email protected]
Subject: [PATCH 0/5] session: add per-interface routing
Message-ID: <[email protected]>

From: Lukasz Nowak <[email protected]>

Adding a new feature to the sessions, which allows applications to direct
routed traffic to a specific network interface.

This requires that multiple default routes with gateways are set up, one
for each interface. And then iproute and iptables rules need to be added
to direct traffic based on source ip address, to the correct routing table.
Applications can use bind before connect mechanism, to bind sockets to
required interfaces.

The application side can be tested with:
ping -I <interface_ip> <target_ip>

Use case for this is to have multiple network interfaces available for
external traffic at the same time. It can be used to validate that a full
path to an external server is working properly, by maintaining multiple
tcp connections, one for each interface.

Lukasz Nowak (5):
  session: fix default route for ppp services
  session: add allowed interface config parameter
  client: add session allowed interface config
  session: add source ip rule
  client: add session source ip rule

 client/commands.c       |  39 +++++++++++++
 include/session.h       |   2 +
 src/connman.h           |   3 +-
 src/firewall-iptables.c |  12 +++-
 src/firewall-nftables.c |   5 +-
 src/session.c           | 147 ++++++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 198 insertions(+), 10 deletions(-)

-- 
2.7.4



------------------------------

Message: 2
Date: Mon, 12 Dec 2016 18:35:04 +0000
From: [email protected]
To: [email protected]
Subject: [PATCH 1/5] session: fix default route for ppp services
Message-ID: <[email protected]>

From: Lukasz Nowak <[email protected]>

When a session is connected to a ppp service, ipconfig
will not contain a gateway IP address. Currently setting up
of the session routing table fails, due to
__connman_inet_add_default_to_table returning an error.

In that scenario, INADDR_ANY needs to be used as a gateway.
---
 src/session.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/session.c b/src/session.c
index b1e9e1b..09fc7c3 100644
--- a/src/session.c
+++ b/src/session.c
@@ -351,6 +351,7 @@ static void add_default_route(struct connman_session 
*session)
 {
        struct connman_ipconfig *ipconfig;
        int err;
+       struct in_addr addr = { INADDR_ANY };
 
        if (!session->service)
                return;
@@ -359,6 +360,9 @@ static void add_default_route(struct connman_session 
*session)
        session->index = __connman_ipconfig_get_index(ipconfig);
        session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
 
+       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);
 
-- 
2.7.4



------------------------------

Message: 3
Date: Mon, 12 Dec 2016 18:35:05 +0000
From: [email protected]
To: [email protected]
Subject: [PATCH 2/5] session: add allowed interface config parameter
Message-ID: <[email protected]>

From: Lukasz Nowak <[email protected]>

In order to be able to bind a session to a specific interface,
a config option has been added. It is supported through both
dbus and session policy. Policy always overrides dbus.

This is the first step to implement per-interface routing.
Next step will be to add src ip rules to iptables, which
will allow the application to transmit through multiple
interfaces.
---
 include/session.h |  1 +
 src/session.c     | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/include/session.h b/include/session.h
index 37dfc4e..e8d7e93 100644
--- a/include/session.h
+++ b/include/session.h
@@ -65,6 +65,7 @@ struct connman_session_config {
        enum connman_session_type type;
        bool ecall;
        GSList *allowed_bearers;
+       char *allowed_interface;
 };
 
 typedef int (* connman_session_config_func_t) (struct connman_session *session,
diff --git a/src/session.c b/src/session.c
index 09fc7c3..2dfd428 100644
--- a/src/session.c
+++ b/src/session.c
@@ -63,6 +63,7 @@ struct connman_session {
        struct connman_service *service_last;
        struct connman_session_config *policy_config;
        GSList *user_allowed_bearers;
+       char *user_allowed_interface;
 
        bool ecall;
 
@@ -467,6 +468,7 @@ static void free_session(struct connman_session *session)
 
        destroy_policy_config(session);
        g_slist_free(session->info->config.allowed_bearers);
+       g_free(session->info->config.allowed_interface);
        g_free(session->owner);
        g_free(session->session_path);
        g_free(session->notify_path);
@@ -505,6 +507,7 @@ static void cleanup_session(gpointer user_data)
        update_session_state(session);
 
        g_slist_free(session->user_allowed_bearers);
+       g_free(session->user_allowed_interface);
 
        free_session(session);
 }
@@ -516,6 +519,7 @@ struct creation_data {
        /* user config */
        enum connman_session_type type;
        GSList *allowed_bearers;
+       char *allowed_interface;
 };
 
 static void cleanup_creation_data(struct creation_data *creation_data)
@@ -527,6 +531,7 @@ static void cleanup_creation_data(struct creation_data 
*creation_data)
                dbus_message_unref(creation_data->pending);
 
        g_slist_free(creation_data->allowed_bearers);
+       g_free(creation_data->allowed_interface);
        g_free(creation_data);
 }
 
@@ -725,6 +730,17 @@ static void apply_policy_on_bearers(GSList 
*policy_bearers, GSList *bearers,
        }
 }
 
+static char * apply_policy_on_interface(const char *policy_interface,
+                               const char *user_interface)
+{
+       if (policy_interface)
+               return g_strdup(policy_interface);
+       else if (user_interface)
+               return g_strdup(user_interface);
+       else
+               return NULL;
+}
+
 const char *connman_session_get_owner(struct connman_session *session)
 {
        return session->owner;
@@ -870,6 +886,17 @@ static void append_notify(DBusMessageIter *dict,
                info_last->config.allowed_bearers = 
info->config.allowed_bearers;
        }
 
+       if (session->append_all ||
+                       info->config.allowed_interface != 
info_last->config.allowed_interface) {
+               char *ifname = info->config.allowed_interface;
+               if (!ifname)
+                       ifname = "";
+               connman_dbus_dict_append_basic(dict, "AllowedInterface",
+                                               DBUS_TYPE_STRING,
+                                               &ifname);
+               info_last->config.allowed_interface = 
info->config.allowed_interface;
+       }
+
        session->append_all = false;
 }
 
@@ -889,7 +916,8 @@ static bool compute_notifiable_changes(struct 
connman_session *session)
                return true;
 
        if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
-                       info->config.type != info_last->config.type)
+                       info->config.type != info_last->config.type ||
+                       info->config.allowed_interface != 
info_last->config.allowed_interface)
                return true;
 
        return false;
@@ -943,6 +971,7 @@ int connman_session_config_update(struct connman_session 
*session)
 {
        struct session_info *info = session->info;
        GSList *allowed_bearers;
+       char *allowed_interface;
        int err;
 
        DBG("session %p", session);
@@ -968,6 +997,10 @@ int connman_session_config_update(struct connman_session 
*session)
                session->user_allowed_bearers,
                &allowed_bearers);
 
+       allowed_interface = apply_policy_on_interface(
+               session->policy_config->allowed_interface,
+               session->user_allowed_interface);
+
        if (session->active)
                set_active_session(session, false);
 
@@ -977,6 +1010,9 @@ int connman_session_config_update(struct connman_session 
*session)
        g_slist_free(info->config.allowed_bearers);
        info->config.allowed_bearers = allowed_bearers;
 
+       g_free(info->config.allowed_interface);
+       info->config.allowed_interface = allowed_interface;
+
        session_activate(session);
 
        info->config.type = apply_policy_on_type(
@@ -1105,6 +1141,26 @@ static DBusMessage *change_session(DBusConnection *conn,
                        info->config.type = apply_policy_on_type(
                                session->policy_config->type,
                                connman_session_parse_connection_type(val));
+               } else if (g_str_equal(name, "AllowedInterface")) {
+                       dbus_message_iter_get_basic(&value, &val);
+                       if (session->active)
+                               set_active_session(session, false);
+
+                       session->active = false;
+                       session_deactivate(session);
+
+                       g_free(session->user_allowed_interface);
+                       /* empty string means allow any interface */
+                       if (0 == g_strcmp0(val, ""))
+                               session->user_allowed_interface = NULL;
+                       else
+                               session->user_allowed_interface = g_strdup(val);
+
+                       info->config.allowed_interface = 
apply_policy_on_interface(
+                               session->policy_config->allowed_interface,
+                               session->user_allowed_interface);
+
+                       session_activate(session);
                } else {
                        goto err;
                }
@@ -1238,11 +1294,18 @@ static int session_policy_config_cb(struct 
connman_session *session,
        session->user_allowed_bearers = creation_data->allowed_bearers;
        creation_data->allowed_bearers = NULL;
 
+       session->user_allowed_interface = creation_data->allowed_interface;
+       creation_data->allowed_interface = NULL;
+
        apply_policy_on_bearers(
                        session->policy_config->allowed_bearers,
                        session->user_allowed_bearers,
                        &info->config.allowed_bearers);
 
+       info->config.allowed_interface = apply_policy_on_interface(
+               session->policy_config->allowed_interface,
+               session->user_allowed_interface);
+
        g_hash_table_replace(session_hash, session->session_path, session);
 
        DBG("add %s", session->session_path);
@@ -1267,6 +1330,7 @@ static int session_policy_config_cb(struct 
connman_session *session,
        info_last->config.priority = info->config.priority;
        info_last->config.roaming_policy = info->config.roaming_policy;
        info_last->config.allowed_bearers = info->config.allowed_bearers;
+       info_last->config.allowed_interface = info->config.allowed_interface;
 
        session->append_all = true;
 
@@ -1354,6 +1418,9 @@ int __connman_session_create(DBusMessage *msg)
                                        
connman_session_parse_connection_type(val);
 
                                user_connection_type = true;
+                       } else if (g_str_equal(key, "AllowedInterface")) {
+                               dbus_message_iter_get_basic(&value, &val);
+                               creation_data->allowed_interface = 
g_strdup(val);
                        } else {
                                err = -EINVAL;
                                goto err;
@@ -1553,6 +1620,7 @@ static bool session_match_service(struct connman_session 
*session,
        enum connman_service_type bearer_type;
        enum connman_service_type service_type;
        GSList *list;
+       char *ifname;
 
        if (policy && policy->allowed)
                return policy->allowed(session, service);
@@ -1560,9 +1628,15 @@ static bool session_match_service(struct connman_session 
*session,
        for (list = session->info->config.allowed_bearers; list; list = 
list->next) {
                bearer_type = GPOINTER_TO_INT(list->data);
                service_type = connman_service_get_type(service);
+               ifname = connman_service_get_interface(service);
 
-               if (bearer_type == service_type)
-                       return true;
+               if (bearer_type == service_type &&
+                       (session->info->config.allowed_interface == NULL ||
+                       0 == g_strcmp0(session->info->config.allowed_interface, 
ifname))) {
+                               g_free(ifname);
+                               return true;
+               }
+               g_free(ifname);
        }
 
        return false;
-- 
2.7.4



------------------------------

Message: 4
Date: Mon, 12 Dec 2016 18:35:06 +0000
From: [email protected]
To: [email protected]
Subject: [PATCH 3/5] client: add session allowed interface config
Message-ID: <[email protected]>

From: Lukasz Nowak <[email protected]>

Add ability to set allowed interface in session config.
Using --ifname without a second argument, clears the
allowed interface, i.e. any interface is allowed.
---
 client/commands.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/client/commands.c b/client/commands.c
index d7f59ef..c41e9b4 100644
--- a/client/commands.c
+++ b/client/commands.c
@@ -1896,6 +1896,7 @@ static int session_config(char *args[], int num,
        int index = 0, res = 0;
        struct config_append append;
        char c;
+       char *ifname;
 
        while (index < num && args[index]) {
                append.opts = &args[index];
@@ -1922,6 +1923,18 @@ static int session_config(char *args[], int num,
                                        DBUS_TYPE_STRING, &args[index + 1]);
                        append.values = 2;
                        break;
+               case 'i':
+                       if (index + 1 < num)
+                               ifname = args[index + 1];
+                       else
+                               ifname = "";
+
+                       res = __connmanctl_dbus_session_change(connection,
+                                       session_path, session_config_return,
+                                       "AllowedInterface", "AllowedInterface",
+                                       DBUS_TYPE_STRING, &ifname);
+                       append.values = 2;
+                       break;
 
                default:
                        res = -EINVAL;
@@ -2209,6 +2222,7 @@ static struct connman_option monitor_options[] = {
 static struct connman_option session_options[] = {
        {"bearers", 'b', "<technology1> [<technology2> [...]]"},
        {"type", 't', "local|internet|any"},
+       {"ifname", 'i', "[<interface_name>]"},
        { NULL, }
 };
 
-- 
2.7.4



------------------------------

Message: 5
Date: Mon, 12 Dec 2016 18:35:07 +0000
From: [email protected]
To: [email protected]
Subject: [PATCH 4/5] session: add source ip rule
Message-ID: <[email protected]>

From: Lukasz Nowak <[email protected]>

Implement an option for a session to enable packet filtering
based on interfce source ip address. This allows an application
to create a session, and direct traffic to a specific network
interface, on which the session is connected.

Applications can use bind before connect on a socket to specify
the source ip address.

This mechanism re-uses the routing table created by the session,
iproute fwmark rule, and adds a new iptables source ip rule.
---
 include/session.h       |  1 +
 src/connman.h           |  3 ++-
 src/firewall-iptables.c | 12 ++++++++-
 src/firewall-nftables.c |  5 ++--
 src/session.c           | 65 ++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/include/session.h b/include/session.h
index e8d7e93..48f1510 100644
--- a/include/session.h
+++ b/include/session.h
@@ -66,6 +66,7 @@ struct connman_session_config {
        bool ecall;
        GSList *allowed_bearers;
        char *allowed_interface;
+       bool source_ip_rule;
 };
 
 typedef int (* connman_session_config_func_t) (struct connman_session *session,
diff --git a/src/connman.h b/src/connman.h
index 577c808..51c3c03 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -1013,7 +1013,8 @@ int __connman_firewall_enable_snat(struct 
firewall_context *ctx,
 int __connman_firewall_disable_snat(struct firewall_context *ctx);
 int __connman_firewall_enable_marking(struct firewall_context *ctx,
                                        enum connman_session_id_type id_type,
-                                       char *id, uint32_t mark);
+                                       char *id, const char *src_ip_address,
+                                       uint32_t mark);
 int __connman_firewall_disable_marking(struct firewall_context *ctx);
 
 int __connman_firewall_init(void);
diff --git a/src/firewall-iptables.c b/src/firewall-iptables.c
index c58efc1..e7a966d 100644
--- a/src/firewall-iptables.c
+++ b/src/firewall-iptables.c
@@ -495,7 +495,8 @@ static void firewall_disable_connmark(void)
 
 int __connman_firewall_enable_marking(struct firewall_context *ctx,
                                        enum connman_session_id_type id_type,
-                                       char *id, uint32_t mark)
+                                       char *id, const char *src_ip_address,
+                                       uint32_t mark)
 {
        int err;
 
@@ -514,11 +515,20 @@ int __connman_firewall_enable_marking(struct 
firewall_context *ctx,
                                "-m owner --gid-owner %s -j MARK --set-mark %d",
                                        id, mark);
                break;
+       case CONNMAN_SESSION_ID_TYPE_UNKNOWN:
+               break;
        case CONNMAN_SESSION_ID_TYPE_LSM:
        default:
                return -EINVAL;
        }
 
+       if (src_ip_address)
+       {
+               firewall_add_rule(ctx, "mangle", "OUTPUT",
+                               "-s %s -j MARK --set-mark %d",
+                                       src_ip_address, mark);
+       }
+
        return firewall_enable_rules(ctx);
 }
 
diff --git a/src/firewall-nftables.c b/src/firewall-nftables.c
index 4d47f20..dc4c934 100644
--- a/src/firewall-nftables.c
+++ b/src/firewall-nftables.c
@@ -800,7 +800,8 @@ err:
 
 int __connman_firewall_enable_marking(struct firewall_context *ctx,
                                        enum connman_session_id_type id_type,
-                                       char *id, uint32_t mark)
+                                       char *id, const char *src_ip_address,
+                                       uint32_t mark)
 {
        struct nftnl_rule *rule;
        struct mnl_socket *nl;
@@ -811,7 +812,7 @@ int __connman_firewall_enable_marking(struct 
firewall_context *ctx,
        DBG("");
 
 
-       if (id_type != CONNMAN_SESSION_ID_TYPE_UID)
+       if (id_type != CONNMAN_SESSION_ID_TYPE_UID || src_ip_address)
                return -ENOTSUP;
 
        pw = getpwnam(id);
diff --git a/src/session.c b/src/session.c
index 2dfd428..28a4f77 100644
--- a/src/session.c
+++ b/src/session.c
@@ -273,8 +273,11 @@ static int init_firewall_session(struct connman_session 
*session)
 {
        struct firewall_context *fw;
        int err;
+       struct connman_ipconfig *ipconfig;
+       const char *addr = NULL;
 
-       if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN)
+       if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN 
&&
+                       !session->info->config.source_ip_rule)
                return 0;
 
        DBG("");
@@ -283,10 +286,15 @@ static int init_firewall_session(struct connman_session 
*session)
        if (!fw)
                return -ENOMEM;
 
+       ipconfig = __connman_service_get_ip4config(session->service);
+       if (session->info->config.source_ip_rule && ipconfig) {
+               addr = __connman_ipconfig_get_local(ipconfig);
+       }
+
        err =__connman_firewall_enable_marking(fw,
                                        session->policy_config->id_type,
                                        session->policy_config->id,
-                                       session->mark);
+                                       addr, session->mark);
        if (err < 0) {
                __connman_firewall_destroy(fw);
                return err;
@@ -313,7 +321,8 @@ static int init_routing_table(struct connman_session 
*session)
 {
        int err;
 
-       if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN)
+       if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN 
&&
+                       !session->info->config.source_ip_rule)
                return 0;
 
        DBG("");
@@ -520,6 +529,7 @@ struct creation_data {
        enum connman_session_type type;
        GSList *allowed_bearers;
        char *allowed_interface;
+       bool source_ip_rule
 };
 
 static void cleanup_creation_data(struct creation_data *creation_data)
@@ -897,6 +907,17 @@ static void append_notify(DBusMessageIter *dict,
                info_last->config.allowed_interface = 
info->config.allowed_interface;
        }
 
+       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)
+                       source_ip_rule = TRUE;
+               connman_dbus_dict_append_basic(dict, "SourceIPRule",
+                                               DBUS_TYPE_BOOLEAN,
+                                               &source_ip_rule);
+               info_last->config.source_ip_rule = info->config.source_ip_rule;
+       }
+
        session->append_all = false;
 }
 
@@ -917,7 +938,8 @@ static bool compute_notifiable_changes(struct 
connman_session *session)
 
        if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
                        info->config.type != info_last->config.type ||
-                       info->config.allowed_interface != 
info_last->config.allowed_interface)
+                       info->config.allowed_interface != 
info_last->config.allowed_interface ||
+                       info->config.source_ip_rule != 
info_last->config.source_ip_rule)
                return true;
 
        return false;
@@ -1165,6 +1187,27 @@ static DBusMessage *change_session(DBusConnection *conn,
                        goto err;
                }
                break;
+       case DBUS_TYPE_BOOLEAN:
+               if (g_str_equal(name, "SourceIPRule")) {
+                       dbus_bool_t source_ip_rule;
+                       dbus_message_iter_get_basic(&value, &source_ip_rule);
+
+                       cleanup_firewall_session(session);
+                       cleanup_routing_table(session);
+
+                       info->config.source_ip_rule = source_ip_rule;
+                       update_session_state(session);
+
+                       init_routing_table(session);
+                       err = init_firewall_session(session);
+                       if (err < 0) {
+                               connman_session_destroy(session);
+                               goto err;
+                       }
+               } else {
+                       goto err;
+               }
+               break;
        default:
                goto err;
        }
@@ -1425,7 +1468,21 @@ int __connman_session_create(DBusMessage *msg)
                                err = -EINVAL;
                                goto err;
                        }
+                       break;
+               case DBUS_TYPE_BOOLEAN:
+                       if (g_str_equal(key, "SourceIPRule")) {
+                               dbus_bool_t source_ip_rule;
+                               dbus_message_iter_get_basic(&value, 
&source_ip_rule);
+                               creation_data->source_ip_rule = source_ip_rule;
+                       } else {
+                               err = -EINVAL;
+                               goto err;
+                       }
+                       break;
+               default:
+                       goto err;
                }
+
                dbus_message_iter_next(&array);
        }
 
-- 
2.7.4



------------------------------

Subject: Digest Footer

_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman


------------------------------

End of connman Digest, Vol 14, Issue 16
***************************************

Reply via email to