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