diff --git a/src/Makefile.am b/src/Makefile.am index a873e2e281..d72788986a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -160,9 +160,11 @@ NETWORK_CONF_SOURCES = \ # Network filter driver generic impl APIs NWFILTER_PARAM_CONF_SOURCES = \ conf/nwfilter_params.c conf/nwfilter_params.h \ + conf/nwfilter_ipaddrmap.c \ + conf/nwfilter_ipaddrmap.h \ conf/nwfilter_conf.h -NWFILTER_CONF_SOURCES = \ +NWFILTER_CONF_SOURCES = \ $(NWFILTER_PARAM_CONF_SOURCES) \ conf/nwfilter_conf.c conf/nwfilter_conf.h diff --git a/src/conf/nwfilter_ipaddrmap.c b/src/conf/nwfilter_ipaddrmap.c new file mode 100644 index 0000000000..c72958bbc4 --- /dev/null +++ b/src/conf/nwfilter_ipaddrmap.c @@ -0,0 +1,167 @@ +/* + * nwfilter_ipaddrmap.c: IP address map for mapping interfaces to their + * detected/expected IP addresses + * + * Copyright (C) 2010, 2012 IBM Corp. + * + * Author: + * Stefan Berger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "internal.h" + +#include "virterror_internal.h" +#include "datatypes.h" +#include "nwfilter_params.h" +#include "nwfilter_ipaddrmap.h" + +#define VIR_FROM_THIS VIR_FROM_NWFILTER + +static virMutex ipAddressMapLock; +static virNWFilterHashTablePtr ipAddressMap; + + +/* 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 + */ +int +virNWFilterIPAddrMapAddIPAddr(const char *ifname, char *addr) +{ + int ret = -1; + virNWFilterVarValuePtr val; + + virMutexLock(&ipAddressMapLock); + + val = virHashLookup(ipAddressMap->hashTable, ifname); + if (!val) { + val = virNWFilterVarValueCreateSimple(addr); + if (!val) { + virReportOOMError(); + goto cleanup; + } + ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1); + goto cleanup; + } else { + if (virNWFilterVarValueAddValue(val, addr) < 0) + goto cleanup; + } + + ret = 0; + +cleanup: + virMutexUnlock(&ipAddressMapLock); + + return ret; +} + +/* Delete all or a specific IP address from an interface. After this + * call either all or the given IP address will not be associated + * 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 +virNWFilterIPAddrMapDelIPAddr(const char *ifname, const char *ipaddr) +{ + int ret = -1; + virNWFilterVarValuePtr val = NULL; + + virMutexLock(&ipAddressMapLock); + + if (ipaddr != NULL) { + val = virHashLookup(ipAddressMap->hashTable, ifname); + if (val) { + 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); + + return ret; +} + +/* 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 +virNWFilterIPAddrMapGetIPAddr(const char *ifname) +{ + virNWFilterVarValuePtr res; + + virMutexLock(&ipAddressMapLock); + + res = virHashLookup(ipAddressMap->hashTable, ifname); + + virMutexUnlock(&ipAddressMapLock); + + return res; +} + +int +virNWFilterIPAddrMapInit(void) +{ + ipAddressMap = virNWFilterHashTableCreate(0); + if (!ipAddressMap) { + virReportOOMError(); + return -1; + } + + if (virMutexInit(&ipAddressMapLock) < 0) { + virNWFilterIPAddrMapShutdown(); + return -1; + } + + return 0; +} + +void +virNWFilterIPAddrMapShutdown(void) +{ + virNWFilterHashTableFree(ipAddressMap); + ipAddressMap = NULL; +} diff --git a/src/conf/nwfilter_ipaddrmap.h b/src/conf/nwfilter_ipaddrmap.h new file mode 100644 index 0000000000..3411a99a9e --- /dev/null +++ b/src/conf/nwfilter_ipaddrmap.h @@ -0,0 +1,37 @@ +/* + * nwfilter_ipaddrmap.h: IP address map for mapping interfaces to their + * detected/expected IP addresses + * + * Copyright (C) 2010, 2012 IBM Corp. + * + * Author: + * Stefan Berger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __VIR_NWFILTER_IPADDRMAP_H +# define __VIR_NWFILTER_IPADDRMAP_H + +int virNWFilterIPAddrMapInit(void); +void virNWFilterIPAddrMapShutdown(void); + +int virNWFilterIPAddrMapAddIPAddr(const char *ifname, char *addr); +int virNWFilterIPAddrMapDelIPAddr(const char *ifname, + const char *ipaddr); +virNWFilterVarValuePtr virNWFilterIPAddrMapGetIPAddr(const char *ifname); + +#endif /* __VIR_NWFILTER_IPADDRMAP_H */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c6fe0e39f8..fdf21866ff 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -873,6 +873,14 @@ virNWFilterTestUnassignDef; virNWFilterUnlockFilterUpdates; +# nwfilter_ipaddrmap +virNWFilterIPAddrMapAddIPAddr; +virNWFilterIPAddrMapDelIPAddr; +virNWFilterIPAddrMapGetIPAddr; +virNWFilterIPAddrMapInit; +virNWFilterIPAddrMapShutdown; + + # nwfilter_params.h virNWFilterHashTableCreate; virNWFilterHashTableFree; diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index 677d03808b..e24cd26dce 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -39,6 +39,7 @@ #include "nwfilter_gentech_driver.h" #include "configmake.h" +#include "nwfilter_ipaddrmap.h" #include "nwfilter_dhcpsnoop.h" #include "nwfilter_learnipaddr.h" @@ -67,10 +68,12 @@ static int nwfilterDriverStartup(int privileged) { char *base = NULL; - if (virNWFilterDHCPSnoopInit() < 0) + if (virNWFilterIPAddrMapInit() < 0) return -1; if (virNWFilterLearnInit() < 0) - return -1; + goto err_exit_ipaddrmapshutdown; + if (virNWFilterDHCPSnoopInit() < 0) + goto err_exit_learnshutdown; virNWFilterTechDriversInit(privileged); @@ -123,7 +126,10 @@ alloc_err_exit: conf_init_err: virNWFilterTechDriversShutdown(); virNWFilterDHCPSnoopShutdown(); +err_exit_learnshutdown: virNWFilterLearnShutdown(); +err_exit_ipaddrmapshutdown: + virNWFilterIPAddrMapShutdown(); return -1; } @@ -202,6 +208,7 @@ nwfilterDriverShutdown(void) { virNWFilterTechDriversShutdown(); virNWFilterDHCPSnoopShutdown(); virNWFilterLearnShutdown(); + virNWFilterIPAddrMapShutdown(); nwfilterDriverLock(driverState); diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 1738f5cba1..4769d21d4f 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -33,6 +33,7 @@ #include "nwfilter_gentech_driver.h" #include "nwfilter_ebiptables_driver.h" #include "nwfilter_dhcpsnoop.h" +#include "nwfilter_ipaddrmap.h" #include "nwfilter_learnipaddr.h" #include "virnetdev.h" #include "datatypes.h" @@ -870,7 +871,7 @@ __virNWFilterInstantiateFilter(const unsigned char *vmuuid, goto err_exit; } - ipaddr = virNWFilterGetIpAddrForIfname(ifname); + ipaddr = virNWFilterIPAddrMapGetIPAddr(ifname); vars1 = virNWFilterCreateVarHashmap(str_macaddr, ipaddr); if (!vars1) { @@ -1132,7 +1133,7 @@ _virNWFilterTeardownFilter(const char *ifname) techdriver->allTeardown(ifname); - virNWFilterDelIpAddrForIfname(ifname, NULL); + virNWFilterIPAddrMapDelIPAddr(ifname, NULL); virNWFilterUnlockIface(ifname); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 140aea8724..af13738122 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -52,6 +52,7 @@ #include "conf/domain_conf.h" #include "nwfilter_gentech_driver.h" #include "nwfilter_ebiptables_driver.h" +#include "nwfilter_ipaddrmap.h" #include "nwfilter_learnipaddr.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -118,9 +119,6 @@ struct ether_vlan_header static virMutex pendingLearnReqLock; static virHashTablePtr pendingLearnReq; -static virMutex ipAddressMapLock; -static virNWFilterHashTablePtr ipAddressMap; - static virMutex ifaceMapLock; static virHashTablePtr ifaceLockMap; @@ -310,113 +308,8 @@ virNWFilterDeregisterLearnReq(int ifindex) { 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 -virNWFilterAddIpAddrForIfname(const char *ifname, char *addr) -{ - int ret = -1; - virNWFilterVarValuePtr val; - - virMutexLock(&ipAddressMapLock); - - val = virHashLookup(ipAddressMap->hashTable, ifname); - if (!val) { - val = virNWFilterVarValueCreateSimple(addr); - if (!val) { - virReportOOMError(); - goto cleanup; - } - ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1); - goto cleanup; - } else { - if (virNWFilterVarValueAddValue(val, addr) < 0) - goto cleanup; - } - - ret = 0; - -cleanup: - virMutexUnlock(&ipAddressMapLock); - - return ret; -} #endif -/* Delete all or a specific IP address from an interface. After this - * call either all or the given IP address will not be associated - * 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); - - if (ipaddr != NULL) { - val = virHashLookup(ipAddressMap->hashTable, ifname); - if (val) { - 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); - - return ret; -} - -/* 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; - - virMutexLock(&ipAddressMapLock); - - res = virHashLookup(ipAddressMap->hashTable, ifname); - - virMutexUnlock(&ipAddressMapLock); - - return res; -} - - #ifdef HAVE_LIBPCAP static void @@ -699,7 +592,7 @@ learnIPAddressThread(void *arg) char *inetaddr; if ((inetaddr = virSocketAddrFormat(&sa)) != NULL) { - if (virNWFilterAddIpAddrForIfname(req->ifname, inetaddr) < 0) { + if (virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr) < 0) { VIR_ERROR(_("Failed to add IP address %s to IP address " "cache for interface %s"), inetaddr, req->ifname); } @@ -901,18 +794,6 @@ virNWFilterLearnInit(void) { return -1; } - ipAddressMap = virNWFilterHashTableCreate(0); - if (!ipAddressMap) { - virReportOOMError(); - virNWFilterLearnShutdown(); - return -1; - } - - if (virMutexInit(&ipAddressMapLock) < 0) { - virNWFilterLearnShutdown(); - return -1; - } - ifaceLockMap = virHashCreate(0, freeIfaceLock); if (!ifaceLockMap) { virNWFilterLearnShutdown(); @@ -954,9 +835,6 @@ virNWFilterLearnShutdown(void) virHashFree(pendingLearnReq); pendingLearnReq = NULL; - virNWFilterHashTableFree(ipAddressMap); - ipAddressMap = NULL; - virHashFree(ifaceLockMap); ifaceLockMap = NULL; } diff --git a/src/nwfilter/nwfilter_learnipaddr.h b/src/nwfilter/nwfilter_learnipaddr.h index 5db9bf8c4b..ce78923ec0 100644 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ b/src/nwfilter/nwfilter_learnipaddr.h @@ -65,9 +65,6 @@ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex); int virNWFilterTerminateLearnReq(const char *ifname); -int virNWFilterDelIpAddrForIfname(const char *ifname, const char *ipaddr); -virNWFilterVarValuePtr virNWFilterGetIpAddrForIfname(const char *ifname); - int virNWFilterLockIface(const char *ifname) ATTRIBUTE_RETURN_CHECK; void virNWFilterUnlockIface(const char *ifname);