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