mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 02:51:16 +00:00
Enable detection of multiple IP addresses
In preparation of DHCP Snooping and the detection of multiple IP addresses per interface: The hash table that is used to collect the detected IP address of an interface can so far only handle one IP address per interface. With this patch we extend this to allow it to handle a list of IP addresses. Above changes the returned variable type of virNWFilterGetIpAddrForIfname() from char * to virNWFilterVarValuePtr; adapt all existing functions calling this function.
This commit is contained in:
parent
5c5e07b84c
commit
ad6c67cf85
@ -37,7 +37,7 @@
|
|||||||
static bool isValidVarValue(const char *value);
|
static bool isValidVarValue(const char *value);
|
||||||
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
virNWFilterVarValueFree(virNWFilterVarValuePtr val)
|
virNWFilterVarValueFree(virNWFilterVarValuePtr val)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -60,7 +60,7 @@ virNWFilterVarValueFree(virNWFilterVarValuePtr val)
|
|||||||
VIR_FREE(val);
|
VIR_FREE(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static virNWFilterVarValuePtr
|
virNWFilterVarValuePtr
|
||||||
virNWFilterVarValueCopy(const virNWFilterVarValuePtr val)
|
virNWFilterVarValueCopy(const virNWFilterVarValuePtr val)
|
||||||
{
|
{
|
||||||
virNWFilterVarValuePtr res;
|
virNWFilterVarValuePtr res;
|
||||||
@ -222,6 +222,56 @@ virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virNWFilterVarValueDelNthValue(virNWFilterVarValuePtr val, unsigned int pos)
|
||||||
|
{
|
||||||
|
switch (val->valType) {
|
||||||
|
case NWFILTER_VALUE_TYPE_SIMPLE:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case NWFILTER_VALUE_TYPE_ARRAY:
|
||||||
|
if (pos < val->u.array.nValues) {
|
||||||
|
VIR_FREE(val->u.array.values[pos]);
|
||||||
|
val->u.array.nValues--;
|
||||||
|
|
||||||
|
if (pos < val->u.array.nValues)
|
||||||
|
memmove(&val->u.array.values[pos],
|
||||||
|
&val->u.array.values[pos + 1],
|
||||||
|
sizeof(val->u.array.values[0]) *
|
||||||
|
(val->u.array.nValues - pos));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NWFILTER_VALUE_TYPE_LAST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
switch (val->valType) {
|
||||||
|
case NWFILTER_VALUE_TYPE_SIMPLE:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case NWFILTER_VALUE_TYPE_ARRAY:
|
||||||
|
for (i = 0; i < val->u.array.nValues; i++)
|
||||||
|
if (STREQ(value, val->u.array.values[i]))
|
||||||
|
return virNWFilterVarValueDelNthValue(val, i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NWFILTER_VALUE_TYPE_LAST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci)
|
virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci)
|
||||||
{
|
{
|
||||||
@ -521,14 +571,14 @@ virNWFilterHashTableCreate(int n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
void *
|
||||||
virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht,
|
virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht,
|
||||||
const char *entry)
|
const char *entry)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int rc = virHashRemoveEntry(ht->hashTable, entry);
|
void *value = virHashSteal(ht->hashTable, entry);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (value) {
|
||||||
for (i = 0; i < ht->nNames; i++) {
|
for (i = 0; i < ht->nNames; i++) {
|
||||||
if (STREQ(ht->names[i], entry)) {
|
if (STREQ(ht->names[i], entry)) {
|
||||||
VIR_FREE(ht->names[i]);
|
VIR_FREE(ht->names[i]);
|
||||||
@ -538,7 +588,7 @@ virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,11 +50,14 @@ struct _virNWFilterVarValue {
|
|||||||
|
|
||||||
virNWFilterVarValuePtr virNWFilterVarValueCreateSimple(char *);
|
virNWFilterVarValuePtr virNWFilterVarValueCreateSimple(char *);
|
||||||
virNWFilterVarValuePtr virNWFilterVarValueCreateSimpleCopyValue(const char *);
|
virNWFilterVarValuePtr virNWFilterVarValueCreateSimpleCopyValue(const char *);
|
||||||
|
virNWFilterVarValuePtr virNWFilterVarValueCopy(const virNWFilterVarValuePtr);
|
||||||
|
void virNWFilterVarValueFree(virNWFilterVarValuePtr val);
|
||||||
const char *virNWFilterVarValueGetSimple(const virNWFilterVarValuePtr val);
|
const char *virNWFilterVarValueGetSimple(const virNWFilterVarValuePtr val);
|
||||||
const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val,
|
const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val,
|
||||||
unsigned int idx);
|
unsigned int idx);
|
||||||
unsigned int virNWFilterVarValueGetCardinality(const virNWFilterVarValuePtr);
|
unsigned int virNWFilterVarValueGetCardinality(const virNWFilterVarValuePtr);
|
||||||
int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value);
|
int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value);
|
||||||
|
int virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value);
|
||||||
|
|
||||||
typedef struct _virNWFilterHashTable virNWFilterHashTable;
|
typedef struct _virNWFilterHashTable virNWFilterHashTable;
|
||||||
typedef virNWFilterHashTable *virNWFilterHashTablePtr;
|
typedef virNWFilterHashTable *virNWFilterHashTablePtr;
|
||||||
@ -77,7 +80,7 @@ int virNWFilterHashTablePut(virNWFilterHashTablePtr table,
|
|||||||
const char *name,
|
const char *name,
|
||||||
virNWFilterVarValuePtr val,
|
virNWFilterVarValuePtr val,
|
||||||
int freeName);
|
int freeName);
|
||||||
int virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
|
void *virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
|
||||||
const char *name);
|
const char *name);
|
||||||
int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src,
|
int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src,
|
||||||
virNWFilterHashTablePtr dest);
|
virNWFilterHashTablePtr dest);
|
||||||
|
@ -846,8 +846,14 @@ virNWFilterVarCombIterCreate;
|
|||||||
virNWFilterVarCombIterFree;
|
virNWFilterVarCombIterFree;
|
||||||
virNWFilterVarCombIterGetVarValue;
|
virNWFilterVarCombIterGetVarValue;
|
||||||
virNWFilterVarCombIterNext;
|
virNWFilterVarCombIterNext;
|
||||||
|
virNWFilterVarValueAddValue;
|
||||||
|
virNWFilterVarValueCopy;
|
||||||
virNWFilterVarValueCreateSimple;
|
virNWFilterVarValueCreateSimple;
|
||||||
virNWFilterVarValueCreateSimpleCopyValue;
|
virNWFilterVarValueCreateSimpleCopyValue;
|
||||||
|
virNWFilterVarValueDelValue;
|
||||||
|
virNWFilterVarValueFree;
|
||||||
|
virNWFilterVarValueGetCardinality;
|
||||||
|
virNWFilterVarValueGetNthValue;
|
||||||
virNWFilterVarValueGetSimple;
|
virNWFilterVarValueGetSimple;
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst)
|
|||||||
static int
|
static int
|
||||||
virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
|
virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
|
||||||
char *macaddr,
|
char *macaddr,
|
||||||
char *ipaddr)
|
const virNWFilterVarValuePtr ipaddr)
|
||||||
{
|
{
|
||||||
virNWFilterVarValue *val;
|
virNWFilterVarValue *val;
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ipaddr) {
|
if (ipaddr) {
|
||||||
val = virNWFilterVarValueCreateSimple(ipaddr);
|
val = virNWFilterVarValueCopy(ipaddr);
|
||||||
if (!val)
|
if (!val)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -194,7 +194,8 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
|
|||||||
* is attached to the virConnect object.
|
* is attached to the virConnect object.
|
||||||
*/
|
*/
|
||||||
virNWFilterHashTablePtr
|
virNWFilterHashTablePtr
|
||||||
virNWFilterCreateVarHashmap(char *macaddr, char *ipaddr) {
|
virNWFilterCreateVarHashmap(char *macaddr,
|
||||||
|
const virNWFilterVarValuePtr ipaddr) {
|
||||||
virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
|
virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
|
||||||
if (!table) {
|
if (!table) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -796,7 +797,7 @@ __virNWFilterInstantiateFilter(virConnectPtr conn,
|
|||||||
virNWFilterDefPtr filter;
|
virNWFilterDefPtr filter;
|
||||||
char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
|
char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
|
||||||
char *str_macaddr = NULL;
|
char *str_macaddr = NULL;
|
||||||
const char *ipaddr;
|
virNWFilterVarValuePtr ipaddr;
|
||||||
char *str_ipaddr = NULL;
|
char *str_ipaddr = NULL;
|
||||||
|
|
||||||
techdriver = virNWFilterTechDriverForName(drvname);
|
techdriver = virNWFilterTechDriverForName(drvname);
|
||||||
@ -836,16 +837,8 @@ __virNWFilterInstantiateFilter(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ipaddr = virNWFilterGetIpAddrForIfname(ifname);
|
ipaddr = virNWFilterGetIpAddrForIfname(ifname);
|
||||||
if (ipaddr) {
|
|
||||||
str_ipaddr = strdup(ipaddr);
|
|
||||||
if (!str_ipaddr) {
|
|
||||||
virReportOOMError();
|
|
||||||
rc = 1;
|
|
||||||
goto err_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vars1 = virNWFilterCreateVarHashmap(str_macaddr, str_ipaddr);
|
vars1 = virNWFilterCreateVarHashmap(str_macaddr, ipaddr);
|
||||||
if (!vars1) {
|
if (!vars1) {
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
@ -1101,7 +1094,7 @@ _virNWFilterTeardownFilter(const char *ifname)
|
|||||||
|
|
||||||
techdriver->allTeardown(ifname);
|
techdriver->allTeardown(ifname);
|
||||||
|
|
||||||
virNWFilterDelIpAddrForIfname(ifname);
|
virNWFilterDelIpAddrForIfname(ifname, NULL);
|
||||||
|
|
||||||
virNWFilterUnlockIface(ifname);
|
virNWFilterUnlockIface(ifname);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ int virNWFilterInstantiateFilterLate(virConnectPtr conn,
|
|||||||
int virNWFilterTeardownFilter(const virDomainNetDefPtr net);
|
int virNWFilterTeardownFilter(const virDomainNetDefPtr net);
|
||||||
|
|
||||||
virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr,
|
virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr,
|
||||||
char *ipaddr);
|
const virNWFilterVarValuePtr);
|
||||||
|
|
||||||
void virNWFilterDomainFWUpdateCB(void *payload,
|
void virNWFilterDomainFWUpdateCB(void *payload,
|
||||||
const void *name,
|
const void *name,
|
||||||
|
@ -310,41 +310,99 @@ virNWFilterDeregisterLearnReq(int ifindex) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add an IP address to the list of IP addresses an interface is
|
||||||
|
* known to use. This function feeds the per-interface cache that
|
||||||
|
* is used to instantiate filters with variable '$IP'.
|
||||||
|
*
|
||||||
|
* @ifname: The name of the (tap) interface
|
||||||
|
* @addr: An IPv4 address in dotted decimal format that the (tap)
|
||||||
|
* interface is known to use.
|
||||||
|
*
|
||||||
|
* This function returns 0 on success, -1 otherwise
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
virNWFilterAddIpAddrForIfname(const char *ifname, char *addr) {
|
virNWFilterAddIpAddrForIfname(const char *ifname, char *addr)
|
||||||
|
{
|
||||||
int ret;
|
int ret;
|
||||||
virNWFilterVarValuePtr val = virNWFilterVarValueCreateSimple(addr);
|
virNWFilterVarValuePtr val;
|
||||||
|
|
||||||
if (!val)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
virMutexLock(&ipAddressMapLock);
|
virMutexLock(&ipAddressMapLock);
|
||||||
|
|
||||||
|
val = virHashLookup(ipAddressMap->hashTable, ifname);
|
||||||
|
if (!val) {
|
||||||
|
val = virNWFilterVarValueCreateSimple(addr);
|
||||||
|
if (!val) {
|
||||||
|
virReportOOMError();
|
||||||
|
ret = -1;
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1);
|
ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1);
|
||||||
|
} else {
|
||||||
|
if (virNWFilterVarValueAddValue(val, addr) < 0)
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_exit:
|
||||||
virMutexUnlock(&ipAddressMapLock);
|
virMutexUnlock(&ipAddressMapLock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Delete all or a specific IP address from an interface. After this
|
||||||
void
|
* call either all or the given IP address will not be associated
|
||||||
virNWFilterDelIpAddrForIfname(const char *ifname) {
|
* with the interface anymore.
|
||||||
|
*
|
||||||
|
* @ifname: The name of the (tap) interface
|
||||||
|
* @addr: An IPv4 address in dotted decimal format that the (tap)
|
||||||
|
* interface is not using anymore; provide NULL to remove all IP
|
||||||
|
* addresses associated with the given interface
|
||||||
|
*
|
||||||
|
* This function returns the number of IP addresses that are still
|
||||||
|
* known to be associated with this interface, in case of an error
|
||||||
|
* -1 is returned. Error conditions are:
|
||||||
|
* - IP addresses is not known to be associated with the interface
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virNWFilterDelIpAddrForIfname(const char *ifname, const char *ipaddr)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
virNWFilterVarValuePtr val = NULL;
|
||||||
|
|
||||||
virMutexLock(&ipAddressMapLock);
|
virMutexLock(&ipAddressMapLock);
|
||||||
|
|
||||||
if (virHashLookup(ipAddressMap->hashTable, ifname))
|
if (ipaddr != NULL) {
|
||||||
virNWFilterHashTableRemoveEntry(ipAddressMap, ifname);
|
val = virHashLookup(ipAddressMap->hashTable, ifname);
|
||||||
|
if (val) {
|
||||||
virMutexUnlock(&ipAddressMapLock);
|
if (virNWFilterVarValueGetCardinality(val) == 1 &&
|
||||||
|
STREQ(ipaddr,
|
||||||
|
virNWFilterVarValueGetNthValue(val, 0)))
|
||||||
|
goto remove_entry;
|
||||||
|
virNWFilterVarValueDelValue(val, ipaddr);
|
||||||
|
ret = virNWFilterVarValueGetCardinality(val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
remove_entry:
|
||||||
|
/* remove whole entry */
|
||||||
|
val = virNWFilterHashTableRemoveEntry(ipAddressMap, ifname);
|
||||||
|
virNWFilterVarValueFree(val);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virMutexUnlock(&ipAddressMapLock);
|
||||||
|
|
||||||
const char *
|
return ret;
|
||||||
virNWFilterGetIpAddrForIfname(const char *ifname) {
|
}
|
||||||
|
|
||||||
|
/* Get the list of IP addresses known to be in use by an interface
|
||||||
|
*
|
||||||
|
* This function returns NULL in case no IP address is known to be
|
||||||
|
* associated with the interface, a virNWFilterVarValuePtr otherwise
|
||||||
|
* that then can contain one or multiple entries.
|
||||||
|
*/
|
||||||
|
virNWFilterVarValuePtr
|
||||||
|
virNWFilterGetIpAddrForIfname(const char *ifname)
|
||||||
|
{
|
||||||
virNWFilterVarValuePtr res;
|
virNWFilterVarValuePtr res;
|
||||||
|
|
||||||
virMutexLock(&ipAddressMapLock);
|
virMutexLock(&ipAddressMapLock);
|
||||||
@ -353,10 +411,7 @@ virNWFilterGetIpAddrForIfname(const char *ifname) {
|
|||||||
|
|
||||||
virMutexUnlock(&ipAddressMapLock);
|
virMutexUnlock(&ipAddressMapLock);
|
||||||
|
|
||||||
if (res)
|
return res;
|
||||||
return virNWFilterVarValueGetSimple(res);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -642,7 +697,10 @@ learnIPAddressThread(void *arg)
|
|||||||
char *inetaddr;
|
char *inetaddr;
|
||||||
|
|
||||||
if ((inetaddr = virSocketAddrFormat(&sa))!= NULL) {
|
if ((inetaddr = virSocketAddrFormat(&sa))!= NULL) {
|
||||||
virNWFilterAddIpAddrForIfname(req->ifname, inetaddr);
|
if (virNWFilterAddIpAddrForIfname(req->ifname, inetaddr) < 0) {
|
||||||
|
VIR_ERROR(_("Failed to add IP address %s to IP address "
|
||||||
|
"cache for interface %s"), inetaddr, req->ifname);
|
||||||
|
}
|
||||||
|
|
||||||
ret = virNWFilterInstantiateFilterLate(NULL,
|
ret = virNWFilterInstantiateFilterLate(NULL,
|
||||||
req->ifname,
|
req->ifname,
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#ifndef __NWFILTER_LEARNIPADDR_H
|
#ifndef __NWFILTER_LEARNIPADDR_H
|
||||||
# define __NWFILTER_LEARNIPADDR_H
|
# define __NWFILTER_LEARNIPADDR_H
|
||||||
|
|
||||||
|
# include "conf/nwfilter_params.h"
|
||||||
|
|
||||||
enum howDetect {
|
enum howDetect {
|
||||||
DETECT_DHCP = 1,
|
DETECT_DHCP = 1,
|
||||||
DETECT_STATIC = 2,
|
DETECT_STATIC = 2,
|
||||||
@ -63,8 +65,8 @@ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver,
|
|||||||
virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex);
|
virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex);
|
||||||
int virNWFilterTerminateLearnReq(const char *ifname);
|
int virNWFilterTerminateLearnReq(const char *ifname);
|
||||||
|
|
||||||
void virNWFilterDelIpAddrForIfname(const char *ifname);
|
int virNWFilterDelIpAddrForIfname(const char *ifname, const char *ipaddr);
|
||||||
const char *virNWFilterGetIpAddrForIfname(const char *ifname);
|
virNWFilterVarValuePtr virNWFilterGetIpAddrForIfname(const char *ifname);
|
||||||
|
|
||||||
int virNWFilterLockIface(const char *ifname) ATTRIBUTE_RETURN_CHECK;
|
int virNWFilterLockIface(const char *ifname) ATTRIBUTE_RETURN_CHECK;
|
||||||
void virNWFilterUnlockIface(const char *ifname);
|
void virNWFilterUnlockIface(const char *ifname);
|
||||||
|
Loading…
Reference in New Issue
Block a user