[Pkg-privacy-commits] [onioncat] 71/241: TAP device and NDP should work sufficient for prototype tests controller interface has additional commands "version", "setup" and "macs"
Intrigeri
intrigeri at moszumanska.debian.org
Wed Aug 26 16:16:30 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 cff4e682ae039eb701a50e30ef73c08d1c2bab70
Author: eagle <eagle at 58e1ccc2-750e-0410-8d0d-f93ca75ab447>
Date: Thu Oct 30 10:37:23 2008 +0000
TAP device and NDP should work sufficient for prototype tests
controller interface has additional commands "version", "setup" and "macs"
git-svn-id: https://www.cypherpunk.at/svn/onioncat/trunk@343 58e1ccc2-750e-0410-8d0d-f93ca75ab447
---
src/ocat.c | 4 +-
src/ocat.h | 32 ++++-
src/ocateth.c | 353 ++++++++++++++++++++++++++++++++------------------------
src/ocatroute.c | 110 ++++++++++++++----
src/ocatsetup.c | 67 ++++++++++-
5 files changed, 382 insertions(+), 184 deletions(-)
diff --git a/src/ocat.c b/src/ocat.c
index d29178b..c9a5b9a 100644
--- a/src/ocat.c
+++ b/src/ocat.c
@@ -205,9 +205,9 @@ int main(int argc, char *argv[])
{
log_msg(L_NOTICE, "MAC address %02x:%02x:%02x:%02x:%02x:%02x",
setup.ocat_hwaddr[0], setup.ocat_hwaddr[1], setup.ocat_hwaddr[2], setup.ocat_hwaddr[3], setup.ocat_hwaddr[4], setup.ocat_hwaddr[5]);
- if (pipe(setup.icmpv6fd) == -1)
+ /*if (pipe(setup.icmpv6fd) == -1)
log_msg(L_FATAL, "cannot create multicast pipe: %s", strerror(errno)), exit(1);
- run_ocat_thread("icmpv6", icmpv6_handler, NULL);
+ run_ocat_thread("icmpv6", icmpv6_handler, NULL);*/
}
#ifndef WITHOUT_TUN
diff --git a/src/ocat.h b/src/ocat.h
index 410fa6f..de9f65e 100644
--- a/src/ocat.h
+++ b/src/ocat.h
@@ -79,8 +79,10 @@
//! Maximum idle time for a peer, after that time the peer is closed.
#define MAX_IDLE_TIME 120
+//! # of secs after a cleaner wakeup occurs
#define CLEANER_WAKEUP 10
-#define STAT_WAKEUP (120/CLEANER_WAKEUP)
+//! # of secs after stats output is generated
+#define STAT_WAKEUP (600/CLEANER_WAKEUP)
//! log flags. word is considered as 16 bit, lower byte for level, upper byte for additional flags.
#define L_LEVEL_MASK 0x00ff
@@ -152,8 +154,6 @@ struct OcatSetup
int create_clog;
//! flag to not change uid to unprivileged user
int runasroot;
- //int urlconv;
- //int test_only;
int controller;
char *ocat_dir;
char *tun_dev;
@@ -163,7 +163,6 @@ struct OcatSetup
char *config_file;
int config_read;
int use_tap;
- int icmpv6fd[2];
uint8_t ocat_hwaddr[ETH_ALEN];
};
@@ -230,9 +229,24 @@ typedef struct IPv4Route
struct in6_addr gw;
} IPv4Route_t;
+//! IPv6 pseudo header used for checksum calculation
+struct ip6_psh
+{
+ struct in6_addr src;
+ struct in6_addr dst;
+ uint32_t len;
+ char _pad[3];
+ uint8_t nxt;
+} __attribute__((packed));
+
typedef struct MACTable
{
- struct in6_addr in6addr;
+ uint16_t family;
+ union
+ {
+ struct in6_addr in6addr;
+ struct in_addr inaddr;
+ };
uint8_t hwaddr[ETH_ALEN];
time_t age;
} MACTable_t;
@@ -357,6 +371,7 @@ void delete_peer(OcatPeer_t *);
/* ocatsetup.c */
extern struct OcatSetup setup;
+void print_setup_struct(FILE *);
/* ocatipv4route.c */
struct in6_addr *ipv4_lookup_route(uint32_t);
@@ -364,7 +379,12 @@ int parse_route(const char *);
void print_routes(FILE *);
/* ocateth.c */
-void *icmpv6_handler(void *);
+int eth_check(char *, int);
+int mac_get_mac(const struct in6_addr *, uint8_t *);
+void print_mac_tbl(FILE *);
+void mac_cleanup(void);
+char *mac_hw2str(const uint8_t *, char *);
+
#endif
diff --git a/src/ocateth.c b/src/ocateth.c
index f932aab..b2e8cf0 100644
--- a/src/ocateth.c
+++ b/src/ocateth.c
@@ -62,61 +62,86 @@ static pthread_mutex_t mac_mutex_ = PTHREAD_MUTEX_INITIALIZER;
/*! Pseudo header for IPv6 checksum calculation.
* RFC2460 8.1, (RFC1885 2.3) RFC2463, RFC1071. */
-void mac_cleanup(void)
+/* IPv6 Ethernet Multicast: (MAC) 33:33:xx:xx:xx:xx, xx -> 4 lowest order bytes of IPv6 destination
+ * Solicited-Node address: (IPv6) FF02:0:0:0:0:1:ffxx:xxxx, -> xx -> 3 lowest order bytes of IPv6 destination (RFC4291)
+ * IPv4 Ethernet Multicast: 01:00:5e:0xx:xx:xx, */
+
+
+/*! Convert an ethernet hardware address to a string.
+ * @param hwaddr Pointer to hardware address. Must be of len ETH_ALEN (6).
+ * @param str Pointer to string. Must have at least 18 bytes!
+ */
+char *mac_hw2str(const uint8_t *hwaddr, char *str)
{
+ char *s = str;
int i;
+ for (i = 0; i < ETH_ALEN; i++, str += 3, hwaddr++)
+ sprintf(str, "%02x:", *hwaddr);
+ str--;
+ *str = '\0';
+
+ return s;
+}
+
+
+void print_mac_tbl(FILE *f)
+{
+ int i;
+ char buf[INET6_ADDRSTRLEN];
+
+ //fprintf(f, " # age MAC C address\n");
pthread_mutex_lock(&mac_mutex_);
for (i = 0; i < mac_cnt_; i++)
- if (mac_tbl_[i].age + MAX_MAC_AGE < time(NULL))
- {
- memmove(&mac_tbl_[i], &mac_tbl_[i + 1], sizeof(MACTable_t) * (MAX_MAC_ENTRY - i));
- mac_cnt_--;
- i--;
- }
+ {
+ mac_hw2str(mac_tbl_[i].hwaddr, buf);
+ fprintf(f, "%3d %3d %s ", i, (int) (time(NULL) - mac_tbl_[i].age), buf);
+ fprintf(f, "%s ", mac_tbl_[i].family == AF_INET6 ? "IN6" : "IN ");
+ inet_ntop(mac_tbl_[i].family, &mac_tbl_[i].in6addr, buf, INET6_ADDRSTRLEN);
+ fprintf(f, "%s\n", buf);
+ }
pthread_mutex_unlock(&mac_mutex_);
}
-int mac_get_mac(const struct in6_addr *in6, uint8_t *hwaddr)
+void mac_cleanup(void)
{
int i;
pthread_mutex_lock(&mac_mutex_);
for (i = 0; i < mac_cnt_; i++)
- if (IN6_ARE_ADDR_EQUAL(in6, &mac_tbl_[i].in6addr))
+ if (mac_tbl_[i].age + MAX_MAC_AGE < time(NULL))
{
- memcpy(hwaddr, &mac_tbl_[i].hwaddr, ETH_ALEN);
- mac_tbl_[i].age = time(NULL);
- break;
+ log_debug("mac table entry %d timed out", i);
+ memmove(&mac_tbl_[i], &mac_tbl_[i + 1], sizeof(MACTable_t) * (MAX_MAC_ENTRY - i));
+ mac_cnt_--;
+ i--;
}
pthread_mutex_unlock(&mac_mutex_);
-
- return i < mac_cnt_ ? i : -1;
}
-int mac_get_ip(const uint8_t *hwaddr, struct in6_addr *in6)
+int mac_get_mac(const struct in6_addr *in6, uint8_t *hwaddr)
{
int i;
pthread_mutex_lock(&mac_mutex_);
- for (i = 0; i < mac_cnt_; i++)
- if (!memcmp(hwaddr, &mac_tbl_[i].hwaddr, ETH_ALEN))
+ for (i = mac_cnt_ - 1; i >= 0; i--)
+ if (IN6_ARE_ADDR_EQUAL(in6, &mac_tbl_[i].in6addr))
{
- memcpy(in6, &mac_tbl_[i].in6addr, sizeof(struct in6_addr));
+ memcpy(hwaddr, &mac_tbl_[i].hwaddr, ETH_ALEN);
mac_tbl_[i].age = time(NULL);
break;
}
pthread_mutex_unlock(&mac_mutex_);
- return i < mac_cnt_ ? i : -1;
+ return i;
}
@@ -128,10 +153,12 @@ int mac_add_entry(const uint8_t *hwaddr, const struct in6_addr *in6)
if (mac_cnt_ < MAX_MAC_ENTRY)
{
+ log_debug("adding entry to MAC table %d", mac_cnt_);
memcpy(&mac_tbl_[mac_cnt_].hwaddr, hwaddr, ETH_ALEN);
memcpy(&mac_tbl_[mac_cnt_].in6addr, in6, sizeof(struct in6_addr));
mac_tbl_[mac_cnt_].age = time(NULL);
- e = ++mac_cnt_;
+ mac_tbl_[mac_cnt_].family = AF_INET6;
+ e = mac_cnt_++;
}
pthread_mutex_unlock(&mac_mutex_);
@@ -140,35 +167,24 @@ int mac_add_entry(const uint8_t *hwaddr, const struct in6_addr *in6)
}
-struct ip6_psh
+int mac_get_ip(const uint8_t *hwaddr, struct in6_addr *in6)
{
- struct in6_addr src;
- struct in6_addr dst;
- uint32_t len;
- char _pad[3];
- uint8_t nxt;
-} __attribute__((packed));
-
+ int i;
-#if 0
-/*! Swap to memory areas. Those may not overlap.*/
-int memswp(void *dst, void *src, int len)
-{
- char tmp[FRAME_SIZE];
+ pthread_mutex_lock(&mac_mutex_);
- if (len > FRAME_SIZE)
- {
- log_debug("buffers too large to swap");
- return -1;
- }
+ for (i = mac_cnt_ - 1; i >= 0; i--)
+ if (!memcmp(hwaddr, &mac_tbl_[i].hwaddr, ETH_ALEN))
+ {
+ memcpy(in6, &mac_tbl_[i].in6addr, sizeof(struct in6_addr));
+ mac_tbl_[i].age = time(NULL);
+ break;
+ }
- memcpy(tmp, dst, len);
- memcpy(dst, src, len);
- memcpy(src, tmp, len);
+ pthread_mutex_unlock(&mac_mutex_);
- return len;
+ return i;
}
-#endif
/*! Calculate 16 bit one's complement sum (RFC1071).
@@ -179,7 +195,6 @@ uint16_t checksum(const uint16_t *buf, int len)
{
uint32_t sum = 0;
-// len >>= 1;
// sum up all 16 bit words
// (Note that it's endiness independent)
for (; len > 1 ; len -= 2, buf++)
@@ -198,148 +213,184 @@ uint16_t checksum(const uint16_t *buf, int len)
}
-void *icmpv6_handler(void *p)
+void free_ckbuf(uint16_t *buf)
{
- char buf[FRAME_SIZE], ckbuf[FRAME_SIZE];
- struct ether_header *eh = (struct ether_header*) (buf + 4);
- struct ip6_hdr *ip6 = (struct ip6_hdr*) (eh + 1); // ip6 header starts behind ether_header
- struct icmp6_hdr *icmp6 = (struct icmp6_hdr*) (ip6 + 1); // imcp6 header starts behind ip6 header
- struct nd_neighbor_solicit *nds = (struct nd_neighbor_solicit*) icmp6;
- struct nd_neighbor_advert *nda = (struct nd_neighbor_advert*) icmp6;
- struct nd_opt_hdr *ohd = (struct nd_opt_hdr*) (nds + 1);
- struct ip6_psh *ip6ph = (struct ip6_psh*) ckbuf;
- int rlen;
+ free(buf);
+}
- memset(ckbuf, 0, sizeof(struct ip6_psh));
-// if (pipe(setup.icmpv6fd) == -1)
-// log_msg(L_FATAL, "cannot create pipe: %s", strerror(errno)), exit(1);
+uint16_t *malloc_ckbuf(const struct in6_addr *src, const struct in6_addr *dst, uint16_t plen, uint8_t proto, const void *payload)
+{
+ struct ip6_psh *psh;
- while ((rlen = read(setup.icmpv6fd[0], buf, FRAME_SIZE)) != -1)
+ if (!(psh = calloc(1, sizeof(struct ip6_psh) + plen)))
{
- log_debug("received %d bytes on icmp pipe", rlen);
+ log_msg(L_FATAL, "error creating checksum buffer: %s", strerror(errno));
+ //return NULL;
+ exit(1);
+ }
- if (rlen < 4 + sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))
- {
- log_debug("frame too short: %d < %d", rlen, 4 + sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr));
- continue;
- }
+ psh->src = *src;
+ psh->dst = *dst;
+ psh->len = htons(plen);
+ psh->nxt = proto;
+ memcpy(psh + 1, payload, plen);
- // just to be on the safe side check icmpv6_mcast and ethertype
-// if ((*((uint16_t*) &buf[4]) != 0x3333) || (*((uint16_t*) &buf[12]) != htons(ETHERTYPE_IPV6)))
- if (eh->ether_type != htons(ETHERTYPE_IPV6))
- {
- log_debug("protocol 0x%04x not implemented yet", htons(eh->ether_type));
- continue;
- }
+ return (uint16_t*) psh;
+}
- if (ip6->ip6_nxt != IPPROTO_ICMPV6)
- {
- log_debug("frame contains not ICMPV6, next header = %d", ip6->ip6_nxt);
- continue;
- }
- if (icmp6->icmp6_type != ND_NEIGHBOR_SOLICIT)
- {
- log_debug("icmpv6 type %d not implemented", icmp6->icmp6_type);
- continue;
- }
+/*
+int ndp_(const struct in6_addr *in6)
+{
+ char buf[FRAME_SIZE];
+ struct ether_header *eh = (struct ether_header*) (buf + 4);
+ struct ip6_hdr *ip6 = (struct ip6_hdr*) (eh + 1); // ip6 header starts behind ether_header
+ struct nd_neighbor_solicit *nds = (struct nd_neighbor_solicit*) ip6;
+ struct nd_opt_hdr *ohd = (struct nd_opt_hdr*) (nds + 1);
+ uint16_t *ckb, cksum;
- log_debug("ICMPv6 ND_NEIGHBOR_SOLICIT received");
+ return -1;
+}
+*/
- memcpy(&ip6ph->src, &ip6->ip6_src, sizeof(struct in6_addr));
- memcpy(&ip6ph->dst, &ip6->ip6_dst, sizeof(struct in6_addr));
- ip6ph->len = ip6->ip6_plen;
- ip6ph->nxt = IPPROTO_ICMPV6;
- memcpy(ip6ph + 1, icmp6, ntohs(ip6->ip6_plen));
- if (checksum((uint16_t*) ip6ph, ntohs(ip6->ip6_plen) + sizeof(struct ip6_psh)))
- {
- log_msg(L_ERROR, "icmpv6 checksum wrong");
- continue;
- }
+int ndp_solicit(char *buf, int rlen)
+{
+ struct ether_header *eh = (struct ether_header*) (buf + 4);
+ struct ip6_hdr *ip6 = (struct ip6_hdr*) (eh + 1); // ip6 header starts behind ether_header
+ struct icmp6_hdr *icmp6 = (struct icmp6_hdr*) (ip6 + 1); // imcp6 header starts behind ip6 header
+ struct nd_neighbor_solicit *nds = (struct nd_neighbor_solicit*) icmp6;
+ struct nd_neighbor_advert *nda = (struct nd_neighbor_advert*) icmp6;
+ struct nd_opt_hdr *ohd = (struct nd_opt_hdr*) (nds + 1);
+ uint16_t *ckb, cksum;
+ struct in6_addr in6;
+ int minlen = 4 + sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
- log_debug("checksum correct, generating response");
- memcpy(eh->ether_dhost, eh->ether_shost, ETH_ALEN);
- memcpy(eh->ether_shost, setup.ocat_hwaddr, ETH_ALEN);
+ char mb[100];
+// uint8_t md[4] = {0xff};
- memcpy(&ip6->ip6_dst, &ip6->ip6_src, sizeof(struct in6_addr));
- memcpy(&ip6->ip6_src, &nds->nd_ns_target, sizeof(struct in6_addr));
- icmp6->icmp6_type = ND_NEIGHBOR_ADVERT;
- icmp6->icmp6_code = 0;
- icmp6->icmp6_cksum = 0;
+ if (rlen < minlen)
+ {
+ log_debug("frame too short for ICMP6 %d < %d", rlen, minlen);
+ return -1;
+ }
- memcpy(&ip6ph->src, &ip6->ip6_src, sizeof(struct in6_addr));
- memcpy(&ip6ph->dst, &ip6->ip6_dst, sizeof(struct in6_addr));
- ip6ph->len = ip6->ip6_plen;
- ip6ph->nxt = IPPROTO_ICMPV6;
+ if (eh->ether_type != htons(ETHERTYPE_IPV6))
+ {
+ log_debug("protocol 0x%04x not implemented yet", htons(eh->ether_type));
+ return -1;
+ }
- nda->nd_na_flags_reserved = ND_NA_FLAG_SOLICITED;
- ohd->nd_opt_type = ND_OPT_TARGET_LINKADDR;
- memcpy(ohd + 1, setup.ocat_hwaddr, ETH_ALEN);
+ // check for right multicast destination on ethernet
+ if (eh->ether_dhost[2] != 0xff)
+ {
+ log_debug("ethernet multicast destination %s cannot be solicited node address", mac_hw2str(eh->ether_dhost, mb));
+ return -1;
+ }
- memcpy(ip6ph + 1, icmp6, ntohs(ip6->ip6_plen));
+ // check for right multicast destination in IPv6
+ if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || !IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
+ {
+ log_debug("IPv6 multicast destination not solicited node address");
+ return -1;
+ }
- icmp6->icmp6_cksum = checksum((uint16_t*) ip6ph, ntohs(ip6->ip6_plen) + sizeof(struct ip6_psh));
+ if (!has_tor_prefix(&ip6->ip6_src))
+ {
+ log_debug("source IPv6 is not TOR ipv6");
+ return -1;
+ }
- log_debug("writing %d bytes to tunfd %d", rlen, setup.tunfd[1]);
- if (write(setup.tunfd[1], buf, rlen) < rlen)
- log_msg(L_ERROR, "short write");
+ if (ip6->ip6_nxt != IPPROTO_ICMPV6)
+ {
+ log_debug("frame contains not ICMPV6, next header = %d", ip6->ip6_nxt);
+ return -1;
}
- log_msg(L_FATAL, "error reading from pipe fd %d: %s", setup.icmpv6fd[0], strerror(errno));
- exit(1);
-}
+ if (icmp6->icmp6_type != ND_NEIGHBOR_SOLICIT)
+ {
+ log_debug("icmpv6 type %d not implemented", icmp6->icmp6_type);
+ return -1;
+ }
+ log_debug("ICMPv6 ND_NEIGHBOR_SOLICIT received");
+ minlen = minlen - sizeof(struct icmp6_hdr) + sizeof(struct nd_neighbor_solicit);
+ if (rlen < minlen)
+ {
+ log_debug("frame too short for ND_NEIGHBOR_SOLICIT");
+ return -1;
+ }
-#if 0
-#ifdef DEBUG
-static char hexbuf_[FRAME_SIZE];
-static char convbuf_[] = "0123456789ABCDEF";
+ if (!has_tor_prefix(&nds->nd_ns_target))
+ {
+ log_debug("solicit target is not TOR IPv6");
+ return -1;
+ }
-char *buf2hex(const char *buf, int len)
-{
- char *b = hexbuf_;
- for (; len; buf++, len--)
+ ckb = malloc_ckbuf(&ip6->ip6_src, &ip6->ip6_dst, ntohs(ip6->ip6_plen), IPPROTO_ICMPV6, icmp6);
+ cksum = checksum(ckb, ntohs(ip6->ip6_plen) + sizeof(struct ip6_psh));
+ free_ckbuf(ckb);
+ if (cksum)
{
- *b++ = convbuf_[((*buf) >> 4) & 0xf];
- *b++ = convbuf_[(*buf) & 0xf];
- *b++ = ' ';
+ log_msg(L_ERROR, "icmpv6 checksum wrong");
+ return -1;
}
- *(b - 1) = '\0';
- return hexbuf_;
-}
-#endif
+
+ log_debug("generating response");
+ // set MAC addresses in ethernet header and add MAC to table
+ if (mac_get_ip(eh->ether_shost, &in6) == -1)
+ if (mac_add_entry(eh->ether_shost, &ip6->ip6_src) == -1)
+ {
+ log_msg(L_ERROR, "MAC table full");
+ return -1;
+ }
+ memcpy(eh->ether_dhost, eh->ether_shost, ETH_ALEN);
+ memcpy(eh->ether_shost, setup.ocat_hwaddr, ETH_ALEN);
+
+ // init ip6 header
+ memcpy(&ip6->ip6_dst, &ip6->ip6_src, sizeof(struct in6_addr));
+ memcpy(&ip6->ip6_src, &nds->nd_ns_target, sizeof(struct in6_addr));
+
+ // init nda icmp6 header
+ nda->nd_na_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
+ nda->nd_na_hdr.icmp6_code = 0;
+ nda->nd_na_hdr.icmp6_cksum = 0;
+ nda->nd_na_flags_reserved = ND_NA_FLAG_SOLICITED;
+ ohd->nd_opt_type = ND_OPT_TARGET_LINKADDR;
+ memcpy(ohd + 1, setup.ocat_hwaddr, ETH_ALEN);
+
+ ckb = malloc_ckbuf(&ip6->ip6_src, &ip6->ip6_dst, ntohs(ip6->ip6_plen), IPPROTO_ICMPV6, icmp6);
+ nda->nd_na_hdr.icmp6_cksum = checksum(ckb, ntohs(ip6->ip6_plen) + sizeof(struct ip6_psh));
+ free_ckbuf(ckb);
+
+ log_debug("writing %d bytes to tunfd %d", rlen, setup.tunfd[1]);
+ if (write(setup.tunfd[1], buf, rlen) < rlen)
+ log_msg(L_ERROR, "short write");
+
+ return 0;
+}
-void *icmpv6_handler(void *p)
+int eth_check(char *buf, int rlen)
{
- char buf[FRAME_SIZE];
- int s, offset = 2, rlen;
- struct sockaddr_in6 in6;
- socklen_t slen;
+ struct ether_header *eh = (struct ether_header*) (buf + 4);
- if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1)
+ if (!(eh->ether_dhost[0] & 1))
{
- log_msg(L_ERROR, "could not create ICMPv6 socket: %s", strerror(errno));
- return NULL;
+ log_debug("dest MAC is not multicast");
+ return -1;
}
- if (setsockopt(s, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) == -1)
- log_msg(L_ERROR, "could not set IPV6_CHECKSUM on raw socket: %s", strerror(errno));
-
- for (;;)
+ if (*((uint16_t*) &eh->ether_dhost) == 0x3333)
{
- slen = sizeof(in6);
- if ((rlen = recvfrom(s, buf, FRAME_SIZE, 0, (struct sockaddr*) &in6, &slen)) == -1)
- {
- log_msg(L_ERROR, "could not recvfrom(): %s", strerror(errno));
- continue;
- }
- log_debug("received %d bytes on raw socket %d", rlen, s);
- log_debug("%s", buf2hex(buf, rlen));
+ log_debug("dest MAC is IPv6 multicast");
+ return ndp_solicit(buf, rlen);
}
+
+ log_debug("unknown multicast MAC destination");
+ return -1;
}
-#endif
+
diff --git a/src/ocatroute.c b/src/ocatroute.c
index b4b1ddd..41ff14f 100644
--- a/src/ocatroute.c
+++ b/src/ocatroute.c
@@ -277,6 +277,7 @@ void *socket_receiver(void *p)
OcatPeer_t *peer;
struct in6_addr *in6;
int drop = 0;
+ struct ether_header *eh = (struct ether_header*) (buf + 4);
if (pipe(lpfd_) < 0)
log_msg(L_FATAL, "could not create pipe for socket_receiver: \"%s\"", strerror(errno)), exit(1);
@@ -437,7 +438,8 @@ void *socket_receiver(void *p)
// set IP address if it is not set yet and frame is valid
//if (!memcmp(&peer->addr, &in6addr_any, sizeof(struct in6_addr)))
- if (IN6_ARE_ADDR_EQUAL(&peer->addr, &in6addr_any))
+ //if (IN6_ARE_ADDR_EQUAL(&peer->addr, &in6addr_any))
+ if (IN6_IS_ADDR_UNSPECIFIED(&peer->addr))
{
if (*peer->tunhdr == setup.fhd_key[IPV6_KEY])
memcpy(&peer->addr, &((struct ip6_hdr*)peer->fragbuf)->ip6_src, sizeof(struct in6_addr));
@@ -464,9 +466,42 @@ void *socket_receiver(void *p)
if (!drop)
{
- log_debug("writing to tun %d framesize %d + 4", setup.tunfd[1], len);
- if (write(setup.tunfd[1], peer->tunhdr, len + 4) != (len + 4))
- log_msg(L_ERROR, "could not write %d bytes to tunnel %d", len + 4, setup.tunfd[1]);
+ // write directly on TUN device
+ if (!setup.use_tap)
+ {
+ log_debug("writing to tun %d framesize %d + 4", setup.tunfd[1], len);
+ if (write(setup.tunfd[1], peer->tunhdr, len + 4) != (len + 4))
+ log_msg(L_ERROR, "could not write %d bytes to tunnel %d", len + 4, setup.tunfd[1]);
+ }
+ // create ethernet header and handle MAC on TAP device
+ else if (*peer->tunhdr == setup.fhd_key[IPV6_KEY])
+ {
+ log_debug("creating ethernet header");
+
+ // FIXME: should differentiate between IPv6 and IP!!
+ if (mac_get_mac(&((struct ip6_hdr*)peer->fragbuf)->ip6_dst, eh->ether_dhost) == -1)
+ {
+ log_debug("dest MAC unknown, must resolve...not implemented");
+ }
+ else
+ {
+ *((uint32_t*) buf) = *peer->tunhdr;
+ memcpy(buf + 4 + sizeof(struct ether_header), peer->fragbuf, len);
+ memcpy(eh->ether_shost, setup.ocat_hwaddr, ETH_ALEN);
+
+ if (*peer->tunhdr == setup.fhd_key[IPV6_KEY])
+ eh->ether_type = htons(ETHERTYPE_IPV6);
+ else if (*peer->tunhdr == setup.fhd_key[IPV4_KEY])
+ eh->ether_type = htons(ETHERTYPE_IP);
+
+ if (write(setup.tunfd[1], buf, len + 4 + sizeof(struct ether_header)) != (len + 4 + sizeof(struct ether_header)))
+ log_msg(L_ERROR, "could not write %d bytes to tunnel %d", len + 4 + sizeof(struct ether_header), setup.tunfd[1]);
+ }
+ }
+ else
+ {
+ log_debug("protocol %x not implemented on TAP device", ntohs(*peer->tunhdr));
+ }
}
else
{
@@ -888,7 +923,7 @@ void packet_forwarder(void)
#ifdef PACKET_LOG
if ((pktlog != -1) && (write(pktlog, buf, rlen) == -1))
- log_debug("could write frame to packet log: %s", strerror(errno));
+ log_debug("could not write frame to packet log: %s", strerror(errno));
#endif
// just to be on the safe side but this should never happen
@@ -901,21 +936,17 @@ void packet_forwarder(void)
// in case of TAP device handle ethernet header
if (setup.use_tap)
{
- if (eh->ether_dhost[0] & 1)
- {
- log_debug("forwarding %d bytes eth multicast to icmp pipe", rlen);
- if (write(setup.icmpv6fd[1], buf, rlen) < rlen)
- log_msg(L_ERROR, "error writing to icmp pipe");
- continue;
- }
- // remove ethernet header from buffer
- // FIXME: it would be better to adjust pointers instead of moving data
- if (memcmp(eh->ether_dhost, setup.ocat_hwaddr, ETH_ALEN))
+ if (!memcmp(eh->ether_dhost, setup.ocat_hwaddr, ETH_ALEN))
+ // remove ethernet header from buffer
+ // FIXME: it would be better to adjust pointers instead of moving data
+ memmove(eh, eh + 1, rlen - 4 - sizeof(struct ether_header));
+ else
{
- log_msg(L_ERROR, "destination MAC is not OCat, dropping frame");
+ log_debug("forwarding %d bytes eth handler", rlen);
+ //ndp_solicit(buf, rlen);
+ eth_check(buf, rlen);
continue;
}
- memmove(eh, eh + 1, rlen - 4 - sizeof(struct ether_header));
}
if (*((uint32_t*) buf) == setup.fhd_key[IPV6_KEY])
@@ -987,6 +1018,10 @@ void *socket_cleaner(void *ptr)
sleep(CLEANER_WAKEUP);
log_debug("wakeup");
+ // cleanup MAC table
+ mac_cleanup();
+
+ // cleanup peers
lock_peers();
for (p = get_first_peer_ptr(); *p; p = &(*p)->next)
{
@@ -1149,24 +1184,24 @@ void *ctrl_handler(void *p)
}
unlock_peers();
}
- else if (!strncmp(buf, "threads", 7))
+ else if (!strcmp(buf, "threads"))
{
pthread_mutex_lock(&thread_mutex_);
for (th = octh_; th; th = th->next)
fprintf(ff, "%2d: %s\n", th->id, th->name);
pthread_mutex_unlock(&thread_mutex_);
}
- else if (!strncmp(buf, "terminate", 9))
+ else if (!strcmp(buf, "terminate"))
{
log_msg(L_NOTICE, "terminate request from control port");
//FIXME: fds should be closed properly
exit(0);
}
- else if (!strncmp(buf, "fds", 3))
+ else if (!strcmp(buf, "fds"))
{
fprintf(fo, "acceptor sockets: %d/%d\nconntroller sockets: %d/%d\n", sockfd_[0], sockfd_[1], ctrlfd_[0], ctrlfd_[1]);
}
- else if (!strncmp(buf, "route", 5))
+ else if (!strcmp(buf, "route"))
{
if (rlen > 6)
{
@@ -1190,7 +1225,6 @@ void *ctrl_handler(void *p)
else
print_routes(fo);
}
- //else if (!strncmp(buf, "connect", 7))
else if (!strcmp(buf, "connect"))
{
if ((s = strtok_r(NULL, " \t\r\n", &tokbuf)))
@@ -1210,9 +1244,37 @@ void *ctrl_handler(void *p)
else
fprintf(ff, "ERR missing args\n");
}
- else if (!strncmp(buf, "help", 4))
+ else if (!strcmp(buf, "macs"))
+ {
+ print_mac_tbl(ff);
+ }
+ else if (!strcmp(buf, "setup"))
+ {
+ print_setup_struct(ff);
+ }
+ else if (!strcmp(buf, "version"))
+ {
+ fprintf(ff, "%s (c) Bernhard R. Fischer -- compiled %s %s\n", PACKAGE_STRING, __DATE__, __TIME__);
+ }
+ else if (!strcmp(buf, "help") || !strcmp(buf, "?"))
{
- fprintf(fo, "commands:\nexit\nquit\nterminate\nclose <n>\nstatus\nthreads\nfds\nroute [<destination IP> <netmask> <IPv6 gateway>]\nconnect <.onion-URL> [\"perm\"]\n");
+ fprintf(fo,
+ "commands:\n"
+ "exit | quit exit from control interface\n"
+ "terminate terminate OnionCat\n"
+ "close <n> close file descriptor <n> of a peer\n"
+ "status list peer status\n"
+ "threads show active threads\n"
+ "fds show open file descriptors (w/o peers)\n"
+ "route [<dst IP> show routing table or add route\n"
+ " <netmask>\n"
+ " <IPv6 gw>]\n"
+ "connect <.onion-URL> connect to a hidden service. if \"perm\" is set,\n"
+ " [\"perm\"] connection will stay open forever\n"
+ "macs show MAC address table\n"
+ "setup show internal setup struct\n"
+ "version show version\n"
+ );
}
else
{
diff --git a/src/ocatsetup.c b/src/ocatsetup.c
index a735b85..65148b4 100644
--- a/src/ocatsetup.c
+++ b/src/ocatsetup.c
@@ -24,6 +24,8 @@
#include "config.h"
+#include <arpa/inet.h>
+
#include "ocat.h"
struct OcatSetup setup = {
@@ -38,7 +40,70 @@ struct OcatSetup setup = {
0, TOR_PREFIX4, TOR_PREFIX4_MASK,
NULL, 1,
0, // use_tap
- {-1, -1}, // icmpv6fd
+ //{-1, -1}, // icmpv6fd
{0x00, 0x00, 0x6c, 0x00, 0x00, 0x00} // ocat_hwaddr (OnionCat MAC address)
};
+
+#define _SB 100
+
+void print_setup_struct(FILE *f)
+{
+ char ip[_SB], nm[_SB], ip6[_SB], hw[_SB];
+
+ inet_ntop(AF_INET, &setup.ocat_addr4, ip, _SB);
+ inet_ntop(AF_INET, &setup.ocat_addr4_mask, nm, _SB);
+ inet_ntop(AF_INET6, &setup.ocat_addr, ip6, _SB);
+ mac_hw2str(setup.ocat_hwaddr, hw);
+
+ fprintf(f,
+ "fhd_key[] = [IPV4(%d) => 0x%04x, IPV6(%d) => 0x%04x]\n"
+ "fhd_key_len = %d\n"
+ "tor_socks_port = %d\n"
+ "ocat_listen_port = %d\n"
+ "ocat_dest_port = %d\n"
+ "ocat_ctrl_port = %d\n"
+ "tunfd[] = [(0) => %d, (1) => %d]\n"
+ "debug_level = %d\n"
+ "usrname = \"%s\"\n"
+ "onion_url = \"%s\"\n"
+ "ocat_addr = %s\n"
+ "create_clog = %d\n"
+ "runasroot = %d\n"
+ "controller = %d\n"
+ "ocat_dir = \"%s\"\n"
+ "tun_dev = \"%s\"\n"
+ "ipv4_enable = %d\n"
+ "ocat_addr4 = %s\n"
+ "ocat_addr4_mask = %s\n"
+ "config_file = \"%s\"\n"
+ "config_read = %d\n"
+ "use_tap = %d\n"
+ "ocat_hwaddr = %s\n",
+
+ IPV4_KEY, ntohl(setup.fhd_key[IPV4_KEY]), IPV6_KEY, ntohl(setup.fhd_key[IPV6_KEY]),
+ setup.fhd_key_len,
+ setup.tor_socks_port,
+ setup.ocat_listen_port,
+ setup.ocat_dest_port,
+ setup.ocat_ctrl_port,
+ setup.tunfd[0], setup.tunfd[1],
+ setup.debug_level,
+ setup.usrname,
+ setup.onion_url,
+ ip6,
+ setup.create_clog,
+ setup.runasroot,
+ setup.controller,
+ setup.ocat_dir,
+ setup.tun_dev,
+ setup.ipv4_enable,
+ ip,
+ nm,
+ setup.config_file,
+ setup.config_read,
+ setup.use_tap,
+ hw
+ );
+}
+
--
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