Gabriele Contini
2020-03-15 36ce07093b68b07513149577c209ae7a57ab356b
src/library/os/linux/network.cpp
New file
@@ -0,0 +1,125 @@
/**
 * @file network_id.c
 * @date 16 Sep 2014
 * @brief File containing network interface detection functions for Linux.
 *
 * The only public function of this module is #getAdapterInfos(OsAdapterInfo *,
 *      size_t *), other functions are either static or inline.
 *
 * Responsibility of this module is to fill OsAdapterInfo structures, in a
 * predictable way (skip "lo" interfaces,
 * @TODO: place physical interfaces in front in a repeatable order: "eth", "wlan","ib"
 * and other interfaces later, first the one with a a specified mac address, then
 * the ones with only an ip.)
 */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* To get defns of NI_MAXSERV and NI_MAXHOST */
#endif
#include <arpa/inet.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <linux/if_link.h>
#include <netpacket/packet.h>
#include <stdio.h>
#include <unordered_map>
#include <string.h>
#include <memory.h>
#include "../../base/StringUtils.h"
#include "../../base/logger.h"
#include "../network.hpp"
namespace license {
namespace os {
using namespace std;
/**
 *
 * @param adapterInfos
 * @param adapter_info_size
 * @return
 */
FUNCTION_RETURN getAdapterInfos(vector<OsAdapterInfo> &adapterInfos) {
   unordered_map<string, OsAdapterInfo> adapterByName;
   FUNCTION_RETURN f_return = FUNC_RET_OK;
   struct ifaddrs *ifaddr, *ifa;
   int family, n = 0;
   unsigned int if_num, if_max;
   if (getifaddrs(&ifaddr) == -1) {
      LOG_WARN("getifaddrs failed == -1");
      return FUNC_RET_ERROR;
   }
   for (ifa = ifaddr, n = 0, if_num = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
      if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_LOOPBACK) != 0) {
         continue;
      }
      string if_name(ifa->ifa_name, mstrnlen_s(ifa->ifa_name, NI_MAXHOST));
      // if_name_position = ifname_position(ifnames, ifa->ifa_name, if_num);
      // interface name not seen en advance
      OsAdapterInfo *currentAdapter;
      // FIXME not working
      if (adapterByName.find(if_name) == adapterByName.end()) {
         OsAdapterInfo newAdapter;
         memset(&newAdapter, 0, sizeof(OsAdapterInfo));
         strncpy(&newAdapter.description[0], ifa->ifa_name, NI_MAXHOST);
         adapterByName[if_name] = newAdapter;
      }
      auto it = adapterByName.find(if_name);
      currentAdapter = &it->second;
      family = ifa->ifa_addr->sa_family;
      /* Display interface name and family (including symbolic
       form of the latter for the common families) */
#ifdef _DEBUG
      printf("%-8s %s (%d)\n", ifa->ifa_name,
            (family == AF_PACKET) ? "AF_PACKET"
                            : (family == AF_INET) ? "AF_INET" : (family == AF_INET6) ? "AF_INET6" : "???",
            family);
#endif
      /* For an AF_INET* interface address, display the address
       * || family == AF_INET6*/
      if (family == AF_INET) {
         struct sockaddr_in *s1 = (struct sockaddr_in *)ifa->ifa_addr;
         in_addr_t iaddr = s1->sin_addr.s_addr;
         currentAdapter->ipv4_address[0] = (iaddr & 0x000000ff);
         currentAdapter->ipv4_address[1] = (iaddr & 0x0000ff00) >> 8;
         currentAdapter->ipv4_address[2] = (iaddr & 0x00ff0000) >> 16;
         currentAdapter->ipv4_address[3] = (iaddr & 0xff000000) >> 24;
      } else if (family == AF_PACKET && ifa->ifa_data != NULL) {
         struct sockaddr_ll *s1 = (struct sockaddr_ll *)ifa->ifa_addr;
         int i;
         for (i = 0; i < 6; i++) {
            currentAdapter->mac_address[i] = s1->sll_addr[i];
#ifdef _DEBUG
            printf("%02x:", s1->sll_addr[i]);
#endif
         }
#ifdef _DEBUG
         printf("\t %s\n", ifa->ifa_name);
#endif
      }
   }
   freeifaddrs(ifaddr);
   // FIXME sort by eth , enps, wlan
   if (adapterByName.size() == 0) {
      f_return = FUNC_RET_NOT_AVAIL;
   } else {
      f_return = FUNC_RET_OK;
      adapterInfos.reserve(adapterByName.size());
      for (auto &it : adapterByName) {
         adapterInfos.push_back(it.second);
      }
   }
   return f_return;
}
}  // namespace os
}  // namespace license