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__
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 */
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)
{
{
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)
{
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)
while(lenin)
{
+ /* Decrypt */
+
if(cl->status.decryptin && !decrypted)
{
EVP_DecryptUpdate(cl->cipher_inctx, inbuf, &lenin, cl->buffer + oldlen, lenin);
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
{
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"
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
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
}
vp.len = lenin - 2;
}
- total_tap_in += lenin;
+ total_tap_in += vp.len;
if(lenin < 32)
{
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__
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);
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"
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);
}
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))
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)
{
{
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;
}
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"
{
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);