1 /*****************************************************************************
2 * Copyright 2005 Daniel Ferullo *
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 *
8 * http://www.apache.org/licenses/LICENSE-2.0 *
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. *
16 *****************************************************************************/
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?
31 #include "peerfsm_private.h"
33 #include "directconn.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");
63 errorcode
peer_fsm_hello(peer_conn_info_t
*info
) {
65 /* declare local variables */
68 /* error check arguments */
69 CHECK_NOT_NULL(info
,ERROR_NULL_ARG_1
);
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
));
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");
92 CHECK_FAILED(peer_fsm_conn_again(info
),ERROR_CALLED_FUNCTION
);
94 DBG_TIME("time at end of function");
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
);
107 DBG_TIME("time at start of function");
110 CHECK_FAILED(readMsg(info
->socks
.helper
,COMM_MSG_CONNECT_AGAIN
,NULL
,0),
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
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");
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
);
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");
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
);
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");
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
);
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
244 CHECK_FAILED(peer_fsm_reply_bday(info
),
245 ERROR_CALLED_FUNCTION
);
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
);
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");
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
);
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
));
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");
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
);
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
),
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");
349 if (info
->direct_conn_status
== FLAG_FAILED
)
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
);
366 DBG_TIME("time at start of function");
368 /* seed random sequence number */
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();
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
;
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");
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
);
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");
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
);
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");
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
);
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");