diff --git a/plugin/business/pangu-http/pangu_http.cpp b/plugin/business/pangu-http/pangu_http.cpp index 076a075..b5be075 100644 --- a/plugin/business/pangu-http/pangu_http.cpp +++ b/plugin/business/pangu-http/pangu_http.cpp @@ -1,24 +1,61 @@ -enum HttpActionType -{ - kActionBypass = 0x00, - kActionMonitor = 0x01, - kActionBlock = 0x10, - kActionDrop = 0x20, - kActionRedirect = 0x30, - kActionRateLimit = 0x40, - kActionReplace = 0x50, - kActionWhiteList = 0x80, - kActionMax = 0xff -}; +#include +#include +#include -Maat_feather_t init_maat(const char* profile, const char* section,int max_thread, void* logger) +#include +#include +#include +#include + +#include +#include +#include +#include +#define MAX_SCAN_RESULT 16 +#define MAX_EDIT_ZONE_NUM 64 +enum pangu_action//Bigger action number is prior. +{ + PG_ACTION_NONE = 0x00, + PG_ACTION_MONIT = 0x01, + PG_ACTION_FORWARD = 0x02, /* N/A */ + PG_ACTION_REJECT = 0x10, + PG_ACTION_DROP = 0x20, /* N/A */ + PG_ACTION_REDIRECT = 0x30, + PG_ACTION_RATELIMIT= 0x40, /* N/A */ + PG_ACTION_REPLACE = 0x50, + PG_ACTION_LOOP = 0x60, /* N/A */ + PG_ACTION_WHITELIST= 0x80 +}; +enum scan_table +{ + PXY_CTRL_IP, + PXY_CTRL_HTTP_URL, + PXY_CTRL_HTTP_REQ_HDR, + PXY_CTRL_HTTP_REQ_BODY, + PXY_CTRL_HTTP_RES_HDR, + PXY_CTRL_HTTP_RES_BODY, + __SCAN_TABLE_MAX +}; +struct pangu_rt +{ + Maat_feather_t maat; + struct pangu_logger* send_logger; + void* local_logger; + int log_level; + int thread_num; + int scan_table_id[__SCAN_TABLE_MAX]; + char* reject_page; + int page_size; +}; +struct pangu_rt *g_pangu_rt; +static Maat_feather_t create_maat_feather(const char* profile, const char* section,int max_thread, void* logger) { Maat_feather_t target; int maat_json_switch=0,maat_stat_on=0,maat_perf_on=0; int ret=0,scan_detail=0,effect_interval=60; - char table_info[MAX_PATH_LEN]={0},inc_cfg_dir[MAX_PATH_LEN]={0},ful_cfg_dir[MAX_PATH_LEN]={0}; - char json_cfg_file[MAX_PATH_LEN]={0},maat_stat_file[MAX_PATH_LEN]={0}; - const char* instance_name="soq"; + char table_info[TFE_STRING_MAX]={0},inc_cfg_dir[TFE_STRING_MAX]={0},ful_cfg_dir[TFE_STRING_MAX]={0}; + char json_cfg_file[TFE_STRING_MAX]={0},maat_stat_file[TFE_STRING_MAX]={0}; + const char* instance_name="pangu"; MESA_load_profile_int_def(profile, section,"MAAT_JSON_SWITCH", &(maat_json_switch),0); MESA_load_profile_int_def(profile, section,"STAT_SWITCH", &(maat_stat_on),1); MESA_load_profile_int_def(profile, section,"PERF_SWITCH", &(maat_perf_on),1); @@ -55,13 +92,522 @@ Maat_feather_t init_maat(const char* profile, const char* section,int max_thread } Maat_set_feather_opt(target, MAAT_OPT_EFFECT_INVERVAL_MS, &effect_interval, sizeof(effect_interval)); - //t1 or t2 do not care hit position. + Maat_set_feather_opt(target, MAAT_OPT_SCAN_DETAIL, &scan_detail, sizeof(scan_detail)); ret=Maat_initiate_feather(target); if(ret<0) { + TFE_LOG_ERROR(logger, "%s MAAT init failed.", __FUNCTION__); return NULL; } return target; } +void pangu_http_init(struct tfe_proxy * proxy) +{ + const char* profile="./pangu/pangu_pxy.conf"; + const char* logfile="./log/pangu_pxy.log"; + g_pangu_rt=ALLOC(struct pangu_rt,1); + MESA_load_profile_int_def(profile, "DEBUG", "LOG_LEVEL", &(g_pangu_rt->log_level),0); + g_pangu_rt->local_logger=MESA_create_runtime_log_handle(logfile, g_pangu_rt->log_level); + g_pangu_rt->send_logger=pangu_send_log_init(profile, "LOG", g_pangu_rt->local_logger); + if(!g_pangu_rt->send_logger) + { + goto error_out; + } + g_pangu_rt->maat=create_maat_feather(profile, "MAAT", g_pangu_rt->thread_num, g_pangu_rt->local_logger); + if(!g_pangu_rt->maat) + { + goto error_out; + } + const char* table_name[__SCAN_TABLE_MAX]; + table_name[PXY_CTRL_IP]="PXY_CTRL_IP"; + table_name[PXY_CTRL_HTTP_URL]="PXY_CTRL_HTTP_URL"; + table_name[PXY_CTRL_HTTP_REQ_HDR]="PXY_CTRL_HTTP_REQ_HDR"; + table_name[PXY_CTRL_HTTP_REQ_BODY]="PXY_CTRL_HTTP_REQ_BODY"; + table_name[PXY_CTRL_HTTP_RES_HDR]="PXY_CTRL_HTTP_RES_HDR"; + table_name[PXY_CTRL_HTTP_RES_BODY]="PXY_CTRL_HTTP_RES_BODY"; + for(int i=0;i<__SCAN_TABLE_MAX;i++) + { + + g_pangu_rt->scan_table_id[i]=Maat_table_register(g_pangu_rt->maat, table_name[i]); + if(g_pangu_rt->scan_table_id[i]<0) + { + TFE_LOG_ERROR(proxy->logger, "Pangu HTTP Maat table %s register failed.", table_name[i]); + goto error_out; + } + } + TFE_LOG_INFO(proxy->logger, "Pangu HTTP init success."); + return; + +error_out: + TFE_LOG_ERROR(proxy->logger, "Pangu HTTP init failed."); + return; +} +static void _wrap_std_field_write(struct tfe_http_half * half, enum tfe_http_std_field field_id, const char * value) +{ + struct http_field_name tmp_name; + tmp_name.field_id=field_id; + tmp_name.field_name=NULL; + tfe_http_field_write(half, tmp_name, value); + return; +} +static void _wrap_non_std_field_write(struct tfe_http_half * half, const char* field_name, const char * value) +{ + struct http_field_name tmp_name; + tmp_name.field_id=TFE_HTTP_UNKNOWN_FIELD; + tmp_name.field_name=field_name; + tfe_http_field_write(half, tmp_name, value); + return; +} +struct pangu_http_ctx +{ + enum pangu_action action; + char* action_para; + scan_status_t mid; + stream_para_t sp; + struct Maat_rule_t* enforce_rule; + char* enforce_para; + struct Maat_rule_t* monit_rule; + int monit_num; + int thread_id; +}; +static struct pangu_http_ctx* pangu_http_ctx_new(unsigned int thread_id) +{ + struct pangu_http_ctx* ctx=ALLOC(struct pangu_http_ctx,1); + ctx->mid=NULL; + ctx->thread_id=(int)thread_id; + return ctx; +} +static void pangu_http_ctx_free(struct pangu_http_ctx* ctx) +{ + + Maat_clean_status(&(ctx->mid)); + ctx->mid=NULL; + free(ctx); +} +inline void addr_tfe2sapp(const struct tfe_stream_addr* tfe_addr, struct ipaddr* sapp_addr) +{ + sapp_addr->addrtype=tfe_addr->addrtype; + sapp_addr->paddr=tfe_addr->paddr; + return; +} + +/* +20180909记录 +1)const char * tfe_http_field_iterate(const struct tfe_http_half * half, void * interator, struct http_field_name * name); void**? +2)http入口函数返回值增加 enum tfe_bussiness_action +3)struct http_field_name中的field_name内存是如何分配到? +4)http对上层要暴露evbuffer吗? +5) uint64_t cont_len; + uint64_t cont_range_from; + uint64_t cont_range_to; +需要保留吗?accept_encoding? +6)entry函数中缺少thread id; +7) plugin init and deinit cb; +8) add http session open and close cb; +9)enum tfe_bussiness_action pangu_http_entry(const struct tfe_stream * stream, const struct tfe_http_session * session, + uint64_t event, const char* body_frag, size_t frag_size, unsigned int thread_id void ** pme) +*/ + +static enum pangu_action decide_ctrl_action(const Maat_rule_t* hit_result,int cnt,const Maat_rule_t**enforce_rule) +{ + int i=0; + int idx=0; + const Maat_rule_t* tmp_rule=hit_result; + enum pangu_action tmp_action=PG_ACTION_NONE; + + for(i=0;itmp_action) + { + tmp_rule=hit_result+i; + tmp_action=hit_result[i].action; + } + else if(hit_result[i].action==tmp_action) + { + if(hit_result[i].config_idconfig_id) + { + tmp_rule=hit_result+i; + } + + } + else + { + continue; + } + } + *enforce_rule=tmp_rule; + return tmp_action; +} +static void html_generate(const char* enforce_para, char** page_buff,size_t *page_size) +{ + *page_buff=g_pangu_rt->reject_page; + *page_size=g_pangu_rt->page_size; +} +static void html_free(char** page_buff) +{ + return; +} +static int is_http_request(uint64 events) +{ + if((events&EV_HTTP_REQ_HDR)|(events&EV_HTTP_REQ_BODY_BEGIN)|(events&EV_HTTP_REQ_BODY_END)|(events&EV_HTTP_REQ_BODY_CONT)) + { + return 1; + } + else + { + return 0; + } +} +enum replace_zone +{ + kZoneRequestUri=0, + kZoneRequestHeaders, + kZoneRequestBody, + kZoneResponseHeader, + kZoneResponseBody, + kZoneMax +}; +struct replace_rule +{ + enum replace_zone zone; + char* find; + char* replace_with; +}; +enum replace_zone zone_name_to_id(const char* name) +{ + const char* std_name[]={"http_req_uri", + "http_req_header", + "http_req_body", + "http_resp_header", + "http_resp_body", + "http_resp_body"}; + int i=0; + for(i=0;i< sizeof(std_name)/sizeof(const char*);i++) + { + if(0==strcasecmp(name,std_name[i])) + { + break; + } + } + return (enum replace_zone)i; +} +static char* strchr_esc(char* s,const char delim) +{ + char *token; + if(s==NULL) + return NULL; + for(token=s;*token!='\0';token++) + { + if(*token=='\\') + { + token++; + continue; + } + if(*token==delim) + break; + } + if (*token == '\0') + { + return NULL; + } + else + { + return token; + } +} +static char *strtok_r_esc(char *s, const char delim, char **save_ptr) { + char *token; + + if (s == NULL) s = *save_ptr; + + /* Scan leading delimiters. */ + token=strchr_esc(s,delim); + if(token==NULL) + { + *save_ptr=token; + return s; + } + /* Find the end of the token. */ + *token='\0'; + token++; + *save_ptr=token; + + return s; +} + +size_t format_replace_rule(const char* enforce_para,struct replace_rule* zone, size_t n_zone) +{ + + char* tmp=ALLOC(char, strlen(enforce_para)+1); + char *token=NULL,*sub_token=NULL,*saveptr=NULL, *saveptr2=NULL; + size_t idx=0; + const char* str_zone="zone="; + const char* str_subs="substitute="; + memcpy(tmp,enforce_para,strlen(enforce_para)); + for (token = tmp; ; token= NULL) + { + sub_token= strtok_r(token,";", &saveptr); + if (sub_token == NULL) + break; + if(0=strncasecmp(sub_token,str_zone,strlen(str_zone))) + { + zone[idx].zone=zone_name_to_id(sub_token+strlen(str_zone)); + if(zone[idx].zone==kZoneMax) + { + break; + } + } + if(0==strncasecmp(sub_token,str_subs,strlen(str_subs))) + { + sub_token=+=strlen(str_subs); + zone[idx].find=tfe_strdup(strtok_r_esc(sub_token,"/", &saveptr2)); + zone[idx].replace_with==tfe_strdup(strtok_r_esc(NULL,"/", &saveptr2)); + idx++; + if(idx==n_zone) + { + break; + } + } + } + free(tmp); + tmp=NULL; + return idx; +} +static enum tfe_bussiness_action http_replace(const struct tfe_stream * stream, const struct tfe_http_session * session, + uint64_t events, const char* body_frag, size_t frag_size,struct pangu_http_ctx* ctx) +{ + enum tfe_bussiness_action plugin_ret=BIZ_ACTION_FORWARD; + struct replace_rule* zone=ALLOC(struct replace_rule, MAX_EDIT_ZONE_NUM); + size_t zone_num=format_replace_rule(ctx->enforce_para, zone, MAX_EDIT_ZONE_NUM); + +} +static enum tfe_bussiness_action http_reject(const struct tfe_http_session * session, uint64_t events, struct pangu_http_ctx* ctx) +{ + + enum tfe_bussiness_action plugin_ret=BIZ_ACTION_FORWARD; + int resp_code=0,ret=0; + struct tfe_http_half* response=NULL; + struct http_field_name tmp_name; + char* page_buff=NULL; + size_t page_size=0; + char buff[TFE_STRING_MAX]; + + ret=sscanf(ctx->enforce_para,"code=%d%[^;];",&resp_code); + if(ret!=1) + { + TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid reject rule %d paramter %s", + ctx->enforce_rule->config_id, ctx->enforce_para); + goto error_out; + } + + response=tfe_http_response_create(session->major_version, resp_code); + + html_generate(ctx->enforce_para, &page_buff, &page_size); + _wrap_std_field_write(response, TFE_HTTP_CONT_TYPE, "text/html; charset=utf-8"); + snprinf(buff,sizeof(buff),"%d",page_size); + _wrap_std_field_write(response, TFE_HTTP_CONT_LENGTH, buff); + + tfe_http_append_body(response, page_buff, page_size, EV_HTTP_RESP_BODY_FULL); + + tfe_http_session_set_half(session,response); + plugin_ret=is_http_request(events)?BIZ_ACTION_ANSWER:BIZ_ACTION_MODIFIED; + +error_out: + html_free(page_buff); + return plugin_ret; +} +static enum tfe_bussiness_action http_redirect(const struct tfe_http_session * session, uint64_t events, struct pangu_http_ctx* ctx) +{ + + enum tfe_bussiness_action plugin_ret=BIZ_ACTION_FORWARD; + int resp_code=0,ret=0; + char* url=NULL; + struct tfe_http_half* response=NULL; + + url=ALLOC(char, ctx->enforce_rule->serv_def_len); + ret=sscanf(ctx->enforce_para,"code=%d%[^;];url=%*[^;];",&resp_code,url); + if(ret!=2) + { + TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid redirect rule %d paramter %s", + ctx->enforce_rule->config_id, ctx->enforce_para); + goto error_out; + } + response=tfe_http_response_create(session->major_version, resp_code); + _wrap_std_field_write(response, TFE_HTTP_LOCATION, url); + tfe_http_session_set_half(session,response); + + plugin_ret=is_http_request(events)?BIZ_ACTION_ANSWER:BIZ_ACTION_MODIFIED; +error_out: + free(url); + return plugin_ret; +} + +enum pangu_action http_scan(const struct tfe_http_session * session, uint64_t events, + const char* body_frag, size_t frag_size, struct pangu_http_ctx* ctx) +{ + void * interator=NULL; + const char* field_val=NULL; + struct http_field_name field_name; + struct Maat_rule_t result[MAX_SCAN_RESULT], *choosen=NULL; + char buff[TFE_STRING_MAX], *p=NULL; + int scan_ret=0, hit_cnt=0, table_id=0, read_rule_ret=0; + unsigned int i=0; + if(events&EV_HTTP_REQ_HDR) + { + scan_ret=Maat_full_scan_string(g_pangu_rt->maat, g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_URL], + CHARSET_UTF8, session->req->req_spec.url, strlen(session->req->req_spec.url), + result, NULL, MAX_SCAN_RESULT, &(ctx->mid), ctx->thread_id); + if(scan_ret>0) + { + hit_cnt+=scan_ret; + } + } + if((events&EV_HTTP_REQ_HDR)|(events&EV_HTTP_RESP_HDR)) + { + table_id=events&EV_HTTP_REQ_HDR?g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_REQ_HDR]:g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_RES_HDR]; + for(i=0; ireq->field_cnt && hit_cntreq, &interator, &field_name); + scan_ret=Maat_set_scan_status(g_pangu_rt->maat, ctx->mid, MAAT_SET_SCAN_DISTRICT, + field_name.field_name,strlen(field_name.field_name)); + assert(scan_ret==0); + scan_ret=Maat_full_scan_string(g_pangu_rt->maat, table_id, + CHARSET_UTF8, field_val, strlen(field_val), + result+hit_cnt, NULL, MAX_SCAN_RESULT-hit_cnt, &(ctx->mid), ctx->thread_id); + if(scan_ret>0) + { + hit_cnt+=scan_ret; + } + } + } + if((events&EV_HTTP_REQ_BODY_BEGIN)|(events&EV_HTTP_RESP_BODY_BEGIN)) + { + assert(ctx->sp==NULL); + table_id=events&EV_HTTP_REQ_BODY_BEGIN?g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_REQ_BODY]:g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_RES_BODY] + ctx->sp=Maat_stream_scan_string_start(g_pangu_rt->maat, table_id, ctx->thread_id); + } + if(body_frag!=NULL) + { + scan_ret=Maat_stream_scan_string(&(ctx->sp),CHARSET_UTF8, body_frag, (int)frag_size + ,result+hit_cnt, NULL, MAX_SCAN_RESULT-hit_cnt, &(ctx->mid)); + if(scan_ret>0) + { + hit_cnt+=scan_ret; + } + } + if(events&EV_HTTP_REQ_BODY_END) + { + Maat_stream_scan_string_end(&(ctx->sp); + ctx->sp=NULL; + } + if(hit_cnt>0) + { + ctx->action=decide_ctrl_action(result, hit_cnt, &choosen); + ctx->enforce_rule=ALLOC(struct Maat_rule_t, 1); + memcpy(ctx->enforce_rule, choosen, sizeof(struct Maat_rule_t)); + if(ctx->enforce_rule.serv_def_len>MAX_SERVICE_DEFINE_LEN) + { + ctx->enforce_para=ALLOC(char, ctx->enforce_rule.serv_def_len); + read_rule_ret=Maat_read_rule(g_pangu_rt->maat, ctx->enforce_rule, + MAAT_RULE_SERV_DEFINE, ctx->enforce_para, ctx->enforce_rule.serv_def_len); + assert(read_rule_ret== ctx->enforce_rule.serv_def_len); + } + if(hit_cnt>1) + { + p=buff; + for(i=0;i<(unsigned int)hit_cnt;i++) + { + p+=snprintf(p, sizeof(buff)-(p-buff), "%d:", result[i].config_id); + } + *p='\0'; + TFE_LOG_INFO(g_pangu_rt->local_logger, "Multiple rules matched: url=%s num=%d ids=%s enforce=%d .", + session->req->req_spec.url, buff, hit_cnt, ctx->enforce_rule->config_id); + } + } + return ctx->action; +} + + enum tfe_bussiness_action pangu_on_http_begin(const struct tfe_stream * stream, + const struct tfe_http_session * session, unsigned int thread_id, void ** pme) + +{ + struct pangu_http_ctx* ctx=*(struct pangu_http_ctx**)pme; + struct Maat_rule_t result[MAX_SCAN_RESULT]; + struct Maat_rule_t* choosen=NULL; + struct ipaddr sapp_addr; + int hit_cnt=0; + assert(ctx==NULL); + ctx=pangu_http_ctx_new(thread_id); + addr_tfe2sapp(stream->addr, sapp_addr); + hit_cnt=Maat_scan_proto_addr(g_pangu_rt->maat, g_pangu_rt->scan_table_id[PXY_CTRL_IP], sapp_addr, 0, + result, MAX_SCAN_RESULT, &(ctx->mid), (int)thread_id); + if(hit_cnt>0) + { + ctx->action=decide_ctrl_action(result, hit_cnt, &choosen); + } + if(ctx->action==PG_ACTION_WHITELIST) + { + + } +} + + +void pangu_on_http_end(const struct tfe_stream * stream, + const struct tfe_http_session * session, unsigned int thread_id, void ** pme) + +{ + struct pangu_http_ctx* ctx=*(struct pangu_http_ctx**)pme; + struct pangu_log log_msg={.stream=stream, .http=session, .result=ctx->enforce_rule, .result_num=1}; + if(ctx->action!=PG_ACTION_NONE) + { + pangu_send_log(g_pangu_rt->send_logger, &log_msg, NULL, 0); + } + pangu_http_ctx_free(ctx); + *pme=NULL; + return; +} + +enum tfe_bussiness_action pangu_on_http_data(const struct tfe_stream * stream, const struct tfe_http_session * session, + uint64_t events, const char* body_frag, size_t frag_size, unsigned int thread_id, void ** pme) +{ + struct pangu_http_ctx* ctx=*(struct pangu_http_ctx**)pme; + int hit_cnt=0; + enum pangu_action hit_action=PG_ACTION_NONE; + enum tfe_bussiness_action plugin_ret=BIZ_ACTION_FORWARD; + +Re_Enter: + switch(ctx->action) + { + case PG_ACTION_NONE: + hit_action=http_scan(session, events, body_frag, frag_size, ctx); + if(hit_action!=PG_ACTION_NONE) + { + //ctx->action changed in http_scan. + goto Re_Enter; + } + break; + case PG_ACTION_MONIT: + //send log on close. + plugin_ret=BIZ_ACTION_FORWARD; + break; + case PG_ACTION_REJECT: + plugin_ret=http_reject(session, events, ctx); + break; + case PG_ACTION_REDIRECT: + plugin_ret=http_redirect(session, events, ctx); + case PG_ACTION_REPLACE: + plugin_ret=http_replace(stream, session, events, body_frag, frag_size,ctx); + break; + case PG_ACTION_WHITELIST: + plugin_ret=BIZ_ACTION_PASSTHROUGH; + break; + default: + assert(0); + plugin_ret=BIZ_ACTION_FORWARD + break; + } + + return plugin_ret; +} diff --git a/plugin/business/pangu-http/pangu_logger.cpp b/plugin/business/pangu-http/pangu_logger.cpp index 7d39fe7..c56d867 100644 --- a/plugin/business/pangu-http/pangu_logger.cpp +++ b/plugin/business/pangu-http/pangu_logger.cpp @@ -1,5 +1,5 @@ -#include "tfe_utils.h" -#include "cJSON.h" +#include +#include #include #include @@ -40,7 +40,7 @@ struct pangu_logger -unsigned int get_ip_by_eth_name(const char *ifname) +static unsigned int get_ip_by_eth_name(const char *ifname) { int sockfd; struct ifreq ifr; @@ -69,7 +69,7 @@ error: -rd_kafka_t * create_kafka_handle(const char* brokerlist) +static rd_kafka_t * create_kafka_handle(const char* brokerlist) { int i = 0; char kafka_errstr[1024]; @@ -98,7 +98,7 @@ rd_kafka_t * create_kafka_handle(const char* brokerlist) -struct pangu_logger* pangu_logger_init(const char* profile, const char* section, void* logger) +struct pangu_logger* pangu_send_log_init(const char* profile, const char* section, void* logger) { int ret=-1,i=0; char addr_string[TFE_SYMBOL_MAX]={0},local_msg_dir[TFE_STRING_MAX]={0}; @@ -154,7 +154,7 @@ error_out: free(instance); return NULL; } -int pangu_send_log(struct pangu_logger* logger, const pangu_log* log_msg,struct opt_unit* log_opt,int opt_num) +int pangu_send_log(struct pangu_logger* logger, const struct pangu_log* log_msg,struct opt_unit* log_opt,int opt_num) { } diff --git a/plugin/business/pangu-http/pangu_logger.h b/plugin/business/pangu-http/pangu_logger.h index 0f20366..45464a3 100644 --- a/plugin/business/pangu-http/pangu_logger.h +++ b/plugin/business/pangu-http/pangu_logger.h @@ -1,6 +1,7 @@ #pragma once -#include "tfe_stream.h" +#include +#include #include enum pangu_log_opt @@ -77,6 +78,7 @@ struct opt_unit struct pangu_log { const struct tfe_stream *stream; + const struct tfe_http_session* http; const Maat_rule_t*result; int result_num; };