Flattened examples directory
This commit is contained in:
194
examples/layer2/layer2.cpp
Normal file
194
examples/layer2/layer2.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user