[libvirt] [PATCHv2 1/4] util: introduce 2 new helpers for get interface IPv6 address
John Ferlan
jferlan at redhat.com
Mon Mar 9 23:50:16 UTC 2015
On 03/09/2015 11:37 AM, Luyao Huang wrote:
>
> On 03/09/2015 07:50 AM, John Ferlan wrote:
>> On 02/28/2015 04:08 AM, Luyao Huang wrote:
>>> Introduce virNetDevGetIfaddrsAddress to help to get interface IPv6
>>> and IPv4 address.
>>>
>>> Introduce virNetDevGetIPAddress to use virNetDevGetIfaddrsAddress
>>> and virNetDevGetIPv4Address to get IP address.
>>>
>>> Signed-off-by: Luyao Huang <lhuang at redhat.com>
>>> ---
>>> v2: add a new function virNetDevGetIPAddress to call
>>> virNetDevGetIfaddrsAddress
>>> , and make virNetDevGetIfaddrsAddress can get ipv4 address for a
>>> interface.
>>> Also add a error output in virNetDevGetIfaddrsAddress when get
>>> multiple ip
>>> address for a host interface.
>>>
>>> src/libvirt_private.syms | 1 +
>>> src/util/virnetdev.c | 98
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>> src/util/virnetdev.h | 4 ++
>>> 3 files changed, 103 insertions(+)
>>>
> ...
>>
>>> + if (ifa->ifa_addr->sa_family == (want_ipv6 ? AF_INET6 :
>>> AF_INET)) {
>>> + if (++nIPaddr > 1)
>>> + break;
>> [1]... hmm not sure about this...
>>
>>> + if (want_ipv6) {
>>> + addr->len = sizeof(addr->data.inet6);
>>> + memcpy(&addr->data.inet6, ifa->ifa_addr, addr->len);
>>> + } else {
>>> + addr->len = sizeof(addr->data.inet4);
>>> + memcpy(&addr->data.inet4, ifa->ifa_addr, addr->len);
>>> + }
>>> + addr->data.stor.ss_family = ifa->ifa_addr->sa_family;
>>> + }
>>> + }
>>> +
>>> + if (nIPaddr == 1)
>>> + ret = 0;
>>> + else if (nIPaddr > 1)
>>> + virReportError(VIR_ERR_INTERNAL_ERROR,
>>> + _("Interface '%s' has multiple %s address"),
>> s/address/addresses
>>
>>> + ifname, want_ipv6 ? "IPv6" : "IPv4");
>> [1]
>> But is this really desired... It seems from the previous review, if
>> someone wants a specific address they use "<listen type='address'...".
>>
>> Otherwise, they use this function. Since you'll be returning either an
>> IPv4 or IPv6 address here you'd be causing an error here if the network
>> had more than one IPv4 address defined; whereas, the previous code just
>> returned the "first" from the ioctl(SIOCGIFADDR...).
>>
>> I think once you have an address you just return the first one found and
>> document it that way avoiding this path completely. You could also note
>> that if you want a specific address use the type='address'
>>
>>
> I had an idea but my eyes almost close ;) so i write here without test
> them.
>
> I think it will be better if we make this function to get mutli address
> and return the number of address we get, like this:
>
> +static int
> +virNetDevGetIfaddrsAddress(const char *ifname,
> + bool want_ipv6,
> + virSocketAddrPtr *addrs)
We'd need to have an naddrs to know how many we can stuff in... or you'd
need to do the *REALLOC on the fly in this module for each address found.
Interesting idea, but you'd be just throwing things away. I could
perhaps having some code "periodically" cache addresses... or cache
addresses, subscribe to some event to let you know when a new address is
generated so you can add it to your list (if there is one)...
But, how do you use it?
John
> +{
> + struct ifaddrs *ifap, *ifa;
> + int nIPaddr = 0;
> +
> + if (getifaddrs(&ifap) < 0) {
> + virReportSystemError(errno,
> + _("Could not get interface list for '%s'"),
> + ifname);
> + return -1;
> + }
> +
> + for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> + virSocketAddrPtr tmpaddr;
> +
> + if (!ifa->ifa_addr ||
> + STRNEQ_NULLABLE(ifa->ifa_name, ifname)) {
> + continue;
> + }
> +
> + if (ifa->ifa_addr->sa_family == (want_ipv6 ? AF_INET6 :
> AF_INET)) {
> + memset(tmpaddr, 0, sizeof(*tmpaddr));
> +
> + if (!ifa->ifa_addr ||
> + STRNEQ_NULLABLE(ifa->ifa_name, ifname)) {
> + continue;
> + }
> +
> + if (ifa->ifa_addr->sa_family == (want_ipv6 ? AF_INET6 :
> AF_INET)) {
> + memset(tmpaddr, 0, sizeof(*tmpaddr));
> +
> + if (want_ipv6) {
> + tmpaddr->len = sizeof(tmpaddr->data.inet6);
> + memcpy(&tmpaddr->data.inet6, ifa->ifa_addr, tmpaddr->len);
> + } else {
> + tmpaddr->len = sizeof(tmpaddr->data.inet4);
> + memcpy(&tmpaddr->data.inet4, ifa->ifa_addr, tmpaddr->len);
> + }
> + tmpaddr->data.stor.ss_family = ifa->ifa_addr->sa_family;
> + addrs[nIPaddr++] = tmpaddr;
> + }
> + }
> + if (nIPaddr == 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Interface '%s' not found"),
> + ifname);
> + return -1;
> + }
> + freeifaddrs(ifap);
> + return nIPaddr;
> +}
>
>>> +int virNetDevGetIPAddress(const char *ifname,
>>> + bool want_ipv6,
>>> + virSocketAddrPtr addr)
> and then rename this function to virNetDevGetOneIPAddress()
>
> and rework the code like this:
>
> +int virNetDevGetOneIPAddress(const char *ifname,
> + bool want_ipv6,
> + virSocketAddrPtr addr)
> +{
> + int ret;
> + virSocketAddrPtr *addrs = NULL;
> +
> + ret = virNetDevGetIfaddrsAddress(ifname, want_ipv6, addrs);
> + if (ret > 0) {
> + addr = addrs[0];
> + } else if (ret == -2 && !want_ipv6) {
> + return virNetDevGetIPv4Address(ifname, addr);
> + }
> +
> + return ret;
> +}
>
> ...
>>
>> These changes require modifying src/network/bridge_driver.c (temporarily
>> until we add the IPv6 aware code later):
>>
>> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
>> index 2a61991..7d6e173 100644
>> --- a/src/network/bridge_driver.c
>> +++ b/src/network/bridge_driver.c
>> @@ -4608,7 +4608,7 @@ networkGetNetworkAddress(const char *netname, char
>> **netaddr)
>> }
>>
>> if (dev_name) {
>> - if (virNetDevGetIPv4Address(dev_name, &addr) < 0)
>> + if (virNetDevGetIPAddress(dev_name, false, &addr) < 0)
>> goto cleanup;
>> addrptr = &addr;
>> }
>>
>
> At last, add the multiple address check to here and this place will like
> this:
>
> + int num = virNetDevGetOneIPAddress(dev_name, want_ipv6, &addr);
> + if (num > 1) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("interface '%s' has multiple %s addresses"),
> + dev_name, want_ipv6 ? "IPv6" : "IPv4");
> + goto cleanup;
> + } else if (num < 0) {
> goto cleanup;
> + }
>
>
> because i am not test them so there will be some mistake, I will test
> them tomorrow, hope it will work :)
>>
>>
>> John
>
> Luyao
More information about the libvir-list
mailing list