From 0288790e61dec962f43b4ebf4a4fa3057dbd2d02 Mon Sep 17 00:00:00 2001
From: open-license-manager <rillf@maildrop.cc>
Date: 周一, 21 4月 2014 18:14:24 +0800
Subject: [PATCH] network adapter detection linux

---
 src/library/CMakeLists.txt              |    1 
 src/library/os/linux/os-linux.cpp       |   74 +---
 src/library/pc-identifiers.h            |   20 +
 .gitignore                              |    1 
 src/library/api/datatypes.h             |   33 +-
 src/library/api/license++.h             |    4 
 src/library/os/os.h                     |   47 +++
 src/library/license++.cpp               |    4 
 src/library/os/linux/os-linux.c         |  211 +++++++++++++++
 src/library/LicenseReader.h             |    2 
 src/library/pc-identifiers.c            |  194 +++++++++++++
 src/library/os/os-cpp.h                 |   31 ++
 test/library/CMakeLists.txt             |   20 +
 src/library/base/EventRegistry.h        |    2 
 /dev/null                               |   50 ---
 src/library/base/base.h                 |   28 ++
 test/license-generator/CMakeLists.txt   |    2 
 src/library/LicenseReader.cpp           |    4 
 test/library/Os_Linux_test.cpp          |   50 +++
 src/library/os/linux/CMakeLists.txt     |    1 
 src/license-generator/LicenseSigner.cpp |    4 
 21 files changed, 657 insertions(+), 126 deletions(-)

diff --git a/.gitignore b/.gitignore
index d97328f..1dc413f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@
 *.la
 *.a
 /Makefile
+/Testing
diff --git a/src/library/CMakeLists.txt b/src/library/CMakeLists.txt
index 4322104..47bc4ba 100644
--- a/src/library/CMakeLists.txt
+++ b/src/library/CMakeLists.txt
@@ -9,6 +9,7 @@
 ADD_LIBRARY(license++_static STATIC
     license++.cpp
     LicenseReader.cpp
+    pc-identifiers.c
 )
 
 target_link_libraries(
diff --git a/src/library/LicenseReader.cpp b/src/library/LicenseReader.cpp
index 6e1c064..093b276 100644
--- a/src/library/LicenseReader.cpp
+++ b/src/library/LicenseReader.cpp
@@ -23,7 +23,7 @@
 #include "base/public-key.h"
 #include <build_properties.h>
 
-#include "os/os.hpp"
+#include "os/os-cpp.h"
 
 namespace license {
 
@@ -47,7 +47,7 @@
 
 EventRegistry FullLicenseInfo::validate(int sw_version) {
 	EventRegistry er;
-	OsFunctions::initialize();
+	os_initialize();
 	bool sigVerified = OsFunctions::verifySignature(printForSign().c_str(),
 			license_signature.c_str());
 	if (sigVerified) {
diff --git a/src/library/LicenseReader.h b/src/library/LicenseReader.h
index a172e1a..10b4f0e 100644
--- a/src/library/LicenseReader.h
+++ b/src/library/LicenseReader.h
@@ -10,7 +10,7 @@
 
 #include "api/datatypes.h"
 #include "base/EventRegistry.h"
-#include "os/os.hpp"
+#include "os/os.h"
 #define SI_SUPPORT_IOSTREAMS
 #include "ini/SimpleIni.h"
 #include <string>
diff --git a/src/library/api/datatypes.h b/src/library/api/datatypes.h
index fb730c1..dad399e 100644
--- a/src/library/api/datatypes.h
+++ b/src/library/api/datatypes.h
@@ -11,9 +11,10 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
+
 #ifdef __unix__
 #define DllExport
-#define MAX_PATH 1024
 #else
 #include <windows.h>
 #define DllExport  __declspec( dllexport )
@@ -26,39 +27,37 @@
 #define LICENESE_INT_VERSION 100
 #define LICENSEPP_VERSION "1.0.0"
 
-enum EVENT_TYPE {
+typedef enum {
 	LICENSE_OK = 0, 						//OK
 	LICENSE_FILE_NOT_FOUND = 1, 		//license file not found
 	LICENSE_SERVER_NOT_FOUND = 2, 		//license server can't be contacted
 	ENVIRONMENT_VARIABLE_NOT_DEFINED = 3, //environment variable not defined
 	FILE_FORMAT_NOT_RECOGNIZED = 4,	//license file has invalid format (not .ini file)
-	LICENSE_MALFORMED = 5,          //some mandatory field are missing, or data can't be fully read.
+	LICENSE_MALFORMED = 5, //some mandatory field are missing, or data can't be fully read.
 	PRODUCT_NOT_LICENSED = 6,		//this product was not licensed
 	PRODUCT_EXPIRED = 7,
-	LICENSE_CORRUPTED = 8,		//License signature didn't match with current license
-	IDENTIFIERS_MISMATCH = 9,   //Calculated identifier and the one provided in license didn't match
+	LICENSE_CORRUPTED = 8,//License signature didn't match with current license
+	IDENTIFIERS_MISMATCH = 9, //Calculated identifier and the one provided in license didn't match
 
 	LICENSE_FILE_FOUND = 100,
 	LICENSE_VERIFIED = 101
 
-};
+}  EVENT_TYPE;
 
-enum LICENSE_TYPE {
+typedef enum {
 	LOCAL, REMOTE //remote licenses are not supported now.
-};
+}  LICENSE_TYPE;
 
-enum SEVERITY {
+typedef enum {
 	INFO, SEVERITY_WARN, SEVERITY_ERROR
-};
+} SEVERITY;
 
-
-
-struct AuditEvent {
+typedef struct {
 	SEVERITY severity;
 	EVENT_TYPE event_type;
 	char param1[256];
 	char param2[256];
-};
+} AuditEvent;
 
 typedef struct {
 	const char *licenseFileLocation;
@@ -85,7 +84,7 @@
 	/* A string of character inserted into the license understood
 	 * by the calling application.
 	 * '\0' if the application didn't specify one */
-	char proprietary_data[PROPRIETARY_DATA_SIZE+1];
+	char proprietary_data[PROPRIETARY_DATA_SIZE + 1];
 	int license_version; //license file version
 } LicenseInfo;
 
@@ -93,9 +92,9 @@
  * Enum to select a specific pc identification_strategy. DEFAULT Should be used
  * in most cases.
  */
-enum IDENTIFICATION_STRATEGY {
+typedef enum {
 	DEFAULT, ETHERNET, IP_ADDRESS, DISK_NUM, DISK_LABEL
-};
+} IDENTIFICATION_STRATEGY;
 
 #ifdef __cplusplus
 }
diff --git a/src/library/api/license++.h b/src/library/api/license++.h
index 713692a..b56a0e9 100644
--- a/src/library/api/license++.h
+++ b/src/library/api/license++.h
@@ -51,12 +51,12 @@
  * Should be called from time to time to confirm we're still using the
  * slicense.
  */
-DllExport enum EVENT_TYPE confirm_license(char * productName,
+DllExport EVENT_TYPE confirm_license(char * productName,
 		LicenseLocation licenseLocation);
 /**
  * Do nothing for now, useful for network licenses.
  */
-DllExport enum EVENT_TYPE release_license(char * productName,
+DllExport EVENT_TYPE release_license(char * productName,
 		LicenseLocation licenseLocation);
 
 #ifdef __cplusplus
diff --git a/src/library/base/EventRegistry.h b/src/library/base/EventRegistry.h
index 0ef229b..310a430 100644
--- a/src/library/base/EventRegistry.h
+++ b/src/library/base/EventRegistry.h
@@ -38,7 +38,7 @@
 	/**
 	 * @return NULL if no failures are found.
 	 */
-	AuditEvent const  * getLastFailure() const;
+	AuditEvent const * getLastFailure() const;
 	bool isGood() const;
 
 	void addError(EVENT_TYPE event);
diff --git a/src/library/base/base.h b/src/library/base/base.h
new file mode 100644
index 0000000..eccdb76
--- /dev/null
+++ b/src/library/base/base.h
@@ -0,0 +1,28 @@
+#ifndef BASE_H_
+#define BASE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __unix__
+#include <limits.h>
+#define DllExport
+#define MAX_PATH PATH_MAX
+#else
+#include <windows.h>
+#define DllExport  __declspec( dllexport )
+#endif
+
+#define _DEBUG
+
+typedef enum  {
+	OK, NOOK, ERROR, BUFFER_TOO_SMALL
+} FUNCTION_RETURN;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/library/license++.cpp b/src/library/license++.cpp
index 414fd37..9ed9fd4 100644
--- a/src/library/license++.cpp
+++ b/src/library/license++.cpp
@@ -75,12 +75,12 @@
 	return result;
 }
 
-DllExport enum EVENT_TYPE confirm_license(char * product,
+DllExport EVENT_TYPE confirm_license(char * product,
 		LicenseLocation licenseLocation) {
 	return LICENSE_OK;
 }
 
-DllExport enum EVENT_TYPE release_license(char * product,
+DllExport EVENT_TYPE release_license(char * product,
 		LicenseLocation licenseLocation) {
 	return LICENSE_OK;
 }
diff --git a/src/library/os/linux/CMakeLists.txt b/src/library/os/linux/CMakeLists.txt
index 436f2fb..1bdbb26 100644
--- a/src/library/os/linux/CMakeLists.txt
+++ b/src/library/os/linux/CMakeLists.txt
@@ -1,4 +1,5 @@
 ADD_LIBRARY(os STATIC
+	os-linux.c
     os-linux.cpp
 )
 
diff --git a/src/library/os/linux/os-linux.c b/src/library/os/linux/os-linux.c
new file mode 100644
index 0000000..b316c17
--- /dev/null
+++ b/src/library/os/linux/os-linux.c
@@ -0,0 +1,211 @@
+#define _GNU_SOURCE     /* To get defns of NI_MAXSERV and NI_MAXHOST */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/if_link.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+
+#include <paths.h>
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "../os.h"
+#include "../../base/public-key.h"
+
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+static int ifname_position(char *ifnames, char * ifname, int ifnames_max) {
+	int i, position;
+	position = -1;
+	for (i = 0; i < ifnames_max; i++) {
+		if (strcmp(ifname, &ifnames[i * NI_MAXHOST]) == 0) {
+			position = i;
+			break;
+		}
+	}
+	return position;
+
+}
+
+FUNCTION_RETURN getAdapterInfos(AdapterInfo * adapterInfos,
+		size_t * adapter_info_size) {
+
+	FUNCTION_RETURN f_return = OK;
+	struct ifaddrs *ifaddr, *ifa;
+	int family, i, s, n, if_name_position;
+	unsigned int if_num, if_max;
+	char host[NI_MAXHOST];
+	char *ifnames;
+
+	if (getifaddrs(&ifaddr) == -1) {
+		perror("getifaddrs");
+		return ERROR;
+	}
+	/* count the maximum number of interfaces */
+	for (ifa = ifaddr, if_max = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
+		if (ifa->ifa_addr == NULL) {
+			continue;
+		}
+		if_max++;
+	}
+
+	/* allocate space for names */
+	ifnames = (char*) malloc(NI_MAXHOST * if_max);
+	memset(ifnames, 0, NI_MAXHOST * if_max);
+	/* Walk through linked list, maintaining head pointer so we
+	 can free list later */
+	for (ifa = ifaddr, n = 0, if_num = 0; ifa != NULL;
+			ifa = ifa->ifa_next, n++) {
+		if (ifa->ifa_addr == NULL) {
+			continue;
+		}
+		if_name_position = ifname_position(ifnames, ifa->ifa_name, if_num);
+		//interface name not seen en advance
+		if (if_name_position < 0) {
+			strncpy(&ifnames[if_num * NI_MAXHOST], ifa->ifa_name, NI_MAXHOST);
+			if (adapterInfos != NULL && if_num < *adapter_info_size) {
+				strncpy(adapterInfos[if_num].description, ifa->ifa_name,
+						NI_MAXHOST);
+			}
+			if_name_position = if_num;
+			if_num++;
+			if (adapterInfos == NULL) {
+				continue;
+			}
+		}
+		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) {
+			/*
+			 s = getnameinfo(ifa->ifa_addr,
+			 (family == AF_INET) ?
+			 sizeof(struct sockaddr_in) :
+			 sizeof(struct sockaddr_in6), host, NI_MAXHOST,
+			 NULL, 0, NI_NUMERICHOST);
+			 */
+#ifdef _DEBUG
+			s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host,
+			NI_MAXHOST,
+			NULL, 0, NI_NUMERICHOST);
+			if (s != 0) {
+				printf("getnameinfo() failed: %s\n", gai_strerror(s));
+			}
+			printf("\t\taddress: <%s>\n", host);
+#endif
+
+			if (adapterInfos != NULL && if_name_position < *adapter_info_size) {
+				struct sockaddr_in *s1 = (struct sockaddr_in*) ifa->ifa_addr;
+				in_addr_t iaddr = s1->sin_addr.s_addr;
+				adapterInfos[if_name_position].ipv4_address[0] = (iaddr
+						& 0x000000ff);
+				adapterInfos[if_name_position].ipv4_address[1] = (iaddr
+						& 0x0000ff00) >> 8;
+				adapterInfos[if_name_position].ipv4_address[2] = (iaddr
+						& 0x00ff0000) >> 16;
+				adapterInfos[if_name_position].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;
+			if (adapterInfos != NULL && if_name_position < *adapter_info_size) {
+				for (i = 0; i < 6; i++) {
+					adapterInfos[if_name_position].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
+
+			}
+		}
+	}
+
+	*adapter_info_size = if_num;
+	if (adapterInfos == NULL) {
+		f_return = OK;
+	} else if (*adapter_info_size < if_num) {
+		f_return = BUFFER_TOO_SMALL;
+	}
+	freeifaddrs(ifaddr);
+	return f_return;
+}
+
+FUNCTION_RETURN getDiskInfos(DiskInfo * diskInfos, size_t * disk_info_size) {
+	struct stat filename_stat, mount_stat;
+	static char discard[1024];
+	char device[64], name[64], type[64];
+	FILE *mounts = fopen(_PATH_MOUNTED, "r");
+	if (mounts == NULL) {
+		return ERROR;
+	}
+
+	while (fscanf(mounts, "%64s %64s %64s %1024[^\n]", device, name, type,
+			discard) != EOF) {
+		if (stat(device, &mount_stat) != 0)
+			continue;
+		if (filename_stat.st_dev == mount_stat.st_rdev) {
+			fprintf(stderr, "device: %s; name: %s; type: %s\n", device, name,
+					type);
+		}
+	}
+
+	return ERROR;
+}
+
+void os_initialize() {
+	static int initialized = 0;
+	if (initialized == 0) {
+		initialized = 1;
+		ERR_load_ERR_strings();
+		ERR_load_crypto_strings();
+		OpenSSL_add_all_algorithms();
+	}
+}
+
+VIRTUALIZATION getVirtualization() {
+//http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
+//
+//bool rc = true;
+	/*__asm__ (
+	 "push   %edx\n"
+	 "push   %ecx\n"
+	 "push   %ebx\n"
+	 "mov    %eax, 'VMXh'\n"
+	 "mov    %ebx, 0\n" // any value but not the MAGIC VALUE
+	 "mov    %ecx, 10\n"// get VMWare version
+	 "mov    %edx, 'VX'\n"// port number
+	 "in     %eax, dx\n"// read port on return EAX returns the VERSION
+	 "cmp    %ebx, 'VMXh'\n"// is it a reply from VMWare?
+	 "setz   [rc] \n"// set return value
+	 "pop    %ebx \n"
+	 "pop    %ecx \n"
+	 "pop    %edx \n"
+	 );*/
+
+	return NONE;
+}
+
diff --git a/src/library/os/linux/os-linux.cpp b/src/library/os/linux/os-linux.cpp
index eb515b2..722c8ad 100644
--- a/src/library/os/linux/os-linux.cpp
+++ b/src/library/os/linux/os-linux.cpp
@@ -1,5 +1,17 @@
-#include <paths.h>
+#define _GNU_SOURCE     /* To get defns of NI_MAXSERV and NI_MAXHOST */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <ifaddrs.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/if_link.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+
+#include <paths.h>
+
 #include <stdlib.h>
 #include <cstring>
 #include <string>
@@ -8,8 +20,9 @@
 #include <sstream>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
-#include "../os.hpp"
+#include "../os-cpp.h"
 #include "../../base/public-key.h"
+
 #include <openssl/evp.h>
 #include <openssl/bio.h>
 #include <openssl/pem.h>
@@ -18,27 +31,6 @@
 namespace license {
 
 using namespace std;
-
-vector<AdapterInfo> OsFunctions::getAdapterInfos() {
-	return vector<AdapterInfo>();
-}
-vector<DiskInfo> OsFunctions::getDiskInfos() {
-	struct stat filename_stat, mount_stat;
-	static char discard[1024];
-	char device[64], name[64], type[64];
-	FILE *mounts = fopen(_PATH_MOUNTED, "r");
-
-	while (fscanf(mounts, "%64s %64s %64s %1024[^\n]", device, name, type,
-			discard) != EOF) {
-		if (stat(device, &mount_stat) != 0)
-			continue;
-		if (filename_stat.st_dev == mount_stat.st_rdev)
-			fprintf(stderr, "device: %s; name: %s; type: %s\n", device, name,
-					type);
-	}
-
-	return vector<DiskInfo>();
-}
 
 string OsFunctions::getModuleName() {
 	char path[2048] = { 0 };
@@ -59,9 +51,7 @@
 	return result;
 }
 
-string OsFunctions::getUserHomePath() {
-	return "";
-}
+
 
 bool OsFunctions::verifySignature(const char* stringToVerify,
 		const char* signatureB64) {
@@ -86,8 +76,8 @@
 	 PEM_read_bio_RSAPublicKey(bo, &key, 0, 0);
 	 BIO_free(bo);*/
 
-	//RSA* rsa = EVP_PKEY_get1_RSA( key );
-	//RSA * pubKey = d2i_RSA_PUBKEY(NULL, <der encoded byte stream pointer>, <num bytes>);
+//RSA* rsa = EVP_PKEY_get1_RSA( key );
+//RSA * pubKey = d2i_RSA_PUBKEY(NULL, <der encoded byte stream pointer>, <num bytes>);
 	unsigned char buffer[512];
 	BIO* b64 = BIO_new(BIO_f_base64());
 	BIO* encoded_signature = BIO_new_mem_buf((void *) signatureB64,
@@ -95,7 +85,7 @@
 	BIO* biosig = BIO_push(b64, encoded_signature);
 	BIO_set_flags(biosig, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
 	unsigned int len = BIO_read(biosig, (void *) buffer, strlen(signatureB64));
-	//Can test here if len == decodeLen - if not, then return an error
+//Can test here if len == decodeLen - if not, then return an error
 	buffer[len] = 0;
 
 	BIO_free_all(biosig);
@@ -107,14 +97,12 @@
 	if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey)) {
 		throw new logic_error("Error initializing digest");
 	}
-	int en=strlen(stringToVerify);
-	if (1
-			!= EVP_DigestVerifyUpdate(mdctx, stringToVerify,
-					en)) {
+	int en = strlen(stringToVerify);
+	if (1 != EVP_DigestVerifyUpdate(mdctx, stringToVerify, en)) {
 		throw new logic_error("Error verifying digest");
 	}
 	bool result;
-	int res= EVP_DigestVerifyFinal(mdctx, buffer, len);
+	int res = EVP_DigestVerifyFinal(mdctx, buffer, len);
 	if (1 == res) {
 		result = true;
 	} else {
@@ -129,20 +117,12 @@
 	return result;
 }
 
-void OsFunctions::initialize() {
-	static bool initialized = false;
-	if (!initialized) {
-		initialized = true;
-		ERR_load_ERR_strings();
-		ERR_load_crypto_strings();
-		OpenSSL_add_all_algorithms();
-	}
-}
 
-VIRTUALIZATION OsFunctions::getVirtualization() {
-	//http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
-	//
-	bool rc = true;
+
+VIRTUALIZATION getVirtualization() {
+//http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
+//
+//bool rc = true;
 	/*__asm__ (
 	 "push   %edx\n"
 	 "push   %ecx\n"
diff --git a/src/library/os/os-cpp.h b/src/library/os/os-cpp.h
new file mode 100644
index 0000000..bf43d3a
--- /dev/null
+++ b/src/library/os/os-cpp.h
@@ -0,0 +1,31 @@
+/*
+ * os-dependent.hpp
+ *
+ *  Created on: Mar 29, 2014
+ *      Author: devel
+ */
+
+#ifndef OS_DEPENDENT_CPP_
+#define OS_DEPENDENT_CPP_
+
+/* deprecated: all os dependent functions have been implemented in C*/
+#include "os.h"
+
+namespace license {
+using namespace std;
+
+
+
+class OsFunctions {
+public:
+
+	static string getModuleName();
+	//use system dependent methods to verify signature
+	static bool verifySignature(const char * stringToVerify,
+			const char* signature);
+
+};
+
+}
+
+#endif /* OS_DEPENDENT_HPP_ */
diff --git a/src/library/os/os.h b/src/library/os/os.h
new file mode 100644
index 0000000..7e0e3e7
--- /dev/null
+++ b/src/library/os/os.h
@@ -0,0 +1,47 @@
+/*
+ * os-dependent.hpp
+ *
+ *  Created on: Mar 29, 2014
+ *      Author: devel
+ */
+
+#ifndef OS_DEPENDENT_HPP_
+#define OS_DEPENDENT_HPP_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../base/base.h"
+#include <stddef.h>
+
+typedef enum {
+	NONE, VMWARE
+} VIRTUALIZATION;
+
+typedef struct {
+	int id;
+	char description[1024];
+	unsigned char mac_address[6];
+	unsigned char ipv4_address[4];
+} AdapterInfo;
+
+typedef struct {
+	int id;
+	char device[255];
+	unsigned char disk_sn[8];
+	char label[255];
+} DiskInfo;
+
+FUNCTION_RETURN getAdapterInfos(AdapterInfo * adapterInfos,
+		size_t * adapter_info_size);
+FUNCTION_RETURN getDiskInfos(DiskInfo * diskInfos, size_t * disk_info_size);
+FUNCTION_RETURN getUserHomePath(char[MAX_PATH]);
+VIRTUALIZATION getVirtualization();
+void os_initialize();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OS_DEPENDENT_HPP_ */
diff --git a/src/library/os/os.hpp b/src/library/os/os.hpp
deleted file mode 100644
index d8a9795..0000000
--- a/src/library/os/os.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * os-dependent.hpp
- *
- *  Created on: Mar 29, 2014
- *      Author: devel
- */
-
-#ifndef OS_DEPENDENT_HPP_
-#define OS_DEPENDENT_HPP_
-
-#include <string>
-#include <vector>
-
-namespace license {
-using namespace std;
-
-enum VIRTUALIZATION {
-	NONE,VMWARE
-};
-
-struct AdapterInfo {
-	int id;
-	string description;
-	unsigned char mac_address[8];
-	unsigned char ipv4_address[4];
-};
-
-struct DiskInfo {
-	int id;
-	string device;
-	unsigned char disk_sn[8];
-	string label;
-};
-
-class OsFunctions {
-public:
-	static void initialize();
-	static vector<AdapterInfo> getAdapterInfos();
-	static vector<DiskInfo> getDiskInfos();
-	static string getModuleName();
-	static string getUserHomePath();
-	//use system dependent methods to verify signature
-	static bool verifySignature(const char * stringToVerify, const char* signature);
-	static VIRTUALIZATION getVirtualization();
-};
-
-}
-
-
-#endif /* OS_DEPENDENT_HPP_ */
diff --git a/src/library/pc-identifiers.c b/src/library/pc-identifiers.c
new file mode 100644
index 0000000..a4ea81c
--- /dev/null
+++ b/src/library/pc-identifiers.c
@@ -0,0 +1,194 @@
+/*
+ * pc-identifiers.c
+ *
+ *  Created on: Apr 16, 2014
+ *      Author: devel
+ */
+
+#include "os/os.h"
+#include "pc-identifiers.h"
+#include <stdlib.h>
+#include <stdbool.h>
+
+static FUNCTION_RETURN generate_default_pc_id(PcIdentifier * identifiers,
+		unsigned int * num_identifiers) {
+	size_t adapter_num, disk_num;
+	FUNCTION_RETURN result_adapterInfos, result_diskinfos;
+	unsigned int required_id_size, i, j, k;
+	DiskInfo * diskInfos;
+	AdapterInfo *adapterInfos;
+
+	result_adapterInfos = getAdapterInfos(NULL, &adapter_num);
+	if (result_adapterInfos != OK) {
+		//call generate_disk_pc_id;
+		return result_adapterInfos;
+	}
+	result_diskinfos = getDiskInfos(NULL, &disk_num);
+	if (result_diskinfos == OK) {
+		required_id_size = disk_num * adapter_num;
+	} else {
+		required_id_size = disk_num;
+	}
+	if (identifiers == NULL) {
+		*num_identifiers = required_id_size;
+		return OK;
+	} else if (*num_identifiers < required_id_size) {
+		*num_identifiers = required_id_size;
+		return BUFFER_TOO_SMALL;
+	}
+	diskInfos = (DiskInfo*) malloc(disk_num * sizeof(DiskInfo));
+	result_diskinfos = getDiskInfos(diskInfos, &disk_num);
+	adapterInfos = (AdapterInfo*) malloc(adapter_num * sizeof(AdapterInfo));
+	result_adapterInfos = getAdapterInfos(adapterInfos, &adapter_num);
+	for (i = 0; i < disk_num; i++) {
+		for (j = 0; j < adapter_num; i++) {
+			for (k = 0; k < 6; k++)
+				identifiers[i * adapter_num + j][k] = diskInfos[i].disk_sn[k
+						+ 2] ^ adapterInfos[j].mac_address[k + 2];
+		}
+	}
+
+	free(diskInfos);
+	free(adapterInfos);
+	return OK;
+}
+
+static FUNCTION_RETURN generate_ethernet_pc_id(PcIdentifier * identifiers,
+		unsigned int * num_identifiers, bool use_mac) {
+	size_t adapters;
+	FUNCTION_RETURN result_adapterInfos;
+	unsigned int i, j, k;
+	AdapterInfo *adapterInfos;
+
+	result_adapterInfos = getAdapterInfos(NULL, &adapters);
+	if (result_adapterInfos != OK) {
+		return result_adapterInfos;
+	}
+	if (identifiers == NULL) {
+		*num_identifiers = adapters;
+		return OK;
+	} else if (*num_identifiers < adapters) {
+		*num_identifiers = adapters;
+		return BUFFER_TOO_SMALL;
+	}
+	adapterInfos = (AdapterInfo*) malloc(adapters * sizeof(AdapterInfo));
+	result_adapterInfos = getAdapterInfos(adapterInfos, &adapters);
+	for (j = 0; j < adapters; i++) {
+		for (k = 0; k < 6; k++)
+			if (use_mac) {
+				identifiers[j][k] = adapterInfos[j].mac_address[k + 2];
+			} else {
+				//use ip
+				if (k < 4) {
+					identifiers[j][k] = adapterInfos[j].ipv4_address[k];
+				} else {
+					//padding
+					identifiers[j][k] = 42;
+				}
+			}
+	}
+	free(adapterInfos);
+	return OK;
+}
+
+static FUNCTION_RETURN generate_disk_pc_id(PcIdentifier * identifiers,
+		unsigned int * num_identifiers, bool use_label) {
+	size_t disk_num;
+	FUNCTION_RETURN result_diskinfos;
+	unsigned int required_id_size, i, k;
+	DiskInfo * diskInfos;
+
+	result_diskinfos = getDiskInfos(NULL, &disk_num);
+	if (result_diskinfos != OK) {
+		return result_diskinfos;
+	}
+	if (identifiers == NULL) {
+		*num_identifiers = disk_num;
+		return OK;
+	} else if (*num_identifiers < disk_num) {
+		*num_identifiers = disk_num;
+		return BUFFER_TOO_SMALL;
+	}
+	diskInfos = (DiskInfo*) malloc(disk_num * sizeof(DiskInfo));
+	result_diskinfos = getDiskInfos(diskInfos, &disk_num);
+
+	for (i = 0; i < disk_num; i++) {
+		for (k = 0; k < 6; k++) {
+			if (use_label) {
+				identifiers[i][k] = diskInfos[i].label[k];
+			} else {
+				identifiers[i][k] = diskInfos[i].disk_sn[k + 2];
+			}
+		}
+	}
+	free(diskInfos);
+	return OK;
+}
+
+/**
+ *
+ * Calculates all the possible identifiers for the current machine, for the
+ * given calculation strategy requested. Pc identifiers are more than one,
+ * for instance a machine with more than one disk and one network interface has
+ * usually multiple identifiers.
+ *
+ * @param identifiers
+ * @param array_size
+ * @param
+ * @return
+ */
+FUNCTION_RETURN generate_pc_id(PcIdentifier * identifiers,
+		unsigned int * array_size, IDENTIFICATION_STRATEGY strategy) {
+	FUNCTION_RETURN result;
+	unsigned int i;
+	unsigned char strategy_num;
+	switch (strategy) {
+	case DEFAULT:
+		result = generate_default_pc_id(identifiers, array_size);
+		break;
+	case ETHERNET:
+		result = generate_ethernet_pc_id(identifiers, array_size, false);
+		break;
+	case IP_ADDRESS:
+		result = generate_ethernet_pc_id(identifiers, array_size, false);
+		break;
+	case DISK_NUM:
+		result = generate_disk_pc_id(identifiers, array_size, false);
+		break;
+	case DISK_LABEL:
+		result = generate_disk_pc_id(identifiers, array_size, false);
+		break;
+	default:
+		return ERROR;
+	}
+
+	if (result == OK && identifiers != NULL) {
+		strategy_num = strategy << 5;
+		for (i = 0; i < *array_size; i++) {
+			//encode strategy in the first three bits of the pc_identifier
+			identifiers[i][0] = (identifiers[i][0] & 31) | strategy_num;
+		}
+	}
+	return result;
+}
+
+FUNCTION_RETURN encode_pc_id(PcIdentifier identifier1, PcIdentifier identifier2,
+		UserPcIdentifier* pc_identifier_out) {
+
+}
+
+FUNCTION_RETURN parity_check_id(UserPcIdentifier pc_identifier) {
+
+}
+
+/**
+ * Extract the two pc identifiers from the user provided code.
+ * @param identifier1_out
+ * @param identifier2_out
+ * @param str_code: the code in the string format XXXX-XXXX-XXXX-XXXX
+ * @return
+ */
+int decode_pc_id(PcIdentifier* identifier1_out, PcIdentifier* identifier2_out,
+		UserPcIdentifier str_code) {
+
+}
diff --git a/src/library/pc-identifiers.h b/src/library/pc-identifiers.h
new file mode 100644
index 0000000..99d50c0
--- /dev/null
+++ b/src/library/pc-identifiers.h
@@ -0,0 +1,20 @@
+/*
+ * pc-identifiers.h
+ *
+ *  Created on: Apr 16, 2014
+ *      Author: devel
+ */
+
+#ifndef PC_IDENTIFIERS_H_
+#define PC_IDENTIFIERS_H_
+#include "api/datatypes.h"
+#include "base/base.h"
+
+typedef unsigned char PcIdentifier[6];
+typedef char UserPcIdentifier[21];
+
+
+FUNCTION_RETURN generate_pc_id(PcIdentifier * identifiers, unsigned int * array_size,
+		IDENTIFICATION_STRATEGY strategy);
+
+#endif /* PC_IDENTIFIERS_H_ */
diff --git a/src/license-generator/LicenseSigner.cpp b/src/license-generator/LicenseSigner.cpp
index f24472b..908cd46 100644
--- a/src/license-generator/LicenseSigner.cpp
+++ b/src/license-generator/LicenseSigner.cpp
@@ -20,11 +20,11 @@
 using namespace std;
 
 LicenseSigner::LicenseSigner() {
-	OsFunctions::initialize();
+	os_initialize();
 }
 
 LicenseSigner::LicenseSigner(const std::string& alternatePrimaryKey) {
-	OsFunctions::initialize();
+	os_initialize();
 }
 
 string LicenseSigner::Opensslb64Encode(size_t slen, unsigned char* signature) {
diff --git a/test/library/CMakeLists.txt b/test/library/CMakeLists.txt
index c8c638c..d4067c2 100644
--- a/test/library/CMakeLists.txt
+++ b/test/library/CMakeLists.txt
@@ -12,4 +12,22 @@
 )
 
 SET_TARGET_PROPERTIES(license_reader_test PROPERTIES LINK_SEARCH_START_STATIC ON)
-ADD_TEST(license_reader_test ${EXECUTABLE_OUTPUT_PATH}/LicenseReader_test)
+ADD_TEST(license_reader_test ${EXECUTABLE_OUTPUT_PATH}/license_reader_test)
+
+IF(WIN32)
+#test windows
+ELSE(WIN32)
+    add_executable(
+ 		os_linux_test
+ 		Os_Linux_test.cpp
+	)
+
+	target_link_libraries(
+ 		os_linux_test
+ 		os
+ 		${Boost_LIBRARIES}
+	)
+
+	SET_TARGET_PROPERTIES(os_linux_test PROPERTIES LINK_SEARCH_START_STATIC ON)
+	ADD_TEST(os_linux_test ${EXECUTABLE_OUTPUT_PATH}/os_linux_test)   
+ENDIF(WIN32)
\ No newline at end of file
diff --git a/test/library/Os_Linux_test.cpp b/test/library/Os_Linux_test.cpp
new file mode 100644
index 0000000..ea92662
--- /dev/null
+++ b/test/library/Os_Linux_test.cpp
@@ -0,0 +1,50 @@
+#define BOOST_TEST_MODULE os_linux_test
+//#define BOOST_TEST_MAIN
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include "../../src/library/os/os.h"
+#include <build_properties.h>
+
+#include <string>
+#include <iostream>
+using namespace std;
+
+/*
+ BOOST_AUTO_TEST_CASE( read_disk_id ) {
+ DiskInfo * diskInfos = NULL;
+ size_t disk_info_size =0;
+ FUNCTION_RETURN result = getDiskInfos(NULL, & disk_info_size);
+ BOOST_CHECK_EQUAL(result, OK);
+ BOOST_CHECK_GT(disk_info_size, 0);
+ diskInfos = (DiskInfo*)malloc(sizeof(DiskInfo) * disk_info_size);
+ result = getDiskInfos(diskInfos, & disk_info_size);
+ BOOST_CHECK_EQUAL(result, OK);
+ BOOST_CHECK_GT(strlen(diskInfos[0].device),0);
+ BOOST_CHECK_GT(strlen(diskInfos[0].label),0);
+ BOOST_CHECK_GT(diskInfos[0].disk_sn[0],0);
+ }
+ */
+
+BOOST_AUTO_TEST_CASE( read_network_adapters ) {
+	AdapterInfo * adapter_info = NULL;
+	size_t adapter_info_size = 0;
+	FUNCTION_RETURN result = getAdapterInfos(NULL, &adapter_info_size);
+	BOOST_CHECK_EQUAL(result, OK);
+	BOOST_CHECK_GT(adapter_info_size, 0);
+	adapter_info = (AdapterInfo*) malloc(
+			sizeof(AdapterInfo) * adapter_info_size);
+	result = getAdapterInfos(adapter_info, &adapter_info_size);
+	BOOST_CHECK_EQUAL(result, OK);
+	for (size_t i = 0; i < adapter_info_size; i++) {
+		cout << "Interface found: " << string(adapter_info[i].description)
+				<< endl;
+		BOOST_CHECK_GT(strlen(adapter_info[i].description), 0);
+		//lo mac address is always 0 but it has ip
+		//other interfaces may not be connected
+		if (string(adapter_info[i].description) != "lo") {
+			BOOST_CHECK_NE(adapter_info[i].ipv4_address[0], 0);
+		} else {
+			BOOST_CHECK_NE(adapter_info[i].mac_address[0], 0);
+		}
+	}
+}
diff --git a/test/license-generator/CMakeLists.txt b/test/license-generator/CMakeLists.txt
index c01ca18..f9c5ae0 100644
--- a/test/license-generator/CMakeLists.txt
+++ b/test/license-generator/CMakeLists.txt
@@ -10,4 +10,4 @@
 )
 
 SET_TARGET_PROPERTIES(license_generator_test PROPERTIES LINK_SEARCH_START_STATIC ON)
-ADD_TEST(license_generator_test ${EXECUTABLE_OUTPUT_PATH}/license-generator_test)
+ADD_TEST(license_generator_test ${EXECUTABLE_OUTPUT_PATH}/license_generator_test)

--
Gitblit v1.9.1