[Pkg-privacy-commits] [onioncat] 69/241: merged current tap-branch into trunk

Intrigeri intrigeri at moszumanska.debian.org
Wed Aug 26 16:16:29 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 00ebf6337b310ddd9382045bc1c7d53a1e239580
Author: eagle <eagle at 58e1ccc2-750e-0410-8d0d-f93ca75ab447>
Date:   Tue Oct 28 21:15:02 2008 +0000

    merged current tap-branch into trunk
    
    git-svn-id: https://www.cypherpunk.at/svn/onioncat/trunk@341 58e1ccc2-750e-0410-8d0d-f93ca75ab447
---
 src/Makefile.am     |   2 +-
 src/Makefile.in     |   5 +-
 src/ocat.c          |  16 ++-
 src/ocat.h          |  18 ++-
 src/ocateth.c       | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ocatipv4route.c |  14 ++-
 src/ocatpeer.c      |   3 +-
 src/ocatroute.c     |  51 +++++++-
 src/ocatsetup.c     |   4 +-
 src/ocattun.c       |  33 +++--
 10 files changed, 468 insertions(+), 23 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 68b27e8..b2b1726 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
 bin_PROGRAMS = ocat
-ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c
+ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c ocateth.c
 include_HEADERS = ocat.h strlcpy.c strlcat.c
 
diff --git a/src/Makefile.in b/src/Makefile.in
index e761638..f930659 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -48,7 +48,7 @@ PROGRAMS = $(bin_PROGRAMS)
 am_ocat_OBJECTS = ocat.$(OBJEXT) ocatlog.$(OBJEXT) ocatroute.$(OBJEXT) \
 	ocatthread.$(OBJEXT) ocattun.$(OBJEXT) ocatv6conv.$(OBJEXT) \
 	ocatcompat.$(OBJEXT) ocatpeer.$(OBJEXT) ocatsetup.$(OBJEXT) \
-	ocatipv4route.$(OBJEXT)
+	ocatipv4route.$(OBJEXT) ocateth.$(OBJEXT)
 ocat_OBJECTS = $(am_ocat_OBJECTS)
 ocat_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
@@ -152,7 +152,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c
+ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c ocateth.c
 include_HEADERS = ocat.h strlcpy.c strlcat.c
 all: all-am
 
@@ -222,6 +222,7 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatcompat.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocateth.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatipv4route.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatlog.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatpeer.Po at am__quote@
diff --git a/src/ocat.c b/src/ocat.c
index e658090..d29178b 100644
--- a/src/ocat.c
+++ b/src/ocat.c
@@ -200,12 +200,26 @@ int main(int argc, char *argv[])
       ctrl_handler((void*) c);
    }
 
+   memcpy(&setup.ocat_hwaddr[3], &setup.ocat_addr.s6_addr[13], 3);
+   if (setup.use_tap);
+   {
+      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)
+         log_msg(L_FATAL, "cannot create multicast pipe: %s", strerror(errno)), exit(1);
+      run_ocat_thread("icmpv6", icmpv6_handler, NULL);
+   }
+
 #ifndef WITHOUT_TUN
    // create TUN device
    setup.tunfd[0] = setup.tunfd[1] = tun_alloc(tunname, setup.ocat_addr);
 #endif
 
-   log_msg(L_NOTICE, "local IP is %s on %s", ip6addr, tunname);
+   log_msg(L_NOTICE, "IPv6 address %s", ip6addr);
+   log_msg(L_NOTICE, "TUN/TAP device %s", tunname);
+   if (setup.ipv4_enable)
+      log_msg(L_NOTICE, "IP address %s", inet_ntoa(setup.ocat_addr4));
+ 
    log_debug("tun frameheader v6 = 0x%08x, v4 = 0x%08x", ntohl(setup.fhd_key[IPV6_KEY]), ntohl(setup.fhd_key[IPV4_KEY]));
 
    // start socket receiver thread
diff --git a/src/ocat.h b/src/ocat.h
index fcf6888..b655132 100644
--- a/src/ocat.h
+++ b/src/ocat.h
@@ -37,6 +37,7 @@
 #elif HAVE_SYS_ENDIAN_H
 #include <sys/endian.h>
 #endif
+#include <net/ethernet.h>
 
 #ifndef ETHERTYPE_IPV6
 #define ETHERTYPE_IPV6 0x86dd
@@ -118,6 +119,10 @@
 #define E_RT_NOTORGW -6
 #define E_RT_GWSELF -7
 
+//! maximum number of MAC address entries in table
+#define MAX_MAC_ENTRY 128
+//! maximum age of MAC address in table
+#define MAX_MAC_AGE 120
 
 #define IPV4_KEY 0
 #define IPV6_KEY 1
@@ -158,6 +163,8 @@ struct OcatSetup
    char *config_file;
    int config_read;
    int use_tap;
+   int icmpv6fd[2];
+   uint8_t ocat_hwaddr[ETH_ALEN];
 };
 
 typedef struct PacketQueue
@@ -175,7 +182,7 @@ typedef struct SocksHdr
    char cmd;
    uint16_t port;
    struct in_addr addr;
-} __attribute__ ((packed)) SocksHdr_t;
+} __attribute__((packed)) SocksHdr_t;
 
 typedef struct OcatPeer
 {
@@ -223,6 +230,13 @@ typedef struct IPv4Route
    struct in6_addr gw;
 } IPv4Route_t;
 
+typedef struct MACTable
+{
+   struct in6_addr in6addr;
+   uint8_t hwaddr[ETH_ALEN];
+   time_t age;
+} MACTable_t;
+
 /*
 // next header value for ocat internal use (RFC3692)
 #define OCAT_NEXT_HEADER 254
@@ -350,6 +364,8 @@ struct in6_addr *ipv4_lookup_route(uint32_t);
 int parse_route(const char *);
 void print_routes(FILE *);
 
+/* ocateth.c */
+void *icmpv6_handler(void *);
 
 #endif
 
diff --git a/src/ocateth.c b/src/ocateth.c
new file mode 100644
index 0000000..f932aab
--- /dev/null
+++ b/src/ocateth.c
@@ -0,0 +1,345 @@
+/* Copyright 2008 Bernhard R. Fischer, Daniel Haslinger.
+ *
+ * This file is part of OnionCat.
+ *
+ * OnionCat 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, version 3 of the License.
+ *
+ * OnionCat 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 OnionCat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! ocateth.c
+ *  Contains Ethernet (for TAP) and ICMPv6 (for NDP) code.
+ *
+ *  @author Bernhard Fischer <rahra _at_ cypherpunk at>
+ *  @version 2008/10/10
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_LINUX_SOCKIOS_H
+#include <linux/sockios.h>
+#endif
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#include <net/ethernet.h>
+#include <netinet/icmp6.h>
+
+#include "ocat.h"
+
+
+static MACTable_t mac_tbl_[MAX_MAC_ENTRY];
+static int mac_cnt_ = 0;
+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)
+{
+   int i;
+
+   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--;
+      }
+
+   pthread_mutex_unlock(&mac_mutex_);
+}
+
+
+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 (IN6_ARE_ADDR_EQUAL(in6, &mac_tbl_[i].in6addr))
+      {
+         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;
+}
+
+
+int mac_get_ip(const uint8_t *hwaddr, struct in6_addr *in6)
+{
+   int i;
+
+   pthread_mutex_lock(&mac_mutex_);
+
+   for (i = 0; i < mac_cnt_; 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;
+      }
+
+   pthread_mutex_unlock(&mac_mutex_);
+
+   return i < mac_cnt_ ? i : -1;
+}
+
+
+int mac_add_entry(const uint8_t *hwaddr, const struct in6_addr *in6)
+{
+   int e = -1;
+
+   pthread_mutex_lock(&mac_mutex_);
+
+   if (mac_cnt_ < MAX_MAC_ENTRY)
+   {
+      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_;
+   }
+
+   pthread_mutex_unlock(&mac_mutex_);
+
+   return e;
+}
+
+
+struct ip6_psh
+{
+   struct in6_addr src;
+   struct in6_addr dst;
+   uint32_t len;
+   char _pad[3];
+   uint8_t nxt;
+} __attribute__((packed));
+
+
+#if 0
+/*! Swap to memory areas. Those may not overlap.*/
+int memswp(void *dst, void *src, int len)
+{
+   char tmp[FRAME_SIZE];
+
+   if (len > FRAME_SIZE)
+   {
+      log_debug("buffers too large to swap");
+      return -1;
+   }
+
+   memcpy(tmp, dst, len);
+   memcpy(dst, src, len);
+   memcpy(src, tmp, len);
+
+   return len;
+}
+#endif
+
+
+/*! Calculate 16 bit one's complement sum (RFC1071).
+ *  @param buf Pointer to buffer.
+ *  @param len Number of bytes in buffer.
+ */
+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++)
+      sum += *buf;
+
+   // add last byte if buffer has odd length
+   if (len)
+      sum += *((uint8_t*) buf);
+
+   // add carries
+   while (sum >> 16)
+      sum = (sum & 0xffff) + (sum >> 16);
+
+   // return complement
+   return ~sum;
+}
+
+
+void *icmpv6_handler(void *p)
+{
+   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;
+
+   memset(ckbuf, 0, sizeof(struct ip6_psh));
+
+//   if (pipe(setup.icmpv6fd) == -1)
+//      log_msg(L_FATAL, "cannot create pipe: %s", strerror(errno)), exit(1);
+
+   while ((rlen = read(setup.icmpv6fd[0], buf, FRAME_SIZE)) != -1)
+   {
+      log_debug("received %d bytes on icmp pipe", rlen);
+
+      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;
+      }
+
+      // 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;
+      }
+
+      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;
+      }
+
+      log_debug("ICMPv6 ND_NEIGHBOR_SOLICIT received");
+
+      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;
+      }
+
+      log_debug("checksum correct, generating response");
+      memcpy(eh->ether_dhost, eh->ether_shost, ETH_ALEN);
+      memcpy(eh->ether_shost, setup.ocat_hwaddr, ETH_ALEN);
+
+      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;
+
+      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;
+
+      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);
+
+      memcpy(ip6ph + 1, icmp6, ntohs(ip6->ip6_plen));
+
+      icmp6->icmp6_cksum = checksum((uint16_t*) ip6ph, ntohs(ip6->ip6_plen) + sizeof(struct ip6_psh));
+
+      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");
+   }
+
+   log_msg(L_FATAL, "error reading from pipe fd %d: %s", setup.icmpv6fd[0], strerror(errno));
+   exit(1);
+}
+
+
+#if 0
+#ifdef DEBUG
+static char hexbuf_[FRAME_SIZE];
+static char convbuf_[] = "0123456789ABCDEF";
+
+char *buf2hex(const char *buf, int len)
+{
+   char *b = hexbuf_;
+   for (; len; buf++, len--)
+   {
+      *b++ = convbuf_[((*buf) >> 4) & 0xf];
+      *b++ = convbuf_[(*buf) & 0xf];
+      *b++ = ' ';
+   }
+   *(b - 1) = '\0';
+   return hexbuf_;
+}
+
+#endif
+
+
+void *icmpv6_handler(void *p)
+{
+   char buf[FRAME_SIZE];
+   int s, offset = 2, rlen;
+   struct sockaddr_in6 in6;
+   socklen_t slen;
+
+   if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1)
+   {
+      log_msg(L_ERROR, "could not create ICMPv6 socket: %s", strerror(errno));
+      return NULL;
+   }
+
+   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 (;;)
+   {
+      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));
+   }
+}
+#endif
+
diff --git a/src/ocatipv4route.c b/src/ocatipv4route.c
index 77ba99f..775131c 100644
--- a/src/ocatipv4route.c
+++ b/src/ocatipv4route.c
@@ -61,13 +61,15 @@ int ipv4_add_route(IPv4Route_t *route, IPv4Route_t **root, uint32_t cur_nm)
 
    if (route->netmask == cur_nm /*(*root)->netmask*/)
    {
-      if (!memcmp(&(*root)->gw, &in6addr_any, sizeof(struct in6_addr)))
+      //if (!memcmp(&(*root)->gw, &in6addr_any, sizeof(struct in6_addr)))
+      if (IN6_ARE_ADDR_EQUAL(&(*root)->gw, &in6addr_any))
       {
          memcpy(&(*root)->gw, &route->gw, sizeof(struct in6_addr));
          return 0;
       }
 
-      if (!memcmp(&(*root)->gw, &route->gw, sizeof(struct in6_addr)))
+      //if (!memcmp(&(*root)->gw, &route->gw, sizeof(struct in6_addr)))
+      if (IN6_ARE_ADDR_EQUAL(&(*root)->gw, &route->gw))
          return 0;
 
       log_msg(L_ERROR, "route already exists");
@@ -103,7 +105,8 @@ IPv4Route_t *ipv4_lookup_route__(uint32_t ip, IPv4Route_t *route, uint32_t cur_n
    if (route->next[BRANCH(ip, cur_nm)])
       return ipv4_lookup_route__(ip, route->next[BRANCH(ip, cur_nm)], cur_nm);
 
-   if (memcmp(&route->gw, &in6addr_any, sizeof(struct in6_addr)))
+   //if (memcmp(&route->gw, &in6addr_any, sizeof(struct in6_addr)))
+   if (!IN6_ARE_ADDR_EQUAL(&route->gw, &in6addr_any))
       return route;
 
    return NULL;
@@ -141,7 +144,8 @@ void ipv4_print(IPv4Route_t *route, void *f)
    char addr[INET6_ADDRSTRLEN];
    struct in_addr iaddr;
 
-   if (!memcmp(&route->gw, &in6addr_any, sizeof(struct in6_addr)))
+   //if (!memcmp(&route->gw, &in6addr_any, sizeof(struct in6_addr)))
+   if (IN6_ARE_ADDR_EQUAL(&route->gw, &in6addr_any))
       return;
 
    iaddr.s_addr = htonl(route->dest);
@@ -194,7 +198,7 @@ int parse_route(const char *rs)
    if (!has_tor_prefix(&route.gw))
       return E_RT_NOTORGW;
 
-   if (!memcmp(&route.gw, &setup.ocat_addr, sizeof(setup.ocat_addr)))
+   if (IN6_ARE_ADDR_EQUAL(&route.gw, &setup.ocat_addr))
       return E_RT_GWSELF;
 
    route.netmask = ntohl(route.netmask);
diff --git a/src/ocatpeer.c b/src/ocatpeer.c
index 6644523..41e17d0 100644
--- a/src/ocatpeer.c
+++ b/src/ocatpeer.c
@@ -81,7 +81,8 @@ OcatPeer_t *search_peer(const struct in6_addr *addr)
    OcatPeer_t *peer;
 
    for (peer = peer_; peer; peer = peer->next)
-      if (!memcmp(addr, &peer->addr, sizeof(struct in6_addr)))
+      //if (!memcmp(addr, &peer->addr, sizeof(struct in6_addr)))
+      if (IN6_ARE_ADDR_EQUAL(addr, &peer->addr))
          return peer;
    return NULL;
 }
diff --git a/src/ocatroute.c b/src/ocatroute.c
index d616d5c..839c133 100644
--- a/src/ocatroute.c
+++ b/src/ocatroute.c
@@ -36,6 +36,7 @@
 #include <sys/time.h>
 #include <sys/select.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #ifdef HAVE_LINUX_SOCKIOS_H
@@ -48,6 +49,8 @@
 #include <netinet/ip.h>
 #endif
 
+#include <net/ethernet.h>
+
 #include "ocat.h"
 
 #ifdef HAVE_STRUCT_IPHDR
@@ -434,7 +437,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 (!memcmp(&peer->addr, &in6addr_any, sizeof(struct in6_addr)))
+            if (IN6_ARE_ADDR_EQUAL(&peer->addr, &in6addr_any))
             {
                if (*peer->tunhdr == setup.fhd_key[IPV6_KEY])
                   memcpy(&peer->addr, &((struct ip6_hdr*)peer->fragbuf)->ip6_src, sizeof(struct in6_addr));
@@ -764,7 +768,8 @@ void socks_queue(const struct in6_addr *addr, int perm)
 
    pthread_mutex_lock(&socks_queue_mutex_);
    for (squeue = socks_queue_; squeue; squeue = squeue->next)
-      if (!memcmp(&squeue->addr, addr, sizeof(struct in6_addr)))
+      //if (!memcmp(&squeue->addr, addr, sizeof(struct in6_addr)))
+      if (IN6_ARE_ADDR_EQUAL(&squeue->addr, addr))
          break;
    if (!squeue)
    {
@@ -850,12 +855,22 @@ void *socks_connector(void *p)
 }
 
 
+#define PACKET_LOG
+
 void packet_forwarder(void)
 {
    char buf[FRAME_SIZE];
    int rlen;
    struct in6_addr *dest;
    struct in_addr in;
+   struct ether_header *eh = (struct ether_header*) &buf[4];
+#ifdef PACKET_LOG
+   int pktlog;
+
+   log_debug("opening packetlog");
+   if ((pktlog = open("pkt_log", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1)
+      log_debug("could not open packet log: %s", strerror(errno));
+#endif
 
    for (;;)
    {
@@ -874,6 +889,38 @@ void packet_forwarder(void)
 
       log_debug("received on tunfd %d, framesize %d + 4", setup.tunfd[0], rlen - 4);
 
+#ifdef PACKET_LOG
+      if ((pktlog != -1) && (write(pktlog, buf, rlen) == -1))
+         log_debug("could write frame to packet log: %s", strerror(errno));
+#endif
+
+      // just to be on the safe side but this should never happen
+      if ((!setup.use_tap && (rlen < 4)) || (setup.use_tap && (rlen < 4 + sizeof(struct ether_header))))
+      {
+         log_msg(L_ERROR, "frame effektively too short (rlen = %d)", rlen);
+         continue;
+      }
+
+      // 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))
+         {
+            log_msg(L_ERROR, "destination MAC is not OCat, dropping frame");
+            continue;
+         }
+         memmove(eh, eh + 1, rlen - 4 - sizeof(struct ether_header));
+      }
+
       if (*((uint32_t*) buf) == setup.fhd_key[IPV6_KEY])
       {
          if (((rlen - 4) < IP6HLEN))
diff --git a/src/ocatsetup.c b/src/ocatsetup.c
index 0a50e5b..a735b85 100644
--- a/src/ocatsetup.c
+++ b/src/ocatsetup.c
@@ -37,6 +37,8 @@ struct OcatSetup setup = {
    4, OCAT_UNAME, {0}, {{{0}}}, 0, 0, 1, OCAT_DIR, TUN_DEV,
    0, TOR_PREFIX4, TOR_PREFIX4_MASK,
    NULL, 1,
-   0        // use_tap
+   0,         // use_tap
+   {-1, -1},  // icmpv6fd
+   {0x00, 0x00, 0x6c, 0x00, 0x00, 0x00}   // ocat_hwaddr (OnionCat MAC address)
 };
 
diff --git a/src/ocattun.c b/src/ocattun.c
index d9a5e35..43fe148 100644
--- a/src/ocattun.c
+++ b/src/ocattun.c
@@ -83,10 +83,13 @@ int tun_alloc(char *dev, struct in6_addr addr)
    if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0)
       perror("TUNSETIFF"), exit(1);
    strlcpy(dev, ifr.ifr_name, IFNAMSIZ);
-   sprintf(buf, "ifconfig %s add %s/%d up", dev, astr, TOR_PREFIX_LEN);
-   log_msg(L_NOTICE, "configuring tun IP: \"%s\"", buf);
-   if (system(buf) == -1)
-      log_msg(L_ERROR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   if (!setup.use_tap)
+   {
+      sprintf(buf, "ifconfig %s add %s/%d up", dev, astr, TOR_PREFIX_LEN);
+      log_msg(L_NOTICE, "configuring tun IP: \"%s\"", buf);
+      if (system(buf) == -1)
+         log_msg(L_ERROR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   }
 
    // according to drivers/net/tun.c only IFF_MULTICAST and IFF_PROMISC are supported.
 /*   ifr.ifr_flags = IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_NOARP;
@@ -115,15 +118,18 @@ int tun_alloc(char *dev, struct in6_addr addr)
 
 #endif
 
-   sprintf(buf, "ifconfig tun0 inet6 %s/%d up", astr, TOR_PREFIX_LEN);
-   log_debug("setting IP on tun: \"%s\"", buf);
-   if (system(buf) == -1)
-      log_msg(L_ERROR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   if (!setup.use_tap)
+   {
+      sprintf(buf, "ifconfig tun0 inet6 %s/%d up", astr, TOR_PREFIX_LEN);
+      log_debug("setting IP on tun: \"%s\"", buf);
+      if (system(buf) == -1)
+         log_msg(L_ERROR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   }
 
 #endif
 
    // setting up IPv4 address
-   if (setup.ipv4_enable)
+   if (setup.ipv4_enable && !setup.use_tap)
    {
       sprintf(buf, "ifconfig %s %s netmask %s", dev, astr4, inet_ntoa(netmask));
       log_msg(L_NOTICE, "configuring tun IP: \"%s\"", buf);
@@ -131,6 +137,15 @@ int tun_alloc(char *dev, struct in6_addr addr)
          log_msg(L_ERROR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
    }
 
+   // bring up tap device
+   if (setup.use_tap)
+   {
+       sprintf(buf, "ifconfig %s up", dev);
+      log_msg(L_NOTICE, "bringing up TAP device \"%s\"", buf);
+      if (system(buf) == -1)
+         log_msg(L_ERROR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   }
+
    return fd;
 }              
  

-- 
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