mirror of
git://git.code.sf.net/p/dhcpd-pools/code
synced 2025-12-16 15:57:00 +00:00
getdata: add cidr range support
This makes 'range6 123::/45' style cidr notation to be understood as address range. Earlier ranges that used cidr failed to parse completely. Reported-by: Jeff Bailey <jeffrey.bailey@bt.com> Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
parent
48d0629881
commit
bb0fa9adae
13 changed files with 175 additions and 5 deletions
1
THANKS
1
THANKS
|
|
@ -41,3 +41,4 @@ Ivanov Ivan
|
||||||
Manuel Hachtkemper
|
Manuel Hachtkemper
|
||||||
Klaus Slott
|
Klaus Slott
|
||||||
Boris Lytochkin
|
Boris Lytochkin
|
||||||
|
Jeff Bailey
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,8 @@ extern int parse_ipaddr_init(const char *restrict src,
|
||||||
extern int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst);
|
extern int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst);
|
||||||
extern int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst);
|
extern int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst);
|
||||||
|
|
||||||
|
extern void parse_cidr(struct range_t *range_p, const char *word);
|
||||||
|
|
||||||
extern void (*copy_ipaddr) (union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
|
extern void (*copy_ipaddr) (union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
|
||||||
extern void copy_ipaddr_init(union ipaddr_t *restrict dst,
|
extern void copy_ipaddr_init(union ipaddr_t *restrict dst,
|
||||||
const union ipaddr_t *restrict src);
|
const union ipaddr_t *restrict src);
|
||||||
|
|
|
||||||
|
|
@ -339,13 +339,19 @@ void parse_config(int is_include, const char *restrict config_file,
|
||||||
/* printf ("range 2nd ip: %s\n", word); */
|
/* printf ("range 2nd ip: %s\n", word); */
|
||||||
range_p = ranges + num_ranges;
|
range_p = ranges + num_ranges;
|
||||||
argument = ITS_NOTHING_INTERESTING;
|
argument = ITS_NOTHING_INTERESTING;
|
||||||
parse_ipaddr(word, &addr);
|
if (strchr(word, '/')) {
|
||||||
if (one_ip_range == 1) {
|
parse_cidr(range_p, word);
|
||||||
one_ip_range = 0;
|
one_ip_range = 0;
|
||||||
copy_ipaddr(&range_p->first_ip, &addr);
|
} else {
|
||||||
|
/* not cidr */
|
||||||
|
parse_ipaddr(word, &addr);
|
||||||
|
if (one_ip_range == 1) {
|
||||||
|
one_ip_range = 0;
|
||||||
|
copy_ipaddr(&range_p->first_ip, &addr);
|
||||||
|
}
|
||||||
|
copy_ipaddr(&range_p->last_ip, &addr);
|
||||||
|
reorder_last_first(range_p);
|
||||||
}
|
}
|
||||||
copy_ipaddr(&range_p->last_ip, &addr);
|
|
||||||
reorder_last_first(range_p);
|
|
||||||
newrange:
|
newrange:
|
||||||
range_p->count = 0;
|
range_p->count = 0;
|
||||||
range_p->touched = 0;
|
range_p->touched = 0;
|
||||||
|
|
|
||||||
94
src/other.c
94
src/other.c
|
|
@ -52,10 +52,15 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "progname.h"
|
#include "progname.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
|
#include "xalloc.h"
|
||||||
|
|
||||||
#include "dhcpd-pools.h"
|
#include "dhcpd-pools.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
|
|
||||||
|
char *(*cidr_last)(union ipaddr_t *restrict addr, const int mask);
|
||||||
|
static char *cidr_last_v4(union ipaddr_t *restrict addr, const int mask);
|
||||||
|
static char *cidr_last_v6(union ipaddr_t *restrict addr, const int mask);
|
||||||
|
|
||||||
/*! \brief Set function pointers depending on IP version.
|
/*! \brief Set function pointers depending on IP version.
|
||||||
* \param ip IP version.
|
* \param ip IP version.
|
||||||
*/
|
*/
|
||||||
|
|
@ -73,6 +78,7 @@ void set_ipv_functions(int version)
|
||||||
leasecomp = leasecomp_v4;
|
leasecomp = leasecomp_v4;
|
||||||
ntop_ipaddr = ntop_ipaddr_v4;
|
ntop_ipaddr = ntop_ipaddr_v4;
|
||||||
parse_ipaddr = parse_ipaddr_v4;
|
parse_ipaddr = parse_ipaddr_v4;
|
||||||
|
cidr_last = cidr_last_v4;
|
||||||
xstrstr = xstrstr_v4;
|
xstrstr = xstrstr_v4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -86,6 +92,7 @@ void set_ipv_functions(int version)
|
||||||
leasecomp = leasecomp_v6;
|
leasecomp = leasecomp_v6;
|
||||||
ntop_ipaddr = ntop_ipaddr_v6;
|
ntop_ipaddr = ntop_ipaddr_v6;
|
||||||
parse_ipaddr = parse_ipaddr_v6;
|
parse_ipaddr = parse_ipaddr_v6;
|
||||||
|
cidr_last = cidr_last_v6;
|
||||||
xstrstr = xstrstr_v6;
|
xstrstr = xstrstr_v6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -99,6 +106,7 @@ void set_ipv_functions(int version)
|
||||||
leasecomp = leasecomp_init;
|
leasecomp = leasecomp_init;
|
||||||
ntop_ipaddr = ntop_ipaddr_init;
|
ntop_ipaddr = ntop_ipaddr_init;
|
||||||
parse_ipaddr = parse_ipaddr_init;
|
parse_ipaddr = parse_ipaddr_init;
|
||||||
|
cidr_last = NULL;
|
||||||
xstrstr = xstrstr_init;
|
xstrstr = xstrstr_init;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -148,6 +156,92 @@ int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst)
|
||||||
return rv == 1;
|
return rv == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int strtol_mask(const char *str)
|
||||||
|
{
|
||||||
|
long num;
|
||||||
|
char *end = NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (str == NULL || *str == '\0')
|
||||||
|
goto err;
|
||||||
|
num = strtol(str, &end, 10);
|
||||||
|
|
||||||
|
if (errno || str == end || (end && *end))
|
||||||
|
goto err;
|
||||||
|
if (num < 0 || 128 < num)
|
||||||
|
goto err;
|
||||||
|
return (int)num;
|
||||||
|
err:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *cidr_last_v4(union ipaddr_t *restrict addr, const int mask)
|
||||||
|
{
|
||||||
|
union ipaddr_t last_ip;
|
||||||
|
uint32_t netmask;
|
||||||
|
const char *ip;
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
netmask = (1U << (32 - mask)) - 1;
|
||||||
|
else
|
||||||
|
netmask = 0;
|
||||||
|
last_ip.v4 = addr->v4 | netmask;
|
||||||
|
|
||||||
|
ip = ntop_ipaddr(&last_ip);
|
||||||
|
return xstrdup(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *cidr_last_v6(union ipaddr_t *restrict addr, const int mask)
|
||||||
|
{
|
||||||
|
union ipaddr_t bitmask;
|
||||||
|
int i, j;
|
||||||
|
char ip[128];
|
||||||
|
|
||||||
|
memset(&bitmask, 0x0, sizeof(bitmask));
|
||||||
|
for (i = mask, j = 0; i > 0; i -= 8, j++) {
|
||||||
|
if (i >= 8)
|
||||||
|
bitmask.v6[j] = 0xff;
|
||||||
|
else
|
||||||
|
bitmask.v6[j] = (unsigned char)(0xffU << (8 - i));
|
||||||
|
}
|
||||||
|
for (i = 0; i < (int)sizeof(bitmask); i++)
|
||||||
|
addr->v6[i] |= ~bitmask.v6[i];
|
||||||
|
inet_ntop(AF_INET6, addr, ip, sizeof(ip));
|
||||||
|
return xstrdup(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_cidr(struct range_t *range_p, const char *word)
|
||||||
|
{
|
||||||
|
char *divider;
|
||||||
|
int mask;
|
||||||
|
union ipaddr_t addr;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
/* determine cidr */
|
||||||
|
divider = strchr(word, '/');
|
||||||
|
*divider++ = '\0';
|
||||||
|
mask = strtol_mask(divider);
|
||||||
|
if (mask < 0)
|
||||||
|
error(EXIT_FAILURE, 0, "cidr %s invalid mask %s", word,
|
||||||
|
divider);
|
||||||
|
if (config.ip_version == IPvUNKNOWN) {
|
||||||
|
if (!strchr(word, ':'))
|
||||||
|
set_ipv_functions(IPv4);
|
||||||
|
else
|
||||||
|
set_ipv_functions(IPv6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start of the range is easy */
|
||||||
|
parse_ipaddr(word, &addr);
|
||||||
|
copy_ipaddr(&range_p->first_ip, &addr);
|
||||||
|
|
||||||
|
/* end of the range depends cidr size */
|
||||||
|
last = cidr_last(&addr, mask);
|
||||||
|
parse_ipaddr(last, &addr);
|
||||||
|
copy_ipaddr(&range_p->last_ip, &addr);
|
||||||
|
free(last);
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief Copy IP address to union.
|
/*! \brief Copy IP address to union.
|
||||||
*
|
*
|
||||||
* \param dst Destination for a binary IP address.
|
* \param dst Destination for a binary IP address.
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ TESTS = \
|
||||||
tests/leading0 \
|
tests/leading0 \
|
||||||
tests/one-ip \
|
tests/one-ip \
|
||||||
tests/one-line \
|
tests/one-line \
|
||||||
|
tests/range4 \
|
||||||
|
tests/range6 \
|
||||||
tests/same-twice \
|
tests/same-twice \
|
||||||
tests/simple \
|
tests/simple \
|
||||||
tests/sorts \
|
tests/sorts \
|
||||||
|
|
|
||||||
31
tests/confs/range4
Normal file
31
tests/confs/range4
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
shared-network example1 {
|
||||||
|
subnet 10.0.0.0 netmask 255.255.255.0 {
|
||||||
|
pool {
|
||||||
|
range 10.0.0.0/27;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subnet 10.1.0.0 netmask 255.255.255.0 {
|
||||||
|
pool {
|
||||||
|
range 10.1.0.1/27;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shared-network example2 {
|
||||||
|
subnet 10.2.0.0 netmask 255.255.255.0 {
|
||||||
|
pool {
|
||||||
|
range 10.2.0.1/28;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subnet 10.3.0.0 netmask 255.255.255.0 {
|
||||||
|
pool {
|
||||||
|
range 10.3.0.1/29;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subnet 10.4.0.0 netmask 255.255.255.0 {
|
||||||
|
pool {
|
||||||
|
range 10.4.0.1/32;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
tests/confs/range6
Normal file
4
tests/confs/range6
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
subnet6 dead:abba:1000::/56 {
|
||||||
|
range6 dead:abba:1000::/56;
|
||||||
|
prefix6 dead:abba:1000:0100:: dead:abba:1000:ff00::/56;
|
||||||
|
}
|
||||||
16
tests/expected/range4
Normal file
16
tests/expected/range4
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
Ranges:
|
||||||
|
shared net name first ip last ip max cur percent touch t+c t+c perc
|
||||||
|
example1 10.0.0.0 - 10.0.0.31 32 12 37.500 0 12 37.500
|
||||||
|
example1 10.1.0.1 - 10.1.0.31 31 10 32.258 0 10 32.258
|
||||||
|
example2 10.2.0.1 - 10.2.0.15 15 8 53.333 0 8 53.333
|
||||||
|
example2 10.3.0.1 - 10.3.0.7 7 7 100.000 0 7 100.000
|
||||||
|
All networks 10.4.0.1 - 10.4.0.1 1 1 100.000 0 1 100.000
|
||||||
|
|
||||||
|
Shared networks:
|
||||||
|
name max cur percent touch t+c t+c perc
|
||||||
|
example1 63 22 34.921 0 22 34.921
|
||||||
|
example2 22 15 68.182 0 15 68.182
|
||||||
|
|
||||||
|
Sum of all ranges:
|
||||||
|
name max cur percent touch t+c t+c perc
|
||||||
|
All networks 86 38 44.186 0 38 44.186
|
||||||
10
tests/expected/range6
Normal file
10
tests/expected/range6
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
Ranges:
|
||||||
|
shared net name first ip last ip max cur percent touch t+c t+c perc
|
||||||
|
All networks dead:abba:1000:: - dead:abba:1000:ff:ffff:ffff:ffff:ffff 4.72237e+21 2 0.000 1 3 0.000
|
||||||
|
|
||||||
|
Shared networks:
|
||||||
|
name max cur percent touch t+c t+c perc
|
||||||
|
|
||||||
|
Sum of all ranges:
|
||||||
|
name max cur percent touch t+c t+c perc
|
||||||
|
All networks 4.72237e+21 2 0.000 1 3 0.000
|
||||||
1
tests/leases/range4
Symbolic link
1
tests/leases/range4
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
complete
|
||||||
1
tests/leases/range6
Symbolic link
1
tests/leases/range6
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
v6
|
||||||
1
tests/range4
Symbolic link
1
tests/range4
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
test.sh
|
||||||
1
tests/range6
Symbolic link
1
tests/range6
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
test.sh
|
||||||
Loading…
Add table
Add a link
Reference in a new issue