You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/detect-address-ipv4.c

221 lines
6.0 KiB
C

/* Address part of the detection engine.
*
* Copyright (c) 2008 Victor Julien
*/
#include "decode.h"
#include "detect.h"
#include "flow-var.h"
#include "util-cidr.h"
#include "util-unittest.h"
#include "detect-address.h"
int AddressCmpIPv4(DetectAddressData *a, DetectAddressData *b) {
u_int32_t a_ip1 = ntohl(a->ip[0]);
u_int32_t a_ip2 = ntohl(a->ip2[0]);
u_int32_t b_ip1 = ntohl(b->ip[0]);
u_int32_t b_ip2 = ntohl(b->ip2[0]);
/* ADDRESS_EQ */
if (a_ip1 == b_ip1 && a_ip2 == b_ip2) {
//printf("ADDRESS_EQ\n");
return ADDRESS_EQ;
/* ADDRESS_ES */
} else if (a_ip1 >= b_ip1 && a_ip1 < b_ip2 && a_ip2 <= b_ip2) {
//printf("ADDRESS_ES\n");
return ADDRESS_ES;
/* ADDRESS_EB */
} else if (a_ip1 <= b_ip1 && a_ip2 >= b_ip2) {
//printf("ADDRESS_EB\n");
return ADDRESS_EB;
} else if (a_ip1 < b_ip1 && a_ip2 < b_ip2 && a_ip2 > b_ip1) {
//printf("ADDRESS_LE\n");
return ADDRESS_LE;
} else if (a_ip1 < b_ip1 && a_ip2 < b_ip2) {
//printf("ADDRESS_LT\n");
return ADDRESS_LT;
} else if (a_ip1 > b_ip1 && a_ip1 < b_ip2 && a_ip2 > b_ip2) {
//printf("ADDRESS_GE\n");
return ADDRESS_GE;
} else if (a_ip1 > b_ip2) {
//printf("ADDRESS_GT\n");
return ADDRESS_GT;
} else {
/* should be unreachable */
printf("Internal Error: should be unreachable\n");
}
return ADDRESS_ER;
}
/* a = 1.2.3.4, b = 1.2.3.4-1.2.3.5
* must result in: a == 1.2.3.4, b == 1.2.3.5, c == NULL
*
* a = 1.2.3.4, b = 1.2.3.3-1.2.3.5
* must result in: a == 1.2.3.3, b == 1.2.3.4, c == 1.2.3.5
*
* a = 1.2.3.0/24 b = 1.2.3.128-1.2.4.10
* must result in: a == 1.2.3.0/24, b == 1.2.4.0-1.2.4.10, c == NULL
*
* a = 1.2.3.4, b = 1.2.3.0/24
* must result in: a == 1.2.3.0-1.2.3.3, b == 1.2.3.4, c == 1.2.3.5-1.2.3.255
*/
int AddressCutIPv4(DetectAddressData *a, DetectAddressData *b, DetectAddressData **c) {
u_int32_t a_ip1 = ntohl(a->ip[0]);
u_int32_t a_ip2 = ntohl(a->ip2[0]);
u_int32_t b_ip1 = ntohl(b->ip[0]);
u_int32_t b_ip2 = ntohl(b->ip2[0]);
/* default to NULL */
*c = NULL;
int r = AddressCmpIPv4(a,b);
if (r != ADDRESS_ES && r != ADDRESS_EB && r != ADDRESS_LE && r != ADDRESS_GE) {
goto error;
}
/* we have 3 parts: [aaa[abab]bbb]
* part a: a_ip1 <-> b_ip1 - 1
* part b: b_ip1 <-> a_ip2
* part c: a_ip2 + 1 <-> b_ip2
*/
if (r == ADDRESS_LE) {
a->ip[0] = htonl(a_ip1);
a->ip2[0] = htonl(b_ip1 - 1);
b->ip[0] = htonl(b_ip1);
b->ip2[0] = htonl(a_ip2);
DetectAddressData *tmp_c;
tmp_c = malloc(sizeof(DetectAddressData));
if (tmp_c == NULL) {
goto error;
}
tmp_c->family = AF_INET;
tmp_c->ip[0] = htonl(a_ip2 + 1);
tmp_c->ip2[0] = htonl(b_ip2);
*c = tmp_c;
/* we have 3 parts: [bbb[baba]aaa]
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> b_ip2
* part c: b_ip2 + 1 <-> a_ip2
*/
} else if (r == ADDRESS_GE) {
a->ip[0] = htonl(b_ip1);
a->ip2[0] = htonl(a_ip1 - 1);
b->ip[0] = htonl(a_ip1);
b->ip2[0] = htonl(b_ip2);
DetectAddressData *tmp_c;
tmp_c = malloc(sizeof(DetectAddressData));
if (tmp_c == NULL) {
goto error;
}
tmp_c->family = AF_INET;
tmp_c->ip[0] = htonl(b_ip2 + 1);
tmp_c->ip2[0] = htonl(a_ip2);
*c = tmp_c;
/* we have 2 or three parts:
*
* 2 part: [[abab]bbb] or [bbb[baba]]
* part a: a_ip1 <-> a_ip2
* part b: a_ip2 + 1 <-> b_ip2
*
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> a_ip2
*
* 3 part [bbb[aaa]bbb]
* part a: b_ip1 <-> a_ip1 - 1
* part b: a_ip1 <-> a_ip2
* part c: a_ip2 + 1 <-> b_ip2
*/
} else if (r == ADDRESS_ES) {
if (a_ip1 == b_ip1) {
a->ip[0] = htonl(a_ip1);
a->ip2[0] = htonl(a_ip2);
b->ip[0] = htonl(a_ip2 + 1);
b->ip2[0] = htonl(b_ip2);
} else if (a_ip2 == b_ip2) {
a->ip[0] = htonl(b_ip1);
a->ip2[0] = htonl(a_ip1 - 1);
b->ip[0] = htonl(a_ip1);
b->ip2[0] = htonl(a_ip2);
} else {
a->ip[0] = htonl(b_ip1);
a->ip2[0] = htonl(a_ip1 - 1);
b->ip[0] = htonl(a_ip1);
b->ip2[0] = htonl(a_ip2);
DetectAddressData *tmp_c;
tmp_c = malloc(sizeof(DetectAddressData));
if (tmp_c == NULL) {
goto error;
}
tmp_c->family = AF_INET;
tmp_c->ip[0] = htonl(a_ip2 + 1);
tmp_c->ip2[0] = htonl(b_ip2);
*c = tmp_c;
}
/* we have 2 or three parts:
*
* 2 part: [[baba]aaa] or [aaa[abab]]
* part a: b_ip1 <-> b_ip2
* part b: b_ip2 + 1 <-> a_ip2
*
* part a: a_ip1 <-> b_ip1 - 1
* part b: b_ip1 <-> b_ip2
*
* 3 part [aaa[bbb]aaa]
* part a: a_ip1 <-> b_ip2 - 1
* part b: b_ip1 <-> b_ip2
* part c: b_ip2 + 1 <-> a_ip2
*/
} else if (r == ADDRESS_EB) {
if (a_ip1 == b_ip1) {
a->ip[0] = htonl(b_ip1);
a->ip2[0] = htonl(b_ip2);
b->ip[0] = htonl(b_ip2 + 1);
b->ip2[0] = htonl(a_ip2);
} else if (a_ip2 == b_ip2) {
a->ip[0] = htonl(a_ip1);
a->ip2[0] = htonl(b_ip1 - 1);
b->ip[0] = htonl(b_ip1);
b->ip2[0] = htonl(b_ip2);
} else {
a->ip[0] = htonl(a_ip1);
a->ip2[0] = htonl(b_ip1 - 1);
b->ip[0] = htonl(b_ip1);
b->ip2[0] = htonl(b_ip2);
DetectAddressData *tmp_c;
tmp_c = malloc(sizeof(DetectAddressData));
if (tmp_c == NULL) {
goto error;
}
tmp_c->family = AF_INET;
tmp_c->ip[0] = htonl(b_ip2 + 1);
tmp_c->ip2[0] = htonl(a_ip2);
*c = tmp_c;
}
}
return 0;
error:
return -1;
}