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