mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 13:19:17 +00:00
lib: Rewrite ipv6 prefix matcher
Simplify ipv6 prefix matcher / validator to use standard Linux networking functions instead of a state machine. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com> Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
parent
2caa9b3957
commit
4c58c70dcb
130
lib/command.c
130
lib/command.c
@ -1003,13 +1003,6 @@ cmd_ipv4_prefix_match (const char *str)
|
|||||||
|
|
||||||
#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
|
#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
|
||||||
#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
|
#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
|
||||||
#define STATE_START 1
|
|
||||||
#define STATE_COLON 2
|
|
||||||
#define STATE_DOUBLE 3
|
|
||||||
#define STATE_ADDR 4
|
|
||||||
#define STATE_DOT 5
|
|
||||||
#define STATE_SLASH 6
|
|
||||||
#define STATE_MASK 7
|
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|
||||||
@ -1040,11 +1033,10 @@ cmd_ipv6_match (const char *str)
|
|||||||
static enum match_type
|
static enum match_type
|
||||||
cmd_ipv6_prefix_match (const char *str)
|
cmd_ipv6_prefix_match (const char *str)
|
||||||
{
|
{
|
||||||
int state = STATE_START;
|
struct sockaddr_in6 sin6_dummy;
|
||||||
int colons = 0, nums = 0, double_colon = 0;
|
const char *delim = "/\0";
|
||||||
int mask;
|
char *dupe, *prefix, *mask, *context, *endptr;
|
||||||
const char *sp = NULL;
|
int nmask = -1;
|
||||||
char *endptr = NULL;
|
|
||||||
|
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
return partly_match;
|
return partly_match;
|
||||||
@ -1052,115 +1044,25 @@ cmd_ipv6_prefix_match (const char *str)
|
|||||||
if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
|
if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
|
||||||
return no_match;
|
return no_match;
|
||||||
|
|
||||||
while (*str != '\0' && state != STATE_MASK)
|
/* tokenize to address + mask */
|
||||||
{
|
dupe = XMALLOC(MTYPE_TMP, strlen(str)+1);
|
||||||
switch (state)
|
strncpy(dupe, str, strlen(str)+1);
|
||||||
{
|
prefix = strtok_r(dupe, delim, &context);
|
||||||
case STATE_START:
|
mask = strtok_r(NULL, delim, &context);
|
||||||
if (*str == ':')
|
|
||||||
{
|
|
||||||
if (*(str + 1) != ':' && *(str + 1) != '\0')
|
|
||||||
return no_match;
|
|
||||||
colons--;
|
|
||||||
state = STATE_COLON;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sp = str;
|
|
||||||
state = STATE_ADDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
if (!mask)
|
||||||
case STATE_COLON:
|
|
||||||
colons++;
|
|
||||||
if (*(str + 1) == '/')
|
|
||||||
return no_match;
|
|
||||||
else if (*(str + 1) == ':')
|
|
||||||
state = STATE_DOUBLE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sp = str + 1;
|
|
||||||
state = STATE_ADDR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATE_DOUBLE:
|
|
||||||
if (double_colon)
|
|
||||||
return no_match;
|
|
||||||
|
|
||||||
if (*(str + 1) == ':')
|
|
||||||
return no_match;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*(str + 1) != '\0' && *(str + 1) != '/')
|
|
||||||
colons++;
|
|
||||||
sp = str + 1;
|
|
||||||
|
|
||||||
if (*(str + 1) == '/')
|
|
||||||
state = STATE_SLASH;
|
|
||||||
else
|
|
||||||
state = STATE_ADDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
double_colon++;
|
|
||||||
nums += 1;
|
|
||||||
break;
|
|
||||||
case STATE_ADDR:
|
|
||||||
if (*(str + 1) == ':' || *(str + 1) == '.'
|
|
||||||
|| *(str + 1) == '\0' || *(str + 1) == '/')
|
|
||||||
{
|
|
||||||
if (str - sp > 3)
|
|
||||||
return no_match;
|
|
||||||
|
|
||||||
for (; sp <= str; sp++)
|
|
||||||
if (*sp == '/')
|
|
||||||
return no_match;
|
|
||||||
|
|
||||||
nums++;
|
|
||||||
|
|
||||||
if (*(str + 1) == ':')
|
|
||||||
state = STATE_COLON;
|
|
||||||
else if (*(str + 1) == '.')
|
|
||||||
{
|
|
||||||
if (colons || double_colon)
|
|
||||||
state = STATE_DOT;
|
|
||||||
else
|
|
||||||
return no_match;
|
|
||||||
}
|
|
||||||
else if (*(str + 1) == '/')
|
|
||||||
state = STATE_SLASH;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATE_DOT:
|
|
||||||
state = STATE_ADDR;
|
|
||||||
break;
|
|
||||||
case STATE_SLASH:
|
|
||||||
if (*(str + 1) == '\0')
|
|
||||||
return partly_match;
|
return partly_match;
|
||||||
|
|
||||||
state = STATE_MASK;
|
/* validate prefix */
|
||||||
break;
|
if (inet_pton(AF_INET6, prefix, &sin6_dummy.sin6_addr) != 1)
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nums > 11)
|
|
||||||
return no_match;
|
return no_match;
|
||||||
|
|
||||||
if (colons > 7)
|
/* validate mask */
|
||||||
|
nmask = strtol (mask, &endptr, 10);
|
||||||
|
if (*endptr != '\0' || nmask < 0 || nmask > 128)
|
||||||
return no_match;
|
return no_match;
|
||||||
|
|
||||||
str++;
|
XFREE(MTYPE_TMP, dupe);
|
||||||
}
|
|
||||||
|
|
||||||
if (state < STATE_MASK)
|
|
||||||
return partly_match;
|
|
||||||
|
|
||||||
mask = strtol (str, &endptr, 10);
|
|
||||||
if (*endptr != '\0')
|
|
||||||
return no_match;
|
|
||||||
|
|
||||||
if (mask < 0 || mask > 128)
|
|
||||||
return no_match;
|
|
||||||
|
|
||||||
return exact_match;
|
return exact_match;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user