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