X-Git-Url: https://www.tinc-vpn.org/git/browse?a=blobdiff_plain;ds=sidebyside;f=src%2Fpokey%2Fmeta.c;fp=src%2Fpokey%2Fmeta.c;h=c3138e3a74490667ed5a0c2d5288c0ce5f9e0971;hb=04d33be4bd102de67bb6dba5c449e12fea0db4d2;hp=0000000000000000000000000000000000000000;hpb=b0a676988a8da3120e64ef0e1a4ea4c28b1511e1;p=tinc diff --git a/src/pokey/meta.c b/src/pokey/meta.c new file mode 100644 index 00000000..c3138e3a --- /dev/null +++ b/src/pokey/meta.c @@ -0,0 +1,190 @@ +/* + meta.c -- handle the meta communication + Copyright (C) 2000-2002 Guus Sliepen , + 2000-2002 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: meta.c,v 1.1 2002/04/28 12:46:26 zarq Exp $ +*/ + +#include "config.h" +#include +#include + +#include +#include +#include +/* This line must be below the rest for FreeBSD */ +#include +#include + +#include + +#include "net.h" +#include "connection.h" +#include "interface.h" +#include "system.h" +#include "protocol.h" +#include "logging.h" + +int send_meta(connection_t *c, char *buffer, int length) +{ + char *bufp; + int outlen; + char outbuf[MAXBUFSIZE]; +cp + log(DEBUG_META, TLOG_DEBUG, + _("Sending %d bytes of metadata to %s (%s)"), + length, c->name, c->hostname); + + if(c->status.encryptout) + { + EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length); + bufp = outbuf; + length = outlen; + } + else + bufp = buffer; + + if(write(c->socket, bufp, length) < 0) + { + syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, c->hostname, strerror(errno)); + return -1; + } +cp + return 0; +} + +void broadcast_meta(connection_t *from, char *buffer, int length) +{ + avl_node_t *node; + connection_t *c; +cp + for(node = connection_tree->head; node; node = node->next) + { + c = (connection_t *)node->data; + if(c != from && c->status.active) + send_meta(c, buffer, length); + } +cp +} + +int receive_meta(connection_t *c) +{ + int x, l = sizeof(x); + int oldlen, i; + int lenin, reqlen; + int decrypted = 0; + char inbuf[MAXBUFSIZE]; +cp + if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) + { + syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__, __LINE__, c->socket, strerror(errno), + c->name, c->hostname); + return -1; + } + if(x) + { + syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"), + c->name, c->hostname, strerror(x)); + 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(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen); + + if(lenin<=0) + { + if(lenin==0) + { + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), + c->name, c->hostname); + } + else + if(errno==EINTR) + return 0; + else + syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"), + c->name, c->hostname, strerror(errno)); + + return -1; + } + + oldlen = c->buflen; + c->buflen += lenin; + + while(lenin) + { + /* Decrypt */ + + if(c->status.decryptin && !decrypted) + { + EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, lenin); + memcpy(c->buffer + oldlen, inbuf, lenin); + decrypted = 1; + } + + /* Otherwise we are waiting for a request */ + + reqlen = 0; + + for(i = oldlen; i < c->buflen; i++) + { + if(c->buffer[i] == '\n') + { + c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ + reqlen = i + 1; + break; + } + } + + if(reqlen) + { + if(receive_request(c)) + return -1; + + c->buflen -= reqlen; + lenin -= reqlen; + memmove(c->buffer, c->buffer + reqlen, c->buflen); + oldlen = 0; + continue; + } + else + { + break; + } + } + + if(c->buflen >= MAXBUFSIZE) + { + syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"), + c->name, c->hostname); + return -1; + } + + c->last_ping_time = now; +cp + return 0; +}