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