Commit ac750912 authored by Stig Venaas's avatar Stig Venaas
Browse files

lots of changes to handle IPv6 addresses, until now all data passed as uint....

lots of changes to handle IPv6 addresses, until now all data passed as uint. Source but not binary compatible with apps built with old topx.h. Set x to 1 if <1 (before <0), give error if x too large for shared mem

git-svn-id: file:///home/svn/mapi/trunk@812 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent 3904e45b
......@@ -7,6 +7,8 @@
#include <errno.h>
#include <pcap.h> /* DLT_EN10MB */
#include <assert.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include "mapidflib.h"
#include "mapidlib.h"
#include "mapidevices.h"
......@@ -15,8 +17,6 @@
#include "topx.h"
#include "protocols.h"
#include "mapi_errors.h"
#include <netinet/in.h>
#include <netinet/ip6.h>
#ifndef CHDLC_HDRLEN
#define CHDLC_HDRLEN 4
......@@ -65,9 +65,9 @@ static int topx_reset(mapidflib_function_instance_t *instance)
}
void extract_field(struct topx_field *field, unsigned char *ip_pkt, int protocol, int pfield);
struct topx_hash_node *hash_lookup(unsigned int value,struct topx_data *data);
struct topx_hash_node *hash_lookup(struct topx_val *value, struct topx_data *data);
void check_for_shift(struct topx_data *data,struct topx_list_node *node);
void add_to_hashtable_and_list(struct topx_data *data,unsigned int value,unsigned long long bytes, unsigned int last_rst);
void add_to_hashtable_and_list(struct topx_data *data, struct topx_val *value, unsigned long long bytes, unsigned int last_rst);
void add_field_to_list(struct topx_field *field,struct topx_data *data,unsigned long long bytes,unsigned int last_rst);
void extract_field(struct topx_field *field, unsigned char *ip_pkt, int protocol, int pfield) {
......@@ -142,12 +142,22 @@ void extract_field(struct topx_field *field, unsigned char *ip_pkt, int protocol
field->len=2;
break;
case TOPX_IP_SRCIP:
field->pointer=&(ip->saddr);
field->len=4;
if (ip_ver == 4) {
field->pointer = &ip->saddr;
field->len = 4;
} else {
field->pointer = &ip6->ip6_src;
field->len = 16;
}
break;
case TOPX_IP_DSTIP:
field->pointer=&(ip->daddr);
field->len=4;
if (ip_ver == 4) {
field->pointer = &ip->daddr;
field->len = 4;
} else {
field->pointer = &ip6->ip6_dst;
field->len = 16;
}
break;
}
break;
......@@ -220,17 +230,20 @@ void extract_field(struct topx_field *field, unsigned char *ip_pkt, int protocol
}
}
struct topx_hash_node *hash_lookup(unsigned int value,struct topx_data *data) {
struct topx_hash_node *hash_lookup(struct topx_val *value, struct topx_data *data) {
unsigned int pos;
struct topx_hash_node *tmp;
pos=value%TOPX_HASH_SIZE;
tmp=data->hashtable[pos];
while(tmp) {
if(tmp->value==value)
return tmp;
tmp=tmp->next;
if (value->len == 1) {
pos = value->val[0] % TOPX_HASH_SIZE;
for (tmp = data->hashtable[pos]; tmp; tmp=tmp->next)
if (tmp->value.val[0] == value->val[0])
return tmp;
} else { /* length 1 or 4, so assuming 4 */
pos = (value->val[0] ^ value->val[1] ^ value->val[2] ^ value->val[3]) % TOPX_HASH_SIZE;
for (tmp = data->hashtable[pos]; tmp; tmp=tmp->next)
if (!memcmp(tmp->value.val, value->val, 16 /* 4 * sizeof(unsigned int) */))
return tmp;
}
return NULL;
......@@ -266,14 +279,14 @@ void check_for_shift(struct topx_data *data,struct topx_list_node *node) {
before->previous = node;
}
void add_to_hashtable_and_list(struct topx_data *data,unsigned int value,unsigned long long bytes, unsigned int last_rst) {
void add_to_hashtable_and_list(struct topx_data *data, struct topx_val *value, unsigned long long bytes, unsigned int last_rst) {
unsigned int pos;
struct topx_list_node *newlistnode;
struct topx_hash_node *newhashnode;
newlistnode=(struct topx_list_node *)malloc(sizeof(struct topx_list_node));
bzero(newlistnode, sizeof(struct topx_list_node));
newlistnode->value=value;
newlistnode->value = *value;
newlistnode->count=1;
newlistnode->bytecount=bytes;
newlistnode->last_rst_secs=last_rst;
......@@ -291,10 +304,13 @@ void add_to_hashtable_and_list(struct topx_data *data,unsigned int value,unsigne
data->list_tail=newlistnode;
}
pos=value%TOPX_HASH_SIZE;
pos = ((value->len == 1)
? value->val[0]
: value->val[0] ^ value->val[1] ^ value->val[2] ^ value->val[3])
% TOPX_HASH_SIZE;
newhashnode=(struct topx_hash_node *)malloc(sizeof(struct topx_hash_node));
bzero(newhashnode, sizeof(struct topx_hash_node));
newhashnode->value=value;
newhashnode->value = *value;
newhashnode->node=newlistnode;
newhashnode->next=data->hashtable[pos];
data->hashtable[pos]=newhashnode;
......@@ -303,31 +319,39 @@ void add_to_hashtable_and_list(struct topx_data *data,unsigned int value,unsigne
void add_field_to_list(struct topx_field *field,struct topx_data *data,unsigned long long bytes, unsigned int last_rst) {
struct topx_hash_node *lookup;
unsigned int value=0;
struct topx_val value;
bzero(&value, sizeof(struct topx_val));
switch(field->len) {
case 1:
value=(unsigned int)(*((unsigned char *)(field->pointer)));
value.len = 1;
value.val[0] = (unsigned int)(*((unsigned char *)(field->pointer)));
break;
case 2:
value.len = 1;
if(field->needs_reverse==1)
value=(unsigned int)(ntohs(*((unsigned short *)(field->pointer))));
value.val[0] = (unsigned int)(ntohs(*((unsigned short *)(field->pointer))));
else
value=(unsigned int)(*((unsigned short *)(field->pointer)));
value.val[0] = (unsigned int)(*((unsigned short *)(field->pointer)));
break;
case 4:
value.len = 1;
if(field->needs_reverse==1)
value=ntohl((*((unsigned int *)(field->pointer))));
value.val[0] = ntohl((*((unsigned int *)(field->pointer))));
else
value=(*((unsigned int *)(field->pointer)));
value.val[0] = (*((unsigned int *)(field->pointer)));
break;
case 16:
value.len = 4;
memcpy(value.val, field->pointer, 16);
default:
break;
}
lookup=hash_lookup(value,data);
lookup = hash_lookup(&value, data);
if(lookup==NULL) {
add_to_hashtable_and_list(data,value,bytes,last_rst);
add_to_hashtable_and_list(data, &value, bytes, last_rst);
}
else {
lookup->node->count++;
......@@ -414,8 +438,15 @@ static int topx_process(mapidflib_function_instance_t *instance,
//write results
result=(struct topx_result *)ptr;
while(tmp && i<data->x) {
result->value=tmp->value;
while (tmp && i < data->x) {
if (tmp->value.len == 1)
result->value = tmp->value.val[0];
else /* len != 1 only for IPv6 addresses */
memcpy(&result->addr6, tmp->value.val, 16);
if (data->field == TOPX_IP_SRCIP || data->field == TOPX_IP_DSTIP)
result->family = (tmp->value.len == 1) ? AF_INET : AF_INET6;
result->count=tmp->count;
result->bytecount=tmp->bytecount;
result->last_rst_secs=tmp->last_rst_secs;
......@@ -433,7 +464,8 @@ static int topx_instance(mapidflib_function_instance_t *instance,
{
mapiFunctArg *fargs = instance->args;
getargint(&fargs);
if (getargint(&fargs) > TOPX_MAX_X)
return MFUNCT_INVALID_ARGUMENT_1;
int protocol = getargint(&fargs);
if(protocol!=TOPX_IP && protocol!=TOPX_TCP && protocol!=TOPX_UDP)
......@@ -450,7 +482,7 @@ static int topx_init(mapidflib_function_instance_t *instance, MAPI_UNUSED int fd
fargs=instance->args;
x = getargint(&fargs);
if(x<0)
if (x < 1)
x=1;
protocol = getargint(&fargs);
......@@ -487,7 +519,7 @@ static mapidflib_function_def_t topfinfo={
"iiiii", //argdescr
MAPI_DEVICE_ALL, //devoid
MAPIRES_SHM, //Use shared memory to return results
sizeof(struct topx_result)*1000+sizeof(unsigned int), //shm size
sizeof(struct topx_result) * TOPX_MAX_X + sizeof(unsigned int), //shm size
0, //modifies_pkts
0, //filters packets
MAPIOPT_AUTO, //Optimization
......
#define TOPX_HASH_SIZE 4096
#define TOPX_MAX_X 1000
struct topx_val {
unsigned int val[4];
unsigned char len; /* len == 1 || len == 4 */
};
struct topx_list_node {
unsigned int value;
struct topx_val value;
unsigned int count;
unsigned long long bytecount;
unsigned int last_rst_secs;
......@@ -11,6 +17,8 @@ struct topx_list_node {
struct topx_result {
unsigned int value;
struct in6_addr addr6;
sa_family_t family;
unsigned int count;
unsigned long long bytecount;
unsigned int last_rst_secs;
......@@ -18,7 +26,7 @@ struct topx_result {
struct topx_hash_node {
unsigned int value;
struct topx_val value;
struct topx_list_node *node;
struct topx_hash_node *next;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment