Making magic with the network stack
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

182 lines
4.7 KiB

/*
This file is part of NetGuard.
NetGuard is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
NetGuard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with NetGuard. If not, see <http://www.gnu.org/licenses/>.
Copyright 2015-2019 by Marcel Bokhorst (M66B)
*/
#include "netguard.h"
extern int loglevel;
uint16_t calc_checksum(uint16_t start, const uint8_t *buffer, size_t length) {
register uint32_t sum = start;
register uint16_t *buf = (uint16_t *) buffer;
register size_t len = length;
while (len > 1) {
sum += *buf++;
len -= 2;
}
if (len > 0)
sum += *((uint8_t *) buf);
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
return (uint16_t) sum;
}
int compare_u32(uint32_t s1, uint32_t s2) {
// https://tools.ietf.org/html/rfc1982
if (s1 == s2)
return 0;
uint32_t i1 = s1;
uint32_t i2 = s2;
if ((i1 < i2 && i2 - i1 < 0x7FFFFFFF) ||
(i1 > i2 && i1 - i2 > 0x7FFFFFFF))
return -1;
else
return 1;
}
int sdk_int(JNIEnv *env) {
jclass clsVersion = jniFindClass(env, "android/os/Build$VERSION");
jfieldID fid = (*env)->GetStaticFieldID(env, clsVersion, "SDK_INT", "I");
return (*env)->GetStaticIntField(env, clsVersion, fid);
}
void log_android(int prio, const char *fmt, ...) {
if (prio >= loglevel) {
char line[1024];
va_list argptr;
va_start(argptr, fmt);
vsprintf(line, fmt, argptr);
__android_log_print(prio, TAG, "%s", line);
va_end(argptr);
}
}
uint8_t char2nible(const char c) {
if (c >= '0' && c <= '9') return (uint8_t) (c - '0');
if (c >= 'a' && c <= 'f') return (uint8_t) ((c - 'a') + 10);
if (c >= 'A' && c <= 'F') return (uint8_t) ((c - 'A') + 10);
return 255;
}
void hex2bytes(const char *hex, uint8_t *buffer) {
size_t len = strlen(hex);
for (int i = 0; i < len; i += 2)
buffer[i / 2] = (char2nible(hex[i]) << 4) | char2nible(hex[i + 1]);
}
char *trim(char *str) {
while (isspace(*str))
str++;
if (*str == 0)
return str;
char *end = str + strlen(str) - 1;
while (end > str && isspace(*end))
end--;
*(end + 1) = 0;
return str;
}
const char *strstate(const int state) {
switch (state) {
case TCP_ESTABLISHED:
return "ESTABLISHED";
case TCP_SYN_SENT:
return "SYN_SENT";
case TCP_SYN_RECV:
return "SYN_RECV";
case TCP_FIN_WAIT1:
return "FIN_WAIT1";
case TCP_FIN_WAIT2:
return "FIN_WAIT2";
case TCP_TIME_WAIT:
return "TIME_WAIT";
case TCP_CLOSE:
return "CLOSE";
case TCP_CLOSE_WAIT:
return "CLOSE_WAIT";
case TCP_LAST_ACK:
return "LAST_ACK";
case TCP_LISTEN:
return "LISTEN";
case TCP_CLOSING:
return "CLOSING";
default:
return "UNKNOWN";
}
}
char *hex(const u_int8_t *data, const size_t len) {
char hex_str[] = "0123456789ABCDEF";
char *hexout;
hexout = (char *) ng_malloc(len * 3 + 1, "hex"); // TODO free
for (size_t i = 0; i < len; i++) {
hexout[i * 3 + 0] = hex_str[(data[i] >> 4) & 0x0F];
hexout[i * 3 + 1] = hex_str[(data[i]) & 0x0F];
hexout[i * 3 + 2] = ' ';
}
hexout[len * 3] = 0;
return hexout;
}
int32_t get_local_port(const int sock) {
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *) &sin, &len) < 0) {
log_android(ANDROID_LOG_ERROR, "getsockname error %d: %s", errno, strerror(errno));
return -1;
} else
return ntohs(sin.sin_port);
}
int is_event(int fd, short event) {
struct pollfd p;
p.fd = fd;
p.events = event;
p.revents = 0;
int r = poll(&p, 1, 0);
if (r < 0) {
log_android(ANDROID_LOG_ERROR, "poll readable error %d: %s", errno, strerror(errno));
return 0;
} else if (r == 0)
return 0;
else
return (p.revents & event);
}
int is_readable(int fd) {
return is_event(fd, POLLIN);
}
int is_writable(int fd) {
return is_event(fd, POLLOUT);
}
long long get_ms() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000LL + ts.tv_nsec / 1e6;
}