05a4adaa1b98f39363f531d3fa17e07476140550
[tinc] / src / protocol_misc.c
1 /*
2     protocol_misc.c -- handle the meta-protocol, miscellaneous functions
3     Copyright (C) 1999-2005 Ivo Timmermans,
4                   2000-2013 Guus Sliepen <guus@tinc-vpn.org>
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 along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "system.h"
22
23 #include "conf.h"
24 #include "connection.h"
25 #include "logger.h"
26 #include "meta.h"
27 #include "net.h"
28 #include "netutl.h"
29 #include "protocol.h"
30 #include "utils.h"
31 #include "xalloc.h"
32
33 #ifndef MIN
34 #define MIN(x, y) (((x)<(y))?(x):(y))
35 #endif
36
37 int maxoutbufsize = 0;
38 int mtu_info_interval = 5;
39 int udp_info_interval = 5;
40
41 /* Status and error notification routines */
42
43 bool send_status(connection_t *c, int statusno, const char *statusstring) {
44         if(!statusstring)
45                 statusstring = "Status";
46
47         return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
48 }
49
50 bool status_h(connection_t *c, const char *request) {
51         int statusno;
52         char statusstring[MAX_STRING_SIZE];
53
54         if(sscanf(request, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) {
55                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "STATUS",
56                            c->name, c->hostname);
57                 return false;
58         }
59
60         logger(DEBUG_STATUS, LOG_NOTICE, "Status message from %s (%s): %d: %s",
61                            c->name, c->hostname, statusno, statusstring);
62
63         return true;
64 }
65
66 bool send_error(connection_t *c, int err, const char *errstring) {
67         if(!errstring)
68                 errstring = "Error";
69
70         return send_request(c, "%d %d %s", ERROR, err, errstring);
71 }
72
73 bool error_h(connection_t *c, const char *request) {
74         int err;
75         char errorstring[MAX_STRING_SIZE];
76
77         if(sscanf(request, "%*d %d " MAX_STRING, &err, errorstring) != 2) {
78                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ERROR",
79                            c->name, c->hostname);
80                 return false;
81         }
82
83         logger(DEBUG_ERROR, LOG_NOTICE, "Error message from %s (%s): %d: %s",
84                            c->name, c->hostname, err, errorstring);
85
86         return false;
87 }
88
89 bool send_termreq(connection_t *c) {
90         return send_request(c, "%d", TERMREQ);
91 }
92
93 bool termreq_h(connection_t *c, const char *request) {
94         return false;
95 }
96
97 bool send_ping(connection_t *c) {
98         c->status.pinged = true;
99         c->last_ping_time = now.tv_sec;
100
101         return send_request(c, "%d", PING);
102 }
103
104 bool ping_h(connection_t *c, const char *request) {
105         return send_pong(c);
106 }
107
108 bool send_pong(connection_t *c) {
109         return send_request(c, "%d", PONG);
110 }
111
112 bool pong_h(connection_t *c, const char *request) {
113         c->status.pinged = false;
114
115         /* Succesful connection, reset timeout if this is an outgoing connection. */
116
117         if(c->outgoing) {
118                 c->outgoing->timeout = 0;
119                 c->outgoing->cfg = NULL;
120                 if(c->outgoing->ai)
121                         freeaddrinfo(c->outgoing->ai);
122                 c->outgoing->ai = NULL;
123                 c->outgoing->aip = NULL;
124         }
125
126         return true;
127 }
128
129 /* Sending and receiving packets via TCP */
130
131 bool send_tcppacket(connection_t *c, const vpn_packet_t *packet) {
132         /* If there already is a lot of data in the outbuf buffer, discard this packet.
133            We use a very simple Random Early Drop algorithm. */
134
135         if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
136                 return true;
137
138         if(!send_request(c, "%d %d", PACKET, packet->len))
139                 return false;
140
141         return send_meta(c, (char *)DATA(packet), packet->len);
142 }
143
144 bool tcppacket_h(connection_t *c, const char *request) {
145         short int len;
146
147         if(sscanf(request, "%*d %hd", &len) != 1) {
148                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "PACKET", c->name,
149                            c->hostname);
150                 return false;
151         }
152
153         /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
154
155         c->tcplen = len;
156
157         return true;
158 }
159
160 bool send_sptps_tcppacket(connection_t *c, const char* packet, int len) {
161         /* If there already is a lot of data in the outbuf buffer, discard this packet.
162            We use a very simple Random Early Drop algorithm. */
163
164         if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
165                 return true;
166
167         if(!send_request(c, "%d %d", SPTPS_PACKET, len))
168                 return false;
169
170         send_meta_raw(c, packet, len);
171         return true;
172 }
173
174 bool sptps_tcppacket_h(connection_t *c, const char* request) {
175         short int len;
176
177         if(sscanf(request, "%*d %hd", &len) != 1) {
178                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "SPTPS_PACKET", c->name,
179                            c->hostname);
180                 return false;
181         }
182
183         /* Set sptpslen to len, this will tell receive_meta() that a SPTPS packet is coming. */
184
185         c->sptpslen = len;
186
187         return true;
188 }
189
190 /* Transmitting UDP information */
191
192 bool send_udp_info(node_t *from, node_t *to) {
193         /* If there's a static relay in the path, there's no point in sending the message
194            farther than the static relay. */
195         to = (to->via == myself) ? to->nexthop : to->via;
196
197         if (to == NULL) {
198                 logger(DEBUG_ALWAYS, LOG_ERR, "Something went wrong when selecting relay - possible fake UDP_INFO");
199                 return false;
200         }
201
202         /* Skip cases where sending UDP info messages doesn't make sense.
203            This is done here in order to avoid repeating the same logic in multiple callsites. */
204
205         if(to == myself)
206                 return true;
207
208         if(!to->status.reachable)
209                 return true;
210
211         if(from == myself) {
212                 if(to->connection)
213                         return true;
214
215                 struct timeval elapsed;
216                 timersub(&now, &to->udp_info_sent, &elapsed);
217                 if(elapsed.tv_sec < udp_info_interval)
218                         return true;
219         }
220
221         if((myself->options | from->options | to->options) & OPTION_TCPONLY)
222                 return true;
223
224         if((to->nexthop->options >> 24) < 5)
225                 return true;
226
227         char *from_address, *from_port;
228         /* If we're the originator, the address we use is irrelevant
229            because the first intermediate node will ignore it.
230            We use our local address as it somewhat makes sense
231            and it's simpler than introducing an encoding for "null" addresses anyway. */
232         sockaddr2str((from != myself) ? &from->address : &to->nexthop->connection->edge->local_address, &from_address, &from_port);
233
234         bool x = send_request(to->nexthop->connection, "%d %s %s %s %s", UDP_INFO, from->name, to->name, from_address, from_port);
235
236         free(from_address);
237         free(from_port);
238
239         if(from == myself)
240                 to->udp_info_sent = now;
241
242         return x;
243 }
244
245 bool udp_info_h(connection_t *c, const char* request) {
246         char from_name[MAX_STRING_SIZE];
247         char to_name[MAX_STRING_SIZE];
248         char from_address[MAX_STRING_SIZE];
249         char from_port[MAX_STRING_SIZE];
250
251         if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING, from_name, to_name, from_address, from_port) != 4) {
252                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "UDP_INFO", c->name, c->hostname);
253                 return false;
254         }
255
256         if(!check_id(from_name) || !check_id(to_name)) {
257                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "UDP_INFO", c->name, c->hostname, "invalid name");
258                 return false;
259         }
260
261         node_t *from = lookup_node(from_name);
262         if(!from) {
263                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", "UDP_INFO", c->name, c->hostname, from_name);
264                 return true;
265         }
266
267         if(from != from->via) {
268                 /* Not supposed to happen, as it means the message wandered past a static relay */
269                 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got UDP info message from %s (%s) which we can't reach directly", from->name, from->hostname);
270                 return true;
271         }
272
273         /* If we have a direct edge to "from", we are in a better position
274            to guess its address than it is itself. */
275         if(!from->connection && !from->status.udp_confirmed) {
276                 sockaddr_t from_addr = str2sockaddr(from_address, from_port);
277                 if(sockaddrcmp(&from_addr, &from->address))
278                         update_node_udp(from, &from_addr);
279         }
280
281         node_t *to = lookup_node(to_name);
282         if(!to) {
283                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", "UDP_INFO", c->name, c->hostname, to_name);
284                 return true;
285         }
286
287         /* Send our own data (which could be what we just received) up the chain. */
288
289         return send_udp_info(from, to);
290 }
291
292 /* Transmitting MTU information */
293
294 bool send_mtu_info(node_t *from, node_t *to, int mtu) {
295         /* Skip cases where sending MTU info messages doesn't make sense.
296            This is done here in order to avoid repeating the same logic in multiple callsites. */
297
298         if(to == myself)
299                 return true;
300
301         if(!to->status.reachable)
302                 return true;
303
304         if(from == myself) {
305                 if(to->connection)
306                         return true;
307
308                 struct timeval elapsed;
309                 timersub(&now, &to->mtu_info_sent, &elapsed);
310                 if(elapsed.tv_sec < mtu_info_interval)
311                         return true;
312         }
313
314         if((to->nexthop->options >> 24) < 6)
315                 return true;
316
317         /* We will send the passed-in MTU value, unless we believe ours is better. */
318
319         node_t *via = (from->via == myself) ? from->nexthop : from->via;
320         if(from->minmtu == from->maxmtu && from->via == myself) {
321                 /* We have a direct measurement. Override the value entirely.
322                    Note that we only do that if we are sitting as a static relay in the path;
323                    otherwise, we can't guarantee packets will flow through us, and increasing
324                    MTU could therefore end up being too optimistic. */
325                 mtu = from->minmtu;
326         } else if(via->minmtu == via->maxmtu) {
327                 /* Static relay. Ensure packets will make it through the entire relay path. */
328                 mtu = MIN(mtu, via->minmtu);
329         } else if(via->nexthop->minmtu == via->nexthop->maxmtu) {
330                 /* Dynamic relay. Ensure packets will make it through the entire relay path. */
331                 mtu = MIN(mtu, via->nexthop->minmtu);
332         }
333
334         if(from == myself)
335                 to->mtu_info_sent = now;
336
337         /* If none of the conditions above match in the steady state, it means we're using TCP,
338            so the MTU is irrelevant. That said, it is still important to honor the MTU that was passed in,
339            because other parts of the relay path might be able to use UDP, which means they care about the MTU. */
340
341         return send_request(to->nexthop->connection, "%d %s %s %d", MTU_INFO, from->name, to->name, mtu);
342 }
343
344 bool mtu_info_h(connection_t *c, const char* request) {
345         char from_name[MAX_STRING_SIZE];
346         char to_name[MAX_STRING_SIZE];
347         int mtu;
348
349         if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" %d", from_name, to_name, &mtu) != 3) {
350                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "MTU_INFO", c->name, c->hostname);
351                 return false;
352         }
353
354         if(mtu < 512) {
355                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "MTU_INFO", c->name, c->hostname, "invalid MTU");
356                 return false;
357         }
358
359         mtu = MIN(mtu, MTU);
360
361         if(!check_id(from_name) || !check_id(to_name)) {
362                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "MTU_INFO", c->name, c->hostname, "invalid name");
363                 return false;
364         }
365
366         node_t *from = lookup_node(from_name);
367         if(!from) {
368                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", "MTU_INFO", c->name, c->hostname, from_name);
369                 return true;
370         }
371
372         /* If we don't know the current MTU for that node, use the one we received.
373            Even if we're about to make our own measurements, the value we got from downstream nodes should be pretty close
374            so it's a good idea to use it in the mean time. */
375         if(from->mtu != mtu && from->minmtu != from->maxmtu) {
376                 logger(DEBUG_TRAFFIC, LOG_INFO, "Using provisional MTU %d for node %s (%s)", mtu, from->name, from->hostname);
377                 from->mtu = mtu;
378         }
379
380         node_t *to = lookup_node(to_name);
381         if(!to) {
382                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", "MTU_INFO", c->name, c->hostname, to_name);
383                 return true;
384         }
385
386         /* Continue passing the MTU value (or a better one if we have it) up the chain. */
387
388         return send_mtu_info(from, to, mtu);
389 }