add winpcap 4.0.2 from url http://www.winpcap.org/
[natblaster.git] / src / peer / peerfsm.c
blobfc19c5b9356c2d68a3f72168be68b2bebcff42c2
1 /*****************************************************************************
2 * Copyright 2005 Daniel Ferullo *
3 * *
4 * Licensed under the Apache License, Version 2.0 (the "License"); *
5 * you may not use this file except in compliance with the License. *
6 * You may obtain a copy of the License at *
7 * *
8 * http://www.apache.org/licenses/LICENSE-2.0 *
9 * *
10 * Unless required by applicable law or agreed to in writing, software *
11 * distributed under the License is distributed on an "AS IS" BASIS, *
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13 * See the License for the specific language governing permissions and *
14 * limitations under the License. *
15 * *
16 *****************************************************************************/
18 /**
19 * @file peerfsm.c
20 * @author Daniel Ferullo (ferullo@cmu.edu)
22 * @brief contains defintions of fsm-like functions to control peer connection
23 * protocol control flow.
25 * @bug peer_fsm_forge_syn_ack only forges one SYN/ACK. Because network could
26 * be lossy, maybe send more than one?
30 #include "peerfsm.h"
31 #include "peerfsm_private.h"
32 #include "peercon.h"
33 #include "directconn.h"
34 #include "nethelp.h"
35 #include "netio.h"
36 #include "comm.h"
37 #include "debug.h"
38 #include "sniff.h"
39 #include "spoof.h"
40 #include <time.h>
41 #include <stdlib.h>
43 errorcode peer_fsm_start(peer_conn_info_t *info) {
45 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
47 DBG_TIME("time at start of fsm");
49 /* create the tcp connection to the helper */
50 CHECK_FAILED(tcp_connect(info->helper.ip,info->helper.port,
51 &(info->socks.helper)),ERROR_TCP_CONNECT);
54 /* move into the hello state */
55 CHECK_FAILED(peer_fsm_hello(info),ERROR_CALLED_FUNCTION);
57 DBG_TIME("time at end of fsm");
59 return SUCCESS;
63 errorcode peer_fsm_hello(peer_conn_info_t *info) {
65 /* declare local variables */
66 comm_msg_hello_t msg;
68 /* error check arguments */
69 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
71 /* do function */
73 DBG_TIME("time at start of function");
75 /* create the message payload... */
76 msg.peer_ip = info->peer.ip;
77 msg.peer_port = info->peer.port;
78 msg.buddy_int_ip = info->buddy.int_ip;
79 msg.buddy_int_port = info->buddy.int_port;
80 msg.buddy_ext_ip = info->buddy.ext_ip;
82 DEBUG(DBG_BDAY,"BDAY: peer internal port: %u\n",
83 DBG_PORT(info->peer.port));
85 /* ...and send it */
86 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_HELLO,&msg,
87 sizeof(msg)),ERROR_NETWORK_SEND);
89 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent HELLO\n");
91 /* call next state */
92 CHECK_FAILED(peer_fsm_conn_again(info),ERROR_CALLED_FUNCTION);
94 DBG_TIME("time at end of function");
96 return SUCCESS;
99 errorcode peer_fsm_conn_again(peer_conn_info_t *info) {
101 /* declare variables */
103 /* error check arguments */
104 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
106 /* do function */
107 DBG_TIME("time at start of function");
109 /* get message */
110 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_CONNECT_AGAIN,NULL,0),
111 ERROR_NETWORK_READ);
113 DEBUG(DBG_PROTOCOL,"PROTOCOL:received CONNECT_AGAIN\n");
115 /* open a second connection */
116 CHECK_FAILED(tcp_connect(info->helper.ip,info->helper.port,
117 &(info->socks.helper_pred)),ERROR_TCP_CONNECT);
119 /* send a message indicating that the second connection has
120 * been made */
121 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_CONNECTED_AGAIN,
122 NULL,0),ERROR_NETWORK_SEND);
124 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent CONNECTED_AGAIN\n");
126 /* enter next state */
127 if (FAILED(peer_fsm_check_port_pred(info))) {
128 /* close the second connection socket */
129 close(info->socks.helper_pred);
130 return ERROR_CALLED_FUNCTION;
133 /* close the second connection */
134 close(info->socks.helper_pred);
136 DBG_TIME("time at end of function");
138 return SUCCESS;
141 errorcode peer_fsm_check_port_pred(peer_conn_info_t *info) {
143 /* declare local variables */
144 comm_msg_pred_port_t msg;
146 /* error check arguments */
147 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
149 /* do function */
150 DBG_TIME("time at start of function");
152 /* read the next message */
153 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_PORT_PRED,
154 &msg,sizeof(comm_msg_pred_port_t)),ERROR_NETWORK_READ);
156 info->port_alloc.method = msg.port_alloc;
158 DEBUG(DBG_PROTOCOL,"PROTOCOL:received PORT_PRED\n");
159 DEBUG(DBG_VERBOSE,"VERBOSE:alloc method = %s\n",
160 (info->port_alloc.method==COMM_PORT_ALLOC_SEQ) ?
161 "sequential" : "random" );
163 /* send message saying waiting for buddy information from helper */
164 CHECK_FAILED(sendMsg(info->socks.helper,
165 COMM_MSG_WAITING_FOR_BUDDY_ALLOC, NULL, 0),ERROR_NETWORK_SEND);
167 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent WAITING_FOR_BUDDY_ALLOC\n");
168 /* enter next state */
169 CHECK_FAILED(peer_fsm_buddy_alloc(info),ERROR_CALLED_FUNCTION);
171 DBG_TIME("time at end of function");
173 return SUCCESS;
177 errorcode peer_fsm_buddy_alloc(peer_conn_info_t *info) {
179 /* declare local variables */
180 comm_msg_buddy_alloc_t buddy;
182 /* error check arguments */
183 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
185 /* do function */
186 DBG_TIME("time at start of function");
188 /* receive the buddy info */
189 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_BUDDY_ALLOC,
190 &buddy,sizeof(buddy)),ERROR_NETWORK_READ);
192 DEBUG(DBG_PROTOCOL,"PROTOCOL:received BUDDY_ALLOC\n");
193 DEBUG(DBG_VERBOSE,"VERBOSE:buddy alloc method: %s\n",
194 (buddy.buddy_port_alloc==COMM_PORT_ALLOC_SEQ
195 ? "sequential" : "random" ));
196 DEBUG(DBG_VERBOSE,"VERBOSE:connection is %ssupported\n",
197 (buddy.support==COMM_CONNECTION_SUPPORTED ? "" : "not "));
200 /* send a message asking for the buddy's external port */
201 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_WAITING_FOR_BUDDY_PORT,
202 NULL,0),ERROR_NETWORK_SEND);
203 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent WAITING_FOR_BUDDY_PORT\n");
205 /* enter next state */
206 CHECK_FAILED(peer_fsm_buddy_port(info),ERROR_CALLED_FUNCTION);
208 DBG_TIME("time at end of function");
210 return SUCCESS;
213 errorcode peer_fsm_buddy_port(peer_conn_info_t *info) {
215 /* declare local variables */
216 comm_msg_buddy_port_t msg;
218 /* error check arguments */
219 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
221 /* do function */
222 DBG_TIME("time at start of function");
224 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_BUDDY_PORT,&msg,
225 sizeof(msg)),ERROR_NETWORK_READ);
226 DEBUG(DBG_PROTOCOL,"PROTOCOL:received BUDDY_PORT\n");
227 DEBUG(DBG_VERBOSE,"VERBOSE:buddy port = %d\n",
228 DBG_PORT(msg.ext_port));
229 DEBUG(DBG_VERBOSE,"VERBOSE:bday is %sneeded\n",
230 (msg.bday == COMM_BDAY_NEEDED ? "" : "not "));
232 /* put the port in the correct location in internal data structure */
233 info->buddy.ext_port = msg.ext_port;
235 /* here there is a deviation from the normal receive-do-send format
236 * of peer_fsm functions. go to the next state based on if the bday
237 * paradox is needed */
239 if (msg.bday == COMM_BDAY_NEEDED) {
240 /* the birthday paradox is needed */
241 if (info->port_alloc.method == COMM_PORT_ALLOC_SEQ) {
242 /* the peer is sequential and needs to helper predicte
243 * the buddy port */
244 CHECK_FAILED(peer_fsm_reply_bday(info),
245 ERROR_CALLED_FUNCTION);
247 else {
248 /* the peer is random is needs to use bday paradox to
249 * determine it's port */
250 CHECK_FAILED(peer_fsm_start_bday(info),
251 ERROR_CALLED_FUNCTION_1);
254 else {
255 DEBUG(DBG_PROTOCOL,"PROTOCOL:straight connection will work\n");
256 /* a straight connection will work */
257 CHECK_FAILED(peer_fsm_start_direct_conn(info),
258 ERROR_CALLED_FUNCTION);
261 DBG_TIME("time at end of function");
263 return SUCCESS;
266 errorcode peer_fsm_start_direct_conn(peer_conn_info_t *info) {
268 /* declare local variables */
269 comm_msg_buddy_syn_seq_t msg;
271 /* error check arguments */
272 CHECK_FAILED(info,ERROR_NULL_ARG_1);
274 /* do function */
275 DBG_TIME("time at start of function");
277 CHECK_FAILED(start_direct_conn(info),ERROR_CALLED_FUNCTION_1);
278 DEBUG(DBG_BDAY,"BDAY:started direct connection\n");
279 CHECK_FAILED(capture_peer_to_buddy_syn(info),ERROR_CALLED_FUNCTION_2);
281 /* the syn has been found, send it to the helper */
282 msg.seq_num = info->buddy_syn.seq_num;
283 DEBUG(DBG_VERBOSE,"VERBOSE:sequence number of buddy syn is %u\n",
284 DBG_SEQ_NUM(msg.seq_num));
286 /* send message */
287 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_BUDDY_SYN_SEQ,
288 &msg,sizeof(msg)),ERROR_NETWORK_SEND);
289 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent BUDDY_SYN_SEQ message\n");
291 /* enter the next state */
292 CHECK_FAILED(peer_fsm_forge_syn_ack(info),ERROR_CALLED_FUNCTION_3);
294 DBG_TIME("time at end of function");
296 return SUCCESS;
299 errorcode peer_fsm_forge_syn_ack(peer_conn_info_t *info) {
301 /* declare local variables */
302 comm_msg_peer_syn_seq_t peer_syn_msg;
303 comm_msg_goodbye_t goodbye;
305 /* error check arguments */
306 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
308 /* do function */
309 DBG_TIME("time at start of function");
311 /* receive the sequence number to base SYN/ACK on */
312 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_PEER_SYN_SEQ,
313 &peer_syn_msg,sizeof(peer_syn_msg)),ERROR_NETWORK_READ);
314 DEBUG(DBG_PROTOCOL,"PROTOCOL:received PEER_SYN_SEQ\n");
316 /* fill in info about syn/ack to forge - almost a straight copy of
317 * previous captured syn - just set ACK flag and fill in ack num */
318 info->buddy_syn_ack.d_addr = info->buddy_syn.d_addr;
319 info->buddy_syn_ack.s_addr = info->buddy_syn.s_addr;
320 info->buddy_syn_ack.d_port = info->buddy_syn.d_port;
321 info->buddy_syn_ack.s_port = info->buddy_syn.s_port;
322 info->buddy_syn_ack.seq_num = info->buddy_syn.seq_num;
323 info->buddy_syn_ack.ack_num = SEQ_NUM_ADD(peer_syn_msg.seq_num,1);
324 info->buddy_syn_ack.window = info->buddy_syn.window;
325 info->buddy_syn_ack.ack_flag = FLAG_SET;
326 info->buddy_syn_ack.syn_flag = FLAG_SET;
328 /* forge the SYN/ACK */
329 CHECK_FAILED(spoof(&info->buddy_syn_ack,info->device,NULL,0,TTL_OK),
330 ERROR_CALLED_FUNCTION);
331 DEBUG(DBG_VERBOSE,"VERBOSE:forged SYN/ACK to buddy\n");
333 /* now just wait to success (hopefully) */
334 CHECK_FAILED(wait_for_direct_conn(&info->direct_conn_status),
335 ERROR_1);
337 DEBUG(DBG_VERBOSE,"VERBOSE:connection attempt was %ssuccessful\n",
338 ((info->direct_conn_status==FLAG_SUCCESS) ? "" : "not "));
340 /* send confirmation to helper that connection succeeded/failed */
341 goodbye.success_or_failure = info->direct_conn_status;
342 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_GOODBYE,&goodbye,
343 sizeof(goodbye)),ERROR_NETWORK_SEND);
344 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent GOODBYE\n");
346 DBG_TIME("time at end of function");
348 /* DONE!!! */
349 if (info->direct_conn_status == FLAG_FAILED)
350 return ERROR_2;
351 else
352 return SUCCESS;
355 errorcode peer_fsm_start_bday(peer_conn_info_t *info) {
357 /* declare local variables */
358 comm_msg_syn_flooded_t msg;
359 tcp_packet_info_t skeleton;
361 /* error check arguments */
362 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
364 /* do function */
366 DBG_TIME("time at start of function");
368 /* seed random sequence number */
369 srand(time(NULL));
371 /* create tcp skeleton */
372 DEBUG(DBG_BDAY,"BDAY:buddy external port = %u\n",
373 DBG_PORT(info->buddy.ext_port));
374 skeleton.d_addr = info->buddy.ext_ip;
375 skeleton.d_port = info->buddy.ext_port;
376 skeleton.s_addr = info->peer.ip;
377 skeleton.seq_num = (seq_num_t) rand();
379 /* do flooding */
380 DBG_TIME("starting SYN flood");
381 CHECK_FAILED(flood_syns(skeleton,info->device),ERROR_1);
382 DBG_TIME("finished SYN flood");
384 /* start looking for the SYN/ACK */
385 CHECK_FAILED(start_find_synack(info),ERROR_2);
387 /* create message to send */
388 msg.seq_num = skeleton.seq_num;
390 /* send msg */
391 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_SYN_FLOODED,&msg,
392 sizeof(msg)), ERROR_NETWORK_SEND);
393 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent SYN_FLOODED\n");
395 /* enter next state */
396 CHECK_FAILED(peer_fsm_end_bday(info),ERROR_CALLED_FUNCTION);
398 DBG_TIME("time st end of function");
400 return SUCCESS;
403 errorcode peer_fsm_end_bday(peer_conn_info_t *info) {
405 /* declare local variables */
406 comm_msg_bday_success_port_t msg;
407 /* error check arguments */
408 CHECK_FAILED(info,ERROR_NULL_ARG_1);
410 /* do function */
412 DBG_TIME("time at start of function");
414 /* receive message */
415 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_BUDDY_SYN_ACK_FLOODED,
416 NULL,0),ERROR_NETWORK_READ);
417 DEBUG(DBG_PROTOCOL,"PROTOCOL:received BUDDY_SYN_ACK_FLOODED\n");
419 DBG_TIME("waiting for SYNACK flood");
420 CHECK_FAILED(wait_and_join_find_synack(info),ERROR_1);
421 DEBUG(DBG_BDAY,"BDAY:the synack flood was received\n");
422 DBG_TIME("done waiting for SYNACK flood");
424 /* fill in the message */
425 msg.port = info->bday.port;
427 DEBUG((DBG_VERBOSE|DBG_BDAY),"VERBOSE|BDAY:bday success port = %u\n",
428 DBG_PORT(info->bday.port));
430 /* send the message */
431 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_BDAY_SUCCESS_PORT,
432 &msg,sizeof(msg)),ERROR_NETWORK_SEND);
433 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent BDAY_SUCCESS_PORT\n");
435 /* fill in the peer internal port location with the new internal port
436 * since the direct connection needs to know what it is */
437 info->peer.port = info->bday.port;
439 /* enter the next state */
440 /* the next state is recursive, go back and receive another message
441 * with the buddy's port, and then continue with full knowledge */
442 CHECK_FAILED(peer_fsm_buddy_port(info),ERROR_CALLED_FUNCTION);
444 DBG_TIME("time at end of function");
446 return SUCCESS;
450 errorcode peer_fsm_reply_bday(peer_conn_info_t *info) {
452 /* declare local variables */
454 /* error check arguments */
455 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
457 /* do function */
458 DBG_TIME("time at start of function");
460 CHECK_FAILED(sendMsg(info->socks.helper,
461 COMM_MSG_WAITING_TO_SYN_ACK_FLOOD,NULL,0),ERROR_NETWORK_SEND);
462 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent WAITING_TO_SYN_ACK_FLOOD\n");
464 /* enter next state */
465 CHECK_FAILED(peer_fsm_bday_synack_flood(info),ERROR_CALLED_FUNCTION);
467 DBG_TIME("time at end of function");
469 return SUCCESS;
472 errorcode peer_fsm_bday_synack_flood(peer_conn_info_t *info) {
474 /* declare local variables */
475 comm_msg_syn_ack_flood_seq_num_t msg;
477 /* error check arguments */
478 CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
480 /* do function */
481 DBG_TIME("time at start of function");
483 /* receive the message telling the peer to do the bday synack flood */
484 CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_SYN_ACK_FLOOD_SEQ_NUM,
485 &msg,sizeof(msg)),ERROR_NETWORK_READ);
486 DEBUG(DBG_PROTOCOL,"PROTOCOL:received SYN_ACK_FLOOD_SEQ_NUM\n");
488 /* do the synack flood */
489 DBG_TIME("starting SYNACK flood");
490 CHECK_FAILED(synack_flood(info,msg.seq_num),ERROR_1);
491 DBG_TIME("finished SYNACK flood");
493 /* send a message indicating the flood happened */
494 CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_SYN_ACK_FLOOD_DONE,
495 NULL,0),ERROR_NETWORK_SEND);
496 DEBUG(DBG_PROTOCOL,"PROTOCOL:sent SYN_ACK_FLOOD_DONE\n");
498 /* enter the next state */
499 /* this is recursive, go expect another message with the buddy's
500 * port information */
501 CHECK_FAILED(peer_fsm_buddy_port(info),ERROR_CALLED_FUNCTION);
503 DBG_TIME("time at end of function");
504 return SUCCESS;