summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-10-27 09:37:43 +0100
committerThomas Haller <thaller@redhat.com>2020-10-27 17:07:57 +0100
commit0c2d5fc9722d0a713569bbe969ffcbd821ea5848 (patch)
treee13c85c93be47b19520225ef079c05aa8cea9349
parent0438820805386268d43e25a7d76824ef931a98ad (diff)
downloadNetworkManager-0c2d5fc9722d0a713569bbe969ffcbd821ea5848.tar.gz
core: add NMUtilsShareRules API for handling IP tables rules
Currently, shared rules are tracked by NMActRequest. Add a small type for tracking the shared rules.
-rw-r--r--src/NetworkManagerUtils.c124
-rw-r--r--src/NetworkManagerUtils.h22
2 files changed, 146 insertions, 0 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 4739e9dd15..a9d5d2ff91 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -1636,3 +1636,127 @@ nm_utils_ip_routes_to_dbus(int addr_family,
NM_SET_OUT(out_route_data, g_variant_builder_end(&builder_data));
NM_SET_OUT(out_routes, g_variant_builder_end(&builder_legacy));
}
+
+/*****************************************************************************/
+
+typedef struct {
+ char *table;
+ char *rule;
+} ShareRule;
+
+struct _NMUtilsShareRules {
+ GArray *rules;
+};
+
+static void
+_share_rule_clear(gpointer data)
+{
+ ShareRule *rule = data;
+
+ g_free(rule->table);
+ g_free(rule->rule);
+}
+
+NMUtilsShareRules *
+nm_utils_share_rules_new(void)
+{
+ NMUtilsShareRules *self;
+
+ self = g_slice_new(NMUtilsShareRules);
+ *self = (NMUtilsShareRules){
+ .rules = g_array_sized_new(FALSE, FALSE, sizeof(ShareRule), 10),
+ };
+
+ g_array_set_clear_func(self->rules, _share_rule_clear);
+ return self;
+}
+
+void
+nm_utils_share_rules_free(NMUtilsShareRules *self)
+{
+ if (!self)
+ return;
+
+ g_array_unref(self->rules);
+ nm_g_slice_free(self);
+}
+
+void
+nm_utils_share_rules_add_rule_take(NMUtilsShareRules *self, const char *table, char *rule_take)
+{
+ ShareRule *rule;
+
+ g_return_if_fail(self);
+ g_return_if_fail(table);
+ g_return_if_fail(rule_take);
+
+ rule = nm_g_array_append_new(self->rules, ShareRule);
+ *rule = (ShareRule){
+ .table = g_strdup(table),
+ .rule = g_steal_pointer(&rule_take),
+ };
+}
+
+void
+nm_utils_share_rules_apply(NMUtilsShareRules *self, gboolean shared)
+{
+ guint i;
+
+ g_return_if_fail(self);
+
+ if (self->rules->len == 0)
+ return;
+
+ /* depending on whether we share or unshare, we add/remote the rules
+ * in opposite order. */
+ if (shared)
+ i = self->rules->len - 1;
+ else
+ i = 0;
+
+ for (;;) {
+ gs_free_error GError *error = NULL;
+ ShareRule * rule;
+ gs_free const char ** argv = NULL;
+ gs_free char * cmd = NULL;
+ int status;
+
+ rule = &g_array_index(self->rules, ShareRule, i);
+
+ cmd = g_strdup_printf("%s --table %s %s %s",
+ IPTABLES_PATH,
+ rule->table,
+ shared ? "--insert" : "--delete",
+ rule->rule);
+ argv = nm_utils_strsplit_set(cmd, " ");
+
+ nm_log_info(LOGD_SHARING, "Executing: %s", cmd);
+ if (!g_spawn_sync("/",
+ (char **) argv,
+ (char **) NM_PTRARRAY_EMPTY(const char *),
+ G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &status,
+ &error)) {
+ nm_log_warn(LOGD_SHARING, "Error executing command: %s", error->message);
+ goto next;
+ }
+ if (WEXITSTATUS(status)) {
+ nm_log_warn(LOGD_SHARING, "** Command returned exit status %d.", WEXITSTATUS(status));
+ }
+
+next:
+ if (shared) {
+ if (i == 0)
+ break;
+ i--;
+ } else {
+ i++;
+ if (i >= self->rules->len)
+ break;
+ }
+ }
+}
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index e961c785a1..adf3645014 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -224,4 +224,26 @@ NM_AUTO_DEFINE_FCN(NMDhcpLease *, _nm_auto_unref_dhcplease, nm_dhcp_lease_unref)
/*****************************************************************************/
+typedef struct _NMUtilsShareRules NMUtilsShareRules;
+
+NMUtilsShareRules *nm_utils_share_rules_new(void);
+
+void nm_utils_share_rules_free(NMUtilsShareRules *self);
+
+void
+nm_utils_share_rules_add_rule_take(NMUtilsShareRules *self, const char *table, char *rule_take);
+
+static inline void
+nm_utils_share_rules_add_rule(NMUtilsShareRules *self, const char *table, const char *rule)
+{
+ nm_utils_share_rules_add_rule_take(self, table, g_strdup(rule));
+}
+
+#define nm_utils_share_rules_add_rule_v(self, table, ...) \
+ nm_utils_share_rules_add_rule_take((self), (table), g_strdup_printf(__VA_ARGS__))
+
+void nm_utils_share_rules_apply(NMUtilsShareRules *self, gboolean shared);
+
+/*****************************************************************************/
+
#endif /* __NETWORKMANAGER_UTILS_H__ */