]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
libvirt_nss: Report newer addresses first
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 10 Jul 2019 12:30:11 +0000 (14:30 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 15 Jul 2019 11:48:19 +0000 (13:48 +0200)
Ideally, a software that's translating domain names would iterate
over all addresses the NSS returned, but some software does not
bother (e.g. ping). What happens is that for instance when
installing a guest, it's assigned one IP address but once it's
installed and rebooted it gets a different IP address (because
client ID used for the first DHCP traffic when installing the
guest was generated dynamically and never saved so after reboot
the guest generated new ID which resulted in different IP address
to be assigned). This results in 'ping $domain' not working
properly as it still pings the old IP address. Well, it might -
NSS plugin does not guarantee any order of addresses.

To resolve this problem, we can sort the array just before
returning it to the caller (ping) so that the newer IP addresses
come before older ones.

Reported-by: Andrea Bolognani <abologna@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
tests/nssdata/virbr0.status
tests/nsstest.c
tools/nss/libvirt_nss.c

index d040774269354d4086f356baebe352fa07b8caab..78afaf6200f933e6007eddf37c767ecf91b0ea52 100644 (file)
@@ -3,13 +3,13 @@
         "ip-address": "192.168.122.197",
         "mac-address": "52:54:00:a4:6f:91",
         "hostname": "fedora",
-        "expiry-time": 1900000000
+        "expiry-time": 1900000002
     },
     {
         "ip-address": "192.168.122.198",
         "mac-address": "52:54:00:a4:6f:92",
         "hostname": "fedora",
-        "expiry-time": 1900000000
+        "expiry-time": 1900000001
     },
     {
         "ip-address": "192.168.122.254",
index d43c59c4a2e3a029b17ec3eab4e62b5804e14acf..4118c31cefab0b492287535ad1d7cafd4675cc23 100644 (file)
@@ -46,7 +46,7 @@ testGetHostByName(const void *opaque)
     char buf[BUF_SIZE] = { 0 };
     char **addrList;
     int rv, tmp_errno = 0, tmp_herrno = 0;
-    size_t i = 0, j = 0;
+    size_t i = 0;
 
     memset(&resolved, 0, sizeof(resolved));
 
@@ -117,6 +117,7 @@ testGetHostByName(const void *opaque)
     }
 
     addrList = resolved.h_addr_list;
+    i = 0;
     while (*addrList) {
         virSocketAddr sa;
         char *ipAddr;
@@ -135,14 +136,10 @@ testGetHostByName(const void *opaque)
             goto cleanup;
         }
 
-        for (j = 0; data->ipAddr[j]; j++) {
-            if (STREQ(data->ipAddr[j], ipAddr))
-                break;
-        }
-
-        if (!data->ipAddr[j]) {
+        if (STRNEQ_NULLABLE(data->ipAddr[i], ipAddr)) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-                           "Unexpected address %s", ipAddr);
+                           "Unexpected address %s, expecting %s",
+                           ipAddr, NULLSTR(data->ipAddr[i]));
             VIR_FREE(ipAddr);
             goto cleanup;
         }
@@ -152,12 +149,10 @@ testGetHostByName(const void *opaque)
         i++;
     }
 
-    for (j = 0; data->ipAddr[j]; j++)
-        ;
-
-    if (i != j) {
+    if (data->ipAddr[i]) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "Expected %zu addresses, got %zu", j, i);
+                       "Expected %s address, got NULL",
+                       data->ipAddr[i]);
         goto cleanup;
     }
 
index b0e118bf371b659ce6a4c946a74f2764d286e4ad..519046a4e0a3f1c2694f930f225406ac3a7e7856 100644 (file)
@@ -76,9 +76,29 @@ do { \
 typedef struct {
     unsigned char addr[16];
     int af;
+    long long expirytime;
 } leaseAddress;
 
 
+static int
+leaseAddressSorter(const void *a,
+                   const void *b)
+{
+    const leaseAddress *la = a;
+    const leaseAddress *lb = b;
+
+    return lb->expirytime - la->expirytime;
+}
+
+
+static void
+sortAddr(leaseAddress *tmpAddress,
+         size_t ntmpAddress)
+{
+    qsort(tmpAddress, ntmpAddress, sizeof(*tmpAddress), leaseAddressSorter);
+}
+
+
 static int
 appendAddr(const char *name ATTRIBUTE_UNUSED,
            leaseAddress **tmpAddress,
@@ -89,6 +109,7 @@ appendAddr(const char *name ATTRIBUTE_UNUSED,
     const char *ipAddr;
     virSocketAddr sa;
     int family;
+    long long expirytime;
     size_t i;
 
     if (!(ipAddr = virJSONValueObjectGetString(lease, "ip-address"))) {
@@ -109,6 +130,12 @@ appendAddr(const char *name ATTRIBUTE_UNUSED,
         return 0;
     }
 
+    if (virJSONValueObjectGetNumberLong(lease, "expiry-time", &expirytime) < 0) {
+        /* A lease cannot be present without expiry-time */
+        ERROR("expiry-time field missing for %s", name);
+        return -1;
+    }
+
     for (i = 0; i < *ntmpAddress; i++) {
         if (memcmp((*tmpAddress)[i].addr,
                    (family == AF_INET ?
@@ -125,6 +152,7 @@ appendAddr(const char *name ATTRIBUTE_UNUSED,
         return -1;
     }
 
+    (*tmpAddress)[*ntmpAddress].expirytime = expirytime;
     (*tmpAddress)[*ntmpAddress].af = family;
     memcpy((*tmpAddress)[*ntmpAddress].addr,
            (family == AF_INET ?
@@ -325,6 +353,8 @@ findLease(const char *name,
 
 #endif /* defined(LIBVIRT_NSS_GUEST) */
 
+    sortAddr(tmpAddress, ntmpAddress);
+
     VIR_STEAL_PTR(*address, tmpAddress);
     *naddress = ntmpAddress;
     ntmpAddress = 0;