重新实现解密流量转发模块,增加按策略转发功能。
This commit is contained in:
@@ -3,19 +3,16 @@
|
||||
#include <event2/event.h>
|
||||
|
||||
struct tfe_proxy;
|
||||
|
||||
const char * tfe_proxy_default_conffile();
|
||||
const char * tfe_proxy_default_logger();
|
||||
unsigned int tfe_proxy_get_work_thread_count();
|
||||
struct event_base * tfe_proxy_get_work_thread_evbase(unsigned int thread_id);
|
||||
struct evdns_base* tfe_proxy_get_work_thread_dnsbase(unsigned int thread_id);
|
||||
|
||||
struct event_base * tfe_proxy_get_gc_evbase(void);
|
||||
screen_stat_handle_t tfe_proxy_get_fs_handle(void);
|
||||
void * tfe_proxy_get_error_logger(void);
|
||||
|
||||
int tfe_proxy_ssl_add_trust_ca(const char* pem_file);
|
||||
int tfe_proxy_ssl_del_trust_ca(const char* pem_file);
|
||||
int tfe_proxy_ssl_add_crl(const char* pem_file);
|
||||
int tfe_proxy_ssl_del_crl(const char* pem_file);
|
||||
void tfe_proxy_ssl_reset_trust_ca();
|
||||
|
||||
|
||||
@@ -495,6 +495,11 @@ screen_stat_handle_t tfe_proxy_get_fs_handle(void)
|
||||
return g_default_proxy->fs_handle;
|
||||
}
|
||||
|
||||
void * tfe_proxy_get_error_logger(void)
|
||||
{
|
||||
return g_default_logger;
|
||||
}
|
||||
|
||||
int tfe_proxy_ssl_add_trust_ca(const char* pem_file)
|
||||
{
|
||||
return ssl_manager_add_trust_ca(g_default_proxy->ssl_mgr_handler, pem_file);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
add_library(decrypt-mirroring src/decrypt_mirror_plugin.cpp src/mirror_stream.cpp src/sendpkt.cpp)
|
||||
target_include_directories(decrypt-mirroring PRIVATE include/internal)
|
||||
target_include_directories(decrypt-mirroring PUBLIC include/external)
|
||||
target_link_libraries(decrypt-mirroring common)
|
||||
add_library(traffic-mirror src/entry.cpp src/ethdev.cpp src/rebuild.cpp)
|
||||
target_include_directories(traffic-mirror PRIVATE include)
|
||||
target_link_libraries(traffic-mirror common cjson)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include <tfe_stream.h>
|
||||
|
||||
int decrypt_mirror_init(void *proxy);
|
||||
|
||||
enum tfe_stream_action decrypt_mirror_on_open_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme);
|
||||
|
||||
enum tfe_stream_action decrypt_mirror_on_data_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme);
|
||||
|
||||
void decrypt_mirror_on_close_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_stream_close_reason reason, void ** pme);
|
||||
void decrypt_mirror_deinit(void);
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#ifndef DELIVER_PROCESS_H
|
||||
#define DELIVER_PROCESS_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <tfe_stream.h>
|
||||
|
||||
|
||||
|
||||
struct origin_stream_addr
|
||||
{
|
||||
struct sockaddr* client;
|
||||
struct sockaddr* server;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Description:deliver read config from filepath to init;
|
||||
Paraments:
|
||||
thread_num:[IN],total process data thread num
|
||||
filepath:[IN], conf file path,read use MESA_prof_load;
|
||||
Return:
|
||||
0:succes
|
||||
<0:error
|
||||
***************************************************************************/
|
||||
int mirror_stream_init(int thread_num, const char* filepath);
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Description:call this function before send a new session data
|
||||
Paraments:
|
||||
thread_seq:[IN], thread seq
|
||||
addr:[IN],addr of the session to be send
|
||||
pme:[OUT],buffer alive in the session,deliver malloc and free *pme;
|
||||
Return:
|
||||
0:succes
|
||||
<0:error
|
||||
***************************************************************************/
|
||||
int mirror_stream_open(int thread_id, const struct tfe_stream_addr* addr,void** pme);
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Description:call this function when send session data
|
||||
Paraments:
|
||||
cur_dir:[IN], direction of current data,definition in DELIVER_DIR_***
|
||||
thread_seq:[IN],thread seq
|
||||
buflen:[IN],buffer len,tcp payload len;
|
||||
buf:[IN],data fo the session to be send,tcp payload
|
||||
pme:[OUT]
|
||||
Return:
|
||||
0:succes
|
||||
<0:error
|
||||
***************************************************************************/
|
||||
int mirror_stream_write(int cur_dir,const unsigned char * data, size_t len, void** pme,int thread_id);
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Description:call this function after send all of session data
|
||||
Paraments:
|
||||
thread_seq:[IN], thread seq
|
||||
pme:[OUT]; free *pme when deliver_end()
|
||||
Return:
|
||||
0:succes
|
||||
<0:error
|
||||
***************************************************************************/
|
||||
void mirror_stream_close(void** pme, int thread_id);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
#ifndef DELIVER_PRIVATE_H
|
||||
#define DELIVER_PRIVATE_H
|
||||
|
||||
#include <mirror_stream.h>
|
||||
#include <MESA/field_stat2.h>
|
||||
|
||||
#ifndef MAX_THREAD_NUM
|
||||
#define MAX_THREAD_NUM 128
|
||||
#endif
|
||||
|
||||
#define DELIVER_DEFAULT_MTU 1500
|
||||
#define DELIVER_SENDPKT_BUFLEN 2048
|
||||
|
||||
//runtime log
|
||||
#define DELIVER_MODULE_INIT "mirror_stream_init"
|
||||
#define DELIVER_MODULE_SENDPKT "mirror_stream_sendpkt"
|
||||
#define DELIVER_SENDPKT_START "sendpkt_start"
|
||||
#define DELIVER_SENDPKT_DEBUG "sendpkt_debug"
|
||||
#define DELIVER_RECVPKT_DEBUG "recvpkt_debug"
|
||||
#define DELIVER_SENDPKT_END "sendpkt_end"
|
||||
|
||||
#define DELIVER_FLAG_SENDPKT 0
|
||||
#define DELIVER_FLAG_RECVPKT 1
|
||||
#define DELIVER_FLAG_ENT 2
|
||||
|
||||
//init profile info
|
||||
#define DELIVER_CARDNAME_LEN 128
|
||||
#define DELIVER_CONF_MAXLEN 1024
|
||||
#define DELIVER_CONF_MODE "DELIVER"
|
||||
#define DELIVER_RCV_MAC "reveiver_mac"
|
||||
|
||||
#define PROTO_TYPE_TCP 6
|
||||
#define PROTO_TYPE_UDP 17
|
||||
|
||||
|
||||
//lqueue info
|
||||
#define DELIVER_THREAD_SAFE 1
|
||||
#define DELIVER_USLEEP_TIME 10
|
||||
#define DELIVER_LQUEUE_MAXNUM 100000
|
||||
|
||||
|
||||
//send pkt
|
||||
#define DELIVER_MACADDR_LEN 6
|
||||
#define DELIVER_MACADDR_STR_LEN 18
|
||||
#define DELIVER_ETHER_LEN 14
|
||||
#define TCPHDR_DEFAULT_LEN 20
|
||||
|
||||
//fs2 info
|
||||
#define FS2_COLUMN_NUM 5
|
||||
#define FS2_APPNAME "DELIVER"
|
||||
|
||||
|
||||
enum deliver_fs_colume
|
||||
{
|
||||
FS2_COLUME_RECVPKT=0,
|
||||
FS2_COLUME_RECVBYTE,
|
||||
FS2_COLUME_SENDPKT,
|
||||
FS2_COLUME_SENDBYTE,
|
||||
FS2_COLUME_ERROR,
|
||||
};
|
||||
|
||||
|
||||
struct deliver_fs2_info
|
||||
{
|
||||
screen_stat_handle_t handler;
|
||||
int column_id[FS2_COLUMN_NUM];
|
||||
unsigned long long column_value[MAX_THREAD_NUM][FS2_COLUMN_NUM];
|
||||
};
|
||||
|
||||
struct deliver_comm_info
|
||||
{
|
||||
int threadnum;
|
||||
void* logger;
|
||||
};
|
||||
|
||||
|
||||
struct deliver_pkt_info
|
||||
{
|
||||
int dir;
|
||||
unsigned int seq; //host order
|
||||
unsigned int ack; //host order
|
||||
unsigned int len; //host order,tcp payload len
|
||||
unsigned short ipid; //host order
|
||||
unsigned short win; //host order
|
||||
unsigned char flag;
|
||||
unsigned char ttl;
|
||||
|
||||
};
|
||||
|
||||
struct deliver_session_info
|
||||
{
|
||||
int recv_pkt;
|
||||
int send_pkt;
|
||||
long long recv_byte;
|
||||
long long send_byte;
|
||||
};
|
||||
|
||||
|
||||
struct deliver_pme_info
|
||||
{
|
||||
unsigned char dst_macaddr[DELIVER_MACADDR_LEN];
|
||||
const struct tfe_stream_addr* addr_info;
|
||||
struct deliver_pkt_info pkt_info;
|
||||
struct deliver_session_info session_info;
|
||||
};
|
||||
|
||||
struct deliver_recver_info
|
||||
{
|
||||
unsigned char dst_macaddr[DELIVER_MACADDR_LEN];
|
||||
};
|
||||
|
||||
struct deliver_sendpkt_info
|
||||
{
|
||||
int mtu;
|
||||
int thread_num;
|
||||
int receiver_num;
|
||||
struct ifreq ifr;
|
||||
int* send_socket;
|
||||
char senddevice[DELIVER_CARDNAME_LEN];
|
||||
unsigned char src_macaddr[DELIVER_MACADDR_LEN];
|
||||
struct deliver_recver_info* receiver_info;
|
||||
};
|
||||
|
||||
struct deliver_globle_info
|
||||
{
|
||||
int deliver_switch;
|
||||
char *fs2_name[FS2_COLUMN_NUM];
|
||||
unsigned char* sendbuf[MAX_THREAD_NUM];
|
||||
struct deliver_comm_info comminfo;
|
||||
struct deliver_sendpkt_info sendinfo;
|
||||
struct deliver_fs2_info fs2info;
|
||||
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
#ifndef DELIVER_SENDPKT_H
|
||||
#define DELIVER_SENDPKT_H
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
|
||||
#ifndef ETHER_ADDR_LEN
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#endif
|
||||
|
||||
#define ARPHRD_ETHER 1 /* ethernet hardware format */
|
||||
|
||||
#define SENDPACKET_ETH_H 0xe /* Etherner header: 14 bytes */
|
||||
#define SENDPACKET_IP_H 0x14 /* IP header: 20 bytes */
|
||||
#define SENDPACKET_TCP_H 0x14 /* TCP header: 20 bytes */
|
||||
|
||||
|
||||
struct mesa_ethernet_hdr
|
||||
{
|
||||
unsigned char ether_dhost[ETHER_ADDR_LEN]; /* destination ethernet address */
|
||||
unsigned char ether_shost[ETHER_ADDR_LEN]; /* source ethernet address */
|
||||
unsigned short ether_type; /* packet type ID */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct mesa_ip4_hdr
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
u_int8_t ip_hl:4, /* header length */
|
||||
ip_v:4; /* version */
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t ip_v:4, /* version */
|
||||
ip_hl:4; /* header length */
|
||||
#else
|
||||
#error "Please check <endian.h>"
|
||||
#endif
|
||||
u_int8_t ip_tos; /* type of service */
|
||||
u_int16_t ip_len; /* total length */
|
||||
u_int16_t ip_id; /* identification */
|
||||
u_int16_t ip_off;
|
||||
u_int8_t ip_ttl; /* time to live */
|
||||
u_int8_t ip_p; /* protocol */
|
||||
u_int16_t ip_sum; /* checksum */
|
||||
struct in_addr ip_src, ip_dst; /* source and dest address */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IPv6 packet header prototype, add by LiJia 2012-03-19.
|
||||
*/
|
||||
struct mesa_ip6_hdr
|
||||
{
|
||||
u_int8_t ip6_flags[4]; /* version, traffic-class, flow-label */
|
||||
u_int16_t ip6_payload_len; /* payload length, not contain header */
|
||||
u_int8_t ip6_nxt_hdr; /* next header, same as protocol in IPv4 */
|
||||
u_int8_t ip6_hop; /* hop limit, same as TTL in IPv4 */
|
||||
struct in6_addr ip6_src; /* source address */
|
||||
struct in6_addr ip6_dst; /* dest address */
|
||||
};
|
||||
|
||||
|
||||
#ifndef TH_FIN
|
||||
#define TH_FIN 0x01
|
||||
#endif
|
||||
#ifndef TH_SYN
|
||||
#define TH_SYN 0x02
|
||||
#endif
|
||||
#ifndef TH_RST
|
||||
#define TH_RST 0x04
|
||||
#endif
|
||||
#ifndef TH_PUSH
|
||||
#define TH_PUSH 0x08
|
||||
#endif
|
||||
#ifndef TH_ACK
|
||||
#define TH_ACK 0x10
|
||||
#endif
|
||||
#ifndef TH_URG
|
||||
#define TH_URG 0x20
|
||||
#endif
|
||||
|
||||
|
||||
struct mesa_tcp_hdr
|
||||
{
|
||||
u_int16_t th_sport; /* source port */
|
||||
u_int16_t th_dport; /* destination port */
|
||||
u_int32_t th_seq; /* sequence number */
|
||||
u_int32_t th_ack; /* acknowledgement number */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
u_int8_t th_x2:4, /* (unused) */
|
||||
th_off:4; /* data offset */
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t th_off:4, /* data offset */
|
||||
th_x2:4; /* (unused) */
|
||||
#else
|
||||
#error "Please check <endian.h>"
|
||||
#endif
|
||||
u_int8_t th_flags; /* control flags */
|
||||
u_int16_t th_win; /* window */
|
||||
u_int16_t th_sum; /* checksum */
|
||||
u_int16_t th_urp; /* urgent pointer */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* UDP packet header prototype.
|
||||
*/
|
||||
struct mesa_udp_hdr
|
||||
{
|
||||
u_int16_t uh_sport; /* soure port */
|
||||
u_int16_t uh_dport; /* destination port */
|
||||
u_int16_t uh_ulen; /* length */
|
||||
u_int16_t uh_sum; /* checksum */
|
||||
};
|
||||
|
||||
unsigned int deliver_rand(void);
|
||||
unsigned int deliver_rand_range(unsigned int start, unsigned int end);
|
||||
int deliver_get_dev_mac(const char *device, unsigned char mac[6]);
|
||||
int deliver_mac_pton(const char *str, int delim, char *mac);
|
||||
int deliver_do_checksum(unsigned char *buf, int protocol, int len);
|
||||
int deliver_build_ethernet(unsigned char *dst, unsigned char *src, unsigned short type,
|
||||
const unsigned char *payload, int payload_s, unsigned char *buf);
|
||||
int deliver_build_ethhdr(unsigned char *dst, unsigned char *src, unsigned short type,unsigned char *buf);
|
||||
int deliver_build_ipv6(unsigned char traffic_class, unsigned int flow_lable,
|
||||
unsigned short len, unsigned char next_header, unsigned char hop,
|
||||
const struct in6_addr *src, const struct in6_addr *dst,
|
||||
const unsigned char *payload, int payload_s, unsigned char *buf);
|
||||
int deliver_build_ipv4(unsigned short carry_layer_len, unsigned char tos, unsigned short id,
|
||||
unsigned short frag, unsigned char ttl, unsigned char prot, unsigned int src, unsigned int dst,
|
||||
const unsigned char *payload,int payload_s, unsigned char *buf);
|
||||
int deliver_build_tcp(unsigned short sp, unsigned short dp, unsigned int seq, unsigned int ack,
|
||||
unsigned char th_flags, unsigned short win, unsigned short urg,
|
||||
const unsigned char *payload, int payload_s, unsigned char *buf);
|
||||
|
||||
#endif
|
||||
|
||||
84
plugin/business/decrypt-mirroring/include/traffic_mirror.h
Normal file
84
plugin/business/decrypt-mirroring/include/traffic_mirror.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <netinet/ether.h>
|
||||
#include <MESA/Maat_rule.h>
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
enum traffic_mirror_ethdev_type
|
||||
{
|
||||
TRAFFIC_MIRROR_ETHDEV_AF_PACKET,
|
||||
TRAFFIC_MIRROR_ETHDEV_MARSIO
|
||||
};
|
||||
|
||||
enum traffic_mirror_target_addr_type
|
||||
{
|
||||
TRAFFIC_MIRROR_TARGET_BY_VLAN_ID,
|
||||
TRAFFIC_MIRROR_TARGET_BY_ETHER_ADDR,
|
||||
};
|
||||
|
||||
struct traffic_mirror_instance
|
||||
{
|
||||
void * logger;
|
||||
unsigned int nr_threads;
|
||||
|
||||
Maat_feather_t maat_feather;
|
||||
int policy_table_id;
|
||||
int profile_table_id;
|
||||
|
||||
/* DEFAULT MAC ADDRESS, IN VLAN MODE */
|
||||
char default_ether_addr_src;
|
||||
char default_ether_addr_dst;
|
||||
};
|
||||
|
||||
struct policy_table_ex_data
|
||||
{
|
||||
unsigned int atomic_refcnt;
|
||||
unsigned int enable;
|
||||
unsigned int profile_id;
|
||||
};
|
||||
|
||||
struct profile_table_ex_data
|
||||
{
|
||||
unsigned int atomic_refcnt;
|
||||
|
||||
enum traffic_mirror_target_addr_type target_addr_type;
|
||||
unsigned int nr_targets;
|
||||
|
||||
/* Target VLANS */
|
||||
unsigned int * vlans;
|
||||
struct ether_addr * ether_addrs;
|
||||
};
|
||||
|
||||
struct traffic_mirror_ethdev
|
||||
{
|
||||
/* PUBLIC */
|
||||
char str_device[TFE_SYMBOL_MAX];
|
||||
enum traffic_mirror_ethdev_type type;
|
||||
|
||||
unsigned int mtu;
|
||||
unsigned int en_offload_vlan;
|
||||
unsigned int en_offload_ip_cksum;
|
||||
unsigned int en_offload_tcp_cksum;
|
||||
|
||||
/* PRIVATE, FOR PCAP */
|
||||
pcap_t * pcap_device_handle;
|
||||
char local_ether_addr[6];
|
||||
|
||||
/* FUNCTIONS */
|
||||
int (*fn_inject)(struct traffic_mirror_ethdev *, const char * pkt, unsigned int pktlen);
|
||||
void (*fn_destroy)(struct traffic_mirror_ethdev * ethdev);
|
||||
};
|
||||
|
||||
struct traffic_mirror_ethdev * traffic_mirror_ethdev_pcap_create(const char * str_ethdev, void * logger);
|
||||
void traffic_mirror_ethdev_destroy(struct traffic_mirror_ethdev * ethdev);
|
||||
int traffic_mirror_ethdev_inject(struct traffic_mirror_ethdev * ethdev, const char * pkt, unsigned int pktlen);
|
||||
|
||||
|
||||
struct traffic_mirror_rebuild * traffic_mirror_rebuild_create(struct tfe_stream_addr * addr,
|
||||
struct profile_table_ex_data * 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);
|
||||
void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance,
|
||||
const char * data, unsigned int datalen, enum tfe_conn_dir dir);
|
||||
void traffic_mirror_rebuild_farewell(struct traffic_mirror_rebuild * instance);
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#include "mirror_stream.h"
|
||||
#include <tfe_stream.h>
|
||||
#include <tfe_plugin.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
extern unsigned int tfe_proxy_get_work_thread_count(void);
|
||||
|
||||
int decrypt_mirror_init(struct tfe_proxy * proxy)
|
||||
{
|
||||
const char* filepath="./conf/tfe/decrypt_mirror.conf";
|
||||
int ret=0;
|
||||
int thread_num = tfe_proxy_get_work_thread_count();
|
||||
ret=mirror_stream_init(thread_num, filepath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int decrypt_mirror_on_open_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_conn_dir dir, void ** pme)
|
||||
{
|
||||
int ret=0;
|
||||
ret=mirror_stream_open(thread_id, stream->addr, pme);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum tfe_stream_action decrypt_mirror_on_data_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme)
|
||||
{
|
||||
mirror_stream_write(dir, data,len, pme, thread_id);
|
||||
return ACTION_FORWARD_DATA;
|
||||
}
|
||||
|
||||
void decrypt_mirror_on_close_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_stream_close_reason reason, void ** pme)
|
||||
{
|
||||
mirror_stream_close(pme, thread_id);
|
||||
return;
|
||||
}
|
||||
|
||||
void decrypt_mirror_deinit(struct tfe_proxy * proxy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct tfe_plugin decrypt_mirror_spec={
|
||||
.symbol=NULL,
|
||||
.type = TFE_PLUGIN_TYPE_BUSINESS,
|
||||
.on_init = decrypt_mirror_init,
|
||||
.on_deinit = decrypt_mirror_deinit,
|
||||
.on_open = decrypt_mirror_on_open_cb,
|
||||
.on_data = decrypt_mirror_on_data_cb,
|
||||
.on_close = decrypt_mirror_on_close_cb};
|
||||
TFE_PLUGIN_REGISTER(decrypt_mirror,decrypt_mirror_spec)
|
||||
|
||||
|
||||
436
plugin/business/decrypt-mirroring/src/entry.cpp
Normal file
436
plugin/business/decrypt-mirroring/src/entry.cpp
Normal file
@@ -0,0 +1,436 @@
|
||||
#include <assert.h>
|
||||
#include <cjson/cJSON.h>
|
||||
#include <tfe_stream.h>
|
||||
#include <tfe_plugin.h>
|
||||
#include <tfe_proxy.h>
|
||||
#include "../include/traffic_mirror.h"
|
||||
|
||||
extern Maat_feather_t g_business_maat;
|
||||
|
||||
struct traffic_mirror_me
|
||||
{
|
||||
struct profile_table_ex_data * profile_ex_data;
|
||||
struct traffic_mirror_rebuild * rebuild_ctx;
|
||||
};
|
||||
|
||||
struct traffic_mirror_instance __g_traffic_mirror_instance;
|
||||
struct traffic_mirror_instance * g_traffic_mirror_instance = &__g_traffic_mirror_instance;
|
||||
|
||||
void policy_table_ex_data_free(struct policy_table_ex_data * object)
|
||||
{
|
||||
if ((__sync_sub_and_fetch(&object->atomic_refcnt, 1) == 0)) free(object);
|
||||
}
|
||||
|
||||
void policy_table_ex_data_dup_cb(int table_id, MAAT_PLUGIN_EX_DATA * to,
|
||||
MAAT_PLUGIN_EX_DATA * from, long argl, void * argp)
|
||||
{
|
||||
struct policy_table_ex_data * ex_data = (struct policy_table_ex_data *)from;
|
||||
__sync_add_and_fetch(&ex_data->atomic_refcnt, 1);
|
||||
*to = (void *)ex_data;
|
||||
}
|
||||
|
||||
void policy_table_ex_data_free_cb(int table_id, MAAT_PLUGIN_EX_DATA * ad, long argl, void * argp)
|
||||
{
|
||||
struct policy_table_ex_data * ex_data = (struct policy_table_ex_data *)argp;
|
||||
policy_table_ex_data_free(ex_data);
|
||||
}
|
||||
|
||||
void policy_table_ex_data_new_cb(int table_id, const char * key, const char * table_line,
|
||||
MAAT_PLUGIN_EX_DATA * ad, long argl, void * argp)
|
||||
{
|
||||
struct traffic_mirror_instance * instance = (struct traffic_mirror_instance *) argp;
|
||||
assert(instance != nullptr && instance->logger != nullptr);
|
||||
|
||||
char * str_json = NULL;
|
||||
cJSON * json_root = NULL;
|
||||
cJSON * json_subroot = NULL;
|
||||
cJSON * json_item = NULL;
|
||||
|
||||
struct policy_table_ex_data * ex_data = NULL;
|
||||
|
||||
unsigned int user_region_offset;
|
||||
unsigned int user_region_len;
|
||||
unsigned int policy_enable;
|
||||
unsigned int policy_profile_id;
|
||||
|
||||
int result = Maat_helper_read_column(table_line, 7, &user_region_offset, &user_region_len);
|
||||
if (unlikely(result < 0))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "Failed at get policy table's user region.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
str_json = ALLOC(char, user_region_len + 1);
|
||||
memcpy(str_json, table_line + user_region_offset, user_region_len);
|
||||
|
||||
json_root = cJSON_Parse(str_json);
|
||||
if (unlikely(!json_root))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at parsing user region as JSON format.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
json_subroot = cJSON_GetObjectItem(json_root, "decrypt_mirror");
|
||||
if (unlikely(!json_subroot))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid format, decrypt_mirror is not defined.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ex_data = ALLOC(struct policy_table_ex_data, 1);
|
||||
ex_data->atomic_refcnt = 1;
|
||||
ex_data->enable = 0;
|
||||
ex_data->profile_id = 0;
|
||||
|
||||
json_item = cJSON_GetObjectItem(json_subroot, "enable");
|
||||
if (unlikely(!json_item || cJSON_IsNumber(json_item)))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, decrypt_mirror->enable not existed or invalid type.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ex_data->enable = json_item->valueint;
|
||||
if (!ex_data->enable)
|
||||
{
|
||||
goto success;
|
||||
}
|
||||
|
||||
json_item = cJSON_GetObjectItem(json_subroot, "mirror_profile");
|
||||
if (unlikely(!json_item || cJSON_IsNumber(json_item)))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, decrypt_mirror->mirror_profile not existed or invalid type.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
success:
|
||||
TFE_LOG_DEBUG(instance->logger, "table line in PXY_INTERCEPT_COMPILE added: %s", table_line);
|
||||
*ad = ex_data;
|
||||
ex_data = nullptr;
|
||||
goto out;
|
||||
|
||||
ignore:
|
||||
TFE_LOG_ERROR(instance->logger, "table line in PXY_INTERCEPT_COMPILE ignored: %s", table_line);
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (ex_data) policy_table_ex_data_free(ex_data);
|
||||
if (json_root) cJSON_Delete(json_root);
|
||||
if (str_json) free(str_json);
|
||||
}
|
||||
|
||||
void profile_table_ex_data_dup_cb(int table_id, MAAT_PLUGIN_EX_DATA * to,
|
||||
MAAT_PLUGIN_EX_DATA * from, long argl, void * argp)
|
||||
{
|
||||
struct profile_table_ex_data * ex_data = (struct profile_table_ex_data *)from;
|
||||
__sync_add_and_fetch(&ex_data->atomic_refcnt, 1);
|
||||
*to = (void *)ex_data;
|
||||
}
|
||||
|
||||
void profile_table_ex_data_free(struct profile_table_ex_data * object)
|
||||
{
|
||||
if ((__sync_sub_and_fetch(&object->atomic_refcnt, 1) == 0)) free(object);
|
||||
}
|
||||
|
||||
void profile_table_ex_data_free_cb(int table_id, MAAT_PLUGIN_EX_DATA * ad, long argl, void * argp)
|
||||
{
|
||||
struct profile_table_ex_data * ex_data = (struct profile_table_ex_data *)ad;
|
||||
profile_table_ex_data_free(ex_data);
|
||||
}
|
||||
|
||||
void profile_table_ex_data_new_cb(int table_id, const char * key, const char * table_line,
|
||||
MAAT_PLUGIN_EX_DATA * ad, long argl, void * argp)
|
||||
{
|
||||
struct traffic_mirror_instance * instance = (struct traffic_mirror_instance *) argp;
|
||||
assert(instance != nullptr && instance->logger != nullptr);
|
||||
|
||||
char * str_json = NULL;
|
||||
cJSON * json_root = NULL;
|
||||
cJSON * json_item = NULL;
|
||||
|
||||
struct profile_table_ex_data * ex_data = NULL;
|
||||
|
||||
unsigned int addr_list_offset;
|
||||
unsigned int addr_list_len;
|
||||
|
||||
int result = Maat_helper_read_column(table_line, 3, &addr_list_offset, &addr_list_len);
|
||||
if (unlikely(result < 0))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "Failed at get profile table's addrlist.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
str_json = ALLOC(char, addr_list_len + 1);
|
||||
memcpy(str_json, table_line + addr_list_offset, addr_list_len);
|
||||
|
||||
json_root = cJSON_Parse(str_json);
|
||||
if (unlikely(!json_root))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at parsing addrlist as JSON format.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ex_data = ALLOC(struct profile_table_ex_data, 1);
|
||||
ex_data->atomic_refcnt = 1;
|
||||
|
||||
json_item = cJSON_GetObjectItem(json_root, "vlan");
|
||||
if (json_item)
|
||||
{
|
||||
if (unlikely(!cJSON_IsArray(json_item)))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, mirror_profile->vlan is not a array.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ex_data->target_addr_type = TRAFFIC_MIRROR_TARGET_BY_VLAN_ID;
|
||||
ex_data->nr_targets = cJSON_GetArraySize(json_item);
|
||||
ex_data->vlans = (unsigned int *)calloc(ex_data->nr_targets, sizeof(ex_data->vlans[0]));
|
||||
|
||||
cJSON * element;
|
||||
unsigned int iter = 0;
|
||||
cJSON_ArrayForEach(element, json_item)
|
||||
{
|
||||
if (unlikely(!cJSON_IsNumber(element)))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, "
|
||||
"elements in mirror_profile->vlan is not a number");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ex_data->vlans[iter++] = element->valueint;
|
||||
}
|
||||
|
||||
assert(iter + 1 == ex_data->nr_vlans);
|
||||
goto success;
|
||||
}
|
||||
|
||||
json_item = cJSON_GetObjectItem(json_item, "mac");
|
||||
if (json_item)
|
||||
{
|
||||
if (unlikely(!cJSON_IsArray(json_item)))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, mirror_profile->mac is not a array.");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ex_data->target_addr_type = TRAFFIC_MIRROR_TARGET_BY_ETHER_ADDR;
|
||||
ex_data->nr_ether_addrs = cJSON_GetArraySize(json_item);
|
||||
ex_data->ether_addrs = (struct ether_addr *)calloc(ex_data->nr_ether_addrs, sizeof(ex_data->ether_addrs[0]));
|
||||
|
||||
cJSON * element;
|
||||
unsigned int iter;
|
||||
|
||||
cJSON_ArrayForEach(element, json_item)
|
||||
{
|
||||
if (unlikely(!cJSON_IsString(element)))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, "
|
||||
"elements in mirror_profile->mac is not a string");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
struct ether_addr * result = ether_aton_r(element->valuestring, &ex_data->ether_addrs[iter++]);
|
||||
if (unlikely(!result))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "invalid JSON, "
|
||||
"elements in mirror_profile->mac is not a valid ether address");
|
||||
goto ignore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
success:
|
||||
*ad = (void *)ex_data;
|
||||
ex_data = nullptr;
|
||||
|
||||
TFE_LOG_DEBUG(instance->logger, "table line in PXY_PROFILE_TRAFFIC_MIRROR added: %s", table_line);
|
||||
goto out;
|
||||
|
||||
ignore:
|
||||
TFE_LOG_ERROR(instance->logger, "table line in PXY_PROFILE_TRAFFIC_MIRROR ignored: %s", table_line);
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (ex_data)
|
||||
{
|
||||
profile_table_ex_data_free(ex_data);
|
||||
}
|
||||
|
||||
if (str_json)
|
||||
{
|
||||
free(str_json);
|
||||
}
|
||||
|
||||
if (json_root)
|
||||
{
|
||||
cJSON_Delete(json_root);
|
||||
}
|
||||
}
|
||||
|
||||
int traffic_mirror_init(struct tfe_proxy * proxy)
|
||||
{
|
||||
int result = 0;
|
||||
struct traffic_mirror_instance * instance = g_traffic_mirror_instance;
|
||||
|
||||
/* INIT DECRYPT MIRROR INSTANCE */
|
||||
instance->maat_feather = g_business_maat;
|
||||
instance->logger = tfe_proxy_get_error_logger();
|
||||
instance->nr_threads = tfe_proxy_get_work_thread_count();
|
||||
|
||||
/* REGISTER MAAT FEATHER */
|
||||
instance->policy_table_id = Maat_table_register(instance->maat_feather, "PXY_INTERCEPT_COMPILE");
|
||||
if (unlikely(instance->policy_table_id < 0))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at register table PXY_INTERCEPT_COMPILE, ret = %d",
|
||||
instance->policy_table_id); goto errout;
|
||||
}
|
||||
|
||||
instance->profile_table_id = Maat_table_register(instance->maat_feather, "PXY_PROFILE_TRAFFIC_MIRROR");
|
||||
if (unlikely(instance->profile_table_id < 0))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at register table PXY_PROFILE_TRAFFIC_MIRROR, ret = %d",
|
||||
instance->profile_table_id); goto errout;
|
||||
}
|
||||
|
||||
result = Maat_plugin_EX_register(instance->maat_feather, instance->policy_table_id,
|
||||
policy_table_ex_data_new_cb, policy_table_ex_data_free_cb, policy_table_ex_data_dup_cb,
|
||||
nullptr, 0, instance);
|
||||
|
||||
if(unlikely(result < 0))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at Maat_plugin_EX_register(PXY_INTERCEPT_COMPILE), "
|
||||
"table_id = %d, ret = %d", instance->policy_table_id, result);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
result = Maat_plugin_EX_register(instance->maat_feather, instance->policy_table_id,
|
||||
profile_table_ex_data_new_cb, profile_table_ex_data_free_cb, policy_table_ex_data_dup_cb,
|
||||
nullptr, 0, instance);
|
||||
|
||||
if (unlikely(result < 0))
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at Maat_plugin_EX_register(PXY_PROFILE_TRAFFIC_MIRROR), "
|
||||
"table_id = %d, ret = %d", instance->policy_table_id, result);
|
||||
}
|
||||
|
||||
errout:
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
assert(instance != NULL);
|
||||
assert(cmsg != NULL);
|
||||
|
||||
char str_policy_id[TFE_SYMBOL_MAX];
|
||||
char str_profile_id[TFE_SYMBOL_MAX];
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TFE_LOG_ERROR(instance->logger, "failed at getting policy %s's EXDATA, detach the stream", str_policy_id);
|
||||
goto detach;
|
||||
}
|
||||
|
||||
if (!policy_ex_data->enable)
|
||||
{
|
||||
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 (!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, profile_ex_data, NULL);
|
||||
me->profile_ex_data = profile_ex_data;
|
||||
|
||||
/* profile_ex_data's ownership is transfer to me */
|
||||
profile_ex_data = NULL;
|
||||
traffic_mirror_rebuild_handshake(me->rebuild_ctx);
|
||||
|
||||
*pme = (void *)me;
|
||||
return ACTION_FORWARD_DATA;
|
||||
|
||||
detach:
|
||||
if (me)
|
||||
{
|
||||
free(me);
|
||||
}
|
||||
|
||||
if (policy_ex_data)
|
||||
{
|
||||
policy_table_ex_data_free(policy_ex_data);
|
||||
}
|
||||
|
||||
if (profile_ex_data)
|
||||
{
|
||||
profile_table_ex_data_free(profile_ex_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,
|
||||
enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme)
|
||||
{
|
||||
struct traffic_mirror_me * me = (struct traffic_mirror_me *)(*pme);
|
||||
traffic_mirror_rebuild_data(me->rebuild_ctx, (const char *)data, (size_t)len, dir);
|
||||
}
|
||||
|
||||
void traffic_mirror_on_close_cb(const struct tfe_stream * stream, unsigned int thread_id,
|
||||
enum tfe_stream_close_reason reason, void ** pme)
|
||||
{
|
||||
struct traffic_mirror_me * me = (struct traffic_mirror_me *)(*pme);
|
||||
traffic_mirror_rebuild_farewell(me->rebuild_ctx);
|
||||
traffic_mirror_rebuild_destroy(me->rebuild_ctx);
|
||||
profile_table_ex_data_free(me->profile_ex_data);
|
||||
|
||||
free(me);
|
||||
*pme = NULL;
|
||||
}
|
||||
|
||||
void traffic_mirror_deinit(struct tfe_proxy * proxy){}
|
||||
|
||||
struct tfe_plugin traffic_mirror_plugin_desc =
|
||||
{
|
||||
.symbol= "traffic_mirror",
|
||||
.type = TFE_PLUGIN_TYPE_BUSINESS,
|
||||
.on_init = traffic_mirror_init,
|
||||
.on_deinit = traffic_mirror_deinit,
|
||||
.on_open = traffic_mirror_on_open_cb,
|
||||
.on_data = traffic_mirror_on_data_cb,
|
||||
.on_close = traffic_mirror_on_close_cb
|
||||
};
|
||||
|
||||
TFE_PLUGIN_REGISTER(traffic_mirror, traffic_mirror_plugin_desc)
|
||||
109
plugin/business/decrypt-mirroring/src/ethdev.cpp
Normal file
109
plugin/business/decrypt-mirroring/src/ethdev.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <unistd.h>
|
||||
#include <pcap/pcap.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <tfe_utils.h>
|
||||
#include <tfe_proxy.h>
|
||||
|
||||
struct traffic_mirror_ethdev_pkt_desc{};
|
||||
struct traffic_mirror_ethdev_pkt_desc_pcap
|
||||
{
|
||||
unsigned int pktlen;
|
||||
char * pkt;
|
||||
};
|
||||
|
||||
static int pcap_ethdev_inject(struct traffic_mirror_ethdev * ethdev, const char * pkt, unsigned int pktlen)
|
||||
{
|
||||
return pcap_sendpacket(ethdev->pcap_device_handle, (const u_char *)pkt, pktlen);
|
||||
}
|
||||
|
||||
static void pcap_ethdev_destroy(struct traffic_mirror_ethdev * ethdev)
|
||||
{
|
||||
pcap_close(ethdev->pcap_device_handle);
|
||||
return free(ethdev);
|
||||
}
|
||||
|
||||
void traffic_mirror_ethdev_destroy(struct traffic_mirror_ethdev * ethdev)
|
||||
{
|
||||
ethdev->fn_destroy(ethdev);
|
||||
}
|
||||
|
||||
int traffic_mirror_ethdev_inject(struct traffic_mirror_ethdev * ethdev, const char * pkt, unsigned int pktlen)
|
||||
{
|
||||
return ethdev->fn_inject(ethdev, pkt, pktlen);
|
||||
}
|
||||
|
||||
struct traffic_mirror_ethdev * traffic_mirror_ethdev_pcap_create(const char * str_ethdev, void * logger)
|
||||
{
|
||||
struct traffic_mirror_ethdev * ethdev = ALLOC(struct traffic_mirror_ethdev, 1);
|
||||
char pcap_errbuf[PCAP_ERRBUF_SIZE] = {};
|
||||
|
||||
int fd = 0;
|
||||
struct ifreq if_req{};
|
||||
|
||||
ethdev->en_offload_ip_cksum = 0;
|
||||
ethdev->en_offload_tcp_cksum = 0;
|
||||
ethdev->en_offload_vlan = 0;
|
||||
|
||||
/* open the device by pcap */
|
||||
ethdev->pcap_device_handle = pcap_open_live(str_ethdev, 0, 0, 0, pcap_errbuf);
|
||||
if (!ethdev->pcap_device_handle)
|
||||
{
|
||||
TFE_LOG_ERROR(logger, "failed at pcap_open_live(), device = %s: %s", str_ethdev, pcap_errbuf);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* local ether address */
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(fd < 0)
|
||||
{
|
||||
TFE_LOG_ERROR(logger, "failed at create socket: %s", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
memset(&if_req, 0, sizeof(if_req));
|
||||
strncpy(if_req.ifr_ifrn.ifrn_name, str_ethdev, IFNAMSIZ - 1);
|
||||
|
||||
if(ioctl(fd, SIOCGIFHWADDR, &if_req) < 0)
|
||||
{
|
||||
TFE_LOG_ERROR(logger, "failed at read hwaddr of device %s: %s", str_ethdev, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
ethdev->local_ether_addr[i] = if_req.ifr_ifru.ifru_hwaddr.sa_data[i];
|
||||
}
|
||||
|
||||
/* MTU */
|
||||
memset(&if_req, 0, sizeof(if_req));
|
||||
strncpy(if_req.ifr_ifrn.ifrn_name, str_ethdev, IFNAMSIZ - 1);
|
||||
|
||||
if (ioctl(fd, SIOCGIFMTU, &if_req) < 0)
|
||||
{
|
||||
TFE_LOG_ERROR(logger, "failed at read mtu of device %s: %s", str_ethdev, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ethdev->mtu = if_req.ifr_ifru.ifru_mtu;
|
||||
strncpy(ethdev->str_device, str_ethdev, sizeof(ethdev->str_device) - 1);
|
||||
|
||||
TFE_LOG_INFO(logger, "traffic mirror device %s (pcap mode): %02X:%02X:%02X:%02X:%02X:%02X, mtu=%u",
|
||||
ethdev->str_device, ethdev->local_ether_addr[0], ethdev->local_ether_addr[1],
|
||||
ethdev->local_ether_addr[2], ethdev->local_ether_addr[3],
|
||||
ethdev->local_ether_addr[4], ethdev->local_ether_addr[5], ethdev->mtu);
|
||||
|
||||
ethdev->fn_inject = pcap_ethdev_inject;
|
||||
ethdev->fn_destroy = pcap_ethdev_destroy;
|
||||
|
||||
close(fd);
|
||||
return ethdev;
|
||||
|
||||
errout:
|
||||
if (fd > 0) close(fd);
|
||||
if (ethdev->pcap_device_handle) pcap_close(ethdev->pcap_device_handle);
|
||||
if (ethdev) FREE(ðdev);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1,808 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <MESA/MESA_prof_load.h>
|
||||
#include <MESA/MESA_handle_logger.h>
|
||||
#include <MESA/field_stat2.h>
|
||||
|
||||
#include <mirror_stream.h>
|
||||
#include <mirror_stream_inl.h>
|
||||
#include <sendpkt-inl.h>
|
||||
|
||||
int g_deliver_version_VERSION_20180718;
|
||||
|
||||
struct deliver_globle_info g_deliver_globle_info;
|
||||
|
||||
|
||||
|
||||
|
||||
int deliver_set_filestate2(int thread_seq,int colum_index,int value)
|
||||
{
|
||||
if(thread_seq>=g_deliver_globle_info.comminfo.threadnum)
|
||||
{
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,"deliver_set_filestate2","thread_seq:%d,thread_num:%d",thread_seq,g_deliver_globle_info.comminfo.threadnum);
|
||||
}
|
||||
|
||||
g_deliver_globle_info.fs2info.column_value[thread_seq][colum_index]+=value;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int deliver_filestate2_init(char* filepath)
|
||||
{
|
||||
int i=0;
|
||||
int trans_switch=0;
|
||||
int value=1;
|
||||
unsigned int fs2_sport;
|
||||
char fs2_filename[DELIVER_CONF_MAXLEN]={0};
|
||||
char fs2_sip[DELIVER_CONF_MAXLEN]={0};
|
||||
|
||||
MESA_load_profile_string_def((char*)filepath,(char*)DELIVER_CONF_MODE,(char*)"filestat2_filename",fs2_filename,DELIVER_CONF_MAXLEN,(char*)"./log/deliver_fs2.log");
|
||||
MESA_load_profile_string_def((char*)filepath,(char*)DELIVER_CONF_MODE,(char*)"filestat2_sip",fs2_sip,DELIVER_CONF_MAXLEN,(char*)"192.168.11.241");
|
||||
MESA_load_profile_uint_def((char*)filepath,(char*)DELIVER_CONF_MODE,(char*)"filestat2_sport",(unsigned int*)&fs2_sport,8125);
|
||||
MESA_load_profile_uint_def((char*)filepath,(char*)DELIVER_CONF_MODE,(char*)"filestat2_trans_switch",(unsigned int*)&trans_switch,0);
|
||||
|
||||
g_deliver_globle_info.fs2info.handler=FS_create_handle();
|
||||
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, OUTPUT_DEVICE,fs2_filename, strlen(fs2_filename)+1);
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, PRINT_MODE, &value, sizeof(value));
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, STAT_CYCLE, &value, sizeof(value));
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, CREATE_THREAD, &value, sizeof(value));
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, APP_NAME, FS2_APPNAME, strlen(FS2_APPNAME)+1);
|
||||
|
||||
if(trans_switch==1)
|
||||
{
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, STATS_SERVER_IP, fs2_sip, strlen(fs2_sip)+1);
|
||||
FS_set_para(g_deliver_globle_info.fs2info.handler, STATS_SERVER_PORT,&fs2_sport,sizeof(int));
|
||||
}
|
||||
|
||||
for(i=0;i<FS2_COLUMN_NUM;i++)
|
||||
{
|
||||
g_deliver_globle_info.fs2info.column_id[i]=FS_register(g_deliver_globle_info.fs2info.handler, FS_STYLE_FIELD, FS_CALC_CURRENT,g_deliver_globle_info.fs2_name[i]);
|
||||
}
|
||||
|
||||
|
||||
FS_start(g_deliver_globle_info.fs2info.handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void* deliver_filestat2(void* arg)
|
||||
{
|
||||
int i=0;
|
||||
int j=0;
|
||||
|
||||
char* filepath=(char*)arg;
|
||||
|
||||
unsigned long long column_value[FS2_COLUMN_NUM];
|
||||
|
||||
deliver_filestate2_init(filepath);
|
||||
|
||||
while(1)
|
||||
{
|
||||
for(i=0;i<FS2_COLUMN_NUM;i++)
|
||||
{
|
||||
column_value[i]=0;
|
||||
|
||||
for(j=0;j<g_deliver_globle_info.comminfo.threadnum;j++)
|
||||
{
|
||||
column_value[i]+=g_deliver_globle_info.fs2info.column_value[j][i];
|
||||
}
|
||||
|
||||
FS_operate(g_deliver_globle_info.fs2info.handler,g_deliver_globle_info.fs2info.column_id[i], 0,FS_OP_SET,column_value[i]);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int deliver_debug_log_v6(int level,char* module,struct deliver_pme_info* pmeinfo,int flag,int recv_len)
|
||||
{
|
||||
struct deliver_session_info* session_info=&(pmeinfo->session_info);
|
||||
struct deliver_pkt_info* pkt_info=&(pmeinfo->pkt_info);
|
||||
|
||||
const struct tfe_stream_addr_tuple4_v6* tuple4_v6 = pmeinfo->addr_info->tuple4_v6;
|
||||
|
||||
char saddr_v6[INET6_ADDRSTRLEN ]={0};
|
||||
char daddr_v6[INET6_ADDRSTRLEN ]={0};
|
||||
unsigned short sport=ntohs(tuple4_v6->source);
|
||||
unsigned short dport=ntohs(tuple4_v6->dest);
|
||||
|
||||
inet_ntop(AF_INET6, (void *)&(tuple4_v6->saddr), saddr_v6, INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, (void *)&(tuple4_v6->daddr), daddr_v6, INET6_ADDRSTRLEN);
|
||||
|
||||
switch(flag)
|
||||
{
|
||||
case DELIVER_FLAG_SENDPKT:
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,level,module,"addr:%s,%d,%s,%d,len:%d,dir:%d,seq:%u,ack:%u,ipid:%d,win:%d,flag:%d",
|
||||
saddr_v6,sport,daddr_v6,dport,pkt_info->len,pkt_info->dir,
|
||||
pkt_info->seq,pkt_info->ack,pkt_info->ipid,pkt_info->win,pkt_info->flag);
|
||||
break;
|
||||
case DELIVER_FLAG_RECVPKT:
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,level,module,"addr:%s,%d,%s,%d,dir:%d,recv_len:%d",
|
||||
saddr_v6,sport,daddr_v6,dport,pkt_info->dir,recv_len);
|
||||
break;
|
||||
case DELIVER_FLAG_ENT:
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,level,module,"addr:%s,%d,%s,%d,recvpkt:%d,recvbyte:%lld,sendpkt:%d,sendbytes:%lld",
|
||||
saddr_v6,sport,daddr_v6,dport,session_info->recv_pkt,session_info->recv_byte,
|
||||
session_info->send_pkt,session_info->recv_byte);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int deliver_debug_log_v4(int level,char* module,struct deliver_pme_info* pmeinfo,int flag,int recv_len)
|
||||
{
|
||||
struct deliver_session_info* session_info=&(pmeinfo->session_info);
|
||||
struct deliver_pkt_info* pkt_info=&(pmeinfo->pkt_info);
|
||||
|
||||
|
||||
const struct tfe_stream_addr_tuple4_v4* tuple4_v4 = pmeinfo->addr_info->tuple4_v4;
|
||||
|
||||
char saddr_v4[INET_ADDRSTRLEN]={0};
|
||||
char daddr_v4[INET_ADDRSTRLEN]={0};
|
||||
unsigned short sport=ntohs(tuple4_v4->source);
|
||||
unsigned short dport=ntohs(tuple4_v4->dest);
|
||||
|
||||
inet_ntop(AF_INET, (void *)&(tuple4_v4->saddr), saddr_v4, INET_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, (void *)&(tuple4_v4->daddr), daddr_v4, INET_ADDRSTRLEN);
|
||||
|
||||
switch(flag)
|
||||
{
|
||||
case DELIVER_FLAG_SENDPKT:
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,level,module,"addr:%s,%d,%s,%d,len:%d,dir:%d,seq:%u,ack:%u,ipid:%d,win:%d,flag:%d",
|
||||
saddr_v4,sport,daddr_v4,dport,pkt_info->len,pkt_info->dir,
|
||||
pkt_info->seq,pkt_info->ack,pkt_info->ipid,pkt_info->win,pkt_info->flag);
|
||||
break;
|
||||
case DELIVER_FLAG_RECVPKT:
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,level,module,"addr:%s,%d,%s,%d,dir:%d,recv_len:%d",
|
||||
saddr_v4,sport,daddr_v4,dport,pkt_info->dir,recv_len);
|
||||
break;
|
||||
case DELIVER_FLAG_ENT:
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,level,module,"addr:%s,%d,%s,%d,recvpkt:%d,recvbyte:%lld,sendpkt:%d,sendbytes:%lld",
|
||||
saddr_v4,sport,daddr_v4,dport,session_info->recv_pkt,session_info->recv_byte,
|
||||
session_info->send_pkt,session_info->recv_byte);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int deliver_sendpkt_ether(int thread_seq,int buflen,unsigned char* buf,unsigned char* dmac)
|
||||
{
|
||||
int ret=0;
|
||||
|
||||
if(-1==ioctl(g_deliver_globle_info.sendinfo.send_socket[thread_seq],SIOCGIFINDEX,&(g_deliver_globle_info.sendinfo.ifr)))
|
||||
{
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,DELIVER_MODULE_INIT,"get if index error:%d,%s,name:%d",errno,strerror(errno),g_deliver_globle_info.sendinfo.senddevice);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// struct sockaddr_ll addr={0};
|
||||
struct sockaddr_ll addr;
|
||||
memset(&addr,0,sizeof(struct sockaddr_ll));
|
||||
|
||||
addr.sll_family=AF_PACKET;
|
||||
addr.sll_halen=ETHER_ADDR_LEN;
|
||||
addr.sll_ifindex=g_deliver_globle_info.sendinfo.ifr.ifr_ifindex;
|
||||
addr.sll_protocol=htons(ETH_P_IP);
|
||||
memcpy(addr.sll_addr,dmac,ETHER_ADDR_LEN);
|
||||
|
||||
|
||||
if(ioctl(g_deliver_globle_info.sendinfo.send_socket[thread_seq],SIOCGIFHWADDR,&(g_deliver_globle_info.sendinfo.ifr))==-1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret=sendto(g_deliver_globle_info.sendinfo.send_socket[thread_seq],buf,buflen,0,(struct sockaddr*)&addr,sizeof(addr));
|
||||
if(ret<0)
|
||||
{
|
||||
deliver_set_filestate2(thread_seq,FS2_COLUME_ERROR,1);
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,DELIVER_MODULE_SENDPKT,"sendto() error,errno:%d,msg:%s!",errno,strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
deliver_set_filestate2(thread_seq,FS2_COLUME_SENDPKT,1);
|
||||
deliver_set_filestate2(thread_seq,FS2_COLUME_SENDBYTE,buflen-14-20-20);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int deliver_init_pmeinfo(const struct tfe_stream_addr* addr,void** pme)
|
||||
{
|
||||
//TODO:choose dst mac
|
||||
int i=deliver_rand()%(g_deliver_globle_info.sendinfo.receiver_num);
|
||||
|
||||
struct deliver_pme_info* pmeinfo=(struct deliver_pme_info*)malloc(sizeof(struct deliver_pme_info));
|
||||
memset(pmeinfo,0,sizeof(struct deliver_pme_info));
|
||||
pmeinfo->addr_info = addr;
|
||||
memcpy(pmeinfo->dst_macaddr,g_deliver_globle_info.sendinfo.receiver_info[i].dst_macaddr,DELIVER_MACADDR_LEN);
|
||||
|
||||
*pme=pmeinfo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int deliver_send_v6(int thread_seq,struct deliver_pme_info* pmeinfo,int payload_len,const unsigned char* payload)
|
||||
{
|
||||
int offset = 0;
|
||||
unsigned short eth_type=0x0800;
|
||||
|
||||
|
||||
int cur_dir=pmeinfo->pkt_info.dir;
|
||||
const struct tfe_stream_addr* addr_info = pmeinfo->addr_info;
|
||||
struct deliver_pkt_info* curpkt_info=&(pmeinfo->pkt_info);
|
||||
|
||||
offset = sizeof(struct mesa_ethernet_hdr);
|
||||
|
||||
if(cur_dir==CONN_DIR_DOWNSTREAM)
|
||||
{
|
||||
deliver_build_tcp(ntohs(addr_info->tuple4_v6->source), ntohs(addr_info->tuple4_v6->dest),
|
||||
curpkt_info->seq, curpkt_info->ack,curpkt_info->flag, curpkt_info->win, 0,
|
||||
payload,payload_len,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset+sizeof(struct mesa_ip6_hdr));
|
||||
|
||||
deliver_build_ipv6(0, 0, payload_len + sizeof(struct mesa_tcp_hdr), IPPROTO_TCP, curpkt_info->ttl,
|
||||
&(addr_info->tuple4_v6->saddr),&(addr_info->tuple4_v6->daddr),NULL, 0,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
deliver_build_tcp(ntohs(addr_info->tuple4_v6->dest), ntohs(addr_info->tuple4_v6->source),
|
||||
curpkt_info->seq, curpkt_info->ack,curpkt_info->flag, curpkt_info->win, 0,
|
||||
payload,payload_len,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset+sizeof(struct mesa_ip6_hdr));
|
||||
|
||||
deliver_build_ipv6(0, 0, payload_len + sizeof(struct mesa_tcp_hdr), IPPROTO_TCP, curpkt_info->ttl,
|
||||
&(addr_info->tuple4_v6->daddr),&(addr_info->tuple4_v6->saddr),NULL, 0,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
deliver_do_checksum(g_deliver_globle_info.sendbuf[thread_seq]+offset, IPPROTO_TCP, SENDPACKET_TCP_H+payload_len);
|
||||
|
||||
// deliver_do_checksum(g_deliver_globle_info.sendbuf[thread_seq]+offset, IPPROTO_IP, SENDPACKET_IP_H);
|
||||
|
||||
|
||||
deliver_build_ethernet((unsigned char*)(pmeinfo->dst_macaddr),(unsigned char*)(g_deliver_globle_info.sendinfo.src_macaddr),
|
||||
eth_type,NULL,0,(unsigned char*)g_deliver_globle_info.sendbuf[thread_seq]);
|
||||
|
||||
deliver_sendpkt_ether(thread_seq,SENDPACKET_TCP_H+SENDPACKET_IP_H+SENDPACKET_ETH_H+payload_len,
|
||||
g_deliver_globle_info.sendbuf[thread_seq],pmeinfo->dst_macaddr);
|
||||
|
||||
|
||||
pmeinfo->session_info.send_pkt++;
|
||||
pmeinfo->session_info.send_byte+=payload_len;
|
||||
|
||||
deliver_debug_log_v6(RLOG_LV_DEBUG,(char*)DELIVER_SENDPKT_DEBUG,pmeinfo,DELIVER_FLAG_SENDPKT,0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
int deliver_send_v4(int thread_seq,struct deliver_pme_info* pmeinfo,int payload_len,const unsigned char* payload)
|
||||
{
|
||||
int offset = 0;
|
||||
unsigned short eth_type=0x0800;
|
||||
|
||||
|
||||
int cur_dir=pmeinfo->pkt_info.dir;
|
||||
const struct tfe_stream_addr* addr_info = pmeinfo->addr_info;
|
||||
struct deliver_pkt_info* curpkt_info=&(pmeinfo->pkt_info);
|
||||
|
||||
offset = sizeof(struct mesa_ethernet_hdr);
|
||||
|
||||
if(cur_dir==CONN_DIR_DOWNSTREAM)
|
||||
{
|
||||
deliver_build_tcp(ntohs(addr_info->tuple4_v4->source), ntohs(addr_info->tuple4_v4->dest),
|
||||
curpkt_info->seq, curpkt_info->ack,curpkt_info->flag, curpkt_info->win, 0,
|
||||
payload,payload_len,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset+sizeof(struct mesa_ip4_hdr));
|
||||
|
||||
deliver_build_ipv4(SENDPACKET_TCP_H+payload_len, 0, curpkt_info->ipid, 0, 64, IPPROTO_TCP,
|
||||
addr_info->tuple4_v4->saddr.s_addr,addr_info->tuple4_v4->daddr.s_addr, NULL, 0,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
deliver_build_tcp(ntohs(addr_info->tuple4_v4->dest), ntohs(addr_info->tuple4_v4->source),
|
||||
curpkt_info->seq, curpkt_info->ack,curpkt_info->flag, curpkt_info->win, 0,
|
||||
payload,payload_len,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset+sizeof(struct mesa_ip4_hdr));
|
||||
|
||||
deliver_build_ipv4(SENDPACKET_TCP_H+payload_len, 0, curpkt_info->ipid, 0, 64, IPPROTO_TCP,
|
||||
addr_info->tuple4_v4->daddr.s_addr,addr_info->tuple4_v4->saddr.s_addr, NULL, 0,
|
||||
g_deliver_globle_info.sendbuf[thread_seq]+offset);
|
||||
}
|
||||
|
||||
|
||||
deliver_do_checksum(g_deliver_globle_info.sendbuf[thread_seq]+offset, IPPROTO_TCP, SENDPACKET_TCP_H+payload_len);
|
||||
|
||||
deliver_do_checksum(g_deliver_globle_info.sendbuf[thread_seq]+offset, IPPROTO_IP, SENDPACKET_IP_H);
|
||||
|
||||
|
||||
deliver_build_ethernet((unsigned char*)(pmeinfo->dst_macaddr),(unsigned char*)(g_deliver_globle_info.sendinfo.src_macaddr),
|
||||
eth_type,NULL,0,(unsigned char*)g_deliver_globle_info.sendbuf[thread_seq]);
|
||||
|
||||
deliver_sendpkt_ether(thread_seq,SENDPACKET_TCP_H+SENDPACKET_IP_H+SENDPACKET_ETH_H+payload_len,
|
||||
g_deliver_globle_info.sendbuf[thread_seq],pmeinfo->dst_macaddr);
|
||||
|
||||
|
||||
pmeinfo->session_info.send_pkt++;
|
||||
pmeinfo->session_info.send_byte+=payload_len;
|
||||
|
||||
deliver_debug_log_v4(RLOG_LV_DEBUG,(char*)DELIVER_SENDPKT_DEBUG,pmeinfo,DELIVER_FLAG_SENDPKT,0);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int deliver_send_syn(int thread_seq,struct deliver_pme_info* pmeinfo)
|
||||
{
|
||||
pmeinfo->pkt_info.dir=CONN_DIR_DOWNSTREAM;
|
||||
pmeinfo->pkt_info.len=0;
|
||||
pmeinfo->pkt_info.seq= deliver_rand();
|
||||
pmeinfo->pkt_info.ack=0;
|
||||
pmeinfo->pkt_info.flag=TH_SYN;
|
||||
pmeinfo->pkt_info.win = deliver_rand_range(1460, 65500);
|
||||
pmeinfo->pkt_info.ipid = deliver_rand() % 65535;
|
||||
pmeinfo->pkt_info.ttl=deliver_rand_range(32,65);
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_send_v4(thread_seq,pmeinfo,0,NULL);
|
||||
deliver_debug_log_v4(RLOG_LV_INFO,(char*)DELIVER_SENDPKT_START,pmeinfo,DELIVER_FLAG_SENDPKT,0);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_send_v6(thread_seq,pmeinfo,0,NULL);
|
||||
deliver_debug_log_v6(RLOG_LV_INFO,(char*)DELIVER_SENDPKT_START,pmeinfo,DELIVER_FLAG_SENDPKT,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deliver_send_syn_ack(int thread_seq,struct deliver_pme_info* pmeinfo)
|
||||
{
|
||||
pmeinfo->pkt_info.dir=CONN_DIR_UPSTREAM;
|
||||
pmeinfo->pkt_info.len=0;
|
||||
pmeinfo->pkt_info.ack=pmeinfo->pkt_info.seq+1;
|
||||
pmeinfo->pkt_info.seq= deliver_rand();
|
||||
pmeinfo->pkt_info.flag=TH_SYN|TH_ACK;
|
||||
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_send_v4(thread_seq,pmeinfo,0,NULL);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_send_v6(thread_seq,pmeinfo,0,NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int deliver_send_ack(int thread_seq,struct deliver_pme_info* pmeinfo)
|
||||
{
|
||||
unsigned int ack_tmp=pmeinfo->pkt_info.ack;
|
||||
|
||||
pmeinfo->pkt_info.dir=CONN_DIR_DOWNSTREAM;
|
||||
pmeinfo->pkt_info.len=0;
|
||||
pmeinfo->pkt_info.ack=pmeinfo->pkt_info.seq+1;
|
||||
pmeinfo->pkt_info.seq= ack_tmp;
|
||||
pmeinfo->pkt_info.flag=TH_ACK;
|
||||
|
||||
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_send_v4(thread_seq,pmeinfo,0,NULL);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_send_v6(thread_seq,pmeinfo,0,NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int deliver_set_pktinfo(struct deliver_pme_info* pmeinfo,int flag, int cur_dir,int payload_len)
|
||||
{
|
||||
struct deliver_pkt_info last_pkt_info;
|
||||
memcpy((void*)&last_pkt_info,(void*)&(pmeinfo->pkt_info),sizeof(struct deliver_pkt_info));
|
||||
|
||||
pmeinfo->pkt_info.dir=cur_dir;
|
||||
pmeinfo->pkt_info.len=payload_len;
|
||||
pmeinfo->pkt_info.flag=flag;
|
||||
|
||||
|
||||
if(cur_dir==last_pkt_info.dir)
|
||||
{
|
||||
pmeinfo->pkt_info.seq=last_pkt_info.seq+last_pkt_info.len;
|
||||
pmeinfo->pkt_info.ack=last_pkt_info.ack;
|
||||
}
|
||||
else
|
||||
{
|
||||
pmeinfo->pkt_info.seq=last_pkt_info.ack;
|
||||
pmeinfo->pkt_info.ack=last_pkt_info.seq+last_pkt_info.len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int deliver_send_rst(int thread_seq,struct deliver_pme_info* pmeinfo)
|
||||
{
|
||||
deliver_set_pktinfo(pmeinfo,TH_RST,CONN_DIR_DOWNSTREAM,0);
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_send_v4(thread_seq,pmeinfo,0,NULL);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_send_v6(thread_seq,pmeinfo,0,NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
|
||||
deliver_set_pktinfo(pmeinfo,TH_RST,CONN_DIR_UPSTREAM,0);
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_send_v4(thread_seq,pmeinfo,0,NULL);
|
||||
deliver_debug_log_v4(RLOG_LV_INFO,(char*)DELIVER_SENDPKT_END,pmeinfo,DELIVER_FLAG_ENT,0);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_send_v6(thread_seq,pmeinfo,0,NULL);
|
||||
deliver_debug_log_v6(RLOG_LV_INFO,(char*)DELIVER_SENDPKT_END,pmeinfo,DELIVER_FLAG_ENT,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mirror_stream_open(int thread_id, const struct tfe_stream_addr* addr,void** pme)
|
||||
{
|
||||
if(g_deliver_globle_info.deliver_switch == 0)
|
||||
{
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_INFO,DELIVER_MODULE_INIT,"mirror_stream switch is 0,not run....");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct deliver_pme_info* pmeinfo=NULL;
|
||||
|
||||
deliver_init_pmeinfo(addr,pme);
|
||||
pmeinfo=(struct deliver_pme_info*)*pme;
|
||||
|
||||
deliver_send_syn(thread_id,pmeinfo);
|
||||
deliver_send_syn_ack(thread_id,pmeinfo);
|
||||
deliver_send_ack(thread_id,pmeinfo);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mirror_stream_write(int cur_dir,const unsigned char * data, size_t len, void** pme,int thread_id)
|
||||
{
|
||||
if(g_deliver_globle_info.deliver_switch == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i=0;
|
||||
const unsigned char* payload=data;
|
||||
int payload_len=0;
|
||||
int remain_len=len;
|
||||
int max_payloadlen_per=0;
|
||||
int pkt_num=0;
|
||||
// int pkt_num=(len/(g_deliver_globle_info.sendinfo.mtu))+1;
|
||||
struct deliver_pme_info* pmeinfo=(struct deliver_pme_info*)*pme;
|
||||
|
||||
|
||||
deliver_set_filestate2(thread_id,FS2_COLUME_RECVPKT,1);
|
||||
deliver_set_filestate2(thread_id,FS2_COLUME_RECVBYTE,len);
|
||||
|
||||
pmeinfo->session_info.recv_pkt++;
|
||||
pmeinfo->session_info.recv_byte+=len;
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_debug_log_v4(RLOG_LV_DEBUG,(char*)DELIVER_RECVPKT_DEBUG,pmeinfo,DELIVER_FLAG_RECVPKT,len);
|
||||
max_payloadlen_per=g_deliver_globle_info.sendinfo.mtu-sizeof(struct mesa_tcp_hdr)-sizeof(struct mesa_ip4_hdr);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_debug_log_v6(RLOG_LV_DEBUG,(char*)DELIVER_RECVPKT_DEBUG,pmeinfo,DELIVER_FLAG_RECVPKT,len);
|
||||
max_payloadlen_per=g_deliver_globle_info.sendinfo.mtu-sizeof(struct mesa_tcp_hdr)-sizeof(struct mesa_ip6_hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
pkt_num=(len/(max_payloadlen_per))+1;
|
||||
|
||||
for(i=0;i<pkt_num;i++)
|
||||
{
|
||||
/*
|
||||
payload_len=remain_len<(g_deliver_globle_info.sendinfo.mtu)?remain_len:(g_deliver_globle_info.sendinfo.mtu);
|
||||
payload=data+(len-remain_len);
|
||||
remain_len-=g_deliver_globle_info.sendinfo.mtu;
|
||||
*/
|
||||
payload_len=remain_len<max_payloadlen_per?remain_len:max_payloadlen_per;
|
||||
payload=data+(len-remain_len);
|
||||
remain_len-=max_payloadlen_per;
|
||||
|
||||
deliver_set_pktinfo(pmeinfo,TH_ACK,cur_dir,payload_len);
|
||||
if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
deliver_send_v4(thread_id,pmeinfo,payload_len,payload);
|
||||
}
|
||||
else if(pmeinfo->addr_info->addrtype==TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
deliver_send_v6(thread_id,pmeinfo,payload_len,payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void mirror_stream_close(void** pme, int thread_id)
|
||||
{
|
||||
if(g_deliver_globle_info.deliver_switch == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
struct deliver_pme_info* pmeinfo=(struct deliver_pme_info*)*pme;
|
||||
|
||||
deliver_send_rst(thread_id,pmeinfo);
|
||||
|
||||
|
||||
if(*pme!=NULL)
|
||||
{
|
||||
free(*pme);
|
||||
*pme=NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int deliver_device_init()
|
||||
{
|
||||
char* if_name=g_deliver_globle_info.sendinfo.senddevice;
|
||||
|
||||
//init socket
|
||||
size_t ifname_len=strlen(if_name);
|
||||
if(ifname_len<sizeof(g_deliver_globle_info.sendinfo.ifr.ifr_name))
|
||||
{
|
||||
memset(g_deliver_globle_info.sendinfo.ifr.ifr_name,0,IFNAMSIZ);
|
||||
memcpy(g_deliver_globle_info.sendinfo.ifr.ifr_name,if_name,ifname_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,DELIVER_MODULE_INIT,"interface name :%s is too long\n",if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
deliver_get_dev_mac(g_deliver_globle_info.sendinfo.senddevice,g_deliver_globle_info.sendinfo.src_macaddr);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int deliver_profile_init(const char* filepath,int* logger_level,char* logger_filepath)
|
||||
{
|
||||
int i=1;
|
||||
char mac_addr_str[DELIVER_MACADDR_STR_LEN];
|
||||
char receiver_mac_name[DELIVER_CARDNAME_LEN]={0};
|
||||
|
||||
//switch
|
||||
MESA_load_profile_int_def(filepath,(char*)DELIVER_CONF_MODE,(char*)"mirror_switch",&(g_deliver_globle_info.deliver_switch),0);
|
||||
|
||||
|
||||
//runtime log
|
||||
MESA_load_profile_int_def(filepath,(char*)DELIVER_CONF_MODE,(char*)"logger_level",logger_level,RLOG_LV_INFO);
|
||||
MESA_load_profile_string_def(filepath,(char*)DELIVER_CONF_MODE,(char*)"logger_filepath",logger_filepath,DELIVER_CONF_MAXLEN,"./log/deliver.log");
|
||||
|
||||
//sendpkt info
|
||||
MESA_load_profile_int_def(filepath,(char*)DELIVER_CONF_MODE,(char*)"mtu",&(g_deliver_globle_info.sendinfo.mtu),DELIVER_DEFAULT_MTU);
|
||||
MESA_load_profile_int_def(filepath,(char*)DELIVER_CONF_MODE,(char*)"receiver_num",&(g_deliver_globle_info.sendinfo.receiver_num),1);
|
||||
MESA_load_profile_string_nodef(filepath,(char*)DELIVER_CONF_MODE,(char*)"senddevice",g_deliver_globle_info.sendinfo.senddevice,DELIVER_CARDNAME_LEN);
|
||||
|
||||
g_deliver_globle_info.sendinfo.receiver_info=(struct deliver_recver_info*)ALLOC(struct deliver_recver_info,g_deliver_globle_info.sendinfo.receiver_num);
|
||||
for(i=1;i<=g_deliver_globle_info.sendinfo.receiver_num;i++)
|
||||
{
|
||||
memset(mac_addr_str,0,DELIVER_MACADDR_STR_LEN);
|
||||
|
||||
memset(receiver_mac_name,0,DELIVER_CARDNAME_LEN);
|
||||
sprintf(receiver_mac_name,"%s%d",DELIVER_RCV_MAC,i);
|
||||
|
||||
MESA_load_profile_string_nodef(filepath,(char*)DELIVER_CONF_MODE,(char*)receiver_mac_name,(char*)mac_addr_str,DELIVER_MACADDR_STR_LEN);
|
||||
|
||||
if(deliver_mac_pton(mac_addr_str, ':', (char *)(g_deliver_globle_info.sendinfo.receiver_info[i-1].dst_macaddr)) < 0)
|
||||
{
|
||||
printf("error, receiver %d mac:%s is not correct, for example:00:11:22:33:44:55\n", i,mac_addr_str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deliver_socket_error(int n)
|
||||
{
|
||||
for(int i=0;i<n;i++)
|
||||
{
|
||||
close(g_deliver_globle_info.sendinfo.send_socket[i]);
|
||||
g_deliver_globle_info.sendinfo.send_socket[i]=0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deliver_init_log()
|
||||
{
|
||||
int i=0;
|
||||
int j=0;
|
||||
|
||||
char mac_str[DELIVER_MACADDR_STR_LEN+1]={0};
|
||||
|
||||
for(j = 0; j < 6; j++)
|
||||
{
|
||||
sprintf(mac_str+3*j, "%02x:", (unsigned char)g_deliver_globle_info.sendinfo.src_macaddr[j]);
|
||||
}
|
||||
mac_str[DELIVER_MACADDR_STR_LEN]=0;
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,DELIVER_MODULE_INIT,"mtu:%d,receiver_num:%d,senddevice:%s,mac:%s",
|
||||
g_deliver_globle_info.sendinfo.mtu,g_deliver_globle_info.sendinfo.receiver_num,g_deliver_globle_info.sendinfo.senddevice,mac_str);
|
||||
|
||||
for(i=0;i<g_deliver_globle_info.sendinfo.receiver_num;i++)
|
||||
{
|
||||
|
||||
for(j = 0; j < 6; j++)
|
||||
{
|
||||
sprintf(mac_str+3*j, "%02x:", (unsigned char)g_deliver_globle_info.sendinfo.receiver_info[i].dst_macaddr[j]);
|
||||
}
|
||||
|
||||
mac_str[DELIVER_MACADDR_STR_LEN]=0;
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,DELIVER_MODULE_INIT,"reveiver_mac:%s",mac_str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mirror_stream_init(int thread_num, const char* filepath)
|
||||
{
|
||||
int i=0;
|
||||
int flag=0;
|
||||
int logger_level;
|
||||
char logger_filepath[DELIVER_CONF_MAXLEN]={0};
|
||||
|
||||
pthread_t pid_deliver_filestat2;
|
||||
|
||||
g_deliver_globle_info.comminfo.threadnum=thread_num;
|
||||
g_deliver_globle_info.fs2_name[FS2_COLUME_RECVPKT] = (char*)"RECV_PKTS";
|
||||
g_deliver_globle_info.fs2_name[FS2_COLUME_RECVBYTE] = (char*)"RECV_BYTES";
|
||||
g_deliver_globle_info.fs2_name[FS2_COLUME_SENDPKT] = (char*)"SEND_PKTS";
|
||||
g_deliver_globle_info.fs2_name[FS2_COLUME_SENDBYTE] = (char*)"SEND_BYTES";
|
||||
g_deliver_globle_info.fs2_name[FS2_COLUME_ERROR] = (char*)"ERROR_PKTS";
|
||||
|
||||
//profile
|
||||
deliver_profile_init(filepath,&logger_level,logger_filepath);
|
||||
|
||||
|
||||
//init runtime log
|
||||
g_deliver_globle_info.comminfo.logger=MESA_create_runtime_log_handle(logger_filepath,logger_level);
|
||||
if(g_deliver_globle_info.comminfo.logger==NULL)
|
||||
{
|
||||
printf("MESA_create_runtime_log_handle() error!exit...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//socket init
|
||||
g_deliver_globle_info.sendinfo.thread_num=thread_num;
|
||||
g_deliver_globle_info.sendinfo.send_socket=(int*)malloc(g_deliver_globle_info.sendinfo.thread_num*sizeof(int));
|
||||
for(i=0;i<g_deliver_globle_info.sendinfo.thread_num;i++)
|
||||
{
|
||||
g_deliver_globle_info.sendbuf[i] = (unsigned char*)malloc(g_deliver_globle_info.sendinfo.mtu + sizeof(struct mesa_ethernet_hdr));
|
||||
|
||||
g_deliver_globle_info.sendinfo.send_socket[i]=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_IP));
|
||||
if((g_deliver_globle_info.sendinfo.send_socket[i]<0) ||(g_deliver_globle_info.sendbuf[i]==NULL))
|
||||
{
|
||||
deliver_socket_error(i);
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger, RLOG_LV_FATAL,DELIVER_MODULE_INIT,"ipv4_raw_socket error,i:%d",i);
|
||||
return -1;
|
||||
}
|
||||
flag= fcntl(g_deliver_globle_info.sendinfo.send_socket[i], F_GETFL, 0);
|
||||
if(flag<0)
|
||||
{
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger, RLOG_LV_FATAL,DELIVER_MODULE_INIT,"fcntl():getfl error,errno is:%d,%s",errno,strerror(errno));
|
||||
}
|
||||
if( fcntl( g_deliver_globle_info.sendinfo.send_socket[i], F_SETFL, flag|O_NONBLOCK ) < 0 )
|
||||
{
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger, RLOG_LV_FATAL,DELIVER_MODULE_INIT,"fcntl():setfl error,errno is:%d,%s",errno,strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
pthread_create(&pid_deliver_filestat2,NULL,deliver_filestat2,(void*)filepath);
|
||||
|
||||
deliver_device_init();
|
||||
|
||||
deliver_init_log();
|
||||
|
||||
MESA_handle_runtime_log(g_deliver_globle_info.comminfo.logger,RLOG_LV_FATAL,DELIVER_MODULE_INIT,"thread_num:%d,filepath:%s,deliver.so init sucess!",thread_num,filepath);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
251
plugin/business/decrypt-mirroring/src/rebuild.cpp
Normal file
251
plugin/business/decrypt-mirroring/src/rebuild.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
|
||||
#include <tfe_proxy.h>
|
||||
#include <tfe_utils.h>
|
||||
#include <tfe_types.h>
|
||||
#include <traffic_mirror.h>
|
||||
|
||||
struct traffic_mirror_rebuild
|
||||
{
|
||||
struct tfe_stream_addr * addr;
|
||||
struct profile_table_ex_data * target;
|
||||
struct traffic_mirror_ethdev * ethdev;
|
||||
|
||||
uint32_t c_seq;
|
||||
uint32_t s_seq;
|
||||
uint32_t c_ipid;
|
||||
uint32_t s_ipid;
|
||||
uint8_t c_ttl;
|
||||
uint8_t s_ttl;
|
||||
};
|
||||
|
||||
static int tcp_header_construct(unsigned char *buf, unsigned short sp,
|
||||
unsigned short dp, unsigned int seq, unsigned int ack,
|
||||
unsigned char flags, unsigned short win, unsigned short urg)
|
||||
{
|
||||
struct tcphdr * tcp_hdr = (struct tcphdr *) buf;
|
||||
assert(tcp_hdr != NULL);
|
||||
|
||||
tcp_hdr->th_sport = sp;
|
||||
tcp_hdr->th_dport = dp;
|
||||
tcp_hdr->th_seq = htonl(seq);
|
||||
tcp_hdr->th_ack = htonl(ack);
|
||||
tcp_hdr->th_flags = flags;
|
||||
tcp_hdr->th_x2 = 0;
|
||||
tcp_hdr->th_off = 5; /* 20 byte header */
|
||||
tcp_hdr->th_win = htons(win); /* window size */
|
||||
tcp_hdr->th_sum = 0; /* checksum done in userland */
|
||||
tcp_hdr->th_urp = 0; /* urgent pointer */
|
||||
|
||||
return sizeof(struct tcphdr);
|
||||
}
|
||||
|
||||
static int tcp_header_construct_by_stream_addr(struct tfe_stream_addr * addr, unsigned char *buf,
|
||||
unsigned int seq, unsigned int ack, unsigned char flags, unsigned short win, unsigned short urg)
|
||||
{
|
||||
unsigned short sport;
|
||||
unsigned short dport;
|
||||
|
||||
if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
sport = addr->tuple4_v4->source;
|
||||
dport = addr->tuple4_v4->dest;
|
||||
}
|
||||
else if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V6)
|
||||
{
|
||||
sport = addr->tuple4_v6->source;
|
||||
dport = addr->tuple4_v6->dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return tcp_header_construct(buf, sport, dport, seq, ack, flags, win, urg);
|
||||
}
|
||||
|
||||
static int ipv4_header_construct(unsigned char *buf, unsigned short carry_layer_len,
|
||||
unsigned char tos, unsigned short id, unsigned short frag, unsigned char ttl,
|
||||
unsigned char protocol, unsigned int src, unsigned int dst)
|
||||
{
|
||||
struct iphdr * ip_hdr = (struct iphdr *) buf;
|
||||
ip_hdr->version = 4;
|
||||
ip_hdr->ihl = 5;
|
||||
ip_hdr->tos = tos;
|
||||
ip_hdr->tot_len = htons(sizeof(struct iphdr) + carry_layer_len);
|
||||
ip_hdr->id = htons(id);
|
||||
ip_hdr->frag_off = 0;
|
||||
ip_hdr->ttl = ttl;
|
||||
ip_hdr->protocol = protocol;
|
||||
ip_hdr->check = 0;
|
||||
ip_hdr->saddr = src;
|
||||
ip_hdr->daddr = dst;
|
||||
|
||||
return sizeof(struct iphdr);
|
||||
}
|
||||
|
||||
static int ip_header_construct_by_stream_addr(struct tfe_stream_addr * addr,
|
||||
unsigned char *buf, unsigned short carry_layer_len, unsigned char tos,
|
||||
unsigned short id, unsigned short frag, unsigned char ttl, unsigned char protocol)
|
||||
{
|
||||
if (addr->addrtype == TFE_ADDR_STREAM_TUPLE4_V4)
|
||||
{
|
||||
return ipv4_header_construct(buf, carry_layer_len, tos, id,
|
||||
frag, ttl, protocol, addr->tuple4_v4->saddr.s_addr, addr->tuple4_v4->daddr.s_addr);
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ether_header_construct(unsigned char *buf, unsigned char *dst,
|
||||
unsigned char *src, unsigned short type)
|
||||
{
|
||||
struct ethhdr * eth_hdr = (struct ethhdr *) buf;
|
||||
memcpy(eth_hdr->h_dest, dst, ETHER_ADDR_LEN);
|
||||
memcpy(eth_hdr->h_source, src, ETHER_ADDR_LEN);
|
||||
eth_hdr->h_proto = htons(type);
|
||||
}
|
||||
|
||||
struct vlan_hdr
|
||||
{
|
||||
uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */
|
||||
uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static void vlan_tag_construct(unsigned char *buf, unsigned short tci, unsigned short type)
|
||||
{
|
||||
struct vlan_hdr * vlan_hdr = (struct vlan_hdr *)buf;
|
||||
vlan_hdr->vlan_tci = htons(tci);
|
||||
vlan_hdr->eth_proto = htons(type);
|
||||
}
|
||||
|
||||
static void l2_send_to_target(struct traffic_mirror_ethdev * ethdev,
|
||||
unsigned char * snd_buffer, unsigned int l3_data_offset, unsigned int l3_data_len,
|
||||
struct ether_addr * target_addr, unsigned int vlan_tci, unsigned l3_protocol)
|
||||
{
|
||||
assert(l3_data_offset >= (sizeof(struct ethhdr) + sizeof(struct vlan_hdr)));
|
||||
unsigned int header_offset = l3_data_offset;
|
||||
|
||||
/* need to construct vlan header */
|
||||
if (vlan_tci > 0)
|
||||
{
|
||||
header_offset -= sizeof(struct vlan_hdr);
|
||||
vlan_tag_construct(snd_buffer + header_offset, vlan_tci, l3_protocol);
|
||||
}
|
||||
|
||||
unsigned int eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol;
|
||||
header_offset -= sizeof(struct ethhdr);
|
||||
|
||||
ether_header_construct(snd_buffer + header_offset, (unsigned char *)target_addr->ether_addr_octet,
|
||||
(unsigned char *)ethdev->local_ether_addr, eth_protocol);
|
||||
}
|
||||
|
||||
static void l2_send_to_target_group(struct traffic_mirror_ethdev * ethdev, struct profile_table_ex_data * t_group,
|
||||
unsigned char * snd_buffer, unsigned int l3_data_offset, unsigned int l3_data_len, unsigned l3_protocol)
|
||||
{
|
||||
for(unsigned int i = 0; i < t_group->nr_targets; i++)
|
||||
{
|
||||
l2_send_to_target(ethdev, snd_buffer, l3_data_offset, l3_data_len,
|
||||
&t_group->ether_addrs[i], t_group->vlans[i], l3_protocol);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev,
|
||||
struct profile_table_ex_data * t_group, const char * payload, unsigned int payload_len,
|
||||
unsigned int seq, unsigned int ack, char flags)
|
||||
{
|
||||
char pkt[ETHER_MAX_LEN];
|
||||
unsigned sz_pkt_prepend = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct tcphdr);
|
||||
unsigned l3_l4_header_len = 0;
|
||||
|
||||
l3_l4_header_len += tcp_header_construct_by_stream_addr(addr,
|
||||
(unsigned char *)pkt + sz_pkt_prepend, seq, ack, flags, 0xffff, 0);
|
||||
|
||||
l3_l4_header_len += ip_header_construct_by_stream_addr(addr, (unsigned char *)pkt + sz_pkt_prepend,
|
||||
sizeof(struct tcphdr) + payload_len, 0, 0x1000, 0, 128, IPPROTO_TCP);
|
||||
|
||||
sz_pkt_prepend -= l3_l4_header_len;
|
||||
|
||||
l2_send_to_target_group(ethdev, t_group, (unsigned char *)pkt,
|
||||
sz_pkt_prepend, l3_l4_header_len + payload_len, ETHERTYPE_IP);
|
||||
}
|
||||
|
||||
static void tcp_send_to_target_group(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev,
|
||||
struct profile_table_ex_data * t_group, const char * payload,
|
||||
unsigned int payload_len, unsigned int seq, unsigned int ack, char flags)
|
||||
{
|
||||
unsigned int payload_offset = 0;
|
||||
unsigned mss = ethdev->mtu - (sizeof(struct iphdr) + sizeof(struct tcphdr));
|
||||
|
||||
while(payload_offset < payload_len)
|
||||
{
|
||||
unsigned int payload_sz_seg = MIN(payload_offset, mss);
|
||||
const char * payload_ptr_seg = payload + payload_offset;
|
||||
|
||||
tcp_segment_send_to_target_group(addr, ethdev, t_group, 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 profile_table_ex_data * target, struct traffic_mirror_ethdev * ethdev)
|
||||
{
|
||||
struct traffic_mirror_rebuild * instance = ALLOC(struct traffic_mirror_rebuild, 1);
|
||||
instance->target = target;
|
||||
instance->ethdev = ethdev;
|
||||
|
||||
/* the c_seq, s_seq, c_ipid, s_ipid is random
|
||||
* TODO: use the fast random algorithm like Linux TCP/IP stack */
|
||||
instance->c_seq = random();
|
||||
instance->s_seq = random();
|
||||
instance->c_ipid = random();
|
||||
instance->s_ipid = random();
|
||||
instance->s_ttl = 128;
|
||||
instance->c_ttl = 64;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void traffic_mirror_rebuild_destroy(struct traffic_mirror_rebuild * instance)
|
||||
{
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance)
|
||||
{
|
||||
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
|
||||
NULL, 0, instance->c_seq, 0, TH_SYN);
|
||||
|
||||
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
|
||||
NULL, 0, instance->s_seq, instance->c_seq + 1, TH_SYN | TH_ACK);
|
||||
|
||||
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
|
||||
NULL, 0, instance->c_seq + 1, instance->s_seq + 1, TH_ACK);
|
||||
|
||||
instance->s_seq++;
|
||||
instance->c_seq++;
|
||||
}
|
||||
|
||||
void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance,
|
||||
const char * data, unsigned int datalen, enum tfe_conn_dir dir)
|
||||
{
|
||||
if (dir == CONN_DIR_DOWNSTREAM)
|
||||
{
|
||||
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
|
||||
NULL, 0, instance->c_seq, instance->s_seq + 1, TH_ACK);
|
||||
|
||||
instance->c_seq += datalen;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
|
||||
NULL, 0, instance->s_seq, instance->c_seq + 1, TH_ACK);
|
||||
|
||||
instance->s_seq += datalen;
|
||||
}
|
||||
}
|
||||
|
||||
void traffic_mirror_rebuild_farewell(struct traffic_mirror_rebuild * instance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1,467 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <sendpkt-inl.h>
|
||||
|
||||
static volatile uint64_t g_rand_seed = 0x013579ABCDEF;
|
||||
|
||||
#define SENDPACKET_CKSUM_CARRY(x) (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
|
||||
|
||||
unsigned int deliver_rand(void)
|
||||
{
|
||||
return g_rand_seed ^ (unsigned int)random();
|
||||
}
|
||||
|
||||
unsigned int deliver_rand_range(unsigned int start, unsigned int end)
|
||||
{
|
||||
unsigned int rand_num = deliver_rand();
|
||||
|
||||
if(start > end)
|
||||
{
|
||||
return end + rand_num % (start - end + 1);
|
||||
}
|
||||
|
||||
return start + rand_num % (end - start + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ascii字符转16进制 */
|
||||
char MESA_ascii_to_hex(char ascii)
|
||||
{
|
||||
char c = 0;
|
||||
|
||||
switch(ascii)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
c = ascii - 0x30;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
c = 10 + ascii - 0x61;
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
c = 10 + ascii - 0x41;
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 2012-04-10 LiJia add, 获取网卡MAC地址
|
||||
参数:
|
||||
device: 网卡名称
|
||||
mac: 存储MAC地址的数组,结果为网络序,
|
||||
如网卡MAC地址为11:22:33:44:55:66,则mac[0]为0x11,mac[5]为0x66.
|
||||
返回值:
|
||||
0: 正常
|
||||
-1:错误
|
||||
*/
|
||||
int deliver_get_dev_mac(const char *device, unsigned char mac[6])
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(fd < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(ifr.ifr_ifrn.ifrn_name, 0, sizeof(ifr.ifr_ifrn.ifrn_name));
|
||||
strncpy(ifr.ifr_ifrn.ifrn_name, device, sizeof(ifr.ifr_ifrn.ifrn_name));
|
||||
if(ioctl(fd, SIOCGIFHWADDR, &ifr) == -1)
|
||||
{
|
||||
printf("Cann't get hwaddr of %s:%s\n", device, strerror(errno));
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if(ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
|
||||
{
|
||||
printf("'%s' is not ethernet interface!\n", device);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
memcpy(mac, ifr.ifr_ifru.ifru_addr.sa_data, 6);
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 2012-04-11 LiJia add,将MAC字符串形式转换为16进制MAC地址.
|
||||
参数:
|
||||
str: MAC地址字符串
|
||||
delim: 字符串分隔符,常见为':', '-'等,如: xx:xx:xx:xx:xx:xx
|
||||
如果字符串无分隔符,delim设为-1.
|
||||
mac: 存储MAC地址的数组(指针),结果为网络序,
|
||||
如网卡MAC地址为11:22:33:44:55:66,则mac[0]为0x11,mac[5]为0x66.
|
||||
返回值:
|
||||
0: 正常
|
||||
-1:错误
|
||||
*/
|
||||
int deliver_mac_pton(const char *str, int delim, char *mac)
|
||||
{
|
||||
#define MAC_STR_LEN_DELIM (17) /* length of "11:22:33:44:55:66" */
|
||||
#define MAC_STR_LEN_NODELIM (12) /* length of "112233445566" */
|
||||
const char *s = str;
|
||||
int i;
|
||||
|
||||
/* 检查输入合法性 */
|
||||
if(delim != -1)
|
||||
{
|
||||
if(strlen(str) != MAC_STR_LEN_DELIM)
|
||||
{
|
||||
printf("MAC string length error!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(strlen(str) != MAC_STR_LEN_NODELIM)
|
||||
{
|
||||
printf("MAC string length error!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 检查输入合法性,同时转换成16进制值 */
|
||||
for(i = 0; i < 6; i++)
|
||||
{
|
||||
mac[i] = 0; /* 先清零,赋值语句都是或操作 */
|
||||
if(isxdigit(*s)==0)
|
||||
{
|
||||
printf("MAC string type error!\n");
|
||||
return -1;
|
||||
}
|
||||
mac[i] |= MESA_ascii_to_hex(*s) << 4;
|
||||
s++;
|
||||
|
||||
if(isxdigit(*s)==0)
|
||||
{
|
||||
printf("MAC string type error!\n");
|
||||
return -1;
|
||||
}
|
||||
mac[i] |= MESA_ascii_to_hex(*s);
|
||||
s++;
|
||||
|
||||
if((delim != -1) && i<5 && (*s++ != (char)delim))
|
||||
{
|
||||
printf("MAC string type error!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int sendpacket_in_cksum(unsigned short *addr, int len)
|
||||
{
|
||||
int sum;
|
||||
int nleft;
|
||||
unsigned short ans;
|
||||
unsigned short *w;
|
||||
|
||||
sum = 0;
|
||||
ans = 0;
|
||||
nleft = len;
|
||||
w = addr;
|
||||
|
||||
while (nleft > 1)
|
||||
{
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
if (nleft == 1)
|
||||
{
|
||||
*(char *)(&ans) = *(char *)w;
|
||||
sum += ans;
|
||||
}
|
||||
return (sum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int deliver_do_checksum(unsigned char *buf, int protocol, int len)
|
||||
{
|
||||
struct mesa_ip4_hdr *iph_p;
|
||||
struct mesa_ip6_hdr *ip6h_p;
|
||||
int ip_hl;
|
||||
int sum;
|
||||
int is_ipv6 = 0;
|
||||
|
||||
sum = 0;
|
||||
iph_p = (struct mesa_ip4_hdr *)buf;
|
||||
|
||||
if(4 == iph_p->ip_v) /* IP版本号字段,IPv4和IPv6格式是相同的 */
|
||||
{
|
||||
ip_hl = iph_p->ip_hl << 2;
|
||||
ip6h_p = NULL;
|
||||
}
|
||||
else if(6 == iph_p->ip_v)
|
||||
{
|
||||
ip6h_p = (struct mesa_ip6_hdr *)buf;
|
||||
iph_p = NULL;
|
||||
ip_hl = sizeof(struct mesa_ip6_hdr);
|
||||
is_ipv6 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
switch (protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
{
|
||||
struct mesa_tcp_hdr *tcph_p = (struct mesa_tcp_hdr *)(buf + ip_hl);
|
||||
|
||||
tcph_p->th_sum = 0;
|
||||
if(is_ipv6)
|
||||
{
|
||||
sum = sendpacket_in_cksum((unsigned short*)&ip6h_p->ip6_src, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum = sendpacket_in_cksum((unsigned short *)&iph_p->ip_src, 8);
|
||||
}
|
||||
sum += ntohs(IPPROTO_TCP + len);
|
||||
sum += sendpacket_in_cksum((unsigned short *)tcph_p, len);
|
||||
tcph_p->th_sum = SENDPACKET_CKSUM_CARRY(sum);
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_UDP:
|
||||
{
|
||||
struct mesa_udp_hdr *udph_p =(struct mesa_udp_hdr *)(buf + ip_hl);
|
||||
|
||||
udph_p->uh_sum = 0;
|
||||
if(is_ipv6)
|
||||
{
|
||||
sum = sendpacket_in_cksum((unsigned short*)&ip6h_p->ip6_src, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
sum = sendpacket_in_cksum((unsigned short*)&iph_p->ip_src, 8);
|
||||
}
|
||||
sum += ntohs(IPPROTO_UDP + len);
|
||||
sum += sendpacket_in_cksum((unsigned short*)udph_p, len);
|
||||
udph_p->uh_sum = SENDPACKET_CKSUM_CARRY(sum);
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_IP:
|
||||
{
|
||||
iph_p->ip_sum = 0;
|
||||
sum = sendpacket_in_cksum((unsigned short*)iph_p, len);
|
||||
iph_p->ip_sum = SENDPACKET_CKSUM_CARRY(sum);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if playload2 is not NULL, it means that there is ip spice, it must be copied first, then
|
||||
playload is copied
|
||||
otherwise, only payload is copied and it includes ip header
|
||||
*/
|
||||
int deliver_build_ethhdr(unsigned char *dst, unsigned char *src, unsigned short type,unsigned char *buf)
|
||||
{
|
||||
struct mesa_ethernet_hdr eth_hdr;
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */
|
||||
memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */
|
||||
eth_hdr.ether_type = htons(type); /* packet type */
|
||||
|
||||
memcpy(buf, ð_hdr, sizeof(eth_hdr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if playload2 is not NULL, it means that there is ip spice, it must be copied first, then
|
||||
playload is copied
|
||||
otherwise, only payload is copied and it includes ip header
|
||||
*/
|
||||
int deliver_build_ethernet(unsigned char *dst, unsigned char *src, unsigned short type,
|
||||
const unsigned char *payload, int payload_s, unsigned char *buf)
|
||||
{
|
||||
struct mesa_ethernet_hdr eth_hdr;
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */
|
||||
memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */
|
||||
eth_hdr.ether_type = htons(type); /* packet type */
|
||||
|
||||
if (payload && payload_s)
|
||||
{
|
||||
memcpy(buf + SENDPACKET_ETH_H, payload, payload_s);
|
||||
}
|
||||
memcpy(buf, ð_hdr, sizeof(eth_hdr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int deliver_build_ipv6(unsigned char traffic_class, unsigned int flow_lable,
|
||||
unsigned short len, unsigned char next_header, unsigned char hop,
|
||||
const struct in6_addr *src, const struct in6_addr *dst,
|
||||
const unsigned char *payload, int payload_s, unsigned char *buf)
|
||||
{
|
||||
struct mesa_ip6_hdr *ip6_h;
|
||||
|
||||
if(!buf){
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip6_h = (struct mesa_ip6_hdr *)buf;
|
||||
|
||||
memset(ip6_h, 0, sizeof(struct mesa_ip6_hdr));
|
||||
|
||||
ip6_h->ip6_flags[0] = 0x60 | ((traffic_class & 0xF0) >> 4);
|
||||
ip6_h->ip6_flags[1] = ((traffic_class & 0x0F) << 4) | ((flow_lable & 0xF0000) >> 16);
|
||||
ip6_h->ip6_flags[2] = flow_lable & 0x0FF00 >> 8;
|
||||
ip6_h->ip6_flags[3] = flow_lable & 0x000FF;
|
||||
ip6_h->ip6_payload_len = htons(len);
|
||||
ip6_h->ip6_nxt_hdr = next_header;
|
||||
ip6_h->ip6_hop = hop;
|
||||
memcpy(&ip6_h->ip6_src, src, sizeof(struct in6_addr));
|
||||
memcpy(&ip6_h->ip6_dst, dst, sizeof(struct in6_addr));
|
||||
|
||||
if(payload && payload_s)
|
||||
{
|
||||
memcpy(buf + sizeof(struct mesa_ip6_hdr), payload, payload_s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int deliver_build_ipv4(unsigned short carry_layer_len, unsigned char tos, unsigned short id,
|
||||
unsigned short frag, unsigned char ttl, unsigned char prot, unsigned int src, unsigned int dst,
|
||||
const unsigned char *payload,int payload_s, unsigned char *buf)
|
||||
{
|
||||
struct mesa_ip4_hdr *ip_hdr;
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ip_hdr = (struct mesa_ip4_hdr *)buf;
|
||||
|
||||
ip_hdr->ip_v = 4; /* version 4 */
|
||||
ip_hdr->ip_hl = 5; /* 20 byte header */
|
||||
ip_hdr->ip_tos = tos; /* IP tos */
|
||||
ip_hdr->ip_len = htons(SENDPACKET_IP_H + carry_layer_len); /* total length */
|
||||
ip_hdr->ip_id = htons(id); /* IP ID */
|
||||
ip_hdr->ip_off = htons(frag); /* fragmentation flags */
|
||||
ip_hdr->ip_ttl = ttl; /* time to live */
|
||||
ip_hdr->ip_p = prot; /* transport protocol */
|
||||
ip_hdr->ip_sum = 0; /* do this later */
|
||||
ip_hdr->ip_src.s_addr = src; /* 为什么地址用网络序? 历史遗留原因, 改动太多,只能这么继续了 */
|
||||
ip_hdr->ip_dst.s_addr = dst; /* 为什么地址用网络序? 历史遗留原因, 改动太多,只能这么继续了 */
|
||||
if (payload && payload_s)
|
||||
{
|
||||
memcpy(buf + SENDPACKET_IP_H, payload, payload_s);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int deliver_build_tcp(unsigned short sp, unsigned short dp, unsigned int seq, unsigned int ack,
|
||||
unsigned char th_flags, unsigned short win, unsigned short urg,
|
||||
const unsigned char *payload, int payload_s, unsigned char *buf)
|
||||
{
|
||||
struct mesa_tcp_hdr *tcp_hdr;
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tcp_hdr = (struct mesa_tcp_hdr *)buf;
|
||||
|
||||
tcp_hdr->th_sport = htons(sp); /* source port */
|
||||
tcp_hdr->th_dport = htons(dp); /* destination port */
|
||||
tcp_hdr->th_seq = htonl(seq); /* sequence number */
|
||||
tcp_hdr->th_ack = htonl(ack); /* acknowledgement number */
|
||||
tcp_hdr->th_flags = th_flags; /* control flags */
|
||||
tcp_hdr->th_x2 = 0; /* UNUSED */
|
||||
tcp_hdr->th_off = 5; /* 20 byte header */
|
||||
tcp_hdr->th_win = htons(win); /* window size */
|
||||
tcp_hdr->th_sum = 0; /* checksum done in userland */
|
||||
tcp_hdr->th_urp = urg; /* urgent pointer */
|
||||
|
||||
if (payload && payload_s)
|
||||
{
|
||||
// memcpy(buf + SENDPACKET_TCP_H, payload, payload_s);
|
||||
memcpy(buf + sizeof(struct mesa_tcp_hdr), payload, payload_s);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user