mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-20 11:48:28 -06:00
Use libvirt's existing ipv6/ipv4 parser/printer rather than self-written ones
This patch changes the network filtering code to use libvirt's existing IPv4 and IPv6 address parsers/printers rather than my self-written ones. I am introducing a new function in network.c that counts the number of bits in a netmask and ensures that the given address is indeed a netmask, return -1 on error or values of 0-32 for IPv4 addresses and 0-128 for IPv6 addresses. I then based the function checking for valid netmask on invoking this function.
This commit is contained in:
parent
bc2102104f
commit
0e0f6021ce
@ -473,22 +473,6 @@ checkValidMask(unsigned char *data, int len)
|
||||
}
|
||||
|
||||
|
||||
/* check for a valid IPv4 mask */
|
||||
static bool
|
||||
checkIPv4Mask(enum attrDatatype datatype ATTRIBUTE_UNUSED, void *maskptr,
|
||||
virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return checkValidMask(maskptr, 4);
|
||||
}
|
||||
|
||||
static bool
|
||||
checkIPv6Mask(enum attrDatatype datatype ATTRIBUTE_UNUSED, void *maskptr,
|
||||
virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return checkValidMask(maskptr, 16);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
checkMACMask(enum attrDatatype datatype ATTRIBUTE_UNUSED,
|
||||
void *macMask,
|
||||
@ -498,16 +482,6 @@ checkMACMask(enum attrDatatype datatype ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static int getMaskNumBits(const unsigned char *mask, int len) {
|
||||
int i = 0;
|
||||
while (i < (len << 3)) {
|
||||
if (!(mask[i>>3] & (0x80 >> (i & 3))))
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* supported arp opcode -- see 'ebtables -h arp' for the naming
|
||||
*/
|
||||
@ -1227,21 +1201,8 @@ static bool
|
||||
virNWIPv4AddressParser(const char *input,
|
||||
nwIPAddressPtr output)
|
||||
{
|
||||
int i;
|
||||
char *endptr;
|
||||
const char *n = input;
|
||||
long int d;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
d = strtol(n, &endptr, 10);
|
||||
if (d < 0 || d > 255 ||
|
||||
(endptr - n > 3 ) ||
|
||||
(i <= 2 && *endptr != '.' ) ||
|
||||
(i == 3 && *endptr != '\0'))
|
||||
return 0;
|
||||
output->addr.ipv4Addr[i] = (unsigned char)d;
|
||||
n = endptr + 1;
|
||||
}
|
||||
if (virSocketParseIpv4Addr(input, &output->addr) == -1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1250,81 +1211,8 @@ static bool
|
||||
virNWIPv6AddressParser(const char *input,
|
||||
nwIPAddressPtr output)
|
||||
{
|
||||
int i, j, pos;
|
||||
uint16_t n;
|
||||
int shiftpos = -1;
|
||||
char prevchar;
|
||||
char base;
|
||||
|
||||
memset(output, 0x0, sizeof(*output));
|
||||
|
||||
output->isIPv6 = 1;
|
||||
|
||||
pos = 0;
|
||||
i = 0;
|
||||
|
||||
while (i < 8) {
|
||||
j = 0;
|
||||
n = 0;
|
||||
while (1) {
|
||||
prevchar = input[pos++];
|
||||
if (prevchar == ':' || prevchar == 0) {
|
||||
if (j > 0) {
|
||||
output->addr.ipv6Addr[i * 2 + 0] = n >> 8;
|
||||
output->addr.ipv6Addr[i * 2 + 1] = n;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= 4)
|
||||
return 0;
|
||||
|
||||
if (prevchar >= '0' && prevchar <= '9')
|
||||
base = '0';
|
||||
else if (prevchar >= 'a' && prevchar <= 'f')
|
||||
base = 'a' - 10;
|
||||
else if (prevchar >= 'A' && prevchar <= 'F')
|
||||
base = 'A' - 10;
|
||||
else
|
||||
return 0;
|
||||
n <<= 4;
|
||||
n |= (prevchar - base);
|
||||
j++;
|
||||
}
|
||||
|
||||
if (prevchar == 0)
|
||||
break;
|
||||
|
||||
if (input[pos] == ':') {
|
||||
pos ++;
|
||||
// sequence of zeros
|
||||
if (prevchar != ':')
|
||||
return 0;
|
||||
|
||||
if (shiftpos != -1)
|
||||
return 0;
|
||||
|
||||
shiftpos = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (shiftpos != -1) {
|
||||
if (i >= 7)
|
||||
return 0;
|
||||
i--;
|
||||
j = 0;
|
||||
while (i >= shiftpos) {
|
||||
output->addr.ipv6Addr[15 - (j*2) - 1] =
|
||||
output->addr.ipv6Addr[i * 2 + 0];
|
||||
output->addr.ipv6Addr[15 - (j*2) - 0] =
|
||||
output->addr.ipv6Addr[i * 2 + 1];
|
||||
output->addr.ipv6Addr[i * 2 + 0] = 0;
|
||||
output->addr.ipv6Addr[i * 2 + 1] = 0;
|
||||
i--;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (virSocketParseIpv6Addr(input, &output->addr) == -1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1442,11 +1330,10 @@ virNWFilterRuleDetailsParse(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
} else
|
||||
rc = -1;
|
||||
} else {
|
||||
if (checkIPv4Mask(datatype,
|
||||
ipaddr.addr.ipv4Addr, nwf))
|
||||
*(uint8_t *)storage_ptr =
|
||||
getMaskNumBits(ipaddr.addr.ipv4Addr,
|
||||
sizeof(ipaddr.addr.ipv4Addr));
|
||||
int_val = virSocketGetNumNetmaskBits(
|
||||
&ipaddr.addr);
|
||||
if (int_val >= 0)
|
||||
*(uint8_t *)storage_ptr = int_val;
|
||||
else
|
||||
rc = -1;
|
||||
found = 1;
|
||||
@ -1497,11 +1384,10 @@ virNWFilterRuleDetailsParse(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
} else
|
||||
rc = -1;
|
||||
} else {
|
||||
if (checkIPv6Mask(datatype,
|
||||
ipaddr.addr.ipv6Addr, nwf))
|
||||
*(uint8_t *)storage_ptr =
|
||||
getMaskNumBits(ipaddr.addr.ipv6Addr,
|
||||
sizeof(ipaddr.addr.ipv6Addr));
|
||||
int_val = virSocketGetNumNetmaskBits(
|
||||
&ipaddr.addr);
|
||||
if (int_val >= 0)
|
||||
*(uint8_t *)storage_ptr = int_val;
|
||||
else
|
||||
rc = -1;
|
||||
found = 1;
|
||||
@ -2571,43 +2457,12 @@ virNWFilterPoolObjDeleteDef(virConnectPtr conn,
|
||||
static void
|
||||
virNWIPAddressFormat(virBufferPtr buf, nwIPAddressPtr ipaddr)
|
||||
{
|
||||
if (!ipaddr->isIPv6) {
|
||||
virBufferVSprintf(buf, "%d.%d.%d.%d",
|
||||
ipaddr->addr.ipv4Addr[0],
|
||||
ipaddr->addr.ipv4Addr[1],
|
||||
ipaddr->addr.ipv4Addr[2],
|
||||
ipaddr->addr.ipv4Addr[3]);
|
||||
} else {
|
||||
int i;
|
||||
int dcshown = 0, in_dc = 0;
|
||||
unsigned short n;
|
||||
while (i < 8) {
|
||||
n = (ipaddr->addr.ipv6Addr[i * 2 + 0] << 8) |
|
||||
ipaddr->addr.ipv6Addr[i * 2 + 1];
|
||||
if (n == 0) {
|
||||
if (!dcshown) {
|
||||
in_dc = 1;
|
||||
if (i == 0)
|
||||
virBufferAddLit(buf, ":");
|
||||
dcshown = 1;
|
||||
}
|
||||
if (in_dc) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (in_dc) {
|
||||
dcshown = 1;
|
||||
virBufferAddLit(buf, ":");
|
||||
in_dc = 0;
|
||||
}
|
||||
i++;
|
||||
virBufferVSprintf(buf, "%x", n);
|
||||
if (i < 8)
|
||||
virBufferAddLit(buf, ":");
|
||||
}
|
||||
if (in_dc)
|
||||
virBufferAddLit(buf, ":");
|
||||
virSocketAddrPtr addr = &ipaddr->addr;
|
||||
char *output = virSocketFormatAddr(addr);
|
||||
|
||||
if (output) {
|
||||
virBufferVSprintf(buf, "%s", output);
|
||||
VIR_FREE(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
# include "util.h"
|
||||
# include "hash.h"
|
||||
# include "xml.h"
|
||||
# include "network.h"
|
||||
|
||||
|
||||
/**
|
||||
* Chain suffix size is:
|
||||
@ -85,11 +87,7 @@ struct _nwMACAddress {
|
||||
typedef struct _nwIPAddress nwIPAddress;
|
||||
typedef nwIPAddress *nwIPAddressPtr;
|
||||
struct _nwIPAddress {
|
||||
int isIPv6;
|
||||
union {
|
||||
unsigned char ipv4Addr[4];
|
||||
unsigned char ipv6Addr[16];
|
||||
} addr;
|
||||
virSocketAddr addr;
|
||||
};
|
||||
|
||||
|
||||
|
@ -144,7 +144,7 @@ printDataType(virConnectPtr conn,
|
||||
nwItemDescPtr item)
|
||||
{
|
||||
int done;
|
||||
int i, pos, s;
|
||||
char *data;
|
||||
|
||||
if (printVar(conn, vars, buf, bufsize, item, &done))
|
||||
return 1;
|
||||
@ -154,30 +154,38 @@ printDataType(virConnectPtr conn,
|
||||
|
||||
switch (item->datatype) {
|
||||
case DATATYPE_IPADDR:
|
||||
if (snprintf(buf, bufsize, "%d.%d.%d.%d",
|
||||
item->u.ipaddr.addr.ipv4Addr[0],
|
||||
item->u.ipaddr.addr.ipv4Addr[1],
|
||||
item->u.ipaddr.addr.ipv4Addr[2],
|
||||
item->u.ipaddr.addr.ipv4Addr[3]) >= bufsize) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INVALID_NWFILTER,
|
||||
_("Buffer too small for IP address"));
|
||||
data = virSocketFormatAddr(&item->u.ipaddr.addr);
|
||||
if (!data) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("internal IPv4 address representation "
|
||||
"is bad"));
|
||||
return 1;
|
||||
}
|
||||
if (snprintf(buf, bufsize, "%s", data) >= bufsize) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("buffer too small for IP address"));
|
||||
VIR_FREE(data);
|
||||
return 1;
|
||||
}
|
||||
VIR_FREE(data);
|
||||
break;
|
||||
|
||||
case DATATYPE_IPV6ADDR:
|
||||
pos = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
s = snprintf(&buf[pos], bufsize - pos, "%x%s",
|
||||
(unsigned int)item->u.ipaddr.addr.ipv6Addr[i],
|
||||
((i & 1) && (i < 15)) ? ":" : "" );
|
||||
if (s >= bufsize - pos) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INVALID_NWFILTER,
|
||||
_("Buffer too small for IPv6 address"));
|
||||
return 1;
|
||||
}
|
||||
pos += s;
|
||||
data = virSocketFormatAddr(&item->u.ipaddr.addr);
|
||||
if (!data) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("internal IPv6 address representation "
|
||||
"is bad"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (snprintf(buf, bufsize, "%s", data) >= bufsize) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("buffer too small for IPv6 address"));
|
||||
VIR_FREE(data);
|
||||
return 1;
|
||||
}
|
||||
VIR_FREE(data);
|
||||
break;
|
||||
|
||||
case DATATYPE_MACADDR:
|
||||
|
@ -219,88 +219,10 @@ virSocketGetPort(virSocketAddrPtr addr) {
|
||||
* Returns 0 in case of success and -1 in case of error
|
||||
*/
|
||||
int virSocketAddrIsNetmask(virSocketAddrPtr netmask) {
|
||||
int i;
|
||||
|
||||
if (netmask == NULL)
|
||||
return(-1);
|
||||
|
||||
if (netmask->stor.ss_family == AF_INET) {
|
||||
virIPv4Addr tm;
|
||||
unsigned char tmp;
|
||||
int ok = 0;
|
||||
|
||||
if (getIPv4Addr(netmask, &tm) < 0)
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 4;i++) {
|
||||
if (tm[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 4)
|
||||
return(0);
|
||||
|
||||
tmp = 0xFF;
|
||||
do {
|
||||
if (tm[i] == tmp) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
tmp <<= 1;
|
||||
} while (tmp != 0);
|
||||
if (ok == 0)
|
||||
return(-1);
|
||||
i++;
|
||||
|
||||
if (i >= 4)
|
||||
return(0);
|
||||
|
||||
for (;i < 4;i++) {
|
||||
if (tm[i] != 0xFF)
|
||||
return(-1);
|
||||
}
|
||||
} else if (netmask->stor.ss_family == AF_INET6) {
|
||||
virIPv6Addr tm;
|
||||
unsigned short tmp;
|
||||
int ok = 0;
|
||||
|
||||
/*
|
||||
* Hum, on IPv6 people use prefixes instead of netmask
|
||||
*/
|
||||
if (getIPv6Addr(netmask, &tm) < 0)
|
||||
return(-1);
|
||||
|
||||
for (i = 0;i < 8;i++) {
|
||||
if (tm[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 8)
|
||||
return(0);
|
||||
|
||||
tmp = 0xFFFF;
|
||||
do {
|
||||
if (tm[i] == tmp) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
tmp <<= 1;
|
||||
} while (tmp != 0);
|
||||
if (ok == 0)
|
||||
return(-1);
|
||||
i++;
|
||||
|
||||
if (i >= 8)
|
||||
return(0);
|
||||
|
||||
for (;i < 8;i++) {
|
||||
if (tm[i] != 0xFFFF)
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
int n = virSocketGetNumNetmaskBits(netmask);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -415,3 +337,90 @@ int virSocketGetRange(virSocketAddrPtr start, virSocketAddrPtr end) {
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virGetNumNetmaskBits
|
||||
* @netmask: the presumed netmask
|
||||
*
|
||||
* Get the number of netmask bits in a netmask.
|
||||
*
|
||||
* Returns the number of bits in the netmask or -1 if an error occurred
|
||||
* or the netmask is invalid.
|
||||
*/
|
||||
int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask)
|
||||
{
|
||||
int i, j;
|
||||
int c = 0;
|
||||
|
||||
if (netmask->stor.ss_family == AF_INET) {
|
||||
virIPv4Addr tm;
|
||||
uint8_t bit;
|
||||
|
||||
if (getIPv4Addr(netmask, &tm) < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (tm[i] == 0xff)
|
||||
c += 8;
|
||||
else
|
||||
break;
|
||||
|
||||
if (c == 8 * 4)
|
||||
return c;
|
||||
|
||||
j = i << 3;
|
||||
while (j < (8 * 4)) {
|
||||
bit = 1 << (7 - (j & 7));
|
||||
if ((tm[j >> 3] & bit)) {
|
||||
c++;
|
||||
} else
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
|
||||
while (j < (8 * 4)) {
|
||||
bit = 1 << (7 - (j & 7));
|
||||
if ((tm[j >> 3] & bit))
|
||||
return -1;
|
||||
j++;
|
||||
}
|
||||
|
||||
return c;
|
||||
} else if (netmask->stor.ss_family == AF_INET6) {
|
||||
virIPv6Addr tm;
|
||||
uint16_t bit;
|
||||
|
||||
if (getIPv6Addr(netmask, &tm) < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (tm[i] == 0xffff)
|
||||
c += 16;
|
||||
else
|
||||
break;
|
||||
|
||||
if (c == 16 * 8)
|
||||
return c;
|
||||
|
||||
j = i << 4;
|
||||
while (j < (16 * 8)) {
|
||||
bit = 1 << (15 - (j & 0xf));
|
||||
if ((tm[j >> 4] & bit)) {
|
||||
c++;
|
||||
} else
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
|
||||
while (j < (16 * 8)) {
|
||||
bit = 1 << (15 - (j & 0xf));
|
||||
if ((tm[j >> 4]) & bit)
|
||||
return -1;
|
||||
j++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -48,4 +48,7 @@ int virSocketAddrIsNetmask(virSocketAddrPtr netmask);
|
||||
int virSocketCheckNetmask (virSocketAddrPtr addr1,
|
||||
virSocketAddrPtr addr2,
|
||||
virSocketAddrPtr netmask);
|
||||
|
||||
int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask);
|
||||
|
||||
#endif /* __VIR_NETWORK_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user