mirror of
https://github.com/M66B/NetGuard.git
synced 2025-02-26 16:13:01 +00:00
Native refactoring
This commit is contained in:
parent
00b476f599
commit
e5d403e2a7
1 changed files with 152 additions and 155 deletions
|
@ -60,6 +60,8 @@ struct connection {
|
||||||
|
|
||||||
void *handle_events(void *);
|
void *handle_events(void *);
|
||||||
|
|
||||||
|
void handle_ip(JNIEnv *, jobject, const struct arguments *, const uint8_t *, const uint16_t);
|
||||||
|
|
||||||
void handle_tcp(JNIEnv *, jobject, const struct arguments *args,
|
void handle_tcp(JNIEnv *, jobject, const struct arguments *args,
|
||||||
const uint8_t *, const uint16_t, int uid);
|
const uint8_t *, const uint16_t, int uid);
|
||||||
|
|
||||||
|
@ -71,8 +73,6 @@ int canWrite(const int);
|
||||||
|
|
||||||
int writeTCP(const struct connection *, struct data *, uint16_t, int, int, int, int);
|
int writeTCP(const struct connection *, struct data *, uint16_t, int, int, int, int);
|
||||||
|
|
||||||
void handle_ip(JNIEnv *, jobject, const struct arguments *, const uint8_t *, const uint16_t);
|
|
||||||
|
|
||||||
jint getUid(const int, const int, const void *, const uint16_t);
|
jint getUid(const int, const int, const void *, const uint16_t);
|
||||||
|
|
||||||
uint16_t checksum(uint8_t *, uint16_t);
|
uint16_t checksum(uint8_t *, uint16_t);
|
||||||
|
@ -424,6 +424,156 @@ void *handle_events(void *a) {
|
||||||
args->tun, thread_id);
|
args->tun, thread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_ip(JNIEnv *env, jobject instance, const struct arguments *args,
|
||||||
|
const uint8_t *buffer, const uint16_t length) {
|
||||||
|
uint8_t protocol;
|
||||||
|
void *saddr;
|
||||||
|
void *daddr;
|
||||||
|
char source[40];
|
||||||
|
char dest[40];
|
||||||
|
char flags[10];
|
||||||
|
int flen = 0;
|
||||||
|
uint8_t *payload;
|
||||||
|
|
||||||
|
// Get protocol, addresses & payload
|
||||||
|
uint8_t version = (*buffer) >> 4;
|
||||||
|
if (version == 4) {
|
||||||
|
struct iphdr *ip4hdr = buffer;
|
||||||
|
|
||||||
|
protocol = ip4hdr->protocol;
|
||||||
|
saddr = &ip4hdr->saddr;
|
||||||
|
daddr = &ip4hdr->daddr;
|
||||||
|
|
||||||
|
if (ip4hdr->frag_off & IP_MF)
|
||||||
|
flags[flen++] = '+';
|
||||||
|
|
||||||
|
uint8_t optlen = (ip4hdr->ihl - 5) * 4;
|
||||||
|
payload = buffer + 20 + optlen;
|
||||||
|
|
||||||
|
if (ntohs(ip4hdr->tot_len) != length) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid length %u header length %u",
|
||||||
|
length, ntohs(ip4hdr->tot_len));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t csum = checksum(ip4hdr, sizeof(struct iphdr));
|
||||||
|
if (csum != 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid IP checksum");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (version == 6) {
|
||||||
|
struct ip6_hdr *ip6hdr = buffer;
|
||||||
|
|
||||||
|
protocol = ip6hdr->ip6_nxt;
|
||||||
|
saddr = &ip6hdr->ip6_src;
|
||||||
|
daddr = &ip6hdr->ip6_dst;
|
||||||
|
|
||||||
|
payload = buffer + 40;
|
||||||
|
|
||||||
|
// TODO check length
|
||||||
|
// TODO checksum
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
__android_log_print(ANDROID_LOG_WARN, TAG, "Unknown version %d", version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source));
|
||||||
|
inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
|
||||||
|
|
||||||
|
// Get ports & flags
|
||||||
|
int syn = 0;
|
||||||
|
uint16_t sport = -1;
|
||||||
|
uint16_t dport = -1;
|
||||||
|
if (protocol == IPPROTO_TCP) {
|
||||||
|
struct tcphdr *tcp = payload;
|
||||||
|
|
||||||
|
sport = ntohs(tcp->source);
|
||||||
|
dport = ntohs(tcp->dest);
|
||||||
|
|
||||||
|
if (tcp->syn) {
|
||||||
|
syn = 1;
|
||||||
|
flags[flen++] = 'S';
|
||||||
|
}
|
||||||
|
if (tcp->ack)
|
||||||
|
flags[flen++] = 'A';
|
||||||
|
if (tcp->psh)
|
||||||
|
flags[flen++] = 'P';
|
||||||
|
if (tcp->fin)
|
||||||
|
flags[flen++] = 'F';
|
||||||
|
if (tcp->fin)
|
||||||
|
flags[flen++] = 'R';
|
||||||
|
|
||||||
|
// TODO checksum
|
||||||
|
} else if (protocol == IPPROTO_UDP) {
|
||||||
|
struct udphdr *udp = payload;
|
||||||
|
|
||||||
|
sport = ntohs(udp->source);
|
||||||
|
dport = ntohs(udp->dest);
|
||||||
|
|
||||||
|
// TODO checksum
|
||||||
|
}
|
||||||
|
flags[flen] = 0;
|
||||||
|
|
||||||
|
// Get uid
|
||||||
|
jint uid = -1;
|
||||||
|
if ((protocol == IPPROTO_TCP && syn) || protocol == IPPROTO_UDP) {
|
||||||
|
// Sleep 10 ms
|
||||||
|
usleep(1000 * UIDDELAY);
|
||||||
|
|
||||||
|
// Lookup uid
|
||||||
|
uid = getUid(protocol, version, saddr, sport);
|
||||||
|
if (uid < 0 && version == 4) {
|
||||||
|
int8_t saddr128[16];
|
||||||
|
memset(saddr128, 0, 10);
|
||||||
|
saddr128[10] = 0xFF;
|
||||||
|
saddr128[11] = 0xFF;
|
||||||
|
memcpy(saddr128 + 12, saddr, 4);
|
||||||
|
uid = getUid(protocol, 6, saddr128, sport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, TAG,
|
||||||
|
"Packet v%d %s/%u -> %s/%u proto %d flags %s uid %d",
|
||||||
|
version, source, sport, dest, dport, protocol, flags, uid);
|
||||||
|
|
||||||
|
if (protocol == IPPROTO_TCP)
|
||||||
|
handle_tcp(env, instance, args, buffer, length, uid);
|
||||||
|
|
||||||
|
// Call back
|
||||||
|
if ((protocol == IPPROTO_TCP && syn) || protocol == IPPROTO_UDP) {
|
||||||
|
jclass cls = (*env)->GetObjectClass(env, instance);
|
||||||
|
jmethodID mid = (*env)->GetMethodID(env, cls, "logPacket",
|
||||||
|
"(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;IZ)V");
|
||||||
|
if (mid == 0)
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, TAG, "logPacket not found");
|
||||||
|
else {
|
||||||
|
jboolean allowed = 0;
|
||||||
|
jstring jsource = (*env)->NewStringUTF(env, source);
|
||||||
|
jstring jdest = (*env)->NewStringUTF(env, dest);
|
||||||
|
jstring jflags = (*env)->NewStringUTF(env, flags);
|
||||||
|
(*env)->CallVoidMethod(env, instance, mid,
|
||||||
|
version,
|
||||||
|
jsource, sport,
|
||||||
|
jdest, dport,
|
||||||
|
protocol, jflags,
|
||||||
|
uid, allowed);
|
||||||
|
(*env)->DeleteLocalRef(env, jsource);
|
||||||
|
(*env)->DeleteLocalRef(env, jdest);
|
||||||
|
(*env)->DeleteLocalRef(env, jflags);
|
||||||
|
|
||||||
|
jthrowable ex = (*env)->ExceptionOccurred(env);
|
||||||
|
if (ex) {
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
(*env)->ExceptionClear(env);
|
||||||
|
(*env)->DeleteLocalRef(env, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*env)->DeleteLocalRef(env, cls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handle_tcp(JNIEnv *env, jobject instance, const struct arguments *args,
|
void handle_tcp(JNIEnv *env, jobject instance, const struct arguments *args,
|
||||||
const uint8_t *buffer, uint16_t length, int uid) {
|
const uint8_t *buffer, uint16_t length, int uid) {
|
||||||
// Check version
|
// Check version
|
||||||
|
@ -438,9 +588,6 @@ void handle_tcp(JNIEnv *env, jobject instance, const struct arguments *args,
|
||||||
if (optlen)
|
if (optlen)
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG, "optlen %d", optlen);
|
__android_log_print(ANDROID_LOG_DEBUG, TAG, "optlen %d", optlen);
|
||||||
|
|
||||||
if (ntohs(iphdr->tot_len) != length)
|
|
||||||
__android_log_print(ANDROID_LOG_WARN, TAG, "Invalid length %u/%d", iphdr->tot_len, length);
|
|
||||||
|
|
||||||
// Get data
|
// Get data
|
||||||
uint16_t dataoff = sizeof(struct iphdr) + optlen + sizeof(struct tcphdr);
|
uint16_t dataoff = sizeof(struct iphdr) + optlen + sizeof(struct tcphdr);
|
||||||
uint16_t datalen = length - dataoff;
|
uint16_t datalen = length - dataoff;
|
||||||
|
@ -782,156 +929,6 @@ int writeTCP(const struct connection *cur,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_ip(JNIEnv *env, jobject instance, const struct arguments *args,
|
|
||||||
const uint8_t *buffer, const uint16_t length) {
|
|
||||||
uint8_t protocol;
|
|
||||||
void *saddr;
|
|
||||||
void *daddr;
|
|
||||||
char source[40];
|
|
||||||
char dest[40];
|
|
||||||
char flags[10];
|
|
||||||
int flen = 0;
|
|
||||||
uint8_t *payload;
|
|
||||||
|
|
||||||
// Get protocol, addresses & payload
|
|
||||||
uint8_t version = (*buffer) >> 4;
|
|
||||||
if (version == 4) {
|
|
||||||
struct iphdr *ip4hdr = buffer;
|
|
||||||
|
|
||||||
protocol = ip4hdr->protocol;
|
|
||||||
saddr = &ip4hdr->saddr;
|
|
||||||
daddr = &ip4hdr->daddr;
|
|
||||||
|
|
||||||
if (ip4hdr->frag_off & IP_MF)
|
|
||||||
flags[flen++] = '+';
|
|
||||||
|
|
||||||
uint8_t optlen = (ip4hdr->ihl - 5) * 4;
|
|
||||||
payload = buffer + 20 + optlen;
|
|
||||||
|
|
||||||
if (ntohs(ip4hdr->tot_len) != length) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid length %u header length %u",
|
|
||||||
length, ntohs(ip4hdr->tot_len));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t csum = checksum(ip4hdr, sizeof(struct iphdr));
|
|
||||||
if (csum != 0) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid IP checksum");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (version == 6) {
|
|
||||||
struct ip6_hdr *ip6hdr = buffer;
|
|
||||||
|
|
||||||
protocol = ip6hdr->ip6_nxt;
|
|
||||||
saddr = &ip6hdr->ip6_src;
|
|
||||||
daddr = &ip6hdr->ip6_dst;
|
|
||||||
|
|
||||||
payload = buffer + 40;
|
|
||||||
|
|
||||||
// TODO check length
|
|
||||||
// TODO checksum
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
__android_log_print(ANDROID_LOG_WARN, TAG, "Unknown version %d", version);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source));
|
|
||||||
inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
|
|
||||||
|
|
||||||
// Get ports & flags
|
|
||||||
int syn = 0;
|
|
||||||
uint16_t sport = -1;
|
|
||||||
uint16_t dport = -1;
|
|
||||||
if (protocol == IPPROTO_TCP) {
|
|
||||||
struct tcphdr *tcp = payload;
|
|
||||||
|
|
||||||
sport = ntohs(tcp->source);
|
|
||||||
dport = ntohs(tcp->dest);
|
|
||||||
|
|
||||||
if (tcp->syn) {
|
|
||||||
syn = 1;
|
|
||||||
flags[flen++] = 'S';
|
|
||||||
}
|
|
||||||
if (tcp->ack)
|
|
||||||
flags[flen++] = 'A';
|
|
||||||
if (tcp->psh)
|
|
||||||
flags[flen++] = 'P';
|
|
||||||
if (tcp->fin)
|
|
||||||
flags[flen++] = 'F';
|
|
||||||
if (tcp->fin)
|
|
||||||
flags[flen++] = 'R';
|
|
||||||
|
|
||||||
// TODO checksum
|
|
||||||
} else if (protocol == IPPROTO_UDP) {
|
|
||||||
struct udphdr *udp = payload;
|
|
||||||
|
|
||||||
sport = ntohs(udp->source);
|
|
||||||
dport = ntohs(udp->dest);
|
|
||||||
|
|
||||||
// TODO checksum
|
|
||||||
}
|
|
||||||
flags[flen] = 0;
|
|
||||||
|
|
||||||
// Get uid
|
|
||||||
jint uid = -1;
|
|
||||||
if ((protocol == IPPROTO_TCP && syn) || protocol == IPPROTO_UDP) {
|
|
||||||
// Sleep 10 ms
|
|
||||||
usleep(1000 * UIDDELAY);
|
|
||||||
|
|
||||||
// Lookup uid
|
|
||||||
uid = getUid(protocol, version, saddr, sport);
|
|
||||||
if (uid < 0 && version == 4) {
|
|
||||||
int8_t saddr128[16];
|
|
||||||
memset(saddr128, 0, 10);
|
|
||||||
saddr128[10] = 0xFF;
|
|
||||||
saddr128[11] = 0xFF;
|
|
||||||
memcpy(saddr128 + 12, saddr, 4);
|
|
||||||
uid = getUid(protocol, 6, saddr128, sport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, TAG,
|
|
||||||
"Packet v%d %s/%u -> %s/%u proto %d flags %s uid %d",
|
|
||||||
version, source, sport, dest, dport, protocol, flags, uid);
|
|
||||||
|
|
||||||
if (protocol == IPPROTO_TCP)
|
|
||||||
handle_tcp(env, instance, args, buffer, length, uid);
|
|
||||||
|
|
||||||
// Call back
|
|
||||||
if ((protocol == IPPROTO_TCP && syn) || protocol == IPPROTO_UDP) {
|
|
||||||
jclass cls = (*env)->GetObjectClass(env, instance);
|
|
||||||
jmethodID mid = (*env)->GetMethodID(env, cls, "logPacket",
|
|
||||||
"(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;IZ)V");
|
|
||||||
if (mid == 0)
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "logPacket not found");
|
|
||||||
else {
|
|
||||||
jboolean allowed = 0;
|
|
||||||
jstring jsource = (*env)->NewStringUTF(env, source);
|
|
||||||
jstring jdest = (*env)->NewStringUTF(env, dest);
|
|
||||||
jstring jflags = (*env)->NewStringUTF(env, flags);
|
|
||||||
(*env)->CallVoidMethod(env, instance, mid,
|
|
||||||
version,
|
|
||||||
jsource, sport,
|
|
||||||
jdest, dport,
|
|
||||||
protocol, jflags,
|
|
||||||
uid, allowed);
|
|
||||||
(*env)->DeleteLocalRef(env, jsource);
|
|
||||||
(*env)->DeleteLocalRef(env, jdest);
|
|
||||||
(*env)->DeleteLocalRef(env, jflags);
|
|
||||||
|
|
||||||
jthrowable ex = (*env)->ExceptionOccurred(env);
|
|
||||||
if (ex) {
|
|
||||||
(*env)->ExceptionDescribe(env);
|
|
||||||
(*env)->ExceptionClear(env);
|
|
||||||
(*env)->DeleteLocalRef(env, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*env)->DeleteLocalRef(env, cls);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jint getUid(const int protocol, const int version, const void *saddr, const uint16_t sport) {
|
jint getUid(const int protocol, const int version, const void *saddr, const uint16_t sport) {
|
||||||
char line[250];
|
char line[250];
|
||||||
int fields;
|
int fields;
|
||||||
|
|
Loading…
Reference in a new issue