2 meta.c -- handle the meta communication
3 Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
4 2000-2005 Ivo Timmermans
5 2006 Scott Lamb <slamb@slamb.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "splay_tree.h"
26 #include "connection.h"
34 bool send_meta(connection_t *c, const char *buffer, int length) {
36 logger(LOG_ERR, "send_meta() called with NULL pointer!");
40 ifdebug(META) logger(LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length,
41 c->name, c->hostname);
43 /* Add our data to buffer */
44 if(c->status.encryptout) {
46 size_t outlen = length;
48 if(!cipher_encrypt(&c->outcipher, buffer, length, outbuf, &outlen, false) || outlen != length) {
49 logger(LOG_ERR, "Error while encrypting metadata to %s (%s)",
50 c->name, c->hostname);
54 write(c->socket, outbuf, length);
56 write(c->socket, buffer, length);
62 void broadcast_meta(connection_t *from, const char *buffer, int length) {
66 for(node = connection_tree->head; node; node = node->next) {
69 if(c != from && c->status.active)
70 send_meta(c, buffer, length);
74 static bool process_meta(connection_t *c, char *reqbuf, int *len) {
81 receive_tcppacket(c, reqbuf, c->tcplen);
84 memmove(reqbuf, reqbuf, *len - c->tcplen);
87 char *end = memchr(reqbuf, '\n', *len);
94 bool success = receive_request(c, reqbuf);
100 memmove(reqbuf, end, *len - (end - reqbuf));
101 *len -= end - reqbuf;
108 bool receive_meta(connection_t *c) {
111 char inbuf[MAXBUFSIZE];
112 char reqbuf[MAXBUFSIZE];
115 - Read as much as possible from the TCP socket in one go.
116 - Decrypt it if necessary.
117 - Check if a full request is in the request buffer.
118 - If yes, process request and remove it from the buffer, then check again.
119 - If not, try to read more.
123 inlen = recv(c->socket, inbuf, sizeof inbuf - reqlen, 0);
126 if(!inlen || !errno) {
127 ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
128 c->name, c->hostname);
129 } else if(sockwouldblock(sockerrno))
132 logger(LOG_ERR, "Metadata socket read error for %s (%s): %s",
133 c->name, c->hostname, sockstrerror(sockerrno));
138 if(!c->status.decryptin) {
139 char *end = memchr(inbuf, '\n', inlen);
144 memcpy(reqbuf + reqlen, inbuf, end - inbuf);
145 reqlen += end - inbuf;
147 if(!process_meta(c, reqbuf, &reqlen))
150 memmove(inbuf, end, inlen - (end - inbuf));
151 inlen -= end - inbuf;
153 size_t outlen = inlen;
155 if(!cipher_decrypt(&c->incipher, inbuf, inlen, reqbuf + reqlen, &outlen, false) || inlen != outlen) {
156 logger(LOG_ERR, "Error while decrypting metadata from %s (%s)", c->name, c->hostname);
163 if(!process_meta(c, reqbuf, &reqlen))