From 797b47580a5c5de1cc32e061e9be38ff6c834928 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 1 Jun 2012 19:32:06 -0400 Subject: [PATCH] nwfilter: move code for IP address map into separate file The goal of this patch is to prepare for support for multiple IP addresses per interface in the DHCP snooping code. Move the code for the IP address map that maps interface names to IP addresses into their own file. Rename the functions on the way but otherwise leave the code as-is. Initialize this new layer separately before dependent layers (iplearning, dhcpsnooping) and shut it down after them. --- src/Makefile.am | 4 +- src/conf/nwfilter_ipaddrmap.c | 167 +++++++++++++++++++++++++ src/conf/nwfilter_ipaddrmap.h | 37 ++++++ src/libvirt_private.syms | 8 ++ src/nwfilter/nwfilter_driver.c | 11 +- src/nwfilter/nwfilter_gentech_driver.c | 5 +- src/nwfilter/nwfilter_learnipaddr.c | 126 +------------------ src/nwfilter/nwfilter_learnipaddr.h | 3 - 8 files changed, 229 insertions(+), 132 deletions(-) create mode 100644 src/conf/nwfilter_ipaddrmap.c create mode 100644 src/conf/nwfilter_ipaddrmap.h 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);