]> git.meshlink.io Git - meshlink-tiny/blob - src/net_packet.c
b6478e44a7c47f438c7bbfd4f1a419c1ba599ff0
[meshlink-tiny] / src / net_packet.c
1 /*
2     net_packet.c -- Handles in- and outgoing VPN packets
3     Copyright (C) 2014-2017 Guus Sliepen <guus@meshlink.io>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "system.h"
21
22 #include "conf.h"
23 #include "connection.h"
24 #include "crypto.h"
25 #include "logger.h"
26 #include "meshlink_internal.h"
27 #include "net.h"
28 #include "netutl.h"
29 #include "protocol.h"
30 #include "route.h"
31 #include "utils.h"
32 #include "xalloc.h"
33
34 int keylifetime = 0;
35
36 /* VPN packet I/O */
37
38 static void receive_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) {
39         logger(mesh, MESHLINK_DEBUG, "Received packet of %d bytes from %s", packet->len, n->name);
40
41         if(n->status.blacklisted) {
42                 logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name);
43         } else {
44                 n->in_packets++;
45                 n->in_bytes += packet->len;
46
47                 route(mesh, n, packet);
48         }
49 }
50
51 static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *origpkt) {
52         if(!n->status.reachable) {
53                 logger(mesh, MESHLINK_ERROR, "Trying to send SPTPS data to unreachable node %s", n->name);
54                 return;
55         }
56
57         if(!n->status.validkey) {
58                 logger(mesh, MESHLINK_INFO, "No valid key known yet for %s", n->name);
59
60                 if(!n->status.waitingforkey) {
61                         send_req_key(mesh, n);
62                 } else if(n->last_req_key + 10 < mesh->loop.now.tv_sec) {
63                         logger(mesh, MESHLINK_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name);
64                         sptps_stop(&n->sptps);
65                         n->status.waitingforkey = false;
66                         send_req_key(mesh, n);
67                 }
68
69                 return;
70         }
71
72         uint8_t type = 0;
73
74         // If it's a probe, send it immediately without trying to compress it.
75         if(origpkt->probe) {
76                 sptps_send_record(&n->sptps, PKT_PROBE, origpkt->data, origpkt->len);
77                 return;
78         }
79
80         sptps_send_record(&n->sptps, type, origpkt->data, origpkt->len);
81         return;
82 }
83
84 bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
85         assert(handle);
86         assert(data);
87         assert(len);
88
89         node_t *to = handle;
90         meshlink_handle_t *mesh = to->mesh;
91
92         if(!to->status.reachable) {
93                 logger(mesh, MESHLINK_ERROR, "Trying to send SPTPS data to unreachable node %s", to->name);
94                 return false;
95         }
96
97
98         if(type == PKT_PROBE) {
99                 /* Probe packets are not supported. */
100                 return false;
101         }
102
103         /* Send it via TCP. */
104
105         char buf[len * 4 / 3 + 5];
106         b64encode(data, buf, len);
107
108         if(!to->nexthop || !to->nexthop->connection) {
109                 logger(mesh, MESHLINK_WARNING, "Unable to forward SPTPS packet to %s via %s", to->name, to->nexthop ? to->nexthop->name : to->name);
110                 return false;
111         }
112
113         /* If no valid key is known yet, send the packets using ANS_KEY requests,
114            to ensure we get to learn the reflexive UDP address. */
115         if(!to->status.validkey) {
116                 return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, 0);
117         } else {
118                 return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
119         }
120 }
121
122 bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) {
123         assert(handle);
124         assert(!data || len);
125
126         node_t *from = handle;
127         meshlink_handle_t *mesh = from->mesh;
128
129         if(type == SPTPS_HANDSHAKE) {
130                 if(!from->status.validkey) {
131                         logger(mesh, MESHLINK_INFO, "SPTPS key exchange with %s successful", from->name);
132                         from->status.validkey = true;
133                         from->status.waitingforkey = false;
134
135                         if(from->utcp) {
136                                 utcp_reset_timers(from->utcp);
137                         }
138                 }
139
140                 return true;
141         }
142
143         if(len > MAXSIZE) {
144                 logger(mesh, MESHLINK_ERROR, "Packet from %s larger than maximum supported size (%d > %d)", from->name, len, MAXSIZE);
145                 return false;
146         }
147
148         vpn_packet_t inpkt;
149
150         if(type == PKT_PROBE) {
151                 /* We shouldn't receive any UDP probe packets. */
152                 return false;
153         } else {
154                 inpkt.probe = false;
155         }
156
157         if(type & ~(PKT_COMPRESSED)) {
158                 logger(mesh, MESHLINK_ERROR, "Unexpected SPTPS record type %d len %d from %s", type, len, from->name);
159                 return false;
160         }
161
162         if(type & PKT_COMPRESSED) {
163                 logger(mesh, MESHLINK_ERROR, "Error while decompressing packet from %s", from->name);
164                 return false;
165         }
166
167         memcpy(inpkt.data, data, len); // TODO: get rid of memcpy
168         inpkt.len = len;
169
170         receive_packet(mesh, from, &inpkt);
171         return true;
172 }
173
174 /*
175   send a packet to the given vpn ip.
176 */
177 void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) {
178         if(n == mesh->self) {
179                 n->out_packets++;
180                 n->out_bytes += packet->len;
181                 // TODO: send to application
182                 return;
183         }
184
185         logger(mesh, MESHLINK_DEBUG, "Sending packet of %d bytes to %s", packet->len, n->name);
186
187         if(!n->status.reachable) {
188                 logger(mesh, MESHLINK_WARNING, "Node %s is not reachable", n->name);
189                 return;
190         }
191
192         n->out_packets++;
193         n->out_bytes += packet->len;
194         n->status.want_udp = true;
195
196         send_sptps_packet(mesh, n, packet);
197         return;
198 }