From 950fb8e916b0e248dcaa72c96859acd6046683aa Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 11 Oct 2000 10:35:17 +0000 Subject: [PATCH] Big and bad commit of my current tree... - Added seperate file for connection list handling - Updating everything to use connlist, meta and subnet files - Removed dependency on libgmp - Lots of other stuff... --- AUTHORS | 2 - Makefile.am | 2 +- configure.in | 4 +- src/Makefile.am | 8 +-- src/connlist.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++ src/connlist.h | 90 ++++++++++++++++++++++++ src/encr.h | 5 +- src/meta.c | 31 ++++---- src/meta.h | 10 +-- src/net.c | 153 +++++++++++++++------------------------- src/net.h | 74 +++++--------------- src/netutl.c | 122 +------------------------------- src/netutl.h | 9 +-- src/protocol.h | 3 +- src/subnet.c | 160 +++++++++++++++++++++++++++++++++++++++--- src/subnet.h | 52 +++++++++++--- 16 files changed, 577 insertions(+), 331 deletions(-) create mode 100644 src/connlist.c create mode 100644 src/connlist.h diff --git a/AUTHORS b/AUTHORS index aa39942e..532543f4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,5 +5,3 @@ Ivo Timmermans These files are from other sources: * lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from the syslog 1.3 sources. - * The files in cipher/blowfish/ are from the SSLeay package by - Eric Young. diff --git a/Makefile.am b/Makefile.am index 0a91b08c..19ae3014 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = m4 intl lib cipher src doc po redhat debian +SUBDIRS = m4 intl lib src doc po redhat debian ACLOCAL_AMFLAGS = diff --git a/configure.in b/configure.in index cd7172f7..c553e785 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -dnl $Id: configure.in,v 1.13.2.5 2000/09/11 11:40:46 zarq Exp $ +dnl $Id: configure.in,v 1.13.2.6 2000/10/11 10:35:15 guus Exp $ AC_INIT(src/tincd.c) AM_INIT_AUTOMAKE(tinc, 1.0pre3) @@ -103,6 +103,6 @@ AC_CHECK_FUNC(gethostbyname, [], [ AC_CHECK_LIB(nsl, gethostbyname) ]) -AC_OUTPUT([Makefile src/Makefile cipher/Makefile +AC_OUTPUT([Makefile src/Makefile doc/Makefile intl/Makefile lib/Makefile m4/Makefile po/Makefile.in redhat/Makefile debian/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am index a76194b1..9755bae8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,18 +1,18 @@ ## Produce this file with automake to get Makefile.in -# $Id: Makefile.am,v 1.4.4.1 2000/06/06 10:24:33 zarq Exp $ +# $Id: Makefile.am,v 1.4.4.2 2000/10/11 10:35:15 guus Exp $ sbin_PROGRAMS = tincd genauth genauth_SOURCES = genauth.c -tincd_SOURCES = conf.c encr.c net.c netutl.c protocol.c tincd.c +tincd_SOURCES = conf.c connlist.c meta.c net.c netutl.c protocol.c subnet.c tincd.c INCLUDES = -I$(top_builddir) -I$(top_srcdir)/cipher -I$(top_srcdir)/lib -I$(top_srcdir)/intl -noinst_HEADERS = conf.h encr.h net.h netutl.h protocol.h +noinst_HEADERS = conf.h connlist.h meta.h net.h netutl.h protocol.h subnet.h LIBS = @LIBS@ @INTLLIBS@ -tincd_LDADD = $(top_builddir)/cipher/libcipher.la \ +tincd_LDADD = \ $(top_builddir)/lib/libvpn.a genauth_LDADD = $(top_builddir)/lib/libvpn.a diff --git a/src/connlist.c b/src/connlist.c new file mode 100644 index 00000000..12a501f1 --- /dev/null +++ b/src/connlist.c @@ -0,0 +1,183 @@ +/* + connlist.c -- connection list management + Copyright (C) 2000 Guus Sliepen , + 2000 Ivo Timmermans + + This program 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; either version 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: connlist.c,v 1.1.2.1 2000/10/11 10:35:15 guus Exp $ +*/ + +#include "config.h" +#include + +#include "connlist.h" + +/* Root of the connection list */ + +conn_list_t *conn_list = NULL; +conn_list_t *myself = NULL; + +/* Creation and deletion of conn_list elements */ + +conn_list_t *new_conn_list(void) +{ + conn_list_t *p = xmalloc(sizeof(*p)); +cp + /* initialise all those stupid pointers at once */ + memset(p, '\0', sizeof(*p)); +cp + return p; +} + +void free_conn_list(conn_list_t *p) +{ +cp + if(p->sq) + destroy_queue(p->sq); + if(p->rq) + destroy_queue(p->rq); + if(p->name) + free(p->name); + if(p->hostname) + free(p->hostname); + free_key(p->public_key); + free_key(p->datakey); + free(p); +cp +} + +/* + remove all marked connections +*/ +void prune_conn_list(void) +{ + conn_list_t *p, *prev = NULL, *next = NULL; +cp + for(p = conn_list; p != NULL; ) + { + next = p->next; + + if(p->status.remove) + { + if(prev) + prev->next = next; + else + conn_list = next; + + free_conn_element(p); + } + else + prev = p; + + p = next; + } +cp +} + +/* + free all elements of conn_list +*/ +void destroy_conn_list(void) +{ + conn_list_t *p, *next; +cp + for(p = conn_list; p != NULL; ) + { + next = p->next; + free_conn_element(p); + p = next; + } + + conn_list = NULL; +cp +} + +/* Linked list management */ + +void conn_list_add(conn_list_t *cl) +{ +cp + cl->next = connlist; + cl->prev = NULL; + cl->next->prev = cl; + connlist = cl; +cp +} + +void conn_list_del(conn_list_t *cl) +{ +cp + if(cl->prev) + cl->prev->next = cl->next; + else + connlist = cl->next; + + cl->next->prev = cl->prev; + free_conn_list(cl); +cp +} + +/* Lookup functions */ + +conn_list_t *lookup_conn_list_mac(mac_t address) +{ + conn_list_t *p; +cp + for(p = conn_list; p != NULL; p = p->next) + if(lookup_subnet_mac(p, address)) + break; +cp + return p; +} + +conn_list_t *lookup_conn_list_ipv4(ipv4_t address) +{ + conn_list_t *p; +cp + for(p = conn_list; p != NULL; p = p->next) + if(lookup_subnet_ipv4(p, address)) + break; +cp + return p; +} + +conn_list_t *lookup_conn_list_ipv6(ipv6_t address) +{ + conn_list_t *p; +cp + for(p = conn_list; p != NULL; p = p->next) + if(lookup_subnet_ipv6(p, address)) + break; +cp + return p; +} + +/* Debugging */ + +void dump_conn_list(void) +{ + conn_list_t *p; +cp + syslog(LOG_DEBUG, _("Connection list:")); + + for(p = conn_list; p != NULL; p = p->next) + { + syslog(LOG_DEBUG, _("%s netmask %d.%d.%d.%d at %s port %hd flags %d sockets %d, %d status %04x"), + p->name, IP_ADDR_V(p->vpn_mask), p->hostname, p->port, p->flags, + p->socket, p->meta_socket, p->status); + } +cp +} diff --git a/src/connlist.h b/src/connlist.h new file mode 100644 index 00000000..7ded0bfa --- /dev/null +++ b/src/connlist.h @@ -0,0 +1,90 @@ +/* + connlist.h -- header for connlist.c + Copyright (C) 2000 Guus Sliepen , + 2000 Ivo Timmermans + + This program 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; either version 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: connlist.h,v 1.1.2.1 2000/10/11 10:35:15 guus Exp $ +*/ + +#ifndef __TINC_CONNLIST_H__ +#define __TINC_CONNLIST_H__ + +#include + +#include "net.h" +#include "subnet.h" + +typedef struct conn_list_t { + char *name; /* name of this connection */ + ip_t real_ip; /* his real (internet) ip */ + char *hostname; /* the hostname of its real ip */ + short unsigned int port; /* his portnumber */ + int protocol_version; /* used protocol */ + int options; /* options turned on for this connection */ + + int flags; /* his flags */ + int socket; /* our udp vpn socket */ + int meta_socket; /* our tcp meta socket */ + status_bits_t status; /* status info */ + packet_queue_t *sq; /* pending outgoing packets */ + packet_queue_t *rq; /* pending incoming packets (they have no + valid key to be decrypted with) */ + enc_key_t *public_key; /* the other party's public key */ + enc_key_t *datakey; /* encrypt data packets with this key */ + enc_key_t *rsakey; + + EVP_CIPHER_CTX *cipher_inctx; /* Context of encrypted meta data that will come from him to us */ + EVP_CIPHER_CTX *cipher_outctx; /* Context of encrypted meta data that will be sent from us to him */ + + EVP_CIPHER_CTX *cipher_pktctx; /* Context of encrypted vpn packets that will be sent to him */ + EVP_CIPHER *cipher_pkttype; /* Cipher type for encrypted vpn packets */ + char *cipher_pktkey; /* Cipher key */ + char *cipher_pktiv; /* Cipher input vector */ + + char *buffer; /* metadata input buffer */ + int buflen; /* bytes read into buffer */ + int reqlen; /* length of first request in buffer */ + 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 */ + int want_ping; /* 0 if there's no need to check for activity. Shouldn't this go into status? (GS) */ + + char *mychallenge; /* challenge we received from him */ + char *hischallenge; /* challenge we sent to him */ + + struct conn_list_t *nexthop; /* nearest meta-hop in this direction, will be changed to myuplink (GS) */ + struct conn_list_t *hisuplink; /* his nearest meta-hop in our direction */ + struct conn_list_t *myuplink; /* our nearest meta-hop in his direction */ + + struct subnet_t *subnets; /* Pointer to a list of subnets belonging to this connection */ + + struct conn_list_t *next; /* after all, it's a list of connections */ +} conn_list_t; + +extern conn_list_t *conn_list; +extern conn_list_t *myself; + +extern conn_list_t *new_conn_list(); +extern void free_conn_list(conn_list_t *); +extern void add_conn_list(conn_list_t *); +extern void del_conn_list(conn_list_t *); +extern conn_list_t *lookup_conn_list_mac(mac_t); +extern conn_list_t *lookup_conn_list_ipv4(ipv4_t); +extern conn_list_t *lookup_conn_list_ipv6(ipv6_t); +extern void dump_conn_list(void); + +#endif /* __TINC_CONNLIST_H__ */ diff --git a/src/encr.h b/src/encr.h index 77e9923c..3b3aead7 100644 --- a/src/encr.h +++ b/src/encr.h @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: encr.h,v 1.2.4.1 2000/06/25 15:22:16 guus Exp $ + $Id: encr.h,v 1.2.4.2 2000/10/11 10:35:15 guus Exp $ */ #ifndef __TINC_ENCR_H__ @@ -32,9 +32,6 @@ extern int my_key_expiry; extern int security_init(void); -extern void do_bf_encrypt(vpn_packet_t *, real_packet_t *); -extern void do_bf_decrypt(real_packet_t *, vpn_packet_t *); - extern int send_portnumbers(int); extern void set_shared_key(char *); extern int send_passphrase(conn_list_t *); diff --git a/src/meta.c b/src/meta.c index 21cbe964..85781b83 100644 --- a/src/meta.c +++ b/src/meta.c @@ -17,27 +17,34 @@ 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.1 2000/09/26 14:06:03 guus Exp $ + $Id: meta.c,v 1.1.2.2 2000/10/11 10:35:15 guus Exp $ */ #include "config.h" +#include -int send_meta(conn_list_t *cl, const char *buffer, int length) +#include +#include +#include +#include +#include + +#include "net.h" +#include "system.h" + +int send_meta(conn_list_t *cl, char *buffer, int length) { char outbuf[MAXBUFSIZE]; char *bufp; + int outlen; cp if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s): %s"), int length, + syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s): %s"), length, cl->name, cl->hostname, buffer); if(cl->status.encryptout) { - if(EVP_EncryptUpdate(cl->cipher_outctx, cl->buffer + cl->buflen, NULL, inbuf, length) != 1) - { - syslog(LOG_ERR, _("Error during encryption of outgoing metadata to %s (%s)"), cl->name, cl->hostname); - return -1; - } + EVP_EncryptUpdate(cl->cipher_outctx, outbuf, &outlen, buffer, length); bufp = outbuf; } else @@ -84,7 +91,7 @@ cp return -1; } - if(cl->status.encryptin) + if(cl->status.decryptin) bufp = inbuf; else bufp = cl->buffer + cl->buflen; @@ -109,11 +116,7 @@ cp if(cl->status.decryptin) { - if(EVP_DecryptUpdate(cl->cipher_inctx, cl->buffer + cl->buflen, NULL, inbuf, lenin) != 1) - { - syslog(LOG_ERR, _("Error during decryption of incoming metadata from %s (%s)"), cl->name, cl->hostname); - return -1; - } + EVP_DecryptUpdate(cl->cipher_inctx, cl->buffer + cl->buflen, NULL, inbuf, lenin); } oldlen = cl->buflen; diff --git a/src/meta.h b/src/meta.h index cd9c2985..2784947c 100644 --- a/src/meta.h +++ b/src/meta.h @@ -17,16 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: meta.h,v 1.1.2.2 2000/10/01 03:21:49 guus Exp $ + $Id: meta.h,v 1.1.2.3 2000/10/11 10:35:16 guus Exp $ */ #ifndef __TINC_META_H__ #define __TINC_META_H__ -#include net.h +#include "net.h" -extern int send_meta(conn_list_t *, const char *, int) -extern int broadcast_meta(conn_list_t *, const char *, int) -extern int receive_meta(conn_list_t *) +extern int send_meta(conn_list_t *, const char *, int); +extern int broadcast_meta(conn_list_t *, const char *, int); +extern int receive_meta(conn_list_t *); #endif /* __TINC_META_H__ */ diff --git a/src/net.c b/src/net.c index 94c0e445..2efd3408 100644 --- 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.32 2000/09/26 14:06:04 guus Exp $ + $Id: net.c,v 1.35.4.33 2000/10/11 10:35:16 guus Exp $ */ #include "config.h" @@ -37,7 +37,6 @@ #include #include -#include #include #include @@ -69,11 +68,8 @@ conn_list_t *myself = NULL; */ void strip_mac_addresses(vpn_packet_t *p) { - unsigned char tmp[MAXSIZE]; cp - memcpy(tmp, p->data, p->len); - p->len -= 12; - memcpy(p->data, &tmp[12], p->len); + memmove(p->data, p->data + 12, p->len -= 12); cp } @@ -82,39 +78,37 @@ cp */ void add_mac_addresses(vpn_packet_t *p) { - unsigned char tmp[MAXSIZE]; cp - memcpy(&tmp[12], p->data, p->len); + memcpy(p->data + 12, p->data, p->len); p->len += 12; - tmp[0] = tmp[6] = 0xfe; - tmp[1] = tmp[7] = 0xfd; - *((ip_t*)(&tmp[2])) = (ip_t)(htonl(myself->vpn_ip)); - *((ip_t*)(&tmp[8])) = *((ip_t*)(&tmp[26])); - memcpy(p->data, &tmp[0], p->len); + p->data[0] = p->data[6] = 0xfe; + p->data[1] = p->data[7] = 0xfd; + /* Really evil pointer stuff just below! */ + *((ip_t*)(&p->data[2])) = (ip_t)(htonl(myself->real_ip)); + *((ip_t*)(&p->data[8])) = *((ip_t*)(&p->data[26])); cp } -int xsend(conn_list_t *cl, void *packet) +int xsend(conn_list_t *cl, vpn_packet_t *inpkt) { - real_packet_t rp; + vpn_packet_t outpkt; + int outlen, outpad; cp - do_encrypt((vpn_packet_t*)packet, &rp, cl->datakey); - rp.from = htonl(myself->vpn_ip); - rp.data.len = htons(rp.data.len); - rp.len = htons(rp.len); - + outpkt.len = inpkt->len; + EVP_EncryptInit(cl->cipher_pktctx, cl->cipher_pkttype, cl->cipher_pktkey, cl->cipher_pktiv); + EVP_EncryptUpdate(cl->cipher_pktctx, outpkt.data, &outlen, inpkt->data, inpkt->len); + EVP_EncryptFinal(cl->cipher_pktctx, outpkt.data + outlen, &outpad); + outlen += outpad; + if(debug_lvl > 3) syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"), - ntohs(rp.len), cl->name, cl->hostname); + outlen, cl->name, cl->hostname); - total_socket_out += ntohs(rp.len); + total_socket_out += outlen; cl->want_ping = 1; - if((cl->flags | myself->flags) & TCPONLY) - return send_tcppacket(cl, (void*)&rp, ntohs(rp.len)); - - if((send(cl->socket, (char*)&rp, ntohs(rp.len), 0)) < 0) + if((send(cl->socket, (char *) &(outpkt.len), outlen + 2, 0)) < 0) { syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"), cl->name, cl->hostname); @@ -124,25 +118,28 @@ cp return 0; } -int xrecv(conn_list_t *cl, void *packet) +int xrecv(vpn_packet_t *inpkt) { - vpn_packet_t vp; - int lenin; + vpn_packet_t outpkt; + int outlen, outpad; cp - do_decrypt((real_packet_t*)packet, &vp, cl->datakey); - add_mac_addresses(&vp); - if(debug_lvl > 3) - syslog(LOG_ERR, _("Receiving packet of %d bytes from %s (%s)"), - ((real_packet_t*)packet)->len, cl->name, cl->hostname); + syslog(LOG_ERR, _("Receiving packet of %d bytes"), + inpkt->len); + + outpkt.len = inpkt->len; + EVP_DecryptInit(myself->cipher_pktctx, myself->cipher_pkttype, myself->cipher_pktkey, myself->cipher_pktiv); + EVP_DecryptUpdate(myself->cipher_pktctx, outpkt.data, &outlen, inpkt->data, inpkt->len); + /* FIXME: grok DecryptFinal + EVP_DecryptFinal(myself->cipher_pktctx, outpkt.data + outlen, &outpad); + */ + + add_mac_addresses(&outpkt); - if((lenin = write(tap_fd, &vp, vp.len + sizeof(vp.len))) < 0) + if(write(tap_fd, outpkt.data, outpkt.len) < 0) syslog(LOG_ERR, _("Can't write to tap device: %m")); else - total_tap_out += lenin; - - cl->want_ping = 0; - cl->last_ping_time = time(NULL); + total_tap_out += outpkt.len; cp return 0; } @@ -347,11 +344,11 @@ cp if(!cl->status.validkey) { if(debug_lvl > 3) - syslog(LOG_INFO, _("%s (%s) has no valid key, queueing packet"), + syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"), cl->name, cl->hostname); add_queue(&(cl->sq), packet, packet->len + 2); if(!cl->status.waitingforkey) - send_key_request(cl->vpn_ip); /* Keys should be sent to the host running the tincd */ + send_req_key(myself, cl); /* Keys should be sent to the host running the tincd */ return 0; } @@ -603,19 +600,14 @@ int setup_myself(void) cp myself = new_conn_list(); - if(!(cfg = get_config_val(myvpnip))) + myself->hostname = "MYSELF"; /* FIXME? */ + myself->flags = 0; + + if(!(cfg = get_config_val(tincname))) /* Not acceptable */ { - syslog(LOG_ERR, _("No value for my VPN IP given")); + syslog(LOG_ERR, _("Name for tinc daemon required!")); return -1; } - - myself->vpn_ip = cfg->data.ip->ip; - myself->hostname = hostlookup(htonl(myself->vpn_ip)); - myself->vpn_mask = cfg->data.ip->mask; - myself->flags = 0; - - if(!(cfg = get_config_val(tincname))) - asprintf(&(myself->name), IP_ADDR_S, IP_ADDR_V(myself->vpn_ip)); else myself->name = (char*)cfg->data.val; @@ -865,65 +857,32 @@ cp udp socket and write it to the ethertap device after being decrypted */ -int handle_incoming_vpn_data(conn_list_t *cl) +int handle_incoming_vpn_data() { - real_packet_t rp; + vpn_packet_t pkt; int lenin; int x, l = sizeof(x); - conn_list_t *f; cp - if(getsockopt(cl->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) + if(getsockopt(myself->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) { - syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), - __FILE__, __LINE__, cl->socket, - cl->name, cl->hostname); + syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m"), + __FILE__, __LINE__, myself->socket); return -1; } if(x) { - syslog(LOG_ERR, _("Incoming data socket error for %s (%s): %s"), - cl->name, cl->hostname, strerror(x)); + syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x)); return -1; } - rp.len = -1; - lenin = recvfrom(cl->socket, &rp, MTU, 0, NULL, NULL); - if(lenin <= 0) + if(recvfrom(myself->socket, (char *) &(pkt.len), MTU, 0, NULL, NULL) <= 0) { - syslog(LOG_ERR, _("Receiving packet from %s (%s) failed: %m"), - cl->name, cl->hostname); + syslog(LOG_ERR, _("Receiving packet failed: %m")); return -1; } - total_socket_in += lenin; - - rp.data.len = ntohs(rp.data.len); - rp.len = ntohs(rp.len); - rp.from = ntohl(rp.from); - - if(rp.len >= 0) - { - f = lookup_conn(rp.from); - if(!f) - { - syslog(LOG_ERR, _("Got packet from %s (%s) with unknown origin %d.%d.%d.%d?"), - cl->name, cl->hostname, IP_ADDR_V(rp.from)); - return -1; - } - - if(f->status.validkey) - xrecv(f, &rp); - else - { - add_queue(&(f->rq), &rp, rp.len); - if(!cl->status.waitingforkey) - send_key_request(rp.from); - } - if(my_key_expiry <= time(NULL)) - regenerate_keys(); - } cp - return 0; + return xrecv(&pkt); } /* @@ -1036,13 +995,13 @@ cp accept a new tcp connect and create a new connection */ -int handle_new_meta_connection(conn_list_t *cl) +int handle_new_meta_connection() { conn_list_t *ncn; struct sockaddr client; int nfd, len = sizeof(client); cp - if((nfd = accept(cl->meta_socket, &client, &len)) < 0) + if((nfd = accept(myself->meta_socket, &client, &len)) < 0) { syslog(LOG_ERR, _("Accepting a new connection failed: %m")); return -1; @@ -1103,10 +1062,10 @@ cp } if(FD_ISSET(myself->socket, f)) - handle_incoming_vpn_data(myself); + handle_incoming_vpn_data(); if(FD_ISSET(myself->meta_socket, f)) - handle_new_meta_connection(myself); + handle_new_meta_connection(); cp } diff --git a/src/net.h b/src/net.h index 3be9acf9..8d416ec2 100644 --- a/src/net.h +++ b/src/net.h @@ -16,7 +16,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.13 2000/10/01 03:21:49 guus Exp $ + $Id: net.h,v 1.9.4.14 2000/10/11 10:35:16 guus Exp $ */ #ifndef __TINC_NET_H__ @@ -26,6 +26,7 @@ #include "config.h" #include "conf.h" +#include "connlist.h" #define MAXSIZE 1700 /* should be a bit more than the MTU for the tapdevice */ #define MTU 1600 @@ -52,23 +53,29 @@ #define EXPORTINDIRECTDATA 0x0002 /* Used to indicate uplink that it has to tell others to do INDIRECTDATA */ #define TCPONLY 0x0004 /* Tells sender to send packets over TCP instead of UDP (for firewalls) */ -typedef unsigned long ip_t; +typedef struct mac_t +{ + unsigned char x[6]; +} mac_t; + +typedef unsigned long ipv4_t; + +typedef ipv4_t ip_t; /* alias for ipv4_t */ + +typedef struct ipv6_t +{ + unsigned short x[8]; +} ipv6_t; + typedef unsigned short port_t; -typedef short length_t; -struct conn_list_t; +typedef short length_t; typedef struct vpn_packet_t { length_t len; /* the actual number of bytes in the `data' field */ unsigned char data[MAXSIZE]; } vpn_packet_t; -typedef struct real_packet_t { - length_t len; /* the length of the entire packet */ - ip_t from; /* where the packet came from */ - vpn_packet_t data; /* encrypted vpn_packet_t */ -} real_packet_t; - typedef struct passphrase_t { unsigned short len; unsigned char *phrase; @@ -87,8 +94,7 @@ typedef struct status_bits_t { int waitingforkey:1; /* 1 if we already sent out a request */ int dataopen:1; /* 1 if we have a valid UDP connection open */ int encryptout:1; /* 1 if we can encrypt outgoing traffic */ - int encryptin:1; /* 1 if we have to decrypt incoming traffic */ - int encrypted:1; + int decryptin:1; /* 1 if we have to decrypt incoming traffic */ int unused:18; } status_bits_t; @@ -113,45 +119,6 @@ typedef struct enc_key_t { time_t expiry; } enc_key_t; -typedef struct conn_list_t { - char *name; /* name of this connection */ - ip_t real_ip; /* his real (internet) ip */ - char *hostname; /* the hostname of its real ip */ - short unsigned int port; /* his portnumber */ - int protocol_version; /* used protocol */ - int options; /* options turned on for this connection */ - - int flags; /* his flags */ - int socket; /* our udp vpn socket */ - int meta_socket; /* our tcp meta socket */ - status_bits_t status; /* status info */ - packet_queue_t *sq; /* pending outgoing packets */ - packet_queue_t *rq; /* pending incoming packets (they have no - valid key to be decrypted with) */ - enc_key_t *public_key; /* the other party's public key */ - enc_key_t *datakey; /* encrypt data packets with this key */ - enc_key_t *rsakey; - - char *buffer; /* metadata input buffer */ - int buflen; /* bytes read into buffer */ - int reqlen; /* length of first request in buffer */ - 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 */ - int want_ping; /* 0 if there's no need to check for activity. Shouldn't this go into status? (GS) */ - - char *mychallenge; /* challenge we received from him */ - char *hischallenge; /* challenge we sent to him */ - - struct conn_list_t *nexthop; /* nearest meta-hop in this direction, will be changed to myuplink (GS) */ - struct conn_list_t *hisuplink; /* his nearest meta-hop in our direction */ - struct conn_list_t *myuplink; /* our nearest meta-hop in his direction */ - - struct subnet_t *subnets; /* Pointer to a list of subnets belonging to this connection */ - - struct conn_list_t *next; /* after all, it's a list of connections */ -} conn_list_t; - extern int tap_fd; extern int total_tap_in; @@ -159,9 +126,6 @@ extern int total_tap_out; extern int total_socket_in; extern int total_socket_out; -extern conn_list_t *conn_list; -extern conn_list_t *myself; - extern char *request_name[256]; extern char *status_text[10]; @@ -174,7 +138,7 @@ extern void main_loop(void); extern int setup_vpn_connection(conn_list_t *); extern void terminate_connection(conn_list_t *); extern void flush_queues(conn_list_t*); -extern int xrecv(conn_list_t *, void *); +extern int xrecv(vpn_packet_t *); extern void add_queue(packet_queue_t **, void *, size_t); #endif /* __TINC_NET_H__ */ diff --git a/src/netutl.c b/src/netutl.c index c5ff5b76..0a0a3fed 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: netutl.c,v 1.12.4.10 2000/09/15 12:58:40 zarq Exp $ + $Id: netutl.c,v 1.12.4.11 2000/10/11 10:35:17 guus Exp $ */ #include "config.h" @@ -41,25 +41,6 @@ #include "system.h" -/* - look for a connection associated with the given vpn ip, - return its connection structure. - Skips connections that are not activated! -*/ -conn_list_t *lookup_conn(ip_t ip) -{ - conn_list_t *p = conn_list; -cp - /* Exact match suggested by James B. MacLean */ - for(p = conn_list; p != NULL; p = p->next) - if((ip == p->vpn_ip) && p->status.active) - return p; - for(p = conn_list; p != NULL; p = p->next) - if(((ip & p->vpn_mask) == (p->vpn_ip & p->vpn_mask)) && p->status.active) - return p; -cp - return NULL; -} /* free a queue and all of its elements @@ -80,93 +61,6 @@ cp cp } -/* - free a conn_list_t element and all its pointers -*/ -void free_conn_element(conn_list_t *p) -{ -cp - if(p->sq) - destroy_queue(p->sq); - if(p->rq) - destroy_queue(p->rq); - if(p->name) - free(p->name); - if(p->hostname) - free(p->hostname); - free_key(p->public_key); - free_key(p->datakey); - free(p); -cp -} - -/* - remove all marked connections -*/ -void prune_conn_list(void) -{ - conn_list_t *p, *prev = NULL, *next = NULL; -cp - for(p = conn_list; p != NULL; ) - { - next = p->next; - - if(p->status.remove) - { - if(prev) - prev->next = next; - else - conn_list = next; - - free_conn_element(p); - } - else - prev = p; - - p = next; - } -cp -} - -/* - creates new conn_list element, and initializes it -*/ -conn_list_t *new_conn_list(void) -{ - conn_list_t *p = xmalloc(sizeof(*p)); -cp - /* initialise all those stupid pointers at once */ - memset(p, '\0', sizeof(*p)); - p->vpn_mask = (ip_t)(~0L); /* If this isn't done, it would be a - wastebucket for all packets with - unknown destination. */ - p->nexthop = p; -cp - return p; -} - -/* - free all elements of conn_list -*/ -void destroy_conn_list(void) -{ - conn_list_t *p, *next; -cp - for(p = conn_list; p != NULL; ) - { - next = p->next; - free_conn_element(p); - p = next; - } - - conn_list = NULL; -cp -} - -/* - look up the name associated with the ip - address `addr' -*/ char *hostlookup(unsigned long addr) { @@ -238,17 +132,3 @@ cp return ip; } -void dump_conn_list(void) -{ - conn_list_t *p; -cp - syslog(LOG_DEBUG, _("Connection list:")); - - for(p = conn_list; p != NULL; p = p->next) - { - syslog(LOG_DEBUG, _("%s netmask %d.%d.%d.%d at %s port %hd flags %d sockets %d, %d status %04x"), - p->name, IP_ADDR_V(p->vpn_mask), p->hostname, p->port, p->flags, - p->socket, p->meta_socket, p->status); - } -cp -} diff --git a/src/netutl.h b/src/netutl.h index 932814fa..6b6130b1 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: netutl.h,v 1.2.4.1 2000/06/25 15:22:16 guus Exp $ + $Id: netutl.h,v 1.2.4.2 2000/10/11 10:35:17 guus Exp $ */ #ifndef __TINC_NETUTL_H__ @@ -24,14 +24,7 @@ #include "net.h" -extern conn_list_t *lookup_conn(ip_t); -extern void free_conn_element(conn_list_t *); -extern void free_conn_list(conn_list_t*); -extern void prune_conn_list(void); -extern conn_list_t *new_conn_list(void); -extern void destroy_conn_list(void); extern char *hostlookup(unsigned long); extern ip_mask_t *strtoip(char*); -extern void dump_conn_list(void); #endif /* __TINC_NETUTL_H__ */ diff --git a/src/protocol.h b/src/protocol.h index d77c0455..e4fd5f1c 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -17,13 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol.h,v 1.5.4.8 2000/09/26 14:06:11 guus Exp $ + $Id: protocol.h,v 1.5.4.9 2000/10/11 10:35:17 guus Exp $ */ #ifndef __TINC_PROTOCOL_H__ #define __TINC_PROTOCOL_H__ #include "net.h" +#include "subnet.h" /* Protocol version. Different versions are incompatible, incompatible version have different protocols. diff --git a/src/subnet.c b/src/subnet.c index 9c225f21..9a882570 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -17,10 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.c,v 1.1.2.1 2000/10/01 03:21:49 guus Exp $ + $Id: subnet.c,v 1.1.2.2 2000/10/11 10:35:17 guus Exp $ */ #include "config.h" +#include + +#include #include "subnet.h" #include "net.h" @@ -29,29 +32,30 @@ subnet_t *new_subnet(void) { cp -cp + return (subnet_t *)xmalloc(sizeof(subnet_t)); } void free_subnet(subnet_t *subnet) { cp -cp + free(subnet); } /* Linked list management */ -int subnet_add(conn_list_t *cl, subnet_t *subnet) +void subnet_add(conn_list_t *cl, subnet_t *subnet) { cp + /* FIXME: do sorting on netmask size if necessary */ + subnet->next = cl->subnets->next; subnet->prev = NULL; - subnet->next->prev = subnet + subnet->next->prev = subnet; cl->subnets = subnet; cp - return 0; } -int subnet_del(conn_list_t *cl, subnet_t *subnet) +void subnet_del(conn_list_t *cl, subnet_t *subnet) { cp if(subnet->prev) @@ -62,25 +66,163 @@ cp { subnet->owner->subnets = subnet->next; } - + subnet->next->prev = subnet->prev; free_subnet(subnet); cp - return 0; } /* Ascii representation of subnets */ subnet_t *str2net(char *subnetstr) { + int type; + subnet_t *subnet; cp + if(sscanf(subnetstr, "%d,", &type) != 1) + return NULL; + + subnet = new_subnet(); + + switch(type) + { + case SUBNET_MAC: + if(sscanf(netstr, "%d,%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &subnet->type, + &subnet->net.mac.x[0], + &subnet->net.mac.x[1], + &subnet->net.mac.x[2], + &subnet->net.mac.x[3], + &subnet->net.mac.x[4], + &subnet->net.mac.x[5]) != 7) + { + free_subnet(subnet); + return NULL; + } + break; + case SUBNET_IPv4: + if(sscanf(subnetstr, "%d,%lx:%lx", &subnet->type, &subnet->net.ipv4.address, &subnet->net.ipv4.mask) != 3) + { + free_subnet(subnet); + return NULL; + } + break; + case SUBNET_IPv6: + if(sscanf(netstr, "%d,%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", &subnet->type, + &subnet->net.ipv6.address.x[0], + &subnet->net.ipv6.address.x[1], + &subnet->net.ipv6.address.x[2], + &subnet->net.ipv6.address.x[3], + &subnet->net.ipv6.address.x[4], + &subnet->net.ipv6.address.x[5], + &subnet->net.ipv6.address.x[6], + &subnet->net.ipv6.address.x[7], + &subnet->net.ipv6.mask.x[0], + &subnet->net.ipv6.mask.x[1], + &subnet->net.ipv6.mask.x[2], + &subnet->net.ipv6.mask.x[3], + &subnet->net.ipv6.mask.x[4], + &subnet->net.ipv6.mask.x[5], + &subnet->net.ipv6.mask.x[6], + &subnet->net.ipv6.mask.x[7]) != 17) + { + free_subnet(subnet); + return NULL; + } + break; + break; + default: + free_subnet(subnet); + return NULL; cp + return subnet; } char *net2str(subnet_t *subnet) { + char *netstr; cp + switch(subnet->type) + { + case SUBNET_MAC: + asprintf(netstr, "%d,%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", subnet->type, + subnet->net.mac.x[0], + subnet->net.mac.x[1], + subnet->net.mac.x[2], + subnet->net.mac.x[3], + subnet->net.mac.x[4], + subnet->net.mac.x[5]); + case SUBNET_IPv4: + asprintf(netstr, "%d,%lx:%lx", subnet->type, subnet->net.ipv4.address, subnet->net.ipv4.mask); + case SUBNET_IPv6: + asprintf(netstr, "%d,%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", + subnet->net.ipv6.address.x[0], + subnet->net.ipv6.address.x[1], + subnet->net.ipv6.address.x[2], + subnet->net.ipv6.address.x[3], + subnet->net.ipv6.address.x[4], + subnet->net.ipv6.address.x[5], + subnet->net.ipv6.address.x[6], + subnet->net.ipv6.address.x[7], + subnet->net.ipv6.mask.x[0], + subnet->net.ipv6.mask.x[1], + subnet->net.ipv6.mask.x[2], + subnet->net.ipv6.mask.x[3], + subnet->net.ipv6.mask.x[4], + subnet->net.ipv6.mask.x[5], + subnet->net.ipv6.mask.x[6], + subnet->net.ipv6.mask.x[7]); + default: + netstr = NULL; + } cp + return netstr; } /* Subnet lookup routines */ + +subnet_t *lookup_subnet_mac(subnet_t *subnets, mac_t address) +{ + subnet_t *subnet; +cp + for(subnet = subnets; subnet != NULL; subnet = subnet->next) + { + if(subnet->type == SUBNET_MAC) + if(memcmp(&address, &subnet->net.mac.address, sizeof(address)) == 0) + break; + } +cp + return subnet; +} + +subnet_t *lookup_subnet_ipv4(subnet_t *subnets, ipv4_t address) +{ + subnet_t *subnet; +cp + for(subnet = subnets; subnet != NULL; subnet = subnet->next) + { + if(subnet->type == SUBNET_IPV4) + if((address & subnet->net.ipv4.mask) == subnet->net.ipv4.address) + break; + } +cp + return subnet; +} + +subnet_t *lookup_subnet_ipv6(subnet_t *subnets, ipv6_t address) +{ + subnet_t *subnet; +cp + for(subnet = subnets; subnet != NULL; subnet = subnet->next) + { + if(subnet->type == SUBNET_IPV6) + { + for(i=0; i<8; i++) + if((address.x[i] & subnet->net.ipv6.mask.x[i]) != subnet->net.ipv6.address.x[i]) + break; + if(i=8) + break; + } + } +cp + return subnet; +} diff --git a/src/subnet.h b/src/subnet.h index ceb67102..b31226c0 100644 --- a/src/subnet.h +++ b/src/subnet.h @@ -17,18 +17,39 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.h,v 1.1.2.1 2000/10/01 03:21:49 guus Exp $ + $Id: subnet.h,v 1.1.2.2 2000/10/11 10:35:17 guus Exp $ */ #ifndef __TINC_SUBNET_H__ #define __TINC_SUBNET_H__ -enum{ +#include "net.h" +#include "connlist.h" + +enum +{ SUBNET_MAC = 0, - SUBNET_IPv4, - SUBNET_IPv6, + SUBNET_IPV4, + SUBNET_IPV6, }; +typedef struct subnet_mac_t +{ + mac_t address; +} subnet_mac_t; + +typedef struct subnet_ipv4_t +{ + ipv4_t address; + ipv4_t mask; +} subnet_ipv4_t; + +typedef struct subnet_ipv6_t +{ + ipv6_t address; + ipv6_t mask; +} subnet_ipv6_t; + typedef struct subnet_t { struct conn_list_t *owner; /* the owner of this subnet */ struct conn_list_t *uplink; /* the uplink which we should send packets to for this subnet */ @@ -38,11 +59,26 @@ typedef struct subnet_t { int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */ - /* Okay this is IPv4 specific because we are lazy and don't want to implement - other types just now. Type should always be SUBNET_IPv4 for now. */ + /* And now for the actual subnet: */ - ip_t netaddr; - ip_t netmask; + union + { + subnet_mac_t mac; + subnet_ipv4_t ipv4; + subnet_ipv6_t ipv6; + } net; + } subnet_t; +extern subnet_t *new_subnet(void); +extern void free_subnet(subnet_t *); +extern void subnet_add(conn_list_t *, subnet_t *); +extern void subnet_del(subnet_t *); +extern char *net2str(subnet_t *); +extern subnet_t *str2net(char *); +extern subnet_t *lookup_subnet_mac(subnet_t *, mac_t); +extern subnet_t *lookup_subnet_ipv4(subnet_t *, ipv4_t); +extern subnet_t *lookup_subnet_ipv6(subnet_t *, ipv6_t); + + #endif /* __TINC_SUBNET_H__ */ -- 2.20.1