Android support (#105) patch from Marcel Bokhorst

This commit is contained in:
Marcel Bokhorst 2011-04-23 18:55:59 +00:00 committed by Erik Ekman
parent 66d9428dff
commit a569030bb7
12 changed files with 142 additions and 27 deletions

22
src/Android.mk Normal file
View file

@ -0,0 +1,22 @@
#
# iodine for Android
#
# by Marcel Bokhorst
# http://blog.bokhorst.biz/5123/computers-en-internet/iodine-for-android/
#
# cd iodine-0.6.0-rc1/src
# make base64u.h base64u.c
# .../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
#
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := iodine
LOCAL_SRC_FILES := tun.c dns.c read.c encoding.c login.c base32.c base64.c base64u.c base128.c md5.c common.c iodine.c client.c util.c
LOCAL_CFLAGS := -c -DANDROID -DLINUX -DIFCONFIGPATH=\"/system/bin/\" -Wall
LOCAL_LDLIBS := -lz
include $(BUILD_EXECUTABLE)

39
src/android_dns.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef __FIX_ANDROID_H__
#define __FIX_ANDROID_H__
typedef struct {
unsigned id :16;
unsigned rd :1;
unsigned tc :1;
unsigned aa :1;
unsigned opcode :4;
unsigned qr :1;
unsigned rcode :4;
unsigned cd: 1;
unsigned ad: 1;
unsigned unused :1;
unsigned ra :1;
unsigned qdcount :16;
unsigned ancount :16;
unsigned nscount :16;
unsigned arcount :16;
} HEADER;
#define NOERROR 0
#define FORMERR 1
#define SERVFAIL 2
#define NXDOMAIN 3
#define NOTIMP 4
#define REFUSED 5
#define C_IN 1
#define T_A 1
#define T_CNAME 5
#define T_NULL 10
#define T_MX 15
#define T_TXT 16
#define T_SRV 33
#endif

View file

@ -31,6 +31,9 @@
#include "windows.h"
#include <winsock2.h>
#else
#ifdef ANDROID
#include "android_dns.h"
#endif
#include <arpa/nameser.h>
#ifdef DARWIN
#define BIND_8_COMPAT
@ -148,6 +151,32 @@ client_get_conn()
void
client_set_nameserver(const char *cp, int port)
{
#ifdef ANDROID
struct addrinfo hints, *result, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
char sport[10];
sprintf(sport, "%d", port);
getaddrinfo(cp, sport, &hints, &result);
if (result == NULL)
errx(1, "Cannot resolve %s:%s (no network?)", cp, sport);
else {
for (p = result;p != NULL; p = p->ai_next) {
if (p->ai_family == AF_INET) { /* IPv4 */
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
memset(&nameserv, 0, sizeof(nameserv));
nameserv.sin_family = AF_INET;
nameserv.sin_port = htons(port);
nameserv.sin_addr = ipv4->sin_addr;
freeaddrinfo(result);
return;
}
}
freeaddrinfo(result);
}
#endif
struct in_addr addr;
if (inet_aton(cp, &addr) != 1) {

View file

@ -54,7 +54,7 @@
const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
#if !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
#if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
static int daemon(int nochdir, int noclose)
{
int fd, i;
@ -276,13 +276,15 @@ check_topdomain(char *str)
return 0;
}
#ifdef WINDOWS32
#if defined(WINDOWS32) || defined(ANDROID)
#ifndef ANDROID
int
inet_aton(const char *cp, struct in_addr *inp)
{
inp->s_addr = inet_addr(cp);
return inp->s_addr != INADDR_ANY;
}
#endif
void
warn(const char *fmt, ...)
@ -291,11 +293,13 @@ warn(const char *fmt, ...)
va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list);
#ifndef ANDROID
if (errno == 0) {
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
} else {
fprintf(stderr, ": %s\n", strerror(errno));
}
#endif
va_end(list);
}

View file

@ -119,8 +119,10 @@ void read_password(char*, size_t);
int check_topdomain(char *);
#ifdef WINDOWS32
#if defined(WINDOWS32) || defined(ANDROID)
#ifndef ANDROID
int inet_aton(const char *cp, struct in_addr *inp);
#endif
void err(int eval, const char *fmt, ...);
void warn(const char *fmt, ...);

View file

@ -25,6 +25,9 @@
#ifdef WINDOWS32
#include "windows.h"
#else
#ifdef ANDROID
#include "android_dns.h"
#endif
#include <arpa/nameser.h>
#ifdef DARWIN
#define BIND_8_COMPAT

View file

@ -1655,7 +1655,7 @@ tunnel(int tun_fd, int dns_fd, int bind_fd)
requests during heavy upstream traffic.
20msec: ~8 packs every 1/50sec = ~400 DNSreq/sec,
or ~1200bytes every 1/50sec = ~0.5 Mbit/sec upstream */
for (userid = 0; userid < USERS; userid++) {
for (userid = 0; userid < created_users; userid++) {
if (users[userid].active && !users[userid].disabled &&
users[userid].last_pkt + 60 > time(NULL)) {
users[userid].q_sendrealsoon_new = 0;
@ -1707,7 +1707,7 @@ tunnel(int tun_fd, int dns_fd, int bind_fd)
}
/* Send realsoon's if tun or dns didn't already */
for (userid = 0; userid < USERS; userid++)
for (userid = 0; userid < created_users; userid++)
if (users[userid].active && !users[userid].disabled &&
users[userid].last_pkt + 60 > time(NULL) &&
users[userid].q_sendrealsoon.id != 0 &&

View file

@ -24,6 +24,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#ifndef IFCONFIGPATH
#define IFCONFIGPATH "/sbin/"
#endif
#ifdef WINDOWS32
#include <winsock2.h>
#include <winioctl.h>
@ -71,7 +75,11 @@ open_tun(const char *tun_device)
int i;
int tun_fd;
struct ifreq ifreq;
#ifdef ANDROID
char *tunnel = "/dev/tun";
#else
char *tunnel = "/dev/net/tun";
#endif
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
warn("open_tun: %s: %s", tunnel, strerror(errno));
@ -455,7 +463,7 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
}
#ifndef WINDOWS32
snprintf(cmdline, sizeof(cmdline),
"/sbin/ifconfig %s %s %s netmask %s",
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
if_name,
ip,
#ifdef FREEBSD
@ -522,7 +530,7 @@ tun_setmtu(const unsigned mtu)
if (mtu > 200 && mtu <= 1500) {
snprintf(cmdline, sizeof(cmdline),
"/sbin/ifconfig %s mtu %u",
IFCONFIGPATH "ifconfig %s mtu %u",
if_name,
mtu);

View file

@ -33,7 +33,8 @@
#include "encoding.h"
#include "user.h"
struct user users[USERS];
struct user *users;
unsigned usercount;
int
init_users(in_addr_t my_ip, int netbits)
@ -41,7 +42,6 @@ init_users(in_addr_t my_ip, int netbits)
int i;
int skip = 0;
char newip[16];
int created_users = 0;
int maxusers;
@ -57,9 +57,10 @@ init_users(in_addr_t my_ip, int netbits)
ipstart.s_addr = my_ip & net.s_addr;
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
usercount = MIN(maxusers, USERS);
memset(users, 0, USERS * sizeof(struct user));
for (i = 0; i < USERS; i++) {
users = calloc(usercount, sizeof(struct user));
for (i = 0; i < usercount; i++) {
in_addr_t ip;
users[i].id = i;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
@ -72,17 +73,12 @@ init_users(in_addr_t my_ip, int netbits)
}
users[i].tun_ip = ip;
net.s_addr = ip;
if (maxusers-- < 1) {
users[i].disabled = 1;
} else {
users[i].disabled = 0;
created_users++;
}
users[i].disabled = 0;
users[i].active = 0;
/* Rest is reset on login ('V' packet) */
}
return created_users;
return usercount;
}
const char*
@ -100,7 +96,7 @@ users_waiting_on_reply()
int i;
ret = 0;
for (i = 0; i < USERS; i++) {
for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
@ -118,7 +114,7 @@ find_user_by_ip(uint32_t ip)
int i;
ret = -1;
for (i = 0; i < USERS; i++) {
for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
ip == users[i].tun_ip) {
@ -143,7 +139,7 @@ all_users_waiting_to_send()
ret = 1;
now = time(NULL);
for (i = 0; i < USERS; i++) {
for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > now &&
((users[i].conn == CONN_RAW_UDP) ||
@ -167,7 +163,7 @@ find_available_user()
{
int ret = -1;
int i;
for (i = 0; i < USERS; i++) {
for (i = 0; i < usercount; i++) {
/* Not used at all or not used in one minute */
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
users[i].active = 1;
@ -184,7 +180,7 @@ find_available_user()
void
user_switch_codec(int userid, struct encoder *enc)
{
if (userid < 0 || userid >= USERS)
if (userid < 0 || userid >= usercount)
return;
users[userid].encoder = enc;
@ -193,7 +189,7 @@ user_switch_codec(int userid, struct encoder *enc)
void
user_set_conn_type(int userid, enum connection c)
{
if (userid < 0 || userid >= USERS)
if (userid < 0 || userid >= usercount)
return;
if (c < 0 || c >= CONN_MAX)

View file

@ -73,7 +73,7 @@ struct user {
#endif
};
extern struct user users[USERS];
extern struct user *users;
int init_users(in_addr_t, int);
const char* users_get_first_ip();

View file

@ -25,6 +25,16 @@ get_resolvconf_addr()
#ifndef WINDOWS32
char buf[80];
FILE *fp;
#ifdef ANDROID
fp = popen("getprop net.dns1", "r");
if (fp == NULL)
err(1, "getprop net.dns1 failed");
if (fgets(buf, sizeof(buf), fp) == NULL)
err(1, "read getprop net.dns1 failed");
if (sscanf(buf, "%15s", addr) == 1)
rv = addr;
pclose(fp);
#else
rv = NULL;
@ -41,6 +51,7 @@ get_resolvconf_addr()
}
fclose(fp);
#endif
#else /* !WINDOWS32 */
FIXED_INFO *fixed_info;
ULONG buflen;

View file

@ -32,10 +32,11 @@ START_TEST(test_init_users)
in_addr_t ip;
char givenip[16];
int i;
int count;
ip = inet_addr("127.0.0.1");
init_users(ip, 27);
for (i = 0; i < USERS; i++) {
count = init_users(ip, 27);
for (i = 0; i < count; i++) {
fail_unless(users[i].id == i);
fail_unless(users[i].q.id == 0);
fail_unless(users[i].inpacket.len == 0);