TCPonly now works (in a relatively clean way too).
authorGuus Sliepen <guus@tinc-vpn.org>
Fri, 25 May 2001 11:54:28 +0000 (11:54 +0000)
committerGuus Sliepen <guus@tinc-vpn.org>
Fri, 25 May 2001 11:54:28 +0000 (11:54 +0000)
src/connection.h
src/meta.c
src/net.c
src/net.h
src/protocol.c
src/route.c

index 5d2d3be..f46d35b 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: connection.h,v 1.1.2.8 2001/03/04 13:59:25 guus Exp $
+    $Id: connection.h,v 1.1.2.9 2001/05/25 11:54:28 guus Exp $
 */
 
 #ifndef __TINC_CONNECTION_H__
@@ -85,7 +85,7 @@ typedef struct connection_t {
 
   char *buffer;                    /* metadata input buffer */
   int buflen;                      /* bytes read into buffer */
-  int reqlen;                      /* length of first request in buffer */
+  int tcplen;                      /* length of incoming TCPpacket */
   int allow_request;               /* defined if there's only one request possible */
 
   time_t last_ping_time;           /* last time we saw some activity from the other end */  
index 87cb415..3fadb0d 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: meta.c,v 1.1.2.17 2001/05/25 08:36:11 guus Exp $
+    $Id: meta.c,v 1.1.2.18 2001/05/25 11:54:28 guus Exp $
 */
 
 #include "config.h"
 
 int send_meta(connection_t *cl, char *buffer, int length)
 {
-  char outbuf[MAXBUFSIZE];
   char *bufp;
   int outlen;
+  char outbuf[MAXBUFSIZE];
 cp
   if(debug_lvl >= DEBUG_META)
-    syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s): %s"), length,
-           cl->name, cl->hostname, buffer);
-
-  buffer[length-1]='\n';
+    syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
+           cl->name, cl->hostname);
 
   if(cl->status.encryptout)
     {
@@ -91,9 +89,9 @@ int receive_meta(connection_t *cl)
 {
   int x, l = sizeof(x);
   int oldlen, i;
-  int lenin = 0;
-  char inbuf[MAXBUFSIZE];
+  int lenin, reqlen;
   int decrypted = 0;
+  char inbuf[MAXBUFSIZE];
 cp
   if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
     {
@@ -108,6 +106,15 @@ cp
       return -1;
     }
 
+  /* Strategy:
+     - Read as much as possible from the TCP socket in one go.
+     - Decrypt it.
+     - Check if a full request is in the input buffer.
+       - If yes, process request and remove it from the buffer,
+         then check again.
+       - If not, keep stuff in buffer and exit.
+   */
+
   lenin = read(cl->meta_socket, cl->buffer + cl->buflen, MAXBUFSIZE - cl->buflen);
 
   if(lenin<=0)
@@ -133,6 +140,8 @@ cp
 
   while(lenin)
     {
+      /* Decrypt */
+
       if(cl->status.decryptin && !decrypted)
         {
           EVP_DecryptUpdate(cl->cipher_inctx, inbuf, &lenin, cl->buffer + oldlen, lenin);
@@ -140,31 +149,51 @@ cp
           decrypted = 1;
         }
 
-      cl->reqlen = 0;
+      /* Are we receiving a TCPpacket? */
+
+      if(cl->tcplen)
+        {
+          if(cl->tcplen <= cl->buflen)
+            {
+              receive_tcppacket(cl, cl->buffer, cl->tcplen);
+
+              cl->buflen -= cl->tcplen;
+              lenin -= cl->tcplen;
+              memmove(cl->buffer, cl->buffer + cl->tcplen, cl->buflen);
+              oldlen = 0;
+              cl->tcplen = 0;
+              continue;
+            }
+          else
+            {
+              break;
+            }
+        }
+
+      /* Otherwise we are waiting for a request */
+
+      reqlen = 0;
 
       for(i = oldlen; i < cl->buflen; i++)
         {
           if(cl->buffer[i] == '\n')
             {
-              cl->buffer[i] = 0;  /* replace end-of-line by end-of-string so we can use sscanf */
-              cl->reqlen = i + 1;
+              cl->buffer[i] = '\0';  /* replace end-of-line by end-of-string so we can use sscanf */
+              reqlen = i + 1;
               break;
             }
         }
 
-      if(cl->reqlen)
+      if(reqlen)
         {
-          if(debug_lvl >= DEBUG_META)
-            syslog(LOG_DEBUG, _("Got request from %s (%s): %s"),
-                  cl->name, cl->hostname, cl->buffer);
-
           if(receive_request(cl))
             return -1;
 
-          cl->buflen -= cl->reqlen;
-          lenin -= cl->reqlen;
-          memmove(cl->buffer, cl->buffer + cl->reqlen, cl->buflen);
+          cl->buflen -= reqlen;
+          lenin -= reqlen;
+          memmove(cl->buffer, cl->buffer + reqlen, cl->buflen);
           oldlen = 0;
+          continue;
         }
       else
         {
index 33416b3..4db639c 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: net.c,v 1.35.4.107 2001/05/25 10:08:11 guus Exp $
+    $Id: net.c,v 1.35.4.108 2001/05/25 11:54:28 guus Exp $
 */
 
 #include "config.h"
@@ -184,6 +184,17 @@ cp
 cp
 }
 
+void receive_tcppacket(connection_t *cl, char *buffer, int len)
+{
+  vpn_packet_t outpkt;
+cp
+  outpkt.len = len;
+  memcpy(outpkt.data, buffer, len);
+
+  receive_packet(cl, &outpkt);
+cp
+}
+
 void accept_packet(vpn_packet_t *packet)
 {
 cp
@@ -203,7 +214,7 @@ cp
       if(write(tap_fd, packet->data - 2, packet->len + 2) < 0)
         syslog(LOG_ERR, _("Can't write to ethertap device: %m"));
       else
-        total_tap_out += packet->len + 2;
+        total_tap_out += packet->len;
     }
 cp
 }
@@ -1290,7 +1301,7 @@ cp
       vp.len = lenin - 2;
     }
 
-  total_tap_in += lenin;
+  total_tap_in += vp.len;
 
   if(lenin < 32)
     {
index 6323b2a..ba17331 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: net.h,v 1.9.4.30 2001/05/07 19:08:46 guus Exp $
+    $Id: net.h,v 1.9.4.31 2001/05/25 11:54:28 guus Exp $
 */
 
 #ifndef __TINC_NET_H__
@@ -109,6 +109,7 @@ extern int str2opt(const char *);
 extern char *opt2str(int);
 extern void send_packet(connection_t *, vpn_packet_t *);
 extern void receive_packet(connection_t *, vpn_packet_t *);
+extern void receive_tcppacket(connection_t *, char *, int);
 extern void accept_packet(vpn_packet_t *);
 extern int setup_network_connections(void);
 extern void close_network_connections(void);
index 5230063..bf54c6a 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol.c,v 1.28.4.90 2001/05/25 08:36:11 guus Exp $
+    $Id: protocol.c,v 1.28.4.91 2001/05/25 11:54:28 guus Exp $
 */
 
 #include "config.h"
@@ -106,11 +106,15 @@ cp
       return -1;
     }
 
-  len++;
-
   if(debug_lvl >= DEBUG_PROTOCOL)
-    syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
+    {
+      if(debug_lvl >= DEBUG_META)
+        syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], cl->name, cl->hostname, buffer);
+      else
+        syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
+    }
 
+  buffer[len++] = '\n';
 cp
   return send_meta(cl, buffer, len);
 }
@@ -118,20 +122,31 @@ cp
 int receive_request(connection_t *cl)
 {
   int request;
-cp  
+cp
   if(sscanf(cl->buffer, "%d", &request) == 1)
     {
       if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
         {
-          syslog(LOG_ERR, _("Unknown request from %s (%s)"),
-                cl->name, cl->hostname);
+          if(debug_lvl >= DEBUG_META)
+            syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
+                  cl->name, cl->hostname, cl->buffer);
+          else
+            syslog(LOG_ERR, _("Unknown request from %s (%s)"),
+                   cl->name, cl->hostname);
+                   
           return -1;
         }
       else
         {
           if(debug_lvl >= DEBUG_PROTOCOL)
-            syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
-                  request_name[request], cl->name, cl->hostname);
+            {
+              if(debug_lvl >= DEBUG_META)
+                syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
+                      request_name[request], cl->name, cl->hostname, cl->buffer);
+              else
+                syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
+                      request_name[request], cl->name, cl->hostname);
+            }
        }
 
       if((cl->allow_request != ALL) && (cl->allow_request != request))
@@ -158,34 +173,8 @@ cp
   return 0;
 }
 
-/* Connection protocol:
-
-   Client               Server
-   send_id(u)
-                        send_challenge(R)
-   send_chal_reply(H)
-                        send_id(u)
-   send_challenge(R)
-                        send_chal_reply(H)
-   ---------------------------------------
-   send_metakey(R)
-                        send_metakey(R)
-   ---------------------------------------
-   send_ack(u)
-                        send_ack(u)
-   ---------------------------------------
-   Other requests(E)...
-
-   (u) Unencrypted,
-   (R) RSA,
-   (H) SHA1,
-   (E) Encrypted with symmetric cipher.
-
-   Part of the challenge is directly used to set the symmetric cipher
-   key and the initial vector.  Since a man-in-the-middle cannot
-   decrypt the RSA challenges, this means that he cannot get or forge
-   the key for the symmetric cipher.
-*/
+/* The authentication protocol is described in detail in doc/SECURITY2,
+   the rest will be described in doc/PROTOCOL. */
 
 int send_id(connection_t *cl)
 {
@@ -1287,53 +1276,29 @@ int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
 {
   int x;
 cp  
+  /* Evil hack. */
+
   x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
 
   if(x)
     return x;
-  
-  return send_meta(cl->nexthop, packet->data, packet->len);  
+cp
+  return send_meta(cl, packet->data, packet->len);
 }
 
 int tcppacket_h(connection_t *cl)
 {
-  vpn_packet_t packet;
-  char *p;
-  int todo, x;
+  short int len;
 cp  
-  if(sscanf(cl->buffer, "%*d %hd", &packet.len) != 1)
+  if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
     {
       syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
       return -1;
     }
 
-  /* Evil hack. */
-
-  p = packet.data;
-  todo = packet.len;
-
-  while(todo)
-    {
-      x = read(cl->meta_socket, p, todo);
-
-      if(x<=0)
-        {
-          if(x==0)
-            syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
-          else
-            if(errno==EINTR || errno==EAGAIN)  /* FIXME: select() or poll() or reimplement this evil hack */
-              continue;
-            else
-              syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
-
-          return -1;
-        }
-      
-      todo -= x;
-      p += x;
-    }
+  /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
 
-  receive_packet(cl, &packet);
+  cl->tcplen = len;
 cp
   return 0;
 }
index c93379b..3264d56 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: route.c,v 1.1.2.7 2001/03/04 13:59:32 guus Exp $
+    $Id: route.c,v 1.1.2.8 2001/05/25 11:54:28 guus Exp $
 */
 
 #include "config.h"
@@ -181,11 +181,12 @@ void route_incoming(connection_t *source, vpn_packet_t *packet)
 {
   switch(routing_mode)
     {
+      case RMODE_ROUTER:
+        memcpy(packet->data, mymac.net.mac.address.x, 6);
+        break;
       case RMODE_SWITCH:
         learn_mac(source, (mac_t *)(&packet->data[0]));
         break;
-      case RMODE_ROUTER:
-        memcpy(packet->data, mymac.net.mac.address.x, 6);
     }
   
   accept_packet(packet);