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 v5 3/8] client: Add session AllowedInterface config
(Lukasz Nowak)
2. [PATCH v5 4/8] firewall: Add fwmark based on source ip
address (Lukasz Nowak)
3. [PATCH v5 5/8] session: Add source ip rule (Lukasz Nowak)
4. [PATCH v5 6/8] session: Remove old session rules and routes
after a config change (Lukasz Nowak)
5. [PATCH v5 7/8] client: Add session source ip rule (Lukasz Nowak)
----------------------------------------------------------------------
Message: 1
Date: Fri, 3 Feb 2017 10:43:29 +0000
From: Lukasz Nowak <[email protected]>
To: [email protected]
Subject: [PATCH v5 3/8] client: Add session AllowedInterface config
Message-ID: <[email protected]>
From: Lukasz Nowak <[email protected]>
Add ability to set the AllowedInterface field in session
config. Using --ifname without a second argument, clears the
allowed interface, i.e. any interface is allowed.
Using "*" also allows any interface.
---
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: 2
Date: Fri, 3 Feb 2017 10:43:30 +0000
From: Lukasz Nowak <[email protected]>
To: [email protected]
Subject: [PATCH v5 4/8] firewall: Add fwmark based on source ip
address
Message-ID: <[email protected]>
From: Lukasz Nowak <[email protected]>
Add an option to enable insertion of firewall MARK into packets,
based on their source ip address. This will be used by the
multi-interface routing functionality of sessions.
---
src/connman.h | 3 +-
src/firewall-iptables.c | 11 ++++-
src/firewall-nftables.c | 108 +++++++++++++++++++++++++++++++++++++++++-------
src/session.c | 1 +
4 files changed, 105 insertions(+), 18 deletions(-)
diff --git a/src/connman.h b/src/connman.h
index 577c808..ce4d82e 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,
+ 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..45943a8 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,
+ uint32_t mark)
{
int err;
@@ -514,11 +515,19 @@ 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) {
+ firewall_add_rule(ctx, "mangle", "OUTPUT",
+ "-s %s -j MARK --set-mark %d",
+ src_ip, mark);
+ }
+
return firewall_enable_rules(ctx);
}
diff --git a/src/firewall-nftables.c b/src/firewall-nftables.c
index 4d47f20..2503ee2 100644
--- a/src/firewall-nftables.c
+++ b/src/firewall-nftables.c
@@ -798,9 +798,70 @@ err:
return -ENOMEM;
}
+static int build_rule_src_ip(const char *src_ip, uint32_t mark, struct
nftnl_rule **res)
+{
+ struct nftnl_rule *rule;
+ struct nftnl_expr *expr;
+ int err;
+ in_addr_t s_addr;
+
+ /*
+ * # nft --debug netlink add rule connman route-output \
+ * ip saddr 192.168.10.31 mark set 1234
+ *
+ * ip connman route-output
+ * [ payload load 4b @ network header + 12 => reg 1 ]
+ * [ cmp eq reg 1 0x1f0aa8c0 ]
+ * [ immediate reg 1 0x000004d2 ]
+ * [ meta set mark with reg 1 ]
+ */
+
+ rule = nftnl_rule_alloc();
+ if (!rule)
+ return -ENOMEM;
+
+ nftnl_rule_set(rule, NFTNL_RULE_TABLE, CONNMAN_TABLE);
+ nftnl_rule_set(rule, NFTNL_RULE_CHAIN, CONNMAN_CHAIN_ROUTE_OUTPUT);
+
+ /* family ipv4 */
+ nftnl_rule_set_u32(rule, NFTNL_RULE_FAMILY, NFPROTO_IPV4);
+
+ /* source IP */
+ err = add_payload(rule, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1,
+ offsetof(struct iphdr, saddr), sizeof(struct in_addr));
+ if (err < 0)
+ goto err;
+
+ s_addr = inet_addr(src_ip);
+ err = add_cmp(rule, NFT_REG_1, NFT_CMP_EQ, &s_addr, sizeof(s_addr));
+ if (err < 0)
+ goto err;
+
+ expr = nftnl_expr_alloc("immediate");
+ if (!expr)
+ goto err;
+ nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG_1);
+ nftnl_expr_set(expr, NFTNL_EXPR_IMM_DATA, &mark, sizeof(mark));
+ nftnl_rule_add_expr(rule, expr);
+
+ expr = nftnl_expr_alloc("meta");
+ if (!expr)
+ goto err;
+ nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY, NFT_META_MARK);
+ nftnl_expr_set_u32(expr, NFTNL_EXPR_META_SREG, NFT_REG_1);
+ nftnl_rule_add_expr(rule, expr);
+
+ *res = rule;
+ return 0;
+
+err:
+ return -ENOMEM;
+}
+
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,
+ uint32_t mark)
{
struct nftnl_rule *rule;
struct mnl_socket *nl;
@@ -810,29 +871,44 @@ 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) {
+ pw = getpwnam(id);
+ if (!pw)
+ return -EINVAL;
+ uid = pw->pw_uid;
+ }
+ else if (!src_ip)
return -ENOTSUP;
- pw = getpwnam(id);
- if (!pw)
- return -EINVAL;
- uid = pw->pw_uid;
-
err = socket_open_and_bind(&nl);
if (err < 0)
return err;
- err = build_rule_marking(uid, mark, &rule);
- if (err < 0)
- goto out;
+ if (id_type == CONNMAN_SESSION_ID_TYPE_UID) {
+ err = build_rule_marking(uid, mark, &rule);
+ if (err < 0)
+ goto out;
- ctx->rule.chain = CONNMAN_CHAIN_ROUTE_OUTPUT;
- err = rule_cmd(nl, rule, NFT_MSG_NEWRULE, NFPROTO_IPV4,
- NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK,
- CALLBACK_RETURN_HANDLE, &ctx->rule.handle);
+ ctx->rule.chain = CONNMAN_CHAIN_ROUTE_OUTPUT;
+ err = rule_cmd(nl, rule, NFT_MSG_NEWRULE, NFPROTO_IPV4,
+ NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK,
+ CALLBACK_RETURN_HANDLE, &ctx->rule.handle);
- nftnl_rule_free(rule);
+ nftnl_rule_free(rule);
+ }
+
+ if (src_ip) {
+ err = build_rule_src_ip(src_ip, mark, &rule);
+ if (err < 0)
+ goto out;
+
+ ctx->rule.chain = CONNMAN_CHAIN_ROUTE_OUTPUT;
+ err = rule_cmd(nl, rule, NFT_MSG_NEWRULE, NFPROTO_IPV4,
+ NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK,
+ CALLBACK_RETURN_HANDLE, &ctx->rule.handle);
+
+ nftnl_rule_free(rule);
+ }
out:
mnl_socket_close(nl);
return err;
diff --git a/src/session.c b/src/session.c
index 24b39e0..dfa054c 100644
--- a/src/session.c
+++ b/src/session.c
@@ -286,6 +286,7 @@ static int init_firewall_session(struct connman_session
*session)
err =__connman_firewall_enable_marking(fw,
session->policy_config->id_type,
session->policy_config->id,
+ NULL,
session->mark);
if (err < 0) {
__connman_firewall_destroy(fw);
--
2.7.4
------------------------------
Message: 3
Date: Fri, 3 Feb 2017 10:43:31 +0000
From: Lukasz Nowak <[email protected]>
To: [email protected]
Subject: [PATCH v5 5/8] 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/session.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 72 insertions(+), 6 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/session.c b/src/session.c
index dfa054c..dcbb59e 100644
--- a/src/session.c
+++ b/src/session.c
@@ -273,21 +273,33 @@ static int init_firewall_session(struct connman_session
*session)
{
struct firewall_context *fw;
int err;
+ struct connman_ipconfig *ipconfig = NULL;
+ 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("");
+ if (session->info->config.source_ip_rule) {
+ ipconfig = __connman_service_get_ip4config(session->service);
+ if (session->policy_config->id_type ==
CONNMAN_SESSION_ID_TYPE_UNKNOWN && !ipconfig)
+ return 0;
+ }
+
fw = __connman_firewall_create();
if (!fw)
return -ENOMEM;
+ 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,
- NULL,
- session->mark);
+ addr, session->mark);
if (err < 0) {
__connman_firewall_destroy(fw);
return err;
@@ -314,7 +326,11 @@ 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;
+
+ if (!session->service)
return 0;
DBG("");
@@ -432,9 +448,16 @@ static void cleanup_routing_table(struct connman_session
*session)
del_default_route(session);
}
+static void update_firewall(struct connman_session *session)
+{
+ cleanup_firewall_session(session);
+ init_firewall_session(session);
+}
+
static void update_routing_table(struct connman_session *session)
{
- del_default_route(session);
+ cleanup_routing_table(session);
+ init_routing_table(session);
add_default_route(session);
}
@@ -521,6 +544,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)
@@ -898,6 +922,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;
}
@@ -918,7 +953,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;
@@ -1166,6 +1202,17 @@ 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);
+
+ info->config.source_ip_rule = source_ip_rule;
+ update_session_state(session);
+ } else {
+ goto err;
+ }
+ break;
default:
goto err;
}
@@ -1267,6 +1314,7 @@ static int session_policy_config_cb(struct
connman_session *session,
goto err;
session->policy_config = config;
+ session->info->config.source_ip_rule = creation_data->source_ip_rule;
session->mark = session_mark++;
session->index = -1;
@@ -1332,6 +1380,7 @@ static int session_policy_config_cb(struct
connman_session *session,
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;
+ info_last->config.source_ip_rule = info->config.source_ip_rule;
session->append_all = true;
@@ -1426,7 +1475,22 @@ 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:
+ err = -EINVAL;
+ goto err;
}
+
dbus_message_iter_next(&array);
}
@@ -1610,6 +1674,7 @@ static void update_session_state(struct connman_session
*session)
DBG("session %p state %s", session, state2string(state));
+ update_firewall(session);
update_routing_table(session);
update_nat_rules(session);
session_notify(session);
--
2.7.4
------------------------------
Message: 4
Date: Fri, 3 Feb 2017 10:43:32 +0000
From: Lukasz Nowak <[email protected]>
To: [email protected]
Subject: [PATCH v5 6/8] session: Remove old session rules and routes
after a config change
Message-ID: <[email protected]>
From: Lukasz Nowak <[email protected]>
When a session disconnects due to a config change:
- AllowedBearers does not contain a connected service
- AllowedInterface is not in a connected service
several objects created by the session's previous config do not
get removed:
- iproute2 fwmark/table rules
- firewall fwmark rules
- session's routing table
This change cleans up state of the session correctly on each config change.
---
src/session.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/session.c b/src/session.c
index dcbb59e..0553327 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1158,6 +1158,7 @@ static DBusMessage *change_session(DBusConnection *conn,
session->active = false;
session_deactivate(session);
+ update_session_state(session);
g_slist_free(info->config.allowed_bearers);
session->user_allowed_bearers = allowed_bearers;
@@ -1185,6 +1186,7 @@ static DBusMessage *change_session(DBusConnection *conn,
session->active = false;
session_deactivate(session);
+ update_session_state(session);
g_free(session->user_allowed_interface);
/* empty string means allow any interface */
--
2.7.4
------------------------------
Message: 5
Date: Fri, 3 Feb 2017 10:43:33 +0000
From: Lukasz Nowak <[email protected]>
To: [email protected]
Subject: [PATCH v5 7/8] client: Add session source ip rule
Message-ID: <[email protected]>
From: Lukasz Nowak <[email protected]>
Add a session config field to enable/disable creation of the
source ip rule in iptables by a session.
---
client/commands.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/client/commands.c b/client/commands.c
index c41e9b4..583095b 100644
--- a/client/commands.c
+++ b/client/commands.c
@@ -1897,6 +1897,7 @@ static int session_config(char *args[], int num,
struct config_append append;
char c;
char *ifname;
+ dbus_bool_t source_ip_rule;
while (index < num && args[index]) {
append.opts = &args[index];
@@ -1935,6 +1936,29 @@ static int session_config(char *args[], int num,
DBUS_TYPE_STRING, &ifname);
append.values = 2;
break;
+ case 's':
+ if (!args[index + 1]) {
+ res = -EINVAL;
+ break;
+ }
+ switch (parse_boolean(args[index + 1])) {
+ case 1:
+ source_ip_rule = TRUE;
+ break;
+ case 0:
+ source_ip_rule = FALSE;
+ break;
+ default:
+ res = -EINVAL;
+ break;
+ }
+
+ res = __connmanctl_dbus_session_change(connection,
+ session_path, session_config_return,
+ "SourceIPRule", "SourceIPRule",
+ DBUS_TYPE_BOOLEAN, &source_ip_rule);
+ append.values = 2;
+ break;
default:
res = -EINVAL;
@@ -2223,6 +2247,7 @@ static struct connman_option session_options[] = {
{"bearers", 'b', "<technology1> [<technology2> [...]]"},
{"type", 't', "local|internet|any"},
{"ifname", 'i', "[<interface_name>]"},
+ {"srciprule", 's', "yes|no"},
{ NULL, }
};
--
2.7.4
------------------------------
Subject: Digest Footer
_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman
------------------------------
End of connman Digest, Vol 16, Issue 5
**************************************