mirror of
https://code.semirocket.science/wrapsix
synced 2024-11-10 00:01:01 +02:00
Backward translation of ICMP traffic
Fixed mistake in field type in pseudo-IPv6 header Bundled a library for red-black trees (storage mechanism is based on it)
This commit is contained in:
parent
39ba6988c0
commit
b6a9de321b
@ -1,15 +1,16 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -O0
|
||||
CFLAGS = -Wall -O0 -g
|
||||
LDFLAGS = -L/usr/lib -lpcap
|
||||
INCLUDE = -Ilib
|
||||
|
||||
all: wrapper.o process.o translate_ip.o connections.o checksum.o if.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) *.o -o wrapper
|
||||
all: wrapper.o process.o translate_ip.o connections.o checksum.o if.o storage.o lib/jsw_rbtree.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) *.o lib/*.o -o wrapper
|
||||
|
||||
wrapper.o: wrapper.c wrapper.h
|
||||
$(CC) $(CFLAGS) -c wrapper.c -o wrapper.o
|
||||
$(CC) $(CFLAGS) $(INCLUDE) -c wrapper.c -o wrapper.o
|
||||
|
||||
process.o: process.c wrapper.h translate_ip.h
|
||||
$(CC) $(CFLAGS) -c process.c -o process.o
|
||||
$(CC) $(CFLAGS) $(INCLUDE) -c process.c -o process.o
|
||||
|
||||
translate_ip.o: translate_ip.c translate_ip.h wrapper.h
|
||||
$(CC) $(CFLAGS) -c translate_ip.c -o translate_ip.o
|
||||
@ -23,5 +24,12 @@ checksum.o: checksum.c
|
||||
if.o: if.c wrapper.h
|
||||
$(CC) $(CFLAGS) -c if.c -o if.o
|
||||
|
||||
storage.o: storage.c storage.h
|
||||
$(CC) $(CFLAGS) $(INCLUDE) -c storage.c -o storage.o
|
||||
|
||||
# libraries
|
||||
lib/jsw_rbtree.o: lib/jsw_rbtree.c lib/jsw_rbtree.h
|
||||
$(CC) $(CFLAGS) -c lib/jsw_rbtree.c -o lib/jsw_rbtree.o
|
||||
|
||||
clean:
|
||||
rm -f wrapper *.o
|
||||
rm -f wrapper *.o lib/*.o
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "wrapper.h"
|
||||
|
||||
unsigned short checksum(const void *_buf, int len)
|
||||
{
|
||||
const unsigned short *buf = _buf;
|
||||
unsigned sum = 0;
|
||||
unsigned int sum = 0;
|
||||
|
||||
while (len >= 2) {
|
||||
sum += *buf ++;
|
||||
@ -28,3 +30,35 @@ unsigned short checksum(const void *_buf, int len)
|
||||
|
||||
return ~sum;
|
||||
}
|
||||
|
||||
unsigned short checksum_ipv6(struct in6_addr ip_src, struct in6_addr ip_dest, unsigned short paylen, unsigned char proto, unsigned char *data)
|
||||
{
|
||||
unsigned char *buf_ip6_pseudo;
|
||||
struct s_ip6_pseudo *ip6_pseudo;
|
||||
unsigned short sum;
|
||||
unsigned int length = (unsigned int) paylen;
|
||||
|
||||
buf_ip6_pseudo = (unsigned char *) malloc(sizeof(struct s_ip6_pseudo) + length);
|
||||
|
||||
if (buf_ip6_pseudo == NULL) {
|
||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ip6_pseudo = (struct s_ip6_pseudo *) buf_ip6_pseudo;
|
||||
|
||||
ip6_pseudo->ip_src = ip_src;
|
||||
ip6_pseudo->ip_dest = ip_dest;
|
||||
ip6_pseudo->len = htonl(length);
|
||||
ip6_pseudo->zeros = 0x0;
|
||||
ip6_pseudo->next_header = proto;
|
||||
|
||||
memcpy(buf_ip6_pseudo + sizeof(struct s_ip6_pseudo), data, length);
|
||||
|
||||
sum = checksum(buf_ip6_pseudo, sizeof(struct s_ip6_pseudo) + length);
|
||||
|
||||
free(buf_ip6_pseudo);
|
||||
buf_ip6_pseudo = NULL;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
@ -5,26 +5,41 @@
|
||||
#include "wrapper.h"
|
||||
|
||||
void send_there(struct in_addr ip4_addr, unsigned char ttl, unsigned int type, unsigned char *payload, unsigned int paylen) {
|
||||
int sock;
|
||||
struct sockaddr_in sock_addr;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_RAW, type)) == -1) {
|
||||
fprintf(stderr, "Couldn't open RAW socket.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
setsockopt(sock, IPPROTO_IP, IP_TTL, (const char *) &ttl, sizeof(ttl));
|
||||
int sock;
|
||||
|
||||
/* prepare data for the socket */
|
||||
sock_addr.sin_family = AF_INET;
|
||||
sock_addr.sin_port = 0;
|
||||
sock_addr.sin_addr = ip4_addr;
|
||||
|
||||
sendto(sock, (char *) payload, paylen, 0, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr));
|
||||
/* initialize the socket */
|
||||
if ((sock = socket(AF_INET, SOCK_RAW, type)) == -1) {
|
||||
fprintf(stderr, "Couldn't open RAW socket.\n");
|
||||
perror("socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* applies settings of the socket */
|
||||
if (setsockopt(sock, IPPROTO_IP, IP_TTL, (const char *) &ttl, sizeof(ttl)) == -1) {
|
||||
fprintf(stderr, "Couldn't apply settings of the socket.\n");
|
||||
perror("setsockopt()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* send the packet */
|
||||
if (sendto(sock, (char *) payload, paylen, 0, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr)) != paylen) {
|
||||
fprintf(stderr, " Error: Couldn't send an IPv4 packet.\n");
|
||||
perror("sendto()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* close the socket */
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void send_ndp(struct ip6_hdr *ip, unsigned char *packet, int packet_size)
|
||||
void send_ipv6(unsigned char *packet, int packet_size)
|
||||
{
|
||||
struct sockaddr_ll socket_address; /* target address */
|
||||
struct ifreq ifr; /* interface */
|
||||
@ -34,7 +49,7 @@ void send_ndp(struct ip6_hdr *ip, unsigned char *packet, int packet_size)
|
||||
/* prepare data for RAW socket */
|
||||
socket_address.sll_family = PF_PACKET; /* RAW communication */
|
||||
socket_address.sll_protocol = htons(ETH_P_IP); /* protocol above the ethernet layer */
|
||||
socket_address.sll_ifindex = get_dev_index(dev); /* set index of the network device */
|
||||
socket_address.sll_ifindex = dev_index; /* set index of the network device */
|
||||
socket_address.sll_pkttype = PACKET_OTHERHOST; /* target host is another host */
|
||||
|
||||
/* initialize with zeros */
|
||||
@ -59,7 +74,7 @@ void send_ndp(struct ip6_hdr *ip, unsigned char *packet, int packet_size)
|
||||
|
||||
/* send the NDP packet */
|
||||
if (sendto(sock, packet, packet_size, 0, (struct sockaddr *) &socket_address, sizeof(struct sockaddr_ll)) != packet_size) {
|
||||
fprintf(stderr, " Error: Couldn't send NDP packet.\n");
|
||||
fprintf(stderr, " Error: Couldn't send an IPv6 packet.\n");
|
||||
perror("sendto()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
28
wrapper/if.c
28
wrapper/if.c
@ -31,6 +31,34 @@ int get_mac_addr(const char *dev, struct s_mac_addr *addr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the IP address
|
||||
*/
|
||||
int get_ip_addr(const char *dev, struct in_addr *addr)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int s, ret;
|
||||
|
||||
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&ifr, 0x00, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, dev);
|
||||
|
||||
if (ioctl(s, SIOCGIFADDR, &ifr) == 0) {
|
||||
memcpy(addr, &ifr.ifr_addr.sa_data[2], sizeof(struct in_addr));
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
close(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return device index
|
||||
*/
|
||||
|
582
wrapper/lib/jsw_rbtree.c
Normal file
582
wrapper/lib/jsw_rbtree.c
Normal file
@ -0,0 +1,582 @@
|
||||
/*
|
||||
Red Black balanced tree library
|
||||
|
||||
> Created (Julienne Walker): August 23, 2003
|
||||
> Modified (Julienne Walker): March 14, 2008
|
||||
*/
|
||||
#include "jsw_rbtree.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdlib>
|
||||
|
||||
using std::malloc;
|
||||
using std::free;
|
||||
using std::size_t;
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef HEIGHT_LIMIT
|
||||
#define HEIGHT_LIMIT 64 /* Tallest allowable tree */
|
||||
#endif
|
||||
|
||||
typedef struct jsw_rbnode {
|
||||
int red; /* Color (1=red, 0=black) */
|
||||
void *data; /* User-defined content */
|
||||
struct jsw_rbnode *link[2]; /* Left (0) and right (1) links */
|
||||
} jsw_rbnode_t;
|
||||
|
||||
struct jsw_rbtree {
|
||||
jsw_rbnode_t *root; /* Top of the tree */
|
||||
cmp_f cmp; /* Compare two items */
|
||||
dup_f dup; /* Clone an item (user-defined) */
|
||||
rel_f rel; /* Destroy an item (user-defined) */
|
||||
size_t size; /* Number of items (user-defined) */
|
||||
};
|
||||
|
||||
struct jsw_rbtrav {
|
||||
jsw_rbtree_t *tree; /* Paired tree */
|
||||
jsw_rbnode_t *it; /* Current node */
|
||||
jsw_rbnode_t *path[HEIGHT_LIMIT]; /* Traversal path */
|
||||
size_t top; /* Top of stack */
|
||||
};
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Checks the color of a red black node
|
||||
<summary>
|
||||
<param name="root">The node to check</param>
|
||||
<returns>1 for a red node, 0 for a black node</returns>
|
||||
<remarks>For jsw_rbtree.c internal use only</remarks>
|
||||
*/
|
||||
static int is_red ( jsw_rbnode_t *root )
|
||||
{
|
||||
return root != NULL && root->red == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Performs a single red black rotation in the specified direction
|
||||
This function assumes that all nodes are valid for a rotation
|
||||
<summary>
|
||||
<param name="root">The original root to rotate around</param>
|
||||
<param name="dir">The direction to rotate (0 = left, 1 = right)</param>
|
||||
<returns>The new root ater rotation</returns>
|
||||
<remarks>For jsw_rbtree.c internal use only</remarks>
|
||||
*/
|
||||
static jsw_rbnode_t *jsw_single ( jsw_rbnode_t *root, int dir )
|
||||
{
|
||||
jsw_rbnode_t *save = root->link[!dir];
|
||||
|
||||
root->link[!dir] = save->link[dir];
|
||||
save->link[dir] = root;
|
||||
|
||||
root->red = 1;
|
||||
save->red = 0;
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Performs a double red black rotation in the specified direction
|
||||
This function assumes that all nodes are valid for a rotation
|
||||
<summary>
|
||||
<param name="root">The original root to rotate around</param>
|
||||
<param name="dir">The direction to rotate (0 = left, 1 = right)</param>
|
||||
<returns>The new root after rotation</returns>
|
||||
<remarks>For jsw_rbtree.c internal use only</remarks>
|
||||
*/
|
||||
static jsw_rbnode_t *jsw_double ( jsw_rbnode_t *root, int dir )
|
||||
{
|
||||
root->link[!dir] = jsw_single ( root->link[!dir], !dir );
|
||||
|
||||
return jsw_single ( root, dir );
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Creates an initializes a new red black node with a copy of
|
||||
the data. This function does not insert the new node into a tree
|
||||
<summary>
|
||||
<param name="tree">The red black tree this node is being created for</param>
|
||||
<param name="data">The data value that will be stored in this node</param>
|
||||
<returns>A pointer to the new node</returns>
|
||||
<remarks>
|
||||
For jsw_rbtree.c internal use only. The data for this node must
|
||||
be freed using the same tree's rel function. The returned pointer
|
||||
must be freed using C's free function
|
||||
</remarks>
|
||||
*/
|
||||
static jsw_rbnode_t *new_node ( jsw_rbtree_t *tree, void *data )
|
||||
{
|
||||
jsw_rbnode_t *rn = (jsw_rbnode_t *)malloc ( sizeof *rn );
|
||||
|
||||
if ( rn == NULL )
|
||||
return NULL;
|
||||
|
||||
rn->red = 1;
|
||||
rn->data = tree->dup ( data );
|
||||
rn->link[0] = rn->link[1] = NULL;
|
||||
|
||||
return rn;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Creates and initializes an empty red black tree with
|
||||
user-defined comparison, data copy, and data release operations
|
||||
<summary>
|
||||
<param name="cmp">User-defined data comparison function</param>
|
||||
<param name="dup">User-defined data copy function</param>
|
||||
<param name="rel">User-defined data release function</param>
|
||||
<returns>A pointer to the new tree</returns>
|
||||
<remarks>
|
||||
The returned pointer must be released with jsw_rbdelete
|
||||
</remarks>
|
||||
*/
|
||||
jsw_rbtree_t *jsw_rbnew ( cmp_f cmp, dup_f dup, rel_f rel )
|
||||
{
|
||||
jsw_rbtree_t *rt = (jsw_rbtree_t *)malloc ( sizeof *rt );
|
||||
|
||||
if ( rt == NULL )
|
||||
return NULL;
|
||||
|
||||
rt->root = NULL;
|
||||
rt->cmp = cmp;
|
||||
rt->dup = dup;
|
||||
rt->rel = rel;
|
||||
rt->size = 0;
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Releases a valid red black tree
|
||||
<summary>
|
||||
<param name="tree">The tree to release</param>
|
||||
<remarks>
|
||||
The tree must have been created using jsw_rbnew
|
||||
</remarks>
|
||||
*/
|
||||
void jsw_rbdelete ( jsw_rbtree_t *tree )
|
||||
{
|
||||
jsw_rbnode_t *it = tree->root;
|
||||
jsw_rbnode_t *save;
|
||||
|
||||
/*
|
||||
Rotate away the left links so that
|
||||
we can treat this like the destruction
|
||||
of a linked list
|
||||
*/
|
||||
while ( it != NULL ) {
|
||||
if ( it->link[0] == NULL ) {
|
||||
/* No left links, just kill the node and move on */
|
||||
save = it->link[1];
|
||||
tree->rel ( it->data );
|
||||
free ( it );
|
||||
}
|
||||
else {
|
||||
/* Rotate away the left link and check again */
|
||||
save = it->link[0];
|
||||
it->link[0] = save->link[1];
|
||||
save->link[1] = it;
|
||||
}
|
||||
|
||||
it = save;
|
||||
}
|
||||
|
||||
free ( tree );
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Search for a copy of the specified
|
||||
node data in a red black tree
|
||||
<summary>
|
||||
<param name="tree">The tree to search</param>
|
||||
<param name="data">The data value to search for</param>
|
||||
<returns>
|
||||
A pointer to the data value stored in the tree,
|
||||
or a null pointer if no data could be found
|
||||
</returns>
|
||||
*/
|
||||
void *jsw_rbfind ( jsw_rbtree_t *tree, void *data )
|
||||
{
|
||||
jsw_rbnode_t *it = tree->root;
|
||||
|
||||
while ( it != NULL ) {
|
||||
int cmp = tree->cmp ( it->data, data );
|
||||
|
||||
if ( cmp == 0 )
|
||||
break;
|
||||
|
||||
/*
|
||||
If the tree supports duplicates, they should be
|
||||
chained to the right subtree for this to work
|
||||
*/
|
||||
it = it->link[cmp < 0];
|
||||
}
|
||||
|
||||
return it == NULL ? NULL : it->data;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Insert a copy of the user-specified
|
||||
data into a red black tree
|
||||
<summary>
|
||||
<param name="tree">The tree to insert into</param>
|
||||
<param name="data">The data value to insert</param>
|
||||
<returns>
|
||||
1 if the value was inserted successfully,
|
||||
0 if the insertion failed for any reason
|
||||
</returns>
|
||||
*/
|
||||
int jsw_rbinsert ( jsw_rbtree_t *tree, void *data )
|
||||
{
|
||||
if ( tree->root == NULL ) {
|
||||
/*
|
||||
We have an empty tree; attach the
|
||||
new node directly to the root
|
||||
*/
|
||||
tree->root = new_node ( tree, data );
|
||||
|
||||
if ( tree->root == NULL )
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
jsw_rbnode_t head = {0}; /* False tree root */
|
||||
jsw_rbnode_t *g, *t; /* Grandparent & parent */
|
||||
jsw_rbnode_t *p, *q; /* Iterator & parent */
|
||||
int dir = 0, last = 0;
|
||||
|
||||
/* Set up our helpers */
|
||||
t = &head;
|
||||
g = p = NULL;
|
||||
q = t->link[1] = tree->root;
|
||||
|
||||
/* Search down the tree for a place to insert */
|
||||
for ( ; ; ) {
|
||||
if ( q == NULL ) {
|
||||
/* Insert a new node at the first null link */
|
||||
p->link[dir] = q = new_node ( tree, data );
|
||||
|
||||
if ( q == NULL )
|
||||
return 0;
|
||||
}
|
||||
else if ( is_red ( q->link[0] ) && is_red ( q->link[1] ) ) {
|
||||
/* Simple red violation: color flip */
|
||||
q->red = 1;
|
||||
q->link[0]->red = 0;
|
||||
q->link[1]->red = 0;
|
||||
}
|
||||
|
||||
if ( is_red ( q ) && is_red ( p ) ) {
|
||||
/* Hard red violation: rotations necessary */
|
||||
int dir2 = t->link[1] == g;
|
||||
|
||||
if ( q == p->link[last] )
|
||||
t->link[dir2] = jsw_single ( g, !last );
|
||||
else
|
||||
t->link[dir2] = jsw_double ( g, !last );
|
||||
}
|
||||
|
||||
/*
|
||||
Stop working if we inserted a node. This
|
||||
check also disallows duplicates in the tree
|
||||
*/
|
||||
if ( tree->cmp ( q->data, data ) == 0 )
|
||||
break;
|
||||
|
||||
last = dir;
|
||||
dir = tree->cmp ( q->data, data ) < 0;
|
||||
|
||||
/* Move the helpers down */
|
||||
if ( g != NULL )
|
||||
t = g;
|
||||
|
||||
g = p, p = q;
|
||||
q = q->link[dir];
|
||||
}
|
||||
|
||||
/* Update the root (it may be different) */
|
||||
tree->root = head.link[1];
|
||||
}
|
||||
|
||||
/* Make the root black for simplified logic */
|
||||
tree->root->red = 0;
|
||||
++tree->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Remove a node from a red black tree
|
||||
that matches the user-specified data
|
||||
<summary>
|
||||
<param name="tree">The tree to remove from</param>
|
||||
<param name="data">The data value to search for</param>
|
||||
<returns>
|
||||
1 if the value was removed successfully,
|
||||
0 if the removal failed for any reason
|
||||
</returns>
|
||||
<remarks>
|
||||
The most common failure reason should be
|
||||
that the data was not found in the tree
|
||||
</remarks>
|
||||
*/
|
||||
int jsw_rberase ( jsw_rbtree_t *tree, void *data )
|
||||
{
|
||||
if ( tree->root != NULL ) {
|
||||
jsw_rbnode_t head = {0}; /* False tree root */
|
||||
jsw_rbnode_t *q, *p, *g; /* Helpers */
|
||||
jsw_rbnode_t *f = NULL; /* Found item */
|
||||
int dir = 1;
|
||||
|
||||
/* Set up our helpers */
|
||||
q = &head;
|
||||
g = p = NULL;
|
||||
q->link[1] = tree->root;
|
||||
|
||||
/*
|
||||
Search and push a red node down
|
||||
to fix red violations as we go
|
||||
*/
|
||||
while ( q->link[dir] != NULL ) {
|
||||
int last = dir;
|
||||
|
||||
/* Move the helpers down */
|
||||
g = p, p = q;
|
||||
q = q->link[dir];
|
||||
dir = tree->cmp ( q->data, data ) < 0;
|
||||
|
||||
/*
|
||||
Save the node with matching data and keep
|
||||
going; we'll do removal tasks at the end
|
||||
*/
|
||||
if ( tree->cmp ( q->data, data ) == 0 )
|
||||
f = q;
|
||||
|
||||
/* Push the red node down with rotations and color flips */
|
||||
if ( !is_red ( q ) && !is_red ( q->link[dir] ) ) {
|
||||
if ( is_red ( q->link[!dir] ) )
|
||||
p = p->link[last] = jsw_single ( q, dir );
|
||||
else if ( !is_red ( q->link[!dir] ) ) {
|
||||
jsw_rbnode_t *s = p->link[!last];
|
||||
|
||||
if ( s != NULL ) {
|
||||
if ( !is_red ( s->link[!last] ) && !is_red ( s->link[last] ) ) {
|
||||
/* Color flip */
|
||||
p->red = 0;
|
||||
s->red = 1;
|
||||
q->red = 1;
|
||||
}
|
||||
else {
|
||||
int dir2 = g->link[1] == p;
|
||||
|
||||
if ( is_red ( s->link[last] ) )
|
||||
g->link[dir2] = jsw_double ( p, last );
|
||||
else if ( is_red ( s->link[!last] ) )
|
||||
g->link[dir2] = jsw_single ( p, last );
|
||||
|
||||
/* Ensure correct coloring */
|
||||
q->red = g->link[dir2]->red = 1;
|
||||
g->link[dir2]->link[0]->red = 0;
|
||||
g->link[dir2]->link[1]->red = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace and remove the saved node */
|
||||
if ( f != NULL ) {
|
||||
tree->rel ( f->data );
|
||||
f->data = q->data;
|
||||
p->link[p->link[1] == q] =
|
||||
q->link[q->link[0] == NULL];
|
||||
free ( q );
|
||||
}
|
||||
|
||||
/* Update the root (it may be different) */
|
||||
tree->root = head.link[1];
|
||||
|
||||
/* Make the root black for simplified logic */
|
||||
if ( tree->root != NULL )
|
||||
tree->root->red = 0;
|
||||
|
||||
--tree->size;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Gets the number of nodes in a red black tree
|
||||
<summary>
|
||||
<param name="tree">The tree to calculate a size for</param>
|
||||
<returns>The number of nodes in the tree</returns>
|
||||
*/
|
||||
size_t jsw_rbsize ( jsw_rbtree_t *tree )
|
||||
{
|
||||
return tree->size;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Create a new traversal object
|
||||
<summary>
|
||||
<returns>A pointer to the new object</returns>
|
||||
<remarks>
|
||||
The traversal object is not initialized until
|
||||
jsw_rbtfirst or jsw_rbtlast are called.
|
||||
The pointer must be released with jsw_rbtdelete
|
||||
</remarks>
|
||||
*/
|
||||
jsw_rbtrav_t *jsw_rbtnew ( void )
|
||||
{
|
||||
return (jsw_rbtrav_t*)malloc ( sizeof ( jsw_rbtrav_t ) );
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Release a traversal object
|
||||
<summary>
|
||||
<param name="trav">The object to release</param>
|
||||
<remarks>
|
||||
The object must have been created with jsw_rbtnew
|
||||
</remarks>
|
||||
*/
|
||||
void jsw_rbtdelete ( jsw_rbtrav_t *trav )
|
||||
{
|
||||
free ( trav );
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Initialize a traversal object. The user-specified
|
||||
direction determines whether to begin traversal at the
|
||||
smallest or largest valued node
|
||||
<summary>
|
||||
<param name="trav">The traversal object to initialize</param>
|
||||
<param name="tree">The tree that the object will be attached to</param>
|
||||
<param name="dir">
|
||||
The direction to traverse (0 = ascending, 1 = descending)
|
||||
</param>
|
||||
<returns>A pointer to the smallest or largest data value</returns>
|
||||
<remarks>For jsw_rbtree.c internal use only</remarks>
|
||||
*/
|
||||
static void *start ( jsw_rbtrav_t *trav, jsw_rbtree_t *tree, int dir )
|
||||
{
|
||||
trav->tree = tree;
|
||||
trav->it = tree->root;
|
||||
trav->top = 0;
|
||||
|
||||
/* Save the path for later traversal */
|
||||
if ( trav->it != NULL ) {
|
||||
while ( trav->it->link[dir] != NULL ) {
|
||||
trav->path[trav->top++] = trav->it;
|
||||
trav->it = trav->it->link[dir];
|
||||
}
|
||||
}
|
||||
|
||||
return trav->it == NULL ? NULL : trav->it->data;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Traverse a red black tree in the user-specified direction
|
||||
<summary>
|
||||
<param name="trav">The initialized traversal object</param>
|
||||
<param name="dir">
|
||||
The direction to traverse (0 = ascending, 1 = descending)
|
||||
</param>
|
||||
<returns>
|
||||
A pointer to the next data value in the specified direction
|
||||
</returns>
|
||||
<remarks>For jsw_rbtree.c internal use only</remarks>
|
||||
*/
|
||||
static void *move ( jsw_rbtrav_t *trav, int dir )
|
||||
{
|
||||
if ( trav->it->link[dir] != NULL ) {
|
||||
/* Continue down this branch */
|
||||
trav->path[trav->top++] = trav->it;
|
||||
trav->it = trav->it->link[dir];
|
||||
|
||||
while ( trav->it->link[!dir] != NULL ) {
|
||||
trav->path[trav->top++] = trav->it;
|
||||
trav->it = trav->it->link[!dir];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Move to the next branch */
|
||||
jsw_rbnode_t *last;
|
||||
|
||||
do {
|
||||
if ( trav->top == 0 ) {
|
||||
trav->it = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
last = trav->it;
|
||||
trav->it = trav->path[--trav->top];
|
||||
} while ( last == trav->it->link[dir] );
|
||||
}
|
||||
|
||||
return trav->it == NULL ? NULL : trav->it->data;
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Initialize a traversal object to the smallest valued node
|
||||
<summary>
|
||||
<param name="trav">The traversal object to initialize</param>
|
||||
<param name="tree">The tree that the object will be attached to</param>
|
||||
<returns>A pointer to the smallest data value</returns>
|
||||
*/
|
||||
void *jsw_rbtfirst ( jsw_rbtrav_t *trav, jsw_rbtree_t *tree )
|
||||
{
|
||||
return start ( trav, tree, 0 ); /* Min value */
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Initialize a traversal object to the largest valued node
|
||||
<summary>
|
||||
<param name="trav">The traversal object to initialize</param>
|
||||
<param name="tree">The tree that the object will be attached to</param>
|
||||
<returns>A pointer to the largest data value</returns>
|
||||
*/
|
||||
void *jsw_rbtlast ( jsw_rbtrav_t *trav, jsw_rbtree_t *tree )
|
||||
{
|
||||
return start ( trav, tree, 1 ); /* Max value */
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Traverse to the next value in ascending order
|
||||
<summary>
|
||||
<param name="trav">The initialized traversal object</param>
|
||||
<returns>A pointer to the next value in ascending order</returns>
|
||||
*/
|
||||
void *jsw_rbtnext ( jsw_rbtrav_t *trav )
|
||||
{
|
||||
return move ( trav, 1 ); /* Toward larger items */
|
||||
}
|
||||
|
||||
/**
|
||||
<summary>
|
||||
Traverse to the next value in descending order
|
||||
<summary>
|
||||
<param name="trav">The initialized traversal object</param>
|
||||
<returns>A pointer to the next value in descending order</returns>
|
||||
*/
|
||||
void *jsw_rbtprev ( jsw_rbtrav_t *trav )
|
||||
{
|
||||
return move ( trav, 0 ); /* Toward smaller items */
|
||||
}
|
||||
|
60
wrapper/lib/jsw_rbtree.h
Normal file
60
wrapper/lib/jsw_rbtree.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef JSW_RBTREE_H
|
||||
#define JSW_RBTREE_H
|
||||
|
||||
/*
|
||||
Red Black balanced tree library
|
||||
|
||||
> Created (Julienne Walker): August 23, 2003
|
||||
> Modified (Julienne Walker): March 14, 2008
|
||||
|
||||
This code is in the public domain. Anyone may
|
||||
use it or change it in any way that they see
|
||||
fit. The author assumes no responsibility for
|
||||
damages incurred through use of the original
|
||||
code or any variations thereof.
|
||||
|
||||
It is requested, but not required, that due
|
||||
credit is given to the original author and
|
||||
anyone who has modified the code through
|
||||
a header comment, such as this one.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#include <cstddef>
|
||||
|
||||
using std::size_t;
|
||||
|
||||
extern "C" {
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
/* Opaque types */
|
||||
typedef struct jsw_rbtree jsw_rbtree_t;
|
||||
typedef struct jsw_rbtrav jsw_rbtrav_t;
|
||||
|
||||
/* User-defined item handling */
|
||||
typedef int (*cmp_f) ( const void *p1, const void *p2 );
|
||||
typedef void *(*dup_f) ( void *p );
|
||||
typedef void (*rel_f) ( void *p );
|
||||
|
||||
/* Red Black tree functions */
|
||||
jsw_rbtree_t *jsw_rbnew ( cmp_f cmp, dup_f dup, rel_f rel );
|
||||
void jsw_rbdelete ( jsw_rbtree_t *tree );
|
||||
void *jsw_rbfind ( jsw_rbtree_t *tree, void *data );
|
||||
int jsw_rbinsert ( jsw_rbtree_t *tree, void *data );
|
||||
int jsw_rberase ( jsw_rbtree_t *tree, void *data );
|
||||
size_t jsw_rbsize ( jsw_rbtree_t *tree );
|
||||
|
||||
/* Traversal functions */
|
||||
jsw_rbtrav_t *jsw_rbtnew ( void );
|
||||
void jsw_rbtdelete ( jsw_rbtrav_t *trav );
|
||||
void *jsw_rbtfirst ( jsw_rbtrav_t *trav, jsw_rbtree_t *tree );
|
||||
void *jsw_rbtlast ( jsw_rbtrav_t *trav, jsw_rbtree_t *tree );
|
||||
void *jsw_rbtnext ( jsw_rbtrav_t *trav );
|
||||
void *jsw_rbtprev ( jsw_rbtrav_t *trav );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,29 +1,212 @@
|
||||
#include <net/ethernet.h>
|
||||
|
||||
#include "wrapper.h"
|
||||
#include "translate_ip.h"
|
||||
#include "storage.h"
|
||||
|
||||
struct in6_addr ip6addr_wrapsix;
|
||||
|
||||
void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
{
|
||||
const struct s_ethernet *ethernet; /* the ethernet header */
|
||||
const struct s_ip6 *ip; /* the IP header */
|
||||
const struct s_ethernet *eth; /* the ethernet header */
|
||||
const unsigned char *payload; /* the IP header + packet payload */
|
||||
|
||||
/* define ethernet header */
|
||||
eth = (struct s_ethernet*) (packet);
|
||||
payload = packet + SIZE_ETHERNET;
|
||||
|
||||
switch (htons(eth->type)) {
|
||||
case ETHERTYPE_IP:
|
||||
printf("\n IP: 4\n");
|
||||
process_packet4(eth, payload);
|
||||
break;
|
||||
case ETHERTYPE_IPV6:
|
||||
printf("\n IP: 6\n");
|
||||
process_packet6(eth, payload);
|
||||
break;
|
||||
default:
|
||||
printf("\n IP: unknown (%d/0x%x)\n", htons(eth->type), htons(eth->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*** IPv4 ***/
|
||||
void process_packet4(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
{
|
||||
struct s_ip4 *ip; /* the IP header */
|
||||
const unsigned char *payload; /* packet payload */
|
||||
|
||||
unsigned short header_length;
|
||||
|
||||
/* define/compute IP header offset */
|
||||
ip = (struct s_ip4 *) packet;
|
||||
header_length = (ip->ver_ihl & 0x0f) * 4;
|
||||
|
||||
/* define/compute IP payload offset */
|
||||
payload = packet + header_length;
|
||||
|
||||
/* DEBUG: print source and destination IP addresses */
|
||||
printf(" From: %s\n", inet_ntoa(ip->ip_src));
|
||||
printf(" To: %s\n", inet_ntoa(ip->ip_dest));
|
||||
|
||||
/* check if this packet is ours */
|
||||
if (memcmp(dev_ip, &ip->ip_dest, 4)) {
|
||||
printf("==> This packet is not ours! <==\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* determine protocol */
|
||||
switch (ip->proto) {
|
||||
case IPPROTO_TCP:
|
||||
printf(" Protocol: TCP\n");
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
printf(" Protocol: UDP\n");
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
printf(" Protocol: ICMP\n");
|
||||
process_icmp4(eth, ip, payload, htons(ip->pckt_len) - header_length);
|
||||
break;
|
||||
default:
|
||||
printf(" Protocol: unknown (%d/0x%x)\n", ip->proto, ip->proto);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void process_icmp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const unsigned char *payload, unsigned short data_size)
|
||||
{
|
||||
struct s_icmp *icmp;
|
||||
struct ip6_hdr *ip;
|
||||
struct s_ethernet *eth;
|
||||
|
||||
unsigned char *icmp_data;
|
||||
unsigned char *packet;
|
||||
unsigned int packet_size;
|
||||
|
||||
struct stg_conn_icmp *ent = NULL;
|
||||
struct stg_conn_icmp *ent_tmp;
|
||||
|
||||
/* define ICMP header */
|
||||
icmp = (struct s_icmp *) payload;
|
||||
/* define/compute ICMP data offset */
|
||||
icmp_data = (unsigned char *) (payload + sizeof(struct s_icmp));
|
||||
|
||||
/* decide what type of ICMP we have */
|
||||
switch (icmp->type) {
|
||||
case ICMP4_ECHO_REPLY:
|
||||
printf(" ICMP: Echo Reply\n");
|
||||
|
||||
struct s_icmp_ping *icmp_ping;
|
||||
icmp_ping = (struct s_icmp_ping *) icmp_data;
|
||||
|
||||
/* create temporary data entry for finding */
|
||||
if ((ent_tmp = (struct stg_conn_icmp *) malloc(sizeof(struct stg_conn_icmp))) == NULL) {
|
||||
fprintf(stderr, "Fatal Error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* the only needed field is ID */
|
||||
ent_tmp->id = htons(icmp_ping->id);
|
||||
|
||||
/* find the appropriate connection */
|
||||
ent = jsw_rbfind(stg_conn_icmp, ent_tmp);
|
||||
|
||||
/* free allocated memory */
|
||||
free(ent_tmp);
|
||||
|
||||
/* check if this packet is from wrapped connection */
|
||||
if (ent == NULL) {
|
||||
fprintf(stderr, "Error: data not found\n");
|
||||
return;
|
||||
}
|
||||
else if (memcmp(&ent->addr_to, &ip_hdr->ip_src, sizeof(struct in_addr))) {
|
||||
fprintf(stderr, "Error: data not appropriate\n");
|
||||
printf(" Ent-to: %s\n", inet_ntoa(ent->addr_to));
|
||||
printf(" IP-from: %s\n", inet_ntoa(ip_hdr->ip_src));
|
||||
return;
|
||||
}
|
||||
|
||||
/* wrap it back */
|
||||
icmp->type = ICMP6_ECHO_REPLY;
|
||||
icmp->code = 0;
|
||||
icmp->checksum = 0;
|
||||
|
||||
break;
|
||||
default:
|
||||
printf(" ICMP: unknown (%d/0x%x)\n", icmp->type, icmp->type);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
packet_size = data_size + SIZE_ETHERNET + SIZE_IP6;
|
||||
packet = (unsigned char *) malloc(packet_size);
|
||||
|
||||
if (packet == NULL) {
|
||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* initialize the packet with zeros */
|
||||
memset(packet, 0x0, packet_size);
|
||||
|
||||
/* parse the packet into structures */
|
||||
eth = (struct s_ethernet *) packet;
|
||||
ip = (struct ip6_hdr *) (packet + SIZE_ETHERNET);
|
||||
|
||||
/* assemble the ethernet header */
|
||||
memcpy(ð->src, mac, sizeof(struct s_mac_addr));
|
||||
eth->dest = ent->mac;
|
||||
eth->type = htons(ETHERTYPE_IPV6);
|
||||
|
||||
/* assemble the IPv6 header */
|
||||
build_ip6_hdr(ip, /* ip6_hdr structure */
|
||||
ipaddr_4to6(ent->addr_to), /* source address */
|
||||
ent->addr_from, /* destination address */
|
||||
data_size, /* payload length */
|
||||
IPPROTO_ICMPV6, /* protocol */
|
||||
255); /* ttl */
|
||||
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ent->addr_from, ip6addr, sizeof(ip6addr));
|
||||
printf(" Send to: %s\n", ip6addr);
|
||||
|
||||
/* copy ICMP header */
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6, icmp, sizeof(struct s_icmp));
|
||||
|
||||
/* copy ICMP data */
|
||||
memcpy(packet + SIZE_ETHERNET + SIZE_IP6 + sizeof(struct s_icmp), icmp_data, data_size - sizeof(struct s_icmp));
|
||||
|
||||
/* compute the ICMP checksum */
|
||||
icmp->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, icmp, sizeof(struct s_icmp));
|
||||
|
||||
/* send the wrapped packet back */
|
||||
send_ipv6(packet, packet_size);
|
||||
|
||||
/* free allocated memory */
|
||||
free(packet);
|
||||
}
|
||||
|
||||
/*** IPv6 ***/
|
||||
void process_packet6(const struct s_ethernet *eth, const unsigned char *packet)
|
||||
{
|
||||
struct s_ip6 *ip; /* the IP header */
|
||||
const unsigned char *payload; /* packet payload */
|
||||
|
||||
struct in6_addr ip6addr_ndp_multicast;
|
||||
|
||||
/* define ethernet header */
|
||||
ethernet = (struct s_ethernet*) (packet);
|
||||
|
||||
/* define/compute IP header offset */
|
||||
ip = (struct s_ip6*) (packet + SIZE_ETHERNET);
|
||||
ip = (struct s_ip6 *) packet;
|
||||
|
||||
/* define/compute IP payload offset */
|
||||
payload = packet + SIZE_ETHERNET + SIZE_IP6;
|
||||
payload = packet + SIZE_IP6;
|
||||
|
||||
/* DEBUG: print source and destination IP addresses */
|
||||
char ip6addr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ip->ip_src, ip6addr, sizeof(ip6addr));
|
||||
printf("\n From: %s\n", ip6addr);
|
||||
printf(" From: %s\n", ip6addr);
|
||||
inet_ntop(AF_INET6, &ip->ip_dest, ip6addr, sizeof(ip6addr));
|
||||
printf(" To: %s\n", ip6addr);
|
||||
|
||||
@ -41,20 +224,18 @@ void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_cha
|
||||
switch (ip->next_header) {
|
||||
case IPPROTO_TCP:
|
||||
printf(" Protocol: TCP\n");
|
||||
//process_tcp();
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
printf(" Protocol: UDP\n");
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
printf(" Protocol: ICMPv6\n");
|
||||
process_icmp6((const struct s_ethernet *) ethernet, (struct s_ip6 *) ip, payload);
|
||||
process_icmp6(eth, ip, payload);
|
||||
break;
|
||||
default:
|
||||
printf(" Protocol: unknown\n");
|
||||
printf(" Protocol: unknown (%d/0x%x)\n", ip->next_header, ip->next_header);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload)
|
||||
@ -64,8 +245,12 @@ void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigne
|
||||
|
||||
unsigned char *icmp_data;
|
||||
unsigned char *icmp_packet;
|
||||
unsigned char ent_save = 0;
|
||||
|
||||
int packet_size = htons(ip->len);
|
||||
struct stg_conn_icmp *ent;
|
||||
struct stg_conn_icmp *ent_tmp;
|
||||
|
||||
unsigned short packet_size = htons(ip->len);
|
||||
|
||||
/* define ICMP header */
|
||||
icmp = (struct s_icmp *) (payload);
|
||||
@ -85,10 +270,46 @@ void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigne
|
||||
case ICMP6_ECHO_REQUEST:
|
||||
printf(" ICMP: Echo Request\n");
|
||||
|
||||
/* DEBUG */
|
||||
struct s_icmp_ping *icmp_ping = (struct s_icmp_ping *) icmp_data;
|
||||
/* DEBUG */
|
||||
printf("[id;seq]:[0x%x;0x%x]\n", htons(icmp_ping->id), htons(icmp_ping->seq));
|
||||
|
||||
/* check whether the connection is not already saved */
|
||||
/* create temporary data entry for finding */
|
||||
if ((ent_tmp = (struct stg_conn_icmp *) malloc(sizeof(struct stg_conn_icmp))) == NULL) {
|
||||
fprintf(stderr, "Fatal Error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* the only needed field is ID */
|
||||
ent_tmp->id = htons(icmp_ping->id);
|
||||
|
||||
/* find the appropriate connection */
|
||||
ent = jsw_rbfind(stg_conn_icmp, ent_tmp);
|
||||
|
||||
/* free allocated memory */
|
||||
free(ent_tmp);
|
||||
|
||||
/* check if this packet is from wrapped connection */
|
||||
if (ent == NULL) {
|
||||
printf("New connection\n");
|
||||
/* save the connection */
|
||||
ent = (struct stg_conn_icmp *) malloc(sizeof(struct stg_conn_icmp));
|
||||
ent->id = htons(icmp_ping->id);
|
||||
ent->addr_from = ip->ip_src;
|
||||
ent->mac = eth->src;
|
||||
ent->is_ping = 1;
|
||||
time(&ent->time);
|
||||
memset(&ent->addr_to, 0x0, sizeof(struct in_addr));
|
||||
ent_save = 1;
|
||||
}
|
||||
else {
|
||||
printf("Connection found\n");
|
||||
printf(" Conn #: %d\n", jsw_rbsize(stg_conn_icmp));
|
||||
/* set fresh timestamp */
|
||||
time(&ent->time);
|
||||
}
|
||||
|
||||
/* fill into the header known statements */
|
||||
icmp->type = ICMP4_ECHO_REQUEST;
|
||||
icmp->code = 0;
|
||||
@ -100,7 +321,7 @@ void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigne
|
||||
break;
|
||||
/* nothing interesting */
|
||||
default:
|
||||
printf(" ICMP: unknown: %d/0x%x\n", icmp->type, icmp->type);
|
||||
printf(" ICMP: unknown: (%d/0x%x)\n", icmp->type, icmp->type);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
@ -127,12 +348,21 @@ void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigne
|
||||
memcpy(icmp_packet, icmp, sizeof(struct s_icmp));
|
||||
|
||||
/* decide where to send this ICMP */
|
||||
ip4_addr = ipaddr_6to4((struct in6_addr) ip->ip_dest);
|
||||
ip4_addr = ipaddr_6to4(ip->ip_dest);
|
||||
printf(" Send to: %s\n", inet_ntoa(ip4_addr));
|
||||
|
||||
/* send */
|
||||
send_there(ip4_addr, ip->hop_limit, IPPROTO_ICMP, icmp_packet, packet_size);
|
||||
|
||||
/* save the connection */
|
||||
if (ent_save == 1) {
|
||||
ent->addr_to = ip4_addr;
|
||||
jsw_rbinsert(stg_conn_icmp, ent);
|
||||
printf(" Conn #: %d\n", jsw_rbsize(stg_conn_icmp));
|
||||
/* the entry is not needed now and should be freed */
|
||||
free(ent);
|
||||
}
|
||||
|
||||
/* free allocated memory */
|
||||
free(icmp_packet);
|
||||
icmp_packet = NULL;
|
||||
@ -147,10 +377,7 @@ void process_ndp(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, unsigne
|
||||
struct s_icmp_ndp_ns *ndp_ns;
|
||||
struct s_icmp_ndp_na *ndp_na;
|
||||
|
||||
unsigned char *buf_ip6_pseudo;
|
||||
struct s_ip6_pseudo *ip6_pseudo;
|
||||
|
||||
int packet_size;
|
||||
unsigned short packet_size;
|
||||
|
||||
/* get the NDP data */
|
||||
ndp_ns = (struct s_icmp_ndp_ns *) icmp_data;
|
||||
@ -182,13 +409,12 @@ void process_ndp(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, unsigne
|
||||
eth->type = eth_hdr->type;
|
||||
|
||||
/* assemble the IPv6 header */
|
||||
ip->ip6_src = ndp_ns->target;
|
||||
ip->ip6_dst = ip_hdr->ip_src;
|
||||
ip->ip6_flow = 0;
|
||||
ip->ip6_vfc = 0x60;
|
||||
ip->ip6_plen = htons(sizeof(struct s_icmp) + sizeof(struct s_icmp_ndp_na));
|
||||
ip->ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip->ip6_hlim = 255;
|
||||
build_ip6_hdr(ip, /* ip6_hdr structure */
|
||||
ndp_ns->target, /* source address */
|
||||
ip_hdr->ip_src, /* destination address */
|
||||
sizeof(struct s_icmp) + sizeof(struct s_icmp_ndp_na), /* payload length */
|
||||
IPPROTO_ICMPV6, /* protocol */
|
||||
255); /* ttl */
|
||||
|
||||
/* assemble the ICMP header */
|
||||
icmp->type = ICMP6_NDP_NA;
|
||||
@ -206,31 +432,12 @@ void process_ndp(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, unsigne
|
||||
memcpy(&ndp_na->o_tlla, mac, sizeof(struct s_mac_addr));
|
||||
|
||||
/* compute the ICMP checksum */
|
||||
buf_ip6_pseudo = (unsigned char *) malloc(sizeof(struct s_ip6_pseudo) + htons(ip->ip6_plen));
|
||||
|
||||
if (buf_ip6_pseudo == NULL) {
|
||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ip6_pseudo = (struct s_ip6_pseudo *) buf_ip6_pseudo;
|
||||
|
||||
ip6_pseudo->ip_src = ip->ip6_src;
|
||||
ip6_pseudo->ip_dest = ip->ip6_dst;
|
||||
ip6_pseudo->len = ip->ip6_plen;
|
||||
ip6_pseudo->zeros = 0x0;
|
||||
ip6_pseudo->next_header = ip->ip6_nxt;
|
||||
|
||||
memcpy(buf_ip6_pseudo + sizeof(struct s_ip6_pseudo), icmp, htons(ip->ip6_plen));
|
||||
|
||||
icmp->checksum = checksum(buf_ip6_pseudo, sizeof(struct s_ip6_pseudo) + htons(ip->ip6_plen));
|
||||
icmp->checksum = checksum_ipv6(ip->ip6_src, ip->ip6_dst, htons(ip->ip6_plen), ip->ip6_nxt, (unsigned char *) icmp);
|
||||
|
||||
/* send the packet */
|
||||
send_ndp(ip, packet, packet_size);
|
||||
send_ipv6(packet, packet_size);
|
||||
|
||||
/* free allocated memory */
|
||||
free(packet);
|
||||
free(buf_ip6_pseudo);
|
||||
packet = NULL;
|
||||
buf_ip6_pseudo = NULL;
|
||||
}
|
||||
|
32
wrapper/storage.c
Normal file
32
wrapper/storage.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include "storage.h"
|
||||
|
||||
int stg_conn_icmp_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
struct stg_conn_icmp *pp1 = (struct stg_conn_icmp *) p1;
|
||||
struct stg_conn_icmp *pp2 = (struct stg_conn_icmp *) p2;
|
||||
|
||||
if (pp1->id < pp2->id) return -1;
|
||||
if (pp1->id > pp2->id) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *stg_conn_icmp_dup(void *p)
|
||||
{
|
||||
struct stg_conn_icmp *pp = (struct stg_conn_icmp *) p;
|
||||
struct stg_conn_icmp *p_new;
|
||||
|
||||
if ((p_new = (struct stg_conn_icmp *) malloc(sizeof(struct stg_conn_icmp))) == NULL) {
|
||||
fprintf(stderr, "Fatal Error! Lack of free memory!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memcpy(p_new, pp, sizeof(struct stg_conn_icmp));
|
||||
|
||||
return (void *) p_new;
|
||||
}
|
||||
|
||||
void stg_conn_icmp_rel(void *p)
|
||||
{
|
||||
free(p);
|
||||
p = NULL;
|
||||
}
|
28
wrapper/storage.h
Normal file
28
wrapper/storage.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef STORAGE_H
|
||||
#define STORAGE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "jsw_rbtree.h"
|
||||
#include "wrapper.h"
|
||||
|
||||
struct stg_conn_icmp {
|
||||
unsigned short id;
|
||||
struct in_addr addr_to;
|
||||
struct in6_addr addr_from;
|
||||
struct s_mac_addr mac;
|
||||
unsigned char is_ping;
|
||||
time_t time;
|
||||
};
|
||||
|
||||
int stg_conn_icmp_cmp(const void *p1, const void *p2);
|
||||
void *stg_conn_icmp_dup(void *p);
|
||||
void stg_conn_icmp_rel(void *p);
|
||||
|
||||
extern jsw_rbtree_t *stg_conn_icmp;
|
||||
|
||||
#endif
|
@ -16,3 +16,46 @@ struct in_addr ipaddr_6to4(const struct in6_addr ip6_addr)
|
||||
|
||||
return ip4_addr;
|
||||
}
|
||||
|
||||
struct in6_addr ipaddr_4to6(const struct in_addr ip4_addr)
|
||||
{
|
||||
struct ip6addr_ip4part *addr;
|
||||
struct in6_addr ip6_addr;
|
||||
char ip4_str[15];
|
||||
char *ip4_p;
|
||||
unsigned int ip4_a[4];
|
||||
|
||||
/* create a temporary IPv6 variable */
|
||||
addr = (struct ip6addr_ip4part *) malloc(sizeof(struct ip6addr_ip4part));
|
||||
|
||||
/* copy IPv6 prefix of WrapSix IPv6 addresses */
|
||||
memcpy(addr, &ip6addr_wrapsix, 12);
|
||||
|
||||
/* copy the rest of the IPv6 address (the IPv4 address) */
|
||||
ip4_p = inet_ntoa(ip4_addr);
|
||||
memcpy(&ip4_str, ip4_p, 15);
|
||||
sscanf(ip4_str, "%d.%d.%d.%d", &ip4_a[0], &ip4_a[1], &ip4_a[2], &ip4_a[3]);
|
||||
addr->a = (unsigned char) ip4_a[0];
|
||||
addr->b = (unsigned char) ip4_a[1];
|
||||
addr->c = (unsigned char) ip4_a[2];
|
||||
addr->d = (unsigned char) ip4_a[3];
|
||||
|
||||
/* copy the complete IPv6 address */
|
||||
memcpy(&ip6_addr, addr, sizeof(struct in6_addr));
|
||||
|
||||
/* free allocated memory */
|
||||
free(addr);
|
||||
|
||||
return ip6_addr;
|
||||
}
|
||||
|
||||
void build_ip6_hdr(struct ip6_hdr *ip, struct in6_addr ip_src, struct in6_addr ip_dest, unsigned short paylen, unsigned char proto, unsigned char ttl)
|
||||
{
|
||||
ip->ip6_src = ip_src;
|
||||
ip->ip6_dst = ip_dest;
|
||||
ip->ip6_flow = 0;
|
||||
ip->ip6_vfc = 0x60;
|
||||
ip->ip6_plen = htons(paylen);
|
||||
ip->ip6_nxt = proto;
|
||||
ip->ip6_hlim = ttl;
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef TRANSLATE_IP_H
|
||||
#define TRANSLATE_IP_H
|
||||
|
||||
#include <netinet/in.h> /* in6_addr, in_addr */
|
||||
#include <netinet/ip6.h> /* ip6_hdr */
|
||||
|
||||
struct ip6addr_ip4part {
|
||||
long double prefix;
|
||||
unsigned char a;
|
||||
@ -10,6 +13,8 @@ struct ip6addr_ip4part {
|
||||
};
|
||||
|
||||
struct in_addr ipaddr_6to4(const struct in6_addr ip6_addr);
|
||||
//in6_addr ipaddr_4to6(in_addr ip_addr);
|
||||
struct in6_addr ipaddr_4to6(const struct in_addr ip_addr);
|
||||
|
||||
void build_ip6_hdr(struct ip6_hdr *ip, struct in6_addr ip_src, struct in6_addr ip_dest, unsigned short paylen, unsigned char proto, unsigned char ttl);
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,13 @@
|
||||
#include "wrapper.h"
|
||||
#include "storage.h"
|
||||
|
||||
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 */
|
||||
|
||||
/* storage trees */
|
||||
jsw_rbtree_t *stg_conn_icmp;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -11,10 +16,13 @@ int main(int argc, char **argv)
|
||||
pcap_t *handle; /* packet capture handle */
|
||||
|
||||
//char filter_exp[] = "ip6"; /* filter expression */
|
||||
char filter_exp[] = "icmp6"; /* filter expression */
|
||||
char filter_exp[] = "icmp6 or icmp"; /* filter expression */
|
||||
struct bpf_program fp; /* compiled filter program (expression) */
|
||||
int num_packets = 0; /* number of packets to capture; 0 = infinite */
|
||||
|
||||
/* initialize the storage for connections */
|
||||
stg_conn_icmp = jsw_rbnew(&stg_conn_icmp_cmp, &stg_conn_icmp_dup, &stg_conn_icmp_rel);
|
||||
|
||||
/* find a capture device */
|
||||
dev = NULL;
|
||||
dev = pcap_lookupdev(errbuf);
|
||||
@ -48,6 +56,13 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* obtain IP address of the device */
|
||||
dev_ip = (struct in_addr *) malloc(sizeof(struct in_addr));
|
||||
if (get_ip_addr(dev, dev_ip) != 0) {
|
||||
fprintf(stderr, "Couldn't get device IP address\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* get index of the device */
|
||||
dev_index = get_dev_index(dev);
|
||||
|
||||
@ -64,12 +79,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* now we can set our callback function */
|
||||
pcap_loop(handle, num_packets, process_packet6, NULL);
|
||||
pcap_loop(handle, num_packets, process_packet, NULL);
|
||||
|
||||
/* cleanup */
|
||||
pcap_freecode(&fp);
|
||||
pcap_close(handle);
|
||||
|
||||
jsw_rbdelete(stg_conn_icmp);
|
||||
|
||||
free(mac);
|
||||
free(dev_ip);
|
||||
|
||||
printf("\nCapture complete.\n");
|
||||
|
||||
return 0;
|
||||
|
@ -41,6 +41,18 @@ struct s_ethernet {
|
||||
};
|
||||
|
||||
/* IPv4 header structure */
|
||||
struct s_ip4 {
|
||||
unsigned char ver_ihl;
|
||||
unsigned char tos; /* 8 b; type of service */
|
||||
unsigned short pckt_len; /* 16 b; total lenght of the packet (IP header + payload) */
|
||||
unsigned short id; /* 16 b; id of the packet - for purpose of fragmentation */
|
||||
unsigned short flags_offset; /* 16 b; 3 b - flags, 13 b - fragment offset in bytes */
|
||||
unsigned char ttl; /* 8 b; time to live */
|
||||
unsigned char proto; /* 8 b; protocol in the payload */
|
||||
unsigned short checksum; /* 16 b */
|
||||
struct in_addr ip_src; /* 32 b; source address */
|
||||
struct in_addr ip_dest; /* 32 b; destination address */
|
||||
};
|
||||
|
||||
/* IPv6 header structure */
|
||||
struct s_ip6 {
|
||||
@ -56,11 +68,9 @@ struct s_ip6 {
|
||||
|
||||
/* pseudo IPv6 header for checksum */
|
||||
struct s_ip6_pseudo {
|
||||
//unsigned short ip_src[8];
|
||||
//unsigned short ip_dest[8];
|
||||
struct in6_addr ip_src; /* 128 b; source address */
|
||||
struct in6_addr ip_dest; /* 128 b; destination address */
|
||||
unsigned short len; /* 16 b; payload length */
|
||||
unsigned int len; /* 32 b; payload length */
|
||||
unsigned int zeros:24; /* 24 b; reserved */
|
||||
unsigned char next_header; /* 8 b; next header */
|
||||
};
|
||||
@ -115,6 +125,9 @@ struct s_icmp_ndp_na {
|
||||
#define INNAF_S 0x40 /* solicited flag */
|
||||
#define INNAF_O 0x20 /* override flag */
|
||||
|
||||
/* Missing ethertypes */
|
||||
#define ETHERTYPE_IPV6 0x86dd
|
||||
|
||||
/* ICMP types */
|
||||
#define ICMP4_ECHO_REQUEST 0x8
|
||||
#define ICMP4_ECHO_REPLY 0x0
|
||||
@ -130,20 +143,29 @@ struct s_icmp_ndp_na {
|
||||
|
||||
/* Prototypes */
|
||||
int get_mac_addr(const char *dev, struct s_mac_addr *addr);
|
||||
int get_ip_addr(const char *dev, struct in_addr *addr);
|
||||
int get_dev_index(const char *dev);
|
||||
|
||||
void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
|
||||
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
|
||||
|
||||
void process_packet4(const struct s_ethernet *eth, const unsigned char *packet);
|
||||
void process_icmp4(const struct s_ethernet *eth_hdr, struct s_ip4 *ip_hdr, const unsigned char *payload, unsigned short packet_size);
|
||||
|
||||
void process_packet6(const struct s_ethernet *eth, const unsigned char *packet);
|
||||
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_ndp(struct ip6_hdr *ip, unsigned char *packet, int packet_size);
|
||||
void send_ipv6(unsigned char *packet, int packet_size);
|
||||
|
||||
unsigned short checksum(const void *_buf, int len);
|
||||
unsigned short checksum_ipv6(struct in6_addr ip_src, struct in6_addr ip_dest, unsigned short paylen, unsigned char proto, unsigned char *data);
|
||||
|
||||
/* Variables */
|
||||
extern struct s_mac_addr *mac; /* MAC address of the device */
|
||||
extern char *dev; /* capture device name */
|
||||
extern int dev_index; /* capture device index */
|
||||
extern struct in_addr *dev_ip; /* IP address associated with the device */
|
||||
extern struct in6_addr ip6addr_wrapsix; /* IPv6 prefix of WrapSix addresses */
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user