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