|
|
|
|
@ -65,7 +65,7 @@
|
|
|
|
|
*
|
|
|
|
|
* \retval IPOnlyCIDRItem address of the new instance
|
|
|
|
|
*/
|
|
|
|
|
IPOnlyCIDRItem *IPOnlyCIDRItemNew() {
|
|
|
|
|
static IPOnlyCIDRItem *IPOnlyCIDRItemNew() {
|
|
|
|
|
SCEnter();
|
|
|
|
|
IPOnlyCIDRItem *item = NULL;
|
|
|
|
|
|
|
|
|
|
@ -77,7 +77,7 @@ IPOnlyCIDRItem *IPOnlyCIDRItemNew() {
|
|
|
|
|
SCReturnPtr(item, "IPOnlyCIDRItem");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t IPOnlyCIDRItemCompare(IPOnlyCIDRItem *head,
|
|
|
|
|
static uint8_t IPOnlyCIDRItemCompare(IPOnlyCIDRItem *head,
|
|
|
|
|
IPOnlyCIDRItem *item) {
|
|
|
|
|
uint8_t i = 0;
|
|
|
|
|
for (; i < head->netmask / 32 || i < 1; i++) {
|
|
|
|
|
@ -88,6 +88,232 @@ uint8_t IPOnlyCIDRItemCompare(IPOnlyCIDRItem *head,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \internal
|
|
|
|
|
* \brief Parses an ipv4/ipv6 address string and updates the result into the
|
|
|
|
|
* IPOnlyCIDRItem instance sent as the argument.
|
|
|
|
|
*
|
|
|
|
|
* \param dd Pointer to the IPOnlyCIDRItem instance which should be updated with
|
|
|
|
|
* the address (in cidr) details from the parsed ip string.
|
|
|
|
|
* \param str Pointer to address string that has to be parsed.
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 On successfully parsing the address string.
|
|
|
|
|
* \retval -1 On failure.
|
|
|
|
|
*/
|
|
|
|
|
static int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem *dd, char *str)
|
|
|
|
|
{
|
|
|
|
|
char *ipdup = SCStrdup(str);
|
|
|
|
|
char *ip = NULL;
|
|
|
|
|
char *ip2 = NULL;
|
|
|
|
|
char *mask = NULL;
|
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
|
|
SCLogDebug("str %s", str);
|
|
|
|
|
|
|
|
|
|
/* first handle 'any' */
|
|
|
|
|
if (strcasecmp(str, "any") == 0) {
|
|
|
|
|
/* if any, insert 0.0.0.0/0 and ::/0 as well */
|
|
|
|
|
SCLogDebug("adding 0.0.0.0/0 and ::/0 as we\'re handling \'any\'");
|
|
|
|
|
|
|
|
|
|
IPOnlyCIDRItemParseSingle(dd, "0.0.0.0/0");
|
|
|
|
|
BUG_ON(dd->family == 0);
|
|
|
|
|
|
|
|
|
|
dd->next = IPOnlyCIDRItemNew();
|
|
|
|
|
if (dd->next == NULL)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
IPOnlyCIDRItemParseSingle(dd->next, "::/0");
|
|
|
|
|
BUG_ON(dd->family == 0);
|
|
|
|
|
|
|
|
|
|
SCFree(ipdup);
|
|
|
|
|
|
|
|
|
|
SCLogDebug("address is \'any\'");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we dup so we can put a nul-termination in it later */
|
|
|
|
|
ip = ipdup;
|
|
|
|
|
if (ip == NULL) {
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* handle the negation case */
|
|
|
|
|
if (ip[0] == '!') {
|
|
|
|
|
dd->negated = (dd->negated)? 0 : 1;
|
|
|
|
|
ip++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* see if the address is an ipv4 or ipv6 address */
|
|
|
|
|
if ((strchr(str, ':')) == NULL) {
|
|
|
|
|
/* IPv4 Address */
|
|
|
|
|
struct in_addr in;
|
|
|
|
|
|
|
|
|
|
dd->family = AF_INET;
|
|
|
|
|
|
|
|
|
|
if ((mask = strchr(ip, '/')) != NULL) {
|
|
|
|
|
/* 1.2.3.4/xxx format (either dotted or cidr notation */
|
|
|
|
|
ip[mask - ip] = '\0';
|
|
|
|
|
mask++;
|
|
|
|
|
uint32_t netmask = 0;
|
|
|
|
|
size_t u = 0;
|
|
|
|
|
|
|
|
|
|
if ((strchr (mask, '.')) == NULL) {
|
|
|
|
|
/* 1.2.3.4/24 format */
|
|
|
|
|
|
|
|
|
|
for (u = 0; u < strlen(mask); u++) {
|
|
|
|
|
if(!isdigit(mask[u]))
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int cidr = atoi(mask);
|
|
|
|
|
if (cidr < 0 || cidr > 32)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
dd->netmask = cidr;
|
|
|
|
|
} else {
|
|
|
|
|
/* 1.2.3.4/255.255.255.0 format */
|
|
|
|
|
r = inet_pton(AF_INET, mask, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
netmask = in.s_addr;
|
|
|
|
|
|
|
|
|
|
/* Extract cidr netmask */
|
|
|
|
|
while ((0x01 & netmask) == 0) {
|
|
|
|
|
dd->netmask++;
|
|
|
|
|
netmask = netmask >> 1;
|
|
|
|
|
}
|
|
|
|
|
dd->netmask = 32 - dd->netmask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET, ip, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
dd->ip[0] = in.s_addr;
|
|
|
|
|
|
|
|
|
|
} else if ((ip2 = strchr(ip, '-')) != NULL) {
|
|
|
|
|
/* 1.2.3.4-1.2.3.6 range format */
|
|
|
|
|
ip[ip2 - ip] = '\0';
|
|
|
|
|
ip2++;
|
|
|
|
|
|
|
|
|
|
uint32_t tmp_ip[4];
|
|
|
|
|
uint32_t tmp_ip2[4];
|
|
|
|
|
uint32_t first, last;
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET, ip, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
tmp_ip[0] = in.s_addr;
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET, ip2, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
tmp_ip2[0] = in.s_addr;
|
|
|
|
|
|
|
|
|
|
/* a > b is illegal, a = b is ok */
|
|
|
|
|
if (ntohl(tmp_ip[0]) > ntohl(tmp_ip2[0]))
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
first = ntohl(tmp_ip[0]);
|
|
|
|
|
last = ntohl(tmp_ip2[0]);
|
|
|
|
|
|
|
|
|
|
dd->netmask = 32;
|
|
|
|
|
dd->ip[0] =htonl(first);
|
|
|
|
|
|
|
|
|
|
if (first < last) {
|
|
|
|
|
for (first++; first <= last; first++) {
|
|
|
|
|
IPOnlyCIDRItem *new = IPOnlyCIDRItemNew();
|
|
|
|
|
if (new == NULL)
|
|
|
|
|
goto error;
|
|
|
|
|
dd->next = new;
|
|
|
|
|
new->negated = dd->negated;
|
|
|
|
|
new->family= dd->family;
|
|
|
|
|
new->netmask = dd->netmask;
|
|
|
|
|
new->ip[0] = htonl(first);
|
|
|
|
|
dd = dd->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
/* 1.2.3.4 format */
|
|
|
|
|
r = inet_pton(AF_INET, ip, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
/* single host */
|
|
|
|
|
dd->ip[0] = in.s_addr;
|
|
|
|
|
dd->netmask = 32;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* IPv6 Address */
|
|
|
|
|
struct in6_addr in6;
|
|
|
|
|
uint32_t ip6addr[4];
|
|
|
|
|
|
|
|
|
|
dd->family = AF_INET6;
|
|
|
|
|
|
|
|
|
|
if ((mask = strchr(ip, '/')) != NULL) {
|
|
|
|
|
mask[0] = '\0';
|
|
|
|
|
mask++;
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET6, ip, &in6);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
/* Format is cidr val */
|
|
|
|
|
dd->netmask = atoi(mask);
|
|
|
|
|
|
|
|
|
|
memcpy(dd->ip, &in6.s6_addr, sizeof(ip6addr));
|
|
|
|
|
} else {
|
|
|
|
|
r = inet_pton(AF_INET6, ip, &in6);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
memcpy(dd->ip, &in6.s6_addr, sizeof(dd->ip));
|
|
|
|
|
dd->netmask = 128;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCFree(ipdup);
|
|
|
|
|
|
|
|
|
|
BUG_ON(dd->family == 0);
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
if (ipdup)
|
|
|
|
|
SCFree(ipdup);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Setup a single address string, parse it and add the resulting
|
|
|
|
|
* Address items in cidr format to the list of gh
|
|
|
|
|
*
|
|
|
|
|
* \param gh Pointer to the IPOnlyCIDRItem list Head to which the
|
|
|
|
|
* resulting Address-Range(s) from the parsed ip string has to
|
|
|
|
|
* be added.
|
|
|
|
|
* \param s Pointer to the ip address string to be parsed.
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 On success.
|
|
|
|
|
* \retval -1 On failure.
|
|
|
|
|
*/
|
|
|
|
|
static int IPOnlyCIDRItemSetup(IPOnlyCIDRItem *gh, char *s) {
|
|
|
|
|
SCLogDebug("gh %p, s %s", gh, s);
|
|
|
|
|
|
|
|
|
|
/* parse the address */
|
|
|
|
|
if (IPOnlyCIDRItemParseSingle(gh, s) == -1) {
|
|
|
|
|
SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC,
|
|
|
|
|
"DetectAddressParse error \"%s\"", s);
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief This function insert a IPOnlyCIDRItem
|
|
|
|
|
@ -98,7 +324,7 @@ uint8_t IPOnlyCIDRItemCompare(IPOnlyCIDRItem *head,
|
|
|
|
|
*
|
|
|
|
|
* \retval IPOnlyCIDRItem address of the new head if apply
|
|
|
|
|
*/
|
|
|
|
|
IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
|
|
|
|
|
static IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
|
|
|
|
|
IPOnlyCIDRItem *item)
|
|
|
|
|
{
|
|
|
|
|
IPOnlyCIDRItem *it, *prev = NULL;
|
|
|
|
|
@ -143,7 +369,7 @@ IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
|
|
|
|
|
*
|
|
|
|
|
* \retval IPOnlyCIDRItem address of the new head if apply
|
|
|
|
|
*/
|
|
|
|
|
IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
|
|
|
|
|
static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
|
|
|
|
|
IPOnlyCIDRItem *item)
|
|
|
|
|
{
|
|
|
|
|
IPOnlyCIDRItem *it, *prev = NULL;
|
|
|
|
|
@ -216,7 +442,7 @@ void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead) {
|
|
|
|
|
* \param tmphead Pointer to the list
|
|
|
|
|
* \param i number of signature internal id
|
|
|
|
|
*/
|
|
|
|
|
void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i) {
|
|
|
|
|
static void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i) {
|
|
|
|
|
while (tmphead != NULL) {
|
|
|
|
|
tmphead->signum = i;
|
|
|
|
|
tmphead = tmphead->next;
|
|
|
|
|
@ -227,7 +453,7 @@ void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i) {
|
|
|
|
|
* \brief This function print a IPOnlyCIDRItem list
|
|
|
|
|
* \param tmphead Pointer to the head of IPOnlyCIDRItems list
|
|
|
|
|
*/
|
|
|
|
|
void IPOnlyCIDRListPrint(IPOnlyCIDRItem *tmphead) {
|
|
|
|
|
static void IPOnlyCIDRListPrint(IPOnlyCIDRItem *tmphead) {
|
|
|
|
|
uint32_t i = 0;
|
|
|
|
|
|
|
|
|
|
while (tmphead != NULL) {
|
|
|
|
|
@ -246,7 +472,7 @@ void IPOnlyCIDRListPrint(IPOnlyCIDRItem *tmphead) {
|
|
|
|
|
* radix tree print function to help debugging
|
|
|
|
|
* \param tmp Pointer to the head of SigNumArray
|
|
|
|
|
*/
|
|
|
|
|
void SigNumArrayPrint(void *tmp) {
|
|
|
|
|
static void SigNumArrayPrint(void *tmp) {
|
|
|
|
|
SigNumArray *sna = (SigNumArray *)tmp;
|
|
|
|
|
uint32_t u;
|
|
|
|
|
|
|
|
|
|
@ -273,7 +499,7 @@ void SigNumArrayPrint(void *tmp) {
|
|
|
|
|
*
|
|
|
|
|
* \retval SigNumArray address of the new instance
|
|
|
|
|
*/
|
|
|
|
|
SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
|
|
|
|
|
static SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
|
|
|
|
|
DetectEngineIPOnlyCtx *io_ctx)
|
|
|
|
|
{
|
|
|
|
|
SigNumArray *new = SCMalloc(sizeof(SigNumArray));
|
|
|
|
|
@ -305,7 +531,7 @@ SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
|
|
|
|
|
*
|
|
|
|
|
* \retval SigNumArray address of the new instance
|
|
|
|
|
*/
|
|
|
|
|
SigNumArray *SigNumArrayCopy(SigNumArray *orig) {
|
|
|
|
|
static SigNumArray *SigNumArrayCopy(SigNumArray *orig) {
|
|
|
|
|
SigNumArray *new = SCMalloc(sizeof(SigNumArray));
|
|
|
|
|
|
|
|
|
|
if (new == NULL) {
|
|
|
|
|
@ -329,7 +555,7 @@ SigNumArray *SigNumArrayCopy(SigNumArray *orig) {
|
|
|
|
|
* \brief This function free() a SigNumArray
|
|
|
|
|
* \param orig Pointer to the original SigNumArray to copy
|
|
|
|
|
*/
|
|
|
|
|
void SigNumArrayFree(void *tmp) {
|
|
|
|
|
static void SigNumArrayFree(void *tmp) {
|
|
|
|
|
SigNumArray *sna = (SigNumArray *)tmp;
|
|
|
|
|
|
|
|
|
|
if (sna == NULL)
|
|
|
|
|
@ -351,7 +577,7 @@ void SigNumArrayFree(void *tmp) {
|
|
|
|
|
* \retval 0 if success
|
|
|
|
|
* \retval -1 if fails
|
|
|
|
|
*/
|
|
|
|
|
IPOnlyCIDRItem *IPOnlyCIDRListParse2(char *s, int negate)
|
|
|
|
|
static IPOnlyCIDRItem *IPOnlyCIDRListParse2(char *s, int negate)
|
|
|
|
|
{
|
|
|
|
|
size_t x = 0;
|
|
|
|
|
size_t u = 0;
|
|
|
|
|
@ -521,7 +747,7 @@ error:
|
|
|
|
|
* \retval 0 On success.
|
|
|
|
|
* \retval -1 On failure.
|
|
|
|
|
*/
|
|
|
|
|
int IPOnlyCIDRListParse(IPOnlyCIDRItem **gh, char *str)
|
|
|
|
|
static int IPOnlyCIDRListParse(IPOnlyCIDRItem **gh, char *str)
|
|
|
|
|
{
|
|
|
|
|
SCLogDebug("gh %p, str %s", gh, str);
|
|
|
|
|
|
|
|
|
|
@ -597,234 +823,7 @@ int IPOnlySigParseAddress(Signature *s, const char *addrstr, char flag)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \internal
|
|
|
|
|
* \brief Parses an ipv4/ipv6 address string and updates the result into the
|
|
|
|
|
* IPOnlyCIDRItem instance sent as the argument.
|
|
|
|
|
*
|
|
|
|
|
* \param dd Pointer to the IPOnlyCIDRItem instance which should be updated with
|
|
|
|
|
* the address (in cidr) details from the parsed ip string.
|
|
|
|
|
* \param str Pointer to address string that has to be parsed.
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 On successfully parsing the address string.
|
|
|
|
|
* \retval -1 On failure.
|
|
|
|
|
*/
|
|
|
|
|
int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem *dd, char *str)
|
|
|
|
|
{
|
|
|
|
|
char *ipdup = SCStrdup(str);
|
|
|
|
|
char *ip = NULL;
|
|
|
|
|
char *ip2 = NULL;
|
|
|
|
|
char *mask = NULL;
|
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
|
|
SCLogDebug("str %s", str);
|
|
|
|
|
|
|
|
|
|
/* first handle 'any' */
|
|
|
|
|
if (strcasecmp(str, "any") == 0) {
|
|
|
|
|
/* if any, insert 0.0.0.0/0 and ::/0 as well */
|
|
|
|
|
SCLogDebug("adding 0.0.0.0/0 and ::/0 as we\'re handling \'any\'");
|
|
|
|
|
|
|
|
|
|
IPOnlyCIDRItemParseSingle(dd, "0.0.0.0/0");
|
|
|
|
|
BUG_ON(dd->family == 0);
|
|
|
|
|
|
|
|
|
|
dd->next = IPOnlyCIDRItemNew();
|
|
|
|
|
if (dd->next == NULL)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
IPOnlyCIDRItemParseSingle(dd->next, "::/0");
|
|
|
|
|
BUG_ON(dd->family == 0);
|
|
|
|
|
|
|
|
|
|
SCFree(ipdup);
|
|
|
|
|
|
|
|
|
|
SCLogDebug("address is \'any\'");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we dup so we can put a nul-termination in it later */
|
|
|
|
|
ip = ipdup;
|
|
|
|
|
if (ip == NULL) {
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* handle the negation case */
|
|
|
|
|
if (ip[0] == '!') {
|
|
|
|
|
dd->negated = (dd->negated)? 0 : 1;
|
|
|
|
|
ip++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* see if the address is an ipv4 or ipv6 address */
|
|
|
|
|
if ((strchr(str, ':')) == NULL) {
|
|
|
|
|
/* IPv4 Address */
|
|
|
|
|
struct in_addr in;
|
|
|
|
|
|
|
|
|
|
dd->family = AF_INET;
|
|
|
|
|
|
|
|
|
|
if ((mask = strchr(ip, '/')) != NULL) {
|
|
|
|
|
/* 1.2.3.4/xxx format (either dotted or cidr notation */
|
|
|
|
|
ip[mask - ip] = '\0';
|
|
|
|
|
mask++;
|
|
|
|
|
uint32_t netmask = 0;
|
|
|
|
|
size_t u = 0;
|
|
|
|
|
|
|
|
|
|
if ((strchr (mask, '.')) == NULL) {
|
|
|
|
|
/* 1.2.3.4/24 format */
|
|
|
|
|
|
|
|
|
|
for (u = 0; u < strlen(mask); u++) {
|
|
|
|
|
if(!isdigit(mask[u]))
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int cidr = atoi(mask);
|
|
|
|
|
if (cidr < 0 || cidr > 32)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
dd->netmask = cidr;
|
|
|
|
|
} else {
|
|
|
|
|
/* 1.2.3.4/255.255.255.0 format */
|
|
|
|
|
r = inet_pton(AF_INET, mask, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
netmask = in.s_addr;
|
|
|
|
|
|
|
|
|
|
/* Extract cidr netmask */
|
|
|
|
|
while ((0x01 & netmask) == 0) {
|
|
|
|
|
dd->netmask++;
|
|
|
|
|
netmask = netmask >> 1;
|
|
|
|
|
}
|
|
|
|
|
dd->netmask = 32 - dd->netmask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET, ip, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
dd->ip[0] = in.s_addr;
|
|
|
|
|
|
|
|
|
|
} else if ((ip2 = strchr(ip, '-')) != NULL) {
|
|
|
|
|
/* 1.2.3.4-1.2.3.6 range format */
|
|
|
|
|
ip[ip2 - ip] = '\0';
|
|
|
|
|
ip2++;
|
|
|
|
|
|
|
|
|
|
uint32_t tmp_ip[4];
|
|
|
|
|
uint32_t tmp_ip2[4];
|
|
|
|
|
uint32_t first, last;
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET, ip, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
tmp_ip[0] = in.s_addr;
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET, ip2, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
tmp_ip2[0] = in.s_addr;
|
|
|
|
|
|
|
|
|
|
/* a > b is illegal, a = b is ok */
|
|
|
|
|
if (ntohl(tmp_ip[0]) > ntohl(tmp_ip2[0]))
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
first = ntohl(tmp_ip[0]);
|
|
|
|
|
last = ntohl(tmp_ip2[0]);
|
|
|
|
|
|
|
|
|
|
dd->netmask = 32;
|
|
|
|
|
dd->ip[0] =htonl(first);
|
|
|
|
|
|
|
|
|
|
if (first < last) {
|
|
|
|
|
for (first++; first <= last; first++) {
|
|
|
|
|
IPOnlyCIDRItem *new = IPOnlyCIDRItemNew();
|
|
|
|
|
if (new == NULL)
|
|
|
|
|
goto error;
|
|
|
|
|
dd->next = new;
|
|
|
|
|
new->negated = dd->negated;
|
|
|
|
|
new->family= dd->family;
|
|
|
|
|
new->netmask = dd->netmask;
|
|
|
|
|
new->ip[0] = htonl(first);
|
|
|
|
|
dd = dd->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
/* 1.2.3.4 format */
|
|
|
|
|
r = inet_pton(AF_INET, ip, &in);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
/* single host */
|
|
|
|
|
dd->ip[0] = in.s_addr;
|
|
|
|
|
dd->netmask = 32;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* IPv6 Address */
|
|
|
|
|
struct in6_addr in6;
|
|
|
|
|
uint32_t ip6addr[4];
|
|
|
|
|
|
|
|
|
|
dd->family = AF_INET6;
|
|
|
|
|
|
|
|
|
|
if ((mask = strchr(ip, '/')) != NULL) {
|
|
|
|
|
mask[0] = '\0';
|
|
|
|
|
mask++;
|
|
|
|
|
|
|
|
|
|
r = inet_pton(AF_INET6, ip, &in6);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
/* Format is cidr val */
|
|
|
|
|
dd->netmask = atoi(mask);
|
|
|
|
|
|
|
|
|
|
memcpy(dd->ip, &in6.s6_addr, sizeof(ip6addr));
|
|
|
|
|
} else {
|
|
|
|
|
r = inet_pton(AF_INET6, ip, &in6);
|
|
|
|
|
if (r <= 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
memcpy(dd->ip, &in6.s6_addr, sizeof(dd->ip));
|
|
|
|
|
dd->netmask = 128;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCFree(ipdup);
|
|
|
|
|
|
|
|
|
|
BUG_ON(dd->family == 0);
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
if (ipdup)
|
|
|
|
|
SCFree(ipdup);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Setup a single address string, parse it and add the resulting
|
|
|
|
|
* Address items in cidr format to the list of gh
|
|
|
|
|
*
|
|
|
|
|
* \param gh Pointer to the IPOnlyCIDRItem list Head to which the
|
|
|
|
|
* resulting Address-Range(s) from the parsed ip string has to
|
|
|
|
|
* be added.
|
|
|
|
|
* \param s Pointer to the ip address string to be parsed.
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 On success.
|
|
|
|
|
* \retval -1 On failure.
|
|
|
|
|
*/
|
|
|
|
|
int IPOnlyCIDRItemSetup(IPOnlyCIDRItem *gh, char *s) {
|
|
|
|
|
SCLogDebug("gh %p, s %s", gh, s);
|
|
|
|
|
|
|
|
|
|
/* parse the address */
|
|
|
|
|
if (IPOnlyCIDRItemParseSingle(gh, s) == -1) {
|
|
|
|
|
SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC,
|
|
|
|
|
"DetectAddressParse error \"%s\"", s);
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC, "IPOnlyCIDRItemSetup error");
|
|
|
|
|
/* XXX cleanup */
|
|
|
|
|
SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC, "failed to parse addresses");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|