NetGuard/app/src/main/jni/netguard/netguard.c

611 lines
20 KiB
C
Raw Normal View History

2016-01-09 11:10:11 +00:00
#include <jni.h>
2016-01-09 20:17:42 +00:00
#include <stdio.h>
2016-01-10 07:14:47 +00:00
#include <time.h>
2016-01-09 15:56:23 +00:00
#include <unistd.h>
2016-01-09 11:10:11 +00:00
#include <android/log.h>
2016-01-09 15:56:23 +00:00
#include <arpa/inet.h>
2016-01-09 11:10:11 +00:00
#include <netinet/ip.h>
#include <netinet/ip6.h>
2016-01-09 15:56:23 +00:00
#include <netinet/udp.h>
#include <netinet/tcp.h>
2016-01-12 16:19:27 +00:00
#include <pthread.h>
2016-01-09 11:10:11 +00:00
2016-01-11 22:06:35 +00:00
// This should go into a header file later
2016-01-12 12:15:21 +00:00
// https://www.gasmi.net/hpd/
// Ethernet frame: 0800 2086 354b 00e0 f726 3fe9 0800
2016-01-09 11:10:11 +00:00
#define TAG "NetGuard.JNI"
2016-01-09 15:56:23 +00:00
#define MAXPKT 32768
2016-01-12 08:45:58 +00:00
#define TIMEOUTPKT 30
2016-01-12 12:15:21 +00:00
#define TTL 64
2016-01-11 22:06:35 +00:00
struct connection {
2016-01-12 08:45:58 +00:00
time_t time;
2016-01-12 12:15:21 +00:00
__be32 remote_seq; // host notation
__be32 local_seq; // host notation
int32_t saddr; // network notation
__be16 source; // network notation
int32_t daddr; // network notation
__be16 dest; // network notation
2016-01-11 22:06:35 +00:00
int state;
int socket;
2016-01-12 12:15:21 +00:00
int lport; // host notation
2016-01-11 22:06:35 +00:00
struct connection *next;
};
2016-01-12 12:15:21 +00:00
void poll();
void handle_tcp(JNIEnv *, jobject, jbyte *, int);
2016-01-11 22:06:35 +00:00
2016-01-09 18:53:28 +00:00
void decode(JNIEnv *env, jobject instance, jbyte *, int);
2016-01-10 11:51:02 +00:00
int getUid(int, int, void *, int);
2016-01-09 20:17:42 +00:00
2016-01-12 12:15:21 +00:00
unsigned short checksum(unsigned short *, int);
2016-01-11 22:06:35 +00:00
2016-01-12 12:15:21 +00:00
char *hex(jbyte *, int);
int tun;
struct connection *connection = NULL;
2016-01-12 16:19:27 +00:00
pthread_mutex_t poll_lock;
2016-01-11 22:06:35 +00:00
// JNI interface
2016-01-09 11:10:11 +00:00
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_SinkholeService_jni_1init(JNIEnv *env, jobject instance) {
2016-01-11 22:06:35 +00:00
__android_log_print(ANDROID_LOG_INFO, TAG, "Init");
2016-01-12 16:19:27 +00:00
if (pthread_mutex_init(&poll_lock, NULL) != 0)
__android_log_print(ANDROID_LOG_ERROR, TAG, "Mutex init error %d: %s",
errno, strerror(errno));
// TODO pthread_mutex_destroy
2016-01-09 11:10:11 +00:00
}
2016-01-12 12:15:21 +00:00
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_SinkholeService_jni_1tun(JNIEnv *env, jobject instance, jint fd) {
__android_log_print(ANDROID_LOG_INFO, TAG, "tun");
tun = fd;
}
2016-01-09 11:10:11 +00:00
JNIEXPORT void JNICALL
Java_eu_faircode_netguard_SinkholeService_jni_1decode(JNIEnv *env, jobject instance,
2016-01-09 18:53:28 +00:00
jbyteArray buffer_, jint length) {
2016-01-09 11:10:11 +00:00
jbyte *buffer = (*env)->GetByteArrayElements(env, buffer_, NULL);
2016-01-09 18:53:28 +00:00
decode(env, instance, buffer, length);
2016-01-09 11:10:11 +00:00
(*env)->ReleaseByteArrayElements(env, buffer_, buffer, 0);
}
2016-01-09 15:56:23 +00:00
JNIEXPORT void JNICALL
2016-01-12 16:19:27 +00:00
Java_eu_faircode_netguard_SinkholeService_jni_1poll(JNIEnv *env, jobject instance) {
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Poll");
poll();
2016-01-09 15:56:23 +00:00
}
2016-01-11 22:06:35 +00:00
// Private functions
void poll() {
2016-01-12 16:19:27 +00:00
if (pthread_mutex_lock(&poll_lock) != 0)
__android_log_print(ANDROID_LOG_ERROR, TAG, "Mutex lock error %d: %s",
errno, strerror(errno));
2016-01-12 08:45:58 +00:00
time_t now = time(NULL);
2016-01-11 22:06:35 +00:00
struct connection *last = NULL;
struct connection *cur = connection;
while (cur != NULL) {
2016-01-12 08:45:58 +00:00
// Log
char dest[20];
inet_ntop(AF_INET, &(cur->daddr), dest, sizeof(dest));
2016-01-11 22:06:35 +00:00
2016-01-12 08:45:58 +00:00
if (cur->state == TCP_CLOSE || cur->time + TIMEOUTPKT < now) {
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Close/timeout %s/%u lport=%u",
2016-01-12 08:45:58 +00:00
dest, ntohs(cur->dest), cur->lport);
2016-01-11 22:06:35 +00:00
2016-01-12 08:45:58 +00:00
shutdown(cur->socket, SHUT_RDWR);
if (last == NULL)
connection = cur->next;
else
last->next = cur->next;
free(cur);
} else {
if (cur->state == TCP_SYN_RECV) {
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Poll %s/%u lport=%u",
2016-01-12 08:45:58 +00:00
dest, ntohs(cur->dest), cur->lport);
// Check connection state
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(cur->socket, &wfds);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int ready = select(cur->socket + 1, NULL, &wfds, NULL, &tv);
if (ready < 0) {
// TODO
__android_log_print(ANDROID_LOG_ERROR, TAG, "select error %d: %s",
errno, strerror(errno));
continue;
}
// Connected
if (ready == 1) {
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Established ready=%d", ready);
int serr;
int optlen = sizeof(serr);
if (getsockopt(cur->socket, SOL_SOCKET, SO_ERROR, &serr, &optlen) < 0) {
// TODO
__android_log_print(ANDROID_LOG_ERROR, TAG, "getsockopt error %d: %s",
errno, strerror(errno));
cur->state = TCP_CLOSE;
continue;
}
if (serr) {
// TODO
__android_log_print(ANDROID_LOG_ERROR, TAG, "SO_ERROR %d: %s",
serr, strerror(serr));
cur->state = TCP_CLOSE;
continue;
}
// Send ACK
2016-01-12 12:15:21 +00:00
// -> SYN seq=x
// <- SYN-ACK ack=x+1 seq=y
// -> ACK=y+1 seq=x+1
// Build packet
int len = sizeof(struct iphdr) + sizeof(struct tcphdr); // no data
jbyte *buffer = calloc(len, 1); // TODO free
struct iphdr *ip = buffer;
struct tcphdr *tcp = buffer + sizeof(struct iphdr);
// Build IP header
ip->version = 4;
ip->ihl = sizeof(struct iphdr) >> 2;
ip->tot_len = htons(len);
ip->ttl = TTL;
ip->protocol = IPPROTO_TCP;
ip->saddr = cur->daddr;
ip->daddr = cur->saddr;
// Calculate IP checksum
ip->check = checksum(ip, sizeof(struct iphdr));
// Build TCP header
tcp->source = cur->dest;
tcp->dest = cur->source;
tcp->seq = htonl(cur->local_seq);
tcp->ack_seq = htonl(cur->remote_seq + 1); // TODO proper wrap around
tcp->doff = sizeof(struct tcphdr) >> 2;
tcp->syn = 1;
tcp->ack = 1;
// Calculate TCP checksum
int clen = sizeof(struct ippseudo) + sizeof(struct tcphdr);
jbyte csum[clen];
// Build pseudo header
struct ippseudo *pseudo = csum;
pseudo->ippseudo_src.s_addr = ip->saddr;
pseudo->ippseudo_dst.s_addr = ip->daddr;
pseudo->ippseudo_pad = 0;
pseudo->ippseudo_p = ip->protocol;
pseudo->ippseudo_len = htons(sizeof(struct tcphdr)); // no data
// Copy TCP header
memcpy(csum + sizeof(struct ippseudo), tcp, sizeof(struct tcphdr));
tcp->check = checksum(csum, clen);
char to[20];
inet_ntop(AF_INET, &(ip->daddr), to, sizeof(to));
// Send packet
__android_log_print(ANDROID_LOG_DEBUG, TAG,
2016-01-12 16:19:27 +00:00
"Sending SYN+ACK to tun %s/%u ack %u",
to, ntohs(tcp->dest), ntohl(tcp->ack_seq));
2016-01-12 12:15:21 +00:00
if (write(tun, buffer, len) < 0) {
// TODO
__android_log_print(ANDROID_LOG_ERROR, TAG, "write error %d: %s",
errno, strerror(errno));
}
free(buffer);
cur->state = TCP_SYN_SENT;
2016-01-12 08:45:58 +00:00
} else {
// TODO
__android_log_print(ANDROID_LOG_ERROR, TAG, "Connecting ready=%d", ready);
}
2016-01-11 22:06:35 +00:00
}
}
2016-01-12 08:45:58 +00:00
2016-01-11 22:06:35 +00:00
cur = cur->next;
}
2016-01-12 16:19:27 +00:00
if (pthread_mutex_unlock(&poll_lock) != 0)
__android_log_print(ANDROID_LOG_ERROR, TAG, "Mutex unlock error %d: %s",
errno, strerror(errno));
2016-01-11 22:06:35 +00:00
}
2016-01-12 08:45:58 +00:00
void handle_tcp(JNIEnv *env, jobject instance, jbyte *buffer, int len) {
// Check version
jbyte version = (*buffer) >> 4;
if (version != 4)
return;
2016-01-11 22:06:35 +00:00
// Copy buffer
2016-01-12 16:19:27 +00:00
jbyte *copy = malloc(len); // TODO check/free
2016-01-11 22:06:35 +00:00
memcpy(copy, buffer, len);
// Get headers
struct iphdr *iphdr = copy;
jbyte optlen = (iphdr->ihl > 5 ? copy[20] : 0);
struct tcphdr *tcphdr = buffer + (20 + optlen) * sizeof(jbyte);
// Search connection
struct connection *last = NULL;
struct connection *cur = connection;
while (cur != NULL && !(cur->saddr == iphdr->saddr && cur->source != tcphdr->source)) {
last = cur;
cur = cur->next;
}
// Log
char dest[20];
inet_ntop(AF_INET, &(iphdr->daddr), dest, sizeof(dest));
if (cur == NULL) {
if (tcphdr->syn) {
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_DEBUG, TAG, "SYN %s/%u seq %u", dest,
ntohs(tcphdr->dest), ntohl(tcphdr->seq));
2016-01-11 22:06:35 +00:00
// Register connection
2016-01-12 16:19:27 +00:00
struct connection *syn = malloc(sizeof(struct connection)); // TODO check/free
2016-01-12 08:45:58 +00:00
syn->time = time(NULL);
2016-01-12 12:15:21 +00:00
syn->remote_seq = ntohl(tcphdr->seq);
syn->local_seq = 123; // TODO randomize
2016-01-11 22:06:35 +00:00
syn->saddr = iphdr->saddr;
syn->source = tcphdr->source;
syn->daddr = iphdr->daddr;
syn->dest = tcphdr->dest;
syn->state = TCP_SYN_RECV;
syn->next = NULL;
if (last == NULL)
connection = syn;
else
last->next = syn;
// Get TCP socket
if ((syn->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
// TODO
2016-01-12 08:45:58 +00:00
__android_log_print(ANDROID_LOG_ERROR, TAG, "socket error %d: %s",
errno, strerror(errno));
2016-01-11 22:06:35 +00:00
syn->state = TCP_CLOSE;
return;
}
// Set non blocking
int flags = fcntl(syn->socket, F_GETFL, 0);
2016-01-12 08:45:58 +00:00
if (flags < 0 || fcntl(syn->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
2016-01-11 22:06:35 +00:00
// TODO
2016-01-12 08:45:58 +00:00
__android_log_print(ANDROID_LOG_ERROR, TAG, "fcntl error %d: %s",
errno, strerror(errno));
2016-01-11 22:06:35 +00:00
syn->state = TCP_CLOSE;
return;
}
// Protect
jclass cls = (*env)->GetObjectClass(env, instance);
2016-01-12 08:45:58 +00:00
jmethodID mid = (*env)->GetMethodID(env, cls, "protect", "(I)Z");
2016-01-11 22:06:35 +00:00
if (mid == 0) {
2016-01-12 08:45:58 +00:00
__android_log_print(ANDROID_LOG_ERROR, TAG, "protect not found");
2016-01-11 22:06:35 +00:00
syn->state = TCP_CLOSE;
return;
}
else {
2016-01-12 08:45:58 +00:00
jboolean isProtected = (*env)->CallBooleanMethod(env, instance, mid, syn->socket);
if (!isProtected)
__android_log_print(ANDROID_LOG_ERROR, TAG, "protect failed");
jthrowable ex = (*env)->ExceptionOccurred(env);
if (ex) {
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
(*env)->DeleteLocalRef(env, ex);
}
2016-01-11 22:06:35 +00:00
}
2016-01-12 08:45:58 +00:00
// Build target address
2016-01-11 22:06:35 +00:00
struct sockaddr_in a;
memset(&a, 0, sizeof(struct sockaddr_in));
a.sin_family = AF_INET;
a.sin_port = tcphdr->dest;
a.sin_addr.s_addr = iphdr->daddr;
2016-01-12 08:45:58 +00:00
// Initiate connect
2016-01-11 22:06:35 +00:00
int err = connect(syn->socket, &a, sizeof(struct sockaddr_in));
if (err < 0 && errno != EINPROGRESS) {
// TODO
2016-01-12 08:45:58 +00:00
__android_log_print(ANDROID_LOG_ERROR, TAG, "connect error %d: %s",
errno, strerror(errno));
2016-01-11 22:06:35 +00:00
syn->state = TCP_CLOSE;
return;
}
2016-01-12 08:45:58 +00:00
// Get local port
struct sockaddr_in sin;
int sinlen = sizeof(sin);
if (getsockname(syn->socket, &sin, &sinlen) < 0)
__android_log_print(ANDROID_LOG_ERROR, TAG, "getsockname error %d: %s",
errno, strerror(errno));
else
syn->lport = ntohs(sin.sin_port);
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Connecting to %s/%u lport %u",
2016-01-12 08:45:58 +00:00
dest, ntohs(tcphdr->dest), syn->lport);
2016-01-11 22:06:35 +00:00
}
}
else {
2016-01-12 08:45:58 +00:00
cur->time = time(NULL);
2016-01-11 22:06:35 +00:00
if (tcphdr->syn) {
// TODO
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_DEBUG, TAG, "SYNx2 %s/%u", dest, ntohs(tcphdr->dest));
2016-01-11 22:06:35 +00:00
}
2016-01-12 12:15:21 +00:00
else if (tcphdr->ack) {
// TODO
// check seq
// check ack
if (cur->state == TCP_SYN_SENT)
cur->state = TCP_ESTABLISHED;
}
shutdown(cur->socket, SHUT_RDWR);
2016-01-11 22:06:35 +00:00
}
}
2016-01-09 18:53:28 +00:00
void decode(JNIEnv *env, jobject instance, jbyte *buffer, int length) {
2016-01-10 07:14:47 +00:00
jbyte protocol;
2016-01-10 11:51:02 +00:00
void *saddr;
void *daddr;
2016-01-09 18:53:28 +00:00
char source[40];
char dest[40];
char flags[10];
int flen = 0;
2016-01-10 07:14:47 +00:00
jbyte *payload;
2016-01-09 18:53:28 +00:00
2016-01-10 07:14:47 +00:00
// Get protocol, addresses & payload
2016-01-09 18:53:28 +00:00
jbyte version = (*buffer) >> 4;
if (version == 4) {
struct iphdr *ip4hdr = buffer;
2016-01-10 07:14:47 +00:00
2016-01-09 18:53:28 +00:00
protocol = ip4hdr->protocol;
2016-01-10 11:51:02 +00:00
saddr = &ip4hdr->saddr;
daddr = &ip4hdr->daddr;
2016-01-09 18:53:28 +00:00
if (ip4hdr->frag_off & IP_MF)
flags[flen++] = '+';
2016-01-11 22:06:35 +00:00
jbyte optlen = (ip4hdr->ihl > 5 ? buffer[20] : 0);
payload = buffer + 20 + optlen;
2016-01-12 12:15:21 +00:00
uint16_t csum = checksum(ip4hdr, sizeof(struct iphdr));
if (csum != 0) {
// TODO checksum
__android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid IP checksum");
}
2016-01-09 18:53:28 +00:00
}
else if (version == 6) {
struct ip6_hdr *ip6hdr = buffer;
2016-01-10 07:14:47 +00:00
2016-01-09 18:53:28 +00:00
protocol = ip6hdr->ip6_nxt;
2016-01-10 11:51:02 +00:00
saddr = &ip6hdr->ip6_src;
daddr = &ip6hdr->ip6_dst;
2016-01-09 18:53:28 +00:00
2016-01-11 22:06:35 +00:00
payload = buffer + 40;
2016-01-12 12:15:21 +00:00
// TODO checksum
2016-01-09 18:53:28 +00:00
}
else {
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_WARN, TAG, "Unknown version %d", version);
2016-01-10 07:14:47 +00:00
return;
2016-01-09 18:53:28 +00:00
}
2016-01-11 22:06:35 +00:00
inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source));
inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
2016-01-10 07:14:47 +00:00
// Get ports & flags
2016-01-09 18:53:28 +00:00
int sport = -1;
int dport = -1;
if (protocol == IPPROTO_TCP) {
struct tcphdr *tcp = payload;
2016-01-10 07:14:47 +00:00
2016-01-09 18:53:28 +00:00
sport = ntohs(tcp->source);
dport = ntohs(tcp->dest);
2016-01-10 07:14:47 +00:00
2016-01-09 18:53:28 +00:00
if (tcp->syn)
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';
2016-01-12 12:15:21 +00:00
// TODO checksum
2016-01-09 18:53:28 +00:00
} else if (protocol == IPPROTO_UDP) {
struct udphdr *udp = payload;
2016-01-10 07:14:47 +00:00
2016-01-09 18:53:28 +00:00
sport = ntohs(udp->source);
dport = ntohs(udp->dest);
2016-01-12 12:15:21 +00:00
// TODO checksum
2016-01-09 18:53:28 +00:00
}
flags[flen] = 0;
2016-01-10 07:14:47 +00:00
// Get uid
int uid = -1;
if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) {
// Sleep 10 ms
struct timespec tim, tim2;
tim.tv_sec = 0;
tim.tv_nsec = 10000000L;
nanosleep(&tim, &tim2);
// Lookup uid
2016-01-10 11:51:02 +00:00
uid = getUid(protocol, version, saddr, sport);
2016-01-10 07:14:47 +00:00
if (uid < 0 && version == 4) {
2016-01-10 11:51:02 +00:00
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);
2016-01-10 07:14:47 +00:00
}
}
2016-01-12 12:15:21 +00:00
__android_log_print(ANDROID_LOG_DEBUG, TAG,
"Packet v%d %s/%u -> %s/%u proto %d flags %s uid %d",
2016-01-11 22:06:35 +00:00
version, source, sport, dest, dport, protocol, flags, uid);
poll();
2016-01-12 08:45:58 +00:00
if (protocol == IPPROTO_TCP)
handle_tcp(env, instance, buffer, length);
2016-01-11 22:06:35 +00:00
2016-01-10 07:14:47 +00:00
// Call back
2016-01-09 18:53:28 +00:00
jclass cls = (*env)->GetObjectClass(env, instance);
jmethodID mid = (*env)->GetMethodID(env, cls, "logPacket",
2016-01-10 07:14:47 +00:00
"(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;I)V");
2016-01-11 22:06:35 +00:00
if (mid == 0)
__android_log_print(ANDROID_LOG_ERROR, TAG, "logPacket not found");
else {
2016-01-09 18:53:28 +00:00
jstring jsource = (*env)->NewStringUTF(env, source);
jstring jdest = (*env)->NewStringUTF(env, dest);
jstring jflags = (*env)->NewStringUTF(env, flags);
(*env)->CallVoidMethod(env, instance, mid,
2016-01-10 07:14:47 +00:00
version, jsource, sport, jdest, dport, protocol, jflags, uid);
(*env)->DeleteLocalRef(env, jsource);
(*env)->DeleteLocalRef(env, jdest);
(*env)->DeleteLocalRef(env, jflags);
2016-01-10 16:10:52 +00:00
jthrowable ex = (*env)->ExceptionOccurred(env);
if (ex) {
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
(*env)->DeleteLocalRef(env, ex);
}
2016-01-09 18:53:28 +00:00
}
}
2016-01-09 20:17:42 +00:00
2016-01-10 11:51:02 +00:00
int getUid(int protocol, int version, void *saddr, int sport) {
2016-01-10 07:14:47 +00:00
char line[250];
int fields;
int32_t addr32;
int8_t addr128[16];
int port;
int uid = -1;
// Get proc file name
char *fn = NULL;
if (protocol == IPPROTO_TCP)
fn = (version == 4 ? "/proc/net/tcp" : "/proc/net/tcp6");
else if (protocol == IPPROTO_UDP)
fn = (version == 4 ? "/proc/net/udp" : "/proc/net/udp6");
else
return -1;
// Open proc file
FILE *fd = fopen(fn, "r");
if (fd == NULL) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "Error opening %s", fn);
return -1;
}
// Scan proc file
int i = 0;
while (fgets(line, sizeof(line), fd) != NULL) {
if (i++) {
if (version == 4)
fields = sscanf(line,
"%*d: %X:%X %*X:%*X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld ",
&addr32, &port, &uid);
else
fields = sscanf(line,
"%*d: %8X%8X%8X%8X:%X %*X:%*X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld ",
addr128, addr128 + 4, addr128 + 8, addr128 + 12, &port, &uid);
if (fields < 3) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid field #%d: %s", fields, line);
break;
2016-01-09 20:17:42 +00:00
}
2016-01-10 07:14:47 +00:00
2016-01-10 11:51:02 +00:00
if (port == sport) {
if (version == 4) {
if (addr32 == *((int32_t *) saddr))
return uid;
}
else {
if (memcmp(addr128, saddr, (size_t) 16) == 0)
return uid;
}
}
2016-01-09 20:17:42 +00:00
}
}
2016-01-10 07:14:47 +00:00
fclose(fd);
2016-01-10 11:51:02 +00:00
return -1;
2016-01-12 12:15:21 +00:00
}
unsigned short checksum(unsigned short *addr, int len) {
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back
* all the carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
char *hex(jbyte *data, int len) {
char hex_str[] = "0123456789abcdef";
char *out;
out = (char *) malloc(len * 2 + 1);
(out)[len * 2] = 0;
if (!len) return NULL;
for (size_t i = 0; i < len; i++) {
(out)[i * 2 + 0] = hex_str[(data[i] >> 4) & 0x0F];
(out)[i * 2 + 1] = hex_str[(data[i]) & 0x0F];
}
return out;
2016-01-12 16:19:27 +00:00
}