eb005fdf4dc8b0e6bb5b1b8f3486fc3564867ecf
[oweals/tinc.git] / src / meta.c
1 /*
2     meta.c -- handle the meta communication
3     Copyright (C) 2000 Guus Sliepen <guus@sliepen.warande.net>,
4                   2000 Ivo Timmermans <itimmermans@bigfoot.com>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: meta.c,v 1.1.2.10 2000/11/15 01:06:10 zarq Exp $
21 */
22
23 #include "config.h"
24 #include <utils.h>
25
26 #include <errno.h>
27 #include <syslog.h>
28 #include <sys/signal.h>
29 #include <sys/socket.h>
30 #include <unistd.h>
31 #include <string.h>
32
33 #ifdef HAVE_OPENSSL_EVP_H
34 # include <openssl/evp.h>
35 #else
36 # include <evp.h>
37 #endif
38
39 #include "net.h"
40 #include "system.h"
41 #include "protocol.h"
42
43 int send_meta(conn_list_t *cl, char *buffer, int length)
44 {
45   char outbuf[MAXBUFSIZE];
46   char *bufp;
47   int outlen;
48 cp
49   if(debug_lvl >= DEBUG_META)
50     syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s): %s"), length,
51            cl->name, cl->hostname, buffer);
52
53   buffer[length-1]='\n';
54
55   if(cl->status.encryptout)
56     {
57       EVP_EncryptUpdate(cl->cipher_outctx, outbuf, &outlen, buffer, length);
58       bufp = outbuf;
59       length = outlen;
60     }
61   else
62       bufp = buffer;
63
64   if(write(cl->meta_socket, bufp, length) < 0)
65     {
66       syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %m"), cl->name, cl->hostname);
67       return -1;
68     }
69 cp
70   return 0;
71 }
72
73 int broadcast_meta(conn_list_t *cl, char *buffer, int length)
74 {
75   conn_list_t *p;
76 cp
77   for(p = conn_list; p != NULL; p = p->next)
78     if(p != cl && p->status.meta && p->status.active)
79       send_meta(p, buffer, length);
80 cp
81   return 0;
82 }
83
84 int receive_meta(conn_list_t *cl)
85 {
86   int x, l = sizeof(x);
87   int oldlen, i;
88   int lenin = 0;
89   char inbuf[MAXBUFSIZE];
90   char *bufp;
91 cp
92   if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
93     {
94       syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, cl->meta_socket,
95              cl->name, cl->hostname);
96       return -1;
97     }
98   if(x)
99     {
100       syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"),
101              cl->name, cl->hostname, strerror(x));
102       return -1;
103     }
104
105   if(cl->status.decryptin)
106     bufp = inbuf;
107   else
108     bufp = cl->buffer + cl->buflen;
109
110   lenin = read(cl->meta_socket, bufp, MAXBUFSIZE - cl->buflen);
111
112   if(lenin<=0)
113     {
114       if(errno==EINTR)
115         return 0;      
116       if(errno==0)
117         {
118           if(debug_lvl >= DEBUG_CONNECTIONS)
119             syslog(LOG_NOTICE, _("Connection closed by %s (%s)"),
120                 cl->name, cl->hostname);
121         }
122       else
123         syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"),
124                cl->name, cl->hostname);
125       return -1;
126     }
127
128   if(cl->status.decryptin)
129     {
130       EVP_DecryptUpdate(cl->cipher_inctx, cl->buffer + cl->buflen, &lenin, inbuf, lenin);
131     }
132
133   oldlen = cl->buflen;
134   cl->buflen += lenin;
135
136   for(;;)
137     {
138       cl->reqlen = 0;
139
140       for(i = oldlen; i < cl->buflen; i++)
141         {
142           if(cl->buffer[i] == '\n')
143             {
144               cl->buffer[i] = 0;  /* replace end-of-line by end-of-string so we can use sscanf */
145               cl->reqlen = i + 1;
146               break;
147             }
148         }
149
150       if(cl->reqlen)
151         {
152           if(debug_lvl >= DEBUG_META)
153             syslog(LOG_DEBUG, _("Got request from %s (%s): %s"),
154                    cl->name, cl->hostname, cl->buffer);
155
156           if(receive_request(cl))
157             return -1;
158
159           cl->buflen -= cl->reqlen;
160           memmove(cl->buffer, cl->buffer + cl->reqlen, cl->buflen);
161           oldlen = 0;
162         }
163       else
164         {
165           break;
166         }
167     }
168
169   if(cl->buflen >= MAXBUFSIZE)
170     {
171       syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"),
172              cl->name, cl->hostname);
173       return -1;
174     }
175
176   cl->last_ping_time = time(NULL);
177 cp  
178   return 0;
179 }