diff options
author | Thomas Haller <thaller@redhat.com> | 2020-10-27 09:37:43 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-10-27 17:07:57 +0100 |
commit | 0c2d5fc9722d0a713569bbe969ffcbd821ea5848 (patch) | |
tree | e13c85c93be47b19520225ef079c05aa8cea9349 | |
parent | 0438820805386268d43e25a7d76824ef931a98ad (diff) | |
download | NetworkManager-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.c | 124 | ||||
-rw-r--r-- | src/NetworkManagerUtils.h | 22 |
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__ */ |