>From 7fc635f4234963abad95b66f29bcaa7d02d78de2 Mon Sep 17 00:00:00 2001
From: Laine Stump <laine@laine.org>
Date: Fri, 30 Mar 2012 10:13:37 -0400
Subject: [PATCH] qemu: add audit logs when switching bridges

This adds in a standard audit log for detaching and attaching a
network device when the bridge being used is changed.

All *attempts* to detach or attach a tap to a bridge are logged, along
with whether or not they are successful.

The discussion about this led to the idea that the audit logs being
generated are insufficient, since they don't say anything about which
tap device is used, nor about which bridge it is attached to, but that
should be fixed by a separate patch, and this gets the current patch
properly wired into the infrastructure.
---
 src/qemu/qemu_hotplug.c |   36 ++++++++++++++++++++++++------------
 1 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index ce7921c..80b53d7 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1194,11 +1194,13 @@ static virDomainNetDefPtr qemuDomainFindNet(virDomainObjPtr vm,
 }
 
 static
-int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev,
+int qemuDomainChangeNetBridge(virDomainObjPtr vm,
+                              virDomainNetDefPtr olddev,
                               virDomainNetDefPtr newdev)
 {
-    const char *oldbridge = olddev->data.bridge.brname;
-    const char *newbridge = newdev->data.bridge.brname;
+    int ret = -1;
+    char *oldbridge = olddev->data.bridge.brname;
+    char *newbridge = newdev->data.bridge.brname;
 
     VIR_DEBUG("Change bridge for interface %s: %s -> %s",
               olddev->ifname, oldbridge, newbridge);
@@ -1209,20 +1211,31 @@ int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev,
         return -1;
     }
 
-    if (oldbridge &&
-        virNetDevBridgeRemovePort(oldbridge, olddev->ifname) < 0) {
-        return -1;
+    if (oldbridge) {
+        ret = virNetDevBridgeRemovePort(oldbridge, olddev->ifname);
+        virDomainAuditNet(vm, olddev, NULL, "detach", ret == 0);
+        if (ret < 0)
+            return ret;
     }
-    if (virNetDevBridgeAddPort(newbridge, olddev->ifname) < 0) {
-        if (virNetDevBridgeAddPort(oldbridge, olddev->ifname) < 0) {
+
+    /* move newbridge into olddev now so Audit log is correct */
+    olddev->data.bridge.brname = newbridge;
+    ret = virNetDevBridgeAddPort(newbridge, olddev->ifname);
+    virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
+    if (ret < 0) {
+        /* restore oldbridge to olddev */
+        olddev->data.bridge.brname = oldbridge;
+        ret = virNetDevBridgeAddPort(oldbridge, olddev->ifname);
+        virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
+        if (ret < 0) {
             qemuReportError(VIR_ERR_OPERATION_FAILED,
                             _("unable to recover former state by adding port"
                               "to bridge %s"), oldbridge);
         }
         return -1;
     }
-    VIR_FREE(olddev->data.bridge.brname);
-    olddev->data.bridge.brname = newdev->data.bridge.brname;
+    /* oldbridge no longer needed, and newbridge moved to olddev */
+    VIR_FREE(oldbridge);
     newdev->data.bridge.brname = NULL;
     return 0;
 }
@@ -1368,10 +1381,9 @@ int qemuDomainChangeNet(struct qemud_driver *driver,
     }
 
     if (olddev->type == VIR_DOMAIN_NET_TYPE_BRIDGE
-        && dev->type == VIR_DOMAIN_NET_TYPE_BRIDGE
         && STRNEQ_NULLABLE(olddev->data.bridge.brname,
                            dev->data.bridge.brname)) {
-        if ((ret = qemuDomainChangeNetBridge(olddev, dev)) < 0)
+        if ((ret = qemuDomainChangeNetBridge(vm, olddev, dev)) < 0)
             return ret;
     }
 
-- 
1.7.7.6

