[Pkg-privacy-commits] [onioncat] 01/241: repository restructured
Intrigeri
intrigeri at moszumanska.debian.org
Wed Aug 26 16:16:12 UTC 2015
This is an automated email from the git hooks/post-receive script.
intrigeri pushed a commit to branch upstream-master
in repository onioncat.
commit 7f8fe4681070827c2a7449f1a397b2e1e0521898
Author: eagle <eagle at 58e1ccc2-750e-0410-8d0d-f93ca75ab447>
Date: Thu Feb 7 00:31:39 2008 +0000
repository restructured
git-svn-id: https://www.cypherpunk.at/svn/onioncat/trunk@113 58e1ccc2-750e-0410-8d0d-f93ca75ab447
---
Makefile | 14 ++
TODO | 8 +
glob_id.txt | 9 +
ocat.c | 189 +++++++++++++++
ocat.h | 122 ++++++++++
ocatlog.c | 46 ++++
ocatroute.c | 762 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ocattun.c | 88 +++++++
ocatv6conv.c | 102 ++++++++
9 files changed, 1340 insertions(+)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8a75530
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+CC = gcc
+#PREOPTS = -DWITHOUT_TUN
+CFLAGS = -pipe -g -Wall $(PREOPTS)
+#LDFLAGS = -lpthread -lrt
+LDFLAGS = -lpthread
+TARGET = ocat
+
+all: $(TARGET)
+
+ocat: ocatroute.o ocattun.o ocatv6conv.o ocatlog.o
+
+clean:
+ rm -f *.o $(TARGET)
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..0781415
--- /dev/null
+++ b/TODO
@@ -0,0 +1,8 @@
+//* IPv6 adresses are not checked for their validity
+* frame checking may be improved
+//* garbage collector for packet queue missing
+* garbage collector for session cleanup
+* improve getopt() -- currently many things are hardcoded
+//* packets received on sockets should be validated (Ethertype, ip)
+* licence
+
diff --git a/glob_id.txt b/glob_id.txt
new file mode 100644
index 0000000..9ff8749
--- /dev/null
+++ b/glob_id.txt
@@ -0,0 +1,9 @@
+Global ID generation as in RFC4193
+
+NTP timestamp: cb5020bf.78f29ad6
+EUI-64: 21b:24ff:fe73:cd0e
+=> key: cb5020bf78f29ad6021b24fffe73cd0e
+=> SHA1: bfb7f7153a68682657986bc6659e7b87d87eeb43
+=> global ID: 87d87eeb43
+=> IPv6: FD87:D87E:EB43::/40
+
diff --git a/ocat.c b/ocat.c
new file mode 100644
index 0000000..989be2b
--- /dev/null
+++ b/ocat.c
@@ -0,0 +1,189 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <arpa/inet.h>
+//#include <netinet/in.h>
+//#include <netinet/ip6.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <errno.h>
+#include <time.h>
+#include <pthread.h>
+
+#include "ocat.h"
+
+
+int tunfd_[2] = {0, 1};
+
+extern int debug_level_;
+
+
+/*
+void print_v6_hd(FILE *out, const struct ip6_hdr *ihd)
+{
+ char asip[32], adip[32];
+ char onion[32];
+
+ inet_ntop(AF_INET6, &ihd->ip6_src, asip, 32);
+ inet_ntop(AF_INET6, &ihd->ip6_dst, adip, 32);
+ fprintf(out, "playload: %d\nsrcip: %s\ndstip: %s\n", ntohs(ihd->ip6_ctlun.ip6_un1.ip6_un1_plen), asip, adip);
+ ipv6tonion(&ihd->ip6_dst, onion);
+ fprintf(out, "dst onion: %s\n", onion);
+ fprintf(out, "\n");
+}
+*/
+
+
+void usage(const char *s)
+{
+ fprintf(stderr, "usage: %s [OPTIONS] <onion_hostname>\n"
+ " -h display usage message\n"
+ " -d <n> set debug level to n, default = %d\n"
+ " -i <onion_hostname> convert onion hostname to IPv6 and exit\n"
+ " -l <port> set ocat listen port, default = %d\n"
+ " -o <ipv6_addr> convert IPv6 address to onion url and exit\n"
+ " -r run as root, i.e. do not change uid/gid\n"
+ " -s <port> set hidden service virtual port, default = %d\n"
+ " -t <port> set tor SOCKS port, default = %d\n"
+#ifndef WITHOUT_TUN
+ " -T <tun_device> path to tun character device\n"
+#endif
+ " -v validate packets from sockets, default = %d\n"
+ , s, debug_level_, ocat_listen_port_, ocat_dest_port_, tor_socks_port_, vrec_);
+}
+
+
+int main(int argc, char *argv[])
+{
+ char tunname[IFNAMSIZ] = "", onion[ONION_NAME_SIZE], *s, ip6addr[INET6_ADDRSTRLEN];
+ struct in6_addr addr;
+ int c, runasroot = 0;
+ uid_t uid = 504;
+ gid_t gid = 504;
+ int urlconv = 0;
+
+ if (argc < 2)
+ usage(argv[0]), exit(1);
+
+ while ((c = getopt(argc, argv, "d:hriol:t:T:s:")) != -1)
+ switch (c)
+ {
+ case 'd':
+ debug_level_ = atoi(optarg);
+ break;
+
+ case 'i':
+ urlconv = 1;
+ break;
+
+ case 'l':
+ ocat_listen_port_ = atoi(optarg);
+ break;
+
+ case 'o':
+ urlconv = 2;
+ break;
+
+ case 'r':
+ runasroot = 1;
+ break;
+
+ case 's':
+ ocat_dest_port_ = atoi(optarg);
+ break;
+
+ case 't':
+ tor_socks_port_ = atoi(optarg);
+ break;
+
+#ifndef WITHOUT_TUN
+ case 'T':
+ tun_dev_ = optarg;
+ break;
+#endif
+
+ case 'v':
+ vrec_ = 1;
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+
+ if (!argv[optind])
+ usage(argv[0]), exit(1);
+
+ if (urlconv == 2)
+ {
+ if (inet_pton(AF_INET6, argv[optind], &addr) <= 0)
+ log_msg(L_ERROR, "%s", strerror(errno)), exit(1);
+ if (!has_tor_prefix(&addr))
+ log_msg(L_ERROR, "address does not have TOR prefix"), exit(1);
+ ipv6tonion(&addr, onion);
+ printf("%s.onion\n", onion);
+ exit(0);
+ }
+
+ // convert parameter to IPv6 address
+ strncpy(onion, argv[optind], ONION_NAME_SIZE);
+ if ((s = strchr(onion, '.')))
+ *s = '\0';
+ if (strlen(onion) != 16)
+ log_msg(L_ERROR, "[main] parameter seems not to be valid onion hostname"), exit(1);
+ if (oniontipv6(onion, &addr) == -1)
+ log_msg(L_ERROR, "[main] parameter seems not to be valid onion hostname"), exit(1);
+
+ inet_ntop(AF_INET6, &addr, ip6addr, INET6_ADDRSTRLEN);
+
+ if (urlconv == 1)
+ {
+ printf("%s\n", ip6addr);
+ exit(0);
+ }
+
+ // init peer structure
+ init_peers();
+#ifndef WITHOUT_TUN
+ // create TUN device
+ tunfd_[0] = tunfd_[1] = tun_alloc(tunname, addr);
+#endif
+ log_msg(L_NOTICE, "[main] local IP is %s on %s", ip6addr, tunname);
+ // start socket receiver thread
+ init_socket_receiver();
+ // create listening socket and start socket acceptor
+ init_socket_acceptor();
+ // starting socket cleaner
+ init_socket_cleaner();
+
+/* // create socks connector thread
+ init_socks_connector();
+ // start packet dequeuer
+ init_packet_dequeuer();
+*/
+
+ if (!runasroot && !getuid())
+ {
+ log_msg(L_NOTICE, "[main] running as root, changing uid/gid to %d/%d", uid, gid);
+ if (setgid(gid))
+ log_msg(L_ERROR, "[main] could not change gid: \"%s\"", strerror(errno));
+ if (setuid(uid))
+ log_msg(L_ERROR, "[main] could not change uid: \"%d\"", strerror(errno));
+ }
+ log_msg(L_NOTICE, "[main] uid/gid = %d/%d", getuid(), getgid());
+
+ // create socks connector thread
+ init_socks_connector();
+ // start packet dequeuer
+ init_packet_dequeuer();
+
+ // start forwarding packets from tunnel
+ log_msg(L_NOTICE, "[main] starting packet forwarder");
+ packet_forwarder();
+
+ return 0;
+}
+
diff --git a/ocat.h b/ocat.h
new file mode 100644
index 0000000..ee4f9ea
--- /dev/null
+++ b/ocat.h
@@ -0,0 +1,122 @@
+#ifndef OCAT_H
+#define OCAT_H
+
+//#define _POSIX_C_SOURCE 199309L
+
+#include <time.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+
+//#define BUFLEN 64*1024
+
+#define IP6HLEN sizeof(struct ip6_hdr)
+// TOR prefix : FD87:D87E:EB43::/40
+#define TOR_PREFIX {0xfd,0x87,0xd8,0x7e,0xeb,0x43}
+#define TOR_PREFIX_LEN 48
+#define MAXPEERS 1024
+#define OCAT_LISTEN_PORT 8000
+#define OCAT_DEST_PORT 80
+#define TOR_SOCKS_PORT 9050
+
+
+#define FRAME_SIZE 1504
+#define ONION_NAME_SIZE 23
+
+#define DEQUEUER_WAKEUP 3
+//! maximum number a packet stays in queue
+#define MAX_QUEUE_DELAY 10
+
+#define MAX_IDLE_TIME 120
+#define CLEANER_WAKEUP 10
+
+#define L_INFO 0
+#define L_NOTICE 1
+#define L_ERROR 2
+#define L_FATAL 3
+#define L_DEBUG 4
+
+#define E_SOCKS_SOCK -1
+#define E_SOCKS_CONN -2
+#define E_SOCKS_REQ -3
+#define E_SOCKS_RQFAIL -4
+
+//#define PEER_CONNECT 0
+#define PEER_ACTIVE 1
+#define PEER_INCOMING 0
+#define PEER_OUTGOING 1
+
+typedef struct PacketQueue
+{
+ struct PacketQueue *next;
+ struct in6_addr addr;
+ int psize;
+ time_t time;
+ void *data;
+} PacketQueue_t;
+
+typedef struct SocksHdr
+{
+ char ver;
+ char cmd;
+ uint16_t port;
+ struct in_addr addr;
+} SocksHdr_t;
+
+typedef struct OnionPeer
+{
+ struct in6_addr addr; //<! remote address of peer
+ int tcpfd; //<! remote file descriptor
+ time_t time; //<! timestamp of latest packet
+ int state; //<! status of peer
+ int dir;
+} OnionPeer_t;
+
+extern uint16_t tor_socks_port_;
+extern uint16_t ocat_listen_port_;
+extern uint16_t ocat_dest_port_;
+extern int vrec_;
+extern int tunfd_[2];
+
+#ifndef WITHOUT_TUN
+#define TUN_DEV "/dev/net/tun"
+extern char *tun_dev_;
+#endif
+
+/* ocatlog.c */
+void log_msg(int, const char *, ...);
+
+/* ocatsv6.c -- this function is sourced out
+ * here because of conflicting headers. */
+void set_ipv6_addr(int, struct in6_addr, int);
+
+/* ocatv6conv.c */
+void ipv6tonion(const struct in6_addr *, char *);
+int oniontipv6(const char *, struct in6_addr *);
+int has_tor_prefix(const struct in6_addr *);
+
+/* ocattun.c */
+#ifndef WITHOUT_TUN
+int tun_alloc(char *, struct in6_addr);
+#endif
+
+/* ocatroute.c */
+OnionPeer_t *search_peer(const struct in6_addr *);
+OnionPeer_t *establish_peer(int fd, const struct in6_addr *);
+void init_peers(void);
+void init_socket_acceptor(void);
+void init_socket_receiver(void);
+void init_socks_connector(void);
+//void push_socks_connector(const struct in6_addr *);
+//int socks_connect(const char *);
+//void *socket_receiver(void *p);
+//void update_peer_time(const OnionPeer_t *);
+//const OnionPeer_t *forward_packet(const struct in6_addr *, const char *, int);
+//void queue_packet(const struct in6_addr *, const char *, int);
+void init_packet_dequeuer(void);
+void packet_forwarder(void);
+void init_socket_cleaner(void);
+
+
+#endif
+
diff --git a/ocatlog.c b/ocatlog.c
new file mode 100644
index 0000000..263bb5d
--- /dev/null
+++ b/ocatlog.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <time.h>
+#include <pthread.h>
+
+#include "ocat.h"
+
+
+int debug_level_ = 4;
+static pthread_mutex_t log_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+static const char *flty_[] = {"info", "notice", "error", "fatal", "debug"};
+
+
+void log_msg(int lf, const char *fmt, ...)
+{
+ unsigned tid;
+ struct tm *tm;
+ time_t t;
+ FILE *out = stderr;
+ char timestr[32] = "";
+ va_list ap;
+
+ if (debug_level_ < lf || lf < 0)
+ return;
+
+ t = time(NULL);
+ tm = localtime(&t);
+ if (tm)
+ strftime(timestr, 32, "%c", tm);
+ tid = (unsigned) pthread_self();
+
+ pthread_mutex_lock(&log_mutex_);
+ fprintf(out, "%s [%08x] %6s ", timestr, tid, flty_[lf]);
+
+ va_start(ap, fmt);
+ vfprintf(out, fmt, ap);
+ va_end(ap);
+
+ fprintf(out, "\n");
+ pthread_mutex_unlock(&log_mutex_);
+}
+
diff --git a/ocatroute.c b/ocatroute.c
new file mode 100644
index 0000000..77c4ddc
--- /dev/null
+++ b/ocatroute.c
@@ -0,0 +1,762 @@
+/*! ocatroute.c
+ * Contains functions for managing both kind of TCP peers.
+ * Those are active SOCKS4A and passive TCP-LISTEN.
+ *
+ * @author Bernhard Fischer <rahra _at_ cypherpunk at>
+ * @version 2008/02/03-01
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+
+#include "ocat.h"
+
+
+// file descriptor of tcp listener
+static int sockfd_;
+// file descriptors of socket_receiver pipe
+// used for internal communication
+static int lpfd_[2];
+// file descriptors of socks_connector pipe
+// used for internal communication
+static int cpfd_[2];
+// array of active peers
+static OnionPeer_t peer_[MAXPEERS];
+// mutex for locking array of peers
+pthread_mutex_t peer_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+// packet queue pointer
+static PacketQueue_t *queue_ = NULL;
+// mutex and condition variable for packet queue
+static pthread_mutex_t queue_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t queue_cond_ = PTHREAD_COND_INITIALIZER;
+
+uint16_t tor_socks_port_ = TOR_SOCKS_PORT;
+uint16_t ocat_listen_port_ = OCAT_LISTEN_PORT;
+uint16_t ocat_dest_port_ = OCAT_DEST_PORT;
+
+int vrec_ = 0;
+
+
+void init_peers(void)
+{
+ memset(peer_, 0, sizeof(OnionPeer_t) * MAXPEERS);
+}
+
+
+OnionPeer_t *search_peer(const struct in6_addr *addr)
+{
+ int i;
+
+ for (i = 0; i < MAXPEERS; i++)
+ if (!memcmp(addr, &peer_[i].addr, sizeof(struct in6_addr)))
+ break;
+ //return &peer_[i];
+
+ if (i >= MAXPEERS)
+ return NULL;
+
+ return &peer_[i];
+}
+
+
+OnionPeer_t *get_empty_peer(void)
+{
+ int i;
+
+ for (i = 0; i < MAXPEERS; i++)
+ if (!peer_[i].state)
+ return &peer_[i];
+
+ return NULL;
+}
+
+
+void delete_peer(OnionPeer_t *peer)
+{
+ memset(peer, 0, sizeof(OnionPeer_t));
+}
+
+
+const OnionPeer_t *forward_packet(const struct in6_addr *addr, const char *buf, int buflen)
+{
+ OnionPeer_t *peer;
+
+ pthread_mutex_lock(&peer_mutex_);
+ if ((peer = search_peer(addr)))
+ {
+ log_msg(L_DEBUG, "[forwarding_packet]");
+ write(peer->tcpfd, buf, buflen);
+ peer->time = time(NULL);
+ }
+ pthread_mutex_unlock(&peer_mutex_);
+
+ return peer;
+}
+
+
+void queue_packet(const struct in6_addr *addr, const char *buf, int buflen)
+{
+ PacketQueue_t *queue;
+
+ log_msg(L_DEBUG, "[queue_packet] copying packet to heap for queue");
+ if (!(queue = malloc(sizeof(PacketQueue_t) + buflen)))
+ {
+ log_msg(L_ERROR, "[queue_packet] %s for packet to queue", strerror(errno));
+ return;
+ }
+
+ memcpy(&queue->addr, addr, sizeof(struct in6_addr));
+ queue->psize = buflen;
+ queue->data = ((char*)queue) + sizeof(PacketQueue_t);
+ memcpy(queue->data, buf, buflen);
+ queue->time = time(NULL);
+
+ log_msg(L_DEBUG, "[queue_packet] queuing packet");
+ pthread_mutex_lock(&queue_mutex_);
+ queue->next = queue_;
+ queue_ = queue;
+ log_msg(L_DEBUG, "[queue_packet] waking up dequeuer");
+ pthread_cond_signal(&queue_cond_);
+ pthread_mutex_unlock(&queue_mutex_);
+}
+
+
+void *packet_dequeuer(void *p)
+{
+ PacketQueue_t **queue, *fqueue;
+ OnionPeer_t *peer;
+ struct timespec ts;
+ int rc, timed = 0;
+ time_t delay;
+
+ log_msg(L_NOTICE, "[packet_dequeuer] running");
+ for (;;)
+ {
+ pthread_mutex_lock(&queue_mutex_);
+ if (timed)
+ {
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += DEQUEUER_WAKEUP;
+ log_msg(L_DEBUG, "[packet_dequeuer] timed conditional wait...");
+ rc = pthread_cond_timedwait(&queue_cond_, &queue_mutex_, &ts);
+ }
+ else
+ {
+ log_msg(L_DEBUG, "[packet_dequeuer] conditional wait...");
+ rc = pthread_cond_wait(&queue_cond_, &queue_mutex_);
+ }
+
+ if (rc)
+ log_msg(L_FATAL, "[packet_dequeuer] woke up: \"%s\"", strerror(rc));
+
+ log_msg(L_DEBUG, "[packet_dequeuer] starting dequeuing");
+ for (queue = &queue_; *queue; /*queue = &(*queue)->next*/)
+ {
+ //FIXME: this could be more performant of locking is done outside of for(...)
+ pthread_mutex_lock(&peer_mutex_);
+ if ((peer = search_peer(&(*queue)->addr)))
+ {
+ write(peer->tcpfd, (*queue)->data, (*queue)->psize);
+ peer->time = time(NULL);
+ }
+ pthread_mutex_unlock(&peer_mutex_);
+
+ // delete packet from queue if it was sent or is too old
+ delay = time(NULL) - (*queue)->time;
+ if (peer || (delay > MAX_QUEUE_DELAY))
+ {
+ fqueue = *queue;
+ *queue = (*queue)->next;
+ free(fqueue);
+ log_msg(L_DEBUG, "[packet_dequeuer] packet dequeued, delay = %d", delay);
+ continue;
+ }
+ queue = &(*queue)->next;
+ }
+ timed = queue_ != NULL;
+ pthread_mutex_unlock(&queue_mutex_);
+ }
+}
+
+
+void init_packet_dequeuer(void)
+{
+ pthread_t thread;
+ int rc;
+
+ if ((rc = pthread_create(&thread, NULL, packet_dequeuer, NULL)))
+ log_msg(L_FATAL, "[init_packet_dequeuer] could not start socket_receiver thread: \"%s\"", strerror(rc));
+}
+
+
+const static char hdigit_[] = "0123456789abcdef";
+
+void hex_code_header(const char *frame, int len, char *buf)
+{
+ int i;
+
+ for (i = 0; i < len; i++, frame++)
+ {
+ *buf++ = hdigit_[(*frame >> 4) & 0x0f];
+ *buf++ = hdigit_[*frame & 0x0f];
+ *buf++ = ' ';
+ }
+ *--buf = '\0';
+}
+
+
+// do some packet validation
+int validate_frame(const char *frame, int len)
+{
+ char buf[INET6_ADDRSTRLEN];
+ struct ip6_hdr *ihd = (struct ip6_hdr*) (frame + 4);
+ char hexbuf[(IP6HLEN + 4) * 3 + 1];
+
+ hex_code_header(frame, len > IP6HLEN + 4 ? IP6HLEN + 4 : len, hexbuf);
+ log_msg(L_DEBUG, "[validate_frame] header \"%s\"", hexbuf);
+
+ if (len < IP6HLEN + 4)
+ {
+ log_msg(L_ERROR, "[validate_frame] frame too short: %d bytes", len);
+ return 0;
+ }
+ if (/*(buf[2] != (char)0x86) || (buf[3] != (char)0xdd)*/ *((uint16_t*) &frame[2]) != htons(0x86dd))
+ {
+ log_msg(L_ERROR, "[validate_frame] ethertype is not IPv6");
+ return 0;
+ }
+ if (!has_tor_prefix(&ihd->ip6_dst))
+ {
+ log_msg(L_ERROR, "[validate_frame] destination %s unreachable", inet_ntop(AF_INET6, &ihd->ip6_dst, buf, INET6_ADDRSTRLEN));
+ return 0;
+ }
+ if (!has_tor_prefix(&ihd->ip6_src))
+ {
+ log_msg(L_ERROR, "[validate_frame] source address invalid. Remote ocat could not reply");
+ return 0;
+ }
+ return ntohs(ihd->ip6_plen);
+}
+
+
+void cleanup_socket(int fd, OnionPeer_t *peer)
+{
+ log_msg(L_NOTICE, "[cleanup_socket] fd %d reached EOF, closing.", fd);
+ close(fd);
+ pthread_mutex_lock(&peer_mutex_);
+ delete_peer(peer);
+ pthread_mutex_unlock(&peer_mutex_);
+}
+
+
+void *socket_receiver(void *p)
+{
+ int i, fd, maxfd, len, state, plen, rlen;
+ char buf[FRAME_SIZE];
+ char addr[INET6_ADDRSTRLEN];
+ fd_set rset;
+// struct ip6_hdr *ihd;
+
+ log_msg(L_DEBUG, "[socket_receiver] running");
+ for (;;)
+ {
+ FD_ZERO(&rset);
+ FD_SET(lpfd_[0], &rset);
+ maxfd = lpfd_[0];
+
+ // create set for all available peers to read
+ pthread_mutex_lock(&peer_mutex_);
+ for (i = 0; i < MAXPEERS; i++)
+ {
+ // only select active peers
+ if (peer_[i].state != PEER_ACTIVE)
+ continue;
+ if ((fd = peer_[i].tcpfd) >= FD_SETSIZE)
+ log_msg(L_FATAL, "%d >= FD_SETIZE(%d)", fd, FD_SETSIZE), exit(1);
+ FD_SET(fd, &rset);
+ if (fd > maxfd)
+ maxfd = fd;
+ }
+ pthread_mutex_unlock(&peer_mutex_);
+
+ log_msg(L_DEBUG, "[socket_receiver] is selecting...");
+ if (select(maxfd + 1, &rset, NULL, NULL, NULL) == -1)
+ {
+ log_msg(L_FATAL, "[socket_receiver] select encountered error: \"%s\", restarting", strerror(errno));
+ continue;
+ }
+
+ // thread woke up because of internal pipe read => restart selection
+ if (FD_ISSET(lpfd_[0], &rset))
+ {
+ read(lpfd_[0], buf, FRAME_SIZE);
+ continue;
+ }
+
+ //FIXME: should only run until num select returned
+ for (i = 0; i < MAXPEERS; i++)
+ {
+ pthread_mutex_lock(&peer_mutex_);
+ state = peer_[i].state;
+ fd = peer_[i].tcpfd;
+ pthread_mutex_unlock(&peer_mutex_);
+
+ if (state != PEER_ACTIVE)
+ continue;
+
+ if (FD_ISSET(fd, &rset))
+ {
+ log_msg(L_DEBUG, "[socket_receiver] reading from %d", fd);
+
+/* // *** framed receiver
+ // FIXME: needs packet defragmentation
+ if ((len = read(fd, buf, IP6HLEN + 4)) == -1)
+ {
+ log_msg(L_DEBUG, "[socket_receiver] spurious wakup of %d: \"%s\"", fd, strerror(errno));
+ continue;
+ }
+ // handle EOF
+ if (!len)
+ {
+ cleanup_socket(fd, &peer_[i]);
+ continue;
+ }
+ // validate header
+ if (!(plen = validate_frame(buf, len)))
+ {
+ log_msg(L_ERROR, "[socket_receiver] dropping frame");
+ continue;
+ }
+ // read payload
+ if ((rlen = read(fd, &buf[IP6HLEN + 4], plen)) == -1)
+ {
+ log_msg(L_ERROR, "[socket_receiver] error reading packet payload, dropping frame");
+ continue;
+ }
+
+ // forward payload
+ log_msg(L_DEBUG, "[socket_receiver] sending to tun %d framesize %d", tunfd_, len + rlen);
+ write(tunfd_, buf, len + rlen);
+
+ // cleanup on short read => maybe EOF
+ if (rlen < plen)
+ {
+ log_msg(L_DEBUG, "[socket_receiver] short read on %d, %d < %d", fd, rlen, plen);
+ cleanup_socket(fd, &peer_[i]);
+ continue;
+ }
+*/
+
+/* // *** unframed receiver
+ // this works, but has a problem if more then one frame is readable at the time
+ // and vrec_ is set (packet validation)
+ if ((len = read(fd, buf, FRAME_SIZE)) > 0)
+ {
+ plen = validate_frame(buf, len);
+ if (vrec_ && !plen)
+ {
+ log_msg(L_ERROR, "[socket_receiver] dropping frame");
+ continue;
+ }
+ log_msg(L_DEBUG, "[socket_receiver] sending to tun %d framesize %d", tunfd_, len);
+ write(tunfd_, buf, len);
+ }
+
+ // if len == 0 EOF reached => close session
+ if (!len)
+ {
+ log_msg(L_NOTICE, "[socket_receiver] fd %d reached EOF, closing.", fd);
+ close(fd);
+ pthread_mutex_lock(&peer_mutex_);
+ delete_peer(&peer_[i]);
+ pthread_mutex_unlock(&peer_mutex_);
+ continue;
+ }
+ // this might happen on linux, see SELECT(2)
+ else if (len == -1)
+ {
+ log_msg(L_DEBUG, "[socket_receiver] spurious wakup of %d: \"%s\"", fd, strerror(errno));
+ continue;
+ }
+
+ pthread_mutex_lock(&peer_mutex_);
+ // update timestamp
+ peer_[i].time = time(NULL);
+ // set IP address if it has non yet
+ if (plen && !memcmp(&peer_[i].addr, &in6addr_any, sizeof(struct in6_addr)))
+ {
+ memcpy(&peer_[i].addr, &((struct ip6_hdr*) (buf + 4))->ip6_src, sizeof(struct in6_addr));
+ log_msg(L_NOTICE, "[socket_receiver] incoming connection on %d from %s now identified", fd,
+ inet_ntop(AF_INET6, &peer_[i].addr, buf, FRAME_SIZE));
+ }
+ pthread_mutex_unlock(&peer_mutex_);
+*/
+ // *** unframed receiver
+ // write reordered after IP validation
+ // this might happen on linux, see SELECT(2)
+ if ((len = read(fd, buf, FRAME_SIZE)) == -1)
+ {
+ log_msg(L_DEBUG, "[socket_receiver] spurious wakup of %d: \"%s\"", fd, strerror(errno));
+ continue;
+ }
+ // if len == 0 EOF reached => close session
+ if (!len)
+ {
+ log_msg(L_NOTICE, "[socket_receiver] fd %d reached EOF, closing.", fd);
+ close(fd);
+ pthread_mutex_lock(&peer_mutex_);
+ delete_peer(&peer_[i]);
+ pthread_mutex_unlock(&peer_mutex_);
+ continue;
+ }
+ // check frame
+ plen = validate_frame(buf, len);
+ if (vrec_ && !plen)
+ {
+ log_msg(L_ERROR, "[socket_receiver] dropping frame");
+ continue;
+ }
+
+ pthread_mutex_lock(&peer_mutex_);
+ // update timestamp
+ peer_[i].time = time(NULL);
+ // set IP address if it is not set yet and frame is valid
+ if (plen && !memcmp(&peer_[i].addr, &in6addr_any, sizeof(struct in6_addr)))
+ {
+ memcpy(&peer_[i].addr, &((struct ip6_hdr*) (buf + 4))->ip6_src, sizeof(struct in6_addr));
+ log_msg(L_NOTICE, "[socket_receiver] incoming connection on %d from %s is now identified", fd,
+ inet_ntop(AF_INET6, &peer_[i].addr, addr, INET6_ADDRSTRLEN));
+ }
+ pthread_mutex_unlock(&peer_mutex_);
+ log_msg(L_DEBUG, "[socket_receiver] writing to tun %d framesize %d", tunfd_[1], len);
+ write(tunfd_[1], buf, len);
+ }
+ }
+ }
+}
+
+
+void init_socket_receiver(void)
+{
+ pthread_t thread;
+ int rc;
+
+ if (pipe(lpfd_) < 0)
+ log_msg(L_FATAL, "[init_socket_receiver] could not create pipe for socket_receiver: \"%s\"", strerror(errno)), exit(1);
+
+ if ((rc = pthread_create(&thread, NULL, socket_receiver, NULL)))
+ log_msg(L_FATAL, "[init_socket_receiver] could not start socket_receiver thread: \"%s\"", strerror(rc));
+
+/* thread should never terminate
+ if (pthread_detach(thread))
+ log_msg(L_ERROR, "could not detach socket_receiver thread"); */
+}
+
+
+void set_nonblock(int fd)
+{
+ long flags;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ {
+ log_msg(L_ERROR, "[set_nonblock] could not get socket flags for %d: \"%s\"", fd, strerror(errno));
+ flags = 0;
+ }
+
+ log_msg(L_DEBUG, "[set_nonblock] O_NONBLOCK currently is %x", flags & O_NONBLOCK);
+
+ if ((fcntl(socket, F_SETFL, flags | O_NONBLOCK)) == -1)
+ log_msg(L_ERROR, "[set_nonblock] could not set O_NONBLOCK for %d: \"%s\"", fd, strerror(errno));
+}
+
+
+void insert_peer(int fd, const struct in6_addr *addr)
+{
+ OnionPeer_t *peer;
+
+ log_msg(L_DEBUG, "[inserting_peer] %d", fd);
+
+ set_nonblock(fd);
+
+ pthread_mutex_lock(&peer_mutex_);
+ peer = get_empty_peer();
+ peer->tcpfd = fd;
+ peer->state = PEER_ACTIVE;
+ peer->time = time(NULL);
+ if (addr)
+ {
+ memcpy(&peer->addr, addr, sizeof(struct in6_addr));
+ peer->dir = PEER_OUTGOING;
+ }
+ else
+ peer->dir = PEER_INCOMING;
+ pthread_mutex_unlock(&peer_mutex_);
+
+ // wake up socket_receiver
+ log_msg(L_DEBUG, "[inser_peer] waking up socket_receiver");
+ write(lpfd_[1], &fd, 1);
+}
+
+
+void *socket_acceptor(void *p)
+{
+// struct ReceiverInfo *fwinfo;
+// OnionPeer_t *peer;
+ int fd;
+
+ log_msg(L_NOTICE, "[socket_acceptor] running");
+ for (;;)
+ {
+ log_msg(L_DEBUG, "[socket acceptor] is accepting further connections");
+ if ((fd = accept(sockfd_, NULL, NULL)) < 0)
+ perror("onion_receiver:accept"), exit(1);
+
+ log_msg(L_NOTICE, "[socket acceptor] connection accepted on listener");
+ insert_peer(fd, NULL);
+ }
+
+ return NULL;
+}
+
+
+void init_socket_acceptor(void)
+{
+ struct sockaddr_in in = {AF_INET, htons(ocat_listen_port_), {htonl(INADDR_LOOPBACK)}};
+ pthread_t thread;
+ int rc;
+
+ if ((sockfd_ = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+ log_msg(L_FATAL, "[init_socket_acceptor] could not create listener socker: \"%s\"", strerror(errno)), exit(1);
+
+ if (bind(sockfd_, (struct sockaddr*) &in, sizeof(struct sockaddr_in)) < 0)
+ log_msg(L_FATAL, "[init_socket_acceptor] could not bind listener: \"%s\"", strerror(errno)), exit(1);
+
+ if (listen(sockfd_, 32) < 0)
+ log_msg(L_FATAL, "[init_socket_acceptor] could not bring listener to listening state: \"%s\"", strerror(errno)), exit(1);
+
+ log_msg(L_NOTICE, "[init_socket_acceptor] created local listener on port %d", ocat_listen_port_);
+
+ if ((rc = pthread_create(&thread, NULL, socket_acceptor, NULL)))
+ log_msg(L_FATAL, "[init_socket_acceptor] could not create socket_acceptor: \"%s\"", strerror(rc)), exit(1);
+}
+
+
+//int socks_connect(const char *onion)
+int socks_connect(const struct in6_addr *addr)
+{
+ struct sockaddr_in in = {AF_INET, htons(tor_socks_port_), {htonl(INADDR_LOOPBACK)}};
+ int fd;
+ char buf[FRAME_SIZE], onion[ONION_NAME_SIZE];
+ SocksHdr_t *shdr = (SocksHdr_t*) buf;
+
+ log_msg(L_DEBUG, "[socks_connect] called");
+
+ ipv6tonion(addr, onion);
+ strcat(onion, ".onion");
+
+ log_msg(L_NOTICE, "[socks_connect] trying to connecto to \"%s\" [%s]", onion, inet_ntop(AF_INET6, addr, buf, FRAME_SIZE));
+
+ if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+ return E_SOCKS_SOCK;
+
+ if (connect(fd, (struct sockaddr*) &in, sizeof(in)) < 0)
+ {
+ log_msg(L_ERROR, "[socks_connect] connect() failed");
+ close(fd);
+ return E_SOCKS_CONN;
+ }
+
+ log_msg(L_DEBUG, "[socks_connect] connect()");
+
+ shdr->ver = 4;
+ shdr->cmd = 1;
+ shdr->port = htons(ocat_dest_port_);
+ shdr->addr.s_addr = 0x01000000;
+ strcpy(buf + sizeof(SocksHdr_t), "tor6");
+ strcpy(buf + sizeof(SocksHdr_t) + 5, onion);
+
+ write(fd, shdr, sizeof(SocksHdr_t) + strlen(onion) + 6);
+ log_msg(L_DEBUG, "[socks_connect] connect request sent");
+
+ if (read(fd, shdr, sizeof(SocksHdr_t)) < sizeof(SocksHdr_t))
+ {
+ log_msg(L_ERROR, "[socks_connect] short read, closing.");
+ close(fd);
+ return E_SOCKS_REQ;
+ }
+ log_msg(L_DEBUG, "[socks_connect] socks response received");
+
+ if (shdr->ver || (shdr->cmd != 90))
+ {
+ log_msg(L_ERROR, "[socks_connect] request failed, reason = %d", shdr->cmd);
+ close(fd);
+ return E_SOCKS_RQFAIL;
+ }
+ log_msg(L_NOTICE, "[socks_connect] connection to %s successfully opened on fd %d", onion, fd);
+
+ insert_peer(fd, addr);
+
+ return fd;
+}
+
+
+void *socks_connector(void *p)
+{
+ OnionPeer_t *peer;
+ struct in6_addr addr;
+ int len;
+
+ log_msg(L_NOTICE, "[socks_connector] running");
+
+ for (;;)
+ {
+ log_msg(L_DEBUG, "[socks_connector] reading from connector pipe %d", cpfd_[0]);
+ if ((len = read(cpfd_[0], &addr, sizeof(addr))) == -1)
+ log_msg(L_FATAL, "[socks_connector] error reading from connector pipe %d: %s", cpfd_[0], strerror(errno)), exit(1);
+ if (len != sizeof(addr))
+ {
+ log_msg(L_ERROR, "[socks_connector] illegal read on connector pipe %d: %d bytes", cpfd_[0], len);
+ continue;
+ }
+
+ pthread_mutex_lock(&peer_mutex_);
+ peer = search_peer(&addr);
+ pthread_mutex_unlock(&peer_mutex_);
+
+ if (peer)
+ {
+ log_msg(L_NOTICE, "[socks_connector] peer already exists, ignoring");
+ continue;
+ }
+
+ socks_connect(&addr);
+ }
+}
+
+
+void init_socks_connector(void)
+{
+ pthread_t thread;
+ int rc;
+
+ if (pipe(cpfd_) < 0)
+ log_msg(L_FATAL, "[init_socks_connector] could not create pipe for socks_connector: \"%s\"", strerror(errno)), exit(1);
+
+ if ((rc = pthread_create(&thread, NULL, socks_connector, NULL)))
+ log_msg(L_FATAL, "[init_socks_connector] could not start socks_connector thread: \"%s\"", strerror(rc));
+}
+
+
+/*
+void push_socks_connector(const struct in6_addr *addr)
+{
+ log_msg(L_DEBUG, "[push_socks_connector] writing to socks connector pipe %d", cpfd_[1]);
+ write(cpfd_[1], addr, sizeof(*addr));
+}
+*/
+
+
+/*
+int receive_packet(int fd, char *buf)
+{
+ int rlen;
+
+ rlen = read(fd, buf, FRAME_SIZE);
+ log_msg(L_DEBUG, "read frame with framesize %d", rlen);
+
+ return rlen;
+}
+*/
+
+
+void packet_forwarder(void)
+{
+ char buf[FRAME_SIZE];
+ char addr[INET6_ADDRSTRLEN];
+ struct ip6_hdr *ihd = (struct ip6_hdr*) &buf[4];
+ int rlen;
+
+ for (;;)
+ {
+ //rlen = receive_packet(tunfd_, data);
+ rlen = read(tunfd_[0], buf, FRAME_SIZE);
+ log_msg(L_DEBUG, "[packet_forwarder] received on tunfd %d, framesize %d", tunfd_[0], rlen);
+
+ if (!validate_frame(buf, rlen))
+ {
+ log_msg(L_ERROR, "[packet_forwarder] dropping frame");
+ continue;
+ }
+ /*
+ // do some packet validation
+ if (*((uint16_t*) &buf[2]) != htons(0x86dd))
+ {
+ log_msg(L_ERROR, "ethertype is not IPv6, dropping packet");
+ continue;
+ }
+ if (!has_tor_prefix(&ihd->ip6_dst))
+ {
+ log_msg(L_ERROR, "destination %s unreachable, dropping packet", inet_ntop(AF_INET6, &ihd->ip6_dst, buf, FRAME_SIZE));
+ continue;
+ }
+ if (!has_tor_prefix(&ihd->ip6_src))
+ {
+ log_msg(L_ERROR, "source address invalid. Remote ocat could not reply, dropping packet");
+ continue;
+ }
+ */
+
+ if (!forward_packet(&ihd->ip6_dst, buf, rlen))
+ {
+ log_msg(L_NOTICE, "[packet_forwarder] establishing new socks peer");
+ //push_socks_connector(&ihd->ip6_dst);
+ log_msg(L_DEBUG, "[packet_forwarder] writing %s to socks connector pipe %d", inet_ntop(AF_INET6, &ihd->ip6_dst, addr, INET6_ADDRSTRLEN), cpfd_[1]);
+ write(cpfd_[1], &ihd->ip6_dst, sizeof(struct in6_addr));
+ log_msg(L_DEBUG, "[packet_forwarder] queuing packet");
+ queue_packet(&ihd->ip6_dst, buf, rlen);
+ }
+ }
+}
+
+
+void *socket_cleaner(void *p)
+{
+ int i;
+ log_msg(L_NOTICE, "[socket_cleaner] running");
+ for (;;)
+ {
+ sleep(CLEANER_WAKEUP);
+ log_msg(L_DEBUG, "[socket_cleaner] wakeup");
+ pthread_mutex_lock(&peer_mutex_);
+ for (i = 0; i < MAXPEERS; i++)
+ {
+ if (peer_[i].state && peer_[i].time + MAX_IDLE_TIME < time(NULL))
+ {
+ log_msg(L_NOTICE, "[socket_cleaner] peer %d timed out, closing.", peer_[i].tcpfd);
+ close(peer_[i].tcpfd);
+ delete_peer(&peer_[i]);
+ }
+ }
+ pthread_mutex_unlock(&peer_mutex_);
+ }
+}
+
+
+void init_socket_cleaner(void)
+{
+ pthread_t thread;
+ int rc;
+
+ if ((rc = pthread_create(&thread, NULL, socket_cleaner, NULL)))
+ log_msg(L_FATAL, "[init_socket_cleaner] could not start thread: \"%s\"", strerror(rc));
+}
+
diff --git a/ocattun.c b/ocattun.c
new file mode 100644
index 0000000..b3f2f6c
--- /dev/null
+++ b/ocattun.c
@@ -0,0 +1,88 @@
+/*! ocattun.c
+ * These functions create the TUN device.
+ *
+ * @author Bernhard Fischer <rahra _at_ cypherpunk at>
+ * @version 2008/02/03-01
+ */
+
+#ifndef WITHOUT_TUN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netinet/ip6.h>
+#include <net/if.h>
+#include <linux/if_tun.h>
+
+#include "ocat.h"
+
+/* FIXME: this is defined in linux/ipv6.h but including
+ * it conflicts with other headers. */
+struct in6_ifreq
+{
+ struct in6_addr ifr6_addr;
+ uint32_t ifr6_prefixlen;
+ int ifr6_ifindex;
+};
+
+char *tun_dev_ = TUN_DEV;
+
+
+int tun_alloc(char *dev, struct in6_addr addr)
+{
+ struct ifreq ifr;
+ struct in6_ifreq ifr6;
+// struct sockaddr_in6 addr;
+ int fd, sfd;
+
+ if( (fd = open(tun_dev_, O_RDWR)) < 0 )
+ perror("open tun"), exit(1);
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN /*| IFF_NO_PI*/;
+ if(*dev)
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+ if(ioctl(fd, TUNSETIFF, (void *) &ifr) < 0)
+ perror("TUNSETIFF"), exit(1);
+ strcpy(dev, ifr.ifr_name);
+
+ if ((sfd = socket(PF_INET6, SOCK_DGRAM, 0)) < 0)
+ perror("socket"), exit(1);
+
+ if (ioctl(sfd, SIOCGIFINDEX, &ifr ) < 0)
+ perror("SIOCGIFINDEX"), exit(1);
+
+ /*
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ if (inet_pton(AF_INET6, ipv6, &addr.sin6_addr) < 0)
+ perror("inet_pton"), exit(1);
+
+ ifr6.ifr6_addr = addr.sin6_addr;*/
+ ifr6.ifr6_addr = addr;
+ ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+ ifr6.ifr6_prefixlen = TOR_PREFIX_LEN;
+ if (ioctl(sfd, SIOCSIFADDR, &ifr6) < 0)
+ perror("SIOCIFADDR"), exit(1);
+
+ if (ioctl(sfd, SIOCGIFFLAGS, &ifr) < 0)
+ perror("SIOCGIFFLAGS"), exit(1);
+
+ ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+ if (ioctl(sfd, SIOCSIFFLAGS, &ifr) < 0)
+ perror("SIOCSIFFLAGS"), exit(1);
+
+ close(sfd);
+ return fd;
+}
+
+#endif
+
diff --git a/ocatv6conv.c b/ocatv6conv.c
new file mode 100644
index 0000000..24ab611
--- /dev/null
+++ b/ocatv6conv.c
@@ -0,0 +1,102 @@
+/*! ocatv6conv.c
+ * These functions convert IPv6 addresses to onion URLs
+ * and vice versa.
+ *
+ * @author Bernhard Fischer <rahra _at_ cypherpunkt at>
+ * @version 2008/02/03-01
+ */
+
+#include <ctype.h>
+#include <string.h>
+//#include <stdint.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include "ocat.h"
+
+//static const char BASE32[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','j','k','m','n','o','p','q','r','s','t','v','w','x','y','z'};
+static const char BASE32[] = "abcdefghijklmnopqrstuvwxyz234567";
+static const char tor_prefix_[] = TOR_PREFIX;
+
+
+int has_tor_prefix(const struct in6_addr *addr)
+{
+ return memcmp(addr, tor_prefix_, 6) == 0;
+/*
+ int i;
+
+ for (i = 0; i < 6; i++)
+ if (*(((char*) addr) + i) != tor_prefix_[i])
+ return 0;
+ return 1;*/
+}
+
+
+void set_tor_prefix(struct in6_addr *addr)
+{
+ memcpy(addr, tor_prefix_, 6);
+/*
+ int i;
+
+ for (i = 0; i < 6; i++)
+ *(((char*) addr) + i) = tor_prefix_[i];*/
+}
+
+
+void shl5(char *bin)
+{
+ int i;
+
+ for (i = 0; i < 15; i++)
+ {
+ bin[i] <<= 5;
+ bin[i] |= (bin[i + 1] >> 3) & 0x1f;
+ }
+ bin[i] <<= 5;
+}
+
+
+int oniontipv6(const char *onion, struct in6_addr *ip6)
+{
+ int i, j;
+
+ memset(ip6, 0, sizeof(struct in6_addr));
+
+ for (i = 0; i < 16; i++)
+ {
+ shl5((char*) ip6);
+ for (j = 0; j < 32; j++)
+ if (tolower(onion[i]) == BASE32[j])
+ break;
+ if (j == 32)
+ return -1;
+ *(((char*) ip6) + 15) |= j;
+ }
+ set_tor_prefix(ip6);
+ return 0;
+}
+
+
+void ipv6tonion(const struct in6_addr *ip6, char *onion)
+{
+ int i;
+ char bin[16];
+
+ memcpy(bin, (char*) ip6 + 6, 16);
+
+ for (i = 0; i < 16; i++, onion++)
+ {
+ *onion = BASE32[bin[0] >> 3 & 0x1f];
+ shl5(bin);
+ /*
+ for (j = 0; j < 15; j++)
+ {
+ bin[j] <<= 5;
+ bin[j] |= (bin[j + 1] >> 3) & 0x1f;
+ }
+ */
+ }
+ *onion = '\0';
+}
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/onioncat.git
More information about the Pkg-privacy-commits
mailing list