broke jvm
This commit is contained in:
101
src/main/c/tun.c
Normal file
101
src/main/c/tun.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include <jni.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
static int tun_set_up(const char *ifname) {
|
||||
struct ifreq ifr;
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifr.ifr_flags |= IFF_UP;
|
||||
|
||||
int res = ioctl(fd, SIOCSIFFLAGS, &ifr);
|
||||
close(fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int tun_set_ip(const char *ifname, const char *ip) {
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, ip, &sin.sin_addr);
|
||||
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||
memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
|
||||
|
||||
int res = ioctl(fd, SIOCSIFADDR, &ifr);
|
||||
close(fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_su_sonoma_TunDevice_ioctlTun(
|
||||
JNIEnv *env,
|
||||
jobject obj,
|
||||
jobject fdObj,
|
||||
jstring name,
|
||||
jstring ip,
|
||||
jint flags
|
||||
) {
|
||||
const char *dev = (*env)->GetStringUTFChars(env, name, 0);
|
||||
const char *c_ip = (*env)->GetStringUTFChars(env, ip, 0);
|
||||
|
||||
if (c_ip == NULL) return -1;
|
||||
if (dev == NULL) return -1;
|
||||
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
ifr.ifr_flags = flags;
|
||||
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
|
||||
|
||||
jclass fdClass = (*env)->GetObjectClass(env, fdObj);
|
||||
jfieldID fieldID = (*env)->GetFieldID(env, fdClass, "fd", "I");
|
||||
|
||||
int fd = (*env)->GetIntField(env, fdObj, fieldID);
|
||||
|
||||
int result = ioctl(fd, TUNSETIFF, &ifr);
|
||||
|
||||
if (result < 0) {
|
||||
perror("ioctl(TUNSETIFF)");
|
||||
return -1;
|
||||
}
|
||||
if (tun_set_up(dev) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tun_set_ip(dev, c_ip) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, name, dev);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
package su.sonoma
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.DataInputStream
|
||||
import java.net.Socket
|
||||
@ -18,7 +17,6 @@ fun startClient() = runBlocking {
|
||||
launch {
|
||||
val buffer = ByteArray(32768)
|
||||
|
||||
// TUN → SERVER
|
||||
while (true) {
|
||||
val len = tun.input.read(buffer)
|
||||
|
||||
@ -34,7 +32,6 @@ fun startClient() = runBlocking {
|
||||
launch {
|
||||
val buffer = ByteArray(32768)
|
||||
|
||||
// SERVER → TUN
|
||||
while (true) {
|
||||
val hi = input.read()
|
||||
val lo = input.read()
|
||||
|
||||
@ -38,7 +38,6 @@ suspend fun handle(socket: Socket) {
|
||||
|
||||
val packet = buffer.copyOf(len)
|
||||
|
||||
// 🌍 forward to internet
|
||||
val response = forwardPacket(packet)
|
||||
|
||||
output.write(response.size shr 8)
|
||||
@ -49,8 +48,6 @@ suspend fun handle(socket: Socket) {
|
||||
}
|
||||
fun forwardPacket(packet: ByteArray): ByteArray {
|
||||
|
||||
// ⚠️ simplified: we assume HTTP (not real VPN parsing yet)
|
||||
|
||||
val host = "example.com"
|
||||
val port = 80
|
||||
|
||||
|
||||
@ -6,31 +6,45 @@ import java.io.FileOutputStream
|
||||
import java.io.RandomAccessFile
|
||||
|
||||
class TunDevice(
|
||||
private val name: String = "tun0"
|
||||
private val name: String = "tun0",
|
||||
private val ip: String = "10.1.0.1"
|
||||
) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.load(
|
||||
"${System.getProperty("user.dir")}/build/native/libtun.so"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val input: FileInputStream
|
||||
val output: FileOutputStream
|
||||
|
||||
init {
|
||||
val fd = openTun(name)
|
||||
val fd = openTun(name, ip)
|
||||
input = FileInputStream(fd)
|
||||
output = FileOutputStream(fd)
|
||||
}
|
||||
|
||||
private fun openTun(name: String): FileDescriptor {
|
||||
val fd = FileDescriptor()
|
||||
|
||||
private fun openTun(name: String, ip: String): FileDescriptor {
|
||||
val tun = RandomAccessFile("/dev/net/tun", "rw")
|
||||
val field = tun.javaClass.getDeclaredField("fd")
|
||||
field.isAccessible = true
|
||||
|
||||
val flags = 0x0001 or 0x1000
|
||||
|
||||
val ioctl = ioctlTun(tun.fd, name, flags)
|
||||
if (ioctl < 0) error("Cannot open TUN")
|
||||
val result = ioctlTun(tun.fd, name, ip, flags)
|
||||
|
||||
if (result < 0) {
|
||||
error("Cannot open TUN")
|
||||
}
|
||||
|
||||
return tun.fd
|
||||
}
|
||||
|
||||
private external fun ioctlTun(fd: FileDescriptor?, name: String, flags: Int): Int
|
||||
private external fun ioctlTun(
|
||||
fd: FileDescriptor,
|
||||
name: String,
|
||||
ip: String,
|
||||
flags: Int
|
||||
): Int
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
#include <fcntl.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int create_tun(char *dev) {
|
||||
struct ifreq ifr;
|
||||
int fd = open("/dev/net/tun", O_RDWR);
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
||||
strcpy(ifr.ifr_name, dev);
|
||||
|
||||
ioctl(fd, TUNSETIFF, &ifr);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
// gcc -shared -o libtun.so -fPIC src/main/tun.c
|
||||
Reference in New Issue
Block a user