From 1d2a6baaa1fd9d7e3e30027de1d922df5e00be27 Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 29 Jan 2016 20:30:52 +0100 Subject: [PATCH] Native get name by IP PoC --- .../main/java/eu/faircode/netguard/Util.java | 5 + app/src/main/jni/netguard/netguard.c | 97 +++++++++++++++---- app/src/main/jni/netguard/netguard.h | 15 +++ 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/eu/faircode/netguard/Util.java b/app/src/main/java/eu/faircode/netguard/Util.java index 56d9a3f2..85ab0b15 100644 --- a/app/src/main/java/eu/faircode/netguard/Util.java +++ b/app/src/main/java/eu/faircode/netguard/Util.java @@ -74,6 +74,8 @@ public class Util { private static native String jni_getprop(String name); + private static native String jni_resolve(String ip); + static { System.loadLibrary("netguard"); } @@ -370,12 +372,15 @@ public class Util { new AsyncTask() { @Override protected String doInBackground(String... args) { + return jni_resolve(args[0]); + /* try { // This requires internet permission return InetAddress.getByName(args[0]).getHostName(); } catch (UnknownHostException ignored) { return args[0]; } + */ } @Override diff --git a/app/src/main/jni/netguard/netguard.c b/app/src/main/jni/netguard/netguard.c index 84282b53..7e2c5473 100644 --- a/app/src/main/jni/netguard/netguard.c +++ b/app/src/main/jni/netguard/netguard.c @@ -793,6 +793,8 @@ int get_qname(const uint8_t *data, const size_t datalen, uint16_t off, char *qna return (c ? off : ptr); } +static struct dns_entry *dns_entry = NULL; + void parse_dns_response(const struct arguments *args, const uint8_t *data, const size_t datalen) { if (datalen < sizeof(struct dns_header) + 1) { log_android(ANDROID_LOG_WARN, "DNS response length %d", datalen); @@ -804,12 +806,16 @@ void parse_dns_response(const struct arguments *args, const uint8_t *data, const const struct dns_header *dns = (struct dns_header *) data; int qcount = ntohs(dns->q_count); int acount = ntohs(dns->ans_count); - if (dns->qr == 1 && dns->opcode == 0 && qcount > 0) { + if (dns->qr == 1 && dns->opcode == 0 && qcount > 0 && acount > 0) { log_android(ANDROID_LOG_WARN, "DNS response qcount %d acount %d", qcount, acount); // http://tools.ietf.org/html/rfc1035 - char qname[DNS_QNAME_MAX + 1]; + struct dns_entry *entry = malloc(sizeof(struct dns_entry)); + entry->acount = 0; + entry->answer = NULL; + + char qname[DNS_QNAME_MAX + 1]; uint16_t off = sizeof(struct dns_header); for (int q = 0; q < qcount; q++) { off = get_qname(data, datalen, off, qname); @@ -820,6 +826,11 @@ void parse_dns_response(const struct arguments *args, const uint8_t *data, const "DNS question %d qtype %d qclass %d qname %s", q, qtype, qclass, qname); off += 4; + + // TODO multiple qnames? + if (q == 0) + entry->qname = malloc(strlen(qname) + 1); + strcpy(entry->qname, qname); } else { log_android(ANDROID_LOG_ERROR, @@ -839,23 +850,35 @@ void parse_dns_response(const struct arguments *args, const uint8_t *data, const off += 10; if (off + rdlength <= datalen) { - char addr[INET6_ADDRSTRLEN + 1]; - if (qclass == DNS_QCLASS_IN && qtype == DNS_QTYPE_A) { - inet_ntop(AF_INET, data + off, addr, sizeof(addr)); + if (qclass == DNS_QCLASS_IN && + (qtype == DNS_QTYPE_A || + qtype == DNS_QTYPE_AAAA || + qtype == DNS_QTYPE_CNAME)) { + + char rd[INET6_ADDRSTRLEN + 1]; + if (qtype == DNS_QTYPE_A) + inet_ntop(AF_INET, data + off, rd, sizeof(rd)); + else if (qclass == DNS_QCLASS_IN && qtype == DNS_QTYPE_AAAA) + inet_ntop(AF_INET6, data + off, rd, sizeof(rd)); + else if (qclass == DNS_QCLASS_IN && qtype == DNS_QTYPE_CNAME) { + if (get_qname(data, datalen, off, rd) < 0) + log_android(ANDROID_LOG_WARN, "DNS cname error"); + } + log_android(ANDROID_LOG_WARN, - "DNS answer %d qname %s qtype %d ttl %d addr %s", - a, qname, qtype, ttl, addr); - } else if (qclass == DNS_QCLASS_IN && qtype == DNS_QTYPE_AAAA) { - inet_ntop(AF_INET6, data + off, addr, sizeof(addr)); - log_android(ANDROID_LOG_WARN, - "DNS answer %d qname %s qtype %d ttl %d addr %s", - a, qname, qtype, ttl, addr); - } else if (qclass == DNS_QCLASS_IN && qtype == DNS_QTYPE_CNAME) { - char cname[DNS_QNAME_MAX + 1]; - get_qname(data, datalen, off, cname); - log_android(ANDROID_LOG_WARN, - "DNS answer %d qname %s qtype %d ttl %d cname %s", - a, qname, qtype, ttl, cname); + "DNS answer %d qname %s qtype %d ttl %d data %s", + a, qname, qtype, ttl, rd); + + entry->answer = realloc(entry->answer, + sizeof(struct dns_answer *) * (entry->acount + 1)); + entry->answer[entry->acount] = malloc(sizeof(struct dns_answer)); + entry->answer[entry->acount]->time = time(NULL); + entry->answer[entry->acount]->ttl = ttl; + entry->answer[entry->acount]->qtype = qtype; + entry->answer[entry->acount]->rd = malloc(strlen(rd) + 1); + strcpy(entry->answer[entry->acount]->rd, rd); + entry->acount++; + } else log_android(ANDROID_LOG_WARN, "DNS answer %d qname %s qclass %d qtype %d ttl %d length %d", @@ -878,6 +901,14 @@ void parse_dns_response(const struct arguments *args, const uint8_t *data, const return; } } + + if (entry->acount > 0) { + // TODO cleanup old entries + entry->next = dns_entry; + dns_entry = entry; + } + else + free(entry); } else log_android(ANDROID_LOG_INFO, @@ -885,6 +916,36 @@ void parse_dns_response(const struct arguments *args, const uint8_t *data, const dns->qr, dns->opcode, qcount, acount); } +JNIEXPORT jstring JNICALL +Java_eu_faircode_netguard_Util_jni_1resolve(JNIEnv *env, jclass type, jstring ip_) { + const char *ip = (*env)->GetStringUTFChars(env, ip_, 0); + + if (pthread_mutex_lock(&lock)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed"); + + char *result = NULL; + struct dns_entry *entry = dns_entry; + while (entry != NULL) { + for (int a = 0; a < entry->acount; a++) + // TODO check ttl + if (entry->answer[a]->qtype == DNS_QTYPE_CNAME) { + // TODO cname recursion + } + else if (!strcmp(entry->answer[a]->rd, ip)) { + result = entry->qname; + break; + } + entry = entry->next; + } + + if (pthread_mutex_unlock(&lock)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed"); + + (*env)->ReleaseStringUTFChars(env, ip_, ip); + + return (result == NULL ? NULL : (*env)->NewStringUTF(env, result)); +} + void check_tcp_sockets(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds) { struct tcp_session *cur = tcp_session; while (cur != NULL) { diff --git a/app/src/main/jni/netguard/netguard.h b/app/src/main/jni/netguard/netguard.h index 83f33dd8..fe037374 100644 --- a/app/src/main/jni/netguard/netguard.h +++ b/app/src/main/jni/netguard/netguard.h @@ -169,6 +169,21 @@ typedef struct dns_rr { __be16 rdlength; } __packed; +typedef struct dns_answer { + int time; + int ttl; + char *qname; + int qtype; + char *rd; +}; + +typedef struct dns_entry { + char *qname; + int acount; + struct dns_answer **answer; + struct dns_entry *next; +}; + // DHCP #define DHCP_OPTION_MAGIC_NUMBER (0x63825363)