LCOV - code coverage report
Current view: top level - src - iface.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 70 87 80.5 %
Date: 2019-09-02 12:15:29 Functions: 15 20 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Network Address -- classes functions to ease handling IP addresses
       2             : // Copyright (c) 2012-2019  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // https://snapwebsites.org/project/libaddr
       5             : //
       6             : // Permission is hereby granted, free of charge, to any person obtaining a
       7             : // copy of this software and associated documentation files (the
       8             : // "Software"), to deal in the Software without restriction, including
       9             : // without limitation the rights to use, copy, modify, merge, publish,
      10             : // distribute, sublicense, and/or sell copies of the Software, and to
      11             : // permit persons to whom the Software is furnished to do so, subject to
      12             : // the following conditions:
      13             : //
      14             : // The above copyright notice and this permission notice shall be included
      15             : // in all copies or substantial portions of the Software.
      16             : //
      17             : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      18             : // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      19             : // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      20             : // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      21             : // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      22             : // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      23             : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      24             : //
      25             : 
      26             : /** \file
      27             :  * \brief The implementation of the addr class.
      28             :  *
      29             :  * This file includes the implementation of the addr class. The one that
      30             :  * deals with low level classes.
      31             :  */
      32             : 
      33             : // self
      34             : //
      35             : #include "libaddr/iface.h"
      36             : 
      37             : // addr library
      38             : //
      39             : #include "libaddr/route.h"
      40             : 
      41             : // C++ library
      42             : //
      43             : #include <algorithm>
      44             : #include <iostream>
      45             : 
      46             : // C library
      47             : //
      48             : #include <ifaddrs.h>
      49             : #include <net/if.h>
      50             : 
      51             : 
      52             : 
      53             : namespace addr
      54             : {
      55             : 
      56             : 
      57             : /** \brief Details used by the addr class implementation.
      58             :  *
      59             :  * We have a function to check whether an address is part of
      60             :  * the interfaces of your computer. This check requires the
      61             :  * use of a `struct ifaddrs` and as such it requires to
      62             :  * delete that structure. We define a deleter for that
      63             :  * strucure here.
      64             :  */
      65             : namespace
      66             : {
      67             : 
      68             : /** \brief Delete an ifaddrs structure.
      69             :  *
      70             :  * This deleter is used to make sure all the ifaddrs get released when
      71             :  * an exception occurs or the function using such exists.
      72             :  *
      73             :  * \param[in] ia  The ifaddrs structure to free.
      74             :  */
      75          15 : void ifaddrs_deleter(struct ifaddrs * ia)
      76             : {
      77          15 :     freeifaddrs(ia);
      78          15 : }
      79             : 
      80             : 
      81             : }
      82             : // no name namespace
      83             : 
      84             : 
      85             : 
      86             : 
      87             : 
      88             : /** \brief Initializes an interface name/index pair.
      89             :  *
      90             :  * This function creates an interface name/index object.
      91             :  *
      92             :  * In some circumstances (NETLINK) you need to specify the index of an
      93             :  * interface. The kernel keeps a list of interface by index starting at 1
      94             :  * and each have a name such as "eth0". This function initializes
      95             :  * one of those pairs.
      96             :  *
      97             :  * \param[in] index  The index of the interface.
      98             :  * \param[in] name  The name of the interface.
      99             :  */
     100           0 : iface_index_name::iface_index_name(int index, std::string const & name)
     101             :     : f_index(index)
     102           0 :     , f_name(name)
     103             : {
     104           0 : }
     105             : 
     106             : 
     107             : /** \brief Get the index of this interface.
     108             :  *
     109             :  * This function is used to retrieve the index of a name/index pair.
     110             :  *
     111             :  * \return The index of the name/index pair.
     112             :  */
     113           0 : int iface_index_name::get_index() const
     114             : {
     115           0 :     return f_index;
     116             : }
     117             : 
     118             : 
     119             : /** \brief Get the name of this interface.
     120             :  *
     121             :  * This function is used to retrieve the name of a name/index pair.
     122             :  *
     123             :  * \return The name of the name/index pair.
     124             :  */
     125           0 : std::string const & iface_index_name::get_name() const
     126             : {
     127           0 :     return f_name;
     128             : }
     129             : 
     130             : 
     131             : 
     132             : /** \brief Get the list of existing interfaces.
     133             :  *
     134             :  * This function gathers the complete list of interfaces by index and
     135             :  * name pairs. The result is a vector of iface_index_name objects.
     136             :  *
     137             :  * Note that over time the index of an interface can change since interfaces
     138             :  * can be added and removed from your network configuration. It is a good
     139             :  * idea to not cache that information.
     140             :  *
     141             :  * \return A vector of index/name pair objects.
     142             :  */
     143           0 : iface_index_name::vector_t get_interface_name_index()
     144             : {
     145           0 :     iface_index_name::vector_t result;
     146             : 
     147             :     // the index starts at 1
     148             :     //
     149           0 :     for(int index(1);; ++index)
     150             :     {
     151             :         // get the next interface name by index
     152             :         //
     153             :         char name[IF_NAMESIZE + 1];
     154           0 :         if(if_indextoname(index, name) == nullptr)
     155             :         {
     156           0 :             return result;
     157             :         }
     158             : 
     159             :         // make sure the name is null terminated
     160             :         //
     161           0 :         name[IF_NAMESIZE] = '\0';
     162             : 
     163           0 :         iface_index_name const in(index, name);
     164           0 :         result.push_back(in);
     165             :     }
     166             :     // NOT REACHED, the loop is broken by a "return"
     167             : }
     168             : 
     169             : 
     170             : /** \brief Get the index of an interface from its name.
     171             :  *
     172             :  * If you are given the name of an interface, you can retrieve its index
     173             :  * by calling this function. The resulting value is the index from 1 to n.
     174             :  *
     175             :  * If the named interface is not found, then the function returns 0.
     176             :  *
     177             :  * \return The interface index or 0 on error.
     178             :  */
     179           0 : unsigned int get_interface_index_by_name(std::string const & name)
     180             : {
     181           0 :     return if_nametoindex(name.c_str());
     182             : }
     183             : 
     184             : 
     185             : 
     186             : 
     187             : 
     188             : 
     189             : /** \brief Return a list of local addresses on this machine.
     190             :  *
     191             :  * Peruse the list of available interfaces, and return any detected
     192             :  * ip addresses in a vector.
     193             :  *
     194             :  * These addresses include:
     195             :  *
     196             :  * \li A mask whenever available (very likely if the interface is up).
     197             :  * \li A name you can retrieve with get_iface_name()
     198             :  * \li A set of flags defining the current status of the network interface
     199             :  *     (i.e. IFF_UP, IFF_BROADCAST, IFF_NOARP, etc.)
     200             :  *
     201             :  * \return A vector of all the local interface IP addresses.
     202             :  */
     203          15 : iface::vector_t iface::get_local_addresses()
     204             : {
     205             :     // get the list of interface addresses
     206             :     //
     207          15 :     struct ifaddrs * ifa_start(nullptr);
     208          15 :     if(getifaddrs(&ifa_start) != 0)
     209             :     {
     210             :         // TODO: Should this throw, or just return an empty list quietly?
     211             :         //
     212             :         return iface::vector_t(); // LCOV_EXCL_LINE
     213             :     }
     214             : 
     215          30 :     std::shared_ptr<struct ifaddrs> auto_free(ifa_start, ifaddrs_deleter);
     216             : 
     217             :     uint8_t mask[16];
     218          30 :     iface::vector_t iface_list;
     219         255 :     for(struct ifaddrs * ifa(ifa_start); ifa != nullptr; ifa = ifa->ifa_next)
     220             :     {
     221             :         // the documentation says there may be no address at all
     222             :         // skip such entries at the moment
     223             :         //
     224         240 :         if(ifa->ifa_addr == nullptr)
     225             :         {
     226          90 :             continue;
     227             :         }
     228             : 
     229             :         // initialize an interface
     230         390 :         iface the_interface;
     231             : 
     232             :         // copy the name and flags as is
     233             :         //
     234             :         // TBD: can the ifa_name even be a null pointer?
     235             :         //
     236         240 :         the_interface.f_name = ifa->ifa_name;
     237         240 :         the_interface.f_flags = ifa->ifa_flags; // IFF_... flags (see `man 7 netdevice` search for SIOCGIFFLAGS)
     238             : 
     239             :         // get the family to know how to treat the address
     240             :         //
     241             :         // when an interface has an IPv4 and an IPv6, there are two entries in
     242             :         // the list, both with the same name
     243             :         //
     244         240 :         uint16_t const family(ifa->ifa_addr->sa_family);
     245             : 
     246         240 :         switch(family)
     247             :         {
     248             :         case AF_INET:
     249          90 :             the_interface.f_address.set_ipv4(*(reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr)));
     250             : 
     251          90 :             if((ifa->ifa_flags & IFF_BROADCAST) != 0
     252          75 :             && ifa->ifa_broadaddr != nullptr)
     253             :             {
     254          75 :                 the_interface.f_broadcast_address.set_ipv4(*(reinterpret_cast<struct sockaddr_in *>(ifa->ifa_broadaddr)));
     255             :             }
     256          90 :             if((ifa->ifa_flags & IFF_POINTOPOINT) != 0
     257             :             && ifa->ifa_dstaddr != nullptr)  // LCOV_EXCL_LINE
     258             :             {
     259             :                 the_interface.f_destination_address.set_ipv4(*(reinterpret_cast<struct sockaddr_in *>(ifa->ifa_dstaddr)));  // LCOV_EXCL_LINE
     260             :             }
     261             : 
     262             :             // if present, add the mask as well
     263             :             //
     264          90 :             if(ifa->ifa_netmask != nullptr)
     265             :             {
     266             :                 // for the IPv4 mask, we have to break it down in such a
     267             :                 // way as to make it IPv6 compatible
     268             :                 //
     269          90 :                 memset(mask, 255, 12);
     270          90 :                 mask[12] = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask)->sin_addr.s_addr >>  0;
     271          90 :                 mask[13] = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask)->sin_addr.s_addr >>  8;
     272          90 :                 mask[14] = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask)->sin_addr.s_addr >> 16;
     273          90 :                 mask[15] = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask)->sin_addr.s_addr >> 24;
     274          90 :                 the_interface.f_address.set_mask(mask);
     275             :             }
     276          90 :             break;
     277             : 
     278             :         case AF_INET6:
     279          60 :             the_interface.f_address.set_ipv6(*(reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_addr)));
     280             : 
     281          60 :             if((ifa->ifa_flags & IFF_BROADCAST) != 0
     282          45 :             && ifa->ifa_broadaddr != nullptr)
     283             :             {
     284             :                 the_interface.f_broadcast_address.set_ipv6(*(reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_broadaddr)));  // LCOV_EXCL_LINE
     285             :             }
     286          60 :             if((ifa->ifa_flags & IFF_POINTOPOINT) != 0
     287             :             && ifa->ifa_dstaddr != nullptr)  // LCOV_EXCL_LINE
     288             :             {
     289             :                 the_interface.f_destination_address.set_ipv6(*(reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_dstaddr)));  // LCOV_EXCL_LINE
     290             :             }
     291             : 
     292             :             // if present, add the mask as well
     293             :             //
     294          60 :             if(ifa->ifa_netmask != nullptr)
     295             :             {
     296          60 :                 the_interface.f_address.set_mask(reinterpret_cast<uint8_t *>(&reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_netmask)->sin6_addr));
     297             :             }
     298          60 :             break;
     299             : 
     300             :         default:
     301             :             // TODO: can we just ignore unexpected address families?
     302             :             //throw addr_invalid_structure("Unknown address family!");
     303          90 :             continue;
     304             : 
     305             :         }
     306             : 
     307         150 :         iface_list.push_back(the_interface);
     308             :     }
     309             : 
     310          15 :     return iface_list;
     311             : }
     312             : 
     313             : 
     314             : /** \brief Get the interface name.
     315             :  *
     316             :  * This function returns the name of the interface such as 'eth0' or 'p4p1'.
     317             :  *
     318             :  * The name is used in a few places such as the ioctl() function with the
     319             :  * SIOCGIFMTU command. Otherwise, it's mainly for display and easing use
     320             :  * (i.e. to let users select which interface to connect to.)
     321             :  *
     322             :  * \return The interface name.
     323             :  */
     324          12 : std::string iface::get_name() const
     325             : {
     326          12 :     return f_name;
     327             : }
     328             : 
     329             : 
     330             : /** \brief Get the interface setup flags.
     331             :  *
     332             :  * This function returns a set of flags defined on that interface. The flags
     333             :  * are defined in the `man 7 netdevice` as the IFF_... flags. The flags are
     334             :  * defined under the SIOCGIFFLAGS and SIOCSIFFLAGS entries.
     335             :  *
     336             :  * One flag of interest is the IFF_UP flag. This means the interface is
     337             :  * active (even if not actually in use.)
     338             :  *
     339             :  * \return The interface flags.
     340             :  */
     341          30 : unsigned int iface::get_flags() const
     342             : {   
     343          30 :     return f_flags;
     344             : }
     345             : 
     346             : 
     347             : /** \brief Get this interface address.
     348             :  *
     349             :  * This function returns the address of the interface. This address is very
     350             :  * likely to have a mask (i.e. 192.168.0.0/255.255.0.0).
     351             :  *
     352             :  * The address may be an IPv4 or an IPv6 address.
     353             :  *
     354             :  * \return The address of the interface.
     355             :  */
     356         138 : addr const & iface::get_address() const
     357             : {
     358         138 :     return f_address;
     359             : }
     360             : 
     361             : 
     362             : /** \brief Get the broadcast address.
     363             :  *
     364             :  * This function returns a constant reference to the broadcast address
     365             :  * of this interface. The address is always available in this class. It
     366             :  * will be set to the ANY address if it was not defined. Note, however,
     367             :  * that even though the ANY address is not a valid broadcast address,
     368             :  * you should call the has_broadcast_address() function to know whether
     369             :  * this address is indeed defined.
     370             :  *
     371             :  * \return The broadcast address of this interface.
     372             :  */
     373          10 : addr const & iface::get_broadcast_address() const
     374             : {
     375          10 :     return f_broadcast_address;
     376             : }
     377             : 
     378             : 
     379             : /** \brief Get the destination address.
     380             :  *
     381             :  * This function returns a constant reference to the destination address
     382             :  * of this interface. The address is always available in this class. It
     383             :  * will be set to the ANY address if it was not defined. Note, however,
     384             :  * that the ANY address is a valid destination address (i.e. default
     385             :  * route).
     386             :  *
     387             :  * To know whether the destination address is defined in that interface,
     388             :  * make sure to call the has_destination_address() function first.
     389             :  *
     390             :  * \return The destination address of this interface.
     391             :  */
     392          10 : addr const & iface::get_destination_address() const
     393             : {
     394          10 :     return f_destination_address;
     395             : }
     396             : 
     397             : 
     398             : /** \brief Check whether a broadcast address.
     399             :  *
     400             :  * The broadcast address is not present on all interfaces. When it is, this
     401             :  * function returns true.
     402             :  *
     403             :  * Note that you can always call the get_broadcast_address(), but if
     404             :  * undefined it will appear as a default address (NETWORK_TYPE_ANY)
     405             :  * which you can't distinguish from a valid address although a
     406             :  * the NETWORK_TYPE_ANY is not a valid address for a broacast
     407             :  * address.
     408             :  *
     409             :  * \note
     410             :  * When a broadcast address is defined on an interface, then there can't
     411             :  * be a destination address.
     412             :  *
     413             :  * \return true if a broadcast address is defined.
     414             :  */
     415          20 : bool iface::has_broadcast_address() const
     416             : {
     417          20 :     return (f_flags & IFF_BROADCAST) != 0;
     418             : }
     419             : 
     420             : 
     421             : /** \brief Check whether this interface defines a destination address.
     422             :  *
     423             :  * This function returns true if this interface defined a destination
     424             :  * address. Either way you can call the get_destination_address()
     425             :  * function, however, the address will be of type NETWORK_TYPE_ANY
     426             :  * which does not tell you whether it was defined or not.
     427             :  *
     428             :  * Ethernet and the local interfaces all define a destination address.
     429             :  *
     430             :  * \note
     431             :  * The destination address is not assigned any specific mask (all
     432             :  * are ff or 255).
     433             :  *
     434             :  * \note
     435             :  * When there is a destination address defined on an interface, then
     436             :  * there can't be a broadcast address.
     437             :  *
     438             :  * \return true when that interface defined a destination address.
     439             :  */
     440          20 : bool iface::has_destination_address() const
     441             : {
     442          20 :     return (f_flags & IFF_POINTOPOINT) != 0;
     443             : }
     444             : 
     445             : 
     446             : /** \brief Search for the interface corresponding to this address.
     447             :  *
     448             :  * Peruse the list of available interfaces and return the one that matches
     449             :  * this address if any, otherwise return a null pointer.
     450             :  *
     451             :  * Say you create an addr object with the IP address "127.0.0.1" and then
     452             :  * call this function. You will get a pointer to the "lo" interface and
     453             :  * can check the validity of the flags (i.e. is the interface UP, can it
     454             :  * BROADCAST or MULTICAST your UDP packets, etc.)
     455             :  *
     456             :  * If the address is a remote address, then this function returns a null
     457             :  * pointer.
     458             :  *
     459             :  * \note
     460             :  * This function replaces the addr::is_computer_interface_address() function.
     461             :  * If this function returns a non-null pointer when allow_default_destination
     462             :  * set to false, then you've got the same result plus you have access to all
     463             :  * the available information from that interface.
     464             :  *
     465             :  * \warning
     466             :  * If you allow for the default destination, this function calls the
     467             :  * route::get_ipv4_routes() function which can be costly. Try to avoid
     468             :  * doing that in a loop.
     469             :  *
     470             :  * \param[in] a  The address used to search for an interface.
     471             :  * \param[in] allow_default_destination  If true and \p a doesn't match
     472             :  *            any of the interfaces, use the one interface with its
     473             :  *            destination set to 0.0.0.0 or equivalent.
     474             :  *
     475             :  * \return A pointer to an interface IP address.
     476             :  */
     477          14 : iface::pointer_t find_addr_interface(addr const & a, bool allow_default_destination)
     478             : {
     479          28 :     iface::vector_t interfaces(iface::get_local_addresses());
     480             : 
     481         140 :     for(auto i : interfaces)
     482             :     {
     483         128 :         if(i.get_address().match(a))
     484             :         {
     485           2 :             return iface::pointer_t(new iface(i));
     486             :         }
     487             :     }
     488             : 
     489             :     // if there is a default, keep a copy in case we do not find a
     490             :     // local address while looking (and only if the user requested
     491             :     // such, which is the default)
     492             :     //
     493          12 :     if(!allow_default_destination)
     494             :     {
     495          11 :         return iface::pointer_t();
     496             :     }
     497             : 
     498             :     // to determine the default interface, we need the list of routes
     499             :     // so we first gather that information and then search for the
     500             :     // interface that has that name
     501             :     //
     502           2 :     route::vector_t routes(route::get_ipv4_routes());
     503           2 :     route::pointer_t default_route(find_default_route(routes));
     504           1 :     if(default_route == nullptr)
     505             :     {
     506             :         return iface::pointer_t(); // LCOV_EXCL_LINE
     507             :     }
     508             : 
     509           1 :     std::string const & default_iface(default_route->get_interface_name());
     510             :     auto it(std::find_if(
     511             :               interfaces.cbegin()
     512             :             , interfaces.cend()
     513          11 :             , [default_iface](auto & i)
     514             :             {
     515           4 :                 return i.get_name() == default_iface;
     516           5 :             }));
     517           1 :     if(it == interfaces.cend())
     518             :     {
     519             :         return iface::pointer_t(); // LCOV_EXCL_LINE
     520             :     }
     521             : 
     522           1 :     return iface::pointer_t(new iface(*it));
     523             : }
     524             : 
     525             : 
     526             : #if 0
     527             : /** \brief Check whether this address represents this computer.
     528             :  *
     529             :  * This function reads the addresses as given to us by the getifaddrs()
     530             :  * function. This is a system function that returns a complete list of
     531             :  * all the addresses this computer is managing / represents. In other
     532             :  * words, a list of address that other computers can use to connect
     533             :  * to this computer (assuming proper firewall, of course.)
     534             :  *
     535             :  * \warning
     536             :  * The list of addresses from getifaddrs() is not being cached. So you
     537             :  * probably do not want to call this function in a loop. That being
     538             :  * said, I still would imagine that retrieving that list is fast.
     539             :  *
     540             :  * \todo
     541             :  * We need to apply the mask to make this work properly. This is why
     542             :  * the current implementation fails big time (used by snapcommunicator.cpp).
     543             :  *
     544             :  * \return a computer_interface_address_t enumeration: error, true, or
     545             :  *         false at this time; on error errno should be set to represent
     546             :  *         what the error was.
     547             :  */
     548             : 
     549             : // replaced by with a pointer_t == nullptr if there was no match,
     550             : // although make sure to set allow_default_destination to false
     551             : //
     552             : iface::pointer_t find_addr_interface(addr const & a, bool allow_default_destination)
     553             : 
     554             : bool is_computer_interface_address(addr const & a)
     555             : {
     556             :     iface::vector_t interfaces(iface::get_local_addresses());
     557             : 
     558             :     for(auto i : interfaces)
     559             :     {
     560             :     }
     561             : 
     562             : 
     563             :     // TBD: maybe we could cache the ifaddrs for a small amount of time
     564             :     //      (i.e. 1 minute) so additional calls within that time
     565             :     //      can go even faster?
     566             :     //
     567             : 
     568             :     // get the list of interface addresses
     569             :     //
     570             :     struct ifaddrs * ifa_start(nullptr);
     571             :     if(getifaddrs(&ifa_start) != 0)
     572             :     {
     573             :         return computer_interface_address_t::COMPUTER_INTERFACE_ADDRESS_ERROR; // LCOV_EXCL_LINE
     574             :     }
     575             :     std::shared_ptr<struct ifaddrs> auto_free(ifa_start, ifaddrs_deleter);
     576             : 
     577             :     bool const ipv4(a.is_ipv4());
     578             :     uint16_t const family(ipv4 ? AF_INET : AF_INET6);
     579             :     for(struct ifaddrs * ifa(ifa_start); ifa != nullptr; ifa = ifa->ifa_next)
     580             :     {
     581             :         if(ifa->ifa_addr != nullptr
     582             :         && ifa->ifa_addr->sa_family == family)
     583             :         {
     584             :             if(ipv4)
     585             :             {
     586             :                 // the interface address structure is a 'struct sockaddr_in'
     587             :                 //
     588             :                 if(memcmp(&reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr)->sin_addr,
     589             :                             f_address.sin6_addr.s6_addr32 + 3, //&reinterpret_cast<struct sockaddr_in const *>(&f_address)->sin_addr,
     590             :                             sizeof(struct in_addr)) == 0)
     591             :                 {
     592             :                     return computer_interface_address_t::COMPUTER_INTERFACE_ADDRESS_TRUE;
     593             :                 }
     594             :             }
     595             :             else
     596             :             {
     597             :                 // the interface address structure is a 'struct sockaddr_in6'
     598             :                 //
     599             :                 if(memcmp(&reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_addr)->sin6_addr,
     600             :                             &f_address.sin6_addr,
     601             :                             sizeof(f_address.sin6_addr)) == 0)
     602             :                 {
     603             :                     return computer_interface_address_t::COMPUTER_INTERFACE_ADDRESS_TRUE;
     604             :                 }
     605             :             }
     606             :         }
     607             :     }
     608             : 
     609             :     return computer_interface_address_t::COMPUTER_INTERFACE_ADDRESS_FALSE;
     610             : }
     611             : #endif
     612             : 
     613             : 
     614           6 : }
     615             : // addr namespace
     616             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12