gcontini
2020-05-02 4bd7da9ff2eb06c11b1f54e2b8e2cfb44af56776
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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/string_utils.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