支持从原始流量中获取MAC地址并用于解密流量转发以太网头部的构建。

This commit is contained in:
luqiuwen
2019-09-18 20:00:03 +08:00
parent 4af0b21d58
commit ac14a745f9
4 changed files with 189 additions and 142 deletions

View File

@@ -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;
}