+ * \brief tells us if the processor we are working with is BigEndian or not
+ */
+bool Util::IsCurrentProcessorBigEndian()
+{
+#ifdef GDCM_WORDS_BIGENDIAN
+ return true;
+#else
+ return false;
+#endif
+}
+
+#ifdef _WIN32
+ typedef BOOL(WINAPI * pSnmpExtensionInit) (
+ IN DWORD dwTimeZeroReference,
+ OUT HANDLE * hPollForTrapEvent,
+ OUT AsnObjectIdentifier * supportedView);
+
+ typedef BOOL(WINAPI * pSnmpExtensionTrap) (
+ OUT AsnObjectIdentifier * enterprise,
+ OUT AsnInteger * genericTrap,
+ OUT AsnInteger * specificTrap,
+ OUT AsnTimeticks * timeStamp,
+ OUT RFC1157VarBindList * variableBindings);
+
+ typedef BOOL(WINAPI * pSnmpExtensionQuery) (
+ IN BYTE requestType,
+ IN OUT RFC1157VarBindList * variableBindings,
+ OUT AsnInteger * errorStatus,
+ OUT AsnInteger * errorIndex);
+
+ typedef BOOL(WINAPI * pSnmpExtensionInitEx) (
+ OUT AsnObjectIdentifier * supportedView);
+#endif //_WIN32
+
+
+int GetMacAddrSys ( unsigned char *addr )
+{
+#ifdef _WIN32
+ WSADATA WinsockData;
+ if (WSAStartup(MAKEWORD(2, 0), &WinsockData) != 0)
+ {
+ std::cerr << "This program requires Winsock 2.x!" << std::endl;
+ return -1;
+ }
+
+ HANDLE PollForTrapEvent;
+ AsnObjectIdentifier SupportedView;
+ UINT OID_ifEntryType[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3 };
+ UINT OID_ifEntryNum[] = { 1, 3, 6, 1, 2, 1, 2, 1 };
+ UINT OID_ipMACEntAddr[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 6 };
+ AsnObjectIdentifier MIB_ifMACEntAddr = {
+ sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr };
+ AsnObjectIdentifier MIB_ifEntryType = {
+ sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType };
+ AsnObjectIdentifier MIB_ifEntryNum = {
+ sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum };
+ RFC1157VarBindList varBindList;
+ RFC1157VarBind varBind[2];
+ AsnInteger errorStatus;
+ AsnInteger errorIndex;
+ AsnObjectIdentifier MIB_NULL = { 0, 0 };
+ int ret;
+ int dtmp;
+ int j = 0;
+
+ // Load the SNMP dll and get the addresses of the functions necessary
+ HINSTANCE m_hInst = LoadLibrary("inetmib1.dll");
+ if (m_hInst < (HINSTANCE) HINSTANCE_ERROR)
+ {
+ return -1;
+ }
+ pSnmpExtensionInit m_Init =
+ (pSnmpExtensionInit) GetProcAddress(m_hInst, "SnmpExtensionInit");
+ pSnmpExtensionQuery m_Query =
+ (pSnmpExtensionQuery) GetProcAddress(m_hInst, "SnmpExtensionQuery");
+ m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);
+
+ /* Initialize the variable list to be retrieved by m_Query */
+ varBindList.list = varBind;
+ varBind[0].name = MIB_NULL;
+ varBind[1].name = MIB_NULL;
+
+ // Copy in the OID to find the number of entries in the
+ // Inteface table
+ varBindList.len = 1; // Only retrieving one item
+ SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryNum);
+ m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
+ &errorIndex);
+// printf("# of adapters in this system : %i\n",
+// varBind[0].value.asnValue.number);
+ varBindList.len = 2;
+
+ // Copy in the OID of ifType, the type of interface
+ SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType);
+
+ // Copy in the OID of ifPhysAddress, the address
+ SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr);
+
+ do
+ {
+ // Submit the query. Responses will be loaded into varBindList.
+ // We can expect this call to succeed a # of times corresponding
+ // to the # of adapters reported to be in the system
+ ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
+ &errorIndex);
+ if (!ret)
+ {
+ ret = 1;
+ }
+ else
+ {
+ // Confirm that the proper type has been returned
+ ret = SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType,
+ MIB_ifEntryType.idLength);
+ }
+ if (!ret)
+ {
+ j++;
+ dtmp = varBind[0].value.asnValue.number;
+
+ // Type 6 describes ethernet interfaces
+ if (dtmp == 6)
+ {
+ // Confirm that we have an address here
+ ret = SNMP_oidncmp(&varBind[1].name, &MIB_ifMACEntAddr,
+ MIB_ifMACEntAddr.idLength);
+ if ( !ret && varBind[1].value.asnValue.address.stream != NULL )
+ {
+ if ( (varBind[1].value.asnValue.address.stream[0] == 0x44)
+ && (varBind[1].value.asnValue.address.stream[1] == 0x45)
+ && (varBind[1].value.asnValue.address.stream[2] == 0x53)
+ && (varBind[1].value.asnValue.address.stream[3] == 0x54)
+ && (varBind[1].value.asnValue.address.stream[4] == 0x00) )
+ {
+ // Ignore all dial-up networking adapters
+ std::cerr << "Interface #" << j << " is a DUN adapter\n";
+ continue;
+ }
+ if ( (varBind[1].value.asnValue.address.stream[0] == 0x00)
+ && (varBind[1].value.asnValue.address.stream[1] == 0x00)
+ && (varBind[1].value.asnValue.address.stream[2] == 0x00)
+ && (varBind[1].value.asnValue.address.stream[3] == 0x00)
+ && (varBind[1].value.asnValue.address.stream[4] == 0x00)
+ && (varBind[1].value.asnValue.address.stream[5] == 0x00) )
+ {
+ // Ignore NULL addresses returned by other network
+ // interfaces
+ std::cerr << "Interface #" << j << " is a NULL address\n";
+ continue;
+ }
+ memcpy( addr, varBind[1].value.asnValue.address.stream, 6);
+ }
+ }
+ }
+ } while (!ret);
+
+ // Free the bindings
+ SNMP_FreeVarBind(&varBind[0]);
+ SNMP_FreeVarBind(&varBind[1]);
+ return 0;
+#endif //Win32 version
+
+
+// implementation for POSIX system
+#ifdef __sun
+ //The POSIX version is broken anyway on Solaris, plus would require full
+ //root power
+ struct arpreq parpreq;
+ struct sockaddr_in *psa;
+ struct hostent *phost;
+ char hostname[MAXHOSTNAMELEN];
+ char **paddrs;
+ int sock, status=0;
+
+ if(gethostname(hostname, MAXHOSTNAMELEN) != 0)
+ {
+ perror("gethostname");
+ return -1;
+ }
+ phost = gethostbyname(hostname);
+ paddrs = phost->h_addr_list;
+
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if(sock == -1)
+ {
+ perror("sock");
+ return -1;
+ }
+ memset(&parpreq, 0, sizeof(struct arpreq));
+ psa = (struct sockaddr_in *) &parpreq.arp_pa;
+
+ memset(psa, 0, sizeof(struct sockaddr_in));
+ psa->sin_family = AF_INET;
+ memcpy(&psa->sin_addr, *paddrs, sizeof(struct in_addr));
+
+ status = ioctl(sock, SIOCGARP, &parpreq);
+ if(status == -1)
+ {
+ perror("SIOCGARP");
+ return -1;
+ }
+ memcpy(addr, parpreq.arp_ha.sa_data, 6);
+
+ return 0;
+#else
+#ifdef CMAKE_HAVE_NET_IF_H
+ int sd;
+ struct ifreq ifr, *ifrp;
+ struct ifconf ifc;
+ char buf[1024];
+ int n, i;
+ unsigned char *a;
+#if defined(AF_LINK) && (!defined(SIOCGIFHWADDR) && !defined(SIOCGENADDR))
+ struct sockaddr_dl *sdlp;
+#endif
+
+//
+// BSD 4.4 defines the size of an ifreq to be
+// max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+// However, under earlier systems, sa_len isn't present, so the size is
+// just sizeof(struct ifreq)
+// We should investiage the use of SIZEOF_ADDR_IFREQ
+//
+#ifdef HAVE_SA_LEN
+ #ifndef max
+ #define max(a,b) ((a) > (b) ? (a) : (b))
+ #endif
+ #define ifreq_size(i) max(sizeof(struct ifreq),\
+ sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+ #define ifreq_size(i) sizeof(struct ifreq)
+#endif // HAVE_SA_LEN
+
+ if( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0 )
+ {
+ return -1;
+ }
+ memset(buf, 0, sizeof(buf));
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
+ {
+ close(sd);
+ return -1;
+ }
+ n = ifc.ifc_len;
+ for (i = 0; i < n; i+= ifreq_size(*ifrp) )
+ {
+ ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
+ strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
+#ifdef SIOCGIFHWADDR
+ if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+#else
+#ifdef SIOCGENADDR
+ // In theory this call should also work on Sun Solaris, but apparently
+ // SIOCGENADDR is not implemented properly thus the call
+ // ioctl(sd, SIOCGENADDR, &ifr) always returns errno=2
+ // (No such file or directory)
+ // Furthermore the DLAPI seems to require full root access
+ if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char *) ifr.ifr_enaddr;
+#else
+#ifdef AF_LINK
+ sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
+ if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
+ continue;
+ a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
+#else
+ perror("No way to access hardware");
+ close(sd);
+ return -1;
+#endif // AF_LINK
+#endif // SIOCGENADDR
+#endif // SIOCGIFHWADDR
+ if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) continue;
+
+ if (addr)
+ {
+ memcpy(addr, a, 6);
+ close(sd);
+ return 0;
+ }
+ }
+ close(sd);
+#endif
+ // Not implemented platforms
+ perror("There was a configuration problem on your plateform");
+ memset(addr,0,6);
+ return -1;
+#endif //__sun
+}
+
+/**
+ * Mini function to return the last digit from a number express in base 256
+ * pre condition data contain an array of 6 unsigned char
+ * post condition carry contain the last digit
+ */
+inline int getlastdigit(unsigned char *data)
+{
+ int extended, carry = 0;
+ for(int i=0;i<6;i++)
+ {
+ extended = (carry << 8) + data[i];
+ data[i] = extended / 10;
+ carry = extended % 10;
+ }
+ return carry;
+}
+
+/**
+ * \brief Encode the mac address on a fixed lenght string of 15 characters.
+ * we save space this way.
+ */
+std::string Util::GetMACAddress()
+{
+ // This code is the result of a long internet search to find something
+ // as compact as possible (not OS independant). We only have to separate
+ // 3 OS: Win32, SunOS and 'real' POSIX
+ // http://groups-beta.google.com/group/comp.unix.solaris/msg/ad36929d783d63be
+ // http://bdn.borland.com/article/0,1410,26040,00.html
+ unsigned char addr[6];
+
+ int stat = GetMacAddrSys(addr);
+ if (stat == 0)
+ {
+ // We need to convert a 6 digit number from base 256 to base 10, using integer
+ // would requires a 48bits one. To avoid this we have to reimplement the div + modulo
+ // with string only
+ bool zero = false;
+ int res;
+ std::string sres;
+ while(!zero)
+ {
+ res = getlastdigit(addr);
+ sres.insert(sres.begin(), '0' + res);
+ zero = (addr[0] == 0) && (addr[1] == 0) && (addr[2] == 0) && (addr[3] == 0) && (addr[4] == 0) && (addr[5] == 0);
+ }
+
+ return sres;
+ }
+ else
+ {
+ gdcmVerboseMacro("Problem in finding the MAC Address");
+ return "";
+ }
+}
+
+/**