From: "fu.lin" fu.lin10@huawei.com
Conflict:NA Reference:https://gitee.com/src-openeuler/criu/pulls/21 Signed-off-by: fu.lin fu.lin10@huawei.com --- criu/include/nftables.h | 2 + criu/nftables.c | 112 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+)
diff --git a/criu/include/nftables.h b/criu/include/nftables.h index 3b51a3d..e462919 100644 --- a/criu/include/nftables.h +++ b/criu/include/nftables.h @@ -162,5 +162,7 @@ struct nf_conn_params {
struct inet_sk_desc; int nft_connection_switch(struct inet_sk_desc *sk, bool lock, pid_t tree_id); +int nft_lock(void); +int nft_unlock(void);
#endif /* __CR_NFTABLES_H__ */ diff --git a/criu/nftables.c b/criu/nftables.c index 57774e6..817f157 100644 --- a/criu/nftables.c +++ b/criu/nftables.c @@ -821,3 +821,115 @@ int nft_connection_switch(struct inet_sk_desc *sk, bool lock, pid_t tree_id)
return mnl_sendmsg(nf_connection_switch_raw, ¶m); } + +static int nft_ns_rule_internal(uint8_t family, struct mnl_params *mnl_params, + struct nft_rule_params *params, bool create) +{ + struct nftnl_rule *rule; + + rule = setup_rule(family, TABLE_NAME, params, create, true); + if (rule == NULL) + return -1; + + if (create) { + construct_rule_batch(mnl_params->batch, NFT_MSG_NEWRULE, family, + NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK, + mnl_params->seq++, rule); + } else { + construct_rule_batch(mnl_params->batch, NFT_MSG_DELRULE, family, + 0, mnl_params->seq++, rule); + } + + return 0; +} + +static int nft_ns_rule_raw(struct mnl_params *mnl_params, struct mnl_cb_params *args, + struct nft_rule_params *params) +{ + params->chain_name = INPUT_CHAIN_NAME; + if (nft_ns_rule_internal(NFPROTO_INET, mnl_params, params, args->create) < 0) { + pr_err("%s: create nft input rule failed!\n", __func__); + return -1; + } + + params->chain_name = OUTPUT_CHAIN_NAME; + if (nft_ns_rule_internal(NFPROTO_INET, mnl_params, params, args->create) < 0) { + pr_err("%s: create nft output rule failed!\n", __func__); + return -1; + } + + return 0; +} + +static int nft_ns_rule(struct mnl_params *mnl_params, void *args) +{ + struct nft_rule_params params = { 0 }; + + params.mark = 0; + params.mark_op = NFT_CMP_EQ; + params.stmt = NF_DROP; + if (nft_ns_rule_raw(mnl_params, args, ¶ms) < 0) + return -1; + + params.mark = SOCCR_MARK; + + params.stmt = NF_ACCEPT; + if (nft_ns_rule_raw(mnl_params, args, ¶ms) < 0) + return -1; + + return 0; +} + +static int nft_ns_rule_common(struct mnl_params *mnl_params, bool create) +{ + struct mnl_cb_params params = { + .create = create, + }; + int result = 0; + + if (create && + (mnl_batch_send_and_recv(mnl_params, nft_ns_rule, ¶ms, &result) < 0 + && (result != 0 && result != EEXIST))) { + pr_err("%s: crete ns rule failed!\n", __func__); + return -1; + } else if (!create && + (mnl_batch_send_and_recv(mnl_params, nft_ns_rule, ¶ms, NULL) < 0)) { + pr_err("%s: delete ns rule failed!\n", __func__); + return -1; + } + + return 0; +} + +static int network_lock_internal(struct mnl_params *params, + batch_func_t _, void *args) +{ + if (nft_table_prepare(params) < 0) + return -1; + + if (nft_chain_prepare(params) < 0) + return -1; + + if (nft_ns_rule_common(params, true) < 0) + return -1; + + return 0; +} + +int nft_lock(void) +{ + return mnl_common(network_lock_internal, NULL, NULL); +} + +static int network_unlock_internal(struct mnl_params *params, batch_func_t _, + void *args) +{ + if (nft_ns_rule_common(params, false) < 0) + return -1; + return 0; +} + +int nft_unlock(void) +{ + return mnl_common(network_unlock_internal, NULL, NULL); +}