]> git.meshlink.io Git - meshlink-tiny/blob - src/net_packet.c
21e164a81135e9f95310bf268d0f5de879bcf059
[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                 route(mesh, n, packet);
45         }
46 }
47
48 static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *origpkt) {
49         if(!n->status.reachable) {
50                 logger(mesh, MESHLINK_ERROR, "Trying to send SPTPS data to unreachable node %s", n->name);
51                 return;
52         }
53
54         if(!n->status.validkey) {
55                 logger(mesh, MESHLINK_INFO, "No valid key known yet for %s", n->name);
56
57                 if(!n->status.waitingforkey) {
58                         send_req_key(mesh, n);
59                 } else if(n->last_req_key + 10 < mesh->loop.now.tv_sec) {
60                         logger(mesh, MESHLINK_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name);
61                         sptps_stop(&n->sptps);
62                         n->status.waitingforkey = false;
63                         send_req_key(mesh, n);
64                 }
65
66                 return;
67         }
68
69         uint8_t type = 0;
70
71         // If it's a probe, send it immediately without trying to compress it.
72         if(origpkt->probe) {
73                 sptps_send_record(&n->sptps, PKT_PROBE, origpkt->data, origpkt->len);
74                 return;
75         }
76
77         sptps_send_record(&n->sptps, type, origpkt->data, origpkt->len);
78         return;
79 }
80
81 bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
82         assert(handle);
83         assert(data);
84         assert(len);
85
86         node_t *to = handle;
87         meshlink_handle_t *mesh = to->mesh;
88
89         if(!to->status.reachable) {
90                 logger(mesh, MESHLINK_ERROR, "Trying to send SPTPS data to unreachable node %s", to->name);
91                 return false;
92         }
93
94
95         if(type == PKT_PROBE) {
96                 /* Probe packets are not supported. */
97                 return false;
98         }
99
100         /* Send it via TCP. */
101
102         char buf[len * 4 / 3 + 5];
103         b64encode(data, buf, len);
104
105         if(!to->nexthop || !to->nexthop->connection) {
106                 logger(mesh, MESHLINK_WARNING, "Unable to forward SPTPS packet to %s via %s", to->name, to->nexthop ? to->nexthop->name : to->name);
107                 return false;
108         }
109
110         /* If no valid key is known yet, send the packets using ANS_KEY requests,
111            to ensure we get to learn the reflexive UDP address. */
112         if(!to->status.validkey) {
113                 return send_request(mesh, to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, 0);
114         } else {
115                 return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
116         }
117 }
118
119 bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) {
120         assert(handle);
121         assert(!data || len);
122
123         node_t *from = handle;
124         meshlink_handle_t *mesh = from->mesh;
125
126         if(type == SPTPS_HANDSHAKE) {
127                 if(!from->status.validkey) {
128                         logger(mesh, MESHLINK_INFO, "SPTPS key exchange with %s successful", from->name);
129                         from->status.validkey = true;
130                         from->status.waitingforkey = false;
131
132                         if(from->utcp) {
133                                 utcp_reset_timers(from->utcp);
134                         }
135                 }
136
137                 return true;
138         }
139
140         if(len > MAXSIZE) {
141                 logger(mesh, MESHLINK_ERROR, "Packet from %s larger than maximum supported size (%d > %d)", from->name, len, MAXSIZE);
142                 return false;
143         }
144
145         vpn_packet_t inpkt;
146
147         if(type == PKT_PROBE) {
148                 /* We shouldn't receive any UDP probe packets. */
149                 return false;
150         } else {
151                 inpkt.probe = false;
152         }
153
154         if(type & ~(PKT_COMPRESSED)) {
155                 logger(mesh, MESHLINK_ERROR, "Unexpected SPTPS record type %d len %d from %s", type, len, from->name);
156                 return false;
157         }
158
159         if(type & PKT_COMPRESSED) {
160                 logger(mesh, MESHLINK_ERROR, "Error while decompressing packet from %s", from->name);
161                 return false;
162         }
163
164         memcpy(inpkt.data, data, len); // TODO: get rid of memcpy
165         inpkt.len = len;
166
167         receive_packet(mesh, from, &inpkt);
168         return true;
169 }
170
171 /*
172   send a packet to the given vpn ip.
173 */
174 void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) {
175         if(n == mesh->self) {
176                 // TODO: send to application
177                 return;
178         }
179
180         logger(mesh, MESHLINK_DEBUG, "Sending packet of %d bytes to %s", packet->len, n->name);
181
182         if(!n->status.reachable) {
183                 logger(mesh, MESHLINK_WARNING, "Node %s is not reachable", n->name);
184                 return;
185         }
186
187         send_sptps_packet(mesh, n, packet);
188         return;
189 }