>From b26c5abbed4756b1c89f749a2844e15202968189 Mon Sep 17 00:00:00 2001
From: Laine Stump <laine@laine.org>
Date: Mon, 13 May 2013 15:26:43 -0400
Subject: [PATCH] squash into network route patches

---
 docs/formatnetwork.html.in | 61 +++++++++++++++++++++------------------
 src/conf/network_conf.c    | 71 ++++++++++++++++++++++++++++------------------
 src/util/virnetdev.c       |  2 +-
 3 files changed, 79 insertions(+), 55 deletions(-)

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 4c7e74f..a1198ce 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -548,25 +548,25 @@
 
     <h5><a name="elementsStaticroute">Static Routes</a></h5>
     <p>
-      Static route definitions are used to provide routing
-      information to the virtualization host for networks which are not
-      defined as a network on one of the virtual bridges so that such
-      networks can be reachable from the virtualization
-      host <span class="since">Since 1.0.6</span>.
+      Static route definitions are used to provide routing information
+      to the virtualization host for networks which are not directly
+      reachable from the virtualization host, but *are* reachable from
+      a guest domain that is itself reachable from the
+      host <span class="since">since 1.0.6</span>.
     </p>
 
     <p>
-      As shown in <a href="formatnetwork.html#examplesNoGateway">this example</a>,
-      it is possible to define a virtual bridge interface with no
-      IPv4 or IPv6 networks.  Such interfaces are useful in supporting
-      networks which have no visibility or direct connectivity with the
-      virtualization host, but can be used to support
-      virtual networks which only have guest connectivity.  A guest
-      with connectivity to the guest-only network and another network
-      that is directly reachable from the host can act as a gateway between the
-      networks.  A static route added to the "visible" network definition
-      provides the routing information so that IP packets can be sent
-      from the virtualization host to guests on the hidden network.
+      As shown in <a href="formatnetwork.html#examplesNoGateway">this
+      example</a>, it is possible to define a virtual network
+      interface with no IPv4 or IPv6 addresses.  Such networks are
+      useful to provide host connectivity to networks which are only
+      reachable via a guest.  A guest with connectivity both to the
+      guest-only network and to another network that is directly
+      reachable from the host can act as a gateway between the
+      networks.  A static route added to the "host-visible" network
+      definition provides the routing information so that IP packets
+      can be sent from the virtualization host to guests on the hidden
+      network.
     </p>
 
     <p>
@@ -576,9 +576,15 @@
       <code>gateway</code> gateway address specifications.  Note
       that the third static route specification includes the
       <code>metric</code> attribute specification with a value of 2.
-      This indicates that this particular definition is overriding another
-      route definition with the same address and prefix but with a lower
-      value for the metric.
+      This particular route would *not* be preferred if there was
+      another existing rout on the system with the same address and
+      prefix but with a lower value for the metric. If there is a
+      route in the host system configuration that should be overriden
+      by a route in a virtual network whenever the virtual network is
+      running, the configuration for the system-defined route should
+      be modified to have a higher metric, and the route on the
+      virtual network given a lower metric (for example, the default
+      metric of "1").
     </p>
 
     <pre>
@@ -878,14 +884,15 @@
       &lt;/network&gt;</pre>
 
     <p>
-      Below is yet another IPv6 variation.  This variation has only IPv6
-      defined with DHCPv6 on the primary IPv6 network.  A static link
-      if defined for a second IPv6 network which will not be visable on
-      the bridge interface but will have a static route defined for this
-      network via the specified gateway. Note that the gateway address
-      must be directly reachable via (on the same subnet as) one of the
-      &lt;ip&gt; addresses defined for this &lt;network&gt;.
-      <span class="since">Since 1.0.5</span>
+      Below is yet another IPv6 variation.  This variation has only
+      IPv6 defined with DHCPv6 on the primary IPv6 network.  A static
+      link if defined for a second IPv6 network which will not be
+      directly visible on the bridge interface but there will be a
+      static route defined for this network via the specified
+      gateway. Note that the gateway address must be directly
+      reachable via (on the same subnet as) one of the &lt;ip&gt;
+      addresses defined for this &lt;network&gt;.
+      <span class="since">Since 1.0.6</span>
     </p>
 
     <pre>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index b996fbe..eb10c0a 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1325,7 +1325,16 @@ virNetworkRouteDefParseXML(const char *networkName,
                        networkName);
         goto cleanup;
     }
-    def->has_metric = (metricRc == 0);
+    if (metricRc == 0) {
+        def->has_metric = true;
+        if (metric == 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid metric value, must be > 0 "
+                             "in route definition of network '%s'"),
+                           networkName);
+            goto cleanup;
+        }
+    }
     def->metric = metric;
 
     /* Note: both network and gateway addresses must be specified */
@@ -1366,18 +1375,22 @@ virNetworkRouteDefParseXML(const char *networkName,
     if ((def->family == NULL) || (STREQ(def->family, "ipv4"))) {
         if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) ||
               VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_UNSPEC))) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("%s family specified for non-IPv4 address '%s' "
+            virReportError(VIR_ERR_XML_ERROR,
+                           def->family == NULL ?
+                           _("No family specified for non-IPv4 address '%s' "
+                             "in route definition of network '%s'") :
+                           _("IPv4 family specified for non-IPv4 address '%s' "
                              "in route definition of network '%s'"),
-                           def->family == NULL? "no" : "ipv4",
                            address, networkName);
             goto cleanup;
         }
         if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("%s family specified for non-IPv4 gateway '%s' "
+            virReportError(VIR_ERR_XML_ERROR,
+                           def->family == NULL ?
+                           _("No family specified for non-IPv4 gateway '%s' "
+                             "in route definition of network '%s'") :
+                           _("IPv4 family specified for non-IPv4 gateway '%s' "
                              "in route definition of network '%s'"),
-                           def->family == NULL? "no" : "ipv4",
                            address, networkName);
             goto cleanup;
         }
@@ -1390,56 +1403,57 @@ virNetworkRouteDefParseXML(const char *networkName,
                 goto cleanup;
             }
             if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->netmask, AF_INET)) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("network '%s' has invalid netmask '%s' "
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("Network '%s' has invalid netmask '%s' "
                                  "for address '%s' (both must be IPv4)"),
                                networkName, netmask, address);
                 goto cleanup;
             }
             if (def->has_prefix) {
                 /* can't have both netmask and prefix at the same time */
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("route definition '%s' cannot have both "
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("Route definition '%s' cannot have both "
                                  "a prefix and a netmask"),
                                networkName);
                 goto cleanup;
             }
         }
         if (def->prefix > 32) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Invalid IPv4 prefix %u for '%s' specified "
-                             "in route definition of network '%s'"),
-                           def->prefix,
-                           def->family == NULL? "no" : "ipv4", networkName);
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid prefix %u specified "
+                             "in route definition of network '%s', "
+                             "must be 0 - 32"),
+                           def->prefix, networkName);
             goto cleanup;
         }
     } else if (STREQ(def->family, "ipv6")) {
         if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+            virReportError(VIR_ERR_XML_ERROR,
                            _("ipv6 family specified for non-IPv6 address '%s' "
                              "in route definition of network '%s'"),
                            address, networkName);
             goto cleanup;
         }
         if (netmask) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("specifying netmask invalid for IPv6 address '%s' "
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Specifying netmask invalid for IPv6 address '%s' "
                              "in route definition of network '%s'"),
                            address, networkName);
             goto cleanup;
         }
         if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET6)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+            virReportError(VIR_ERR_XML_ERROR,
                            _("ipv6 specified for non-IPv6 gateway address '%s' "
                              "in route definition of network '%s'"),
                            gateway, networkName);
             goto cleanup;
         }
         if (def->prefix > 128) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Invalid IPv6 prefix %u for '%s' specified "
-                             "in route definition of network '%s'"),
-                           def->prefix, def->family, networkName);
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid prefix %u specified "
+                             "in route definition of network '%s', "
+                             "must be 0 - 128"),
+                           def->prefix, networkName);
             goto cleanup;
         }
     } else {
@@ -1453,7 +1467,7 @@ virNetworkRouteDefParseXML(const char *networkName,
     /* make sure the address is a network address */
     if (netmask) {
         if (virSocketAddrMask(&def->address, &def->netmask, &testAddr) < 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+            virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("error converting address '%s' with netmask '%s' "
                              "to network-address "
                              "in route definition of network '%s'"),
@@ -1463,7 +1477,7 @@ virNetworkRouteDefParseXML(const char *networkName,
     } else {
         if (virSocketAddrMaskByPrefix(&def->address,
                                       def->prefix, &testAddr) < 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+            virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("error converting address '%s' with prefix %u "
                              "to network-address "
                              "in route definition of network '%s'"),
@@ -1472,7 +1486,7 @@ virNetworkRouteDefParseXML(const char *networkName,
         }
     }
     if (!virSocketAddrEqual(&def->address, &testAddr)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+        virReportError(VIR_ERR_XML_ERROR,
                        _("address '%s' in route definition of network '%s' "
                          "is not a network address"),
                        address, networkName);
@@ -2125,6 +2139,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
             }
         }
     }
+    VIR_FREE(routeNodes);
 
     forwardNode = virXPathNode("./forward", ctxt);
     if (forwardNode &&
@@ -2436,6 +2451,7 @@ virNetworkRouteDefFormat(virBufferPtr buf,
     }
     if (VIR_SOCKET_ADDR_VALID(&def->address)) {
         char *addr = virSocketAddrFormat(&def->address);
+
         if (!addr)
             goto error;
         virBufferAsprintf(buf, " address='%s'", addr);
@@ -2443,6 +2459,7 @@ virNetworkRouteDefFormat(virBufferPtr buf,
     }
     if (VIR_SOCKET_ADDR_VALID(&def->netmask)) {
         char *addr = virSocketAddrFormat(&def->netmask);
+
         if (!addr)
             goto error;
         virBufferAsprintf(buf, " netmask='%s'", addr);
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 0f390f4..cee4001 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -822,7 +822,7 @@ cleanup:
 }
 
 /**
- * virNetDevSetGateway:
+ * virNetDevAddRoute:
  * @ifname: the interface name
  * @addr: the IP network address (IPv4 or IPv6)
  * @prefix: number of 1 bits in the netmask
-- 
1.7.11.7

