blob: 2e88fc83dce5b94c67f3101a9aa3fe5d34a56ebf [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
#include "nativehelper/scoped_primitive_array.h"
#include "nativehelper/scoped_utf_chars.h"
#define BPF_FD_JUST_USE_INT
#include "BpfSyscallWrappers.h"
namespace android {
static jint com_android_net_module_util_BpfMap_nativeBpfFdGet(JNIEnv *env, jclass clazz,
jstring path, jint mode) {
ScopedUtfChars pathname(env, path);
jint fd = bpf::bpfFdGet(pathname.c_str(), static_cast<unsigned>(mode));
if (fd < 0) jniThrowErrnoException(env, "nativeBpfFdGet", errno);
return fd;
}
static void com_android_net_module_util_BpfMap_nativeWriteToMapEntry(JNIEnv *env, jobject self,
jint fd, jbyteArray key, jbyteArray value, jint flags) {
ScopedByteArrayRO keyRO(env, key);
ScopedByteArrayRO valueRO(env, value);
int ret = bpf::writeToMapEntry(static_cast<int>(fd), keyRO.get(), valueRO.get(),
static_cast<int>(flags));
if (ret) jniThrowErrnoException(env, "nativeWriteToMapEntry", errno);
}
static jboolean throwIfNotEnoent(JNIEnv *env, const char* functionName, int ret, int err) {
if (ret == 0) return true;
if (err != ENOENT) jniThrowErrnoException(env, functionName, err);
return false;
}
static jboolean com_android_net_module_util_BpfMap_nativeDeleteMapEntry(JNIEnv *env, jobject self,
jint fd, jbyteArray key) {
ScopedByteArrayRO keyRO(env, key);
// On success, zero is returned. If the element is not found, -1 is returned and errno is set
// to ENOENT.
int ret = bpf::deleteMapEntry(static_cast<int>(fd), keyRO.get());
return throwIfNotEnoent(env, "nativeDeleteMapEntry", ret, errno);
}
static jboolean com_android_net_module_util_BpfMap_nativeGetNextMapKey(JNIEnv *env, jobject self,
jint fd, jbyteArray key, jbyteArray nextKey) {
// If key is found, the operation returns zero and sets the next key pointer to the key of the
// next element. If key is not found, the operation returns zero and sets the next key pointer
// to the key of the first element. If key is the last element, -1 is returned and errno is
// set to ENOENT. Other possible errno values are ENOMEM, EFAULT, EPERM, and EINVAL.
ScopedByteArrayRW nextKeyRW(env, nextKey);
int ret;
if (key == nullptr) {
// Called by getFirstKey. Find the first key in the map.
ret = bpf::getNextMapKey(static_cast<int>(fd), nullptr, nextKeyRW.get());
} else {
ScopedByteArrayRO keyRO(env, key);
ret = bpf::getNextMapKey(static_cast<int>(fd), keyRO.get(), nextKeyRW.get());
}
return throwIfNotEnoent(env, "nativeGetNextMapKey", ret, errno);
}
static jboolean com_android_net_module_util_BpfMap_nativeFindMapEntry(JNIEnv *env, jobject self,
jint fd, jbyteArray key, jbyteArray value) {
ScopedByteArrayRO keyRO(env, key);
ScopedByteArrayRW valueRW(env, value);
// If an element is found, the operation returns zero and stores the element's value into
// "value". If no element is found, the operation returns -1 and sets errno to ENOENT.
int ret = bpf::findMapEntry(static_cast<int>(fd), keyRO.get(), valueRW.get());
return throwIfNotEnoent(env, "nativeFindMapEntry", ret, errno);
}
/*
* JNI registration.
*/
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeBpfFdGet", "(Ljava/lang/String;I)I",
(void*) com_android_net_module_util_BpfMap_nativeBpfFdGet },
{ "nativeWriteToMapEntry", "(I[B[BI)V",
(void*) com_android_net_module_util_BpfMap_nativeWriteToMapEntry },
{ "nativeDeleteMapEntry", "(I[B)Z",
(void*) com_android_net_module_util_BpfMap_nativeDeleteMapEntry },
{ "nativeGetNextMapKey", "(I[B[B)Z",
(void*) com_android_net_module_util_BpfMap_nativeGetNextMapKey },
{ "nativeFindMapEntry", "(I[B[B)Z",
(void*) com_android_net_module_util_BpfMap_nativeFindMapEntry },
};
int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name) {
return jniRegisterNativeMethods(env,
class_name,
gMethods, NELEM(gMethods));
}
}; // namespace android