Example #1
0
/**
 * \brief Specifies an interface to use for sending.
 *
 * You may call this up to two (2) times with different interfaces
 * when using a tcpprep cache file or dualfile mode.  Note, both interfaces
 * must use the same DLT type
 */
int
tcpreplay_set_interface(tcpreplay_t *ctx, tcpreplay_intf intf, char *value)
{
    static int int1dlt = -1, int2dlt = -1;
    char *intname;
    char ebuf[SENDPACKET_ERRBUF_SIZE];

    assert(ctx);
    assert(value);

    if (intf == intf1) {
        if ((intname = get_interface(ctx->intlist, value)) == NULL) {
            tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", value);
            return -1;
        }

        ctx->options->intf1_name = safe_strdup(intname);

        /* open interfaces for writing */
        if ((ctx->intf1 = sendpacket_open(ctx->options->intf1_name, ebuf, TCPR_DIR_C2S)) == NULL) {
            tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf1_name, ebuf);
            return -1;
        }

        int1dlt = sendpacket_get_dlt(ctx->intf1);
    } else if (intf == intf2) {
        if ((intname = get_interface(ctx->intlist, value)) == NULL) {
            tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", ctx->options->intf2_name);
            return -1;
        }

        ctx->options->intf2_name = safe_strdup(intname);

        /* open interface for writing */
        if ((ctx->intf2 = sendpacket_open(ctx->options->intf2_name, ebuf, TCPR_DIR_S2C)) == NULL) {
            tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf2_name, ebuf);
            return -1;
        }
        int2dlt = sendpacket_get_dlt(ctx->intf2);
    }

    /*
     * If both interfaces are selected, then make sure both interfaces use
     * the same DLT type
     */
    if (int1dlt != -1 && int2dlt != -1) {
        if (int1dlt != int2dlt) {
            tcpreplay_seterr(ctx, "DLT type missmatch for %s (%s) and %s (%s)", 
                ctx->options->intf1_name, pcap_datalink_val_to_name(int1dlt), 
                ctx->options->intf2_name, pcap_datalink_val_to_name(int2dlt));
            return -1;
        }
    }

    return 0;
}
Example #2
0
/**
 * \brief Does all the prep work before calling tcpreplay_replay()
 *
 * Technically this validates our config options, preloads the tcpprep
 * cache file, loads the packet cache and anything else which might
 * cause a delay for starting to send packets with tcpreplay_replay()
 */
int 
tcpreplay_prepare(tcpreplay_t *ctx)
{
    char *intname, ebuf[SENDPACKET_ERRBUF_SIZE];
    int int1dlt, int2dlt, i;

    assert(ctx);

    /*
     * First, process the validations, basically the same we do in 
     * tcpreplay_post_args() and AutoOpts
     */
    if (ctx->options->intf1_name == NULL) {
        tcpreplay_seterr(ctx, "%s", "You must specify at least one network interface");
        return -1;
    }

    if (ctx->options->source_cnt == 0) {
        tcpreplay_seterr(ctx, "%s", "You must specify at least one source pcap");
        return -1;
    }

    if (ctx->options->dualfile) {
        if (! ctx->options->source_cnt >= 2) {
            tcpreplay_seterr(ctx, "%s", "Dual file mode requires 2 or more pcap files");
            return -1;
        }

        if (ctx->options->source_cnt % 2 != 0) {
            tcpreplay_seterr(ctx, "%s", "Dual file mode requires an even number of pcap files");
            return -1;
        }
    }

    if (ctx->options->dualfile && ctx->options->cachedata != NULL) {
        tcpreplay_seterr(ctx, "%s", "Can't use dual file mode and tcpprep cache file together");
        return -1;
    }

    if ((ctx->options->dualfile || ctx->options->cachedata != NULL) && 
           ctx->options->intf2_name == NULL) {
        tcpreplay_seterr(ctx, "%s", "dual file mode and tcpprep cache files require two interfaces");
    }


#ifndef HAVE_SELECT
    if (ctx->options->accurate == accurate_select) {
        tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with select support");
        return -1;
    }
#endif
#ifndef HAVE_RDTSC
    if (ctx->options->accurate == accurate_rdtsc) {
        tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with rdtsc support");
        return -1;
    }
#else
    if (ctx->options->rdtsc_clicks > 0)
        rdtsc_calibrate(ctx->options->rdtsc_clicks);
#endif
#ifndef HAVE_IOPERM
    if (ctx->options->accurate == accurate_ioport) {
        tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with IO Port 0x80 support");
        return -1;
    }
#else
    if (ctx->options->accurate == accurate_ioport) {
        ioport_sleep_init();
    }
#endif
#ifndef HAVE_ABSOLUTE_TIME
    if (ctx->options->accurate == accurate_abs_time) {
        tcpreplay_seterr(ctx, "%s", "tcpreplay_api only supports absolute time on Apple OS X");
        return -1;
    }
#endif

    if ((intname = get_interface(ctx->intlist, ctx->options->intf1_name)) == NULL) {
        tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF1));
        return -1;
    }

    /* open interfaces for writing */
    if ((ctx->intf1 = sendpacket_open(ctx->options->intf1_name, ebuf, TCPR_DIR_C2S)) == NULL) {
        tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf1_name, ebuf);
        return -1;
    }

    int1dlt = sendpacket_get_dlt(ctx->intf1);

    if (ctx->options->intf2_name != NULL) {
        if ((intname = get_interface(ctx->intlist, ctx->options->intf2_name)) == NULL) {
            tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF2));
            return -1;
        }

        /* open interfaces for writing */
        if ((ctx->intf2 = sendpacket_open(ctx->options->intf2_name, ebuf, TCPR_DIR_C2S)) == NULL) {
            tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf2_name, ebuf);
            return -1;
        }

        int2dlt = sendpacket_get_dlt(ctx->intf2);
        if (int2dlt != int1dlt) {
            tcpreplay_seterr(ctx, "DLT type missmatch for %s (%s) and %s (%s)", 
                ctx->options->intf1_name, pcap_datalink_val_to_name(int1dlt), 
                ctx->options->intf2_name, pcap_datalink_val_to_name(int2dlt));
            return -1;
        }
    }

    /*
     * Setup up the file cache, if required
     */
    if (ctx->options->enable_file_cache && ctx->options->file_cache == NULL) {
        /* Initialise each of the file cache structures */
        for (i = 0; i < ctx->options->source_cnt; i++) {
            ctx->options->file_cache[i].index = i;
            ctx->options->file_cache[i].cached = FALSE;
            ctx->options->file_cache[i].packet_cache = NULL;
        }
    }

    return 0;
}
Example #3
0
void 
post_args(_U_ int argc, _U_ char *argv[])
{
    char ebuf[SENDPACKET_ERRBUF_SIZE];
    struct tcpr_ether_addr *eth_buff;
    char *intname;
    sendpacket_t *sp;
#ifdef ENABLE_PCAP_FINDALLDEVS
    interface_list_t *intlist = get_interface_list();
#else
    interface_list_t *intlist = NULL;
#endif
    
#ifdef DEBUG
    if (HAVE_OPT(DBUG))
        debug = OPT_VALUE_DBUG;
#else
    if (HAVE_OPT(DBUG))
        warn("not configured with --enable-debug.  Debugging disabled.");
#endif
    

#ifdef ENABLE_VERBOSE
    if (HAVE_OPT(VERBOSE))
        options.verbose = 1;
    
    if (HAVE_OPT(DECODE))
        options.tcpdump->args = safe_strdup(OPT_ARG(DECODE));
    
#endif

    if (HAVE_OPT(UNIDIR))
        options.unidir = 1;

    if (HAVE_OPT(LIMIT))
        options.limit_send = OPT_VALUE_LIMIT; /* default is -1 */


    if ((intname = get_interface(intlist, OPT_ARG(INTF1))) == NULL)
        errx(-1, "Invalid interface name/alias: %s", OPT_ARG(INTF1));
    
    options.intf1 = safe_strdup(intname);

    if (HAVE_OPT(INTF2)) {
        if ((intname = get_interface(intlist, OPT_ARG(INTF2))) == NULL)
            errx(-1, "Invalid interface name/alias: %s", OPT_ARG(INTF2));
    
        options.intf2 = safe_strdup(intname);
    }
    

    if (HAVE_OPT(MAC)) {
        int ct = STACKCT_OPT(MAC);
        char **list = STACKLST_OPT(MAC);
        int first = 1;
        do {
            char *p = *list++;
            if (first)
                mac2hex(p, (u_char *)options.intf1_mac, ETHER_ADDR_LEN);
            else
                mac2hex(p, (u_char *)options.intf2_mac, ETHER_ADDR_LEN);
            first = 0;
        } while (--ct > 0);
    }

    /* 
     * Figure out MAC addresses of sending interface(s)
     * if user doesn't specify MAC address on CLI, query for it 
     */
    if (memcmp(options.intf1_mac, "\00\00\00\00\00\00", ETHER_ADDR_LEN) == 0) {
        if ((sp = sendpacket_open(NULL, options.intf1, ebuf, TCPR_DIR_C2S)) == NULL)
            errx(-1, "Unable to open interface %s: %s", options.intf1, ebuf);

        if ((eth_buff = sendpacket_get_hwaddr(sp)) == NULL) {
            warnx("Unable to get MAC address: %s", sendpacket_geterr(sp));
            err(-1, "Please consult the man page for using the -M option.");
        }
        sendpacket_close(sp);
        memcpy(options.intf1_mac, eth_buff, ETHER_ADDR_LEN);
    }

    if (memcmp(options.intf2_mac, "\00\00\00\00\00\00", ETHER_ADDR_LEN) == 0) {
        if ((sp = sendpacket_open(NULL, options.intf2, ebuf, TCPR_DIR_S2C)) == NULL)
            errx(-1, "Unable to open interface %s: %s", options.intf2, ebuf);

        if ((eth_buff = sendpacket_get_hwaddr(sp)) == NULL) {
            warnx("Unable to get MAC address: %s", sendpacket_geterr(sp));
            err(-1, "Please consult the man page for using the -M option.");
        }
        sendpacket_close(sp);
        memcpy(options.intf2_mac, eth_buff, ETHER_ADDR_LEN);        
    }

    /* 
     * Open interfaces for sending & receiving 
     */
    if ((options.pcap1 = pcap_open_live(options.intf1, options.snaplen, 
                                          options.promisc, options.to_ms, ebuf)) == NULL)
        errx(-1, "Unable to open interface %s: %s", options.intf1, ebuf);


    if (strcmp(options.intf1, options.intf2) == 0)
        errx(-1, "Whoa tiger!  You don't want to use %s twice!", options.intf1);


    /* we always have to open the other pcap handle to send, but we may not listen */
    if ((options.pcap2 = pcap_open_live(options.intf2, options.snaplen,
                                          options.promisc, options.to_ms, ebuf)) == NULL)
        errx(-1, "Unable to open interface %s: %s", options.intf2, ebuf);
    
    /* poll should be -1 to wait indefinitely */
    options.poll_timeout = -1;
}
Example #4
0
/**
 * \brief Parses the GNU AutoOpts options for tcpreplay
 *
 * If you're using AutoOpts with tcpreplay_api, then just call this after
 * optionProcess() and it will parse all the options for you.  As always,
 * returns 0 on success, and -1 on error & -2 on warning.
 */
int
tcpreplay_post_args(tcpreplay_t *ctx, int argc)
{
    char *temp, *intname;
    char ebuf[SENDPACKET_ERRBUF_SIZE];
    int int1dlt, int2dlt;
    tcpreplay_opt_t *options;
    int warn = 0;

#ifdef USE_AUTOOPTS
    options = ctx->options;

#ifdef DEBUG
    if (HAVE_OPT(DBUG))
        debug = OPT_VALUE_DBUG;
#else
    if (HAVE_OPT(DBUG)) {
        warn ++;
        tcpreplay_setwarn(ctx, "%s", "not configured with --enable-debug.  Debugging disabled.");
    }
#endif

    options->loop = OPT_VALUE_LOOP;
    options->sleep_accel = OPT_VALUE_SLEEP_ACCEL;

    if (HAVE_OPT(LIMIT))
        options->limit_send = OPT_VALUE_LIMIT;

    if (HAVE_OPT(TOPSPEED)) {
        options->speed.mode = speed_topspeed;
        options->speed.speed = 0.0;
    } else if (HAVE_OPT(PPS)) {
        options->speed.mode = speed_packetrate;
        options->speed.speed = (float)OPT_VALUE_PPS;
        options->speed.pps_multi = OPT_VALUE_PPS_MULTI;
    } else if (HAVE_OPT(ONEATATIME)) {
        options->speed.mode = speed_oneatatime;
        options->speed.speed = 0.0;
    } else if (HAVE_OPT(MBPS)) {
        options->speed.mode = speed_mbpsrate;
        options->speed.speed = atof(OPT_ARG(MBPS));
    } else if (HAVE_OPT(MULTIPLIER)) {
        options->speed.mode = speed_multiplier;
        options->speed.speed = atof(OPT_ARG(MULTIPLIER));
    }

#ifdef ENABLE_VERBOSE
    if (HAVE_OPT(VERBOSE))
        options->verbose = 1;

    if (HAVE_OPT(DECODE))
        options->tcpdump->args = safe_strdup(OPT_ARG(DECODE));
#endif

    if (HAVE_OPT(STATS))
        options->stats = OPT_VALUE_STATS;

    /*
     * Check if the file cache should be enabled - if we're looping more than
     * once and the command line option has been spec'd
     */
    if (HAVE_OPT(ENABLE_FILE_CACHE) && (options->loop != 1)) {
        options->enable_file_cache = true;
    }

    /*
     * If we're preloading the pcap before the first run, then
     * we're forcing the file cache to be true
     */

    if (HAVE_OPT(PRELOAD_PCAP)) {
        options->preload_pcap = true;
        options->enable_file_cache = true;
    }

    /* Dual file mode */
    if (HAVE_OPT(DUALFILE)) {
        options->dualfile = true;
        if (argc < 2) {
            tcpreplay_seterr(ctx, "%s", "--dualfile mode requires at least two pcap files");
            return -1;
        }
        if (argc % 2 != 0) {
            tcpreplay_seterr(ctx, "%s", "--dualfile mode requires an even number of pcap files");
            return -1;
        }
    }


    if (HAVE_OPT(TIMER)) {
        if (strcmp(OPT_ARG(TIMER), "select") == 0) {
#ifdef HAVE_SELECT
            options->accurate = accurate_select;
#else
            tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with select support");
            return -1;
#endif
        } else if (strcmp(OPT_ARG(TIMER), "rdtsc") == 0) {
#ifdef HAVE_RDTSC
            options->accurate = accurate_rdtsc;
#else
            tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with rdtsc support");
            return -1;
#endif
        } else if (strcmp(OPT_ARG(TIMER), "ioport") == 0) {
#if defined HAVE_IOPERM && defined(__i386__)
            options->accurate = accurate_ioport;
            ioport_sleep_init();
#else
            tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with IO Port 0x80 support");
            return -1;
#endif
        } else if (strcmp(OPT_ARG(TIMER), "gtod") == 0) {
            options->accurate = accurate_gtod;
        } else if (strcmp(OPT_ARG(TIMER), "nano") == 0) {
            options->accurate = accurate_nanosleep;
        } else if (strcmp(OPT_ARG(TIMER), "abstime") == 0) {
#ifdef HAVE_ABSOLUTE_TIME
            options->accurate = accurate_abs_time;
            if  (!MPLibraryIsLoaded()) {
                tcpreplay_seterr(ctx, "%s", "The MP library did not load.\n");
                return -1;
            }
#else
            tcpreplay_seterr(ctx, "%s", "tcpreplay_api only supports absolute time on Apple OS X");
            return -1;
#endif
        } else {
            tcpreplay_seterr(ctx, "Unsupported timer mode: %s", OPT_ARG(TIMER));
            return -1;
        }
    }

#ifdef HAVE_RDTSC
    if (HAVE_OPT(RDTSC_CLICKS)) {
        rdtsc_calibrate(OPT_VALUE_RDTSC_CLICKS);
    }
#endif

    if (HAVE_OPT(PKTLEN)) {
        options->use_pkthdr_len = true;
        warn ++;
        tcpreplay_setwarn(ctx, "%s", "--pktlen may cause problems.  Use with caution.");
    }

    if ((intname = get_interface(ctx->intlist, OPT_ARG(INTF1))) == NULL) {
        tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF1));
        return -1;
    }

    options->intf1_name = safe_strdup(intname);

    /* open interfaces for writing */
    if ((ctx->intf1 = sendpacket_open(options->intf1_name, ebuf, TCPR_DIR_C2S)) == NULL) {
        tcpreplay_seterr(ctx, "Can't open %s: %s", options->intf1_name, ebuf);
        return -1;
    }

    int1dlt = sendpacket_get_dlt(ctx->intf1);

    if (HAVE_OPT(INTF2)) {
        if ((intname = get_interface(ctx->intlist, OPT_ARG(INTF2))) == NULL) {
            tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF2));
            return -1;
        }

        options->intf2_name = safe_strdup(intname);

        /* open interface for writing */
        if ((ctx->intf2 = sendpacket_open(options->intf2_name, ebuf, TCPR_DIR_S2C)) == NULL) {
            tcpreplay_seterr(ctx, "Can't open %s: %s", options->intf2_name, ebuf);
        }

        int2dlt = sendpacket_get_dlt(ctx->intf2);
        if (int2dlt != int1dlt) {
            tcpreplay_seterr(ctx, "DLT type missmatch for %s (%s) and %s (%s)", 
                options->intf1_name, pcap_datalink_val_to_name(int1dlt), 
                options->intf2_name, pcap_datalink_val_to_name(int2dlt));
            return -1;
        }
    }

    if (HAVE_OPT(CACHEFILE)) {
        temp = safe_strdup(OPT_ARG(CACHEFILE));
        options->cache_packets = read_cache(&options->cachedata, temp,
            &options->comment);
        safe_free(temp);
    }

    /* return -2 on warnings */
    if (warn > 0)
        return -2;

    return 0;

#else
    tcpreplay_seterr(ctx, "autopts support not compiled in.  tcpreplay_post_args() not supported");
    return -1;
#endif /* USE_AUTOOPTS */

}
Example #5
0
/**
 * This is the main function of the program that handles calling other
 * functions to implemented the needed operations of the replay functionaily.
 */
int
main(int argc, char **argv)
{
    unsigned int k;
    unsigned int num_packets=0;

    char port_mode[10];    /* does user specify random port generation?*/
    char random_strg[7] = "random";

    char* iface = argv[1];
    char* new_rmac_ptr;
    char* new_rip_ptr;
    in_addr new_remoteip;
    struct mac_addr new_remotemac;
    in_addr myip;
    struct mac_addr mymac;


    /*temporary packet buffers*/


    unsigned int new_src_port = 0;
    unsigned int retransmissions = 0;

    pcap_t *local_handle;
    char errbuf[PCAP_ERRBUF_SIZE];



    char ebuf[SENDPACKET_ERRBUF_SIZE];


    optionProcess(&tcpliveplayOptions, argc, argv); /*Process AutoOpts for manpage options*/

    if((argc < 5) || (argv[1]==NULL) || (argv[2]==NULL) || (argv[3]==NULL) || (argv[4]==NULL) || (argv[5]==NULL)) {
        printf("ERROR: Incorrect Usage!\n");
        printf("Usage: tcpliveplay <eth0/eth1> <file.pcap> <Destinatin IP [1.2.3.4]> <Destination mac [0a:1b:2c:3d:4e:5f]> <specify 'random' or specific port#>\n");
        printf("Example:\n    yhsiam@yhsiam-VirtualBox:~$ sudo tcpliveplay eth0 test1.pcap 192.168.1.4 52:57:01:11:31:92 random\n\n");
        exit(0);
    }

    iface_addrs(iface, &myip, &mymac);	/* Extract MAC of interface replay is being request on */

    /* open send function socket*/
    if ((sp = sendpacket_open(iface, ebuf, TCPR_DIR_C2S, SP_TYPE_NONE)) == NULL)
        errx(-1, "Can't open %s: %s", argv[1], ebuf);

    /* random dport vs. specified dport operation*/
    strcpy(port_mode, argv[5]);
    /*for(int i = 0; i<10; i++) tolower(port_mode[i]);*/
    if(strcmp(port_mode, random_strg)==0) {
        new_src_port = random_port();
    } else new_src_port = atoi(argv[5]);
    /*else {
    printf("Port specification error. Please specify 'random' for random source port generation between 49152 and 65535 OR specifiy a specific source port number.\n");
        return;
    }*/
    printf("new source port:: %d\n", new_src_port);

    /* Establish a handler for SIGALRM signals. */
    /* This is used as timeout for unresponsive remote hosts */
    signal (SIGALRM, catch_alarm);


    /* Extract new Remote MAC & IP inputted at command line */
    new_rmac_ptr= argv[4];
    new_rip_ptr = argv[3];

    /* These function setup the MAC & IP addresses in the mac_addr & in_addr structs */
    extmac(new_rmac_ptr, &new_remotemac);
    extip(new_rip_ptr, &new_remoteip);

    /* Rewrites the given "*.pcap" file with all the new parameters and returns the number of packets */
    /* that need to be replayed */
    num_packets = rewrite(&new_remoteip, &new_remotemac, &myip, &mymac, argv[2], new_src_port);

    /* create schedule & set it up */
    sched = (struct tcp_sched*) malloc(num_packets*sizeof(struct tcp_sched));
    pkts_scheduled = setup_sched(sched);    /* Returns number of packets in schedule*/

    /* Set up the schedule struct to be relative numbers rather than absolute*/
    relative_sched(sched, sched[1].exp_rseq, num_packets);
    printf("Packets Scheduled %d\n", pkts_scheduled);

    /* Open socket for savedfile traffic to be sent*/
    local_handle = pcap_open_offline("newfile.pcap", errbuf);   /*call pcap library function*/
    if (local_handle == NULL) {
        fprintf(stderr,"Couldn't open pcap file %s: %s\n", "newfile.pcap", errbuf);
        return(2);
    }

    /* Open socket for live traffic to be listed to*/
    live_handle = set_live_filter(iface, &myip, new_src_port);  /* returns a pcap_t that filters out traffic other than TCP*/
    if (live_handle == NULL) {
        fprintf(stderr,"Error occured while listing on traffic: %s\n", errbuf);
        return(2);
    }


    /* Printout when no packets are scheduled */
    if(pkts_scheduled==0) {
        printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
        printf("+ ERROR:: There are no TCP packets to sent                      +\n");
        printf("+ Closing replay...                                             +\n");
        printf("+ Thank you for Playing, Play again!                            +\n");
        printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
        return ERROR;
    }

    /* Start replay by sending the first packet, the SYN, from the schedule */
    else if(sched[0].local) { /* Send first packet*/
        sendpacket(sp, sched[sched_index].packet_ptr, sched[sched_index].pkthdr.len, &sched[sched_index].pkthdr);
        printf("Sending Local Packet...............	[%d]\n",sched_index+1);
        sched_index++; /* Proceed in the schedule */
    }

    /* Main while loop that handles the decision making and the replay oprations */
    while(sched_index<pkts_scheduled) {
        if(!keep_going) { /*Check the timeout variable */
            printf("\n======================================================================\n");
            printf("= TIMEOUT:: Remote host is not responding. You may have crashed      =\n");
            printf("= the host you replayed these packets against OR the packet sequence =\n");
            printf("= changed since the capture was taken resulting in differing         =\n");
            printf("= expectations. Closing replay...                                    =\n");
            printf("======================================================================\n\n");
            break;
        }
        /* tcphdr_rprev carries the last remote tcp header */
        if(tcphdr_rprev == NULL) {
            //printf("FIRST PASS!\n");
        }
        /* Check if received RST or RST-ACK flagged packets*/
        else if((tcphdr_rprev->th_flags==TH_RST) || (tcphdr_rprev->th_flags==(TH_RST|TH_ACK))) {
            printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
            printf("+ ERROR:: Remote host has requested to RESET the connection.   +\n");
            printf("+ Closing replay...                                            +\n");
            printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
            break;
        }
        /*Check if received earlier FIN-ACK than expected
        else if((sched_index-1 < finack_rindex) && (tcphdr_rprev->th_flags==(TH_FIN|TH_ACK))){
            printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
            printf("+ ERROR:: Remote host sent an earlier FIN-ACK than expected.   +\n");
            printf("+ Closing replay...                                            +\n");
            printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
            return;
        } */
        /* Do the following if we receive a packet that ACKs for the same ACKing of next packet */
        else if((tcphdr_rprev->th_seq==htonl(sched[sched_index].exp_rseq)) && (tcphdr_rprev->th_ack==htonl(sched[sched_index].exp_rack)) && (size_payload_prev>0)) {
            printf("Received Remote Packet...............	[%d]\n",sched_index+1);
            printf("Skipping Packet......................	[%d] to Packet [%d]\n",sched_index+1, sched_index+2);
            printf("Next Remote Packet Expectation met.\nProceeding in replay...\n");
            sched_index++;
        }
        /* Do the following if payload does not meet expectation and re-attempt with the remote host for 3 tries*/
        else if(different_payload) {
            printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
            printf("+ WARNING: Remote host is not meeting packet size expectations.               +\n");
            printf("+ for packet %-d. Application layer data differs from capture being replayed.  +\n", diff_payload_index+1);
            printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
            printf("Requesting retransmission.\n Proceeding...\n");
            different_payload = false;
        }

        /* Local Packets */
        if(sched[sched_index].local) {
            /*Reset alarm timeout*/
            alarm (ALARM_TIMEOUT);
            printf("Sending Local Packet...............	[%d]\n",sched_index+1);

            /* edit each packet tcphdr before sending based on the schedule*/
            if(sched_index>0) {
                sched[sched_index].tcphdr->th_ack = htonl(sched[sched_index].curr_lack);
                fix_all_checksum_liveplay(sched[sched_index].iphdr);
            }

            /* If 3 attempts of resending was made, then error out to the user */
            if(sched[sched_index].sent_counter==3) {
                printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
                printf("+ ERROR: Re-sent packet [%-d] 3 times, but remote host is not  +\n", sched_index+1);
                printf("+ responding as expected. 3 resend attempts are a maximum.     +\n");
                printf("+ Closing replay...                                            +\n");
                printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
                break;
            }

            /* If nothing goes wrong, then send the packet scheduled to be sent, then proceed in the schedule */
            sendpacket(sp, sched[sched_index].packet_ptr, sched[sched_index].pkthdr.len, &sched[sched_index].pkthdr);
            sched[sched_index].sent_counter++; /* Keep track of how many times this specific packet was attempted */
            sched_index++;   /* proceed */
        }

        /* Remote Packets */
        else if(sched[sched_index].remote) {

            alarm (ALARM_TIMEOUT);
            printf("Receiving Packets from remote host...\n");
            pcap_dispatch(live_handle, 1, got_packet, NULL); /* Listen in on NIC for tcp packets */
            //printf("pcap_loop returned\n");
        }
    } /* end of main while loop*/


    pcap_breakloop(live_handle);

    pcap_close(live_handle);
    sendpacket_close(sp);  /* Close Send socket*/
    remove("newfile.pcap"); /* Remote the rewritten file that was created*/

    for(k=0; k<pkts_scheduled; k++) {
        retransmissions+=sched[k].sent_counter;
    }


    /* User Debug Result Printouts*/
    if(sched_index==pkts_scheduled) {
        printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
        printf("~ CONGRATS!!! You have successfully Replayed your pcap file '%s'  \n", argv[2]);
        printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
    }
    else {
        printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
        printf("~ Unfortunately an error has occurred  halting the replay of  \n");
        printf("~ the pcap file '%s'. Please see error above for details...   \n", argv[2]);
        printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
    }

    printf("----------------TCP Live Play Summary----------------\n");
    printf("- Packets Scheduled to be Sent & Received: 	    %-d   \n", pkts_scheduled);
    printf("- Actual Packets Sent & Received:                   %-d   \n", sched_index);
    printf("- Total Local Packet Re-Transmissions due to packet       \n");
    printf("- loss and/or differing payload size than expected: %-d   \n", retransmissions);
    printf("- Thank you for Playing, Play again!                      \n");
    printf("----------------------------------------------------------\n\n");

    return 0;
}