X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fmeta.c;h=3fadb0d45dde346ef9fd578b25e7f0d4d8158069;hp=21cbe964661e5c6abdc96b859f283ed8417a16ca;hb=fcf869cd4250a240ea8d443f70fa373e4fbacf07;hpb=c78a204f06182f50b0812c8e4fef6163e82097bf diff --git a/src/meta.c b/src/meta.c index 21cbe964..3fadb0d4 100644 --- a/src/meta.c +++ b/src/meta.c @@ -1,7 +1,7 @@ /* meta.c -- handle the meta communication - Copyright (C) 2000 Guus Sliepen , - 2000 Ivo Timmermans + Copyright (C) 2000,2001 Guus Sliepen , + 2000,2001 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 @@ -17,31 +17,50 @@ 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.18 2001/05/25 11:54:28 guus Exp $ */ #include "config.h" - -int send_meta(conn_list_t *cl, const char *buffer, int length) +#include +#include + +#include +#include +#include +#include +#include +/* This line must be below the rest for FreeBSD */ +#include + +#ifdef HAVE_OPENSSL_EVP_H +# include +#else +# include +#endif + +#include "net.h" +#include "connection.h" +#include "system.h" +#include "protocol.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"), int length, - cl->name, cl->hostname, buffer); + syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length, + cl->name, cl->hostname); 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; + length = outlen; } else - bufp = buffer; + bufp = buffer; if(write(cl->meta_socket, bufp, length) < 0) { @@ -52,24 +71,27 @@ cp return 0; } -int broadcast_meta(conn_list_t *cl, const char *buffer, int length) +void broadcast_meta(connection_t *cl, char *buffer, int length) { - conn_list_t *p; + avl_node_t *node; + connection_t *p; cp - for(p = conn_list; p != NULL; p = p->next) - if(p != cl && p->status.meta && p->status.active) - send_meta(p, buffer, length); + for(node = connection_tree->head; node; node = node->next) + { + p = (connection_t *)node->data; + if(p != cl && p->status.meta && p->status.active) + send_meta(p, buffer, length); + } cp - return 0; } -int receive_meta(conn_list_t *cl) +int receive_meta(connection_t *cl) { int x, l = sizeof(x); int oldlen, i; - int lenin = 0; + int lenin, reqlen; + int decrypted = 0; char inbuf[MAXBUFSIZE]; - char *bufp; cp if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) { @@ -84,67 +106,94 @@ cp return -1; } - if(cl->status.encryptin) - bufp = inbuf; - else - bufp = cl->buffer + cl->buflen; + /* 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, bufp, MAXBUFSIZE - cl->buflen); + lenin = read(cl->meta_socket, cl->buffer + cl->buflen, MAXBUFSIZE - cl->buflen); if(lenin<=0) { - if(errno==EINTR) - return 0; - if(errno==0) + if(lenin==0) { - if(debug_lvl>DEBUG_CONNECTIONS) + if(debug_lvl >= DEBUG_CONNECTIONS) syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname); } else - syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"), - cl->name, cl->hostname); + if(errno==EINTR) + return 0; + else + syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"), + cl->name, cl->hostname); + return -1; } - 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; - } - } - oldlen = cl->buflen; cl->buflen += lenin; - for(;;) + while(lenin) { - cl->reqlen = 0; + /* Decrypt */ + + if(cl->status.decryptin && !decrypted) + { + EVP_DecryptUpdate(cl->cipher_inctx, inbuf, &lenin, cl->buffer + oldlen, lenin); + memcpy(cl->buffer + oldlen, inbuf, lenin); + decrypted = 1; + } + + /* 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; - 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 { @@ -160,7 +209,6 @@ cp } cl->last_ping_time = time(NULL); - cl->want_ping = 0; cp return 0; }