mirror of
https://code.semirocket.science/wrapsix
synced 2024-11-10 00:01:01 +02:00
Completed TCP with fragmenting in IPv6 packets
Modified TCP in 6to4 way to use special IP address
This commit is contained in:
parent
32e7d6459b
commit
e7d8a4c1dd
@ -39,10 +39,47 @@ void send_there(struct in_addr ip4_addr, unsigned char ttl, unsigned int type, u
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void send_raw_ipv4(struct in_addr ip4_addr, unsigned char *packet, int packet_size)
|
||||
{
|
||||
struct sockaddr_in socket_address;
|
||||
|
||||
unsigned char on = 1;
|
||||
int sock;
|
||||
|
||||
/* prepare data for RAW socket */
|
||||
socket_address.sin_family = AF_INET;
|
||||
socket_address.sin_port = htons(0);
|
||||
memcpy(&socket_address.sin_addr.s_addr, &ip4_addr, sizeof(struct in_addr));
|
||||
|
||||
/* initialize raw socket */
|
||||
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {
|
||||
fprintf(stderr, "Couldn't open RAW socket.\n");
|
||||
perror("socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* we will provide our own IPv4 header */
|
||||
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
|
||||
fprintf(stderr, "Couldn't apply the socket settings.\n");
|
||||
perror("setsockopt()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* send the packet */
|
||||
if (sendto(sock, packet, packet_size, 0, (struct sockaddr *) &socket_address, sizeof(struct sockaddr)) != packet_size) {
|
||||
fprintf(stderr, "Couldn't send a RAW packet.\n");
|
||||
perror("sendto()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* close the socket */
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void send_raw(unsigned char *packet, int packet_size)
|
||||
{
|
||||
struct sockaddr_ll socket_address; /* target address */
|
||||
struct ifreq ifr; /* interface */
|
||||
struct sockaddr_ll socket_address;
|
||||
struct ifreq ifr;
|
||||
|
||||
int sock;
|
||||
|
||||
@ -72,9 +109,9 @@ void send_raw(unsigned char *packet, int packet_size)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* send the NDP packet */
|
||||
/* send the packet */
|
||||
if (sendto(sock, packet, packet_size, 0, (struct sockaddr *) &socket_address, sizeof(struct sockaddr_ll)) != packet_size) {
|
||||
fprintf(stderr, " Error: Couldn't send an IPv6 packet.\n");
|
||||
fprintf(stderr, "Couldn't send a RAW packet.\n");
|
||||
perror("sendto()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -5,8 +5,6 @@
|
||||
#include "translate_ip.h"
|
||||
#include "storage.h"
|
||||
|
||||
struct in6_addr ip6addr_wrapsix;
|
||||
|
||||
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
{
|
||||
const struct s_ethernet *eth; /* the ethernet header */
|
||||
@ -30,7 +28,7 @@ void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char
|
||||
process_arp(eth, payload);
|
||||
break;
|
||||
default:
|
||||
printf("\n IP: unknown (%d/0x%x)\n", htons(eth->type), htons(eth->type));
|
||||
printf("\n Proto: unknown (%d/0x%x)\n", htons(eth->type), htons(eth->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -55,7 +53,7 @@ void process_packet4(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
printf(" To: %s\n", inet_ntoa(ip->ip_dest));
|
||||
|
||||
/* check if this packet is ours */
|
||||
if (memcmp(dev_ip, &ip->ip_dest, 4)) {
|
||||
if (memcmp(&ip4addr_wrapsix, &ip->ip_dest, 4)) {
|
||||
printf("==> This packet is not ours! <==\n");
|
||||
return;
|
||||
}
|
||||
@ -82,12 +80,19 @@ void process_packet4(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
|
||||
void process_tcp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const unsigned char *payload, unsigned short data_size)
|
||||
{
|
||||
struct s_tcp *tcp;
|
||||
struct ip6_hdr *ip;
|
||||
struct s_ethernet *eth;
|
||||
struct ip6_hdr *ip;
|
||||
struct s_ip6_fragment *ip_frag;
|
||||
struct s_tcp *tcp;
|
||||
|
||||
unsigned char *packet;
|
||||
unsigned int packet_size;
|
||||
unsigned short packet_size;
|
||||
unsigned char do_frag = 0;
|
||||
unsigned char last_frag = 0;
|
||||
unsigned short frag_size = 1514 - SIZE_ETHERNET - SIZE_IP6 - 8 - 4; /* 4 for alignment */
|
||||
unsigned short data_frag_size;
|
||||
unsigned char *data_offset;
|
||||
unsigned short data_frag_offset = 0;
|
||||
|
||||
struct stg_conn_tup *ent = NULL;
|
||||
struct stg_conn_tup *ent_tmp;
|
||||
@ -121,11 +126,42 @@ void process_tcp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
printf(" IP-from: %s\n", inet_ntoa(ip_hdr->ip_src));
|
||||
return;
|
||||
}
|
||||
ent->packet_num++;
|
||||
|
||||
/* set the checksum to zero */
|
||||
tcp->checksum = 0x0;
|
||||
|
||||
/* compute the TCP checksum */
|
||||
tcp->checksum = checksum_ipv6(ipaddr_4to6(ent->addr_to), ent->addr_from, data_size, IPPROTO_TCP, (unsigned char *) payload);
|
||||
printf(" Checksum: 0x%x\n", tcp->checksum);
|
||||
|
||||
/* handle fragmentation */
|
||||
packet_size = data_size + SIZE_ETHERNET + SIZE_IP6;
|
||||
packet = (unsigned char *) malloc(packet_size);
|
||||
|
||||
if (packet == NULL) {
|
||||
/* check if the packet is not too big => fragment */
|
||||
if (packet_size > 1514) {
|
||||
do_frag = 1;
|
||||
printf("...fragmenting: %d B\n", packet_size);
|
||||
}
|
||||
|
||||
/* send so many packets how many is needed */
|
||||
while (data_size) {
|
||||
if (do_frag && data_size > frag_size) {
|
||||
packet_size = 1514 - 4;
|
||||
data_frag_size = frag_size;
|
||||
}
|
||||
else if (do_frag) {
|
||||
packet_size = SIZE_ETHERNET + SIZE_IP6 + 8 + data_size;
|
||||
data_frag_size = data_size;
|
||||
last_frag = 1;
|
||||
printf("...last fragment\n");
|
||||
}
|
||||
else {
|
||||
data_frag_size = data_size;
|
||||
printf("...not fragmenting: %d B\n", packet_size);
|
||||
}
|
||||
|
||||
if ((packet = (unsigned char *) malloc(packet_size)) == NULL) {
|
||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -136,6 +172,29 @@ void process_tcp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
/* parse the packet into structures */
|
||||
eth = (struct s_ethernet *) packet;
|
||||
ip = (struct ip6_hdr *) (packet + SIZE_ETHERNET);
|
||||
if (do_frag) {
|
||||
if ((ip_frag = (struct s_ip6_fragment *) malloc(sizeof(struct s_ip6_fragment))) == NULL) {
|
||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
data_offset = (unsigned char *) (packet + SIZE_ETHERNET + SIZE_IP6 + sizeof(struct s_ip6_fragment));
|
||||
memset(ip_frag, 0x0, sizeof(struct s_ip6_fragment));
|
||||
|
||||
ip_frag->next_header = IPPROTO_TCP;
|
||||
ip_frag->zeros = 0x0;
|
||||
ip_frag->id = htonl(ent->port + ent->packet_num);
|
||||
ip_frag->offset_flag = (htons((data_frag_offset / 8) << 3));
|
||||
if (!last_frag) {
|
||||
ip_frag->offset_flag |= htons(0x1);
|
||||
}
|
||||
|
||||
// copy it & free it
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6, ip_frag, sizeof(struct s_ip6_fragment));
|
||||
free(ip_frag);
|
||||
}
|
||||
else {
|
||||
data_offset = (unsigned char *) (ip + SIZE_IP6);
|
||||
}
|
||||
|
||||
/* assemble the ethernet header */
|
||||
memcpy(ð->src, mac, sizeof(struct s_mac_addr));
|
||||
@ -143,34 +202,47 @@ void process_tcp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
eth->type = htons(ETHERTYPE_IPV6);
|
||||
|
||||
/* assemble the IPv6 header */
|
||||
if (do_frag) {
|
||||
build_ip6_hdr(ip, /* ip6_hdr structure */
|
||||
ipaddr_4to6(ent->addr_to), /* source address */
|
||||
ent->addr_from, /* destination address */
|
||||
data_size, /* payload length */
|
||||
data_frag_size + 8, /* payload length + fragment header */
|
||||
IPPROTO_FRAGMENT, /* protocol */
|
||||
ip_hdr->ttl); /* ttl */
|
||||
}
|
||||
else {
|
||||
build_ip6_hdr(ip, /* ip6_hdr structure */
|
||||
ipaddr_4to6(ent->addr_to), /* source address */
|
||||
ent->addr_from, /* destination address */
|
||||
data_frag_size, /* payload length */
|
||||
IPPROTO_TCP, /* protocol */
|
||||
ip_hdr->ttl); /* ttl */
|
||||
}
|
||||
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ent->addr_from, ip6addr, sizeof(ip6addr));
|
||||
printf(" Send to: %s\n", ip6addr);
|
||||
|
||||
/* set the checksum to zero */
|
||||
tcp->checksum = 0x0;
|
||||
|
||||
/* copy data into the packet */
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6, payload, data_size);
|
||||
|
||||
/* compute the TCP checksum */
|
||||
tcp->checksum = checksum_ipv6(ip->ip6_src, ip->ip6_dst, data_size, ip->ip6_nxt, (unsigned char *) (packet + SIZE_ETHERNET + SIZE_IP6));
|
||||
|
||||
/* return the checksum into the packet */
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6, tcp, sizeof(struct s_tcp));
|
||||
if (!do_frag) {
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6, payload, data_frag_size);
|
||||
}
|
||||
else {
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6 + sizeof(struct s_ip6_fragment), (unsigned char *) (payload + data_frag_offset), data_frag_size);
|
||||
}
|
||||
|
||||
/* send the wrapped packet back */
|
||||
send_raw(packet, packet_size);
|
||||
|
||||
/* free allocated memory */
|
||||
free(packet);
|
||||
packet = NULL;
|
||||
eth = NULL;
|
||||
ip = NULL;
|
||||
|
||||
data_size -= data_frag_size;
|
||||
data_frag_offset += data_frag_size;
|
||||
}
|
||||
}
|
||||
|
||||
void process_udp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const unsigned char *payload, unsigned short data_size)
|
||||
@ -471,8 +543,7 @@ void process_packet6(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
inet_ntop(AF_INET6, &ip->ip_dest, ip6addr, sizeof(ip6addr));
|
||||
printf(" To: %s\n", ip6addr);
|
||||
|
||||
/* check if this packet is ours - partially hardcoded for now */
|
||||
inet_pton(AF_INET6, "fc00:1::", &ip6addr_wrapsix);
|
||||
/* check if this packet is ours */
|
||||
inet_pton(AF_INET6, "ff02::1:ff00:0", &ip6addr_ndp_multicast);
|
||||
/* check for our prefix || NDP */
|
||||
if (memcmp(&ip6addr_wrapsix, &ip->ip_dest, 12) != 0
|
||||
@ -501,18 +572,20 @@ void process_packet6(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
}
|
||||
}
|
||||
|
||||
void process_tcp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload)
|
||||
void process_tcp6(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, const unsigned char *payload)
|
||||
{
|
||||
struct s_ip4 *ip;
|
||||
struct s_tcp *tcp;
|
||||
struct in_addr ip4_addr_src, ip4_addr_dest;
|
||||
struct in_addr ip4_addr;
|
||||
|
||||
unsigned char *tcp_packet;
|
||||
unsigned char *packet;
|
||||
unsigned char ent_save = 0;
|
||||
|
||||
struct stg_conn_tup *ent;
|
||||
struct stg_conn_tup *ent_tmp;
|
||||
|
||||
unsigned short packet_size = htons(ip->len);
|
||||
unsigned short data_size = htons(ip_hdr->len);
|
||||
unsigned short packet_size = sizeof(struct s_ip4) + data_size;
|
||||
|
||||
/* define TCP header */
|
||||
tcp = (struct s_tcp *) payload;
|
||||
@ -539,9 +612,10 @@ void process_tcp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned
|
||||
/* save the connection */
|
||||
ent = (struct stg_conn_tup *) malloc(sizeof(struct stg_conn_tup));
|
||||
ent->port = htons(tcp->port_src);
|
||||
ent->addr_from = ip->ip_src;
|
||||
ent->mac = eth->src;
|
||||
ent->addr_from = ip_hdr->ip_src;
|
||||
ent->mac = eth_hdr->src;
|
||||
time(&ent->time);
|
||||
ent->packet_num = 0;
|
||||
memset(&ent->addr_to, 0x0, sizeof(struct in_addr));
|
||||
ent_save = 1;
|
||||
}
|
||||
@ -553,36 +627,43 @@ void process_tcp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned
|
||||
}
|
||||
|
||||
/* decide where to send this TCP */
|
||||
ip4_addr_dest = ipaddr_6to4(ip->ip_dest);
|
||||
printf(" Send to: %s\n", inet_ntoa(ip4_addr_dest));
|
||||
ip4_addr = ipaddr_6to4(ip_hdr->ip_dest);
|
||||
printf(" Send to: %s\n", inet_ntoa(ip4_addr));
|
||||
|
||||
/* create one big TCP packet */
|
||||
tcp_packet = (unsigned char *) malloc(packet_size);
|
||||
packet = (unsigned char *) malloc(packet_size);
|
||||
|
||||
if (tcp_packet == NULL) {
|
||||
if (packet == NULL) {
|
||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* first set the checksum to zero */
|
||||
tcp->checksum = 0x0;
|
||||
|
||||
/* copy data into the packet */
|
||||
memcpy(tcp_packet, payload, packet_size);
|
||||
/* assemble IPv4 header */
|
||||
ip = (struct s_ip4 *) packet;
|
||||
ip->ver_ihl = 0x45;
|
||||
ip->tos = 0x0;
|
||||
ip->pckt_len = htons(packet_size);
|
||||
ip->flags_offset = htons(0x4000);
|
||||
ip->id = 0x0;
|
||||
ip->ttl = ip_hdr->hop_limit;
|
||||
ip->proto = IPPROTO_TCP;
|
||||
ip->checksum = 0x0; /* it is computed automatically */
|
||||
ip->ip_src = ip4addr_wrapsix;
|
||||
ip->ip_dest = ip4_addr;
|
||||
|
||||
/* compute the checksum */
|
||||
memcpy(&ip4_addr_src, dev_ip, sizeof(struct in_addr));
|
||||
tcp->checksum = checksum_ipv4(ip4_addr_src, ip4_addr_dest, packet_size, IPPROTO_TCP, tcp_packet);
|
||||
tcp->checksum = 0x0;
|
||||
tcp->checksum = checksum_ipv4(ip4addr_wrapsix, ip4_addr, data_size, IPPROTO_TCP, (unsigned char *) payload);
|
||||
|
||||
/* copy this structure again - because of the checksum */
|
||||
memcpy(tcp_packet, tcp, sizeof(struct s_tcp));
|
||||
/* copy data into the packet */
|
||||
memcpy(packet + sizeof(struct s_ip4), payload, data_size);
|
||||
|
||||
/* send */
|
||||
send_there(ip4_addr_dest, ip->hop_limit, IPPROTO_TCP, tcp_packet, packet_size);
|
||||
send_raw_ipv4(ip->ip_dest, packet, packet_size);
|
||||
|
||||
/* save the connection */
|
||||
if (ent_save == 1) {
|
||||
ent->addr_to = ip4_addr_dest;
|
||||
ent->addr_to = ip4_addr;
|
||||
jsw_rbinsert(stg_conn_tcp, ent);
|
||||
printf(" Conn #: %d\n", jsw_rbsize(stg_conn_tcp));
|
||||
/* the entry is not needed now and should be freed */
|
||||
@ -590,8 +671,8 @@ void process_tcp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned
|
||||
}
|
||||
|
||||
/* free allocated memory */
|
||||
free(tcp_packet);
|
||||
tcp_packet = NULL;
|
||||
free(packet);
|
||||
packet = NULL;
|
||||
}
|
||||
|
||||
void process_udp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload)
|
||||
|
@ -16,6 +16,7 @@ struct stg_conn_tup {
|
||||
struct in6_addr addr_from;
|
||||
struct s_mac_addr mac;
|
||||
time_t time;
|
||||
unsigned int packet_num;
|
||||
};
|
||||
|
||||
struct stg_conn_icmp {
|
||||
|
@ -5,6 +5,7 @@ struct s_mac_addr *mac; /* MAC address of the device */
|
||||
char *dev; /* capture device name */
|
||||
int dev_index; /* capture device index */
|
||||
struct in_addr *dev_ip; /* IP address associated with the device */
|
||||
struct in6_addr ip6addr_wrapsix; /* IPv6 prefix of WrapSix addresses */
|
||||
struct in_addr ip4addr_wrapsix; /* IPv4 address for WrapSix */
|
||||
|
||||
/* storage trees */
|
||||
@ -70,8 +71,9 @@ int main(int argc, char **argv)
|
||||
/* get index of the device */
|
||||
dev_index = get_dev_index(dev);
|
||||
|
||||
/* set the WrapSix IPv4 address */
|
||||
/* set the WrapSix addresses */
|
||||
inet_aton("10.0.0.111", &ip4addr_wrapsix);
|
||||
inet_pton(AF_INET6, "fc00:1::", &ip6addr_wrapsix);
|
||||
|
||||
/* compile the filter expression */
|
||||
if (pcap_compile(handle, &fp, filter_exp, 0, 0) == -1) {
|
||||
|
@ -97,6 +97,14 @@ struct s_ip6_pseudo {
|
||||
unsigned char next_header; /* 8 b; next header */
|
||||
};
|
||||
|
||||
/* IPv6 fragment header */
|
||||
struct s_ip6_fragment {
|
||||
unsigned char next_header; /* 8 b; next header */
|
||||
unsigned char zeros; /* 8 b; reserved */
|
||||
unsigned short offset_flag; /* 16 b; 13 b - data offset, 2 b - reserved, 1 b - flag */
|
||||
unsigned int id; /* 32 b; identification */
|
||||
};
|
||||
|
||||
/* TCP structure */
|
||||
struct s_tcp {
|
||||
unsigned short port_src; /* 16 b; source port */
|
||||
@ -187,13 +195,14 @@ void process_icmp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const
|
||||
void process_arp(const struct s_ethernet *eth_hdr, const unsigned char *arp_packet);
|
||||
|
||||
void process_packet6(const struct s_ethernet *eth, const unsigned char *packet);
|
||||
void process_tcp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload);
|
||||
void process_tcp6(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, const unsigned char *payload);
|
||||
void process_udp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload);
|
||||
void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload);
|
||||
void process_ndp(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, unsigned char *icmp_data);
|
||||
|
||||
void send_there(struct in_addr ip4_addr, unsigned char ttl, unsigned int type, unsigned char *payload, unsigned int paylen);
|
||||
void send_raw(unsigned char *packet, int packet_size);
|
||||
void send_raw_ipv4(struct in_addr ip4_addr, unsigned char *packet, int packet_size);
|
||||
|
||||
unsigned short checksum(const void *_buf, int len);
|
||||
unsigned short checksum_ipv4(struct in_addr ip_src, struct in_addr ip_dest, unsigned short length, unsigned char proto, unsigned char *data);
|
||||
|
Loading…
Reference in New Issue
Block a user