diff options
Diffstat (limited to 'jni/iodine/src/common.c')
-rw-r--r-- | jni/iodine/src/common.c | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/jni/iodine/src/common.c b/jni/iodine/src/common.c new file mode 100644 index 0000000..7a57a8a --- /dev/null +++ b/jni/iodine/src/common.c @@ -0,0 +1,381 @@ +/* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> + * Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <time.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> + +#ifdef WINDOWS32 +#include <winsock2.h> +#include <conio.h> +#else +#include <arpa/nameser.h> +#ifdef DARWIN +#define BIND_8_COMPAT +#include <arpa/nameser_compat.h> +#endif +#include <termios.h> +#include <err.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <syslog.h> +#endif + +#ifdef HAVE_SETCON +# include <selinux/selinux.h> +#endif + +#include "common.h" + +/* The raw header used when not using DNS protocol */ +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__) && !defined(__ANDROID__) +static int daemon(int nochdir, int noclose) +{ + int fd, i; + + switch (fork()) { + case 0: + break; + case -1: + return -1; + default: + _exit(0); + } + + if (!nochdir) { + chdir("/"); + } + + if (setsid() < 0) { + return -1; + } + + if (!noclose) { + if ((fd = open("/dev/null", O_RDWR)) >= 0) { + for (i = 0; i < 3; i++) { + dup2(fd, i); + } + if (fd > 2) { + close(fd); + } + } + } + return 0; +} +#endif + +#if defined(__BEOS__) && !defined(__HAIKU__) +int setgroups(int count, int *groups) +{ + /* errno = ENOSYS; */ + return -1; +} +#endif + + +void +check_superuser(void (*usage_fn)(void)) +{ +#ifndef WINDOWS32 + if (geteuid() != 0) { + warnx("Run as root and you'll be happy.\n"); + usage_fn(); + /* NOTREACHED */ + } +#endif +} + +int +open_dns(int localport, in_addr_t listen_ip) +{ + struct sockaddr_in addr; + int flag = 1; + int fd; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(localport); + /* listen_ip already in network byte order from inet_addr, or 0 */ + addr.sin_addr.s_addr = listen_ip; + + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + fprintf(stderr, "got fd %d\n", fd); + err(1, "socket"); + } + + flag = 1; +#ifdef SO_REUSEPORT + setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag)); +#endif + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag)); + +#ifndef WINDOWS32 + /* To get destination address from each UDP datagram, see iodined.c:read_dns() */ + setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag)); +#endif + +#ifdef IP_OPT_DONT_FRAG + /* Set dont-fragment ip header flag */ + flag = DONT_FRAG_VALUE; + setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag)); +#endif + + if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) + err(1, "bind"); + + fprintf(stderr, "Opened UDP socket\n"); + + return fd; +} + +void +close_dns(int fd) +{ + close(fd); +} + +void +do_chroot(char *newroot) +{ +#if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__)) + if (chroot(newroot) != 0 || chdir("/") != 0) + err(1, "%s", newroot); + + seteuid(geteuid()); + setuid(getuid()); +#else + warnx("chroot not available"); +#endif +} + +void +do_setcon(char *context) +{ +#ifdef HAVE_SETCON + if (-1 == setcon(context)) + err(1, "%s", context); +#else + warnx("No SELinux support built in"); +#endif +} + +void +do_pidfile(char *pidfile) +{ +#ifndef WINDOWS32 + FILE *file; + + if ((file = fopen(pidfile, "w")) == NULL) { + syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile); + err(1, "do_pidfile: Can not write pidfile to %s", pidfile); + } else { + fprintf(file, "%d\n", (int)getpid()); + fclose(file); + } +#else + fprintf(stderr, "Windows version does not support pid file\n"); +#endif +} + +void +do_detach() +{ +#ifndef WINDOWS32 + fprintf(stderr, "Detaching from terminal...\n"); + daemon(0, 0); + umask(0); + alarm(0); +#else + fprintf(stderr, "Windows version does not support detaching\n"); +#endif +} + +void +read_password(char *buf, size_t len) +{ + char pwd[80]; +#ifndef WINDOWS32 + struct termios old; + struct termios tp; + + tcgetattr(0, &tp); + old = tp; + + tp.c_lflag &= (~ECHO); + tcsetattr(0, TCSANOW, &tp); +#else + int i; +#endif + + fprintf(stderr, "Enter password: "); + fflush(stderr); +#ifndef WINDOWS32 + scanf("%79s", pwd); +#else + for (i = 0; i < sizeof(pwd); i++) { + pwd[i] = getch(); + if (pwd[i] == '\r' || pwd[i] == '\n') { + pwd[i] = 0; + break; + } else if (pwd[i] == '\b') { + i--; /* Remove the \b char */ + if (i >=0) i--; /* If not first char, remove one more */ + } + } +#endif + fprintf(stderr, "\n"); + +#ifndef WINDOWS32 + tcsetattr(0, TCSANOW, &old); +#endif + + strncpy(buf, pwd, len); + buf[len-1] = '\0'; +} + +int +check_topdomain(char *str) +{ + int i; + + if(str[0] == '.') /* special case */ + return 1; + + for( i = 0; i < strlen(str); i++) { + if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) + continue; + else + return 1; + } + return 0; +} + +#if defined(WINDOWS32) +int +inet_aton(const char *cp, struct in_addr *inp) +{ + inp->s_addr = inet_addr(cp); + return inp->s_addr != INADDR_ANY; +} + +void +warn(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + if (fmt) fprintf(stderr, fmt, list); + if (errno == 0) { + fprintf(stderr, ": WSA error %d\n", WSAGetLastError()); + } else { + fprintf(stderr, ": %s\n", strerror(errno)); + } + va_end(list); +} +#endif + +#ifdef __ANDROID__ + +void android_printf(const char *fmt, ...) +{ + static char buf[1024]; + va_list list; + va_start(list, fmt); + + snprintf(buf,1024,fmt,list); + + android_log_callback(buf); + + va_end(list); +} + + +void +warn(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + if (fmt) fprintf(stderr, fmt, list); + if (errno != 0) + fprintf(stderr, ": %s\n", strerror(errno)); + va_end(list); +} +#endif + +#if defined(WINDOWS32) || defined(__ANDROID__) +void +warnx(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + if (fmt) fprintf(stderr, fmt, list); + fprintf(stderr, "\n"); + va_end(list); +} + +void +err(int eval, const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + warn(fmt, list); + va_end(list); + exit(eval); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + warnx(fmt, list); + va_end(list); + exit(eval); +} +#endif + + +int recent_seqno(int ourseqno, int gotseqno) +/* Return 1 if we've seen gotseqno recently (current or up to 3 back). + Return 0 if gotseqno is new (or very old). +*/ +{ + int i; + for (i = 0; i < 4; i++, ourseqno--) { + if (ourseqno < 0) + ourseqno = 7; + if (gotseqno == ourseqno) + return 1; + } + return 0; +} |