From d3406045fdfcc3395dc51f16e15c98c2f910dca9 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 2 Nov 2011 15:40:08 +0000 Subject: [PATCH] Split src/util/network.{c,h} into 5 pieces The src/util/network.c file is a dumping ground for many different APIs. Split it up into 5 pieces, along functional lines - src/util/virnetdevbandwidth.c: virNetDevBandwidth type & helper APIs - src/util/virnetdevvportprofile.c: virNetDevVPortProfile type & helper APIs - src/util/virsocketaddr.c: virSocketAddr and APIs - src/conf/netdev_bandwidth_conf.c: XML parsing / formatting for virNetDevBandwidth - src/conf/netdev_vport_profile_conf.c: XML parsing / formatting for virNetDevVPortProfile * src/util/network.c, src/util/network.h: Split into 5 pieces * src/conf/netdev_bandwidth_conf.c, src/conf/netdev_bandwidth_conf.h, src/conf/netdev_vport_profile_conf.c, src/conf/netdev_vport_profile_conf.h, src/util/virnetdevbandwidth.c, src/util/virnetdevbandwidth.h, src/util/virnetdevvportprofile.c, src/util/virnetdevvportprofile.h, src/util/virsocketaddr.c, src/util/virsocketaddr.h: New pieces * daemon/libvirtd.h, daemon/remote.c, src/conf/domain_conf.c, src/conf/domain_conf.h, src/conf/network_conf.c, src/conf/network_conf.h, src/conf/nwfilter_conf.h, src/esx/esx_util.h, src/network/bridge_driver.c, src/qemu/qemu_conf.c, src/rpc/virnetsocket.c, src/rpc/virnetsocket.h, src/util/dnsmasq.h, src/util/interface.h, src/util/iptables.h, src/util/macvtap.c, src/util/macvtap.h, src/util/virnetdev.h, src/util/virnetdevtap.c, tools/virsh.c: Update include files --- daemon/libvirtd.h | 1 - daemon/remote.c | 1 - po/POTFILES.in | 4 +- src/Makefile.am | 12 +- src/conf/domain_conf.c | 3 +- src/conf/domain_conf.h | 4 +- src/conf/netdev_bandwidth_conf.c | 230 +++++ src/conf/netdev_bandwidth_conf.h | 37 + src/conf/netdev_vport_profile_conf.c | 236 +++++ src/conf/netdev_vport_profile_conf.h | 39 + src/conf/network_conf.c | 3 +- src/conf/network_conf.h | 4 +- src/conf/nwfilter_conf.h | 2 +- src/esx/esx_util.h | 2 +- src/network/bridge_driver.c | 1 - src/qemu/qemu_conf.c | 1 - src/rpc/virnetsocket.c | 1 + src/rpc/virnetsocket.h | 2 +- src/util/dnsmasq.h | 2 +- src/util/interface.h | 2 +- src/util/iptables.h | 2 +- src/util/macvtap.c | 1 - src/util/macvtap.h | 8 +- src/util/network.c | 1349 -------------------------- src/util/network.h | 173 ---- src/util/virnetdev.h | 2 +- src/util/virnetdevbandwidth.c | 265 +++++ src/util/virnetdevbandwidth.h | 53 + src/util/virnetdevtap.c | 1 + src/util/virnetdevvportprofile.c | 62 ++ src/util/virnetdevvportprofile.h | 64 ++ src/util/virsocketaddr.c | 688 +++++++++++++ src/util/virsocketaddr.h | 104 ++ tests/sockettest.c | 2 +- tests/virnettlscontexttest.c | 2 +- tools/virsh.c | 2 +- 36 files changed, 1817 insertions(+), 1548 deletions(-) create mode 100644 src/conf/netdev_bandwidth_conf.c create mode 100644 src/conf/netdev_bandwidth_conf.h create mode 100644 src/conf/netdev_vport_profile_conf.c create mode 100644 src/conf/netdev_vport_profile_conf.h delete mode 100644 src/util/network.c delete mode 100644 src/util/network.h create mode 100644 src/util/virnetdevbandwidth.c create mode 100644 src/util/virnetdevbandwidth.h create mode 100644 src/util/virnetdevvportprofile.c create mode 100644 src/util/virnetdevvportprofile.h create mode 100644 src/util/virsocketaddr.c create mode 100644 src/util/virsocketaddr.h diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index ecb7374ffc..ce787a47ff 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -33,7 +33,6 @@ # include "qemu_protocol.h" # include "logging.h" # include "threads.h" -# include "network.h" # if HAVE_SASL # include "virnetsaslcontext.h" # endif diff --git a/daemon/remote.c b/daemon/remote.c index aa3f7683d1..857835e325 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -38,7 +38,6 @@ #include "util.h" #include "stream.h" #include "uuid.h" -#include "network.h" #include "libvirt/libvirt-qemu.h" #include "command.h" #include "intprops.h" diff --git a/po/POTFILES.in b/po/POTFILES.in index a3685e813b..1665d2d393 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -8,6 +8,8 @@ src/conf/cpu_conf.c src/conf/domain_conf.c src/conf/domain_event.c src/conf/interface_conf.c +src/conf/netdev_bandwidth_conf.c +src/conf/netdev_vport_profile_conf.c src/conf/network_conf.c src/conf/node_device_conf.c src/conf/nwfilter_conf.c @@ -116,7 +118,6 @@ src/util/iptables.c src/util/json.c src/util/macvtap.c src/util/netlink.c -src/util/network.c src/util/pci.c src/util/processinfo.c src/util/sexpr.c @@ -130,6 +131,7 @@ src/util/virnetdev.c src/util/virnetdevbridge.c src/util/virnetdevtap.c src/util/virpidfile.c +src/util/virsocketaddr.c src/util/virterror.c src/util/xml.c src/vbox/vbox_MSCOMGlue.c diff --git a/src/Makefile.am b/src/Makefile.am index e931d41592..e0979ebfcc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -73,7 +73,6 @@ UTIL_SOURCES = \ util/pci.c util/pci.h \ 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/sexpr.c util/sexpr.h \ @@ -94,8 +93,11 @@ UTIL_SOURCES = \ util/virkeycode.c util/virkeycode.h \ util/virkeymaps.h \ util/virnetdev.h util/virnetdev.c \ + util/virnetdevbandwidth.h util/virnetdevbandwidth.c \ util/virnetdevbridge.h util/virnetdevbridge.c \ - util/virnetdevtap.h util/virnetdevtap.c + util/virnetdevtap.h util/virnetdevtap.c \ + util/virnetdevvportprofile.h util/virnetdevvportprofile.c \ + util/virsocketaddr.h util/virsocketaddr.c EXTRA_DIST += $(srcdir)/util/virkeymaps.h $(srcdir)/util/keymaps.csv \ $(srcdir)/util/virkeycode-mapgen.py @@ -126,6 +128,10 @@ LOCK_DRIVER_SANLOCK_SOURCES = \ locking/lock_driver_sanlock.c +NETDEV_CONF_SOURCES = \ + conf/netdev_bandwidth_conf.h conf/netdev_bandwidth_conf.c \ + conf/netdev_vport_profile_conf.h conf/netdev_vport_profile_conf.c + # XML configuration format handling sources # Domain driver generic impl APIs DOMAIN_CONF_SOURCES = \ @@ -173,6 +179,7 @@ CPU_CONF_SOURCES = \ conf/cpu_conf.c conf/cpu_conf.h CONF_SOURCES = \ + $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ $(DOMAIN_EVENT_SOURCES) \ $(NETWORK_CONF_SOURCES) \ @@ -1479,6 +1486,7 @@ libvirt_lxc_SOURCES = \ $(UTIL_SOURCES) \ $(NODE_INFO_SOURCES) \ $(ENCRYPTION_CONF_SOURCES) \ + $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ $(SECRET_CONF_SOURCES) \ $(CPU_CONF_SOURCES) \ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 365fb130fc..6b78d97e44 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -42,7 +42,6 @@ #include "buf.h" #include "c-ctype.h" #include "logging.h" -#include "network.h" #include "nwfilter_conf.h" #include "ignore-value.h" #include "storage_file.h" @@ -50,6 +49,8 @@ #include "bitmap.h" #include "count-one-bits.h" #include "secret_conf.h" +#include "netdev_vport_profile_conf.h" +#include "netdev_bandwidth_conf.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 255d8fd8bb..c360674a19 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -35,11 +35,13 @@ # include "util.h" # include "threads.h" # include "hash.h" -# include "network.h" +# include "virsocketaddr.h" # include "nwfilter_params.h" # include "nwfilter_conf.h" # include "macvtap.h" # include "sysinfo.h" +# include "virnetdevvportprofile.h" +# include "virnetdevbandwidth.h" /* Different types of hypervisor */ /* NB: Keep in sync with virDomainVirtTypeToString impl */ diff --git a/src/conf/netdev_bandwidth_conf.c b/src/conf/netdev_bandwidth_conf.c new file mode 100644 index 0000000000..24cd13d649 --- /dev/null +++ b/src/conf/netdev_bandwidth_conf.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Michal Privoznik + * Daniel P. Berrange + */ + +#include + +#include "netdev_bandwidth_conf.h" +#include "virterror_internal.h" +#include "util.h" +#include "memory.h" + +#define VIR_FROM_THIS VIR_FROM_NONE +#define virNetDevError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + + +static int +virNetDevBandwidthParseRate(xmlNodePtr node, virNetDevBandwidthRatePtr rate) +{ + int ret = -1; + char *average = NULL; + char *peak = NULL; + char *burst = NULL; + + if (!node || !rate) { + virNetDevError(VIR_ERR_INVALID_ARG, "%s", + _("invalid argument supplied")); + return -1; + } + + average = virXMLPropString(node, "average"); + peak = virXMLPropString(node, "peak"); + burst = virXMLPropString(node, "burst"); + + if (average) { + if (virStrToLong_ull(average, NULL, 10, &rate->average) < 0) { + virNetDevError(VIR_ERR_CONFIG_UNSUPPORTED, + _("could not convert %s"), + average); + goto cleanup; + } + } else { + virNetDevError(VIR_ERR_XML_DETAIL, "%s", + _("Missing mandatory average attribute")); + goto cleanup; + } + + if (peak && virStrToLong_ull(peak, NULL, 10, &rate->peak) < 0) { + virNetDevError(VIR_ERR_CONFIG_UNSUPPORTED, + _("could not convert %s"), + peak); + goto cleanup; + } + + if (burst && virStrToLong_ull(burst, NULL, 10, &rate->burst) < 0) { + virNetDevError(VIR_ERR_CONFIG_UNSUPPORTED, + _("could not convert %s"), + burst); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(average); + VIR_FREE(peak); + VIR_FREE(burst); + + return ret; +} + +/** + * virNetDevBandwidthParse: + * @node: XML node + * + * Parse bandwidth XML and return pointer to structure + * + * Returns !NULL on success, NULL on error. + */ +virNetDevBandwidthPtr +virNetDevBandwidthParse(xmlNodePtr node) +{ + virNetDevBandwidthPtr def = NULL; + xmlNodePtr cur = node->children; + xmlNodePtr in = NULL, out = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(); + return NULL; + } + + if (!node || !xmlStrEqual(node->name, BAD_CAST "bandwidth")) { + virNetDevError(VIR_ERR_INVALID_ARG, "%s", + _("invalid argument supplied")); + goto error; + } + + while (cur) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "inbound")) { + if (in) { + virNetDevError(VIR_ERR_XML_DETAIL, "%s", + _("Only one child " + "element allowed")); + goto error; + } + in = cur; + } else if (xmlStrEqual(cur->name, BAD_CAST "outbound")) { + if (out) { + virNetDevError(VIR_ERR_XML_DETAIL, "%s", + _("Only one child " + "element allowed")); + goto error; + } + out = cur; + } + /* Silently ignore unknown elements */ + } + cur = cur->next; + } + + if (in) { + if (VIR_ALLOC(def->in) < 0) { + virReportOOMError(); + goto error; + } + + if (virNetDevBandwidthParseRate(in, def->in) < 0) { + /* helper reported error for us */ + goto error; + } + } + + if (out) { + if (VIR_ALLOC(def->out) < 0) { + virReportOOMError(); + goto error; + } + + if (virNetDevBandwidthParseRate(out, def->out) < 0) { + /* helper reported error for us */ + goto error; + } + } + + return def; + +error: + virNetDevBandwidthFree(def); + return NULL; +} + +static int +virNetDevBandwidthRateFormat(virNetDevBandwidthRatePtr def, + virBufferPtr buf, + const char *elem_name) +{ + if (!buf || !elem_name) + return -1; + if (!def) + return 0; + + if (def->average) { + virBufferAsprintf(buf, " <%s average='%llu'", elem_name, + def->average); + + if (def->peak) + virBufferAsprintf(buf, " peak='%llu'", def->peak); + + if (def->burst) + virBufferAsprintf(buf, " burst='%llu'", def->burst); + virBufferAddLit(buf, "/>\n"); + } + + return 0; +} + +/** + * virNetDevBandwidthDefFormat: + * @def: Data source + * @buf: Buffer to print to + * + * Formats bandwidth and prepend each line with @indent. + * @buf may use auto-indentation. + * + * Returns 0 on success, else -1. + */ +int +virNetDevBandwidthFormat(virNetDevBandwidthPtr def, virBufferPtr buf) +{ + int ret = -1; + + if (!buf) + goto cleanup; + + if (!def) { + ret = 0; + goto cleanup; + } + + virBufferAddLit(buf, "\n"); + if (virNetDevBandwidthRateFormat(def->in, buf, "inbound") < 0 || + virNetDevBandwidthRateFormat(def->out, buf, "outbound") < 0) + goto cleanup; + virBufferAddLit(buf, "\n"); + + ret = 0; + +cleanup: + return ret; +} diff --git a/src/conf/netdev_bandwidth_conf.h b/src/conf/netdev_bandwidth_conf.h new file mode 100644 index 0000000000..4bb7def9a4 --- /dev/null +++ b/src/conf/netdev_bandwidth_conf.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Michal Privoznik + * Daniel P. Berrange + */ + +#ifndef __VIR_NETDEV_BANDWIDTH_CONF_H__ +# define __VIR_NETDEV_BANDWIDTH_CONF_H__ + +# include "internal.h" +# include "virnetdevbandwidth.h" +# include "buf.h" +# include "xml.h" + +virNetDevBandwidthPtr virNetDevBandwidthParse(xmlNodePtr node) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virNetDevBandwidthFormat(virNetDevBandwidthPtr def, + virBufferPtr buf) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +#endif /* __VIR_NETDEV_BANDWIDTH_CONF_H__ */ diff --git a/src/conf/netdev_vport_profile_conf.c b/src/conf/netdev_vport_profile_conf.c new file mode 100644 index 0000000000..861ad34b66 --- /dev/null +++ b/src/conf/netdev_vport_profile_conf.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Stefan Berger + * Daniel P. Berrange + */ + +#include + +#include "netdev_vport_profile_conf.h" +#include "virterror_internal.h" +#include "memory.h" + +#define VIR_FROM_THIS VIR_FROM_NONE +#define virNetDevError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + + +VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST, + "none", + "802.1Qbg", + "802.1Qbh") + + +virNetDevVPortProfilePtr +virNetDevVPortProfileParse(xmlNodePtr node) +{ + char *virtPortType; + char *virtPortManagerID = NULL; + char *virtPortTypeID = NULL; + char *virtPortTypeIDVersion = NULL; + char *virtPortInstanceID = NULL; + char *virtPortProfileID = NULL; + virNetDevVPortProfilePtr virtPort = NULL; + xmlNodePtr cur = node->children; + + if (VIR_ALLOC(virtPort) < 0) { + virReportOOMError(); + return NULL; + } + + virtPortType = virXMLPropString(node, "type"); + if (!virtPortType) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("missing virtualportprofile type")); + goto error; + } + + if ((virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) { + virNetDevError(VIR_ERR_XML_ERROR, + _("unknown virtualportprofile type %s"), virtPortType); + goto error; + } + + while (cur != NULL) { + if (xmlStrEqual(cur->name, BAD_CAST "parameters")) { + + virtPortManagerID = virXMLPropString(cur, "managerid"); + virtPortTypeID = virXMLPropString(cur, "typeid"); + virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion"); + virtPortInstanceID = virXMLPropString(cur, "instanceid"); + virtPortProfileID = virXMLPropString(cur, "profileid"); + + break; + } + + cur = cur->next; + } + + switch (virtPort->virtPortType) { + case VIR_NETDEV_VPORT_PROFILE_8021QBG: + if (virtPortManagerID != NULL && virtPortTypeID != NULL && + virtPortTypeIDVersion != NULL) { + unsigned int val; + + if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("cannot parse value of managerid parameter")); + goto error; + } + + if (val > 0xff) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("value of managerid out of range")); + goto error; + } + + virtPort->u.virtPort8021Qbg.managerID = (uint8_t)val; + + if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("cannot parse value of typeid parameter")); + goto error; + } + + if (val > 0xffffff) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("value for typeid out of range")); + goto error; + } + + virtPort->u.virtPort8021Qbg.typeID = (uint32_t)val; + + if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("cannot parse value of typeidversion parameter")); + goto error; + } + + if (val > 0xff) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("value of typeidversion out of range")); + goto error; + } + + virtPort->u.virtPort8021Qbg.typeIDVersion = (uint8_t)val; + + if (virtPortInstanceID != NULL) { + if (virUUIDParse(virtPortInstanceID, + virtPort->u.virtPort8021Qbg.instanceID)) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("cannot parse instanceid parameter as a uuid")); + goto error; + } + } else { + if (virUUIDGenerate(virtPort->u.virtPort8021Qbg.instanceID)) { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("cannot generate a random uuid for instanceid")); + goto error; + } + } + + virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBG; + + } else { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("a parameter is missing for 802.1Qbg description")); + goto error; + } + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBH: + if (virtPortProfileID != NULL) { + if (virStrcpyStatic(virtPort->u.virtPort8021Qbh.profileID, + virtPortProfileID) != NULL) { + virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBH; + } else { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("profileid parameter too long")); + goto error; + } + } else { + virNetDevError(VIR_ERR_XML_ERROR, "%s", + _("profileid parameter is missing for 802.1Qbh descripion")); + goto error; + } + break; + + default: + virNetDevError(VIR_ERR_XML_ERROR, + _("unexpected virtualport type %d"), virtPort->virtPortType); + goto error; + } + +cleanup: + VIR_FREE(virtPortManagerID); + VIR_FREE(virtPortTypeID); + VIR_FREE(virtPortTypeIDVersion); + VIR_FREE(virtPortInstanceID); + VIR_FREE(virtPortProfileID); + VIR_FREE(virtPortType); + + return virtPort; + +error: + VIR_FREE(virtPort); + goto cleanup; +} + + +int +virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort, + virBufferPtr buf) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + if (!virtPort || virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE) + return 0; + + virBufferAsprintf(buf, "\n", + virNetDevVPortTypeToString(virtPort->virtPortType)); + + switch (virtPort->virtPortType) { + case VIR_NETDEV_VPORT_PROFILE_8021QBG: + virUUIDFormat(virtPort->u.virtPort8021Qbg.instanceID, + uuidstr); + virBufferAsprintf(buf, + " \n", + virtPort->u.virtPort8021Qbg.managerID, + virtPort->u.virtPort8021Qbg.typeID, + virtPort->u.virtPort8021Qbg.typeIDVersion, + uuidstr); + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBH: + virBufferAsprintf(buf, + " \n", + virtPort->u.virtPort8021Qbh.profileID); + break; + + default: + virNetDevError(VIR_ERR_XML_ERROR, + _("unexpected virtualport type %d"), virtPort->virtPortType); + return -1; + } + + virBufferAddLit(buf, "\n"); + return 0; +} diff --git a/src/conf/netdev_vport_profile_conf.h b/src/conf/netdev_vport_profile_conf.h new file mode 100644 index 0000000000..30084d5678 --- /dev/null +++ b/src/conf/netdev_vport_profile_conf.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Stefan Berger + * Daniel P. Berrange + */ + +#ifndef __VIR_NETDEV_VPORT_PROFILE_CONF_H__ +# define __VIR_NETDEV_VPORT_PROFILE_CONF_H__ + +# include "internal.h" +# include "virnetdevvportprofile.h" +# include "buf.h" +# include "xml.h" + +virNetDevVPortProfilePtr +virNetDevVPortProfileParse(xmlNodePtr node); + +int +virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort, + virBufferPtr buf); + + +#endif /* __VIR_NETDEV_VPORT_PROFILE_CONF_H__ */ diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 5e38bee922..10afcde6d9 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -34,7 +34,8 @@ #include "virterror_internal.h" #include "datatypes.h" #include "network_conf.h" -#include "network.h" +#include "netdev_vport_profile_conf.h" +#include "netdev_bandwidth_conf.h" #include "memory.h" #include "xml.h" #include "uuid.h" diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 57ad6377ab..1be20f8d93 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -30,7 +30,9 @@ # include "internal.h" # include "threads.h" -# include "network.h" +# include "virsocketaddr.h" +# include "virnetdevbandwidth.h" +# include "virnetdevvportprofile.h" # include "util.h" enum virNetworkForwardType { diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index c96851aabb..f48c7cd1d1 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -35,7 +35,7 @@ # include "hash.h" # include "xml.h" # include "buf.h" -# include "network.h" +# include "virsocketaddr.h" /* XXX * The config parser/structs should not be using platform specific diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h index 8d172e10a7..2bee51051a 100644 --- a/src/esx/esx_util.h +++ b/src/esx/esx_util.h @@ -23,7 +23,7 @@ # define __ESX_UTIL_H__ # include - +# include # include "internal.h" typedef struct _esxUtil_ParsedUri esxUtil_ParsedUri; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index ee1c46a97e..15b52ce005 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -58,7 +58,6 @@ #include "interface.h" #include "logging.h" #include "dnsmasq.h" -#include "util/network.h" #include "configmake.h" #include "ignore-value.h" #include "virnetdev.h" diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 0cf921f4f5..d7e9d7d834 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -49,7 +49,6 @@ #include "xml.h" #include "nodeinfo.h" #include "logging.h" -#include "network.h" #include "macvtap.h" #include "cpu/cpu.h" #include "domain_nwfilter.h" diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 30b8fe654d..02fd0ae032 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef HAVE_NETINET_TCP_H # include diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h index e444aef3b0..c4c0c1f665 100644 --- a/src/rpc/virnetsocket.h +++ b/src/rpc/virnetsocket.h @@ -24,7 +24,7 @@ #ifndef __VIR_NET_SOCKET_H__ # define __VIR_NET_SOCKET_H__ -# include "network.h" +# include "virsocketaddr.h" # include "command.h" # include "virnettlscontext.h" # ifdef HAVE_SASL diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h index d16a54fb8d..2bec726bb7 100644 --- a/src/util/dnsmasq.h +++ b/src/util/dnsmasq.h @@ -22,7 +22,7 @@ #ifndef __DNSMASQ_H__ # define __DNSMASQ_H__ -# include "network.h" +# include "virsocketaddr.h" typedef struct { diff --git a/src/util/interface.h b/src/util/interface.h index 7be1444f9d..3603c68f03 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -25,7 +25,7 @@ struct nlattr; # endif # include "datatypes.h" -# include "network.h" +# include "virsocketaddr.h" # define NET_SYSFS "/sys/class/net/" diff --git a/src/util/iptables.h b/src/util/iptables.h index 572d612fd1..429f29cdbd 100644 --- a/src/util/iptables.h +++ b/src/util/iptables.h @@ -22,7 +22,7 @@ #ifndef __QEMUD_IPTABLES_H__ # define __QEMUD_IPTABLES_H__ -# include "network.h" +# include "virsocketaddr.h" typedef struct _iptablesContext iptablesContext; diff --git a/src/util/macvtap.c b/src/util/macvtap.c index d4370e682e..d5791a2223 100644 --- a/src/util/macvtap.c +++ b/src/util/macvtap.c @@ -50,7 +50,6 @@ #include "util.h" #include "macvtap.h" -#include "network.h" VIR_ENUM_IMPL(virMacvtapMode, VIR_MACVTAP_MODE_LAST, "vepa", diff --git a/src/util/macvtap.h b/src/util/macvtap.h index d685ab9e18..a6b00fed5a 100644 --- a/src/util/macvtap.h +++ b/src/util/macvtap.h @@ -23,7 +23,10 @@ #ifndef __UTIL_MACVTAP_H__ # define __UTIL_MACVTAP_H__ -# include +# include "internal.h" +# include "virsocketaddr.h" +# include "virnetdevbandwidth.h" +# include "virnetdevvportprofile.h" /* the mode type for macvtap devices */ enum virMacvtapMode { @@ -50,9 +53,6 @@ enum virVMOperationType { # if WITH_MACVTAP -# include "internal.h" -# include "network.h" - int openMacvtapTap(const char *ifname, const unsigned char *macaddress, const char *linkdev, diff --git a/src/util/network.c b/src/util/network.c deleted file mode 100644 index 4fb10fdf75..0000000000 --- a/src/util/network.c +++ /dev/null @@ -1,1349 +0,0 @@ -/* - * network.c: network helper APIs for libvirt - * - * Copyright (C) 2009-2011 Red Hat, Inc. - * - * See COPYING.LIB for the License of this software - * - * Daniel Veillard - */ - -#include -#include - -#include "memory.h" -#include "uuid.h" -#include "network.h" -#include "util.h" -#include "virterror_internal.h" -#include "command.h" -#include "ignore-value.h" - -#define VIR_FROM_THIS VIR_FROM_NONE -#define virSocketError(code, ...) \ - virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) - -/* - * Helpers to extract the IP arrays from the virSocketAddrPtr - * That part is the less portable of the module - */ -typedef unsigned char virSocketAddrIPv4[4]; -typedef virSocketAddrIPv4 *virSocketAddrIPv4Ptr; -typedef unsigned short virSocketAddrIPv6[8]; -typedef virSocketAddrIPv6 *virSocketAddrIPv6Ptr; - -static int virSocketAddrGetIPv4Addr(virSocketAddrPtr addr, virSocketAddrIPv4Ptr tab) { - unsigned long val; - int i; - - if ((addr == NULL) || (tab == NULL) || (addr->data.stor.ss_family != AF_INET)) - return(-1); - - val = ntohl(addr->data.inet4.sin_addr.s_addr); - - for (i = 0;i < 4;i++) { - (*tab)[3 - i] = val & 0xFF; - val >>= 8; - } - - return(0); -} - -static int virSocketAddrGetIPv6Addr(virSocketAddrPtr addr, virSocketAddrIPv6Ptr tab) { - int i; - - if ((addr == NULL) || (tab == NULL) || (addr->data.stor.ss_family != AF_INET6)) - return(-1); - - for (i = 0;i < 8;i++) { - (*tab)[i] = ((addr->data.inet6.sin6_addr.s6_addr[2 * i] << 8) | - addr->data.inet6.sin6_addr.s6_addr[2 * i + 1]); - } - - return(0); -} - -/** - * virSocketAddrParse: - * @val: a numeric network address IPv4 or IPv6 - * @addr: where to store the return value, optional. - * @family: address family to pass down to getaddrinfo - * - * Mostly a wrapper for getaddrinfo() extracting the address storage - * from the numeric string like 1.2.3.4 or 2001:db8:85a3:0:0:8a2e:370:7334 - * - * Returns the length of the network address or -1 in case of error. - */ -int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) { - int len; - struct addrinfo hints; - struct addrinfo *res = NULL; - int err; - - if (val == NULL) { - virSocketError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); - return -1; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_flags = AI_NUMERICHOST; - if ((err = getaddrinfo(val, NULL, &hints, &res)) != 0) { - virSocketError(VIR_ERR_SYSTEM_ERROR, - _("Cannot parse socket address '%s': %s"), - val, gai_strerror(err)); - return -1; - } - - if (res == NULL) { - virSocketError(VIR_ERR_SYSTEM_ERROR, - _("No socket addresses found for '%s'"), - val); - return -1; - } - - len = res->ai_addrlen; - if (addr != NULL) { - memcpy(&addr->data.stor, res->ai_addr, len); - addr->len = res->ai_addrlen; - } - - freeaddrinfo(res); - return(len); -} - -/* - * virSocketAddrParseIPv4: - * @val: an IPv4 numeric address - * @addr: the location to store the result - * - * Extract the address storage from an IPv4 numeric address - * - * Returns the length of the network address or -1 in case of error. - */ -int -virSocketAddrParseIPv4(virSocketAddrPtr addr, const char *val) { - return virSocketAddrParse(addr, val, AF_INET); -} - -/* - * virSocketAddrParseIPv6: - * @val: an IPv6 numeric address - * @addr: the location to store the result - * - * Extract the address storage from an IPv6 numeric address - * - * Returns the length of the network address or -1 in case of error. - */ -int -virSocketAddrParseIPv6(virSocketAddrPtr addr, const char *val) { - return virSocketAddrParse(addr, val, AF_INET6); -} - -/* - * virSocketAddrFormat: - * @addr: an initialized virSocketAddrPtr - * - * Returns a string representation of the given address - * Returns NULL on any error - * Caller must free the returned string - */ -char * -virSocketAddrFormat(virSocketAddrPtr addr) { - return virSocketAddrFormatFull(addr, false, NULL); -} - - -/* - * virSocketAddrFormatFull: - * @addr: an initialized virSocketAddrPtr - * @withService: if true, then service info is appended - * @separator: separator between hostname & service. - * - * Returns a string representation of the given address - * Returns NULL on any error - * Caller must free the returned string - */ -char * -virSocketAddrFormatFull(virSocketAddrPtr addr, - bool withService, - const char *separator) -{ - char host[NI_MAXHOST], port[NI_MAXSERV]; - char *addrstr; - int err; - - if (addr == NULL) { - virSocketError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); - return NULL; - } - - /* Short-circuit since getnameinfo doesn't work - * nicely for UNIX sockets */ - if (addr->data.sa.sa_family == AF_UNIX) { - if (withService) { - if (virAsprintf(&addrstr, "127.0.0.1%s0", - separator ? separator : ":") < 0) - goto no_memory; - } else { - if (!(addrstr = strdup("127.0.0.1"))) - goto no_memory; - } - return addrstr; - } - - if ((err = getnameinfo(&addr->data.sa, - addr->len, - host, sizeof(host), - port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - virSocketError(VIR_ERR_SYSTEM_ERROR, - _("Cannot convert socket address to string: %s"), - gai_strerror(err)); - return NULL; - } - - if (withService) { - if (virAsprintf(&addrstr, "%s%s%s", host, separator, port) == -1) - goto no_memory; - } else { - if (!(addrstr = strdup(host))) - goto no_memory; - } - - return addrstr; - -no_memory: - virReportOOMError(); - return NULL; -} - - -/* - * virSocketAddrSetPort: - * @addr: an initialized virSocketAddrPtr - * @port: the port number to set - * - * Set the transport layer port of the given virtSocketAddr - * - * Returns 0 on success, -1 on failure - */ -int -virSocketAddrSetPort(virSocketAddrPtr addr, int port) { - if (addr == NULL) - return -1; - - port = htons(port); - - if(addr->data.stor.ss_family == AF_INET) { - addr->data.inet4.sin_port = port; - } - - else if(addr->data.stor.ss_family == AF_INET6) { - addr->data.inet6.sin6_port = port; - } - - else { - return -1; - } - - return 0; -} - -/* - * virSocketGetPort: - * @addr: an initialized virSocketAddrPtr - * - * Returns the transport layer port of the given virtSocketAddr - * Returns -1 if @addr is invalid - */ -int -virSocketAddrGetPort(virSocketAddrPtr addr) { - if (addr == NULL) - return -1; - - if(addr->data.stor.ss_family == AF_INET) { - return ntohs(addr->data.inet4.sin_port); - } - - else if(addr->data.stor.ss_family == AF_INET6) { - return ntohs(addr->data.inet6.sin6_port); - } - - return -1; -} - -/** - * virSocketAddrIsNetmask: - * @netmask: the netmask address - * - * Check that @netmask is a proper network mask - * - * Returns 0 in case of success and -1 in case of error - */ -int virSocketAddrIsNetmask(virSocketAddrPtr netmask) { - int n = virSocketAddrGetNumNetmaskBits(netmask); - if (n < 0) - return -1; - return 0; -} - -/** - * virSocketAddrMask: - * @addr: address that needs to be masked - * @netmask: the netmask address - * @network: where to store the result, can be same as @addr - * - * Mask off the host bits of @addr according to @netmask, turning it - * into a network address. - * - * Returns 0 in case of success, or -1 on error. - */ -int -virSocketAddrMask(const virSocketAddrPtr addr, - const virSocketAddrPtr netmask, - virSocketAddrPtr network) -{ - if (addr->data.stor.ss_family != netmask->data.stor.ss_family) { - network->data.stor.ss_family = AF_UNSPEC; - return -1; - } - - if (addr->data.stor.ss_family == AF_INET) { - network->data.inet4.sin_addr.s_addr - = (addr->data.inet4.sin_addr.s_addr - & netmask->data.inet4.sin_addr.s_addr); - network->data.inet4.sin_port = 0; - network->data.stor.ss_family = AF_INET; - network->len = addr->len; - return 0; - } - if (addr->data.stor.ss_family == AF_INET6) { - int ii; - for (ii = 0; ii < 16; ii++) { - network->data.inet6.sin6_addr.s6_addr[ii] - = (addr->data.inet6.sin6_addr.s6_addr[ii] - & netmask->data.inet6.sin6_addr.s6_addr[ii]); - } - network->data.inet6.sin6_port = 0; - network->data.stor.ss_family = AF_INET6; - network->len = addr->len; - return 0; - } - network->data.stor.ss_family = AF_UNSPEC; - return -1; -} - -/** - * virSocketAddrMaskByPrefix: - * @addr: address that needs to be masked - * @prefix: prefix (# of 1 bits) of netmask to apply - * @network: where to store the result, can be same as @addr - * - * Mask off the host bits of @addr according to @prefix, turning it - * into a network address. - * - * Returns 0 in case of success, or -1 on error. - */ -int -virSocketAddrMaskByPrefix(const virSocketAddrPtr addr, - unsigned int prefix, - virSocketAddrPtr network) -{ - virSocketAddr netmask; - - if (virSocketAddrPrefixToNetmask(prefix, &netmask, - addr->data.stor.ss_family) < 0) { - network->data.stor.ss_family = AF_UNSPEC; - return -1; - } - - return virSocketAddrMask(addr, &netmask, network); -} - -/** - * virSocketAddrBroadcast: - * @addr: address that needs to be turned into broadcast address (IPv4 only) - * @netmask: the netmask address - * @broadcast: virSocketAddr to recieve the broadcast address - * - * Mask ON the host bits of @addr according to @netmask, turning it - * into a broadcast address. - * - * Returns 0 in case of success, or -1 on error. - */ -int -virSocketAddrBroadcast(const virSocketAddrPtr addr, - const virSocketAddrPtr netmask, - virSocketAddrPtr broadcast) -{ - if ((addr->data.stor.ss_family != AF_INET) || - (netmask->data.stor.ss_family != AF_INET)) { - broadcast->data.stor.ss_family = AF_UNSPEC; - return -1; - } - - broadcast->data.stor.ss_family = AF_INET; - broadcast->len = addr->len; - broadcast->data.inet4.sin_addr.s_addr - = (addr->data.inet4.sin_addr.s_addr - | ~netmask->data.inet4.sin_addr.s_addr); - return 0; -} - -/** - * virSocketAddrBroadcastByPrefix: - * @addr: address that needs to be turned into broadcast address (IPv4 only) - * @prefix: prefix (# of 1 bits) of netmask to apply - * @broadcast: virSocketAddr to recieve the broadcast address - * - * Mask off the host bits of @addr according to @prefix, turning it - * into a network address. - * - * Returns 0 in case of success, or -1 on error. - */ -int -virSocketAddrBroadcastByPrefix(const virSocketAddrPtr addr, - unsigned int prefix, - virSocketAddrPtr broadcast) -{ - virSocketAddr netmask; - - if (virSocketAddrPrefixToNetmask(prefix, &netmask, - addr->data.stor.ss_family) < 0) - return -1; - - return virSocketAddrBroadcast(addr, &netmask, broadcast); -} - -/** - * virSocketCheckNetmask: - * @addr1: a first network address - * @addr2: a second network address - * @netmask: the netmask address - * - * Check that @addr1 and @addr2 pertain to the same @netmask address - * range and returns the size of the range - * - * Returns 1 in case of success and 0 in case of failure and - * -1 in case of error - */ -int virSocketAddrCheckNetmask(virSocketAddrPtr addr1, virSocketAddrPtr addr2, - virSocketAddrPtr netmask) { - int i; - - if ((addr1 == NULL) || (addr2 == NULL) || (netmask == NULL)) - return(-1); - if ((addr1->data.stor.ss_family != addr2->data.stor.ss_family) || - (addr1->data.stor.ss_family != netmask->data.stor.ss_family)) - return(-1); - - if (virSocketAddrIsNetmask(netmask) != 0) - return(-1); - - if (addr1->data.stor.ss_family == AF_INET) { - virSocketAddrIPv4 t1, t2, tm; - - if ((virSocketAddrGetIPv4Addr(addr1, &t1) < 0) || - (virSocketAddrGetIPv4Addr(addr2, &t2) < 0) || - (virSocketAddrGetIPv4Addr(netmask, &tm) < 0)) - return(-1); - - for (i = 0;i < 4;i++) { - if ((t1[i] & tm[i]) != (t2[i] & tm[i])) - return(0); - } - - } else if (addr1->data.stor.ss_family == AF_INET6) { - virSocketAddrIPv6 t1, t2, tm; - - if ((virSocketAddrGetIPv6Addr(addr1, &t1) < 0) || - (virSocketAddrGetIPv6Addr(addr2, &t2) < 0) || - (virSocketAddrGetIPv6Addr(netmask, &tm) < 0)) - return(-1); - - for (i = 0;i < 8;i++) { - if ((t1[i] & tm[i]) != (t2[i] & tm[i])) - return(0); - } - - } else { - return(-1); - } - return(1); -} - -/** - * virSocketGetRange: - * @start: start of an IP range - * @end: end of an IP range - * - * Check the order of the 2 addresses and compute the range, this - * will return 1 for identical addresses. Errors can come from incompatible - * addresses type, excessive range (>= 2^^16) where the two addresses are - * unrelated or inverted start and end. - * - * Returns the size of the range or -1 in case of failure - */ -int virSocketAddrGetRange(virSocketAddrPtr start, virSocketAddrPtr end) { - int ret = 0, i; - - if ((start == NULL) || (end == NULL)) - return(-1); - if (start->data.stor.ss_family != end->data.stor.ss_family) - return(-1); - - if (start->data.stor.ss_family == AF_INET) { - virSocketAddrIPv4 t1, t2; - - if ((virSocketAddrGetIPv4Addr(start, &t1) < 0) || - (virSocketAddrGetIPv4Addr(end, &t2) < 0)) - return(-1); - - for (i = 0;i < 2;i++) { - if (t1[i] != t2[i]) - return(-1); - } - ret = (t2[2] - t1[2]) * 256 + (t2[3] - t1[3]); - if (ret < 0) - return(-1); - ret++; - } else if (start->data.stor.ss_family == AF_INET6) { - virSocketAddrIPv6 t1, t2; - - if ((virSocketAddrGetIPv6Addr(start, &t1) < 0) || - (virSocketAddrGetIPv6Addr(end, &t2) < 0)) - return(-1); - - for (i = 0;i < 7;i++) { - if (t1[i] != t2[i]) - return(-1); - } - ret = t2[7] - t1[7]; - if (ret < 0) - return(-1); - ret++; - } else { - return(-1); - } - return(ret); -} - - -/** - * virSocketAddrGetNumNetmaskBits - * @netmask: the presumed netmask - * - * Get the number of netmask bits in a netmask. - * - * Returns the number of bits in the netmask or -1 if an error occurred - * or the netmask is invalid. - */ -int virSocketAddrGetNumNetmaskBits(const virSocketAddrPtr netmask) -{ - int i, j; - int c = 0; - - if (netmask->data.stor.ss_family == AF_INET) { - virSocketAddrIPv4 tm; - uint8_t bit; - - if (virSocketAddrGetIPv4Addr(netmask, &tm) < 0) - return -1; - - for (i = 0; i < 4; i++) - if (tm[i] == 0xff) - c += 8; - else - break; - - if (c == 8 * 4) - return c; - - j = i << 3; - while (j < (8 * 4)) { - bit = 1 << (7 - (j & 7)); - if ((tm[j >> 3] & bit)) { - c++; - } else - break; - j++; - } - - while (j < (8 * 4)) { - bit = 1 << (7 - (j & 7)); - if ((tm[j >> 3] & bit)) - return -1; - j++; - } - - return c; - } else if (netmask->data.stor.ss_family == AF_INET6) { - virSocketAddrIPv6 tm; - uint16_t bit; - - if (virSocketAddrGetIPv6Addr(netmask, &tm) < 0) - return -1; - - for (i = 0; i < 8; i++) - if (tm[i] == 0xffff) - c += 16; - else - break; - - if (c == 16 * 8) - return c; - - j = i << 4; - while (j < (16 * 8)) { - bit = 1 << (15 - (j & 0xf)); - if ((tm[j >> 4] & bit)) { - c++; - } else - break; - j++; - } - - while (j < (16 * 8)) { - bit = 1 << (15 - (j & 0xf)); - if ((tm[j >> 4]) & bit) - return -1; - j++; - } - - return c; - } - return -1; -} - -/** - * virSocketPrefixToNetmask: - * @prefix: number of 1 bits to put in the netmask - * @netmask: address to fill in with the desired netmask - * @family: family of the address (AF_INET or AF_INET6 only) - * - * given @prefix and @family, fill in @netmask with a netmask - * (eg 255.255.255.0). - * - * Returns 0 on success or -1 on error. - */ - -int -virSocketAddrPrefixToNetmask(unsigned int prefix, - virSocketAddrPtr netmask, - int family) -{ - int result = -1; - - netmask->data.stor.ss_family = AF_UNSPEC; /* assume failure */ - - if (family == AF_INET) { - int ip; - - if (prefix > 32) - goto error; - - ip = prefix ? ~((1 << (32 - prefix)) - 1) : 0; - netmask->data.inet4.sin_addr.s_addr = htonl(ip); - netmask->data.stor.ss_family = AF_INET; - result = 0; - - } else if (family == AF_INET6) { - int ii = 0; - - if (prefix > 128) - goto error; - - while (prefix >= 8) { - /* do as much as possible an entire byte at a time */ - netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0xff; - prefix -= 8; - } - if (prefix > 0) { - /* final partial byte */ - netmask->data.inet6.sin6_addr.s6_addr[ii++] - = ~((1 << (8 - prefix)) -1); - } - while (ii < 16) { - /* zerofill remainder in case it wasn't initialized */ - netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0; - } - netmask->data.stor.ss_family = AF_INET6; - result = 0; - } - -error: - return result; -} - -/* virtualPortProfile utilities */ - -VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST, - "none", - "802.1Qbg", - "802.1Qbh") - - -virNetDevVPortProfilePtr -virNetDevVPortProfileParse(xmlNodePtr node) -{ - char *virtPortType; - char *virtPortManagerID = NULL; - char *virtPortTypeID = NULL; - char *virtPortTypeIDVersion = NULL; - char *virtPortInstanceID = NULL; - char *virtPortProfileID = NULL; - virNetDevVPortProfilePtr virtPort = NULL; - xmlNodePtr cur = node->children; - - if (VIR_ALLOC(virtPort) < 0) { - virReportOOMError(); - return NULL; - } - - virtPortType = virXMLPropString(node, "type"); - if (!virtPortType) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("missing virtualportprofile type")); - goto error; - } - - if ((virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) { - virSocketError(VIR_ERR_XML_ERROR, - _("unknown virtualportprofile type %s"), virtPortType); - goto error; - } - - while (cur != NULL) { - if (xmlStrEqual(cur->name, BAD_CAST "parameters")) { - - virtPortManagerID = virXMLPropString(cur, "managerid"); - virtPortTypeID = virXMLPropString(cur, "typeid"); - virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion"); - virtPortInstanceID = virXMLPropString(cur, "instanceid"); - virtPortProfileID = virXMLPropString(cur, "profileid"); - - break; - } - - cur = cur->next; - } - - switch (virtPort->virtPortType) { - case VIR_NETDEV_VPORT_PROFILE_8021QBG: - if (virtPortManagerID != NULL && virtPortTypeID != NULL && - virtPortTypeIDVersion != NULL) { - unsigned int val; - - if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("cannot parse value of managerid parameter")); - goto error; - } - - if (val > 0xff) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("value of managerid out of range")); - goto error; - } - - virtPort->u.virtPort8021Qbg.managerID = (uint8_t)val; - - if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("cannot parse value of typeid parameter")); - goto error; - } - - if (val > 0xffffff) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("value for typeid out of range")); - goto error; - } - - virtPort->u.virtPort8021Qbg.typeID = (uint32_t)val; - - if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("cannot parse value of typeidversion parameter")); - goto error; - } - - if (val > 0xff) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("value of typeidversion out of range")); - goto error; - } - - virtPort->u.virtPort8021Qbg.typeIDVersion = (uint8_t)val; - - if (virtPortInstanceID != NULL) { - if (virUUIDParse(virtPortInstanceID, - virtPort->u.virtPort8021Qbg.instanceID)) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("cannot parse instanceid parameter as a uuid")); - goto error; - } - } else { - if (virUUIDGenerate(virtPort->u.virtPort8021Qbg.instanceID)) { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("cannot generate a random uuid for instanceid")); - goto error; - } - } - - virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBG; - - } else { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("a parameter is missing for 802.1Qbg description")); - goto error; - } - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBH: - if (virtPortProfileID != NULL) { - if (virStrcpyStatic(virtPort->u.virtPort8021Qbh.profileID, - virtPortProfileID) != NULL) { - virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBH; - } else { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("profileid parameter too long")); - goto error; - } - } else { - virSocketError(VIR_ERR_XML_ERROR, "%s", - _("profileid parameter is missing for 802.1Qbh descripion")); - goto error; - } - break; - - default: - virSocketError(VIR_ERR_XML_ERROR, - _("unexpected virtualport type %d"), virtPort->virtPortType); - goto error; - } - -cleanup: - VIR_FREE(virtPortManagerID); - VIR_FREE(virtPortTypeID); - VIR_FREE(virtPortTypeIDVersion); - VIR_FREE(virtPortInstanceID); - VIR_FREE(virtPortProfileID); - VIR_FREE(virtPortType); - - return virtPort; - -error: - VIR_FREE(virtPort); - goto cleanup; -} - -bool -virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr b) -{ - /* NULL resistant */ - if (!a && !b) - return true; - - if (!a || !b) - return false; - - if (a->virtPortType != b->virtPortType) - return false; - - switch (a->virtPortType) { - case VIR_NETDEV_VPORT_PROFILE_NONE: - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBG: - if (a->u.virtPort8021Qbg.managerID != b->u.virtPort8021Qbg.managerID || - a->u.virtPort8021Qbg.typeID != b->u.virtPort8021Qbg.typeID || - a->u.virtPort8021Qbg.typeIDVersion != b->u.virtPort8021Qbg.typeIDVersion || - memcmp(a->u.virtPort8021Qbg.instanceID, b->u.virtPort8021Qbg.instanceID, VIR_UUID_BUFLEN) != 0) - return false; - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBH: - if (STRNEQ(a->u.virtPort8021Qbh.profileID, b->u.virtPort8021Qbh.profileID)) - return false; - break; - - default: - break; - } - - return true; -} - - -int -virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort, - virBufferPtr buf) -{ - char uuidstr[VIR_UUID_STRING_BUFLEN]; - - if (!virtPort || virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE) - return 0; - - virBufferAsprintf(buf, "\n", - virNetDevVPortTypeToString(virtPort->virtPortType)); - - switch (virtPort->virtPortType) { - case VIR_NETDEV_VPORT_PROFILE_8021QBG: - virUUIDFormat(virtPort->u.virtPort8021Qbg.instanceID, - uuidstr); - virBufferAsprintf(buf, - " \n", - virtPort->u.virtPort8021Qbg.managerID, - virtPort->u.virtPort8021Qbg.typeID, - virtPort->u.virtPort8021Qbg.typeIDVersion, - uuidstr); - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBH: - virBufferAsprintf(buf, - " \n", - virtPort->u.virtPort8021Qbh.profileID); - break; - - default: - virSocketError(VIR_ERR_XML_ERROR, - _("unexpected virtualport type %d"), virtPort->virtPortType); - return -1; - } - - virBufferAddLit(buf, "\n"); - return 0; -} - -static int -virNetDevBandwidthParseRate(xmlNodePtr node, virNetDevBandwidthRatePtr rate) -{ - int ret = -1; - char *average = NULL; - char *peak = NULL; - char *burst = NULL; - - if (!node || !rate) { - virSocketError(VIR_ERR_INVALID_ARG, "%s", - _("invalid argument supplied")); - return -1; - } - - average = virXMLPropString(node, "average"); - peak = virXMLPropString(node, "peak"); - burst = virXMLPropString(node, "burst"); - - if (average) { - if (virStrToLong_ull(average, NULL, 10, &rate->average) < 0) { - virSocketError(VIR_ERR_CONFIG_UNSUPPORTED, - _("could not convert %s"), - average); - goto cleanup; - } - } else { - virSocketError(VIR_ERR_XML_DETAIL, "%s", - _("Missing mandatory average attribute")); - goto cleanup; - } - - if (peak && virStrToLong_ull(peak, NULL, 10, &rate->peak) < 0) { - virSocketError(VIR_ERR_CONFIG_UNSUPPORTED, - _("could not convert %s"), - peak); - goto cleanup; - } - - if (burst && virStrToLong_ull(burst, NULL, 10, &rate->burst) < 0) { - virSocketError(VIR_ERR_CONFIG_UNSUPPORTED, - _("could not convert %s"), - burst); - goto cleanup; - } - - ret = 0; - -cleanup: - VIR_FREE(average); - VIR_FREE(peak); - VIR_FREE(burst); - - return ret; -} - -/** - * virNetDevBandwidthParse: - * @node: XML node - * - * Parse bandwidth XML and return pointer to structure - * - * Returns !NULL on success, NULL on error. - */ -virNetDevBandwidthPtr -virNetDevBandwidthParse(xmlNodePtr node) -{ - virNetDevBandwidthPtr def = NULL; - xmlNodePtr cur = node->children; - xmlNodePtr in = NULL, out = NULL; - - if (VIR_ALLOC(def) < 0) { - virReportOOMError(); - return NULL; - } - - if (!node || !xmlStrEqual(node->name, BAD_CAST "bandwidth")) { - virSocketError(VIR_ERR_INVALID_ARG, "%s", - _("invalid argument supplied")); - goto error; - } - - while (cur) { - if (cur->type == XML_ELEMENT_NODE) { - if (xmlStrEqual(cur->name, BAD_CAST "inbound")) { - if (in) { - virSocketError(VIR_ERR_XML_DETAIL, "%s", - _("Only one child " - "element allowed")); - goto error; - } - in = cur; - } else if (xmlStrEqual(cur->name, BAD_CAST "outbound")) { - if (out) { - virSocketError(VIR_ERR_XML_DETAIL, "%s", - _("Only one child " - "element allowed")); - goto error; - } - out = cur; - } - /* Silently ignore unknown elements */ - } - cur = cur->next; - } - - if (in) { - if (VIR_ALLOC(def->in) < 0) { - virReportOOMError(); - goto error; - } - - if (virNetDevBandwidthParseRate(in, def->in) < 0) { - /* helper reported error for us */ - goto error; - } - } - - if (out) { - if (VIR_ALLOC(def->out) < 0) { - virReportOOMError(); - goto error; - } - - if (virNetDevBandwidthParseRate(out, def->out) < 0) { - /* helper reported error for us */ - goto error; - } - } - - return def; - -error: - virNetDevBandwidthFree(def); - return NULL; -} - -void -virNetDevBandwidthFree(virNetDevBandwidthPtr def) -{ - if (!def) - return; - - VIR_FREE(def->in); - VIR_FREE(def->out); - VIR_FREE(def); -} - -static int -virNetDevBandwidthRateFormat(virNetDevBandwidthRatePtr def, - virBufferPtr buf, - const char *elem_name) -{ - if (!buf || !elem_name) - return -1; - if (!def) - return 0; - - if (def->average) { - virBufferAsprintf(buf, " <%s average='%llu'", elem_name, - def->average); - - if (def->peak) - virBufferAsprintf(buf, " peak='%llu'", def->peak); - - if (def->burst) - virBufferAsprintf(buf, " burst='%llu'", def->burst); - virBufferAddLit(buf, "/>\n"); - } - - return 0; -} - -/** - * virNetDevBandwidthDefFormat: - * @def: Data source - * @buf: Buffer to print to - * - * Formats bandwidth and prepend each line with @indent. - * @buf may use auto-indentation. - * - * Returns 0 on success, else -1. - */ -int -virNetDevBandwidthFormat(virNetDevBandwidthPtr def, virBufferPtr buf) -{ - int ret = -1; - - if (!buf) - goto cleanup; - - if (!def) { - ret = 0; - goto cleanup; - } - - virBufferAddLit(buf, "\n"); - if (virNetDevBandwidthRateFormat(def->in, buf, "inbound") < 0 || - virNetDevBandwidthRateFormat(def->out, buf, "outbound") < 0) - goto cleanup; - virBufferAddLit(buf, "\n"); - - ret = 0; - -cleanup: - return ret; -} - -/** - * virNetDevBandwidthSet: - * @ifname: on which interface - * @bandwidth: rates to set (may be NULL) - * - * This function enables QoS on specified interface - * and set given traffic limits for both, incoming - * and outgoing traffic. Any previous setting get - * overwritten. - * - * Return 0 on success, -1 otherwise. - */ -int -virNetDevBandwidthSet(const char *ifname, - virNetDevBandwidthPtr bandwidth) -{ - int ret = -1; - virCommandPtr cmd = NULL; - char *average = NULL; - char *peak = NULL; - char *burst = NULL; - - if (!bandwidth) { - /* nothing to be enabled */ - ret = 0; - goto cleanup; - } - - ignore_value(virNetDevBandwidthClear(ifname)); - - if (bandwidth->in) { - if (virAsprintf(&average, "%llukbps", bandwidth->in->average) < 0) - goto cleanup; - if (bandwidth->in->peak && - (virAsprintf(&peak, "%llukbps", bandwidth->in->peak) < 0)) - goto cleanup; - if (bandwidth->in->burst && - (virAsprintf(&burst, "%llukb", bandwidth->in->burst) < 0)) - goto cleanup; - - cmd = virCommandNew(TC); - virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "root", - "handle", "1:", "htb", "default", "1", NULL); - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; - - virCommandFree(cmd); - cmd = virCommandNew(TC); - virCommandAddArgList(cmd,"class", "add", "dev", ifname, "parent", - "1:", "classid", "1:1", "htb", NULL); - virCommandAddArgList(cmd, "rate", average, NULL); - - if (peak) - virCommandAddArgList(cmd, "ceil", peak, NULL); - if (burst) - virCommandAddArgList(cmd, "burst", burst, NULL); - - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; - - virCommandFree(cmd); - cmd = virCommandNew(TC); - virCommandAddArgList(cmd,"filter", "add", "dev", ifname, "parent", - "1:0", "protocol", "ip", "handle", "1", "fw", - "flowid", "1", NULL); - - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; - - VIR_FREE(average); - VIR_FREE(peak); - VIR_FREE(burst); - } - - if (bandwidth->out) { - if (virAsprintf(&average, "%llukbps", bandwidth->out->average) < 0) - goto cleanup; - if (virAsprintf(&burst, "%llukb", bandwidth->out->burst ? - bandwidth->out->burst : bandwidth->out->average) < 0) - goto cleanup; - - virCommandFree(cmd); - cmd = virCommandNew(TC); - virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, - "ingress", NULL); - - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; - - virCommandFree(cmd); - cmd = virCommandNew(TC); - virCommandAddArgList(cmd, "filter", "add", "dev", ifname, "parent", - "ffff:", "protocol", "ip", "u32", "match", "ip", - "src", "0.0.0.0/0", "police", "rate", average, - "burst", burst, "mtu", burst, "drop", "flowid", - ":1", NULL); - - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; - } - - ret = 0; - -cleanup: - virCommandFree(cmd); - VIR_FREE(average); - VIR_FREE(peak); - VIR_FREE(burst); - return ret; -} - -/** - * virNetDevBandwidthClear: - * @ifname: on which interface - * - * This function tries to disable QoS on specified interface - * by deleting root and ingress qdisc. However, this may fail - * if we try to remove the default one. - * - * Return 0 on success, -1 otherwise. - */ -int -virNetDevBandwidthClear(const char *ifname) -{ - int ret = 0; - virCommandPtr cmd = NULL; - - cmd = virCommandNew(TC); - virCommandAddArgList(cmd, "qdisc", "del", "dev", ifname, "root", NULL); - - if (virCommandRun(cmd, NULL) < 0) - ret = -1; - - virCommandFree(cmd); - - cmd = virCommandNew(TC); - virCommandAddArgList(cmd, "qdisc", "del", "dev", ifname, "ingress", NULL); - - if (virCommandRun(cmd, NULL) < 0) - ret = -1; - virCommandFree(cmd); - - return ret; -} - -/* - * virNetDevBandwidthCopy: - * @dest: destination - * @src: source (may be NULL) - * - * Returns -1 on OOM error (which gets reported), - * 0 otherwise. - */ -int -virNetDevBandwidthCopy(virNetDevBandwidthPtr *dest, - const virNetDevBandwidthPtr src) -{ - int ret = -1; - - *dest = NULL; - if (!src) { - /* nothing to be copied */ - return 0; - } - - if (VIR_ALLOC(*dest) < 0) { - virReportOOMError(); - goto cleanup; - } - - if (src->in) { - if (VIR_ALLOC((*dest)->in) < 0) { - virReportOOMError(); - goto cleanup; - } - memcpy((*dest)->in, src->in, sizeof(*src->in)); - } - - if (src->out) { - if (VIR_ALLOC((*dest)->out) < 0) { - virReportOOMError(); - VIR_FREE((*dest)->in); - goto cleanup; - } - memcpy((*dest)->out, src->out, sizeof(*src->out)); - } - - ret = 0; - -cleanup: - if (ret < 0) { - virNetDevBandwidthFree(*dest); - *dest = NULL; - } - return ret; -} - -bool -virNetDevBandwidthEqual(virNetDevBandwidthPtr a, - virNetDevBandwidthPtr b) -{ - if (!a && !b) - return true; - - if (!a || !b) - return false; - - /* in */ - if (a->in->average != b->in->average || - a->in->peak != b->in->peak || - a->in->burst != b->in->burst) - return false; - - /*out*/ - if (a->out->average != b->out->average || - a->out->peak != b->out->peak || - a->out->burst != b->out->burst) - return false; - - return true; -} diff --git a/src/util/network.h b/src/util/network.h deleted file mode 100644 index 98dfacc09f..0000000000 --- a/src/util/network.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * network.h: network helper APIs for libvirt - * - * Copyright (C) 2009-2011 Red Hat, Inc. - * - * See COPYING.LIB for the License of this software - * - * Daniel Veillard - */ - -#ifndef __VIR_NETWORK_H__ -# define __VIR_NETWORK_H__ - -# include "internal.h" -# include "buf.h" -# include "util.h" - -# include -# include -# ifdef HAVE_SYS_UN_H -# include -# endif -# include -# include -# include - -typedef struct { - union { - struct sockaddr sa; - struct sockaddr_storage stor; - struct sockaddr_in inet4; - struct sockaddr_in6 inet6; -# ifdef HAVE_SYS_UN_H - struct sockaddr_un un; -# endif - } data; - socklen_t len; -} virSocketAddr; - -# define VIR_SOCKET_ADDR_VALID(s) \ - ((s)->data.sa.sa_family != AF_UNSPEC) - -# define VIR_SOCKET_ADDR_IS_FAMILY(s, f) \ - ((s)->data.sa.sa_family == f) - -# define VIR_SOCKET_ADDR_FAMILY(s) \ - ((s)->data.sa.sa_family) - -typedef virSocketAddr *virSocketAddrPtr; - -typedef struct _virNetDevBandwidthRate virNetDevBandwidthRate; -typedef virNetDevBandwidthRate *virNetDevBandwidthRatePtr; -struct _virNetDevBandwidthRate { - unsigned long long average; /* kbytes/s */ - unsigned long long peak; /* kbytes/s */ - unsigned long long burst; /* kbytes */ -}; - -typedef struct _virNetDevBandwidth virNetDevBandwidth; -typedef virNetDevBandwidth *virNetDevBandwidthPtr; -struct _virNetDevBandwidth { - virNetDevBandwidthRatePtr in, out; -}; - -int virSocketAddrParse(virSocketAddrPtr addr, - const char *val, - int family); - -int virSocketAddrParseIPv4(virSocketAddrPtr addr, - const char *val); - -int virSocketAddrParseIPv6(virSocketAddrPtr addr, - const char *val); - -char * virSocketAddrFormat(virSocketAddrPtr addr); -char * virSocketAddrFormatFull(virSocketAddrPtr addr, - bool withService, - const char *separator); - -int virSocketAddrSetPort(virSocketAddrPtr addr, int port); - -int virSocketAddrGetPort(virSocketAddrPtr addr); - -int virSocketAddrGetRange(virSocketAddrPtr start, - virSocketAddrPtr end); - -int virSocketAddrIsNetmask(virSocketAddrPtr netmask); - -int virSocketAddrCheckNetmask(virSocketAddrPtr addr1, - virSocketAddrPtr addr2, - virSocketAddrPtr netmask); -int virSocketAddrMask(const virSocketAddrPtr addr, - const virSocketAddrPtr netmask, - virSocketAddrPtr network); -int virSocketAddrMaskByPrefix(const virSocketAddrPtr addr, - unsigned int prefix, - virSocketAddrPtr network); -int virSocketAddrBroadcast(const virSocketAddrPtr addr, - const virSocketAddrPtr netmask, - virSocketAddrPtr broadcast); -int virSocketAddrBroadcastByPrefix(const virSocketAddrPtr addr, - unsigned int prefix, - virSocketAddrPtr broadcast); - -int virSocketAddrGetNumNetmaskBits(const virSocketAddrPtr netmask); -int virSocketAddrPrefixToNetmask(unsigned int prefix, - virSocketAddrPtr netmask, - int family); - -/* virtualPortProfile utilities */ -# ifdef IFLA_VF_PORT_PROFILE_MAX -# define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX IFLA_VF_PORT_PROFILE_MAX -# else -# define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX 40 -# endif - -enum virNetDevVPortProfile { - VIR_NETDEV_VPORT_PROFILE_NONE, - VIR_NETDEV_VPORT_PROFILE_8021QBG, - VIR_NETDEV_VPORT_PROFILE_8021QBH, - - VIR_NETDEV_VPORT_PROFILE_LAST, -}; - -VIR_ENUM_DECL(virNetDevVPort) - -/* profile data for macvtap (VEPA) */ -typedef struct _virNetDevVPortProfile virNetDevVPortProfile; -typedef virNetDevVPortProfile *virNetDevVPortProfilePtr; -struct _virNetDevVPortProfile { - enum virNetDevVPortProfile virtPortType; - union { - struct { - uint8_t managerID; - uint32_t typeID; /* 24 bit valid */ - uint8_t typeIDVersion; - unsigned char instanceID[VIR_UUID_BUFLEN]; - } virtPort8021Qbg; - struct { - char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX]; - } virtPort8021Qbh; - } u; -}; - - -virNetDevVPortProfilePtr -virNetDevVPortProfileParse(xmlNodePtr node); - -int -virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort, - virBufferPtr buf); - -bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, - virNetDevVPortProfilePtr b); - -virNetDevBandwidthPtr virNetDevBandwidthParse(xmlNodePtr node) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -void virNetDevBandwidthFree(virNetDevBandwidthPtr def); -int virNetDevBandwidthFormat(virNetDevBandwidthPtr def, - virBufferPtr buf) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -int virNetDevBandwidthSet(const char *ifname, virNetDevBandwidthPtr bandwidth) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -int virNetDevBandwidthClear(const char *ifname) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -int virNetDevBandwidthCopy(virNetDevBandwidthPtr *dest, const virNetDevBandwidthPtr src) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; - -bool virNetDevBandwidthEqual(virNetDevBandwidthPtr a, virNetDevBandwidthPtr b); - - -#endif /* __VIR_NETWORK_H__ */ diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index a7d4a77bcd..219196b18b 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -23,7 +23,7 @@ #ifndef __VIR_NETDEV_H__ # define __VIR_NETDEV_H__ -# include "network.h" +# include "virsocketaddr.h" int virNetDevExists(const char *brname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c new file mode 100644 index 0000000000..10db1ff90b --- /dev/null +++ b/src/util/virnetdevbandwidth.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Michal Privoznik + * Daniel P. Berrange + */ + +#include + +#include "virnetdevbandwidth.h" +#include "command.h" +#include "memory.h" +#include "virterror_internal.h" +#include "ignore-value.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +void +virNetDevBandwidthFree(virNetDevBandwidthPtr def) +{ + if (!def) + return; + + VIR_FREE(def->in); + VIR_FREE(def->out); + VIR_FREE(def); +} + + +/** + * virNetDevBandwidthSet: + * @ifname: on which interface + * @bandwidth: rates to set (may be NULL) + * + * This function enables QoS on specified interface + * and set given traffic limits for both, incoming + * and outgoing traffic. Any previous setting get + * overwritten. + * + * Return 0 on success, -1 otherwise. + */ +int +virNetDevBandwidthSet(const char *ifname, + virNetDevBandwidthPtr bandwidth) +{ + int ret = -1; + virCommandPtr cmd = NULL; + char *average = NULL; + char *peak = NULL; + char *burst = NULL; + + if (!bandwidth) { + /* nothing to be enabled */ + ret = 0; + goto cleanup; + } + + ignore_value(virNetDevBandwidthClear(ifname)); + + if (bandwidth->in) { + if (virAsprintf(&average, "%llukbps", bandwidth->in->average) < 0) + goto cleanup; + if (bandwidth->in->peak && + (virAsprintf(&peak, "%llukbps", bandwidth->in->peak) < 0)) + goto cleanup; + if (bandwidth->in->burst && + (virAsprintf(&burst, "%llukb", bandwidth->in->burst) < 0)) + goto cleanup; + + cmd = virCommandNew(TC); + virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "root", + "handle", "1:", "htb", "default", "1", NULL); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + virCommandFree(cmd); + cmd = virCommandNew(TC); + virCommandAddArgList(cmd,"class", "add", "dev", ifname, "parent", + "1:", "classid", "1:1", "htb", NULL); + virCommandAddArgList(cmd, "rate", average, NULL); + + if (peak) + virCommandAddArgList(cmd, "ceil", peak, NULL); + if (burst) + virCommandAddArgList(cmd, "burst", burst, NULL); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + virCommandFree(cmd); + cmd = virCommandNew(TC); + virCommandAddArgList(cmd,"filter", "add", "dev", ifname, "parent", + "1:0", "protocol", "ip", "handle", "1", "fw", + "flowid", "1", NULL); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + VIR_FREE(average); + VIR_FREE(peak); + VIR_FREE(burst); + } + + if (bandwidth->out) { + if (virAsprintf(&average, "%llukbps", bandwidth->out->average) < 0) + goto cleanup; + if (virAsprintf(&burst, "%llukb", bandwidth->out->burst ? + bandwidth->out->burst : bandwidth->out->average) < 0) + goto cleanup; + + virCommandFree(cmd); + cmd = virCommandNew(TC); + virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, + "ingress", NULL); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + virCommandFree(cmd); + cmd = virCommandNew(TC); + virCommandAddArgList(cmd, "filter", "add", "dev", ifname, "parent", + "ffff:", "protocol", "ip", "u32", "match", "ip", + "src", "0.0.0.0/0", "police", "rate", average, + "burst", burst, "mtu", burst, "drop", "flowid", + ":1", NULL); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + } + + ret = 0; + +cleanup: + virCommandFree(cmd); + VIR_FREE(average); + VIR_FREE(peak); + VIR_FREE(burst); + return ret; +} + +/** + * virNetDevBandwidthClear: + * @ifname: on which interface + * + * This function tries to disable QoS on specified interface + * by deleting root and ingress qdisc. However, this may fail + * if we try to remove the default one. + * + * Return 0 on success, -1 otherwise. + */ +int +virNetDevBandwidthClear(const char *ifname) +{ + int ret = 0; + virCommandPtr cmd = NULL; + + cmd = virCommandNew(TC); + virCommandAddArgList(cmd, "qdisc", "del", "dev", ifname, "root", NULL); + + if (virCommandRun(cmd, NULL) < 0) + ret = -1; + + virCommandFree(cmd); + + cmd = virCommandNew(TC); + virCommandAddArgList(cmd, "qdisc", "del", "dev", ifname, "ingress", NULL); + + if (virCommandRun(cmd, NULL) < 0) + ret = -1; + virCommandFree(cmd); + + return ret; +} + +/* + * virNetDevBandwidthCopy: + * @dest: destination + * @src: source (may be NULL) + * + * Returns -1 on OOM error (which gets reported), + * 0 otherwise. + */ +int +virNetDevBandwidthCopy(virNetDevBandwidthPtr *dest, + const virNetDevBandwidthPtr src) +{ + int ret = -1; + + *dest = NULL; + if (!src) { + /* nothing to be copied */ + return 0; + } + + if (VIR_ALLOC(*dest) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (src->in) { + if (VIR_ALLOC((*dest)->in) < 0) { + virReportOOMError(); + goto cleanup; + } + memcpy((*dest)->in, src->in, sizeof(*src->in)); + } + + if (src->out) { + if (VIR_ALLOC((*dest)->out) < 0) { + virReportOOMError(); + VIR_FREE((*dest)->in); + goto cleanup; + } + memcpy((*dest)->out, src->out, sizeof(*src->out)); + } + + ret = 0; + +cleanup: + if (ret < 0) { + virNetDevBandwidthFree(*dest); + *dest = NULL; + } + return ret; +} + +bool +virNetDevBandwidthEqual(virNetDevBandwidthPtr a, + virNetDevBandwidthPtr b) +{ + if (!a && !b) + return true; + + if (!a || !b) + return false; + + /* in */ + if (a->in->average != b->in->average || + a->in->peak != b->in->peak || + a->in->burst != b->in->burst) + return false; + + /*out*/ + if (a->out->average != b->out->average || + a->out->peak != b->out->peak || + a->out->burst != b->out->burst) + return false; + + return true; +} diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h new file mode 100644 index 0000000000..58decffe9b --- /dev/null +++ b/src/util/virnetdevbandwidth.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Michal Privoznik + * Daniel P. Berrange + */ + +#ifndef __VIR_NETDEV_BANDWIDTH_H__ +# define __VIR_NETDEV_BANDWIDTH_H__ + +# include "internal.h" + +typedef struct _virNetDevBandwidthRate virNetDevBandwidthRate; +typedef virNetDevBandwidthRate *virNetDevBandwidthRatePtr; +struct _virNetDevBandwidthRate { + unsigned long long average; /* kbytes/s */ + unsigned long long peak; /* kbytes/s */ + unsigned long long burst; /* kbytes */ +}; + +typedef struct _virNetDevBandwidth virNetDevBandwidth; +typedef virNetDevBandwidth *virNetDevBandwidthPtr; +struct _virNetDevBandwidth { + virNetDevBandwidthRatePtr in, out; +}; + +void virNetDevBandwidthFree(virNetDevBandwidthPtr def); + +int virNetDevBandwidthSet(const char *ifname, virNetDevBandwidthPtr bandwidth) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virNetDevBandwidthClear(const char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virNetDevBandwidthCopy(virNetDevBandwidthPtr *dest, const virNetDevBandwidthPtr src) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + +bool virNetDevBandwidthEqual(virNetDevBandwidthPtr a, virNetDevBandwidthPtr b); + +#endif /* __VIR_NETDEV_BANDWIDTH_H__ */ diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c index 5c60925e4b..2ed53c6a88 100644 --- a/src/util/virnetdevtap.c +++ b/src/util/virnetdevtap.c @@ -30,6 +30,7 @@ #include "virterror_internal.h" #include "memory.h" #include "logging.h" +#include "util.h" #include #ifdef HAVE_NET_IF_H diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c new file mode 100644 index 0000000000..6aecd5268c --- /dev/null +++ b/src/util/virnetdevvportprofile.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Stefan Berger + * Daniel P. Berrange + */ + +#include + +#include "virnetdevvportprofile.h" + +bool +virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr b) +{ + /* NULL resistant */ + if (!a && !b) + return true; + + if (!a || !b) + return false; + + if (a->virtPortType != b->virtPortType) + return false; + + switch (a->virtPortType) { + case VIR_NETDEV_VPORT_PROFILE_NONE: + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBG: + if (a->u.virtPort8021Qbg.managerID != b->u.virtPort8021Qbg.managerID || + a->u.virtPort8021Qbg.typeID != b->u.virtPort8021Qbg.typeID || + a->u.virtPort8021Qbg.typeIDVersion != b->u.virtPort8021Qbg.typeIDVersion || + memcmp(a->u.virtPort8021Qbg.instanceID, b->u.virtPort8021Qbg.instanceID, VIR_UUID_BUFLEN) != 0) + return false; + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBH: + if (STRNEQ(a->u.virtPort8021Qbh.profileID, b->u.virtPort8021Qbh.profileID)) + return false; + break; + + default: + break; + } + + return true; +} diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h new file mode 100644 index 0000000000..36e8fd771c --- /dev/null +++ b/src/util/virnetdevvportprofile.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Stefan Berger + * Daniel P. Berrange + */ + +#ifndef __VIR_NETDEV_VPORT_PROFILE_H__ +# define __VIR_NETDEV_VPORT_PROFILE_H__ + +# include "internal.h" +# include "uuid.h" +# include "util.h" + +# define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX 40 + +enum virNetDevVPortProfile { + VIR_NETDEV_VPORT_PROFILE_NONE, + VIR_NETDEV_VPORT_PROFILE_8021QBG, + VIR_NETDEV_VPORT_PROFILE_8021QBH, + + VIR_NETDEV_VPORT_PROFILE_LAST, +}; + +VIR_ENUM_DECL(virNetDevVPort) + +/* profile data for macvtap (VEPA) */ +typedef struct _virNetDevVPortProfile virNetDevVPortProfile; +typedef virNetDevVPortProfile *virNetDevVPortProfilePtr; +struct _virNetDevVPortProfile { + enum virNetDevVPortProfile virtPortType; + union { + struct { + uint8_t managerID; + uint32_t typeID; /* 24 bit valid */ + uint8_t typeIDVersion; + unsigned char instanceID[VIR_UUID_BUFLEN]; + } virtPort8021Qbg; + struct { + char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX]; + } virtPort8021Qbh; + } u; +}; + + +bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, + virNetDevVPortProfilePtr b); + +#endif /* __VIR_NETDEV_VPORT_PROFILE_H__ */ diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c new file mode 100644 index 0000000000..5708e3da61 --- /dev/null +++ b/src/util/virsocketaddr.c @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Daniel Veillard + * Laine Stump + * Daniel P. Berrange + */ + +#include + +#include "virsocketaddr.h" +#include "virterror_internal.h" +#include "util.h" + +#include + +#define VIR_FROM_THIS VIR_FROM_NONE +#define virSocketError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +/* + * Helpers to extract the IP arrays from the virSocketAddrPtr + * That part is the less portable of the module + */ +typedef unsigned char virSocketAddrIPv4[4]; +typedef virSocketAddrIPv4 *virSocketAddrIPv4Ptr; +typedef unsigned short virSocketAddrIPv6[8]; +typedef virSocketAddrIPv6 *virSocketAddrIPv6Ptr; + +static int virSocketAddrGetIPv4Addr(virSocketAddrPtr addr, virSocketAddrIPv4Ptr tab) { + unsigned long val; + int i; + + if ((addr == NULL) || (tab == NULL) || (addr->data.stor.ss_family != AF_INET)) + return(-1); + + val = ntohl(addr->data.inet4.sin_addr.s_addr); + + for (i = 0;i < 4;i++) { + (*tab)[3 - i] = val & 0xFF; + val >>= 8; + } + + return(0); +} + +static int virSocketAddrGetIPv6Addr(virSocketAddrPtr addr, virSocketAddrIPv6Ptr tab) { + int i; + + if ((addr == NULL) || (tab == NULL) || (addr->data.stor.ss_family != AF_INET6)) + return(-1); + + for (i = 0;i < 8;i++) { + (*tab)[i] = ((addr->data.inet6.sin6_addr.s6_addr[2 * i] << 8) | + addr->data.inet6.sin6_addr.s6_addr[2 * i + 1]); + } + + return(0); +} + +/** + * virSocketAddrParse: + * @val: a numeric network address IPv4 or IPv6 + * @addr: where to store the return value, optional. + * @family: address family to pass down to getaddrinfo + * + * Mostly a wrapper for getaddrinfo() extracting the address storage + * from the numeric string like 1.2.3.4 or 2001:db8:85a3:0:0:8a2e:370:7334 + * + * Returns the length of the network address or -1 in case of error. + */ +int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) { + int len; + struct addrinfo hints; + struct addrinfo *res = NULL; + int err; + + if (val == NULL) { + virSocketError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_flags = AI_NUMERICHOST; + if ((err = getaddrinfo(val, NULL, &hints, &res)) != 0) { + virSocketError(VIR_ERR_SYSTEM_ERROR, + _("Cannot parse socket address '%s': %s"), + val, gai_strerror(err)); + return -1; + } + + if (res == NULL) { + virSocketError(VIR_ERR_SYSTEM_ERROR, + _("No socket addresses found for '%s'"), + val); + return -1; + } + + len = res->ai_addrlen; + if (addr != NULL) { + memcpy(&addr->data.stor, res->ai_addr, len); + addr->len = res->ai_addrlen; + } + + freeaddrinfo(res); + return(len); +} + +/* + * virSocketAddrParseIPv4: + * @val: an IPv4 numeric address + * @addr: the location to store the result + * + * Extract the address storage from an IPv4 numeric address + * + * Returns the length of the network address or -1 in case of error. + */ +int +virSocketAddrParseIPv4(virSocketAddrPtr addr, const char *val) { + return virSocketAddrParse(addr, val, AF_INET); +} + +/* + * virSocketAddrParseIPv6: + * @val: an IPv6 numeric address + * @addr: the location to store the result + * + * Extract the address storage from an IPv6 numeric address + * + * Returns the length of the network address or -1 in case of error. + */ +int +virSocketAddrParseIPv6(virSocketAddrPtr addr, const char *val) { + return virSocketAddrParse(addr, val, AF_INET6); +} + +/* + * virSocketAddrFormat: + * @addr: an initialized virSocketAddrPtr + * + * Returns a string representation of the given address + * Returns NULL on any error + * Caller must free the returned string + */ +char * +virSocketAddrFormat(virSocketAddrPtr addr) { + return virSocketAddrFormatFull(addr, false, NULL); +} + + +/* + * virSocketAddrFormatFull: + * @addr: an initialized virSocketAddrPtr + * @withService: if true, then service info is appended + * @separator: separator between hostname & service. + * + * Returns a string representation of the given address + * Returns NULL on any error + * Caller must free the returned string + */ +char * +virSocketAddrFormatFull(virSocketAddrPtr addr, + bool withService, + const char *separator) +{ + char host[NI_MAXHOST], port[NI_MAXSERV]; + char *addrstr; + int err; + + if (addr == NULL) { + virSocketError(VIR_ERR_INVALID_ARG, "%s", _("Missing address")); + return NULL; + } + + /* Short-circuit since getnameinfo doesn't work + * nicely for UNIX sockets */ + if (addr->data.sa.sa_family == AF_UNIX) { + if (withService) { + if (virAsprintf(&addrstr, "127.0.0.1%s0", + separator ? separator : ":") < 0) + goto no_memory; + } else { + if (!(addrstr = strdup("127.0.0.1"))) + goto no_memory; + } + return addrstr; + } + + if ((err = getnameinfo(&addr->data.sa, + addr->len, + host, sizeof(host), + port, sizeof(port), + NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { + virSocketError(VIR_ERR_SYSTEM_ERROR, + _("Cannot convert socket address to string: %s"), + gai_strerror(err)); + return NULL; + } + + if (withService) { + if (virAsprintf(&addrstr, "%s%s%s", host, separator, port) == -1) + goto no_memory; + } else { + if (!(addrstr = strdup(host))) + goto no_memory; + } + + return addrstr; + +no_memory: + virReportOOMError(); + return NULL; +} + + +/* + * virSocketAddrSetPort: + * @addr: an initialized virSocketAddrPtr + * @port: the port number to set + * + * Set the transport layer port of the given virtSocketAddr + * + * Returns 0 on success, -1 on failure + */ +int +virSocketAddrSetPort(virSocketAddrPtr addr, int port) { + if (addr == NULL) + return -1; + + port = htons(port); + + if(addr->data.stor.ss_family == AF_INET) { + addr->data.inet4.sin_port = port; + } + + else if(addr->data.stor.ss_family == AF_INET6) { + addr->data.inet6.sin6_port = port; + } + + else { + return -1; + } + + return 0; +} + +/* + * virSocketGetPort: + * @addr: an initialized virSocketAddrPtr + * + * Returns the transport layer port of the given virtSocketAddr + * Returns -1 if @addr is invalid + */ +int +virSocketAddrGetPort(virSocketAddrPtr addr) { + if (addr == NULL) + return -1; + + if(addr->data.stor.ss_family == AF_INET) { + return ntohs(addr->data.inet4.sin_port); + } + + else if(addr->data.stor.ss_family == AF_INET6) { + return ntohs(addr->data.inet6.sin6_port); + } + + return -1; +} + +/** + * virSocketAddrIsNetmask: + * @netmask: the netmask address + * + * Check that @netmask is a proper network mask + * + * Returns 0 in case of success and -1 in case of error + */ +int virSocketAddrIsNetmask(virSocketAddrPtr netmask) { + int n = virSocketAddrGetNumNetmaskBits(netmask); + if (n < 0) + return -1; + return 0; +} + +/** + * virSocketAddrMask: + * @addr: address that needs to be masked + * @netmask: the netmask address + * @network: where to store the result, can be same as @addr + * + * Mask off the host bits of @addr according to @netmask, turning it + * into a network address. + * + * Returns 0 in case of success, or -1 on error. + */ +int +virSocketAddrMask(const virSocketAddrPtr addr, + const virSocketAddrPtr netmask, + virSocketAddrPtr network) +{ + if (addr->data.stor.ss_family != netmask->data.stor.ss_family) { + network->data.stor.ss_family = AF_UNSPEC; + return -1; + } + + if (addr->data.stor.ss_family == AF_INET) { + network->data.inet4.sin_addr.s_addr + = (addr->data.inet4.sin_addr.s_addr + & netmask->data.inet4.sin_addr.s_addr); + network->data.inet4.sin_port = 0; + network->data.stor.ss_family = AF_INET; + network->len = addr->len; + return 0; + } + if (addr->data.stor.ss_family == AF_INET6) { + int ii; + for (ii = 0; ii < 16; ii++) { + network->data.inet6.sin6_addr.s6_addr[ii] + = (addr->data.inet6.sin6_addr.s6_addr[ii] + & netmask->data.inet6.sin6_addr.s6_addr[ii]); + } + network->data.inet6.sin6_port = 0; + network->data.stor.ss_family = AF_INET6; + network->len = addr->len; + return 0; + } + network->data.stor.ss_family = AF_UNSPEC; + return -1; +} + +/** + * virSocketAddrMaskByPrefix: + * @addr: address that needs to be masked + * @prefix: prefix (# of 1 bits) of netmask to apply + * @network: where to store the result, can be same as @addr + * + * Mask off the host bits of @addr according to @prefix, turning it + * into a network address. + * + * Returns 0 in case of success, or -1 on error. + */ +int +virSocketAddrMaskByPrefix(const virSocketAddrPtr addr, + unsigned int prefix, + virSocketAddrPtr network) +{ + virSocketAddr netmask; + + if (virSocketAddrPrefixToNetmask(prefix, &netmask, + addr->data.stor.ss_family) < 0) { + network->data.stor.ss_family = AF_UNSPEC; + return -1; + } + + return virSocketAddrMask(addr, &netmask, network); +} + +/** + * virSocketAddrBroadcast: + * @addr: address that needs to be turned into broadcast address (IPv4 only) + * @netmask: the netmask address + * @broadcast: virSocketAddr to recieve the broadcast address + * + * Mask ON the host bits of @addr according to @netmask, turning it + * into a broadcast address. + * + * Returns 0 in case of success, or -1 on error. + */ +int +virSocketAddrBroadcast(const virSocketAddrPtr addr, + const virSocketAddrPtr netmask, + virSocketAddrPtr broadcast) +{ + if ((addr->data.stor.ss_family != AF_INET) || + (netmask->data.stor.ss_family != AF_INET)) { + broadcast->data.stor.ss_family = AF_UNSPEC; + return -1; + } + + broadcast->data.stor.ss_family = AF_INET; + broadcast->len = addr->len; + broadcast->data.inet4.sin_addr.s_addr + = (addr->data.inet4.sin_addr.s_addr + | ~netmask->data.inet4.sin_addr.s_addr); + return 0; +} + +/** + * virSocketAddrBroadcastByPrefix: + * @addr: address that needs to be turned into broadcast address (IPv4 only) + * @prefix: prefix (# of 1 bits) of netmask to apply + * @broadcast: virSocketAddr to recieve the broadcast address + * + * Mask off the host bits of @addr according to @prefix, turning it + * into a network address. + * + * Returns 0 in case of success, or -1 on error. + */ +int +virSocketAddrBroadcastByPrefix(const virSocketAddrPtr addr, + unsigned int prefix, + virSocketAddrPtr broadcast) +{ + virSocketAddr netmask; + + if (virSocketAddrPrefixToNetmask(prefix, &netmask, + addr->data.stor.ss_family) < 0) + return -1; + + return virSocketAddrBroadcast(addr, &netmask, broadcast); +} + +/** + * virSocketCheckNetmask: + * @addr1: a first network address + * @addr2: a second network address + * @netmask: the netmask address + * + * Check that @addr1 and @addr2 pertain to the same @netmask address + * range and returns the size of the range + * + * Returns 1 in case of success and 0 in case of failure and + * -1 in case of error + */ +int virSocketAddrCheckNetmask(virSocketAddrPtr addr1, virSocketAddrPtr addr2, + virSocketAddrPtr netmask) { + int i; + + if ((addr1 == NULL) || (addr2 == NULL) || (netmask == NULL)) + return(-1); + if ((addr1->data.stor.ss_family != addr2->data.stor.ss_family) || + (addr1->data.stor.ss_family != netmask->data.stor.ss_family)) + return(-1); + + if (virSocketAddrIsNetmask(netmask) != 0) + return(-1); + + if (addr1->data.stor.ss_family == AF_INET) { + virSocketAddrIPv4 t1, t2, tm; + + if ((virSocketAddrGetIPv4Addr(addr1, &t1) < 0) || + (virSocketAddrGetIPv4Addr(addr2, &t2) < 0) || + (virSocketAddrGetIPv4Addr(netmask, &tm) < 0)) + return(-1); + + for (i = 0;i < 4;i++) { + if ((t1[i] & tm[i]) != (t2[i] & tm[i])) + return(0); + } + + } else if (addr1->data.stor.ss_family == AF_INET6) { + virSocketAddrIPv6 t1, t2, tm; + + if ((virSocketAddrGetIPv6Addr(addr1, &t1) < 0) || + (virSocketAddrGetIPv6Addr(addr2, &t2) < 0) || + (virSocketAddrGetIPv6Addr(netmask, &tm) < 0)) + return(-1); + + for (i = 0;i < 8;i++) { + if ((t1[i] & tm[i]) != (t2[i] & tm[i])) + return(0); + } + + } else { + return(-1); + } + return(1); +} + +/** + * virSocketGetRange: + * @start: start of an IP range + * @end: end of an IP range + * + * Check the order of the 2 addresses and compute the range, this + * will return 1 for identical addresses. Errors can come from incompatible + * addresses type, excessive range (>= 2^^16) where the two addresses are + * unrelated or inverted start and end. + * + * Returns the size of the range or -1 in case of failure + */ +int virSocketAddrGetRange(virSocketAddrPtr start, virSocketAddrPtr end) { + int ret = 0, i; + + if ((start == NULL) || (end == NULL)) + return(-1); + if (start->data.stor.ss_family != end->data.stor.ss_family) + return(-1); + + if (start->data.stor.ss_family == AF_INET) { + virSocketAddrIPv4 t1, t2; + + if ((virSocketAddrGetIPv4Addr(start, &t1) < 0) || + (virSocketAddrGetIPv4Addr(end, &t2) < 0)) + return(-1); + + for (i = 0;i < 2;i++) { + if (t1[i] != t2[i]) + return(-1); + } + ret = (t2[2] - t1[2]) * 256 + (t2[3] - t1[3]); + if (ret < 0) + return(-1); + ret++; + } else if (start->data.stor.ss_family == AF_INET6) { + virSocketAddrIPv6 t1, t2; + + if ((virSocketAddrGetIPv6Addr(start, &t1) < 0) || + (virSocketAddrGetIPv6Addr(end, &t2) < 0)) + return(-1); + + for (i = 0;i < 7;i++) { + if (t1[i] != t2[i]) + return(-1); + } + ret = t2[7] - t1[7]; + if (ret < 0) + return(-1); + ret++; + } else { + return(-1); + } + return(ret); +} + + +/** + * virSocketAddrGetNumNetmaskBits + * @netmask: the presumed netmask + * + * Get the number of netmask bits in a netmask. + * + * Returns the number of bits in the netmask or -1 if an error occurred + * or the netmask is invalid. + */ +int virSocketAddrGetNumNetmaskBits(const virSocketAddrPtr netmask) +{ + int i, j; + int c = 0; + + if (netmask->data.stor.ss_family == AF_INET) { + virSocketAddrIPv4 tm; + uint8_t bit; + + if (virSocketAddrGetIPv4Addr(netmask, &tm) < 0) + return -1; + + for (i = 0; i < 4; i++) + if (tm[i] == 0xff) + c += 8; + else + break; + + if (c == 8 * 4) + return c; + + j = i << 3; + while (j < (8 * 4)) { + bit = 1 << (7 - (j & 7)); + if ((tm[j >> 3] & bit)) { + c++; + } else + break; + j++; + } + + while (j < (8 * 4)) { + bit = 1 << (7 - (j & 7)); + if ((tm[j >> 3] & bit)) + return -1; + j++; + } + + return c; + } else if (netmask->data.stor.ss_family == AF_INET6) { + virSocketAddrIPv6 tm; + uint16_t bit; + + if (virSocketAddrGetIPv6Addr(netmask, &tm) < 0) + return -1; + + for (i = 0; i < 8; i++) + if (tm[i] == 0xffff) + c += 16; + else + break; + + if (c == 16 * 8) + return c; + + j = i << 4; + while (j < (16 * 8)) { + bit = 1 << (15 - (j & 0xf)); + if ((tm[j >> 4] & bit)) { + c++; + } else + break; + j++; + } + + while (j < (16 * 8)) { + bit = 1 << (15 - (j & 0xf)); + if ((tm[j >> 4]) & bit) + return -1; + j++; + } + + return c; + } + return -1; +} + +/** + * virSocketPrefixToNetmask: + * @prefix: number of 1 bits to put in the netmask + * @netmask: address to fill in with the desired netmask + * @family: family of the address (AF_INET or AF_INET6 only) + * + * given @prefix and @family, fill in @netmask with a netmask + * (eg 255.255.255.0). + * + * Returns 0 on success or -1 on error. + */ + +int +virSocketAddrPrefixToNetmask(unsigned int prefix, + virSocketAddrPtr netmask, + int family) +{ + int result = -1; + + netmask->data.stor.ss_family = AF_UNSPEC; /* assume failure */ + + if (family == AF_INET) { + int ip; + + if (prefix > 32) + goto error; + + ip = prefix ? ~((1 << (32 - prefix)) - 1) : 0; + netmask->data.inet4.sin_addr.s_addr = htonl(ip); + netmask->data.stor.ss_family = AF_INET; + result = 0; + + } else if (family == AF_INET6) { + int ii = 0; + + if (prefix > 128) + goto error; + + while (prefix >= 8) { + /* do as much as possible an entire byte at a time */ + netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0xff; + prefix -= 8; + } + if (prefix > 0) { + /* final partial byte */ + netmask->data.inet6.sin6_addr.s6_addr[ii++] + = ~((1 << (8 - prefix)) -1); + } + while (ii < 16) { + /* zerofill remainder in case it wasn't initialized */ + netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0; + } + netmask->data.stor.ss_family = AF_INET6; + result = 0; + } + +error: + return result; +} diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h new file mode 100644 index 0000000000..3af6fe56fb --- /dev/null +++ b/src/util/virsocketaddr.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * 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 + * + * Authors: + * Daniel Veillard + * Laine Stump + * Daniel P. Berrange + */ + +#ifndef __VIR_SOCKETADDR_H__ +# define __VIR_SOCKETADDR_H__ + +# include "internal.h" + +# include +# include +# ifdef HAVE_SYS_UN_H +# include +# endif + +typedef struct { + union { + struct sockaddr sa; + struct sockaddr_storage stor; + struct sockaddr_in inet4; + struct sockaddr_in6 inet6; +# ifdef HAVE_SYS_UN_H + struct sockaddr_un un; +# endif + } data; + socklen_t len; +} virSocketAddr; + +# define VIR_SOCKET_ADDR_VALID(s) \ + ((s)->data.sa.sa_family != AF_UNSPEC) + +# define VIR_SOCKET_ADDR_IS_FAMILY(s, f) \ + ((s)->data.sa.sa_family == f) + +# define VIR_SOCKET_ADDR_FAMILY(s) \ + ((s)->data.sa.sa_family) + +typedef virSocketAddr *virSocketAddrPtr; + +int virSocketAddrParse(virSocketAddrPtr addr, + const char *val, + int family); + +int virSocketAddrParseIPv4(virSocketAddrPtr addr, + const char *val); + +int virSocketAddrParseIPv6(virSocketAddrPtr addr, + const char *val); + +char * virSocketAddrFormat(virSocketAddrPtr addr); +char * virSocketAddrFormatFull(virSocketAddrPtr addr, + bool withService, + const char *separator); + +int virSocketAddrSetPort(virSocketAddrPtr addr, int port); + +int virSocketAddrGetPort(virSocketAddrPtr addr); + +int virSocketAddrGetRange(virSocketAddrPtr start, + virSocketAddrPtr end); + +int virSocketAddrIsNetmask(virSocketAddrPtr netmask); + +int virSocketAddrCheckNetmask(virSocketAddrPtr addr1, + virSocketAddrPtr addr2, + virSocketAddrPtr netmask); +int virSocketAddrMask(const virSocketAddrPtr addr, + const virSocketAddrPtr netmask, + virSocketAddrPtr network); +int virSocketAddrMaskByPrefix(const virSocketAddrPtr addr, + unsigned int prefix, + virSocketAddrPtr network); +int virSocketAddrBroadcast(const virSocketAddrPtr addr, + const virSocketAddrPtr netmask, + virSocketAddrPtr broadcast); +int virSocketAddrBroadcastByPrefix(const virSocketAddrPtr addr, + unsigned int prefix, + virSocketAddrPtr broadcast); + +int virSocketAddrGetNumNetmaskBits(const virSocketAddrPtr netmask); +int virSocketAddrPrefixToNetmask(unsigned int prefix, + virSocketAddrPtr netmask, + int family); + +#endif /* __VIR_SOCKETADDR_H__ */ diff --git a/tests/sockettest.c b/tests/sockettest.c index 69a2201981..bcc28008c8 100644 --- a/tests/sockettest.c +++ b/tests/sockettest.c @@ -25,7 +25,7 @@ #include #include -#include "network.h" +#include "virsocketaddr.h" #include "testutils.h" #include "logging.h" #include "memory.h" diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c index 506068168e..51f75b4d0c 100644 --- a/tests/virnettlscontexttest.c +++ b/tests/virnettlscontexttest.c @@ -33,7 +33,7 @@ #include "logging.h" #include "virfile.h" #include "command.h" -#include "network.h" +#include "virsocketaddr.h" #include "gnutls_1_0_compat.h" #if !defined WIN32 && HAVE_LIBTASN1_H && !defined GNUTLS_1_0_COMPAT diff --git a/tools/virsh.c b/tools/virsh.c index 83dc3c7e1e..af80e4b30f 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -59,7 +59,7 @@ #include "threads.h" #include "command.h" #include "virkeycode.h" -#include "network.h" +#include "virnetdevbandwidth.h" static char *progname;