I am consolidating network interface related functions used in nwfilter and macvtap code in utils/interface.c. All function names are prefixed with 'Iface'. The following functions are now available through interface.h: int IfaceCtrl(const char *name, bool up); int IfaceUp(const char *name); int IfaceDown(const char *name); int IfaceCheck(bool reportError, const char *ifname, const unsigned char *macaddr, int ifindex); int IfaceGetIndex(bool reportError, const char *ifname, int *ifindex); I added 'int ifindex' as parameter to IfaceCheck to the original function and modified the code accordingly. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> --- src/Makefile.am | 1 src/libvirt_private.syms | 4 src/nwfilter/nwfilter_gentech_driver.c | 120 ----------------- src/nwfilter/nwfilter_gentech_driver.h | 2 src/nwfilter/nwfilter_learnipaddr.c | 3 src/util/interface.c | 224 +++++++++++++++++++++++++++++++++ src/util/interface.h | 31 ++++ src/util/macvtap.c | 112 ---------------- 8 files changed, 269 insertions(+), 228 deletions(-) Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c @@ -23,16 +23,11 @@ #include <config.h> -#include <stdint.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <linux/if.h> - #include "internal.h" #include "memory.h" #include "logging.h" -#include "datatypes.h" +#include "interface.h" #include "domain_conf.h" #include "virterror_internal.h" #include "nwfilter_gentech_driver.h" @@ -792,117 +787,6 @@ _virNWFilterInstantiateFilter(virConnect } -// FIXME: move chgIfFlags, ifUp, checkIf into common file & share w/ macvtap.c - -/* - * chgIfFlags: Change flags on an interface - * @ifname : name of the interface - * @flagclear : the flags to clear - * @flagset : the flags to set - * - * The new flags of the interface will be calculated as - * flagmask = (~0 ^ flagclear) - * newflags = (curflags & flagmask) | flagset; - * - * Returns 0 on success, errno on failure. - */ -static int chgIfFlags(const char *ifname, short flagclear, short flagset) { - struct ifreq ifr; - int rc = 0; - int flags; - short flagmask = (~0 ^ flagclear); - int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - - if (fd < 0) - return errno; - - if (virStrncpy(ifr.ifr_name, - ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { - rc = ENODEV; - goto err_exit; - } - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { - rc = errno; - goto err_exit; - } - - flags = (ifr.ifr_flags & flagmask) | flagset; - - if (ifr.ifr_flags != flags) { - ifr.ifr_flags = flags; - - if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) - rc = errno; - } - -err_exit: - close(fd); - return rc; -} - -/* - * ifUp - * @name: name of the interface - * @up: 1 for up, 0 for down - * - * Function to control if an interface is activated (up, 1) or not (down, 0) - * - * Returns 0 in case of success or an errno code in case of failure. - */ -static int -ifUp(const char *name, int up) -{ - return chgIfFlags(name, - (up) ? 0 : IFF_UP, - (up) ? IFF_UP : 0); -} - - -/** - * checkIf - * - * @ifname: Name of the interface - * @macaddr: expected MAC address of the interface - * - * FIXME: the interface's index is another good parameter to check - * - * Determine whether a given interface is still available. If so, - * it must have the given MAC address. - * - * Returns an error code ENODEV in case the interface does not exist - * anymore or its MAC address is different, 0 otherwise. - */ -int -checkIf(const char *ifname, const unsigned char *macaddr) -{ - struct ifreq ifr; - int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - int rc = 0; - - if (fd < 0) - return errno; - - if (virStrncpy(ifr.ifr_name, - ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { - rc = ENODEV; - goto err_exit; - } - - if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { - rc = errno; - goto err_exit; - } - - if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, 6) != 0) - rc = ENODEV; - - err_exit: - close(fd); - return rc; -} - - int virNWFilterInstantiateFilterLate(virConnectPtr conn, const char *ifname, @@ -926,7 +810,7 @@ virNWFilterInstantiateFilterLate(virConn driver); if (rc) { //something went wrong... 'DOWN' the interface - if (ifUp(ifname ,0)) { + if (IfaceDown(ifname)) { // assuming interface disappeared... _virNWFilterTeardownFilter(ifname); } Index: libvirt-acl/src/util/interface.c =================================================================== --- /dev/null +++ libvirt-acl/src/util/interface.c @@ -0,0 +1,226 @@ +/* + * interface.c: interface support functions + * + * 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 + * + * chgIfaceFlags originated from bridge.c + * + * Author: Stefan Berger <stefanb@xxxxxxxxxx> + */ + +#include <config.h> + +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <linux/if.h> + +#include "internal.h" + +#include "util.h" +#include "interface.h" +#include "virterror_internal.h" + +#define ifaceError(code, ...) \ + virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +/* + * chgIfFlags: Change flags on an interface + * + * @ifname : name of the interface + * @flagclear : the flags to clear + * @flagset : the flags to set + * + * The new flags of the interface will be calculated as + * flagmask = (~0 ^ flagclear) + * newflags = (curflags & flagmask) | flagset; + * + * Returns 0 on success, errno on failure. + */ +static int chgIfaceFlags(const char *ifname, short flagclear, short flagset) { + struct ifreq ifr; + int rc = 0; + int flags; + short flagmask = (~0 ^ flagclear); + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + if (virStrncpy(ifr.ifr_name, + ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { + rc = ENODEV; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { + rc = errno; + goto err_exit; + } + + flags = (ifr.ifr_flags & flagmask) | flagset; + + if (ifr.ifr_flags != flags) { + ifr.ifr_flags = flags; + + if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) + rc = errno; + } + +err_exit: + close(fd); + return rc; +} + + +/* + * IfaceCtrl + * @name: name of the interface + * @up: true (1) for up, false (0) for down + * + * Function to control if an interface is activated (up, 1) or not (down, 0) + * + * Returns 0 in case of success or an errno code in case of failure. + */ +int +IfaceCtrl(const char *name, bool up) +{ + return chgIfaceFlags(name, + (up) ? 0 : IFF_UP, + (up) ? IFF_UP : 0); +} + + +/** + * IfaceCheck + * + * @reportError: whether to report errors or keep silent + * @ifname: Name of the interface + * @macaddr: expected MAC address of the interface; not checked if NULL + * @ifindex: expected index of the interface; not checked if '-1' + * + * Determine whether a given interface is still available. If so, + * it must have the given MAC address and if an interface index is + * passed, it must also match the interface index. + * + * Returns 0 on success, an error code on failure. + * ENODEV : if interface with given name does not exist or its interface + * index is different than the one passed + * EINVAL : if interface name is invalid (too long) + */ +int +IfaceCheck(bool reportError, const char *ifname, + const unsigned char *macaddr, int ifindex) +{ + struct ifreq ifr; + int fd = -1; + int rc = 0; + int idx; + + if (macaddr != NULL) { + fd = socket(PF_PACKET, SOCK_DGRAM, 0); + if (fd < 0) + return errno; + + if (virStrncpy(ifr.ifr_name, + ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { + if (reportError) + ifaceError(VIR_ERR_INTERNAL_ERROR, + _("invalid interface name %s"), + ifname); + rc = EINVAL; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { + if (reportError) + ifaceError(VIR_ERR_INTERNAL_ERROR, + _("coud not get MAC address of interface %s"), + ifname); + rc = errno; + goto err_exit; + } + + if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN) != 0) { + rc = ENODEV; + goto err_exit; + } + } + + if (ifindex != -1) { + rc = IfaceGetIndex(reportError, ifname, &idx); + if (rc == 0 && idx != ifindex) + rc = ENODEV; + } + + err_exit: + if (fd >= 0) + close(fd); + + return rc; +} + + +/** + * IfaceGetIndex + * + * @reportError: whether to report errors or keep silent + * @ifname : Name of the interface whose index is to be found + * @ifindex: Pointer to int where the index will be written into + * + * Get the index of an interface given its name. + * + * Returns 0 on success, an error code on failure. + * ENODEV : if interface with given name does not exist + * EINVAL : if interface name is invalid (too long) + */ +int +IfaceGetIndex(bool reportError, const char *ifname, int *ifindex) +{ + int rc = 0; + struct ifreq ifreq; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname), + sizeof(ifreq.ifr_name)) == NULL) { + if (reportError) + ifaceError(VIR_ERR_INTERNAL_ERROR, + _("invalid interface name %s"), + ifname); + rc = EINVAL; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFINDEX, &ifreq) >= 0) + *ifindex = ifreq.ifr_ifindex; + else { + if (reportError) + ifaceError(VIR_ERR_INTERNAL_ERROR, + _("interface %s does not exist"), + ifname); + rc = ENODEV; + } + +err_exit: + close(fd); + + return rc; +} Index: libvirt-acl/src/util/interface.h =================================================================== --- /dev/null +++ libvirt-acl/src/util/interface.h @@ -0,0 +1,31 @@ +/* + * interface.h: interface helper APIs for libvirt + * + * Copyright (C) 2010 IBM Corporation, Inc. + * + * See COPYING.LIB for the License of this software + * + * Stefan Berger <stefanb@xxxxxxxxxx> + */ +#ifndef __VIR_INTERFACE_H__ +# define __VIR_INTERFACE_H__ + +#include "datatypes.h" + +int IfaceCtrl(const char *name, bool up); + +static inline int IfaceUp(const char *name) { + return IfaceCtrl(name, true); +} + +static inline int IfaceDown(const char *name) { + return IfaceCtrl(name, false); +} + +int IfaceCheck(bool reportError, const char *ifname, + const unsigned char *macaddr, int ifindex); + +int IfaceGetIndex(bool reportError, const char *ifname, int *ifindex); + +#endif /* __VIR_INTERFACE_H__ */ + Index: libvirt-acl/src/Makefile.am =================================================================== --- libvirt-acl.orig/src/Makefile.am +++ libvirt-acl/src/Makefile.am @@ -67,6 +67,7 @@ UTIL_SOURCES = \ util/processinfo.c util/processinfo.h \ util/hostusb.c util/hostusb.h \ util/network.c util/network.h \ + util/interface.c util/interface.h \ util/qparams.c util/qparams.h \ util/stats_linux.c util/stats_linux.h \ util/storage_file.c util/storage_file.h \ Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -681,6 +681,10 @@ virFileWaitForDevices; virFileMatchesNameSuffix; virArgvToString; +# interface.h +IfaceCtrl; +IfaceCheck; +IfaceGetIndex; # usb.h usbGetDevice; Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c +++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c @@ -43,6 +43,7 @@ #include "memory.h" #include "logging.h" #include "datatypes.h" +#include "interface.h" #include "virterror_internal.h" #include "threads.h" #include "conf/nwfilter_params.h" @@ -339,7 +340,7 @@ learnIPAddressThread(void *arg) break; } /* listening on linkdev, check whether VM's dev is still there */ - if (checkIf(req->ifname, req->macaddr)) { + if (IfaceCheck(false, req->ifname, req->macaddr, -1)) { req->status = ENODEV; break; } Index: libvirt-acl/src/util/macvtap.c =================================================================== --- libvirt-acl.orig/src/util/macvtap.c +++ libvirt-acl/src/util/macvtap.c @@ -44,6 +44,7 @@ # include "util.h" # include "memory.h" # include "macvtap.h" +# include "interface.h" # include "conf/domain_conf.h" # include "virterror_internal.h" @@ -193,109 +194,6 @@ nlAppend(struct nlmsghdr *nlm, int totle static int -getIfIndex(bool reportError, - const char *ifname, - int *idx) -{ - int rc = 0; - struct ifreq ifreq; - int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - - if (fd < 0) - return errno; - - if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname), - sizeof(ifreq.ifr_name)) == NULL) { - if (reportError) - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("invalid interface name %s"), - ifname); - rc = EINVAL; - goto err_exit; - } - if (ioctl(fd, SIOCGIFINDEX, &ifreq) >= 0) - *idx = ifreq.ifr_ifindex; - else { - if (reportError) - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("interface %s does not exist"), - ifname); - rc = ENODEV; - } - -err_exit: - close(fd); - - return rc; -} - - -/* - * chgIfFlags: Change flags on an interface - * @ifname : name of the interface - * @flagclear : the flags to clear - * @flagset : the flags to set - * - * The new flags of the interface will be calculated as - * flagmask = (~0 ^ flagclear) - * newflags = (curflags & flagmask) | flagset; - * - * Returns 0 on success, errno on failure. - */ -static int chgIfFlags(const char *ifname, short flagclear, short flagset) { - struct ifreq ifr; - int rc = 0; - int flags; - short flagmask = (~0 ^ flagclear); - int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - - if (fd < 0) - return errno; - - if (virStrncpy(ifr.ifr_name, - ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { - rc = ENODEV; - goto err_exit; - } - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { - rc = errno; - goto err_exit; - } - - flags = (ifr.ifr_flags & flagmask) | flagset; - - if (ifr.ifr_flags != flags) { - ifr.ifr_flags = flags; - - if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) - rc = errno; - } - -err_exit: - close(fd); - return rc; -} - -/* - * ifUp - * @name: name of the interface - * @up: 1 for up, 0 for down - * - * Function to control if an interface is activated (up, 1) or not (down, 0) - * - * Returns 0 in case of success or an errno code in case of failure. - */ -static int -ifUp(const char *name, int up) -{ - return chgIfFlags(name, - (up) ? 0 : IFF_UP, - (up) ? IFF_UP : 0); -} - - -static int link_add(const char *type, const unsigned char *macaddress, int macaddrsize, const char *ifname, @@ -314,7 +212,7 @@ link_add(const char *type, char *recvbuf = NULL; int recvbuflen; - if (getIfIndex(true, srcdev, &ifindex) != 0) + if (IfaceGetIndex(true, srcdev, &ifindex) != 0) return -1; *retry = 0; @@ -708,7 +606,7 @@ openMacvtapTap(const char *tgifname, *res_ifname = NULL; if (tgifname) { - if(getIfIndex(false, tgifname, &ifindex) == 0) { + if(IfaceGetIndex(false, tgifname, &ifindex) == 0) { if (STRPREFIX(tgifname, MACVTAP_NAME_PREFIX)) { goto create_name; @@ -727,7 +625,7 @@ create_name: retries = 5; for (c = 0; c < 8192; c++) { snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c); - if (getIfIndex(false, ifname, &ifindex) == ENODEV) { + if (IfaceGetIndex(false, ifname, &ifindex) == ENODEV) { rc = link_add(type, macaddress, 6, ifname, linkdev, macvtapMode, &do_retry); if (rc == 0) @@ -741,7 +639,7 @@ create_name: cr_ifname = ifname; } - rc = ifUp(cr_ifname, 1); + rc = IfaceUp(cr_ifname); if (rc != 0) { virReportSystemError(errno, _("cannot 'up' interface %s -- another " Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.h +++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h @@ -63,6 +63,4 @@ void virNWFilterDomainFWUpdateCB(void *p const char *name ATTRIBUTE_UNUSED, void *data); -int checkIf(const char *ifname, const unsigned char *macaddr); - #endif -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list