2019-06-06 18:41:40 +08:00
|
|
|
#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>
|
2019-06-08 15:54:35 +08:00
|
|
|
#include <traffic_mirror.h>
|
2019-06-06 18:41:40 +08:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|