[libvirt] [PATCH 2/2] util: introduce virSocketAddrParseAny

Jim Fehlig posted 2 patches 7 years, 1 month ago
[libvirt] [PATCH 2/2] util: introduce virSocketAddrParseAny
Posted by Jim Fehlig 7 years, 1 month ago
When preparing for migration, the libxl driver creates a new TCP listen
socket for the incoming migration by calling virNetSocketNewListenTCP,
passing the destination host name. virNetSocketNewListenTCP calls
virSocketAddrParse to check if the host name is a wildcard address, in
which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to
getaddrinfo. If the host name is not an IP address, virSocketAddrParse
reports an error

error : virSocketAddrParseInternal:121 : Cannot parse socket address
'myhost.example.com': Name or service not known

But virNetSocketNewListenTCP succeeds regardless and the overall migration
operation succeeds.

Introduce virSocketAddrParseAny and use it when simply testing if a host
name/addr is parsable.

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---

Essentially a V2 of

https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html

It takes a slightly different approach by creating a function that can
parse host names or IP addresses.

 src/libvirt_private.syms |  1 +
 src/rpc/virnetsocket.c   |  2 +-
 src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++---
 src/util/virsocketaddr.h |  5 +++++
 4 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 03fe3b315..f6cdcde72 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2725,6 +2725,7 @@ virSocketAddrMask;
 virSocketAddrMaskByPrefix;
 virSocketAddrNumericFamily;
 virSocketAddrParse;
+virSocketAddrParseAny;
 virSocketAddrParseIPv4;
 virSocketAddrParseIPv6;
 virSocketAddrPrefixToNetmask;
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 2d41a716b..f362a0955 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -333,7 +333,7 @@ int virNetSocketNewListenTCP(const char *nodename,
      * startup in most cases.
      */
     if (nodename &&
-        !(virSocketAddrParse(&tmp_addr, nodename, AF_UNSPEC) > 0 &&
+        !(virSocketAddrParseAny(&tmp_addr, nodename, AF_UNSPEC, false) > 0 &&
           virSocketAddrIsWildcard(&tmp_addr)))
         hints.ai_flags |= AI_ADDRCONFIG;
 
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 31a740cb8..84610560f 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -101,6 +101,7 @@ static int
 virSocketAddrParseInternal(struct addrinfo **res,
                            const char *val,
                            int family,
+                           int ai_flags,
                            bool reportError)
 {
     struct addrinfo hints;
@@ -114,7 +115,7 @@ virSocketAddrParseInternal(struct addrinfo **res,
 
     memset(&hints, 0, sizeof(hints));
     hints.ai_family = family;
-    hints.ai_flags = AI_NUMERICHOST;
+    hints.ai_flags = ai_flags;
     if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) {
         if (reportError)
             virReportError(VIR_ERR_SYSTEM_ERROR,
@@ -143,7 +144,7 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family)
     int len;
     struct addrinfo *res;
 
-    if (virSocketAddrParseInternal(&res, val, family, true) < 0)
+    if (virSocketAddrParseInternal(&res, val, family, AI_NUMERICHOST, true) < 0)
         return -1;
 
     if (res == NULL) {
@@ -163,6 +164,49 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family)
     return len;
 }
 
+/**
+ * virSocketAddrParseAny:
+ * @addr: where to store the return value, optional.
+ * @val: a network host name or a numeric network address IPv4 or IPv6
+ * @family: address family to pass down to getaddrinfo
+ * @reportError: boolean to control error reporting
+ *
+ * Mostly a wrapper for getaddrinfo() extracting the address storage
+ * from a host name like acme.example.com or a 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 virSocketAddrParseAny(virSocketAddrPtr addr,
+                          const char *val,
+                          int family,
+                          bool reportError)
+{
+    int len;
+    struct addrinfo *res;
+
+    if (virSocketAddrParseInternal(&res, val, family, 0, reportError) < 0)
+        return -1;
+
+    if (res == NULL) {
+        if (reportError) {
+            virReportError(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
@@ -1105,7 +1149,7 @@ virSocketAddrNumericFamily(const char *address)
     struct addrinfo *res;
     unsigned short family;
 
-    if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, false) < 0)
+    if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, AI_NUMERICHOST, false) < 0)
         return -1;
 
     family = res->ai_addr->sa_family;
diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h
index 80e792618..302933848 100644
--- a/src/util/virsocketaddr.h
+++ b/src/util/virsocketaddr.h
@@ -92,6 +92,11 @@ int virSocketAddrParse(virSocketAddrPtr addr,
                        const char *val,
                        int family);
 
+int virSocketAddrParseAny(virSocketAddrPtr addr,
+                          const char *val,
+                          int family,
+                          bool reportError);
+
 int virSocketAddrParseIPv4(virSocketAddrPtr addr,
                            const char *val);
 
-- 
2.16.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] util: introduce virSocketAddrParseAny
Posted by John Ferlan 7 years, 1 month ago

On 03/26/2018 04:29 PM, Jim Fehlig wrote:
> When preparing for migration, the libxl driver creates a new TCP listen
> socket for the incoming migration by calling virNetSocketNewListenTCP,
> passing the destination host name. virNetSocketNewListenTCP calls
> virSocketAddrParse to check if the host name is a wildcard address, in
> which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to
> getaddrinfo. If the host name is not an IP address, virSocketAddrParse
> reports an error
> 
> error : virSocketAddrParseInternal:121 : Cannot parse socket address
> 'myhost.example.com': Name or service not known
> 
> But virNetSocketNewListenTCP succeeds regardless and the overall migration
> operation succeeds.
> 
> Introduce virSocketAddrParseAny and use it when simply testing if a host
> name/addr is parsable.
> 
> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
> ---
> 
> Essentially a V2 of
> 
> https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html
> 
> It takes a slightly different approach by creating a function that can
> parse host names or IP addresses.
> 
>  src/libvirt_private.syms |  1 +
>  src/rpc/virnetsocket.c   |  2 +-
>  src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++---
>  src/util/virsocketaddr.h |  5 +++++
>  4 files changed, 54 insertions(+), 4 deletions(-)
> 

Reviewed-by: John Ferlan <jferlan@redhat.com>

Wait for 4.2.0 for this one...

John

BTW: Your call on whether to add to the new API comments something about
the API could be susceptible to a delay due to network name resolution
lookup pause.  That is, from the getaddrinfo man page:

"The AI_NUMERICHOST flag suppresses any potentially lengthy network host
address lookups."

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] util: introduce virSocketAddrParseAny
Posted by Jim Fehlig 7 years, 1 month ago
On 03/29/2018 11:27 AM, John Ferlan wrote:
> 
> 
> On 03/26/2018 04:29 PM, Jim Fehlig wrote:
>> When preparing for migration, the libxl driver creates a new TCP listen
>> socket for the incoming migration by calling virNetSocketNewListenTCP,
>> passing the destination host name. virNetSocketNewListenTCP calls
>> virSocketAddrParse to check if the host name is a wildcard address, in
>> which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to
>> getaddrinfo. If the host name is not an IP address, virSocketAddrParse
>> reports an error
>>
>> error : virSocketAddrParseInternal:121 : Cannot parse socket address
>> 'myhost.example.com': Name or service not known
>>
>> But virNetSocketNewListenTCP succeeds regardless and the overall migration
>> operation succeeds.
>>
>> Introduce virSocketAddrParseAny and use it when simply testing if a host
>> name/addr is parsable.
>>
>> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
>> ---
>>
>> Essentially a V2 of
>>
>> https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html
>>
>> It takes a slightly different approach by creating a function that can
>> parse host names or IP addresses.
>>
>>   src/libvirt_private.syms |  1 +
>>   src/rpc/virnetsocket.c   |  2 +-
>>   src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++---
>>   src/util/virsocketaddr.h |  5 +++++
>>   4 files changed, 54 insertions(+), 4 deletions(-)
>>
> 
> Reviewed-by: John Ferlan <jferlan@redhat.com>
> 
> Wait for 4.2.0 for this one...
> 
> John
> 
> BTW: Your call on whether to add to the new API comments something about
> the API could be susceptible to a delay due to network name resolution
> lookup pause.  That is, from the getaddrinfo man page:
> 
> "The AI_NUMERICHOST flag suppresses any potentially lengthy network host
> address lookups."

Good point. I squashed in the below comment to this patch before pushing both.

Regards,
Jim

diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 84610560f..99dc54830 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -173,7 +173,10 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char 
*val, int family)
   *
   * Mostly a wrapper for getaddrinfo() extracting the address storage
   * from a host name like acme.example.com or a numeric string like 1.2.3.4
- * or 2001:db8:85a3:0:0:8a2e:370:7334
+ * or 2001:db8:85a3:0:0:8a2e:370:7334.
+ *
+ * When @val is a network host name, this function may be susceptible to a
+ * delay due to potentially lengthy netork host address lookups.
   *
   * Returns the length of the network address or -1 in case of error.
   */

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] util: introduce virSocketAddrParseAny
Posted by Jim Fehlig 7 years, 1 month ago
On 04/05/2018 02:55 PM, Jim Fehlig wrote:
> On 03/29/2018 11:27 AM, John Ferlan wrote:
>>
>>
>> On 03/26/2018 04:29 PM, Jim Fehlig wrote:
>>> When preparing for migration, the libxl driver creates a new TCP listen
>>> socket for the incoming migration by calling virNetSocketNewListenTCP,
>>> passing the destination host name. virNetSocketNewListenTCP calls
>>> virSocketAddrParse to check if the host name is a wildcard address, in
>>> which case it avoids adding the AI_ADDRCONFIG flag to the hints passed to
>>> getaddrinfo. If the host name is not an IP address, virSocketAddrParse
>>> reports an error
>>>
>>> error : virSocketAddrParseInternal:121 : Cannot parse socket address
>>> 'myhost.example.com': Name or service not known
>>>
>>> But virNetSocketNewListenTCP succeeds regardless and the overall migration
>>> operation succeeds.
>>>
>>> Introduce virSocketAddrParseAny and use it when simply testing if a host
>>> name/addr is parsable.
>>>
>>> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
>>> ---
>>>
>>> Essentially a V2 of
>>>
>>> https://www.redhat.com/archives/libvir-list/2018-March/msg01120.html
>>>
>>> It takes a slightly different approach by creating a function that can
>>> parse host names or IP addresses.
>>>
>>>   src/libvirt_private.syms |  1 +
>>>   src/rpc/virnetsocket.c   |  2 +-
>>>   src/util/virsocketaddr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++---
>>>   src/util/virsocketaddr.h |  5 +++++
>>>   4 files changed, 54 insertions(+), 4 deletions(-)
>>>
>>
>> Reviewed-by: John Ferlan <jferlan@redhat.com>
>>
>> Wait for 4.2.0 for this one...
>>
>> John
>>
>> BTW: Your call on whether to add to the new API comments something about
>> the API could be susceptible to a delay due to network name resolution
>> lookup pause.  That is, from the getaddrinfo man page:
>>
>> "The AI_NUMERICHOST flag suppresses any potentially lengthy network host
>> address lookups."
> 
> Good point. I squashed in the below comment to this patch before pushing both.
> 
> Regards,
> Jim
> 
> diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
> index 84610560f..99dc54830 100644
> --- a/src/util/virsocketaddr.c
> +++ b/src/util/virsocketaddr.c
> @@ -173,7 +173,10 @@ int virSocketAddrParse(virSocketAddrPtr addr, const char 
> *val, int family)
>    *
>    * Mostly a wrapper for getaddrinfo() extracting the address storage
>    * from a host name like acme.example.com or a numeric string like 1.2.3.4
> - * or 2001:db8:85a3:0:0:8a2e:370:7334
> + * or 2001:db8:85a3:0:0:8a2e:370:7334.
> + *
> + * When @val is a network host name, this function may be susceptible to a
> + * delay due to potentially lengthy netork host address lookups.

Heh, only now did I notice the misspelling of 'network'. I'll push a trivial 
followup.

Regards,
Jim

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list