#include #include #include #include #include #include #include #include "chaining_policy.h" enum traffic_type { TRAFFIC_TYPE_NONE = 0, TRAFFIC_TYPE_RAW = 1, TRAFFIC_TYPE_DECRYPTED = 2, }; struct chaining_param { uint64_t rule_id; int ref_cnt; enum traffic_type type; }; struct chaining_policy_enforcer { struct maat *maat; int table_id; void *logger; }; static void chaining_param_new_cb(const char *table_name, int table_id, const char *key, const char *table_line, void **ad, long argl, void *argp) { cJSON *json = NULL; cJSON *item = NULL; cJSON *element = NULL; size_t user_region_offset = 0; size_t user_region_len = 0; struct chaining_param *param = NULL; struct chaining_policy_enforcer *enforcer = (struct chaining_policy_enforcer *)argp; if (maat_helper_read_column(table_line, 7, &user_region_offset, &user_region_len) < 0) { TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid user region) %s", table_line); return; } char *json_str = (char *)calloc(user_region_len + 1, sizeof(char)); memcpy(json_str, table_line + user_region_offset, user_region_len); json = cJSON_Parse(json_str); if (json == NULL) { TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid json format) %s", table_line); goto error_out; } param = (struct chaining_param *)calloc(1, sizeof(struct chaining_param)); param->rule_id = atoll(key); param->ref_cnt = 1; item = cJSON_GetObjectItem(json, "targeted_traffic"); if (!item || !cJSON_IsString(item)) { TFE_LOG_ERROR(enforcer->logger, "unexpected chaining rule: (invalid targeted_traffic param) %s", 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, "unexpected chaining rule: (invalid targeted_traffic param) %s", table_line); goto error_out; } *ad = param; TFE_LOG_INFO(enforcer->logger, "Add chaining rule: %lu", param->rule_id); cJSON_Delete(json); free(json_str); return; error_out: if (json) { cJSON_Delete(json); json = NULL; } if (json_str) { free(json_str); json_str = NULL; } if (param) { free(param); param = NULL; } } static void chaining_param_free_cb(int table_id, void **ad, long argl, void *argp) { 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)) { TFE_LOG_INFO(enforcer->logger, "Del chaining policy %lu", param->rule_id); free(param); *ad = NULL; } } static void chaining_param_free(struct chaining_param *param) { chaining_param_free_cb(0, (void **)¶m, 0, NULL); } static void chaining_param_dup_cb(int table_id, 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 = (struct maat *)tfe_bussiness_resouce_get(STATIC_MAAT); enforcer->logger = logger; enforcer->table_id = maat_get_table_id(enforcer->maat, "SERVICE_CHAINING_COMPILE"); if (enforcer->table_id < 0) { TFE_LOG_ERROR(enforcer->logger, "failed at register table of SERVICE_CHAINING_COMPILE, ret = %d", enforcer->table_id); goto error_out; } ret = maat_plugin_table_ex_schema_register(enforcer->maat, "SERVICE_CHAINING_COMPILE", 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_COMPILE, 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, uint64_t rule_id) { uint16_t size = 0; char rule_id_str[16] = {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; } snprintf(rule_id_str, sizeof(rule_id_str), "%lu", rule_id); struct chaining_param *param = (struct chaining_param *)maat_plugin_table_get_ex_data(enforcer->maat, enforcer->table_id, rule_id_str); if (param == NULL) { TFE_LOG_INFO(enforcer->logger, "Failed to get chaining parameter of policy %lu.", 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); }