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