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