diff --git a/common/include/tfe_cmsg.h b/common/include/tfe_cmsg.h index cee1d81..16c879a 100644 --- a/common/include/tfe_cmsg.h +++ b/common/include/tfe_cmsg.h @@ -37,7 +37,11 @@ enum tfe_cmsg_tlv_type TFE_CMSG_SSL_CLIENT_SIDE_VERSION, TFE_CMSG_SSL_PINNING_STATE, //size uint64_t, 0-not pinning 1-pinning 2-maybe pinning TFE_CMSG_SSL_CERT_VERIFY, - TFE_CMSG_SSL_ERROR //string + TFE_CMSG_SSL_ERROR, //string + + /* Original Traffic's src & dst MAC address */ + TFE_CMSG_SRC_MAC, + TFE_CMSG_DST_MAC, }; struct tfe_cmsg* tfe_cmsg_init(); diff --git a/plugin/business/traffic-mirror/include/traffic_mirror.h b/plugin/business/traffic-mirror/include/traffic_mirror.h index bae16df..fdda9d6 100644 --- a/plugin/business/traffic-mirror/include/traffic_mirror.h +++ b/plugin/business/traffic-mirror/include/traffic_mirror.h @@ -108,7 +108,8 @@ void traffic_mirror_ethdev_destroy(struct traffic_mirror_ethdev * ethdev); int traffic_mirror_ethdev_finish(struct traffic_mirror_ethdev * ethdev, unsigned int tid, unsigned int pktlen); struct traffic_mirror_rebuild * traffic_mirror_rebuild_create(struct tfe_stream_addr * addr, - struct traffic_mirror_rebuild_target * target, struct traffic_mirror_ethdev * ethdev); + struct ether_addr * s_ether_addr, struct ether_addr * d_ether_addr, + struct traffic_mirror_rebuild_target * target, struct traffic_mirror_ethdev * ethdev); void traffic_mirror_rebuild_destroy(struct traffic_mirror_rebuild * instance); void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance, unsigned int tid); diff --git a/plugin/business/traffic-mirror/src/entry.cpp b/plugin/business/traffic-mirror/src/entry.cpp index 75410f5..3acb11f 100644 --- a/plugin/business/traffic-mirror/src/entry.cpp +++ b/plugin/business/traffic-mirror/src/entry.cpp @@ -541,99 +541,122 @@ errout: int traffic_mirror_on_open_cb(const struct tfe_stream * stream, unsigned int thread_id, enum tfe_conn_dir dir, void ** pme) { - /* Firstly, fetch destination address of traffic mirror */ - struct traffic_mirror_me * me = NULL; - struct traffic_mirror_instance * instance = g_traffic_mirror_instance; - struct tfe_cmsg * cmsg = tfe_stream_get0_cmsg(stream); + /* Firstly, fetch destination address of traffic mirror */ + struct traffic_mirror_me * me = NULL; + struct traffic_mirror_instance * instance = g_traffic_mirror_instance; + struct tfe_cmsg * cmsg = tfe_stream_get0_cmsg(stream); - unsigned int target_id; - struct traffic_mirror_rebuild_target * rebuild_target = NULL; + unsigned int target_id; + struct traffic_mirror_rebuild_target * rebuild_target = NULL; - assert(instance != NULL); - assert(cmsg != NULL); + assert(instance != NULL); + assert(cmsg != NULL); - char str_policy_id[TFE_SYMBOL_MAX] = {0}; - char str_profile_id[TFE_SYMBOL_MAX] = {0}; + char str_policy_id[TFE_SYMBOL_MAX] = {0}; + char str_profile_id[TFE_SYMBOL_MAX] = {0}; - unsigned int opt_val; - uint16_t opt_out_size; + unsigned int opt_val; + uint16_t opt_out_size; - struct policy_table_ex_data * policy_ex_data = NULL; - struct profile_table_ex_data * profile_ex_data = NULL; + struct policy_table_ex_data * policy_ex_data = NULL; + struct profile_table_ex_data * profile_ex_data = NULL; - int ret = tfe_cmsg_get_value(cmsg, TFE_CMSG_POLICY_ID, (unsigned char *) &opt_val, sizeof(opt_val), &opt_out_size); - if (ret < 0) - { - TFE_LOG_ERROR(instance->logger, "failed at getting policy id from cmsg, detach the stream."); - goto detach; - } + struct ether_addr c_ether_addr = {}; + struct ether_addr s_ether_addr = {}; - snprintf(str_policy_id, sizeof(str_policy_id), "%u", opt_val); - policy_ex_data = (struct policy_table_ex_data *) Maat_plugin_get_EX_data(instance->maat_feather, - instance->policy_table_id, str_policy_id); + int ret = tfe_cmsg_get_value(cmsg, TFE_CMSG_POLICY_ID, (unsigned char *) &opt_val, sizeof(opt_val), &opt_out_size); + if (ret < 0) + { + TFE_LOG_ERROR(instance->logger, "failed at getting policy id from cmsg, detach the stream."); + goto detach; + } - if (!policy_ex_data) - { - TFE_LOG_ERROR(instance->logger, "failed at getting policy %s's EXDATA, detach the stream", str_policy_id); - goto detach; - } + snprintf(str_policy_id, sizeof(str_policy_id), "%u", opt_val); + policy_ex_data = (struct policy_table_ex_data *) Maat_plugin_get_EX_data(instance->maat_feather, + instance->policy_table_id, str_policy_id); - if (!policy_ex_data->enable) - { - goto detach; - } + if (!policy_ex_data) + { + TFE_LOG_ERROR(instance->logger, "failed at getting policy %s's EXDATA, detach the stream", str_policy_id); + goto detach; + } - snprintf(str_profile_id, sizeof(str_policy_id), "%u", policy_ex_data->profile_id); - profile_ex_data = (struct profile_table_ex_data *) Maat_plugin_get_EX_data(instance->maat_feather, - instance->profile_table_id, str_profile_id); + if (!policy_ex_data->enable) + { + goto detach; + } - if (!profile_ex_data) - { - TFE_LOG_ERROR(instance->logger, "failed at getting policy %s's profile, profile id = %s, " - "detach the stream", str_policy_id, str_profile_id); - goto detach; - } + snprintf(str_profile_id, sizeof(str_policy_id), "%u", policy_ex_data->profile_id); + profile_ex_data = (struct profile_table_ex_data *) Maat_plugin_get_EX_data(instance->maat_feather, + instance->profile_table_id, str_profile_id); - target_id = random() % profile_ex_data->nr_targets; - rebuild_target = ALLOC(struct traffic_mirror_rebuild_target, 1); - rebuild_target->vlan_tci = profile_ex_data->vlans[target_id]; - rebuild_target->ether_addr = profile_ex_data->ether_addrs[target_id]; + if (!profile_ex_data) + { + TFE_LOG_ERROR(instance->logger, "failed at getting policy %s's profile, profile id = %s, " + "detach the stream", str_policy_id, str_profile_id); + goto detach; + } - me = ALLOC(struct traffic_mirror_me, 1); - me->rebuild_ctx = traffic_mirror_rebuild_create(stream->addr, rebuild_target, instance->ethdev); - me->profile_ex_data = profile_ex_data; - *pme = (void *) me; + ret = tfe_cmsg_get_value(cmsg, TFE_CMSG_SRC_MAC, (unsigned char *) &c_ether_addr, + sizeof(c_ether_addr), &opt_out_size); - /* the ownership is transfer to struct me and rebuild_target */ - profile_ex_data = NULL; - rebuild_target = NULL; + if (ret < 0) + { + TFE_LOG_ERROR(instance->logger, "failed at source mac address, detach the stream."); + goto detach; + } - traffic_mirror_rebuild_handshake(me->rebuild_ctx, thread_id); - return ACTION_FORWARD_DATA; + ret = tfe_cmsg_get_value(cmsg, TFE_CMSG_DST_MAC, (unsigned char *) &s_ether_addr, + sizeof(s_ether_addr), &opt_out_size); + + if (ret < 0) + { + TFE_LOG_ERROR(instance->logger, "failed at dest mac address, detach the stream."); + goto detach; + } + + target_id = random() % profile_ex_data->nr_targets; + rebuild_target = ALLOC(struct traffic_mirror_rebuild_target, 1); + rebuild_target->vlan_tci = profile_ex_data->vlans[target_id]; + rebuild_target->ether_addr = profile_ex_data->ether_addrs[target_id]; + + me = ALLOC(struct traffic_mirror_me, 1); + me->rebuild_ctx = traffic_mirror_rebuild_create(stream->addr, &c_ether_addr, &s_ether_addr, + rebuild_target, instance->ethdev); + + me->profile_ex_data = profile_ex_data; + *pme = (void *) me; + + /* the ownership is transfer to struct me and rebuild_target */ + profile_ex_data = NULL; + rebuild_target = NULL; + + traffic_mirror_rebuild_handshake(me->rebuild_ctx, thread_id); + return ACTION_FORWARD_DATA; detach: - if (me) - { - free(me); - } + if (me) + { + free(me); + } - if (policy_ex_data) - { - policy_table_ex_data_free(policy_ex_data); - } + if (policy_ex_data) + { + policy_table_ex_data_free(policy_ex_data); + } - if (profile_ex_data) - { - profile_table_ex_data_free(profile_ex_data); - } + if (profile_ex_data) + { + profile_table_ex_data_free(profile_ex_data); + } - if (rebuild_target) - { - free(rebuild_target); - } + if (rebuild_target) + { + free(rebuild_target); + } - tfe_stream_detach(stream); - return ACTION_FORWARD_DATA; + tfe_stream_detach(stream); + return ACTION_FORWARD_DATA; } enum tfe_stream_action traffic_mirror_on_data_cb(const struct tfe_stream * stream, unsigned int thread_id, diff --git a/plugin/business/traffic-mirror/src/rebuild.cpp b/plugin/business/traffic-mirror/src/rebuild.cpp index 11f8c41..1a93b15 100644 --- a/plugin/business/traffic-mirror/src/rebuild.cpp +++ b/plugin/business/traffic-mirror/src/rebuild.cpp @@ -11,6 +11,8 @@ struct traffic_mirror_rebuild { struct tfe_stream_addr * c_s_addr; struct tfe_stream_addr * s_c_addr; + struct ether_addr c_ether_addr; + struct ether_addr s_ether_addr; struct traffic_mirror_rebuild_target * target; struct traffic_mirror_ethdev * ethdev; @@ -278,31 +280,30 @@ static void vlan_tag_construct(unsigned char *buf, unsigned short tci, unsigned } static int ether_header_construct(struct traffic_mirror_ethdev * ethdev, char * buffer, - struct ether_addr * target_addr, unsigned int vlan_tci, unsigned l3_protocol) + struct ether_addr * source, struct ether_addr * dest, unsigned int vlan_tci, unsigned l3_protocol) { - unsigned int header_len = 0; - unsigned int eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol; + unsigned int header_len = 0; + unsigned int eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol; - ether_header_construct_helper((unsigned char *)buffer + header_len, - (unsigned char *)target_addr->ether_addr_octet, - (unsigned char *)ethdev->local_ether_addr, eth_protocol); + ether_header_construct_helper((unsigned char *) buffer + header_len, + (unsigned char *) dest, (unsigned char *) source, eth_protocol); - header_len += sizeof(struct ethhdr); + header_len += sizeof(struct ethhdr); - /* need to construct vlan header */ - if (vlan_tci > 0) - { - vlan_tag_construct((unsigned char *)buffer + header_len, vlan_tci, l3_protocol); - header_len += sizeof(struct vlan_hdr); - } + /* need to construct vlan header */ + if (vlan_tci > 0) + { + vlan_tag_construct((unsigned char *) buffer + header_len, vlan_tci, l3_protocol); + header_len += sizeof(struct vlan_hdr); + } - return header_len; + return header_len; } -static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, - struct traffic_mirror_ethdev * ethdev, struct traffic_mirror_rebuild_target * target, - unsigned int tid, const char * payload, unsigned int payload_len, - unsigned int seq, unsigned int ack, char flags) +static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, struct ether_addr * ether_addr_src, + struct ether_addr * ether_addr_dst, struct traffic_mirror_ethdev * ethdev, + struct traffic_mirror_rebuild_target * target, unsigned int tid, const char * payload, unsigned int payload_len, + unsigned int seq, unsigned int ack, char flags) { char * pkt_buffer = ethdev->fn_send_prepare(ethdev, tid); assert(pkt_buffer != NULL); @@ -318,7 +319,16 @@ static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, unsigned int pkt_len = 0; /* Ethernet and VLAN header */ - pkt_len += ether_header_construct(ethdev, pkt_buffer, &target->ether_addr, target->vlan_tci, l3_protocol); + if (target->vlan_tci > 0) + { + pkt_len += ether_header_construct(ethdev, pkt_buffer, ether_addr_src, + ether_addr_dst, target->vlan_tci, l3_protocol); + } + else + { + pkt_len += ether_header_construct(ethdev, pkt_buffer, ether_addr_src, + &target->ether_addr, target->vlan_tci, l3_protocol); + } /* IPv4/IPv6 Header */ pkt_len += ip_header_construct_by_stream_addr(addr, @@ -338,37 +348,44 @@ static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, } } -static void tcp_send_to_target(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev, - struct traffic_mirror_rebuild_target * target, unsigned int tid, const char * payload, - unsigned int payload_len, unsigned int seq, unsigned int ack, char flags) +static void tcp_send_to_target(struct tfe_stream_addr * addr, struct ether_addr * ether_addr_src, + struct ether_addr * ether_addr_dst, struct traffic_mirror_ethdev * ethdev, + struct traffic_mirror_rebuild_target * target, unsigned int tid, const char * payload, unsigned int payload_len, + unsigned int seq, unsigned int ack, char flags) { - unsigned int payload_offset = 0; - unsigned mss = ethdev->mtu - (MAX(sizeof(struct iphdr), sizeof(struct ip6_hdr)) + sizeof(struct tcphdr)); + unsigned int payload_offset = 0; + unsigned mss = ethdev->mtu - (MAX(sizeof(struct iphdr), sizeof(struct ip6_hdr)) + sizeof(struct tcphdr)); - /* handshake or farewell */ - if (payload == NULL || payload_len == 0) - { - tcp_segment_send_to_target_group(addr, ethdev, target, tid, NULL, 0, seq, ack, flags); - return; - } + /* handshake or farewell */ + if (payload == NULL || payload_len == 0) + { + tcp_segment_send_to_target_group(addr, ether_addr_src, ether_addr_dst, + ethdev, target, tid, NULL, 0, seq, ack, flags); + return; + } - while(payload_offset < payload_len) - { - unsigned int payload_sz_seg = MIN(payload_len - payload_offset, mss); - const char * payload_ptr_seg = payload + payload_offset; + while (payload_offset < payload_len) + { + unsigned int payload_sz_seg = MIN(payload_len - payload_offset, mss); + const char * payload_ptr_seg = payload + payload_offset; - tcp_segment_send_to_target_group(addr, ethdev, target, tid, payload_ptr_seg, payload_sz_seg, seq, ack, flags); - seq += payload_sz_seg; - payload_offset += payload_sz_seg; - } + tcp_segment_send_to_target_group(addr, ether_addr_src, ether_addr_dst, + ethdev, target, tid, payload_ptr_seg, payload_sz_seg, seq, ack, flags); + seq += payload_sz_seg; + payload_offset += payload_sz_seg; + } } struct traffic_mirror_rebuild * traffic_mirror_rebuild_create(struct tfe_stream_addr * addr, + struct ether_addr * c_ether_addr, struct ether_addr * s_ether_addr, struct traffic_mirror_rebuild_target * target, struct traffic_mirror_ethdev * ethdev) { struct traffic_mirror_rebuild * instance = ALLOC(struct traffic_mirror_rebuild, 1); instance->c_s_addr = addr; instance->s_c_addr = tfe_stream_addr_reverse(addr); + instance->c_ether_addr = *c_ether_addr; + instance->s_ether_addr = *s_ether_addr; + instance->target = target; instance->ethdev = ethdev; @@ -387,14 +404,16 @@ void traffic_mirror_rebuild_destroy(struct traffic_mirror_rebuild * instance) void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance, unsigned int tid) { - tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->c_seq, 0, TCP_SYN_FLAG); + tcp_send_to_target(instance->c_s_addr, &instance->c_ether_addr, &instance->s_ether_addr, + instance->ethdev, instance->target, tid,NULL, 0, instance->c_seq, 0, TCP_SYN_FLAG); - tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_SYN_FLAG | TCP_ACK_FLAG); + tcp_send_to_target(instance->s_c_addr, &instance->s_ether_addr, &instance->c_ether_addr, + instance->ethdev, instance->target, tid,NULL, 0, instance->s_seq, + instance->c_seq + 1, TCP_SYN_FLAG | TCP_ACK_FLAG); - tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->c_seq + 1, instance->s_seq + 1, TCP_ACK_FLAG); + tcp_send_to_target(instance->c_s_addr, &instance->c_ether_addr, &instance->s_ether_addr, + instance->ethdev, instance->target, tid,NULL, 0, instance->c_seq + 1, + instance->s_seq + 1, TCP_ACK_FLAG); instance->s_seq++; instance->c_seq++; @@ -403,44 +422,44 @@ void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance, void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance, unsigned int tid, const char * data, unsigned int datalen, enum tfe_conn_dir dir) { - if (data == NULL || datalen == 0) - { - return; - } + if (data == NULL || datalen == 0) + { + return; + } - if (dir == CONN_DIR_DOWNSTREAM) - { - tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid, - data, datalen, instance->c_seq, instance->s_seq, TCP_ACK_FLAG); - instance->c_seq += datalen; - } - else - { - tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid, - data, datalen, instance->s_seq, instance->c_seq, TCP_ACK_FLAG); - instance->s_seq += datalen; - } + if (dir == CONN_DIR_DOWNSTREAM) + { + tcp_send_to_target(instance->c_s_addr, &instance->c_ether_addr, &instance->s_ether_addr, + instance->ethdev, instance->target, tid, data, datalen, instance->c_seq, instance->s_seq, TCP_ACK_FLAG); + instance->c_seq += datalen; + } + else + { + tcp_send_to_target(instance->s_c_addr, &instance->s_ether_addr, &instance->c_ether_addr, instance->ethdev, + instance->target, tid, data, datalen, instance->s_seq, instance->c_seq, TCP_ACK_FLAG); + instance->s_seq += datalen; + } } void traffic_mirror_rebuild_farewell(struct traffic_mirror_rebuild * instance, unsigned int tid) { /* C->S FIN */ - tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->c_seq, instance->s_seq, TCP_FIN_FLAG | TCP_ACK_FLAG); + tcp_send_to_target(instance->c_s_addr, &instance->c_ether_addr, &instance->s_ether_addr, instance->ethdev, instance->target, tid, + NULL, 0, instance->c_seq, instance->s_seq, TCP_FIN_FLAG | TCP_ACK_FLAG); /* C->S FIN, ACK */ - tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_ACK_FLAG); + tcp_send_to_target(instance->s_c_addr, &instance->s_ether_addr, &instance->c_ether_addr, instance->ethdev, instance->target, tid, + NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_ACK_FLAG); instance->c_seq += 1; /* S->C FIN */ - tcp_send_to_target(instance->s_c_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->s_seq, instance->c_seq, TCP_FIN_FLAG | TCP_ACK_FLAG); + tcp_send_to_target(instance->s_c_addr, &instance->s_ether_addr, &instance->c_ether_addr, instance->ethdev, instance->target, tid, + NULL, 0, instance->s_seq, instance->c_seq, TCP_FIN_FLAG | TCP_ACK_FLAG); /* C->S FIN, ACK */ - tcp_send_to_target(instance->c_s_addr, instance->ethdev, instance->target, tid, - NULL, 0, instance->c_seq, instance->s_seq + 1, TCP_ACK_FLAG); + tcp_send_to_target(instance->c_s_addr, &instance->c_ether_addr, &instance->s_ether_addr, instance->ethdev, instance->target, tid, + NULL, 0, instance->c_seq, instance->s_seq + 1, TCP_ACK_FLAG); instance->s_seq += 1; }