Skip to content

Commit

Permalink
Improve hostname functions
Browse files Browse the repository at this point in the history
Fix wrong mapping of libc function gethostname, sethostname, 
getdomainname  and setdomainname. The functions are defined as:

       int getdomainname(char *name, size_t len);
       int setdomainname(const char *name, size_t len);

       int gethostname(char *name, size_t len);
       int sethostname(const char *name, size_t len);

and a C char[] maps by default to a byte[] in java.


In addition bind the winsock gethostname function:

com.sun.jna.platform.win32.Winsock2.gethostname(byte[], int)

This closes java-native-access#871
  • Loading branch information
matthiasblaesing committed Nov 8, 2017
1 parent 24b2108 commit 428fd05
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Bug Fixes
* [#843](https://github.com/java-native-access/jna/pull/843): Correctly bind `com.sun.jna.platform.win32.SecBufferDesc` and add convenience binding as `com.sun.jna.platform.win32.SspiUtil.ManagedSecBufferDesc`. Bind SSPI functions `InitializeSecurityContext`, `AcceptSecurityContext`, `QueryCredentialsAttributes`, `QuerySecurityPackageInfo`, `EncryptMessage`, `DecryptMessage`, `MakeSignature`, `VerifySignature` in `com.sun.jna.platform.win32.Secur32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#863](https://github.com/java-native-access/jna/pull/863): Fix ARM softfloat/hardfloat detection by modifying armSoftFloat condition in ELFAnalyser. Before this fix a softfloat binary could be misdetected as hardfloat. - [@kunkun26](https://github.com/kunkun26).
* [#867](https://github.com/java-native-access/jna/issues/867): Fix memory leak in `COMLateBindingObject#getStringProperty` - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#871](https://github.com/java-native-access/jna/issues/871): Fix mapping of libc function `gethostname`, `sethostname`, `getdomainname` and `setdomainname` and bind `com.sun.jna.platform.win32.Winsock2.gethostname(byte[], int)` - [@matthiasblaesing](https://github.com/matthiasblaesing).

Breaking Changes
----------------
Expand All @@ -39,6 +40,9 @@ Breaking Changes
a `Class<T>` as parameter. `T` was unconstraint and was modified to
extend `com.sun.jna.Library`. This change is source compatible, but not
binary compatbile, so bindings need to be recompiled.
* the parameters of the methods `gethostname`, `sethostname`, `getdomainname`
and `setdomainname` in the interface `com.sun.jna.platform.unix.LibCAPI`
were changed from `(char[] name, int len)` to `(byte[] name, int len)`
* `com.sun.jna.platform.win32.Sspi.SecBufferDesc` was incompatibly changed to
match the correct native semantics. SecBufferDesc describing more than one
buffer were broken. For most usecases
Expand Down
8 changes: 4 additions & 4 deletions contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public interface LibCAPI extends Reboot, Resource {

// see man(2) get/set hostname
int HOST_NAME_MAX = 255; // not including the '\0'
int gethostname(char[] name, int len);
int sethostname(char[] name, int len);
int gethostname(byte[] name, int len);
int sethostname(byte[] name, int len);

// see man(2) get/set domainname
int getdomainname(char[] name, int len);
int setdomainname(char[] name, int len);
int getdomainname(byte[] name, int len);
int setdomainname(byte[] name, int len);

/**
* @param name Environment variable name
Expand Down
153 changes: 153 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Winsock2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/* Copyright (c) 2017 Matthias Bläsing, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.win32.W32APIOptions;

public interface Winsock2 {

Winsock2 INSTANCE = (Winsock2) Native.loadLibrary("ws2_32", Winsock2.class, W32APIOptions.ASCII_OPTIONS);

/**
* The gethostname function retrieves the standard host name for the local
* computer.
*
* <p>
* <strong>Remarks</strong></p>
*
* <p>
* The gethostname function returns the name of the local host into the
* buffer specified by the name parameter. The host name is returned as a
* null-terminated string. The form of the host name is dependent on the
* Windows Sockets provider—it can be a simple host name, or it can be a
* fully qualified domain name. However, it is guaranteed that the name
* returned will be successfully parsed by gethostbyname and
* WSAAsyncGetHostByName.</p>
*
* <p>
* The maximum length of the name returned in the buffer pointed to by the
* name parameter is dependent on the namespace provider.</p>
*
* <p>
* If the gethostname function is used on a cluster resource on Windows
* Server 2008, Windows Server 2003, or Windows 2000 Server and the
* _CLUSTER_NETWORK_NAME_ environment variable is defined, then the value in
* this environment variable overrides the actual hostname and is returned.
* On a cluster resource, the _CLUSTER_NETWORK_NAME_ environment variable
* contains the name of the cluster.</p>
*
* <p>
* The gethostname function queries namespace providers to determine the
* local host name using the SVCID_HOSTNAME GUID defined in the Svgguid.h
* header file. If no namespace provider responds, then the gethostname
* function returns the NetBIOS name of the local computer.</p>
*
* <p>
* The maximum length, in bytes, of the string returned in the buffer
* pointed to by the name parameter is dependent on the namespace provider,
* but this string must be 256 bytes or less. So if a buffer of 256 bytes is
* passed in the name parameter and the namelen parameter is set to 256, the
* buffer size will always be adequate.</p>
*
* @param name A bytearray that receives the local host name.
* @param namelen The length, in bytes, of the buffer pointed to by the name parameter.
* @return If no error occurs, gethostname returns zero. Otherwise, it returns SOCKET_ERROR and a specific error code can be retrieved by calling WSAGetLastError.
*/
public int gethostname(byte[] name, int namelen);

/**
* The WSAGetLastError function returns the error status for the last Windows Sockets operation that failed.
*
* <p>
* <strong>Remarks</strong></p>
* <p>The WSAGetLastError function returns the last error that occurred for
* the calling thread. When a particular Windows Sockets function indicates
* an error has occurred, this function should be called immediately to
* retrieve the extended error code for the failing function call. This
* extended error code can be different from the error code obtained from
* getsockopt when called with an optname parameter of SO_ERROR, which is
* socket-specific since WSAGetLastError is for all thread-specific sockets.
* </p>
*
* <p>If a function call's return value indicates that error or other relevant
* data was returned in the error code, WSAGetLastError should be called
* immediately. This is necessary because some functions may reset the last
* extended error code to 0 if they succeed, overwriting the extended error
* code returned by a previously failed function. To specifically reset the
* extended error code, use the WSASetLastError function call with the
* iError parameter set to zero. A getsockopt function when called with an
* optname parameter of SO_ERROR also resets the extended error code to
* zero.</p>
*
* <p>The WSAGetLastError function should not be used to check for an extended
* error value on receipt of an asynchronous message. In this case, the
* extended error value is passed in the lParam parameter of the message,
* and this can differ from the value returned by WSAGetLastError.</p>
*
* <p>Remark: An application can call the WSAGetLastError function to determine
* the extended error code for other Windows sockets functions as is
* normally done in Windows Sockets even if the WSAStartup function fails or
* the WSAStartup function was not called to properly initialize Windows
* Sockets before calling a Windows Sockets function. The WSAGetLastError
* function is one of the only functions in the Winsock 2.2 DLL that can be
* called in the case of a WSAStartup failure.</p>
*
* <p>The Windows Sockets extended error codes returned by this function and
* the text description of the error are listed under Windows Sockets Error
* Codes. These error codes and a short text description associated with an
* error code are defined in the Winerror.h header file. The FormatMessage
* function can be used to obtain the message string for the returned error.</p>
*
* <p>For information on how to handle error codes when porting socket
* applications to Winsock, see Error Codes - errno, h_errno and
* WSAGetLastError.</p>
*
* @return The return value indicates the error code for this thread's last Windows Sockets operation that failed.
*/
public int WSAGetLastError();

/**
* The WSASetLastError function sets the error code that can be retrieved
* through the WSAGetLastError function.
*
* <p><strong>Remarks</strong></p>
*
* <p>
* The WSASetLastError function allows an application to set the error code
* to be returned by a subsequent WSAGetLastError call for the current
* thread. Note that any subsequent Windows Sockets routine called by the
* application will override the error code as set by this routine.
*
* <p>The error code set by WSASetLastError is different from the error code
* reset by calling the function getsockopt with SO_ERROR.</p>
*
* <p>The Windows Sockets error codes used by this function are listed under
* Windows Sockets Error Codes.</p>
*
* @param error Integer that specifies the error code to be returned by a
* subsequent WSAGetLastError call.
*/
public void WSASetLastError(int error);
}
49 changes: 39 additions & 10 deletions contrib/platform/test/com/sun/jna/platform/unix/LibCTest.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,41 @@
/* Copyright (c) 2015 Goldstein Lyor, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna.platform.unix;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32Util;
import java.sql.Date;
import java.util.Map;
import static junit.framework.TestCase.assertTrue;

import org.junit.Test;

/**
* @author Lyor Goldstein
*/
public class LibCTest extends AbstractUnixTestSupport {

public LibCTest() {
super();
}
Expand Down Expand Up @@ -48,7 +63,7 @@ public void testSetenv() {
LibC.INSTANCE.unsetenv(name);
}
}

@Test
public void testGetLoadAvg() {
double[] loadavg = new double[3];
Expand All @@ -58,4 +73,18 @@ public void testGetLoadAvg() {
assertTrue(loadavg[1] >= 0);
assertTrue(loadavg[2] >= 0);
}

@Test
public void testGethostnameGetdomainname() {
// This needs visual inspection ...
byte[] buffer = new byte[256];
LibC.INSTANCE.gethostname(buffer, buffer.length);
String hostname = Native.toString(buffer);
System.out.println("Hostname: " + hostname);
assertTrue(hostname.length() > 0);
LibC.INSTANCE.getdomainname(buffer, buffer.length);
String domainname = Native.toString(buffer);
System.out.println("Domainname: " + domainname);
assertTrue(domainname.length() > 0);
}
}
46 changes: 46 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/Winsock2Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* Copyright (c) 2017 Matthias Bläsing, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import org.junit.Test;
import static org.junit.Assert.*;

public class Winsock2Test {
@Test
public void testGethostname() {
// This needs visual inspection ...
byte[] buffer = new byte[256];
Winsock2.INSTANCE.gethostname(buffer, buffer.length);
String hostname = Native.toString(buffer);
System.out.println("Hostname: " + hostname);
assertTrue(hostname.length() > 0);
}

@Test
public void testWSAGetSetLastError() {
Winsock2.INSTANCE.WSASetLastError(42);
assertEquals(42, Winsock2.INSTANCE.WSAGetLastError());
}
}

0 comments on commit 428fd05

Please sign in to comment.