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