Add native call to retrieve driver name via ethtool API
This adds a JNI function to retrieve an interface's driver name via ethtool API, which will be used to identify USB NCM interfaces. Unfortunately, SIOCETHTOOL (ETHTOOL_GDRVINFO in particular) does not allow passing in the interface index, meaning that this operation is racy, i.e. the interface might have been replaced when getDriverNameForInterface() is called. SICOETHTOOL is slowly being replaced by a netlink alternative that allows querying by interface index but, unfortunately, does not support ETHTOOL_GDRVINFO yet. Test: verified manually; automated test will be added shortly. Flag: EXEMPT mainline Bug: 1000001 Change-Id: I8bec47e36a607e7d8fe2fac2eebcd8dff0360a02
This commit is contained in:
parent
9e2cf07fbc
commit
0eaec731ec
2 changed files with 37 additions and 0 deletions
|
|
@ -49,6 +49,15 @@ public class ServiceConnectivityJni {
|
|||
*/
|
||||
public static native void setTimerFdTime(int fd, long timeMs) throws ErrnoException;
|
||||
|
||||
/**
|
||||
* Get the driver name for a given interface using the ethtool API.
|
||||
*
|
||||
* @param ifname name of the interface to query.
|
||||
* @return the name of the driver.
|
||||
* @throws ErrnoException if ioctl() returns -1.
|
||||
*/
|
||||
public static native String getDriverNameForInterface(String ifname) throws ErrnoException;
|
||||
|
||||
/** Create tun/tap interface */
|
||||
public static native int createTunTap(boolean isTun, boolean hasCarrier,
|
||||
boolean setIffMulticast, @NonNull String iface);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <jni.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/ipv6_route.h>
|
||||
|
|
@ -80,6 +81,31 @@ static void setTimerFdTime(JNIEnv *env, jclass clazz, jint tfd,
|
|||
}
|
||||
}
|
||||
|
||||
static jstring getDriverNameForInterface(JNIEnv *env, jclass clazz, jstring jifname) {
|
||||
base::unique_fd fd(socket(AF_INET6, SOCK_DGRAM, 0));
|
||||
if (!fd.ok()) {
|
||||
jniThrowErrnoException(env, "getDriverNameForInterface", errno);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedUtfChars ifname(env, jifname);
|
||||
if (!ifname.c_str()) {
|
||||
jniThrowNullPointerException(env, "getDriverNameForInterface: ifname is null");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ethtool_drvinfo msg = { .cmd = ETHTOOL_GDRVINFO };
|
||||
ifreq ifr = { .ifr_data = reinterpret_cast<char *>(&msg) };
|
||||
strlcpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ);
|
||||
|
||||
if (ioctl(fd, SIOCETHTOOL, &ifr)) {
|
||||
jniThrowErrnoException(env, "getDriverNameForInterface", errno);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return env->NewStringUTF(msg.driver);
|
||||
}
|
||||
|
||||
static void throwException(JNIEnv *env, int error, const char *action,
|
||||
const char *iface) {
|
||||
const std::string &msg = "Error: " + std::string(action) + " " +
|
||||
|
|
@ -195,6 +221,8 @@ static const JNINativeMethod gMethods[] = {
|
|||
/* name, signature, funcPtr */
|
||||
{"createTimerFd", "()I", (void *)createTimerFd},
|
||||
{"setTimerFdTime", "(IJ)V", (void *)setTimerFdTime},
|
||||
{"getDriverNameForInterface", "(Ljava/lang/String;)Ljava/lang/String;",
|
||||
(void *)getDriverNameForInterface},
|
||||
{"setTunTapCarrierEnabled", "(Ljava/lang/String;IZ)V",
|
||||
(void *)setTunTapCarrierEnabled},
|
||||
{"createTunTap", "(ZZZLjava/lang/String;)I", (void *)createTunTap},
|
||||
|
|
|
|||
Loading…
Reference in a new issue