[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