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