From 85d97f05f6f8e4c1d73cd2bb096806839d16f3b0 Mon Sep 17 00:00:00 2001
From: gcontini <1121667+gcontini@users.noreply.github.com>
Date: 周六, 31 10月 2020 10:27:16 +0800
Subject: [PATCH] Pc identifier Mac address issues #108 & #107

---
 src/library/os/linux/network.cpp       |    1 
 test/library/os/network_test.cpp       |    5 +
 src/library/os/network.hpp             |    2 
 test/functional/generate-license.cpp   |    6 +-
 src/library/hw_identifier/ethernet.cpp |   20 ++++--
 src/library/os/windows/network.cpp     |  105 ++++++++++++++++++++++++----------
 src/inspector/inspector.cpp            |    9 ++
 7 files changed, 102 insertions(+), 46 deletions(-)

diff --git a/src/inspector/inspector.cpp b/src/inspector/inspector.cpp
index 640071d..eb23c0e 100644
--- a/src/inspector/inspector.cpp
+++ b/src/inspector/inspector.cpp
@@ -5,6 +5,7 @@
 #include <licensecc/licensecc.h>
 #include <fstream>
 #include <string.h>
+#include <iomanip>
 #include "../library/base/string_utils.h"
 #include "../library/ini/SimpleIni.h"
 #include "../library/os/dmi_info.hpp"
@@ -105,10 +106,14 @@
 				 << static_cast<unsigned int>(osAdapter.ipv4_address[2]) << "-"
 				 << static_cast<unsigned int>(osAdapter.ipv4_address[1]) << "-"
 				 << static_cast<unsigned int>(osAdapter.ipv4_address[0]) << "]" << endl;
-			cout << "   mac address [";
+			cout << "   mac address [" << std::hex;
 			for (int i = 0; i < 8; i++) {
-				// print mac
+				if (i != 0) {
+					cout << ":";
+				}
+				cout << static_cast<unsigned int>(osAdapter.mac_address[i]);
 			}
+			cout << "]" << std::dec << endl;
 		}
 	} else {
 		cout << "problem in getting adapter informations:" << ret << endl;
diff --git a/src/library/hw_identifier/ethernet.cpp b/src/library/hw_identifier/ethernet.cpp
index 55b5197..fe68a51 100644
--- a/src/library/hw_identifier/ethernet.cpp
+++ b/src/library/hw_identifier/ethernet.cpp
@@ -33,17 +33,25 @@
 
 	for (auto &it : adapters) {
 		unsigned int k, data_len;
-		array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> identifier;
+		array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> identifier = {};
 		data_len = use_ip ? sizeof(os::OsAdapterInfo::ipv4_address) : sizeof(os::OsAdapterInfo::mac_address);
-
-		for (k = 0; k < HW_IDENTIFIER_PROPRIETARY_DATA; k++) {
-			if (k < data_len) {
-				identifier[k] = use_ip ? it.ipv4_address[k] : it.mac_address[k];
+		bool all_zero = true;
+		for (k = 0; k < data_len && all_zero;k++) {
+			all_zero = all_zero && ((use_ip ? it.ipv4_address[k] : it.mac_address[k]) == 0);
+		}
+		if (all_zero) {
+			continue;
+		}
+		for (k = 1; k < HW_IDENTIFIER_PROPRIETARY_DATA; k++) {
+			if ((k - 1) < data_len) {
+				identifier[k] =
+						use_ip ? it.ipv4_address[k - 1] : it.mac_address[k - 1];
 			} else {
 				identifier[k] = 42;
 			}
 		}
-		identifier[0] = identifier[0] & 0x1F;
+		//identifier[0] = identifier[0] & 0x1F;
+		identifier[0] = 0;
 		data.push_back(identifier);
 	}
 
diff --git a/src/library/os/linux/network.cpp b/src/library/os/linux/network.cpp
index 1281aca..8720c50 100644
--- a/src/library/os/linux/network.cpp
+++ b/src/library/os/linux/network.cpp
@@ -64,7 +64,6 @@
 		// 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));
diff --git a/src/library/os/network.hpp b/src/library/os/network.hpp
index fd991d3..4dbc9aa 100644
--- a/src/library/os/network.hpp
+++ b/src/library/os/network.hpp
@@ -33,7 +33,7 @@
 typedef struct {
 	int id;
 	char description[LCC_ADAPTER_DESCRIPTION_LEN + 1];
-	unsigned char mac_address[8];
+	unsigned char mac_address[6];
 	unsigned char ipv4_address[4];
 	IFACE_TYPE type;
 } OsAdapterInfo;
diff --git a/src/library/os/windows/network.cpp b/src/library/os/windows/network.cpp
index 1b0d554..5116d39 100644
--- a/src/library/os/windows/network.cpp
+++ b/src/library/os/windows/network.cpp
@@ -9,26 +9,34 @@
  * Responsibility of this module is to fill OsAdapterInfo structures, in a predictable way (skip loopback/vpn interfaces)
  */
 
+#define _CRTDBG_MAP_ALLOC
+#define NOMINMAX
+
 #ifdef _MSC_VER
 #include <Windows.h>
 #endif
 #include <iphlpapi.h>
 #include <unordered_map>
 #include <stdio.h>
+#include <algorithm>
+#include <cctype>
 #pragma comment(lib, "IPHLPAPI.lib")
 
 #include "../../base/string_utils.h"
 #include "../../base/logger.h"
 #include "../network.hpp"
 
+#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
+#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
+
 namespace license {
 namespace os {
 using namespace std;
 
-static int translate(char ipStringIn[16], unsigned char ipv4[4]) {
+static int translate(const char ipStringIn[16], unsigned char ipv4[4]) {
 	size_t index = 0;
 
-	char *str2 = ipStringIn; /* save the pointer */
+	const char *str2 = ipStringIn; /* save the pointer */
 	while (*str2) {
 		if (isdigit((unsigned char)*str2)) {
 			ipv4[index] *= 10;
@@ -40,34 +48,59 @@
 	}
 	return 0;
 }
-/**
+
+int score(const OsAdapterInfo &a) {
+	int score = 0;
+	bool allzero = true;
+	const char *bads[] = {"virtual", "ppp", "tunnel", "vpn"};
+	const char *goods[] = {"realtek", "intel", "wireless"};
+
+	for (int i = 0; i < sizeof(a.description) && allzero; i++) {
+		allzero = allzero && (a.description[i] == 0);
+	}
+	if (!allzero) {
+		score++;
+	}
+
+	string descr=string(a.description);
+	std::transform(descr.begin(), descr.end(), descr.begin(), [](unsigned char c) { return std::tolower(c); });
+	for (auto bad: bads) {
+		score += descr.find(bad) == std::string::npos ? 1 : -1;
+	}
+	for (auto good : goods) {
+		score += descr.find(good) == std::string::npos ? -1 : 1;
+	}
+	return score;
+}
+
+bool cmp(const OsAdapterInfo &a, const OsAdapterInfo &b) { return score(a) >= score(b); }
+	/**
  *
  * @param adapterInfos
  * @param adapter_info_size
  * @return
  */
 FUNCTION_RETURN getAdapterInfos(vector<OsAdapterInfo> &adapterInfos) {
-	unordered_map<string, OsAdapterInfo> adapterByName;
+	vector<OsAdapterInfo> tmpAdapters;
 	FUNCTION_RETURN f_return = FUNC_RET_OK;
 	DWORD dwStatus;
-	PIP_ADAPTER_INFO pAdapterInfo;
-	DWORD dwBufLen = sizeof(IP_ADAPTER_INFO);
 
-	// Make an initial call to GetAdaptersInfo to get the necessary size into the ulOutBufLen variable
-	pAdapterInfo = (PIP_ADAPTER_INFO)malloc(dwBufLen);
+	ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO) *10;
+	IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)MALLOC(sizeof(IP_ADAPTER_INFO) * 10);
+
 	if (pAdapterInfo == nullptr) {
 		return FUNC_RET_ERROR;
 	}
 
-	dwStatus = GetAdaptersInfo(	 // Call GetAdapterInfo
+	dwStatus = GetAdaptersInfo(
 		pAdapterInfo,  // [out] buffer to receive data
-		&dwBufLen  // [in] size of receive data buffer
+		&ulOutBufLen  // [in] size of receive data buffer
 	);
 
 	// Incase the buffer was too small, reallocate with the returned dwBufLen
 	if (dwStatus == ERROR_BUFFER_OVERFLOW) {
-		free(pAdapterInfo);
-		pAdapterInfo = (PIP_ADAPTER_INFO)malloc(dwBufLen);
+		FREE(pAdapterInfo);
+		pAdapterInfo = (IP_ADAPTER_INFO *)MALLOC(ulOutBufLen);
 
 		// Will only fail if buffer cannot be allocated (out of memory)
 		if (pAdapterInfo == nullptr) {
@@ -76,7 +109,7 @@
 
 		dwStatus = GetAdaptersInfo(	 // Call GetAdapterInfo
 			pAdapterInfo,  // [out] buffer to receive data
-			&dwBufLen  // [in] size of receive data buffer
+			&ulOutBufLen  // [in] size of receive data buffer
 		);
 
 		switch (dwStatus) {
@@ -84,38 +117,48 @@
 				break;
 
 			case ERROR_BUFFER_OVERFLOW:
-				free(pAdapterInfo);
+				FREE(pAdapterInfo);
 				return FUNC_RET_BUFFER_TOO_SMALL;
 
 			default:
-				free(pAdapterInfo);
+				FREE(pAdapterInfo);
 				return FUNC_RET_ERROR;
 		}
 	}
 
-	PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
+	IP_ADAPTER_INFO* pAdapter = pAdapterInfo;
 	FUNCTION_RETURN result = FUNC_RET_OK;
 	while (pAdapter) {
-		OsAdapterInfo ai = {};
-		strncpy(ai.description, pAdapter->Description,
-				min((int)sizeof(ai.description), MAX_ADAPTER_DESCRIPTION_LENGTH));
-		memcpy(ai.mac_address, pAdapter->Address, 8);
-		translate(pAdapter->IpAddressList.IpAddress.String, ai.ipv4_address);
-		ai.type = IFACE_TYPE_ETHERNET;
+		if (pAdapter->Type == MIB_IF_TYPE_ETHERNET) {
+			OsAdapterInfo ai = {};
+			LOG_DEBUG("Ethernet found %s, %s, mac_l: %d", pAdapter->AdapterName, pAdapter->Description, pAdapter->AddressLength);
+			if (pAdapter->AddressLength > 0) {
+				bool allzero = true;
+				const size_t size_to_be_copied = std::min(sizeof(ai.mac_address), (size_t)pAdapter->AddressLength);
+				for (int i = 0; i < size_to_be_copied && allzero; i++) {
+					allzero = allzero && (pAdapter->Address[i] == 0);
+				}
+				if (!allzero) {
+					strncpy(ai.description, pAdapter->Description,
+						min(sizeof(ai.description) - 1, (size_t)MAX_ADAPTER_DESCRIPTION_LENGTH));
+					memcpy(ai.mac_address, pAdapter->Address, size_to_be_copied);
+					translate(pAdapter->IpAddressList.IpAddress.String, ai.ipv4_address);
+					ai.type = IFACE_TYPE_ETHERNET;
+					tmpAdapters.push_back(ai);
+				}
+			}
+		}
 		pAdapter = pAdapter->Next;
-		adapterByName[string(ai.description)] = ai;
 	}
-	free(pAdapterInfo);
+	if (pAdapterInfo!=nullptr) {
+		FREE(pAdapterInfo);
+	}
 
-	// FIXME sort by eth , enps, wlan
-	if (adapterByName.size() == 0) {
+	if (tmpAdapters.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);
-		}
+		std::sort(tmpAdapters.begin(), tmpAdapters.end(), cmp);
+		adapterInfos = std::move(tmpAdapters);
 	}
 	return f_return;
 }
diff --git a/test/functional/generate-license.cpp b/test/functional/generate-license.cpp
index cdaa175..a1a760a 100644
--- a/test/functional/generate-license.cpp
+++ b/test/functional/generate-license.cpp
@@ -48,11 +48,11 @@
 	}
 	cout << "executing :" << ss.str() << endl;
 	const int retCode = std::system(ss.str().c_str());
-	BOOST_CHECK_EQUAL(retCode, 0);
-	BOOST_ASSERT_MSG(fs::exists(license_fname), "license exists");
+	BOOST_REQUIRE_EQUAL(retCode, 0);
+	BOOST_REQUIRE_MESSAGE(fs::exists(license_fname), "license exists");
 	CSimpleIniA ini;
 	const SI_Error rc = ini.LoadFile(license_fname.c_str());
-	BOOST_CHECK_GE(rc, 0);
+	BOOST_REQUIRE_GE(rc, 0);
 	const int sectionSize = ini.GetSectionSize(LCC_PROJECT_NAME);
 	BOOST_CHECK_GT(sectionSize, 0);
 	return license_fname.string();
diff --git a/test/library/os/network_test.cpp b/test/library/os/network_test.cpp
index 50e4254..ac599d8 100644
--- a/test/library/os/network_test.cpp
+++ b/test/library/os/network_test.cpp
@@ -18,8 +18,8 @@
 
 BOOST_AUTO_TEST_CASE(read_network_adapters) {
 	std::vector<license::os::OsAdapterInfo> adapters;
-	// we can suppose every test environment  other than docker has at least one network interface (it's hard to
-	// download this source code)
+	// we can suppose every test environment other than docker has at least
+	// one network interface
 	FUNCTION_RETURN result = getAdapterInfos(adapters);
 	ExecutionEnvironment exec_env;
 	if (result != FUNC_RET_OK && exec_env.is_docker()) {
@@ -27,6 +27,7 @@
 		return;
 	}
 	BOOST_CHECK_EQUAL(result, FUNC_RET_OK);
+	BOOST_CHECK_GT(adapters.size(),0);
 	for (auto& it : adapters) {
 		cout << "Interface found: " << string(it.description) << endl;
 		BOOST_CHECK_GT(strlen(it.description), 0);

--
Gitblit v1.9.1