blob: c1b7f03c1622e7319ec4c9d0571ccca97130dfc6 [file] [log] [blame]
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdint.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <stdio.h>
#include <assert.h>
#include <packetizer.h>
#include <stdexcept>
#include <fstream>
#ifdef DEBUG_MODE
# define debug(...) (__VA_ARGS__)
#else
# define debug(...) do { } while(0)
#endif
static __inline uint64_t
read_tsc(void)
{
uint64_t tsc;
__asm __volatile("rdtsc" : "=A" (tsc));
return tsc;
}
packetizer::packetizer(const char *target_mac, const char *eth_device,
const char *filename)
{
seqno = 0;
memcpy(this->target_mac, target_mac, 6);
strcpy(this->eth_device, eth_device);
strcpy(this->filename, filename);
memset(&myaddr, 0, sizeof(myaddr));
// setuid root to open a raw socket. if we fail, too bad
seteuid(0);
sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
seteuid(getuid());
if(sock < 0)
throw std::runtime_error("socket() failed! Maybe try running as root...");
myaddr.sll_ifindex = if_nametoindex(eth_device);
myaddr.sll_family = AF_PACKET;
int ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
if (ret < 0)
throw std::runtime_error("bind() failed!");
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(struct timeval)) < 0)
throw std::runtime_error("setsockopt() failed!");
// get MAC address of local ethernet device
struct ifreq ifr;
strcpy(ifr.ifr_name, eth_device);
ret = ioctl(sock, SIOCGIFHWADDR, (char *)&ifr);
if (ret < 0)
throw std::runtime_error("ioctl() failed!");
memcpy(&host_mac, &ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
}
int packetizer::start()
{
std::ifstream file(filename, std::ios::in | std::ios::binary);
packet p(target_mac, host_mac, seqno, MAX_PAYLOAD_SIZE, NULL);
int ret;
printf("Starting to packetize the file: %s\n", filename);
file.read(p.payload, MAX_PAYLOAD_SIZE);
while(file) {
//printf("Sending chunk %d\n", seqno);
ret = ::sendto(sock, (char*)&p, p.size(), 0,
(sockaddr*)&myaddr,sizeof(myaddr));
volatile uint64_t tsc = read_tsc();
while((read_tsc() - tsc) < 34800);
if (ret < 0)
throw std::runtime_error("sending packet failed!");
p.header.seqno = htons(next_seqno());
file.read(p.payload, MAX_PAYLOAD_SIZE);
}
if(file.gcount()) {
p.header.payload_size = ntohl(file.gcount());
p.packet_size = sizeof(p.header)+file.gcount();
ret = ::sendto(sock, (char*)&p, p.size(), 0,
(sockaddr*)&myaddr,sizeof(myaddr));
if (ret < 0)
throw std::runtime_error("sending packet failed!");
//printf("Sending chunk %d\n", seqno);
}
printf("Last chunk had %u bytes...\n", file.gcount());
}
int main(int argc, char** argv)
{
char target_mac[6];
char eth_device[256];
char filename[256];
if(argc == 1) {
target_mac[0] = 0x00;
target_mac[1] = 0x24;
target_mac[2] = 0x1d;
target_mac[3] = 0x10;
target_mac[4] = 0xa2;
target_mac[5] = 0xb5;
strcpy(eth_device, "eth0");
strcpy(filename, "../../fs/i686/tests/e.y4m");
}
if(argc > 1) {
assert(argc == 4);
assert(strlen(argv[1]) == 17);
sscanf(argv[1], "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&target_mac[0],
(unsigned int *)&target_mac[1],
(unsigned int *)&target_mac[2],
(unsigned int *)&target_mac[3],
(unsigned int *)&target_mac[4],
(unsigned int *)&target_mac[5]);
strcpy(eth_device, argv[2]);
strcpy(filename, argv[3]);
}
packetizer p(target_mac, eth_device, filename);
p.start();
return 0;
}