This patch removes remaining pieces of IP address learning. diff --git a/src/Makefile.am b/src/Makefile.am index 3da0797..53cdc00 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -389,9 +389,7 @@ NWFILTER_DRIVER_SOURCES = \ nwfilter/nwfilter_dhcpsnoop.c \ nwfilter/nwfilter_dhcpsnoop.h \ nwfilter/nwfilter_ebiptables_driver.c \ - nwfilter/nwfilter_ebiptables_driver.h \ - nwfilter/nwfilter_learnipaddr.c \ - nwfilter/nwfilter_learnipaddr.h + nwfilter/nwfilter_ebiptables_driver.h # Security framework and drivers for various models diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index 2e20e59..3a73fa4 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -40,7 +40,6 @@ #include "configmake.h" #include "nwfilter_dhcpsnoop.h" -#include "nwfilter_learnipaddr.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -69,8 +68,6 @@ nwfilterDriverStartup(int privileged) { if (virNWFilterDHCPSnoopInit() < 0) return -1; - if (virNWFilterLearnInit() < 0) - return -1; virNWFilterTechDriversInit(privileged); @@ -131,7 +128,6 @@ alloc_err_exit: conf_init_err: virNWFilterTechDriversShutdown(); virNWFilterDHCPSnoopEnd(0); - virNWFilterLearnShutdown(); return -1; } @@ -154,7 +150,7 @@ nwfilterDriverReload(void) { if (conn) { /* shut down all threads -- they will be restarted if necessary */ - virNWFilterLearnThreadsTerminate(true); + virNWFilterDHCPSnoopEnd(0); nwfilterDriverLock(driverState); virNWFilterCallbackDriversLock(); @@ -206,7 +202,6 @@ nwfilterDriverShutdown(void) { virNWFilterConfLayerShutdown(); virNWFilterTechDriversShutdown(); virNWFilterDHCPSnoopEnd(0); - virNWFilterLearnShutdown(); nwfilterDriverLock(driverState); diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index c6e6600..42fd965 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -34,7 +34,6 @@ #include "nwfilter_gentech_driver.h" #include "nwfilter_ebiptables_driver.h" #include "nwfilter_dhcpsnoop.h" -#include "nwfilter_learnipaddr.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -625,14 +624,10 @@ virNWFilterChangeVar(virConnectPtr conn, return 1; } - if (virNWFilterLockIface(ifname)) - goto err_exit; - if (delete) rc = techdriver->removeRules(conn, ifname, nptrs, ptrs); else rc = techdriver->addRules(conn, ifname, nptrs, ptrs); - virNWFilterUnlockIface(ifname); VIR_FREE(ptrs); err_exit: @@ -755,9 +750,6 @@ virNWFilterInstantiate(virConnectPtr conn, if (rc) goto err_exit; - if (virNWFilterLockIface(ifname)) - goto err_exit; - rc = techdriver->applyNewRules(conn, ifname, nptrs, ptrs); if (teardownOld && rc == 0) @@ -768,8 +760,6 @@ virNWFilterInstantiate(virConnectPtr conn, techdriver->allTeardown(ifname); rc = 1; } - - virNWFilterUnlockIface(ifname); } err_exit: @@ -811,7 +801,6 @@ __virNWFilterInstantiateFilter(virConnectPtr conn, virNWFilterDefPtr filter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; char *str_macaddr = NULL; - const char *ipaddr; char *str_ipaddr = NULL; techdriver = virNWFilterTechDriverForName(drvname); @@ -850,16 +839,6 @@ __virNWFilterInstantiateFilter(virConnectPtr conn, goto err_exit; } - ipaddr = virNWFilterGetIpAddrForIfname(ifname); - if (ipaddr) { - str_ipaddr = strdup(ipaddr); - if (!str_ipaddr) { - virReportOOMError(); - rc = 1; - goto err_exit; - } - } - vars1 = virNWFilterCreateVarHashmap(str_macaddr, str_ipaddr); if (!vars1) { rc = 1; @@ -1031,7 +1010,6 @@ int virNWFilterRollbackUpdateFilter(virConnectPtr conn, const virDomainNetDefPtr net) { const char *drvname = EBIPTABLES_DRIVER_ID; - int ifindex; virNWFilterTechDriverPtr techdriver; techdriver = virNWFilterTechDriverForName(drvname); @@ -1043,11 +1021,6 @@ int virNWFilterRollbackUpdateFilter(virConnectPtr conn, return 1; } - /* don't tear anything while the address is being learned */ - if (ifaceGetIndex(true, net->ifname, &ifindex) == 0 && - virNWFilterLookupLearnReq(ifindex) != NULL) - return 0; - return techdriver->tearNewRules(conn, net->ifname); } @@ -1057,7 +1030,6 @@ virNWFilterTearOldFilter(virConnectPtr conn, virDomainNetDefPtr net) { const char *drvname = EBIPTABLES_DRIVER_ID; - int ifindex; virNWFilterTechDriverPtr techdriver; techdriver = virNWFilterTechDriverForName(drvname); @@ -1069,11 +1041,6 @@ virNWFilterTearOldFilter(virConnectPtr conn, return 1; } - /* don't tear anything while the address is being learned */ - if (ifaceGetIndex(true, net->ifname, &ifindex) == 0 && - virNWFilterLookupLearnReq(ifindex) != NULL) - return 0; - return techdriver->tearOldRules(conn, net->ifname); } @@ -1095,17 +1062,8 @@ _virNWFilterTeardownFilter(const char *ifname) virNWFilterDHCPSnoopEnd(ifname); - virNWFilterTerminateLearnReq(ifname); - - if (virNWFilterLockIface(ifname)) - return 1; - techdriver->allTeardown(ifname); - virNWFilterDelIpAddrForIfname(ifname); - - virNWFilterUnlockIface(ifname); - return 0; } diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c deleted file mode 100644 index 96d2a55..0000000 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - * nwfilter_learnipaddr.c: support for learning IP address used by a VM - * on an interface - * - * Copyright (C) 2011 Red Hat, Inc. - * Copyright (C) 2010 IBM Corp. - * Copyright (C) 2010 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 - * - * Author: Stefan Berger <stefanb@xxxxxxxxxx> - */ - -#include <config.h> - -#ifdef HAVE_LIBPCAP -# include <pcap.h> -#endif - -#include <fcntl.h> -#include <sys/ioctl.h> - -#include <arpa/inet.h> -#include <net/ethernet.h> -#include <netinet/ip.h> -#include <netinet/udp.h> -#include <net/if_arp.h> -#include <intprops.h> - -#include "internal.h" - -#include "buf.h" -#include "memory.h" -#include "logging.h" -#include "datatypes.h" -#include "interface.h" -#include "virterror_internal.h" -#include "threads.h" -#include "conf/nwfilter_params.h" -#include "conf/domain_conf.h" -#include "nwfilter_gentech_driver.h" -#include "nwfilter_ebiptables_driver.h" -#include "nwfilter_learnipaddr.h" - -#define VIR_FROM_THIS VIR_FROM_NWFILTER - -#define IFINDEX2STR(VARNAME, ifindex) \ - char VARNAME[INT_BUFSIZE_BOUND(ifindex)]; \ - snprintf(VARNAME, sizeof(VARNAME), "%d", ifindex); - -#define PKT_TIMEOUT_MS 500 /* ms */ - -/* structure of an ARP request/reply message */ -struct f_arphdr { - struct arphdr arphdr; - uint8_t ar_sha[ETH_ALEN]; - uint32_t ar_sip; - uint8_t ar_tha[ETH_ALEN]; - uint32_t ar_tip; -} ATTRIBUTE_PACKED; - - -struct dhcp_option { - uint8_t code; - uint8_t len; - uint8_t value[0]; /* length varies */ -} ATTRIBUTE_PACKED; - - -/* structure representing DHCP message */ -struct dhcp { - uint8_t op; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - uint32_t xid; - uint16_t secs; - uint16_t flags; - uint32_t ciaddr; - uint32_t yiaddr; - uint32_t siaddr; - uint32_t giaddr; - uint8_t chaddr[16]; - uint8_t zeroes[192]; - uint32_t magic; - struct dhcp_option options[0]; -} ATTRIBUTE_PACKED; - -#define DHCP_MSGT_DHCPOFFER 2 -#define DHCP_MSGT_DHCPACK 5 - - -#define DHCP_OPT_BCASTADDRESS 28 -#define DHCP_OPT_MESSAGETYPE 53 - -struct ether_vlan_header -{ - uint8_t dhost[ETH_ALEN]; - uint8_t shost[ETH_ALEN]; - uint16_t vlan_type; - uint16_t vlan_flags; - uint16_t ether_type; -} ATTRIBUTE_PACKED; - - -static virMutex pendingLearnReqLock; -static virHashTablePtr pendingLearnReq; - -static virMutex ipAddressMapLock; -static virNWFilterHashTablePtr ipAddressMap; - -static virMutex ifaceMapLock; -static virHashTablePtr ifaceLockMap; - -typedef struct _virNWFilterIfaceLock virNWFilterIfaceLock; -typedef virNWFilterIfaceLock *virNWFilterIfaceLockPtr; -struct _virNWFilterIfaceLock { - char ifname[IF_NAMESIZE]; - virMutex lock; - int refctr; -}; - - -static bool threadsTerminate = false; - - -int -virNWFilterLockIface(const char *ifname) { - virNWFilterIfaceLockPtr ifaceLock; - - virMutexLock(&ifaceMapLock); - - ifaceLock = virHashLookup(ifaceLockMap, ifname); - if (!ifaceLock) { - if (VIR_ALLOC(ifaceLock) < 0) { - virReportOOMError(); - goto err_exit; - } - - if (virMutexInitRecursive(&ifaceLock->lock)) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("mutex initialization failed")); - VIR_FREE(ifaceLock); - goto err_exit; - } - - if (virStrcpyStatic(ifaceLock->ifname, ifname) == NULL) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - _("interface name %s does not fit into " - "buffer "), - ifaceLock->ifname); - VIR_FREE(ifaceLock); - goto err_exit; - } - - while (virHashAddEntry(ifaceLockMap, ifname, ifaceLock)) { - VIR_FREE(ifaceLock); - goto err_exit; - } - - ifaceLock->refctr = 0; - } - - ifaceLock->refctr++; - - virMutexUnlock(&ifaceMapLock); - - virMutexLock(&ifaceLock->lock); - - return 0; - - err_exit: - virMutexUnlock(&ifaceMapLock); - - return 1; -} - - -static void -freeIfaceLock(void *payload, const void *name ATTRIBUTE_UNUSED) { - VIR_FREE(payload); -} - - -void -virNWFilterUnlockIface(const char *ifname) { - virNWFilterIfaceLockPtr ifaceLock; - - virMutexLock(&ifaceMapLock); - - ifaceLock = virHashLookup(ifaceLockMap, ifname); - - if (ifaceLock) { - virMutexUnlock(&ifaceLock->lock); - - ifaceLock->refctr--; - if (ifaceLock->refctr == 0) - virHashRemoveEntry(ifaceLockMap, ifname); - } - - virMutexUnlock(&ifaceMapLock); -} - - -static void -virNWFilterIPAddrLearnReqFree(virNWFilterIPAddrLearnReqPtr req) { - if (!req) - return; - - VIR_FREE(req->filtername); - virNWFilterHashTableFree(req->filterparams); - - VIR_FREE(req); -} - - -#if HAVE_LIBPCAP - -static int -virNWFilterRegisterLearnReq(virNWFilterIPAddrLearnReqPtr req) { - int res = -1; - IFINDEX2STR(ifindex_str, req->ifindex); - - virMutexLock(&pendingLearnReqLock); - - if (!virHashLookup(pendingLearnReq, ifindex_str)) - res = virHashAddEntry(pendingLearnReq, ifindex_str, req); - - virMutexUnlock(&pendingLearnReqLock); - - return res; -} - - -#endif - -int -virNWFilterTerminateLearnReq(const char *ifname) { - int rc = 1; - int ifindex; - virNWFilterIPAddrLearnReqPtr req; - - if (ifaceGetIndex(false, ifname, &ifindex) == 0) { - - IFINDEX2STR(ifindex_str, ifindex); - - virMutexLock(&pendingLearnReqLock); - - req = virHashLookup(pendingLearnReq, ifindex_str); - if (req) { - rc = 0; - req->terminate = true; - } - - virMutexUnlock(&pendingLearnReqLock); - } - - return rc; -} - - -virNWFilterIPAddrLearnReqPtr -virNWFilterLookupLearnReq(int ifindex) { - void *res; - IFINDEX2STR(ifindex_str, ifindex); - - virMutexLock(&pendingLearnReqLock); - - res = virHashLookup(pendingLearnReq, ifindex_str); - - virMutexUnlock(&pendingLearnReqLock); - - return res; -} - - -static void -freeLearnReqEntry(void *payload, const void *name ATTRIBUTE_UNUSED) { - virNWFilterIPAddrLearnReqFree(payload); -} - - -#ifdef HAVE_LIBPCAP - -static virNWFilterIPAddrLearnReqPtr -virNWFilterDeregisterLearnReq(int ifindex) { - virNWFilterIPAddrLearnReqPtr res; - IFINDEX2STR(ifindex_str, ifindex); - - virMutexLock(&pendingLearnReqLock); - - res = virHashSteal(pendingLearnReq, ifindex_str); - - virMutexUnlock(&pendingLearnReqLock); - - return res; -} - - - -static int -virNWFilterAddIpAddrForIfname(const char *ifname, char *addr) { - int ret; - - virMutexLock(&ipAddressMapLock); - - ret = virNWFilterHashTablePut(ipAddressMap, ifname, addr, 1); - - virMutexUnlock(&ipAddressMapLock); - - return ret; -} -#endif - - -void -virNWFilterDelIpAddrForIfname(const char *ifname) { - - virMutexLock(&ipAddressMapLock); - - if (virHashLookup(ipAddressMap->hashTable, ifname)) - virNWFilterHashTableRemoveEntry(ipAddressMap, ifname); - - virMutexUnlock(&ipAddressMapLock); -} - - -const char * -virNWFilterGetIpAddrForIfname(const char *ifname) { - const char *res; - - virMutexLock(&ipAddressMapLock); - - res = virHashLookup(ipAddressMap->hashTable, ifname); - - virMutexUnlock(&ipAddressMapLock); - - return res; -} - - -#ifdef HAVE_LIBPCAP - -static void -procDHCPOpts(struct dhcp *dhcp, int dhcp_opts_len, - uint32_t *vmaddr, uint32_t *bcastaddr, - enum howDetect *howDetected) { - struct dhcp_option *dhcpopt = &dhcp->options[0]; - - while (dhcp_opts_len >= 2) { - - switch (dhcpopt->code) { - - case DHCP_OPT_BCASTADDRESS: /* Broadcast address */ - if (dhcp_opts_len >= 6) { - uint32_t *tmp = (uint32_t *)&dhcpopt->value; - (*bcastaddr) = ntohl(*tmp); - } - break; - - case DHCP_OPT_MESSAGETYPE: /* Message type */ - if (dhcp_opts_len >= 3) { - uint8_t *val = (uint8_t *)&dhcpopt->value; - switch (*val) { - case DHCP_MSGT_DHCPACK: - case DHCP_MSGT_DHCPOFFER: - *vmaddr = dhcp->yiaddr; - *howDetected = DETECT_DHCP; - break; - } - } - } - dhcp_opts_len -= (2 + dhcpopt->len); - dhcpopt = (struct dhcp_option*)((char *)dhcpopt + 2 + dhcpopt->len); - } -} - - -/** - * learnIPAddressThread - * arg: pointer to virNWFilterIPAddrLearnReq structure - * - * Learn the IP address being used on an interface. Use ARP Request and - * Reply messages, DHCP offers and the first IP packet being sent from - * the VM to detect the IP address it is using. Detects only one IP address - * per interface (IP aliasing not supported). The method on how the - * IP address is detected can be chosen through flags. DETECT_DHCP will - * require that the IP address is detected from a DHCP OFFER, DETECT_STATIC - * will require that the IP address was taken from an ARP packet or an IPv4 - * packet. Both flags can be set at the same time. - */ -static void * -learnIPAddressThread(void *arg) -{ - char errbuf[PCAP_ERRBUF_SIZE] = {0}; - pcap_t *handle = NULL; - struct bpf_program fp; - struct pcap_pkthdr header; - const u_char *packet; - struct ether_header *ether_hdr; - struct ether_vlan_header *vlan_hdr; - virNWFilterIPAddrLearnReqPtr req = arg; - uint32_t vmaddr = 0, bcastaddr = 0; - unsigned int ethHdrSize; - char *listen_if = (strlen(req->linkdev) != 0) ? req->linkdev - : req->ifname; - int dhcp_opts_len; - char macaddr[VIR_MAC_STRING_BUFLEN]; - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *filter = NULL; - uint16_t etherType; - bool showError = true; - enum howDetect howDetected = 0; - virNWFilterTechDriverPtr techdriver = req->techdriver; - - if (virNWFilterLockIface(req->ifname)) - goto err_no_lock; - - req->status = 0; - - /* anything change to the VM's interface -- check at least once */ - if (ifaceCheck(false, req->ifname, NULL, req->ifindex)) { - req->status = ENODEV; - goto done; - } - - handle = pcap_open_live(listen_if, BUFSIZ, 0, PKT_TIMEOUT_MS, errbuf); - - if (handle == NULL) { - VIR_DEBUG("Couldn't open device %s: %s\n", listen_if, errbuf); - req->status = ENODEV; - goto done; - } - - virFormatMacAddr(req->macaddr, macaddr); - - switch (req->howDetect) { - case DETECT_DHCP: - if (techdriver->applyDHCPOnlyRules(req->ifname, - req->macaddr, - NULL)) { - req->status = EINVAL; - goto done; - } - virBufferVSprintf(&buf, " ether dst %s" - " and src port 67 and dst port 68", - macaddr); - break; - default: - if (techdriver->applyBasicRules(req->ifname, - req->macaddr)) { - req->status = EINVAL; - goto done; - } - virBufferVSprintf(&buf, "ether host %s", macaddr); - } - - if (virBufferError(&buf)) { - req->status = ENOMEM; - goto done; - } - - filter = virBufferContentAndReset(&buf); - - if (pcap_compile(handle, &fp, filter, 1, 0) != 0) { - VIR_DEBUG("Couldn't compile filter '%s'.\n", filter); - req->status = EINVAL; - goto done; - } - - if (pcap_setfilter(handle, &fp) != 0) { - VIR_DEBUG("Couldn't set filter '%s'.\n", filter); - req->status = EINVAL; - pcap_freecode(&fp); - goto done; - } - - pcap_freecode(&fp); - - while (req->status == 0 && vmaddr == 0) { - packet = pcap_next(handle, &header); - - if (!packet) { - - if (threadsTerminate || req->terminate) { - req->status = ECANCELED; - showError = false; - break; - } - - /* check whether VM's dev is still there */ - if (ifaceCheck(false, req->ifname, NULL, req->ifindex)) { - req->status = ENODEV; - showError = false; - break; - } - continue; - } - - if (header.len >= sizeof(struct ether_header)) { - ether_hdr = (struct ether_header*)packet; - - switch (ntohs(ether_hdr->ether_type)) { - - case ETHERTYPE_IP: - ethHdrSize = sizeof(struct ether_header); - etherType = ntohs(ether_hdr->ether_type); - break; - - case ETHERTYPE_VLAN: - ethHdrSize = sizeof(struct ether_vlan_header); - vlan_hdr = (struct ether_vlan_header *)packet; - if (ntohs(vlan_hdr->ether_type) != ETHERTYPE_IP || - header.len < ethHdrSize) - continue; - etherType = ntohs(vlan_hdr->ether_type); - break; - - default: - continue; - } - - if (memcmp(ether_hdr->ether_shost, - req->macaddr, - VIR_MAC_BUFLEN) == 0) { - /* packets from the VM */ - - if (etherType == ETHERTYPE_IP && - (header.len >= ethHdrSize + - sizeof(struct iphdr))) { - struct iphdr *iphdr = (struct iphdr*)(packet + - ethHdrSize); - vmaddr = iphdr->saddr; - /* skip mcast addresses (224.0.0.0 - 239.255.255.255), - * class E (240.0.0.0 - 255.255.255.255, includes eth. - * bcast) and zero address in DHCP Requests */ - if ( (ntohl(vmaddr) & 0xe0000000) == 0xe0000000 || - vmaddr == 0) { - vmaddr = 0; - continue; - } - - howDetected = DETECT_STATIC; - } else if (etherType == ETHERTYPE_ARP && - (header.len >= ethHdrSize + - sizeof(struct f_arphdr))) { - struct f_arphdr *arphdr = (struct f_arphdr*)(packet + - ethHdrSize); - switch (ntohs(arphdr->arphdr.ar_op)) { - case ARPOP_REPLY: - vmaddr = arphdr->ar_sip; - howDetected = DETECT_STATIC; - break; - case ARPOP_REQUEST: - vmaddr = arphdr->ar_tip; - howDetected = DETECT_STATIC; - break; - } - } - } else if (memcmp(ether_hdr->ether_dhost, - req->macaddr, - VIR_MAC_BUFLEN) == 0) { - /* packets to the VM */ - if (etherType == ETHERTYPE_IP && - (header.len >= ethHdrSize + - sizeof(struct iphdr))) { - struct iphdr *iphdr = (struct iphdr*)(packet + - ethHdrSize); - if ((iphdr->protocol == IPPROTO_UDP) && - (header.len >= ethHdrSize + - iphdr->ihl * 4 + - sizeof(struct udphdr))) { - struct udphdr *udphdr= (struct udphdr *) - ((char *)iphdr + iphdr->ihl * 4); - if (ntohs(udphdr->source) == 67 && - ntohs(udphdr->dest) == 68 && - header.len >= ethHdrSize + - iphdr->ihl * 4 + - sizeof(struct udphdr) + - sizeof(struct dhcp)) { - struct dhcp *dhcp = (struct dhcp *) - ((char *)udphdr + sizeof(udphdr)); - if (dhcp->op == 2 /* BOOTREPLY */ && - !memcmp(&dhcp->chaddr[0], - req->macaddr, - 6)) { - dhcp_opts_len = header.len - - (ethHdrSize + iphdr->ihl * 4 + - sizeof(struct udphdr) + - sizeof(struct dhcp)); - procDHCPOpts(dhcp, dhcp_opts_len, - &vmaddr, - &bcastaddr, - &howDetected); - } - } - } - } - } - } - if (vmaddr && (req->howDetect & howDetected) == 0) { - vmaddr = 0; - howDetected = 0; - } - } /* while */ - - done: - VIR_FREE(filter); - - if (handle) - pcap_close(handle); - - if (req->status == 0) { - int ret; - virSocketAddr sa; - sa.len = sizeof(sa.data.inet4); - sa.data.inet4.sin_family = AF_INET; - sa.data.inet4.sin_addr.s_addr = vmaddr; - char *inetaddr; - - if ((inetaddr = virSocketFormatAddr(&sa))!= NULL) { - virNWFilterAddIpAddrForIfname(req->ifname, inetaddr); - - ret = virNWFilterInstantiateFilterLate(NULL, - req->ifname, - req->ifindex, - req->linkdev, - req->nettype, - req->macaddr, - req->filtername, - req->filterparams, - req->driver); - VIR_DEBUG("Result from applying firewall rules on " - "%s with IP addr %s : %d\n", req->ifname, inetaddr, ret); - } - } else { - if (showError) - virReportSystemError(req->status, - _("encountered an error on interface %s " - "index %d"), - req->ifname, req->ifindex); - - techdriver->applyDropAllRules(req->ifname); - } - - memset(&req->thread, 0x0, sizeof(req->thread)); - - VIR_DEBUG("pcap thread terminating for interface %s\n",req->ifname); - - virNWFilterUnlockIface(req->ifname); - - err_no_lock: - virNWFilterDeregisterLearnReq(req->ifindex); - - virNWFilterIPAddrLearnReqFree(req); - - return 0; -} - - -/** - * virNWFilterLearnIPAddress - * @techdriver : driver to build firewalls - * @ifname: the name of the interface - * @ifindex: the index of the interface - * @linkdev : the name of the link device; currently only used in case of a - * macvtap device - * @nettype : the type of interface - * @macaddr : the MAC address of the interface - * @filtername : the name of the top-level filter to apply to the interface - * once its IP address has been detected - * @driver : the network filter driver - * @howDetect : the method on how the thread is supposed to detect the - * IP address; must choose any of the available flags - * - * Instruct to learn the IP address being used on a given interface (ifname). - * Unless there already is a thread attempting to learn the IP address - * being used on the interface, a thread is started that will listen on - * the traffic being sent on the interface (or link device) with the - * MAC address that is provided. Will then launch the application of the - * firewall rules on the interface. - */ -int -virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, - const char *ifname, - int ifindex, - const char *linkdev, - enum virDomainNetType nettype, - const unsigned char *macaddr, - const char *filtername, - virNWFilterHashTablePtr filterparams, - virNWFilterDriverStatePtr driver, - enum howDetect howDetect) { - int rc; - virNWFilterIPAddrLearnReqPtr req = NULL; - virNWFilterHashTablePtr ht = NULL; - - if (howDetect == 0) - return 1; - - if ( !techdriver->canApplyBasicRules()) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("IP parameter must be provided since " - "snooping the IP address does not work " - "possibly due to missing tools")); - return 1; - } - - if (VIR_ALLOC(req) < 0) { - virReportOOMError(); - goto err_no_req; - } - - ht = virNWFilterHashTableCreate(0); - if (ht == NULL) { - virReportOOMError(); - goto err_free_req; - } - - if (virNWFilterHashTablePutAll(filterparams, ht)) - goto err_free_ht; - - req->filtername = strdup(filtername); - if (req->filtername == NULL) { - virReportOOMError(); - goto err_free_ht; - } - - if (virStrcpyStatic(req->ifname, ifname) == NULL) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - _("Destination buffer for ifname ('%s') " - "not large enough"), ifname); - goto err_free_ht; - } - - if (linkdev) { - if (virStrcpyStatic(req->linkdev, linkdev) == NULL) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - _("Destination buffer for linkdev ('%s') " - "not large enough"), linkdev); - goto err_free_ht; - } - } - - req->ifindex = ifindex; - req->nettype = nettype; - memcpy(req->macaddr, macaddr, sizeof(req->macaddr)); - req->driver = driver; - req->filterparams = ht; - ht = NULL; - req->howDetect = howDetect; - req->techdriver = techdriver; - - rc = virNWFilterRegisterLearnReq(req); - - if (rc) - goto err_free_req; - - if (pthread_create(&req->thread, - NULL, - learnIPAddressThread, - req) != 0) - goto err_dereg_req; - - return 0; - -err_dereg_req: - virNWFilterDeregisterLearnReq(ifindex); -err_free_ht: - virNWFilterHashTableFree(ht); -err_free_req: - virNWFilterIPAddrLearnReqFree(req); -err_no_req: - return 1; -} - -#else - -int -virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED, - const char *ifname ATTRIBUTE_UNUSED, - int ifindex ATTRIBUTE_UNUSED, - const char *linkdev ATTRIBUTE_UNUSED, - enum virDomainNetType nettype ATTRIBUTE_UNUSED, - const unsigned char *macaddr ATTRIBUTE_UNUSED, - const char *filtername ATTRIBUTE_UNUSED, - virNWFilterHashTablePtr filterparams ATTRIBUTE_UNUSED, - virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED, - enum howDetect howDetect ATTRIBUTE_UNUSED) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("IP parameter must be given since libvirt " - "was not compiled with IP address learning " - "support")); - return 1; -} -#endif /* HAVE_LIBPCAP */ - - -/** - * virNWFilterLearnInit - * Initialization of this layer - */ -int -virNWFilterLearnInit(void) { - - if (pendingLearnReq) - return 0; - - threadsTerminate = false; - - pendingLearnReq = virHashCreate(0, freeLearnReqEntry); - if (!pendingLearnReq) { - return 1; - } - - if (virMutexInit(&pendingLearnReqLock)) { - virNWFilterLearnShutdown(); - return 1; - } - - ipAddressMap = virNWFilterHashTableCreate(0); - if (!ipAddressMap) { - virReportOOMError(); - virNWFilterLearnShutdown(); - return 1; - } - - if (virMutexInit(&ipAddressMapLock)) { - virNWFilterLearnShutdown(); - return 1; - } - - ifaceLockMap = virHashCreate(0, freeIfaceLock); - if (!ifaceLockMap) { - virNWFilterLearnShutdown(); - return 1; - } - - if (virMutexInit(&ifaceMapLock)) { - virNWFilterLearnShutdown(); - return 1; - } - - return 0; -} - - -void -virNWFilterLearnThreadsTerminate(bool allowNewThreads) { - threadsTerminate = true; - - while (virHashSize(pendingLearnReq) != 0) - usleep((PKT_TIMEOUT_MS * 1000) / 3); - - if (allowNewThreads) - threadsTerminate = false; -} - -/** - * virNWFilterLearnShutdown - * Shutdown of this layer - */ -void -virNWFilterLearnShutdown(void) -{ - if (!pendingLearnReq) - return; - - virNWFilterLearnThreadsTerminate(false); - - 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 deleted file mode 100644 index e4b9811..0000000 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * nwfilter_learnipaddr.h: support for learning IP address used by a VM - * on an interface - * - * Copyright (C) 2010 IBM Corp. - * Copyright (C) 2010 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 - * - * Author: Stefan Berger <stefanb@xxxxxxxxxx> - */ - -#ifndef __NWFILTER_LEARNIPADDR_H -# define __NWFILTER_LEARNIPADDR_H - -enum howDetect { - DETECT_DHCP = 1, - DETECT_STATIC = 2, -}; - -typedef struct _virNWFilterIPAddrLearnReq virNWFilterIPAddrLearnReq; -typedef virNWFilterIPAddrLearnReq *virNWFilterIPAddrLearnReqPtr; -struct _virNWFilterIPAddrLearnReq { - virNWFilterTechDriverPtr techdriver; - char ifname[IF_NAMESIZE]; - int ifindex; - char linkdev[IF_NAMESIZE]; - enum virDomainNetType nettype; - unsigned char macaddr[VIR_MAC_BUFLEN]; - char *filtername; - virNWFilterHashTablePtr filterparams; - virNWFilterDriverStatePtr driver; - enum howDetect howDetect; - - int status; - pthread_t thread; - volatile bool terminate; -}; - -int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, - const char *ifname, - int ifindex, - const char *linkdev, - enum virDomainNetType nettype, - const unsigned char *macaddr, - const char *filtername, - virNWFilterHashTablePtr filterparams, - virNWFilterDriverStatePtr driver, - enum howDetect howDetect); - -virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex); -int virNWFilterTerminateLearnReq(const char *ifname); - -void virNWFilterDelIpAddrForIfname(const char *ifname); -const char *virNWFilterGetIpAddrForIfname(const char *ifname); - -int virNWFilterLockIface(const char *ifname) ATTRIBUTE_RETURN_CHECK; -void virNWFilterUnlockIface(const char *ifname); - -int virNWFilterLearnInit(void); -void virNWFilterLearnShutdown(void); -void virNWFilterLearnThreadsTerminate(bool allowNewThreads); - -#endif /* __NWFILTER_LEARNIPADDR_H */ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list