diff --git a/lib/native/freebsd-64/libhwaddressretriever.so b/lib/native/freebsd-64/libhwaddressretriever.so new file mode 100755 index 000000000..cd1813cf6 Binary files /dev/null and b/lib/native/freebsd-64/libhwaddressretriever.so differ diff --git a/lib/native/freebsd/libhwaddressretriever.so b/lib/native/freebsd/libhwaddressretriever.so new file mode 100755 index 000000000..c48366b0f Binary files /dev/null and b/lib/native/freebsd/libhwaddressretriever.so differ diff --git a/lib/native/linux-64/libhwaddressretriever.so b/lib/native/linux-64/libhwaddressretriever.so new file mode 100755 index 000000000..e7882609a Binary files /dev/null and b/lib/native/linux-64/libhwaddressretriever.so differ diff --git a/lib/native/linux/libhwaddressretriever.so b/lib/native/linux/libhwaddressretriever.so new file mode 100755 index 000000000..09574a082 Binary files /dev/null and b/lib/native/linux/libhwaddressretriever.so differ diff --git a/lib/native/mac/libhwaddressretriever.jnilib b/lib/native/mac/libhwaddressretriever.jnilib new file mode 100755 index 000000000..bbfba5e1d Binary files /dev/null and b/lib/native/mac/libhwaddressretriever.jnilib differ diff --git a/lib/native/windows-64/hwaddressretriever.dll b/lib/native/windows-64/hwaddressretriever.dll new file mode 100755 index 000000000..8f29f8fea Binary files /dev/null and b/lib/native/windows-64/hwaddressretriever.dll differ diff --git a/lib/native/windows/hwaddressretriever.dll b/lib/native/windows/hwaddressretriever.dll new file mode 100755 index 000000000..35f20b29e Binary files /dev/null and b/lib/native/windows/hwaddressretriever.dll differ diff --git a/src/native/build.xml b/src/native/build.xml index 3b5dff4d7..fe5d08d9f 100644 --- a/src/native/build.xml +++ b/src/native/build.xml @@ -468,6 +468,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -654,6 +708,7 @@ + diff --git a/src/native/hwaddressretriever/HardwareAddressRetriever.h b/src/native/hwaddressretriever/HardwareAddressRetriever.h new file mode 100644 index 000000000..48a12b166 --- /dev/null +++ b/src/native/hwaddressretriever/HardwareAddressRetriever.h @@ -0,0 +1,30 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ + +/** + * \file HardwareAddressRetriever.h + * \brief Hardware address retriever. + * \author Sebastien Vincent + * \date 2010 + */ + +#ifndef HARDWARE_ADDRESS_RETRIEVER_H +#define HARDWARE_ADDRESS_RETRIEVER_H + +#include + +/** + * \brief Returns the hardware address for the specified interface. + * \param env JNI environment + * \param ifName name of the interface that we want to get the hardware address + * \return byte array representing hardware address or NULL if not found or + * system related errors happen. + */ +jbyteArray getHardwareAddress(JNIEnv* env, jstring ifName); + +#endif /* HARDWARE_ADDRESS_RETRIEVER_H */ + diff --git a/src/native/hwaddressretriever/HardwareAddressRetriever_unix.c b/src/native/hwaddressretriever/HardwareAddressRetriever_unix.c new file mode 100644 index 000000000..f4a79ea12 --- /dev/null +++ b/src/native/hwaddressretriever/HardwareAddressRetriever_unix.c @@ -0,0 +1,124 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ + +/** + * \file HardwareAddressRetriever_unix.c + * \brief Hardware address retriever (Unix specific code). + * \author Sebastien Vincent + * \date 2010 + */ + +#if !defined(_WIN32) && !defined(_WIN64) + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#if defined(__FreeBSD__) || defined(__APPLE__) +#include +#include +#include +#include +#endif + +#include "HardwareAddressRetriever.h" + +jbyteArray getHardwareAddress(JNIEnv* env, jstring ifName) +{ + int sock = -1; + struct ifreq ifr; + jbyteArray hwaddr = NULL; + char* name = NULL; + jbyte* addr = NULL; + int hwlen = 6; + + name = (char*)(*env)->GetStringUTFChars(env, ifName, NULL); + + if(!name) + { + return NULL; + } + +#ifdef __linux__ + + sock = socket(AF_INET, SOCK_DGRAM, 0); + + if(sock == -1) + { + (*env)->ReleaseStringUTFChars(env, ifName, name); + return NULL; + } + + memset(&ifr, 0x00, sizeof(struct ifreq)); + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = 0x00; + + if(ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) + { + (*env)->ReleaseStringUTFChars(env, ifName, name); + close(sock); + return NULL; + } + + close(sock); + addr = (const jbyte*)ifr.ifr_hwaddr.sa_data; + +#else /* BSD like */ + + struct ifaddrs* addrs = NULL; + struct ifaddrs* ifa = NULL; + jbyte buf[hwlen]; + + if(getifaddrs(&addrs) != -1) + { + for(ifa = addrs ; ifa != NULL ; ifa = ifa->ifa_next) + { + if(ifa->ifa_addr->sa_family == AF_LINK && !strcmp(ifa->ifa_name, name)) + { + struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifa->ifa_addr; + + if(sdl->sdl_type == IFT_ETHER) + { + memcpy(buf, LLADDR(sdl), hwlen); + addr = buf; + break; + } + } + } + + freeifaddrs(addrs); + } + +#endif + + if(addr) + { + hwaddr = (*env)->NewByteArray(env, hwlen); + + if(hwaddr) + { + /* copy the hardware address and return it */ + (*env)->SetByteArrayRegion(env, hwaddr, 0, hwlen, addr); + } + } + + /* cleanup */ + (*env)->ReleaseStringUTFChars(env, ifName, name); + return hwaddr; +} + +#endif + diff --git a/src/native/hwaddressretriever/HardwareAddressRetriever_win.c b/src/native/hwaddressretriever/HardwareAddressRetriever_win.c new file mode 100644 index 000000000..384cab090 --- /dev/null +++ b/src/native/hwaddressretriever/HardwareAddressRetriever_win.c @@ -0,0 +1,125 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ + +/** + * \file HardwareAddressRetriever_win.c + * \brief Hardware address retriever (Windows specific code). + * \author Sebastien Vincent + * \date 2010 + */ + +#if defined(_WIN32) || defined(_WIN64) + +/** + * \def WIN32_LEAN_AND_MEAN + * \brief Exclude not commonly used headers from win32 API. + * + * It excludes some unused stuff from windows headers and + * by the way code compiles faster. + */ +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#include +#include + +#include "HardwareAddressRetriever.h" + +jbyteArray getHardwareAddress(JNIEnv* env, jstring ifName) +{ + MIB_IFTABLE* ifTable = NULL; + ULONG size = 15000; + int found = 0; + jbyteArray hwaddr = NULL; + DWORD ret = 0; + DWORD i = 0; + WCHAR* wname = NULL; + MIB_IFROW ifi; + jclass clazz = (*env)->GetObjectClass(env, ifName); + jmethodID method = (*env)->GetMethodID(env, clazz, "compareTo", "(Ljava/lang/String;)I"); + + if(method == NULL) + { + return NULL; + } + + memset(&ifi, 0x00, sizeof(MIB_IFROW)); + + do + { + ifTable = malloc(size); + + if(!ifTable) + { + /* out of memory */ + return NULL; + } + + ret = GetIfTable(ifTable, &size, 1); + + }while(ret == ERROR_INSUFFICIENT_BUFFER); + + if(ret != ERROR_SUCCESS) + { + free(ifTable); + return NULL; + } + + for(i = 0 ; i < ifTable->dwNumEntries ; i++) + { + jstring tmp = NULL; + ifi = ifTable->table[i]; + + if(ifi.dwType == IF_TYPE_OTHER) + { + continue; + } + + /* jstring created by NewStringUTF will be garbage collected at + * the end of the function + */ + tmp = (*env)->NewStringUTF(env, ifi.bDescr); + + if(!tmp) + { + /* printf("error\n"); */ + continue; + } + + if((*env)->CallIntMethod(env, ifName, method, tmp) == 0) + { + found = 1; + break; + } + } + + if(found) + { + DWORD hwlen = ifi.dwPhysAddrLen; + + if(hwlen > 0) + { + hwaddr = (*env)->NewByteArray(env, hwlen); + + if(hwaddr) + { + /* copy the hardware address and return it */ + (*env)->SetByteArrayRegion(env, hwaddr, 0, hwlen, ifi.bPhysAddr); + } + } + } + + /* cleanup */ + free(ifTable); + + return hwaddr; +} + +#endif + diff --git a/src/native/hwaddressretriever/net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.c b/src/native/hwaddressretriever/net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.c new file mode 100644 index 000000000..5e8d94408 --- /dev/null +++ b/src/native/hwaddressretriever/net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.c @@ -0,0 +1,35 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ + +/** + * \file net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.h + * \brief Hardware address retriever. + * \author Sebastien Vincent + * \date 2010 + */ + +#include +#include + +#include + +#include "HardwareAddressRetriever.h" + +/** + * \brief Returns the byte array representing hardware address. + * \param env JVM environment + * \param clazz Java class + * \param ifName name of the interface + * \return byte array representing the hardware address or NULL if anything + * goes wrong + */ +JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever_getHardwareAddress + (JNIEnv* env, jclass clazz, jstring ifName) +{ + return getHardwareAddress(env, ifName); +} + diff --git a/src/native/hwaddressretriever/net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.h b/src/native/hwaddressretriever/net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.h new file mode 100644 index 000000000..528674185 --- /dev/null +++ b/src/native/hwaddressretriever/net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever */ + +#ifndef _Included_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever +#define _Included_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever + * Method: getHardwareAddress + * Signature: (Ljava/lang/String;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever_getHardwareAddress + (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/net/java/sip/communicator/impl/netaddr/HardwareAddressRetriever.java b/src/net/java/sip/communicator/impl/netaddr/HardwareAddressRetriever.java new file mode 100644 index 000000000..823342582 --- /dev/null +++ b/src/net/java/sip/communicator/impl/netaddr/HardwareAddressRetriever.java @@ -0,0 +1,33 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.netaddr; + +/** + * Class to retrieve hardware address of a specific interface. + * + * We know that starting Java 6, NetworkInterface has getHardwareAddress method + * but as we still support Java 5 we have to do it ourself. + * + * @author Sebastien Vincent + */ +public class HardwareAddressRetriever +{ + /* load library */ + static + { + System.loadLibrary("hwaddressretriever"); + } + + /** + * Returns the hardware address of a particular interface. + * + * @param ifName name of the interface + * @return byte array representing the hardware address of the interface or + * null if interface is not found or other system related errors + */ + public static native byte[] getHardwareAddress(String ifName); +} diff --git a/src/net/java/sip/communicator/impl/netaddr/NetworkAddressManagerServiceImpl.java b/src/net/java/sip/communicator/impl/netaddr/NetworkAddressManagerServiceImpl.java index 11cbcab04..042a7d806 100644 --- a/src/net/java/sip/communicator/impl/netaddr/NetworkAddressManagerServiceImpl.java +++ b/src/net/java/sip/communicator/impl/netaddr/NetworkAddressManagerServiceImpl.java @@ -6,6 +6,7 @@ */ package net.java.sip.communicator.impl.netaddr; +import java.lang.reflect.*; import java.beans.*; import java.io.*; import java.net.*; @@ -119,7 +120,8 @@ public void stop() * @return an InetAddress instance representing the local host, and that * a socket can bind upon or distribute to peers as a contact address. */ - public synchronized InetAddress getLocalHost(InetAddress intendedDestination) + public synchronized InetAddress getLocalHost( + InetAddress intendedDestination) { InetAddress localHost = null; String osVersion = System.getProperty("os.version"); @@ -128,18 +130,20 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination) logger.trace( "Querying a localhost addr for dst=" + intendedDestination); - /* use native code (JNI) to find source address for a specific destination - * address on Windows XP SP1 and over. + /* use native code (JNI) to find source address for a specific + * destination address on Windows XP SP1 and over. * * For other systems, we used method based on DatagramSocket.connect * which will returns us source address. The reason why we cannot use it - * on Windows is because its socket implementation returns the any address... + * on Windows is because its socket implementation returns the any + * address... */ if(OSUtils.IS_WINDOWS && !osVersion.startsWith("4") && /* 95/98/Me/NT */ !osVersion.startsWith("5.0")) /* 2000 */ { - byte[] src = Win32LocalhostRetriever.getSourceForDestination(intendedDestination.getAddress()); + byte[] src = Win32LocalhostRetriever.getSourceForDestination( + intendedDestination.getAddress()); if(src == null) { @@ -160,7 +164,8 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination) else { - //no point in making sure that the localHostFinderSocket is initialized. + //no point in making sure that the localHostFinderSocket is + //initialized. //better let it through a NullPointerException. localHostFinderSocket.connect(intendedDestination, RANDOM_ADDR_DISC_PORT); @@ -235,8 +240,8 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination) if (!(localHost instanceof Inet4Address)) { // return the first non localhost interface we find. - Enumeration interfaces = NetworkInterface - .getNetworkInterfaces(); + Enumeration interfaces = + NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { @@ -278,6 +283,51 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination) return localHost; } + /** + * Returns the hardware address (i.e. MAC address) of the specified + * interface name. + * + * @param iface the NetworkInterface + * @return array of bytes representing the layer 2 address or null if + * interface does not exist + */ + public byte[] getHardwareAddress(NetworkInterface iface) + { + String ifName = null; + byte hwAddress[] = null; + + /* try reflection */ + try + { + Method method = iface.getClass(). + getMethod("getHardwareAddress"); + + if(method != null) + { + hwAddress = (byte[])method.invoke(iface, new Object[]{}); + return hwAddress; + } + } + catch(Exception e) + { + } + + /* maybe getHardwareAddress not available on this JVM try + * with our JNI + */ + if(OSUtils.IS_WINDOWS) + { + ifName = iface.getDisplayName(); + } + else + { + ifName = iface.getName(); + } + + hwAddress = HardwareAddressRetriever.getHardwareAddress(ifName); + + return hwAddress; + } /** * Tries to obtain an for the specified port. @@ -556,8 +606,8 @@ public StunCandidateHarvester discoverStunServer(String domainName, if(srvrAddress != null) { - //yay! we seem to have a TURN server, so we'll be using it for both - //TURN and STUN harvesting. + //yay! we seem to have a TURN server, so we'll be using it for + //both TURN and STUN harvesting. return new TurnCandidateHarvester( new TransportAddress(srvrAddress, Transport.UDP), new LongTermCredential(userName, password)); diff --git a/src/net/java/sip/communicator/service/netaddr/NetworkAddressManagerService.java b/src/net/java/sip/communicator/service/netaddr/NetworkAddressManagerService.java index 0893e33a6..90737e412 100644 --- a/src/net/java/sip/communicator/service/netaddr/NetworkAddressManagerService.java +++ b/src/net/java/sip/communicator/service/netaddr/NetworkAddressManagerService.java @@ -7,7 +7,6 @@ package net.java.sip.communicator.service.netaddr; import java.net.*; -import java.text.*; import java.io.*; import org.ice4j.ice.*; @@ -90,6 +89,15 @@ public InetSocketAddress getPublicAddressFor( throws IOException, BindException; + /** + * Returns the hardware address (i.e. MAC address) of the specified + * interface name. + * + * @param iface the NetworkInterface + * @return array of bytes representing the layer 2 address + */ + public byte[] getHardwareAddress(NetworkInterface iface); + /** * Creates a DatagramSocket and binds it to on the specified * localAddress and a port in the range specified by the