Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

peerfsm.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Copyright 2005 Daniel Ferullo                                             *
00003  *                                                                           *
00004  * Licensed under the Apache License, Version 2.0 (the "License");           *
00005  * you may not use this file except in compliance with the License.          *
00006  * You may obtain a copy of the License at                                   *
00007  *                                                                           *
00008  *    http://www.apache.org/licenses/LICENSE-2.0                             *
00009  *                                                                           *
00010  * Unless required by applicable law or agreed to in writing, software       *
00011  * distributed under the License is distributed on an "AS IS" BASIS,         *
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00013  * See the License for the specific language governing permissions and       *
00014  * limitations under the License.                                            *
00015  *                                                                           *
00016  *****************************************************************************/
00017 
00018 /**
00019  * @file peerfsm.c
00020  * @author Daniel Ferullo (ferullo@cmu.edu)
00021  *
00022  * @brief contains defintions of fsm-like functions to control peer connection
00023  *        protocol control flow.
00024  *
00025  * @bug peer_fsm_forge_syn_ack only forges one SYN/ACK.  Because network could
00026  *      be lossy, maybe send more than one?
00027  */
00028 
00029 
00030 #include "peerfsm.h"
00031 #include "peerfsm_private.h"
00032 #include "peercon.h"
00033 #include "directconn.h"
00034 #include "nethelp.h"
00035 #include "netio.h"
00036 #include "comm.h"
00037 #include "debug.h"
00038 #include "sniff.h"
00039 #include "spoof.h"
00040 #include <time.h>
00041 #include <stdlib.h>
00042 
00043 errorcode peer_fsm_start(peer_conn_info_t *info) {
00044 
00045         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00046 
00047         DBG_TIME("time at start of fsm");
00048 
00049         /* create the tcp connection to the helper */
00050         CHECK_FAILED(tcp_connect(info->helper.ip,info->helper.port,
00051                                  &(info->socks.helper)),ERROR_TCP_CONNECT);
00052 
00053 
00054         /* move into the hello state */
00055         CHECK_FAILED(peer_fsm_hello(info),ERROR_CALLED_FUNCTION);
00056 
00057         DBG_TIME("time at end of fsm");
00058 
00059         return SUCCESS;
00060 
00061 }
00062 
00063 errorcode peer_fsm_hello(peer_conn_info_t *info) {
00064 
00065         /* declare local variables */
00066         comm_msg_hello_t msg;
00067 
00068         /* error check arguments */
00069         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00070 
00071         /* do function */
00072 
00073         DBG_TIME("time at start of function");
00074 
00075         /* create the message payload... */
00076         msg.peer_ip         = info->peer.ip;
00077         msg.peer_port       = info->peer.port;
00078         msg.buddy_int_ip    = info->buddy.int_ip;
00079         msg.buddy_int_port  = info->buddy.int_port;
00080         msg.buddy_ext_ip    = info->buddy.ext_ip;
00081 
00082         DEBUG(DBG_BDAY,"BDAY: peer internal port: %u\n",
00083                 DBG_PORT(info->peer.port));
00084 
00085         /* ...and send it */
00086         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_HELLO,&msg,
00087                              sizeof(msg)),ERROR_NETWORK_SEND);
00088 
00089         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent HELLO\n");
00090 
00091         /* call next state */
00092         CHECK_FAILED(peer_fsm_conn_again(info),ERROR_CALLED_FUNCTION);
00093 
00094         DBG_TIME("time at end of function");
00095 
00096         return SUCCESS;
00097 }
00098 
00099 errorcode peer_fsm_conn_again(peer_conn_info_t *info) {
00100 
00101         /* declare variables */
00102 
00103         /* error check arguments */
00104         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00105 
00106         /* do function */
00107         DBG_TIME("time at start of function");
00108 
00109         /* get message */
00110         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_CONNECT_AGAIN,NULL,0),
00111                 ERROR_NETWORK_READ);
00112 
00113         DEBUG(DBG_PROTOCOL,"PROTOCOL:received CONNECT_AGAIN\n");
00114 
00115         /* open a second connection */
00116         CHECK_FAILED(tcp_connect(info->helper.ip,info->helper.port,
00117                         &(info->socks.helper_pred)),ERROR_TCP_CONNECT);
00118 
00119         /* send a message indicating that the second connection has
00120          * been made */
00121         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_CONNECTED_AGAIN,
00122                         NULL,0),ERROR_NETWORK_SEND);
00123 
00124         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent CONNECTED_AGAIN\n");
00125 
00126         /* enter next state */
00127         if (FAILED(peer_fsm_check_port_pred(info))) {
00128                 /* close the second connection socket */
00129                 close(info->socks.helper_pred);
00130                 return ERROR_CALLED_FUNCTION;
00131         }
00132 
00133         /* close the second connection */
00134         close(info->socks.helper_pred);
00135 
00136         DBG_TIME("time at end of function");
00137 
00138         return SUCCESS;
00139 }
00140 
00141 errorcode peer_fsm_check_port_pred(peer_conn_info_t *info) {
00142 
00143         /* declare local variables */
00144         comm_msg_pred_port_t msg;
00145 
00146         /* error check arguments */
00147         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00148 
00149         /* do function */
00150         DBG_TIME("time at start of function");
00151 
00152         /* read the next message */
00153         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_PORT_PRED,
00154                         &msg,sizeof(comm_msg_pred_port_t)),ERROR_NETWORK_READ);
00155 
00156         info->port_alloc.method = msg.port_alloc;
00157 
00158         DEBUG(DBG_PROTOCOL,"PROTOCOL:received PORT_PRED\n");
00159         DEBUG(DBG_VERBOSE,"VERBOSE:alloc method = %s\n",
00160                 (info->port_alloc.method==COMM_PORT_ALLOC_SEQ) ?
00161                 "sequential" : "random" );
00162 
00163         /* send message saying waiting for buddy information from helper  */
00164         CHECK_FAILED(sendMsg(info->socks.helper,
00165                 COMM_MSG_WAITING_FOR_BUDDY_ALLOC, NULL, 0),ERROR_NETWORK_SEND);
00166 
00167         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent WAITING_FOR_BUDDY_ALLOC\n");
00168         /* enter next state */
00169         CHECK_FAILED(peer_fsm_buddy_alloc(info),ERROR_CALLED_FUNCTION);
00170 
00171         DBG_TIME("time at end of function");
00172 
00173         return SUCCESS;
00174 
00175 }
00176 
00177 errorcode peer_fsm_buddy_alloc(peer_conn_info_t *info) {
00178 
00179         /* declare local variables */
00180         comm_msg_buddy_alloc_t buddy;
00181 
00182         /* error check arguments */
00183         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00184 
00185         /* do function */
00186         DBG_TIME("time at start of function");
00187 
00188         /* receive the buddy info */
00189         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_BUDDY_ALLOC,
00190                 &buddy,sizeof(buddy)),ERROR_NETWORK_READ);
00191 
00192         DEBUG(DBG_PROTOCOL,"PROTOCOL:received BUDDY_ALLOC\n");
00193         DEBUG(DBG_VERBOSE,"VERBOSE:buddy alloc method: %s\n",
00194                 (buddy.buddy_port_alloc==COMM_PORT_ALLOC_SEQ
00195                         ? "sequential" : "random" ));
00196         DEBUG(DBG_VERBOSE,"VERBOSE:connection is %ssupported\n",
00197                 (buddy.support==COMM_CONNECTION_SUPPORTED ? "" : "not "));
00198 
00199 
00200         /* send a message asking for the buddy's external port */
00201         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_WAITING_FOR_BUDDY_PORT,
00202                 NULL,0),ERROR_NETWORK_SEND);
00203         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent WAITING_FOR_BUDDY_PORT\n");
00204 
00205         /* enter next state */
00206         CHECK_FAILED(peer_fsm_buddy_port(info),ERROR_CALLED_FUNCTION);
00207 
00208         DBG_TIME("time at end of function");
00209 
00210         return SUCCESS;
00211 }
00212 
00213 errorcode peer_fsm_buddy_port(peer_conn_info_t *info) {
00214 
00215         /* declare local variables */
00216         comm_msg_buddy_port_t msg;
00217 
00218         /* error check arguments */
00219         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00220 
00221         /* do function */
00222         DBG_TIME("time at start of function");
00223 
00224         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_BUDDY_PORT,&msg,
00225                 sizeof(msg)),ERROR_NETWORK_READ);
00226         DEBUG(DBG_PROTOCOL,"PROTOCOL:received BUDDY_PORT\n");
00227         DEBUG(DBG_VERBOSE,"VERBOSE:buddy port = %d\n",
00228                 DBG_PORT(msg.ext_port));
00229         DEBUG(DBG_VERBOSE,"VERBOSE:bday is %sneeded\n",
00230                 (msg.bday == COMM_BDAY_NEEDED ? "" : "not "));
00231 
00232         /* put the port in the correct location in internal data structure */
00233         info->buddy.ext_port = msg.ext_port;
00234 
00235         /* here there is a deviation from the normal receive-do-send format
00236          * of peer_fsm functions.  go to the next state based on if the bday
00237          * paradox is needed */
00238 
00239         if (msg.bday == COMM_BDAY_NEEDED)       {
00240                 /* the birthday paradox is needed */
00241                 if (info->port_alloc.method == COMM_PORT_ALLOC_SEQ) {
00242                         /* the peer is sequential and needs to helper predicte
00243                          * the buddy port */
00244                         CHECK_FAILED(peer_fsm_reply_bday(info),
00245                                 ERROR_CALLED_FUNCTION);
00246                 }
00247                 else {
00248                         /* the peer is random is needs to use bday paradox to
00249                          * determine it's port */
00250                         CHECK_FAILED(peer_fsm_start_bday(info),
00251                                 ERROR_CALLED_FUNCTION_1);
00252                 }
00253         }
00254         else {
00255                 DEBUG(DBG_PROTOCOL,"PROTOCOL:straight connection will work\n");
00256                 /* a straight connection will work */
00257                 CHECK_FAILED(peer_fsm_start_direct_conn(info),
00258                         ERROR_CALLED_FUNCTION);
00259         }
00260 
00261         DBG_TIME("time at end of function");
00262 
00263         return SUCCESS;
00264 }
00265 
00266 errorcode peer_fsm_start_direct_conn(peer_conn_info_t *info) {
00267 
00268         /* declare local variables */
00269         comm_msg_buddy_syn_seq_t msg;
00270 
00271         /* error check arguments */
00272         CHECK_FAILED(info,ERROR_NULL_ARG_1);
00273 
00274         /* do function */
00275         DBG_TIME("time at start of function");
00276 
00277         CHECK_FAILED(start_direct_conn(info),ERROR_CALLED_FUNCTION_1);
00278         DEBUG(DBG_BDAY,"BDAY:started direct connection\n");
00279         CHECK_FAILED(capture_peer_to_buddy_syn(info),ERROR_CALLED_FUNCTION_2);
00280 
00281         /* the syn has been found, send it to the helper */
00282         msg.seq_num = info->buddy_syn.seq_num;
00283         DEBUG(DBG_VERBOSE,"VERBOSE:sequence number of buddy syn is %u\n",
00284                 DBG_SEQ_NUM(msg.seq_num));
00285 
00286         /* send message */
00287         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_BUDDY_SYN_SEQ,
00288                 &msg,sizeof(msg)),ERROR_NETWORK_SEND);
00289         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent BUDDY_SYN_SEQ message\n");
00290 
00291         /* enter the next state */
00292         CHECK_FAILED(peer_fsm_forge_syn_ack(info),ERROR_CALLED_FUNCTION_3);
00293 
00294         DBG_TIME("time at end of function");
00295 
00296         return SUCCESS;
00297 }
00298 
00299 errorcode peer_fsm_forge_syn_ack(peer_conn_info_t *info) {
00300 
00301         /* declare local variables */
00302         comm_msg_peer_syn_seq_t peer_syn_msg;
00303         comm_msg_goodbye_t goodbye;
00304 
00305         /* error check arguments */
00306         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00307 
00308         /* do function */
00309         DBG_TIME("time at start of function");
00310 
00311         /* receive the sequence number to base SYN/ACK on */
00312         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_PEER_SYN_SEQ,
00313                 &peer_syn_msg,sizeof(peer_syn_msg)),ERROR_NETWORK_READ);
00314         DEBUG(DBG_PROTOCOL,"PROTOCOL:received PEER_SYN_SEQ\n");
00315 
00316         /* fill in info about syn/ack to forge - almost a straight copy of
00317          * previous captured syn - just set ACK flag and fill in ack num */
00318         info->buddy_syn_ack.d_addr   = info->buddy_syn.d_addr;
00319         info->buddy_syn_ack.s_addr   = info->buddy_syn.s_addr;
00320         info->buddy_syn_ack.d_port   = info->buddy_syn.d_port;
00321         info->buddy_syn_ack.s_port   = info->buddy_syn.s_port;
00322         info->buddy_syn_ack.seq_num  = info->buddy_syn.seq_num;
00323         info->buddy_syn_ack.ack_num  = SEQ_NUM_ADD(peer_syn_msg.seq_num,1);
00324         info->buddy_syn_ack.window   = info->buddy_syn.window;
00325         info->buddy_syn_ack.ack_flag = FLAG_SET;
00326         info->buddy_syn_ack.syn_flag = FLAG_SET;
00327 
00328         /* forge the SYN/ACK */
00329         CHECK_FAILED(spoof(&info->buddy_syn_ack,info->device,NULL,0,TTL_OK),
00330                 ERROR_CALLED_FUNCTION);
00331         DEBUG(DBG_VERBOSE,"VERBOSE:forged SYN/ACK to buddy\n");
00332 
00333         /* now just wait to success (hopefully) */
00334         CHECK_FAILED(wait_for_direct_conn(&info->direct_conn_status),
00335                 ERROR_1);
00336 
00337         DEBUG(DBG_VERBOSE,"VERBOSE:connection attempt was %ssuccessful\n",
00338                 ((info->direct_conn_status==FLAG_SUCCESS) ? "" : "not "));
00339 
00340         /* send confirmation to helper that connection succeeded/failed */
00341         goodbye.success_or_failure = info->direct_conn_status;
00342         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_GOODBYE,&goodbye,
00343                 sizeof(goodbye)),ERROR_NETWORK_SEND);
00344         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent GOODBYE\n");
00345 
00346         DBG_TIME("time at end of function");
00347 
00348         /* DONE!!! */
00349         if (info->direct_conn_status == FLAG_FAILED)
00350                 return ERROR_2;
00351         else
00352                 return SUCCESS;
00353 }
00354 
00355 errorcode peer_fsm_start_bday(peer_conn_info_t *info) {
00356 
00357         /* declare local variables */
00358         comm_msg_syn_flooded_t msg;
00359         tcp_packet_info_t skeleton;
00360 
00361         /* error check arguments */
00362         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00363 
00364         /* do function */
00365 
00366         DBG_TIME("time at start of function");
00367 
00368         /* seed random sequence number */
00369         srand(time(NULL));
00370 
00371         /* create tcp skeleton */
00372         DEBUG(DBG_BDAY,"BDAY:buddy external port = %u\n",
00373                 DBG_PORT(info->buddy.ext_port));
00374         skeleton.d_addr = info->buddy.ext_ip;
00375         skeleton.d_port = info->buddy.ext_port;
00376         skeleton.s_addr = info->peer.ip;
00377         skeleton.seq_num = (seq_num_t) rand();
00378 
00379         /* do flooding */
00380         DBG_TIME("starting SYN flood");
00381         CHECK_FAILED(flood_syns(skeleton,info->device),ERROR_1);
00382         DBG_TIME("finished SYN flood");
00383 
00384         /* start looking for the SYN/ACK */
00385         CHECK_FAILED(start_find_synack(info),ERROR_2);
00386 
00387         /* create message to send */
00388         msg.seq_num = skeleton.seq_num;
00389 
00390         /* send msg */
00391         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_SYN_FLOODED,&msg,
00392                 sizeof(msg)), ERROR_NETWORK_SEND);
00393         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent SYN_FLOODED\n");
00394 
00395         /* enter next state */
00396         CHECK_FAILED(peer_fsm_end_bday(info),ERROR_CALLED_FUNCTION);
00397 
00398         DBG_TIME("time st end of function");
00399 
00400         return SUCCESS;
00401 }
00402 
00403 errorcode peer_fsm_end_bday(peer_conn_info_t *info) {
00404 
00405         /* declare local variables */
00406         comm_msg_bday_success_port_t msg;
00407         /* error check arguments */
00408         CHECK_FAILED(info,ERROR_NULL_ARG_1);
00409 
00410         /* do function */
00411 
00412         DBG_TIME("time at start of function");
00413 
00414         /* receive message */
00415         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_BUDDY_SYN_ACK_FLOODED,
00416                 NULL,0),ERROR_NETWORK_READ);
00417         DEBUG(DBG_PROTOCOL,"PROTOCOL:received BUDDY_SYN_ACK_FLOODED\n");
00418 
00419         DBG_TIME("waiting for SYNACK flood");
00420         CHECK_FAILED(wait_and_join_find_synack(info),ERROR_1);
00421         DEBUG(DBG_BDAY,"BDAY:the synack flood was received\n");
00422         DBG_TIME("done waiting for SYNACK flood");
00423 
00424         /* fill in the message */
00425         msg.port = info->bday.port;
00426 
00427         DEBUG((DBG_VERBOSE|DBG_BDAY),"VERBOSE|BDAY:bday success port = %u\n",
00428                 DBG_PORT(info->bday.port));
00429 
00430         /* send the message */
00431         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_BDAY_SUCCESS_PORT,
00432                 &msg,sizeof(msg)),ERROR_NETWORK_SEND);
00433         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent BDAY_SUCCESS_PORT\n");
00434 
00435         /* fill in the peer internal port location with the new internal port
00436          * since the direct connection needs to know what it is */
00437         info->peer.port = info->bday.port;
00438 
00439         /* enter the next state */
00440         /* the next state is recursive, go back and receive another message
00441          * with the buddy's port, and then continue with full knowledge */
00442         CHECK_FAILED(peer_fsm_buddy_port(info),ERROR_CALLED_FUNCTION);
00443 
00444         DBG_TIME("time at end of function");
00445 
00446         return SUCCESS;
00447 
00448 }
00449 
00450 errorcode peer_fsm_reply_bday(peer_conn_info_t *info) {
00451 
00452         /* declare local variables */
00453 
00454         /* error check arguments */
00455         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00456 
00457         /* do function */
00458         DBG_TIME("time at start of function");
00459 
00460         CHECK_FAILED(sendMsg(info->socks.helper,
00461                 COMM_MSG_WAITING_TO_SYN_ACK_FLOOD,NULL,0),ERROR_NETWORK_SEND);
00462         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent WAITING_TO_SYN_ACK_FLOOD\n");
00463 
00464         /* enter next state */
00465         CHECK_FAILED(peer_fsm_bday_synack_flood(info),ERROR_CALLED_FUNCTION);
00466 
00467         DBG_TIME("time at end of function");
00468 
00469         return SUCCESS;
00470 }
00471 
00472 errorcode peer_fsm_bday_synack_flood(peer_conn_info_t *info) {
00473 
00474         /* declare local variables */
00475         comm_msg_syn_ack_flood_seq_num_t msg;
00476 
00477         /* error check arguments */
00478         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00479 
00480         /* do function */
00481         DBG_TIME("time at start of function");
00482 
00483         /* receive the message telling the peer to do the bday synack flood */
00484         CHECK_FAILED(readMsg(info->socks.helper,COMM_MSG_SYN_ACK_FLOOD_SEQ_NUM,
00485                 &msg,sizeof(msg)),ERROR_NETWORK_READ);
00486         DEBUG(DBG_PROTOCOL,"PROTOCOL:received SYN_ACK_FLOOD_SEQ_NUM\n");
00487 
00488         /* do the synack flood */
00489         DBG_TIME("starting SYNACK flood");
00490         CHECK_FAILED(synack_flood(info,msg.seq_num),ERROR_1);
00491         DBG_TIME("finished SYNACK flood");
00492 
00493         /* send a message indicating the flood happened */
00494         CHECK_FAILED(sendMsg(info->socks.helper,COMM_MSG_SYN_ACK_FLOOD_DONE,
00495                 NULL,0),ERROR_NETWORK_SEND);
00496         DEBUG(DBG_PROTOCOL,"PROTOCOL:sent SYN_ACK_FLOOD_DONE\n");
00497 
00498         /* enter the next state */
00499         /* this is recursive, go expect another message with the buddy's
00500          * port information */
00501         CHECK_FAILED(peer_fsm_buddy_port(info),ERROR_CALLED_FUNCTION);
00502 
00503         DBG_TIME("time at end of function");
00504         return SUCCESS;
00505 }
00506 

Generated on Wed Mar 30 23:20:47 2005 for NATBLASTER by  doxygen 1.3.9.1