BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file DatagramPeerIO.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <client/DatagramPeerIO.h>
31  
32 #include <generated/blog_channel_DatagramPeerIO.h>
33  
34 #define DATAGRAMPEERIO_MODE_NONE 0
35 #define DATAGRAMPEERIO_MODE_CONNECT 1
36 #define DATAGRAMPEERIO_MODE_BIND 2
37  
38 #define PeerLog(_o, ...) BLog_LogViaFunc((_o)->logfunc, (_o)->user, BLOG_CURRENT_CHANNEL, __VA_ARGS__)
39  
40 static void init_io (DatagramPeerIO *o);
41 static void free_io (DatagramPeerIO *o);
42 static void dgram_handler (DatagramPeerIO *o, int event);
43 static void reset_mode (DatagramPeerIO *o);
44 static void recv_decoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len);
45  
46 void init_io (DatagramPeerIO *o)
47 {
48 // init dgram recv interface
49 BDatagram_RecvAsync_Init(&o->dgram, o->effective_socket_mtu);
50  
51 // connect source
52 PacketRecvConnector_ConnectInput(&o->recv_connector, BDatagram_RecvAsync_GetIf(&o->dgram));
53  
54 // init dgram send interface
55 BDatagram_SendAsync_Init(&o->dgram, o->effective_socket_mtu);
56  
57 // connect sink
58 PacketPassConnector_ConnectOutput(&o->send_connector, BDatagram_SendAsync_GetIf(&o->dgram));
59 }
60  
61 void free_io (DatagramPeerIO *o)
62 {
63 // disconnect sink
64 PacketPassConnector_DisconnectOutput(&o->send_connector);
65  
66 // free dgram send interface
67 BDatagram_SendAsync_Free(&o->dgram);
68  
69 // disconnect source
70 PacketRecvConnector_DisconnectInput(&o->recv_connector);
71  
72 // free dgram recv interface
73 BDatagram_RecvAsync_Free(&o->dgram);
74 }
75  
76 void dgram_handler (DatagramPeerIO *o, int event)
77 {
78 DebugObject_Access(&o->d_obj);
79 ASSERT(o->mode == DATAGRAMPEERIO_MODE_CONNECT || o->mode == DATAGRAMPEERIO_MODE_BIND)
80  
81 PeerLog(o, BLOG_NOTICE, "error");
82  
83 // reset mode
84 reset_mode(o);
85  
86 // report error
87 if (o->handler_error) {
88 o->handler_error(o->user);
89 return;
90 }
91 }
92  
93 void reset_mode (DatagramPeerIO *o)
94 {
95 ASSERT(o->mode == DATAGRAMPEERIO_MODE_NONE || o->mode == DATAGRAMPEERIO_MODE_CONNECT || o->mode == DATAGRAMPEERIO_MODE_BIND)
96  
97 if (o->mode == DATAGRAMPEERIO_MODE_NONE) {
98 return;
99 }
100  
101 // remove recv notifier handler
102 PacketPassNotifier_SetHandler(&o->recv_notifier, NULL, NULL);
103  
104 // free I/O
105 free_io(o);
106  
107 // free datagram object
108 BDatagram_Free(&o->dgram);
109  
110 // set mode
111 o->mode = DATAGRAMPEERIO_MODE_NONE;
112 }
113  
114 void recv_decoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_len)
115 {
116 ASSERT(o->mode == DATAGRAMPEERIO_MODE_BIND)
117 DebugObject_Access(&o->d_obj);
118  
119 // obtain addresses from last received packet
120 BAddr addr;
121 BIPAddr local_addr;
122 ASSERT_EXECUTE(BDatagram_GetLastReceiveAddrs(&o->dgram, &addr, &local_addr))
123  
124 // check address family just in case
125 if (!BDatagram_AddressFamilySupported(addr.type)) {
126 PeerLog(o, BLOG_ERROR, "unsupported receive address");
127 return;
128 }
129  
130 // update addresses
131 BDatagram_SetSendAddrs(&o->dgram, addr, local_addr);
132 }
133  
134 int DatagramPeerIO_Init (
135 DatagramPeerIO *o,
136 BReactor *reactor,
137 int payload_mtu,
138 int socket_mtu,
139 struct spproto_security_params sp_params,
140 btime_t latency,
141 int num_frames,
142 PacketPassInterface *recv_userif,
143 int otp_warning_count,
144 BThreadWorkDispatcher *twd,
145 void *user,
146 BLog_logfunc logfunc,
147 DatagramPeerIO_handler_error handler_error,
148 DatagramPeerIO_handler_otp_warning handler_otp_warning,
149 DatagramPeerIO_handler_otp_ready handler_otp_ready
150 )
151 {
152 ASSERT(payload_mtu >= 0)
153 ASSERT(socket_mtu >= 0)
154 spproto_assert_security_params(sp_params);
155 ASSERT(num_frames > 0)
156 ASSERT(PacketPassInterface_GetMTU(recv_userif) >= payload_mtu)
157 if (SPPROTO_HAVE_OTP(sp_params)) {
158 ASSERT(otp_warning_count > 0)
159 ASSERT(otp_warning_count <= sp_params.otp_num)
160 }
161  
162 // set parameters
163 o->reactor = reactor;
164 o->payload_mtu = payload_mtu;
165 o->sp_params = sp_params;
166 o->user = user;
167 o->logfunc = logfunc;
168 o->handler_error = handler_error;
169  
170 // check num frames (for FragmentProtoAssembler)
171 if (num_frames >= FPA_MAX_TIME) {
172 PeerLog(o, BLOG_ERROR, "num_frames is too big");
173 goto fail0;
174 }
175  
176 // check payload MTU (for FragmentProto)
177 if (o->payload_mtu > UINT16_MAX) {
178 PeerLog(o, BLOG_ERROR, "payload MTU is too big");
179 goto fail0;
180 }
181  
182 // calculate SPProto payload MTU
183 if ((o->spproto_payload_mtu = spproto_payload_mtu_for_carrier_mtu(o->sp_params, socket_mtu)) <= (int)sizeof(struct fragmentproto_chunk_header)) {
184 PeerLog(o, BLOG_ERROR, "socket MTU is too small");
185 goto fail0;
186 }
187  
188 // calculate effective socket MTU
189 if ((o->effective_socket_mtu = spproto_carrier_mtu_for_payload_mtu(o->sp_params, o->spproto_payload_mtu)) < 0) {
190 PeerLog(o, BLOG_ERROR, "spproto_carrier_mtu_for_payload_mtu failed !?");
191 goto fail0;
192 }
193  
194 // init receiving
195  
196 // init assembler
197 if (!FragmentProtoAssembler_Init(&o->recv_assembler, o->spproto_payload_mtu, recv_userif, num_frames, fragmentproto_max_chunks_for_frame(o->spproto_payload_mtu, o->payload_mtu),
198 BReactor_PendingGroup(o->reactor), o->user, o->logfunc
199 )) {
200 PeerLog(o, BLOG_ERROR, "FragmentProtoAssembler_Init failed");
201 goto fail0;
202 }
203  
204 // init notifier
205 PacketPassNotifier_Init(&o->recv_notifier, FragmentProtoAssembler_GetInput(&o->recv_assembler), BReactor_PendingGroup(o->reactor));
206  
207 // init decoder
208 if (!SPProtoDecoder_Init(&o->recv_decoder, PacketPassNotifier_GetInput(&o->recv_notifier), o->sp_params, 2, BReactor_PendingGroup(o->reactor), twd, o->user, o->logfunc)) {
209 PeerLog(o, BLOG_ERROR, "SPProtoDecoder_Init failed");
210 goto fail1;
211 }
212 SPProtoDecoder_SetHandlers(&o->recv_decoder, handler_otp_ready, user);
213  
214 // init connector
215 PacketRecvConnector_Init(&o->recv_connector, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
216  
217 // init buffer
218 if (!SinglePacketBuffer_Init(&o->recv_buffer, PacketRecvConnector_GetOutput(&o->recv_connector), SPProtoDecoder_GetInput(&o->recv_decoder), BReactor_PendingGroup(o->reactor))) {
219 PeerLog(o, BLOG_ERROR, "SinglePacketBuffer_Init failed");
220 goto fail2;
221 }
222  
223 // init sending base
224  
225 // init disassembler
226 FragmentProtoDisassembler_Init(&o->send_disassembler, o->reactor, o->payload_mtu, o->spproto_payload_mtu, -1, latency);
227  
228 // init encoder
229 if (!SPProtoEncoder_Init(&o->send_encoder, FragmentProtoDisassembler_GetOutput(&o->send_disassembler), o->sp_params, otp_warning_count, BReactor_PendingGroup(o->reactor), twd)) {
230 PeerLog(o, BLOG_ERROR, "SPProtoEncoder_Init failed");
231 goto fail3;
232 }
233 SPProtoEncoder_SetHandlers(&o->send_encoder, handler_otp_warning, user);
234  
235 // init connector
236 PacketPassConnector_Init(&o->send_connector, o->effective_socket_mtu, BReactor_PendingGroup(o->reactor));
237  
238 // init buffer
239 if (!SinglePacketBuffer_Init(&o->send_buffer, SPProtoEncoder_GetOutput(&o->send_encoder), PacketPassConnector_GetInput(&o->send_connector), BReactor_PendingGroup(o->reactor))) {
240 PeerLog(o, BLOG_ERROR, "SinglePacketBuffer_Init failed");
241 goto fail4;
242 }
243  
244 // set mode
245 o->mode = DATAGRAMPEERIO_MODE_NONE;
246  
247 DebugObject_Init(&o->d_obj);
248 return 1;
249  
250 fail4:
251 PacketPassConnector_Free(&o->send_connector);
252 SPProtoEncoder_Free(&o->send_encoder);
253 fail3:
254 FragmentProtoDisassembler_Free(&o->send_disassembler);
255 SinglePacketBuffer_Free(&o->recv_buffer);
256 fail2:
257 PacketRecvConnector_Free(&o->recv_connector);
258 SPProtoDecoder_Free(&o->recv_decoder);
259 fail1:
260 PacketPassNotifier_Free(&o->recv_notifier);
261 FragmentProtoAssembler_Free(&o->recv_assembler);
262 fail0:
263 return 0;
264 }
265  
266 void DatagramPeerIO_Free (DatagramPeerIO *o)
267 {
268 DebugObject_Free(&o->d_obj);
269  
270 // reset mode
271 reset_mode(o);
272  
273 // free sending base
274 SinglePacketBuffer_Free(&o->send_buffer);
275 PacketPassConnector_Free(&o->send_connector);
276 SPProtoEncoder_Free(&o->send_encoder);
277 FragmentProtoDisassembler_Free(&o->send_disassembler);
278  
279 // free receiving
280 SinglePacketBuffer_Free(&o->recv_buffer);
281 PacketRecvConnector_Free(&o->recv_connector);
282 SPProtoDecoder_Free(&o->recv_decoder);
283 PacketPassNotifier_Free(&o->recv_notifier);
284 FragmentProtoAssembler_Free(&o->recv_assembler);
285 }
286  
287 PacketPassInterface * DatagramPeerIO_GetSendInput (DatagramPeerIO *o)
288 {
289 DebugObject_Access(&o->d_obj);
290  
291 return FragmentProtoDisassembler_GetInput(&o->send_disassembler);
292 }
293  
294 int DatagramPeerIO_Connect (DatagramPeerIO *o, BAddr addr)
295 {
296 DebugObject_Access(&o->d_obj);
297  
298 // reset mode
299 reset_mode(o);
300  
301 // check address
302 if (!BDatagram_AddressFamilySupported(addr.type)) {
303 PeerLog(o, BLOG_ERROR, "BDatagram_AddressFamilySupported failed");
304 goto fail0;
305 }
306  
307 // init dgram
308 if (!BDatagram_Init(&o->dgram, addr.type, o->reactor, o, (BDatagram_handler)dgram_handler)) {
309 PeerLog(o, BLOG_ERROR, "BDatagram_Init failed");
310 goto fail0;
311 }
312  
313 // set send address
314 BIPAddr local_addr;
315 BIPAddr_InitInvalid(&local_addr);
316 BDatagram_SetSendAddrs(&o->dgram, addr, local_addr);
317  
318 // init I/O
319 init_io(o);
320  
321 // set mode
322 o->mode = DATAGRAMPEERIO_MODE_CONNECT;
323  
324 return 1;
325  
326 fail0:
327 return 0;
328 }
329  
330 int DatagramPeerIO_Bind (DatagramPeerIO *o, BAddr addr)
331 {
332 DebugObject_Access(&o->d_obj);
333 ASSERT(BDatagram_AddressFamilySupported(addr.type))
334  
335 // reset mode
336 reset_mode(o);
337  
338 // init dgram
339 if (!BDatagram_Init(&o->dgram, addr.type, o->reactor, o, (BDatagram_handler)dgram_handler)) {
340 PeerLog(o, BLOG_ERROR, "BDatagram_Init failed");
341 goto fail0;
342 }
343  
344 // bind dgram
345 if (!BDatagram_Bind(&o->dgram, addr)) {
346 PeerLog(o, BLOG_INFO, "BDatagram_Bind failed");
347 goto fail1;
348 }
349  
350 // init I/O
351 init_io(o);
352  
353 // set recv notifier handler
354 PacketPassNotifier_SetHandler(&o->recv_notifier, (PacketPassNotifier_handler_notify)recv_decoder_notifier_handler, o);
355  
356 // set mode
357 o->mode = DATAGRAMPEERIO_MODE_BIND;
358  
359 return 1;
360  
361 fail1:
362 BDatagram_Free(&o->dgram);
363 fail0:
364 return 0;
365 }
366  
367 void DatagramPeerIO_SetEncryptionKey (DatagramPeerIO *o, uint8_t *encryption_key)
368 {
369 ASSERT(SPPROTO_HAVE_ENCRYPTION(o->sp_params))
370 DebugObject_Access(&o->d_obj);
371  
372 // set sending key
373 SPProtoEncoder_SetEncryptionKey(&o->send_encoder, encryption_key);
374  
375 // set receiving key
376 SPProtoDecoder_SetEncryptionKey(&o->recv_decoder, encryption_key);
377 }
378  
379 void DatagramPeerIO_RemoveEncryptionKey (DatagramPeerIO *o)
380 {
381 ASSERT(SPPROTO_HAVE_ENCRYPTION(o->sp_params))
382 DebugObject_Access(&o->d_obj);
383  
384 // remove sending key
385 SPProtoEncoder_RemoveEncryptionKey(&o->send_encoder);
386  
387 // remove receiving key
388 SPProtoDecoder_RemoveEncryptionKey(&o->recv_decoder);
389 }
390  
391 void DatagramPeerIO_SetOTPSendSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv)
392 {
393 ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
394 DebugObject_Access(&o->d_obj);
395  
396 // set sending seed
397 SPProtoEncoder_SetOTPSeed(&o->send_encoder, seed_id, key, iv);
398 }
399  
400 void DatagramPeerIO_RemoveOTPSendSeed (DatagramPeerIO *o)
401 {
402 ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
403 DebugObject_Access(&o->d_obj);
404  
405 // remove sending seed
406 SPProtoEncoder_RemoveOTPSeed(&o->send_encoder);
407 }
408  
409 void DatagramPeerIO_AddOTPRecvSeed (DatagramPeerIO *o, uint16_t seed_id, uint8_t *key, uint8_t *iv)
410 {
411 ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
412 DebugObject_Access(&o->d_obj);
413  
414 // add receiving seed
415 SPProtoDecoder_AddOTPSeed(&o->recv_decoder, seed_id, key, iv);
416 }
417  
418 void DatagramPeerIO_RemoveOTPRecvSeeds (DatagramPeerIO *o)
419 {
420 ASSERT(SPPROTO_HAVE_OTP(o->sp_params))
421 DebugObject_Access(&o->d_obj);
422  
423 // remove receiving seeds
424 SPProtoDecoder_RemoveOTPSeeds(&o->recv_decoder);
425 }