201 lines
5.8 KiB
C++
201 lines
5.8 KiB
C++
#include <assert.h>
|
|
#include <tfe_cmsg.h>
|
|
#include <tfe_utils.h>
|
|
#include <tfe_stream.h>
|
|
#include <tfe_resource.h>
|
|
#include <cjson/cJSON.h>
|
|
#include <MESA/maat.h>
|
|
|
|
#include "chaining_policy.h"
|
|
|
|
enum traffic_type
|
|
{
|
|
TRAFFIC_TYPE_NONE = 0,
|
|
TRAFFIC_TYPE_RAW = 1,
|
|
TRAFFIC_TYPE_DECRYPTED = 2,
|
|
};
|
|
|
|
struct chaining_param
|
|
{
|
|
uuid_t rule_id;
|
|
int ref_cnt;
|
|
enum traffic_type type;
|
|
};
|
|
|
|
struct chaining_policy_enforcer
|
|
{
|
|
struct maat *maat;
|
|
char table_name[32];
|
|
void *logger;
|
|
};
|
|
|
|
static void chaining_param_new_cb(const char *table_name, const char *key, const char *table_line, void **ad, long argl, void *argp)
|
|
{
|
|
cJSON *json_root = NULL;
|
|
cJSON *json_subroot = NULL;
|
|
cJSON *item = NULL;
|
|
struct chaining_param *param = NULL;
|
|
struct chaining_policy_enforcer *enforcer = (struct chaining_policy_enforcer *)argp;
|
|
|
|
char *json_str = strdup(table_line);
|
|
json_root = cJSON_Parse(json_str);
|
|
if (unlikely(!json_root))
|
|
{
|
|
TFE_LOG_ERROR(enforcer->logger, "Invalid chaining profile: %s", table_line);
|
|
goto error_out;
|
|
}
|
|
json_subroot = cJSON_GetObjectItem(json_root, "action_parameter");
|
|
if (unlikely(!json_subroot || !cJSON_IsObject(json_subroot)))
|
|
{
|
|
TFE_LOG_ERROR(enforcer->logger, "Invalid chaining rule: %s (invalid action_parameter format) %s.", key, table_line);
|
|
goto error_out;
|
|
}
|
|
|
|
param = (struct chaining_param *)calloc(1, sizeof(struct chaining_param));
|
|
param->ref_cnt = 1;
|
|
uuid_parse(key, param->rule_id);
|
|
|
|
item = cJSON_GetObjectItem(json_subroot, "targeted_traffic");
|
|
if (!item || !cJSON_IsString(item))
|
|
{
|
|
TFE_LOG_ERROR(enforcer->logger, "Invalid chaining rule: %s (invalid targeted_traffic format) %s.", key, table_line);
|
|
goto error_out;
|
|
}
|
|
if (strcasecmp(item->valuestring, "raw") == 0)
|
|
{
|
|
param->type = TRAFFIC_TYPE_RAW;
|
|
}
|
|
else if (strcasecmp(item->valuestring, "decrypted") == 0)
|
|
{
|
|
param->type = TRAFFIC_TYPE_DECRYPTED;
|
|
}
|
|
else
|
|
{
|
|
TFE_LOG_ERROR(enforcer->logger, "Invalid chaining rule: %s (invalid targeted_traffic format) %s", key, table_line);
|
|
goto error_out;
|
|
}
|
|
|
|
*ad = param;
|
|
TFE_LOG_INFO(enforcer->logger, "Add chaining rule: %s", key);
|
|
cJSON_Delete(json_root);
|
|
free(json_str);
|
|
return;
|
|
|
|
error_out:
|
|
if (json_root)
|
|
{
|
|
cJSON_Delete(json_root);
|
|
json_root = NULL;
|
|
}
|
|
if (json_str)
|
|
{
|
|
free(json_str);
|
|
json_str = NULL;
|
|
}
|
|
if (param)
|
|
{
|
|
free(param);
|
|
param = NULL;
|
|
}
|
|
}
|
|
|
|
static void chaining_param_free_cb(const char *table_name, void **ad, long argl, void *argp)
|
|
{
|
|
char str_rule_id[UUID_STRING_SIZE] = {0};
|
|
struct chaining_policy_enforcer *enforcer = (struct chaining_policy_enforcer *)argp;
|
|
struct chaining_param *param = (struct chaining_param *)*ad;
|
|
if (param == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((__sync_sub_and_fetch(¶m->ref_cnt, 1) == 0))
|
|
{
|
|
uuid_unparse(param->rule_id, str_rule_id);
|
|
TFE_LOG_INFO(enforcer->logger, "Del chaining policy %s", str_rule_id);
|
|
free(param);
|
|
*ad = NULL;
|
|
}
|
|
}
|
|
|
|
static void chaining_param_free(struct chaining_param *param)
|
|
{
|
|
chaining_param_free_cb(NULL, (void **)¶m, 0, NULL);
|
|
}
|
|
|
|
static void chaining_param_dup_cb(const char *table_name, void **to, void **from, long argl, void *argp)
|
|
{
|
|
struct chaining_param *param = (struct chaining_param *)*from;
|
|
if (param)
|
|
{
|
|
__sync_add_and_fetch(&(param->ref_cnt), 1);
|
|
*to = param;
|
|
}
|
|
else
|
|
{
|
|
*to = NULL;
|
|
}
|
|
}
|
|
|
|
struct chaining_policy_enforcer *chaining_policy_enforcer_create(void *logger)
|
|
{
|
|
int ret = 0;
|
|
struct chaining_policy_enforcer *enforcer = ALLOC(struct chaining_policy_enforcer, 1);
|
|
enforcer->maat = tfe_get_maat_handle();
|
|
enforcer->logger = logger;
|
|
snprintf(enforcer->table_name, sizeof(enforcer->table_name), "SERVICE_CHAINING_RULE");
|
|
|
|
ret = maat_plugin_table_ex_schema_register(enforcer->maat, enforcer->table_name,
|
|
chaining_param_new_cb,
|
|
chaining_param_free_cb,
|
|
chaining_param_dup_cb,
|
|
0, enforcer);
|
|
if (ret < 0)
|
|
{
|
|
TFE_LOG_ERROR(enforcer->logger, "failed at register callback of SERVICE_CHAINING_RULE, ret = %d", ret);
|
|
goto error_out;
|
|
}
|
|
return enforcer;
|
|
|
|
error_out:
|
|
chaining_policy_enforcer_destory(enforcer);
|
|
return NULL;
|
|
}
|
|
|
|
void chaining_policy_enforcer_destory(struct chaining_policy_enforcer *enforcer)
|
|
{
|
|
if (enforcer)
|
|
{
|
|
free(enforcer);
|
|
enforcer = NULL;
|
|
}
|
|
}
|
|
|
|
void chaining_policy_enforce(struct chaining_policy_enforcer *enforcer, struct tfe_cmsg *cmsg, uuid_t *rule_id)
|
|
{
|
|
uint16_t size = 0;
|
|
char str_rule_id[UUID_STRING_SIZE] = {0};
|
|
uint8_t enalbe_decrypted_traffic_steering = 0;
|
|
|
|
tfe_cmsg_get_value(cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enalbe_decrypted_traffic_steering, sizeof(enalbe_decrypted_traffic_steering), &size);
|
|
if (enalbe_decrypted_traffic_steering == 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uuid_unparse(*rule_id, str_rule_id);
|
|
struct chaining_param *param = (struct chaining_param *)maat_plugin_table_get_ex_data(enforcer->maat, enforcer->table_name, (const char *)str_rule_id, strlen(str_rule_id));
|
|
if (param == NULL)
|
|
{
|
|
TFE_LOG_INFO(enforcer->logger, "Failed to get chaining parameter of policy %s.", str_rule_id);
|
|
return;
|
|
}
|
|
|
|
if (param->type == TRAFFIC_TYPE_DECRYPTED)
|
|
{
|
|
enalbe_decrypted_traffic_steering = 1;
|
|
}
|
|
|
|
tfe_cmsg_set(cmsg, TFE_CMSG_TCP_DECRYPTED_TRAFFIC_STEERING, (unsigned char *)&enalbe_decrypted_traffic_steering, sizeof(enalbe_decrypted_traffic_steering));
|
|
chaining_param_free(param);
|
|
} |