- Lots of little stuff modified
[tinc] / 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.6 2000/10/24 15:46:16 guus 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 <openssl/evp.h>
31
32 #include "net.h"
33 #include "system.h"
34
35 int send_meta(conn_list_t *cl, char *buffer, int length)
36 {
37   char outbuf[MAXBUFSIZE];
38   char *bufp;
39   int outlen;
40 cp
41   if(debug_lvl >= DEBUG_META)
42     syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s): %s"), length,
43            cl->name, cl->hostname, buffer);
44
45   buffer[length-1]='\n';
46 /*  
47   if(cl->status.encryptout)
48     {
49       EVP_EncryptUpdate(cl->cipher_outctx, outbuf, &outlen, buffer, length);
50       bufp = outbuf;
51     }
52   else
53 */
54     bufp = buffer;
55
56   if(write(cl->meta_socket, bufp, length) < 0)
57     {
58       syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %m"), cl->name, cl->hostname);
59       return -1;
60     }
61 cp
62   return 0;
63 }
64
65 int broadcast_meta(conn_list_t *cl, char *buffer, int length)
66 {
67   conn_list_t *p;
68 cp
69   for(p = conn_list; p != NULL; p = p->next)
70     if(p != cl && p->status.meta && p->status.active)
71       send_meta(p, buffer, length);
72 cp
73   return 0;
74 }
75
76 int receive_meta(conn_list_t *cl)
77 {
78   int x, l = sizeof(x);
79   int oldlen, i;
80   int lenin = 0;
81   char inbuf[MAXBUFSIZE];
82   char *bufp;
83 cp
84   if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
85     {
86       syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, cl->meta_socket,
87              cl->name, cl->hostname);
88       return -1;
89     }
90   if(x)
91     {
92       syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"),
93              cl->name, cl->hostname, strerror(x));
94       return -1;
95     }
96 /*
97   if(cl->status.decryptin)
98     bufp = inbuf;
99   else
100 */
101     bufp = cl->buffer + cl->buflen;
102
103   lenin = read(cl->meta_socket, bufp, MAXBUFSIZE - cl->buflen);
104
105   if(lenin<=0)
106     {
107       if(errno==EINTR)
108         return 0;      
109       if(errno==0)
110         {
111           if(debug_lvl >= DEBUG_CONNECTIONS)
112             syslog(LOG_NOTICE, _("Connection closed by %s (%s)"),
113                 cl->name, cl->hostname);
114         }
115       else
116         syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"),
117                cl->name, cl->hostname);
118       return -1;
119     }
120 /*
121   if(cl->status.decryptin)
122     {
123       EVP_DecryptUpdate(cl->cipher_inctx, cl->buffer + cl->buflen, NULL, inbuf, lenin);
124     }
125 */
126   oldlen = cl->buflen;
127   cl->buflen += lenin;
128
129   for(;;)
130     {
131       cl->reqlen = 0;
132
133       for(i = oldlen; i < cl->buflen; i++)
134         {
135           if(cl->buffer[i] == '\n')
136             {
137               cl->buffer[i] = 0;  /* replace end-of-line by end-of-string so we can use sscanf */
138               cl->reqlen = i + 1;
139               break;
140             }
141         }
142
143       if(cl->reqlen)
144         {
145           if(debug_lvl >= DEBUG_META)
146             syslog(LOG_DEBUG, _("Got request from %s (%s): %s"),
147                    cl->name, cl->hostname, cl->buffer);
148
149           if(receive_request(cl))
150             return -1;
151
152           cl->buflen -= cl->reqlen;
153           memmove(cl->buffer, cl->buffer + cl->reqlen, cl->buflen);
154           oldlen = 0;
155         }
156       else
157         {
158           break;
159         }
160     }
161
162   if(cl->buflen >= MAXBUFSIZE)
163     {
164       syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"),
165              cl->name, cl->hostname);
166       return -1;
167     }
168
169   cl->last_ping_time = time(NULL);
170   cl->want_ping = 0;
171 cp  
172   return 0;
173 }