Commit Graph

720 Commits

Author SHA1 Message Date
Laine Stump
e4be156889 network: explicitly set the MTU of the bridge device.
In the past, the MTU of libvirt virtual network bridge devices was
implicitly set by setting the MTU of the "dummy tap device" (which was
being added in order to force a particular MAC address from the
bridge). But the dummy tap device was removed in commit ee6c936fbb
(libvirt-6.8.0), and so the mtu setting in the network is ignored.

The solution is, of course, to explicitly set the bridge device MTU
when it is created.

Note that any guest interface with a larger MTU that is attached will
cause the bridge to (temporarily) assume the larger MTU, but it will
revert to the bridge's own MTU when that device is deleted (this is
not due to anything libvirt does; it's just how Linux host bridges
work).

Fixes: ee6c936fbb
Resolves: https://bugzilla.redhat.com/1913561
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2021-01-15 12:20:00 -05:00
Michal Privoznik
ea0cfa1153 network: Introduce mutex for bridge name generation
When defining/creating a network the bridge name may be filled in
automatically by libvirt (if none provided in the input XML or
the one provided is a pattern, e.g. "virbr%d"). During the
bridge name generation process a candidate name is generated
which is then checked with the rest of already defined/running
networks for collisions.

Problem is, that there is no mutex guarding this critical section
and thus if two threads line up so that they both generate the
same candidate they won't find any collision and the same name is
then stored.

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/78
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
2021-01-07 20:26:08 +01:00
Michal Privoznik
b304207f58 networkGetDHCPLeases: Don't assign @ipdef_tmp twice
When rewriting the function, I've mistakenly declared a variable
and assigned it to itself. Let's initialize the variable properly.

Fixes: 5fb6d98c88
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2021-01-05 12:54:40 +01:00
Michal Privoznik
5dd53684e1 networkGetDHCPLeases: Handle leases with infinite expiry time
After v6.3.0-rc1~64 a lease can have infinite expiry time. This
means that the expiration time will appear as a value of zero.
Do the expiration check only if the expiration time is not zero.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1908053
Fixes: 97a0aa2467
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2021-01-04 15:33:31 +01:00
Michal Privoznik
5fb6d98c88 network: Rework networkGetDHCPLeases()
Firstly, bring variables that are used only within loops into
their respective loops. Secondly, drop 'error' label which is
redundant since we have @rv which holds the return value.
Thirdly, fix indendation in one case, the rest is indented
properly.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2021-01-04 15:33:31 +01:00
Michal Privoznik
ee93656c40 networkGetDHCPLeases: Use VIR_APPEND_ELEMENT() instead of VIR_INSERT_ELEMENT()
This function is misusing VIR_INSERT_ELEMENT() to behave like
VIR_APPEND_ELEMENT(). Use the latter to make it explicit what we
are trying to achieve.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2021-01-04 15:33:31 +01:00
Michal Privoznik
9c65363a40 network: Drop @custom_lease_file_len variable from networkGetDHCPLeases()
We don't need to track the lease file size. Instead, we can
simply check if the file was empty by comparing the buffer the
file was read into with an empty string.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2021-01-04 15:33:31 +01:00
Michal Privoznik
c14bd64f3e leaseshelper: Report errors on failure
If leasehelper fails all that we are left with is a simple error
message produced by dnsmasq:

  lease-init script returned exit code 1

This is because the leasehelper did not write any message to
stderr. According to dnsmasq's manpage, whenever it's invoking
leasehelper the stderr is kept open:

  All file descriptors are closed except stdin, which is open to
  /dev/null, and stdout and stderr which capture output for
  logging by dnsmasq.

As debugging leasehelper is not trivial (because dnsmasq invokes
it with plenty of env vars set - that's how data is passed onto
helper), let's print an error into stderr if exiting with an
error. And since we are not calling public APIs, we have to call
virDispatchError() explicitly and since we don't have any
connection open, we have to pass NULL.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2021-01-04 15:33:30 +01:00
Laine Stump
c102bbd3ef network: be more verbose about the reason for a firewall reload
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2020-11-24 14:21:47 -05:00
Andrea Bolognani
6e8f28dc25 network: Drop UUID handling for default network
We are generating a fresh UUID and storing it in the XML for the
default network, but this is unnecessary because the network
driver will automatically generate one if it's missing from the
XML; the fact that we only do this if the uuidgen command happens
to be available on the build machine is further proof that we can
safely skip this step.

This patch is best viewed with 'git show -w'.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
2020-11-20 11:44:05 +01:00
Pavel Hrdina
0887a7afc5 src/network/bridge_driver: convert to use GLib DBus
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2020-09-17 18:20:07 +02:00
Laine Stump
362cab1d53 network: don't wait for IPv6 DAD completion when starting a network
0f7436ca54 added code during virtual network startup to wait for DAD
(Duplicate Address Detection) to complete if there were any IPv6
addresses on the network. This wait was needed because (according to
the commit log) "created problems when [the "dummy" tap device] is set
to IFF_DOWN prior to DAD completing".

That commit in turn referenced commit db488c7917, which had added the
code to set the dummy tap device IFF_DOWN, commenting "DAD has
happened (dnsmasq waits for it)", and in its commit message pointed
out that if we just got rid of the dummy tap device this wouldn't be
needed.

Now that the dummy tap device has indeed been removed (commit
ee6c936fbb), there is no longer any need to set it IFF_DOWN, and thus
nothing requiring us to wait for DAD to complete. At any rate, with
the dummy tap device removed, leaving nothing else on the bridge when
it is first started, DAD never completes, leading to failure to start
any IPv6 network.

So, yes, this patch removes the wait for DAD completion, and IPv6
networks can once again start, and their associated dnsmasq process
starts successfully (this is the problem that the DAD wait was
originally intended to fix)

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-09-10 11:41:08 -04:00
Daniel P. Berrangé
ee6c936fbb network: drop use of dummy tap device in bridges
A long time ago we introduced a dummy tap device (e.g. virbr0-nic) that
we attached to the bridge device created for virtual networks:

  commit 5754dbd56d
  Author: Laine Stump <laine@redhat.com>
  Date:   Wed Feb 9 03:28:12 2011 -0500

    Give each virtual network bridge its own fixed MAC address

This was a hack to workaround a Linux kernel bug where it would not
honour any attempt to set a MAC address on a bridge. Instead the
bridge would adopt the numerically lowest MAC address of all NICs
attached to the bridge. This lead to the MAC addrss of the bridge
changing over time as NICs were attached/detached.

The Linux bug was actually fixed 3 years before the libvirt
workaround was added in:

  commit 92c0574f11598c8036f81e27d2e8bdd6eed7d76d
  Author: Stephen Hemminger <shemminger@vyatta.com>
  Date:   Tue Jun 17 16:10:06 2008 -0700

    bridge: make bridge address settings sticky

    Normally, the bridge just chooses the smallest mac address as the
    bridge id and mac address of bridge device. But if the administrator
    has explictly set the interface address then don't change it.

    Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

but libvirt needed to support RHEL-5 kernels at that time, so
none the less added the workaround.

We have long since dropped support for RHEL-5 vintage distros,
so there's no reason to keep the dummy tap device for the purpose
of setting the bridge MAC address.

Later the dummy TAP device was used for a second purpose related
to IPv6 DAD (Duplicate Address Detection) in:

  commit db488c7917
  Author: Benjamin Cama <benoar@dolka.fr>
  Date:   Wed Sep 26 21:02:20 2012 +0200

    network: fix dnsmasq/radvd binding to IPv6 on recent kernels

This was again dealing with a regression in the Linux kernel, where
if there were no devices attached to the bridge in the UP state,
IPv6 DAD would not be performed. The virbr0-nic was attached but
in the DOWN state, so the above libvirt fix tenporarily brought
the NIC online. The Linux commit causing the problem was in v2.6.38

  commit 1faa4356a3bd89ea11fb92752d897cff3a20ec0e
  Author: stephen hemminger <shemminger@vyatta.com>
  Date:   Mon Mar 7 08:34:06 2011 +0000

    bridge: control carrier based on ports online

A short while later Linux was tweaked so that DAD would still occur
if the bridge had no attached devices at all in 3.1:

  commit b64b73d7d0c480f75684519c6134e79d50c1b341
  Author: stephen hemminger <shemminger@vyatta.com>
  Date:   Mon Oct 3 18:14:45 2011 +0000

    bridge: leave carrier on for empty bridge

IOW, the only reason we need the DAD hack of bringing virbr0-nic
online is because virbr0-nic exists. Once it doesn't exist, then
we hit the "empty bridge" case which works in Linux.

We can rely on distros having Linux kernel >= 3.1, so both things
that the virbr0-nic are doing are redundant.

Fixes https://gitlab.com/libvirt/libvirt/-/issues/53
Reviewed-by: Laine Stump <laine@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2020-09-04 17:17:30 +01:00
Michal Privoznik
95b9db4ee2 lib: Prefer WITH_* prefix for #if conditionals
Currently, we are mixing: #if HAVE_BLAH with #if WITH_BLAH.
Things got way better with Pavel's work on meson, but apparently,
mixing these two lead to confusing and easy to miss bugs (see
31fb929eca for instance). While we were forced to use HAVE_
prefix with autotools, we are free to chose our own prefix with
meson and since WITH_ prefix appears to be more popular let's use
it everywhere.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-09-02 10:28:10 +02:00
Andrea Bolognani
88c3490aa1 meson: Use @BASENAME@ more
This patch takes care of just the obvious cases: there are
many more situations where the data we pass to configure_file()
could likely be obtained in a more effective way, but we can
address the low-hanging fruits as a first approximation.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2020-09-01 13:22:24 +02:00
Andrea Bolognani
2b9e277106 network: Use single quotes in default network configuration
Whenever libvirt is upgraded on a Debian system, the user will be
prompted along the lines of

  Configuration file '/etc/libvirt/qemu/networks/default.xml'
   ==> Modified (by you or by a script) since installation.
   ==> Package distributor has shipped an updated version.
     What would you like to do about it ?  Your options are:
      Y or I  : install the package maintainer's version
      N or O  : keep your currently-installed version
        D     : show the differences between the versions
        Z     : start a shell to examine the situation
   The default action is to keep your current version.
  *** default.xml (Y/I/N/O/D/Z) [default=N] ? d
  --- /etc/libvirt/qemu/networks/default.xml      2020-08-04 12:57:25.450911143 +0200
  +++ /etc/libvirt/qemu/networks/default.xml.dpkg-new     2020-08-03 22:47:15.000000000 +0200
  @@ -1,19 +1,11 @@
  -<!--
  -WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
  -OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
  -  virsh net-edit default
  -or other application using the libvirt API.
  --->
  -
   <network>
     <name>default</name>
  -  <uuid>612a2cab-72fb-416d-92bc-4d9e597bfb63</uuid>
  -  <forward mode='nat'/>
  -  <bridge name='virbr0' stp='on' delay='0'/>
  -  <mac address='52:54:00:1f:03:79'/>
  -  <ip address='192.168.122.1' netmask='255.255.255.0'>
  +  <uuid>d020b839-4379-492c-aa74-eab7365076e6</uuid>
  +  <bridge name="virbr0"/>
  +  <forward/>
  +  <ip address="192.168.122.1" netmask="255.255.255.0">
       <dhcp>
  -      <range start='192.168.122.2' end='192.168.122.254'/>
  +      <range start="192.168.122.2" end="192.168.122.254"/>
       </dhcp>
     </ip>
   </network>

The UUID situation should probably be handled the same way it is
in the spec file by stripping it, and in general we could behave
much better towards users, but one part of the diff that
immediately stands out is that some lines are highlighted not
because they are semantically different, but simply because they
use different types of quotes around attributes.

Since the canonical version of all libvirt XML documents (as
returned by the various vir*GetXMLDesc() APIs) as well as the
on-disk representations use single quotes, let's use the same
for configuration files we install as well.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2020-08-04 15:12:18 +02:00
Pavel Hrdina
dc6a76f32e meson: src: add check-aclrules test
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
adf59b27a2 meson: src: add check-driverimpls test
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
7f1e2fa7a6 meson: src/network: install firewalld zone file
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
c957791859 meson: src/network: install default network xml
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
c6193d9ee9 meson: src: install empty directories
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
3d1bd8e8bb meson: src: install libvirt daemon sysconf files
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
25ab77a197 meson: src: generate openrc init files
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
dd4f2c73ad meson: src: generate systemd unit files for libvirt daemons
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
5740e1789e meson: src: generate libvirt daemon conf and augeas files
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
dab71cfe98 meson: src: build libvirt_leaseshelper binary
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
4f0527653f meson: src: build virtnetworkd daemon binary
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:05 +02:00
Pavel Hrdina
141e017519 meson: src: build libvirt_driver_network.so shared module
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:04 +02:00
Pavel Hrdina
412afa5cc1 meson: src: build libvirt_driver_network_impl.a static library
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:27:04 +02:00
Pavel Hrdina
179797ee05 meson: build everything with PIE
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:26:39 +02:00
Pavel Hrdina
b63c979fc9 meson: remove automake specific directives
EXTRA_DIST is not relevant because meson makes a git copy when creating
dist archive so everything tracked by git is part of dist tarball.

The remaining ones are not converted to meson files as they are
automatically tracked by meson.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
2020-08-03 09:26:25 +02:00
Ján Tomko
5c50d1dda5 network: split out networkSetIPv6Sysctl
Refactor networkSetIPv6Sysctls to remove repetition and reuse
of the 'field' variable.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
2020-07-21 14:55:00 +02:00
Laine Stump
cab4a682de network: use g_free() in place of remaining VIR_FREE()
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-20 19:11:39 -04:00
Laine Stump
f931c85fb0 network: eliminate unnecessary labels
All these cleanup/error labels were reduced to having just "return
ret" by a previous patch, so get rid of them and return directly.

This patch coincidentally fixes a bug in
networkFindUnusedBridgeName(), where we would log an error yet still
return success if we failed to find a single unused "virbrNNN" name
after checking all values of "N" from 0 - 256. Said bug was introduced
when that function was originally written, in commit a28d3e485f
(libvirt 1.2.15, 2015)

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-20 19:11:35 -04:00
Laine Stump
b32b2746ad network: use g_auto wherever appropriate
This includes standard g_autofree() as well as other objects that have
a cleanup function defined to use via g_autoptr (virCommand,
virJSONValue)

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-20 19:08:39 -04:00
Laine Stump
9f51c3d6c0 network: replace VIR_ALLOC/REALLOC with g_new0/g_renew
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-20 19:08:07 -04:00
Laine Stump
310ce7cf7e eliminate unnecessary labels and ret variables
after making all virFirewall objects use g_autoptr().

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-08 16:36:22 -04:00
Laine Stump
cf1ec5daac use g_autoptr() for all usages of virFirewallNew/Free
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-08 16:36:19 -04:00
Laine Stump
8d591eb167 network: eliminate unnecessary labels
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-08 16:36:02 -04:00
Laine Stump
453316e8bc network: use g_auto() for all virBuffers
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-08 16:34:49 -04:00
Laine Stump
ab9fd53823 network: use proper arg type when calling virNetDevSetOnline()
The 2nd arg to this function is a bool, not an int.

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-04 23:54:28 -04:00
Laine Stump
e95dd7aacd network: make networkDnsmasqXmlNsDef private to bridge_driver.c
This struct isn't used anywhere else.

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-04 23:53:48 -04:00
Laine Stump
9ceb3cff85 network: fix memory leak in networkBuildDhcpDaemonCommandLine()
hostsfilestr was not being freed. This will be turned into g_autofree
in an upcoming patch converting a lot more of the same file to using
g_auto*, but I wanted to make a separate patch for this first so the
other patch is simpler to review (and to make backporting easier).

The leak was introduced in commit 97a0aa2467

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2020-07-04 23:52:34 -04:00
Michal Privoznik
9ed345ac1a leaseshelper: Report more errors
Some functions or code paths that may fail don't report error
(e.g. when acquiring PID file fails) leading to a silent quit
of the leaseshelper. This makes it super hard for us and users
to debug what is happening. Fortunately, dnsmasq captures both
stdout and stderr so we can write an error message there.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2020-06-24 16:08:03 +02:00
Michal Privoznik
876211ef4a leaseshelper: Wait to acquire PID file
On a DHCP transaction, dnsmasq runs our leases helper which
updates corresponding JSON files. While one dnsmasq won't run the
leaseshelper in parallel, two dnsmasqs (from two distinct
networks) might. To avoid corrupting JSON file, the leaseshelper
acquires PID file first. Well, the way it's acquiring it is not
ideal - it calls virPidFileAcquirePath(wait = false); which
means, that either it acquires the PID file instantly or returns
an error and does not touch the JSON at all. This in turn means
that there might be a leases record missing. With wait = true,
this won't happen.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1840307

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2020-06-24 16:08:03 +02:00
Daniel P. Berrangé
8a4f331e8c network: wire up support for IPv6 NAT rules
Now that we have support for IPv6 in the iptables helpers, and a new
option in the XML schema, we can wire up support for it in the network
driver.

Reviewed-by: Laine Stump <laine@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2020-06-15 17:10:15 +01:00
Laine Stump
2f82fe467f network: add private chains only if there are networks adding iptables rules
Juan Quintela noticed that when he restarted libvirt he was getting
extra iptables rules added by libvirt even though he didn't have any
libvirt networks that used iptables rules. It turns out this also
happens if the firewalld service is restarted. The extra rules are
just the private chains, and they're sometimes being added
unnecessarily because they are added separately in a global
networkPreReloadFirewallRules() that does the init if there are any
active networks, regardless of whether or not any of those networks
will actually add rules to the host firewall.

The fix is to change the check for "any active networks" to instead
check for "any active networks that add firewall rules".

(NB: although the timing seems suspicious, this isn't a new regression
caused by the recently pushed f5418b427 (which forces recreation of
private chains when firewalld is restarted); it was an existing bug
since iptables rules were first put into private chains, even after
commit c6cbe18771 delayed creation of the private chains. The
implication is that any downstream based on v5.1.0 or later that cares
about these extraneous (but harmless) private chains would want to
backport this patch (along with the other two if they aren't already
there))

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2020-06-08 23:06:36 -04:00
Laine Stump
f5418b427e network: force re-creation of iptables private chains on firewalld restart
When firewalld is stopped, it removes *all* iptables rules and chains,
including those added by libvirt. Since restarting firewalld means
stopping and then starting it, any time it is restarted, libvirt needs
to recreate all the private iptables chains it uses, along with all
the rules it adds.

We already have code in place to call networkReloadFirewallRules() any
time we're notified of a firewalld start, and
networkReloadFirewallRules() will call
networkPreReloadFirewallRules(), which calls
networkSetupPrivateChains(); unfortunately that last call is called
using virOnce(), meaning that it will only be called the first time
through networkPreReloadFirewallRules() after libvirtd starts - so of
course when firewalld is later restarted, the call to
networkSetupPrivateChains() is skipped.

The neat and tidy way to fix this would be if there was a standard way
to reset a pthread_once_t object so that the next time virOnce was
called, it would think the function hadn't been called, and call it
again. Unfortunately, there isn't any official way of doing that (we
*could* just fill it with 0 and hope for the best, but that doesn't
seem very safe.

So instead, this patch just adds a static variable called
chainInitDone, which is set to true after networkSetupPrivateChains()
is called for the first time, and then during calls to
networkPreReloadFirewallRules(), if chainInitDone is set, we call
networkSetupPrivateChains() directly instead of via virOnce().

It may seem unsafe to directly call a function that is meant to be
called only once, but I think in this case we're safe - there's
nothing in the function that is inherently "once only" - it doesn't
initialize anything that can't safely be re-initialized (as long as
two threads don't try to do it at the same time), and it only happens
when responding to a dbus message that firewalld has been started (and
I don't think it's possible for us to be processing two of those at
once), and even then only if the initial call to the function has
already been completed (so we're safe if we receive a firewalld
restart call at a time when we haven't yet called it, or even if
another thread is already in the process of executing it. The only
problematic bit I can think of is if another thread is in the process
of adding an iptable rule at the time we're executing this function,
but 1) none of those threads will be trying to add chains, and 2) if
there was a concurrency problem with other threads adding iptables
rules while firewalld was being restarted, it would still be a problem
even without this change.

This is yet another patch that fixes an occurrence of this error:

COMMAND_FAILED: '/usr/sbin/iptables -w10 -w --table filter --insert LIBVIRT_INP --in-interface virbr0 --protocol tcp --destination-port 67 --jump ACCEPT' failed: iptables: No chain/target/match by that name.

In particular, this resolves: https://bugzilla.redhat.com/1813830

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2020-05-11 22:54:52 -04:00
Laine Stump
de110f110f network: make it safe to call networkSetupPrivateChains() multiple times
networkSetupPrivateChains() is currently called only once per run of
libvirtd, so it can assume that errInitV4 and errInitV6 are empty/null
when it is called. In preparation for potentially calling this
function multiple times during one run, this patch moves the reset of
errInitV[46] to the top of the function, to assure no memory is
leaked.

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2020-05-11 22:53:36 -04:00
Laine Stump
0756415f14 systemd: start libvirtd after firewalld/iptables services
When a system has enabled the iptables/ip6tables services rather than
firewalld, there is no explicit ordering of the start of those
services vs. libvirtd. This creates a problem when libvirtd.service is
started before ip[6]tables, as the latter, when it finally is started,
will remove all of the iptables rules that had previously been added
by libvirt, including the custom chains where libvirt's rules are
kept. This results in an error message similar to the following when a
user subsequently tries to start a new libvirt network:

 "Error while activating network: Call to virNetworkCreate failed:
 internal error: Failed to apply firewall rules
 /usr/sbin/ip6tables -w --table filter --insert LIBVIRT_FWO \
   --in-interface virbr2 --jump REJECT:
 ip6tables: No chain/target/match by that name."

(Prior to logging this error, it also would have caused failure to
forward (or block) traffic in some cases, e.g. for guests on a NATed
network, since libvirt's rules to forward/block had all been deleted
and libvirt didn't know about it, so it couldn't fix the problem)

When this happens, the problem can be remedied by simply restarting
libvirtd.service (which has the side-effect of reloading all
libvirt-generated firewall rules)

Instead, we can just explicitly stating in the libvirtd.service file
that libvirtd.service should start after ip6tables.service and
ip6tables.service, eliminating the race condition that leads to the
error.

There is also nothing (that I can see) in the systemd .service files
to guarantee that firewalld.service will be started (if enabled) prior
to libvirtd.service. The same error scenario given above would occur
if libvirtd.service started before firewalld.service.  Even before
that, though libvirtd would have detected that firewalld.service was
disabled, and then turn off all firewalld support. So, for example,
firewalld's libvirt zone wouldn't be used, and most likely traffic
from guests would therefore be blocked (all with no external
indication of the source of the problem other than a debug-level log
when libvirtd was started saying that firewalld wasn't in use); also
libvirtd wouldn't notice when firewalld reloaded its rules (which also
simultaneously deletes all of libvirt's rules).

I'm not aware of any reports that have been traced back to
libvirtd.service starting before firewalld.service, but have seen that
error reported multiple times, and also don't see an existing
dependency that would guarantee firewalld.service starts before
libvirtd.service, so it's possible it's been happening and we just
haven't gotten to the bottom of it.

This patch adds an After= line to the libvirtd.service file for each
of iptables.service, ip6tables.service, and firewalld.servicee, which
should guarantee that libvirtd.service isn't started until systemd has
started whichever of the others is enabled.

This race was diagnosed, and patch proposed, by Jason Montleon in
https://bugzilla.redhat.com/1723698 . At the time (April 2019) danpb
agreed with him that this change to libvirtd.service was a reasonable
thing to do, but I guess everyone thought someone else was going to
post a patch, so in the end nobody did.

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2020-05-05 20:16:02 -04:00