194 lines
5.7 KiB
C++
194 lines
5.7 KiB
C++
// This file is built with libzt.a via `make tests`
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <net/if.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/udp.h>
|
|
|
|
#if defined(__APPLE__)
|
|
#include <net/ethernet.h>
|
|
#endif
|
|
#if defined(__linux__)
|
|
#include <netinet/ether.h>
|
|
#include <sys/socket.h>
|
|
#include <linux/if_packet.h>
|
|
#include <net/ethernet.h>
|
|
#endif
|
|
|
|
#include "libzt.h"
|
|
|
|
unsigned short csum(unsigned short *buf, int nwords)
|
|
{
|
|
unsigned long sum;
|
|
for(sum=0; nwords>0; nwords--)
|
|
sum += *buf++;
|
|
sum = (sum >> 16) + (sum &0xffff);
|
|
sum += (sum >> 16);
|
|
return (unsigned short)(~sum);
|
|
}
|
|
|
|
int main(int argc , char *argv[])
|
|
{
|
|
if (argc < 3) {
|
|
fprintf(stderr, "usage: layer2 <zt_home_dir> <nwid>\n");
|
|
return 1;
|
|
}
|
|
|
|
// initialize library
|
|
printf("Starting libzt...\n");
|
|
zts_startjoin(argv[1], strtoull(argv[2], NULL, 16));
|
|
uint64_t device_id = zts_get_node_id();
|
|
fprintf(stderr, "Complete. I am %llx\n", device_id);
|
|
|
|
// create socket
|
|
int fd;
|
|
if ((fd = zts_socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) {
|
|
printf("There was a problem creating the raw socket\n");
|
|
exit(-1);
|
|
}
|
|
fprintf(stderr, "Created raw socket (%d)\n", fd);
|
|
|
|
#if defined(__APPLE__)
|
|
fprintf(stderr, "SOCK_RAW not supported on mac builds yet. exiting");
|
|
exit(0);
|
|
#endif
|
|
#if defined(__linux__) // The rest of this file isn't yet supported on non-linux platforms
|
|
// get interface index to bind on
|
|
struct ifreq if_idx;
|
|
memset(&if_idx, 0, sizeof(struct ifreq));
|
|
strncpy(if_idx.ifr_name, "libzt0", IFNAMSIZ-1);
|
|
if (zts_ioctl(fd, SIOCGIFINDEX, &if_idx) < 0) {
|
|
perror("SIOCGIFINDEX");
|
|
exit(-1);
|
|
}
|
|
fprintf(stderr, "if_idx.ifr_ifindex=%d\n", if_idx.ifr_ifindex);
|
|
|
|
// get MAC address of interface to send on
|
|
struct ifreq if_mac;
|
|
memset(&if_mac, 0, sizeof(struct ifreq));
|
|
strncpy(if_mac.ifr_name, "libzt0", IFNAMSIZ-1);
|
|
if (zts_ioctl(fd, SIOCGIFHWADDR, &if_mac) < 0) {
|
|
perror("SIOCGIFHWADDR");
|
|
exit(-1);
|
|
}
|
|
const unsigned char* mac=(unsigned char*)if_mac.ifr_hwaddr.sa_data;
|
|
fprintf(stderr, "hwaddr=%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
|
|
|
|
// get IP address of interface to send on
|
|
struct ifreq if_ip;
|
|
memset(&if_ip, 0, sizeof(struct ifreq));
|
|
strncpy(if_ip.ifr_name, "libzt0", IFNAMSIZ-1);
|
|
if (zts_ioctl(fd, SIOCGIFADDR, &if_ip) < 0) {
|
|
perror("SIOCGIFADDR");
|
|
exit(-1);
|
|
}
|
|
char ipv4_str[INET_ADDRSTRLEN];
|
|
struct sockaddr_in *in4 = (struct sockaddr_in *)&if_ip.ifr_addr;
|
|
inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN);
|
|
fprintf(stderr, "addr=%s", ipv4_str);
|
|
|
|
// construct ethernet header
|
|
int tx_len = 0;
|
|
char sendbuf[1024];
|
|
struct ether_header *eh = (struct ether_header *) sendbuf;
|
|
memset(sendbuf, 0, 1024);
|
|
|
|
// Ethernet header
|
|
eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0];
|
|
eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1];
|
|
eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2];
|
|
eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3];
|
|
eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4];
|
|
eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5];
|
|
|
|
// set destination MAC
|
|
int MY_DEST_MAC0 = 0x72;
|
|
int MY_DEST_MAC1 = 0x92;
|
|
int MY_DEST_MAC2 = 0xd4;
|
|
int MY_DEST_MAC3 = 0xfd;
|
|
int MY_DEST_MAC4 = 0x43;
|
|
int MY_DEST_MAC5 = 0x45;
|
|
|
|
eh->ether_dhost[0] = MY_DEST_MAC0;
|
|
eh->ether_dhost[1] = MY_DEST_MAC1;
|
|
eh->ether_dhost[2] = MY_DEST_MAC2;
|
|
eh->ether_dhost[3] = MY_DEST_MAC3;
|
|
eh->ether_dhost[4] = MY_DEST_MAC4;
|
|
eh->ether_dhost[5] = MY_DEST_MAC5;
|
|
eh->ether_type = htons(ETH_P_IP);
|
|
tx_len += sizeof(struct ether_header);
|
|
|
|
|
|
// Construct the IP header
|
|
int ttl = 64;
|
|
struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));
|
|
iph->ihl = 5;
|
|
iph->version = 4;
|
|
iph->tos = 16; // Low delay
|
|
iph->id = htons(54321);
|
|
iph->ttl = ttl; // hops
|
|
iph->protocol = 17; // UDP
|
|
// Source IP address, can be spoofed
|
|
iph->saddr = inet_addr(inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr));
|
|
// iph->saddr = inet_addr("192.168.0.112");
|
|
// Destination IP address
|
|
iph->daddr = inet_addr("10.7.7.1");
|
|
tx_len += sizeof(struct iphdr);
|
|
|
|
// Construct UDP header
|
|
struct udphdr *udph = (struct udphdr *) (sendbuf + sizeof(struct iphdr) + sizeof(struct ether_header));
|
|
udph->source = htons(3423);
|
|
udph->dest = htons(5342);
|
|
udph->check = 0; // skip
|
|
tx_len += sizeof(struct udphdr);
|
|
|
|
// Fill in UDP payload
|
|
sendbuf[tx_len++] = 0xde;
|
|
sendbuf[tx_len++] = 0xad;
|
|
sendbuf[tx_len++] = 0xbe;
|
|
sendbuf[tx_len++] = 0xef;
|
|
|
|
// Fill in remaining header info
|
|
// Length of UDP payload and header
|
|
udph->len = htons(tx_len - sizeof(struct ether_header) - sizeof(struct iphdr));
|
|
// Length of IP payload and header
|
|
iph->tot_len = htons(tx_len - sizeof(struct ether_header));
|
|
// Calculate IP checksum on completed header
|
|
iph->check = csum((unsigned short *)(sendbuf+sizeof(struct ether_header)), sizeof(struct iphdr)/2);
|
|
|
|
// Send packet
|
|
// Destination address
|
|
struct sockaddr_ll socket_address;
|
|
// Index of the network device
|
|
socket_address.sll_ifindex = if_idx.ifr_ifindex;
|
|
// Address length
|
|
socket_address.sll_halen = ETH_ALEN;
|
|
// Destination MAC
|
|
socket_address.sll_addr[0] = MY_DEST_MAC0;
|
|
socket_address.sll_addr[1] = MY_DEST_MAC1;
|
|
socket_address.sll_addr[2] = MY_DEST_MAC2;
|
|
socket_address.sll_addr[3] = MY_DEST_MAC3;
|
|
socket_address.sll_addr[4] = MY_DEST_MAC4;
|
|
socket_address.sll_addr[5] = MY_DEST_MAC5;
|
|
|
|
while(1)
|
|
{
|
|
usleep(10000);
|
|
// Send packet
|
|
if (zts_sendto(fd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0)
|
|
fprintf(stderr, "Send failed\n");
|
|
}
|
|
|
|
// dismantle all zt virtual taps
|
|
zts_stop();
|
|
#endif
|
|
return 0;
|
|
} |