12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253 |
- /*
- * Main Author & Publisher: Yazan H. Siam (tcpliveplay@gmail.com)
- * File: tcpliveplay.c
- * Started as a Senior Design project @ North Carolina State University
- * Last Updated Date: September 5, 2012
- *
- */
- /**
- * Program Description:
- * This program, 'tcpliveplay' replays a captured set of packets using new TCP connections with the
- * captured TCP payloads against a remote host in order to do comprehensive vulnerability testings.
- * This program takes in a "*.pcap" file that contains only one tcp flow connection and replays it
- * against a live host exactly how the captured packets are laid out. At the beginning, the program
- * establishes who the 'client' is and the 'server' is based on who initiates the SYN compares each
- * packet's source ip against the ip of the 'client' (which is named local in the code) and the 'server'
- * (remote) to correctly determine the expected seqs & acks. This also extracts the MACs of both local
- * and remote clients. The program is also capable of rewriting the local and remote MAC & IP so that
- * the packets are properly replayed when used on live networks. The current state of the program is that
- * it takes in a pcap file on command line and writes a new file called "newfile.pcap" which is used thereafter
- * for the rest of the program's calculations and set expectations. The program prints out a summary of the
- * new file on the command prompt. Once the program is done, "newfile.pcap" is cleaned up.
- * Program Design Overview:
- * Before replaying the packets, the program reads in the pcap file that contains one tcp flow,
- * and takes the SEQ/ACK #s.
- * Based on the number of packets, a struct schedule of events are is set up. Based on
- * the SEQ/ACK numbers read in, the schedule is setup to be relative numbers rather than
- * absolute. This is done by starting with local packets, subtracting the first SEQ (which
- * is that of the first SYN packet) from all the SEQs of the local packets then by subtracting
- * the first remote sequence (which is that of the SYN-ACK packet) from all the local packet's
- * ACKs. After the local side SEQ/ACK numbers are fixed to relative numbers, 'lseq_adjust'
- * the locally generated random number for the SYN packet gets added to all the local SEQs
- * to adjust the schedule to absolute number configuration. Then doing the remote side is similar
- * except we only fix the remote ACKs based on our locally generated random number because
- * we do not yet know the remote random number of the SYN-ACK packet. This means that at this
- * point the entire schedule of local packets and remote packets are set in such a way that
- * the local packets' SEQ's are absolute, but ACKs are relative and the remote packets' SEQ's are
- * relative but ACKs as absolute. Once this is set, the replay starts by sending first SYN packet.
- * If the remote host's acks with the SYN packet_SEQ+1 then we save their remote SEQ and adjust
- * the local ACKs and remote SEQs in the struct schedule to be absolute based this remote SEQ.
- * From this point on forward, we know or 'expect' what the remote host's ACKs and SEQs are exactly.
- * If the remote host responds correctly as we expect (checking the schedule position expectation
- * as packets are received) then we proceed in the schedule whether the next event is to send a local
- * packet or wait for a remote packet to arrive.
- *
- * Usage: tcpliveplay <eth0/eth1> <file.pcap> <Destination IP [1.2.3.4]> <Destination mac [0a:1b:2c:3d:4e:5f]> <'random' dst port OR specify dport #>
- *
- * Example:
- * yhsiam@yhsiam-VirtualBox:~$ tcpliveplay eth0 test1.pcap 192.168.1.4 52:57:01:11:31:92 random
- *
- * NOTE: This program may not completely replay the packets due to the remote host responding in an unexpected
- * fashion such as responding with packets never seen in the given *.pcap file or coupling packets together, etc.
- * if you have any suggestion on improving this software or if you find any bugs, please let me know at my
- * email: tcpliveplay@gmail.com
- *
- * Past Contributors (Last contributed May 4, 2012): Andrew Leonard & Beau Luck
- *
- */
- #include "config.h"
- #include "defines.h"
- #include "common.h"
- #include <signal.h>
- #include <time.h>
- #include <utime.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <errno.h>
- #include <stdbool.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <netinet/in.h>
- #include <net/if.h>
- #include <arpa/inet.h>
- #include "tcpliveplay.h"
- #include "tcpliveplay_opts.h"
- #include "common/sendpacket.h"
- #include "common/utils.h"
- #include "send_packets.h"
- volatile int didsig;
- #ifdef DEBUG /* set -DDEBUG=1 */
- int debug = 0;
- #endif
- pcap_t *set_live_filter(char *dev, input_addr* hostip, unsigned int port);
- pcap_t *set_offline_filter(char* file);
- pcap_t *live_handle;
- u_char *recvd_pkt_data = NULL;
- unsigned int buf_write_index = 0;
- unsigned int sched_index = 0;
- unsigned int initial_rseq=0;
- sendpacket_t *sp;
- unsigned int seed = 0;
- const u_char *packet_keeper_rprev = NULL;
- ether_hdr *etherhdr_rprev = NULL; /*g for Global header pointers used in pcap_loop callback*/
- tcp_hdr *tcphdr_rprev = NULL;
- ipv4_hdr *iphdr_rprev = NULL;
- unsigned int size_payload_prev = 0;
- unsigned int finack_rindex = 0;
- unsigned int acked_index = 0;
- unsigned int diff_payload_index = 0;
- bool different_payload = false;
- volatile sig_atomic_t keep_going = 1;
- int random_port();
- unsigned int pkts_scheduled=0; /* packet counter */
- struct tcp_sched* sched = NULL;
- void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
- void catch_alarm (int sig);
- int iface_addrs(char* iface, input_addr* ip, struct mac_addr* mac);
- int extmac(char* new_rmac_ptr, struct mac_addr* new_remotemac);
- int extip(char *ip_string, input_addr* new_remoteip);
- int rewrite(input_addr* new_remoteip, struct mac_addr* new_remotemac, input_addr* myip, struct mac_addr* mymac, char* file, unsigned int new_src_port);
- int setup_sched(struct tcp_sched* sched);
- int relative_sched(struct tcp_sched* sched, u_int32_t first_rseq, int num_packets);
- int fix_all_checksum_liveplay(ipv4_hdr *iphdr);
- int compip(input_addr* lip, input_addr* rip, input_addr* pkgip);
- int do_checksum_liveplay(u_int8_t *data, int proto, int len);
- int do_checksum_math_liveplay(u_int16_t *data, int len);
- /**
- * 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;
- int num_packets = 0;
- static const char random_strg[] = "random";
- char* iface = argv[1];
- char* new_rmac_ptr;
- char* new_rip_ptr;
- input_addr new_remoteip;
- struct mac_addr new_remotemac;
- input_addr myip;
- struct mac_addr mymac;
- int new_src_port = 0;
- unsigned int retransmissions = 0;
- pcap_t *local_handle;
- char errbuf[PCAP_ERRBUF_SIZE];
- char ebuf[SENDPACKET_ERRBUF_SIZE];
- int i;
- 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> <Destination 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);
- }
- if (strlen(iface) > IFNAMSIZ - 1)
- errx(-1, "Invalid interface name %s\n", iface);
- if (iface_addrs(iface, &myip, &mymac) < 0) /* Extract MAC of interface replay is being request on */
- errx(-1, "Failed to access interface %s\n", iface);
- /* open send function socket*/
- if ((sp = sendpacket_open(iface, ebuf, TCPR_DIR_C2S, SP_TYPE_NONE, NULL)) == NULL)
- errx(-1, "Can't open %s: %s", argv[1], ebuf);
- /*for(int i = 0; i<10; i++) tolower(port_mode[i]);*/
- if(strcmp(argv[5], random_strg)==0)
- new_src_port = random_port();
- else
- new_src_port = atoi(argv[5]);
- if (new_src_port < 0 || new_src_port > 65535)
- errx(new_src_port, "Cannot use source port %d", new_src_port);
- 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 inputed 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 */
- if (extmac(new_rmac_ptr, &new_remotemac) == ERROR)
- errx(-1, "failed to parse mac address %s\n", new_rmac_ptr);
- if (extip(new_rip_ptr, &new_remoteip) == ERROR)
- errx(-1, "failed to parse IP address %s\n", new_rip_ptr);
- /* 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);
- if (num_packets < 2)
- errx(-1, "Unable to rewrite PCAP file %s\n",argv[2]);
- /* create schedule & set it up */
- sched = (struct tcp_sched*) malloc(num_packets*sizeof(struct tcp_sched));
- if (!sched)
- err(-1, "out of memory\n");
- pkts_scheduled = setup_sched(sched); /* Returns number of packets in schedule*/
- /* Set up the schedule struct to be relative numbers rather than absolute*/
- for (i = 0; i < num_packets; i++) {
- sched[i].exp_rseq = 0;
- sched[i].exp_rack = 0;
- }
- relative_sched(sched, sched[1].exp_rseq, num_packets);
- printf("Packets Scheduled %u\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);
- free(sched);
- 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 occurred while listing on traffic: %s\n", errbuf);
- free(sched);
- return(2);
- }
- /* Printout when no packets are scheduled */
- if(pkts_scheduled==0){
- printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
- printf("+ ERROR:: There are no TCP packets to send +\n");
- printf("+ Closing replay... +\n");
- printf("+ Thank you for Playing, Play again! +\n");
- printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
- free(sched);
- 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............... [%u]\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............... [%u]\n",sched_index+1);
- printf("Skipping Packet...................... [%u] to Packet [%u]\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 %-u. 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............... [%u]\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 [%-u] 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: %-u\n", pkts_scheduled);
- printf("- Actual Packets Sent & Received: %-u\n", sched_index);
- printf("- Total Local Packet Re-Transmissions due to packet\n");
- printf("- loss and/or differing payload size than expected: %-u\n", retransmissions);
- printf("- Thank you for Playing, Play again!\n");
- printf("----------------------------------------------------------\n\n");
- free(sched);
- restore_stdin();
- return 0;
- }
- /*end of main() function*/
- /**
- * This function serves as a timer alarm
- */
- void
- catch_alarm (int sig){
- keep_going = 0;
- signal (sig, catch_alarm);
- }
- static int tcplp_rand(void)
- {
- struct timeval tv;
- if (!seed) {
- gettimeofday(&tv, NULL);
- seed = (unsigned int)tv.tv_sec ^ (unsigned int)tv.tv_usec;
- }
- return tcpr_random(&seed);
- }
- /**
- * This function returns a random number between 49152 and 65535
- */
- int
- random_port()
- {
- int random = tcplp_rand();
- return (49152 + (random % 16383));
- }
- /**
- * This function sets up the scheduled local ACK and Remote SEQ to be relative numbers,
- * While it sets up the local SEQs and remote ACKs to be absolute within the schedule.
- */
- int
- relative_sched(struct tcp_sched* sched, u_int32_t first_rseq, int num_packets){
- int i;
- u_int32_t lseq_adjust = tcplp_rand();
- printf("Random Local SEQ: %u\n",lseq_adjust);
- u_int32_t first_lseq = sched[0].curr_lseq; /* SYN Packet SEQ number */
- /* Fix schedule to relative and absolute */
- for(i = 0; i < num_packets; i++){
- if(sched[i].local){
- sched[i].curr_lseq = sched[i].curr_lseq - first_lseq; /* Fix current local SEQ to relative */
- sched[i].curr_lseq = sched[i].curr_lseq + lseq_adjust; /* Make absolute. lseq_adjust is the locally generated random number */
- sched[i].curr_lack = sched[i].curr_lack - first_rseq; /* Fix current local ACK to relative */
- if (sched[i].tcphdr)
- sched[i].tcphdr->th_seq = htonl(sched[i].curr_lseq); /* Edit the actual packet header data */
- fix_all_checksum_liveplay(sched[i].iphdr); /* Fix the checksum */
- sched[i].exp_rseq = sched[i].exp_rseq - first_rseq;
- sched[i].exp_rack = sched[i].exp_rack - first_lseq;
- sched[i].exp_rack = sched[i].exp_rack + lseq_adjust;
- }
- else if(sched[i].remote){
- sched[i].exp_rseq = sched[i].exp_rseq - first_rseq; /* Fix expected remote SEQ to be relative */
- sched[i].exp_rack = sched[i].exp_rack - first_lseq; /* Fix expected remote ACK to be relative*/
- sched[i].exp_rack = sched[i].exp_rack + lseq_adjust; /* Fix expected remote ACK to be absolute */
- }
- }
- return SUCCESS;
- }
- /**
- * This function sets up the schedule for the rest of the program
- * extracting all the needed information from the given pcap file
- * and coping into memory (into a struct format)
- *
- */
- int
- setup_sched(struct tcp_sched* sched){
- input_addr sip, dip; /* Source & Destination IP */
- input_addr local_ip, remote_ip; /* ip address of client and server*/
- pcap_t *local_handle;
- const u_char *packet; /* The actual packet */
- unsigned int flags=0;
- struct pcap_pkthdr header; // The header that pcap gives us
- unsigned int pkt_counter=0;
- bool remote = false; /* flags to test if data is from 'client'=local or 'server'=remote */
- bool local = false;
- unsigned int i = 0;
- local_ip.byte1=0;
- local_ip.byte2=0;
- local_ip.byte3=0;
- local_ip.byte4=0;
- remote_ip.byte1=0;
- remote_ip.byte2=0;
- remote_ip.byte3=0;
- remote_ip.byte4=0;
- char errbuf[PCAP_ERRBUF_SIZE];
- 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);
- }
- /*Before sending any packet, setup the schedule with the proper parameters*/
- while((packet = safe_pcap_next(local_handle, &header))) {
- /*temporary packet buffers*/
- ether_hdr *etherhdr;
- tcp_hdr *tcphdr;
- ipv4_hdr *iphdr;
- unsigned int size_ip;
- unsigned int size_tcp;
- unsigned int size_payload;
- pkt_counter++; /*increment number of packets seen*/
- memcpy(&sched[i].pkthdr, &header, sizeof(struct pcap_pkthdr));
- sched[i].packet_ptr = safe_malloc(sched[i].pkthdr.len);
- memcpy(sched[i].packet_ptr, packet, sched[i].pkthdr.len);
- /* extract necessary data */
- etherhdr = (ether_hdr*)(sched[i].packet_ptr);
- iphdr = (ipv4_hdr *)(sched[i].packet_ptr + SIZE_ETHERNET);
- size_ip = iphdr->ip_hl << 2;
- if (size_ip < 20) {
- printf("ERROR: Invalid IP header length: %u bytes\n", size_ip);
- return 0;
- }
- tcphdr = (tcp_hdr *)(sched[i].packet_ptr + SIZE_ETHERNET + size_ip);
- size_tcp = tcphdr->th_off*4;
- if (size_tcp < 20) {
- printf("ERROR: Invalid TCP header length: %u bytes\n", size_tcp);
- return 0;
- }
- /* payload = (u_char *)(sched[i].packet_ptr + SIZE_ETHERNET + size_ip + size_tcp); */
- size_payload = ntohs(iphdr->ip_len) - (size_ip + (size_tcp));
- /* Source IP and Destination IP */
- sip = iphdr->ip_src;
- dip = iphdr->ip_dst;
- flags = tcphdr->th_flags;
- if (flags == TH_SYN){ /* set IPs who's local and who's remote based on the SYN flag */
- local_ip = sip;
- remote_ip = dip;
- }
- /*Compare IPs to see which packet is this coming from*/
- if(compip(&local_ip, &remote_ip, &sip)==LOCAL_IP_MATCH){
- local = true;
- remote = false;
- }
- if(compip(&local_ip, &remote_ip, &sip)==REMOTE_IP_MATCH){
- local = false;
- remote = true;
- }
- /* Setup rest of Schedule, parameter by parameter */
- /* Refer to header file for details on each of the parameters */
- sched[i].etherhdr = etherhdr;
- sched[i].iphdr = iphdr;
- sched[i].tcphdr = tcphdr;
- sched[i].size_ip = size_ip;
- sched[i].size_tcp = size_tcp;
- sched[i].size_payload = size_payload;
- sched[i].sent_counter = 0;
- /* Do the following only for the first packet (SYN)*/
- if(i==0){
- sched[i].length_last_ldata = 0;
- sched[i].length_curr_ldata = 0;
- sched[i].length_last_rdata = 0;
- sched[i].length_curr_rdata = 0;
- sched[i].local = true;
- sched[i].remote = false;
- sched[i].curr_lseq = ntohl(sched[i].tcphdr->th_seq);
- sched[i].curr_lack = 0;
- sched[i].exp_rseq = 0; /* Keep track of previous remote seq & ack #s*/
- sched[i].exp_rack = 0;
- }
- /* Local Packet operations */
- else if(local){
- sched[i].length_last_ldata = sched[i-1].length_curr_ldata;
- sched[i].length_curr_ldata = size_payload;
- sched[i].length_last_rdata = sched[i-1].length_curr_rdata;
- sched[i].length_curr_rdata = 0;
- sched[i].local = true;
- sched[i].remote = false;
- sched[i].curr_lseq = ntohl(sched[i].tcphdr->th_seq);
- sched[i].curr_lack = ntohl(sched[i].tcphdr->th_ack);
- sched[i].exp_rseq = sched[i-1].exp_rseq; /* Keep track of previous remote seq & ack #s*/
- sched[i].exp_rack = sched[i-1].exp_rack;
- }
- /* Remote Packet operations */
- else if(remote){
- sched[i].length_last_ldata = sched[i-1].length_curr_ldata;
- sched[i].length_curr_ldata = 0;
- sched[i].length_last_rdata = sched[i-1].length_curr_rdata;
- sched[i].length_curr_rdata = size_payload;
- sched[i].local = false;
- sched[i].remote = true;
- sched[i].curr_lseq = sched[i-1].curr_lseq;
- sched[i].curr_lack = sched[i-1].curr_lack;
- sched[i].exp_rseq = ntohl(sched[i].tcphdr->th_seq); /* Keep track of previous remote seq & ack #s*/
- sched[i].exp_rack = ntohl(sched[i].tcphdr->th_ack);
- /* Setup global variable where remote FIN-ACK exists*/
- if(flags == (TH_FIN|TH_ACK)) finack_rindex = i;
- //printf("REMOTE --------%d\n",i+1);
- }
- i++; /* increment schedule index */
- } /*end internal loop for reading packets (all in one file)*/
- pcap_close(local_handle); /*close the pcap file*/
- return pkt_counter; /* Return number of packets scheduled */
- }
- /**
- * This function returns a pcap_t for the live traffic handler which
- * filters out traffic other than TCP
- *
- */
- pcap_t*
- set_live_filter(char *dev, input_addr* hostip, unsigned int port)
- {
- pcap_t *handle = NULL; /* Session handle */
- char errbuf[PCAP_ERRBUF_SIZE]; /* Error string buffer */
- struct bpf_program fp; /* The compiled filter */
- char filter_exp[52];
- sprintf(filter_exp,"tcp and dst host %d.%d.%d.%d and dst port %u",
- hostip->byte1, hostip->byte2, hostip->byte3, hostip->byte4, port); /* The filter expression */
- bpf_u_int32 mask; /* Our network mask */
- bpf_u_int32 net; /* Our IP */
- /* Define the device */
- if (dev == NULL) {
- fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
- return handle;
- }
- /* Find the properties for the device */
- if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
- fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
- net = 0;
- mask = 0;
- }
- /* Open the session in promiscuous mode */
- handle = pcap_open_live(dev, BUFSIZ_PLUS, PROMISC_OFF, TIMEOUT_ms, errbuf);
- if (handle == NULL) {
- fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
- return handle;
- }
- /* Compile and apply the filter */
- if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
- fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
- return handle;
- }
- if (pcap_setfilter(handle, &fp) == -1) {
- fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
- return handle;
- }
- return handle;
- }
- /**
- * This function returns a pcap_t for the savedfile traffic handler which
- * filters out traffic other than TCP
- *
- */
- pcap_t*
- set_offline_filter(char* file)
- {
- pcap_t *handle; /* Session handle */
- char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
- struct bpf_program fp; /* The compiled filter */
- char filter_exp[] = "tcp";
- bpf_u_int32 net=0; /* Our IP */
- /* Open savedfile */
- handle = pcap_open_offline(file, errbuf);
- if (handle == NULL) {
- fprintf(stderr, "Couldn't open file %s\n", errbuf);
- return handle;
- }
- /* Compile and apply the filter */
- if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
- fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
- return handle;
- }
- if (pcap_setfilter(handle, &fp) == -1) {
- fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
- return handle;
- }
- return handle;
- }
- /**
- * This is the callback function for pcap_loop
- * This function is called every time we receive a remote packet
- */
- void
- got_packet(_U_ u_char *args, _U_ const struct pcap_pkthdr *header,
- const u_char *packet)
- {
- ether_hdr *etherhdr;
- tcp_hdr *tcphdr;
- ipv4_hdr *iphdr;
- unsigned int size_ip, size_tcp, size_payload;
- unsigned int flags = 0;
- /* Extract and examine received packet headers */
- etherhdr = (ether_hdr*)(packet);
- iphdr = (ipv4_hdr *)(packet + SIZE_ETHERNET);
- size_ip = iphdr->ip_hl << 2;
- if (size_ip < 20) {
- printf("ERROR: Invalid IP header length: %u bytes\n", size_ip);
- return;
- }
- tcphdr = (tcp_hdr *)(packet + SIZE_ETHERNET + size_ip);
- size_tcp = tcphdr->th_off*4;
- if (size_tcp < 20) {
- printf("ERROR: Invalid TCP header length: %u bytes\n", size_tcp);
- return;
- }
- size_payload = ntohs(iphdr->ip_len) - (size_ip + (size_tcp));
- flags = tcphdr->th_flags;
- /* Check correct SYN-ACK expectation, if so then proceed in fixing entire schedule from relative to absolute SEQs+ACKs */
- if((flags == (TH_SYN|TH_ACK)) && (sched_index==1) && (tcphdr->th_ack==htonl(sched[sched_index-1].curr_lseq + 1))){
- unsigned int j;
- printf("Received Remote Packet............... [%u]\n", sched_index + 1);
- printf("Remote Pakcet Expectation met.\nProceeding in replay....\n");
- //printf("SYN-ACKed Random SEQ set!\n");
- initial_rseq = ntohl(tcphdr->th_seq);
- //printf("initial_rseq: %u\n", initial_rseq);
- /* After we receiving the first SYN-ACK, then adjust the entire sched to be absolute rather than relative #s*/
- sched[1].exp_rseq = sched[1].exp_rseq + initial_rseq;
- for(j = 2; j<pkts_scheduled; j++){ /* Based on correctly receiving the random SEQ from the SYN-ACK packet, do the following:*/
- if(sched[j].local){ /* Set local ACKs for entire sched to be absolute #s*/
- sched[j].curr_lack = sched[j].curr_lack + initial_rseq;
- }
- else if(sched[j].remote){ /* Set remote SEQs for entire sched to be absolute #s*/
- sched[j].exp_rseq = sched[j].exp_rseq + initial_rseq;
- }
- }
- sched_index++; /* Proceed in the schedule*/
- return;
- }
- printf(">Received a Remote Packet\n");
- printf(">>Checking Expectations\n");
- /* Handle Remote Packet Loss */
- if(sched[sched_index].exp_rack > ntohl(tcphdr->th_ack)) {
- //printf("Remote Packet Loss! Resending Lost packet\n");
- sched_index=acked_index; /* Reset the schedule index back to the last correctly ACKed packet */
- //printf("ACKED Index = %d\n", acked_index);
- while(!sched[sched_index].local){
- sched_index++;
- }
- return;
- }
- /* Handle Local Packet Loss <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<COME BACK TO THIS<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
- else if((sched[sched_index].exp_rseq < ntohl(tcphdr->th_seq)) && sched[sched_index].remote){
- /* Resend immediate previous LOCAL packet */
- printf("Local Packet Loss! Resending Lost packet >> DupACK Issued!\n");
- sched_index=acked_index; /* Reset the schedule index back to the last correctly ACKed packet */
- /*sched[sched_index].sent_counter=0; Reset the re-transmission counter for this ACKed packet?*/
- //printf("ACKED Index = %d\n", acked_index);
- while(!sched[sched_index].local){
- sched_index++;
- }
- return;
- }
- /* No Packet Loss... Proceed Normally (if expectations are met!) */
- else if((tcphdr->th_seq==htonl(sched[sched_index].exp_rseq)) &&
- (tcphdr->th_ack==htonl(sched[sched_index].exp_rack))){
- printf("Received Remote Packet............... [%d]\n",sched_index+1);
- /* Handles differing payload size and does not trigger on unnecessary ACK + window update issues*/
- if((sched[sched_index].size_payload!=size_payload) && (size_payload!=0)){
- printf("Payload size of received packet does not meet expectations\n");
- /* Resent last local packet, maybe remote host behaves this time*/
- different_payload=true;
- /* Set global variable of where differing payload size is not meeting expectations*/
- diff_payload_index = sched_index;
- /*Treat this as packet loss, and attempt resetting index to resend packets where*/
- /* packets were received matching expectation*/
- sched_index=acked_index; /* Reset the schedule index back to the last correctly ACKed packet */
- //printf("ACKED Index = %d\n", acked_index);
- while(!sched[sched_index].local){
- sched_index++;
- }
- return;
- }
- printf("Remote Packet Expectation met.\nProceeding in replay....\n");
- sched_index++;
- acked_index = sched_index; /*Keep track correctly ACKed packet index*/
- }
- /* Global variable to keep tack of last received packet info */
- packet_keeper_rprev = packet;
- etherhdr_rprev = etherhdr;
- tcphdr_rprev = tcphdr;
- iphdr_rprev = iphdr;
- size_payload_prev = size_payload;
- return;
- }
- /**
- * This function prints out the ip address, given an in_addr struct pointer
- *
- */
- void
- printip(input_addr* IP)
- {
- printf("[%d.%d.%d.%d]\n", IP->byte1, IP->byte2, IP->byte3, IP->byte4);
- return;
- }
- /**
- * This function prints out the mac address, given a mac_addr struct pointer
- *
- */
- void
- printmac(struct mac_addr* MAC)
- {
- printf("[%x:%x:%x:%x:%x:%x]\n", MAC->byte1, MAC->byte2, MAC->byte3, MAC->byte4, MAC->byte5, MAC->byte6);
- return;
- }
- /**
- * This function compares two IPs,
- * returns 1 if match with local ip
- * returns 2 if matches with remote ip
- * returns 0 if no match
- *
- */
- int
- compip(input_addr* lip, input_addr* rip, input_addr* pkgip)
- {
- if((lip->byte1==pkgip->byte1)&&(lip->byte2==pkgip->byte2)&&(lip->byte3==pkgip->byte3)&&(lip->byte4==pkgip->byte4))
- return LOCAL_IP_MATCH;
- else if((rip->byte1==pkgip->byte1)&&(rip->byte2==pkgip->byte2)&&(rip->byte3==pkgip->byte3)&&(rip->byte4==pkgip->byte4))
- return REMOTE_IP_MATCH;
- else
- return NO_MATCH;
- }
- /**
- * This function sets the IP and MAC of a given interface (i.e. eth0)
- * into in_addr & mac_addr struct pointers
- *
- */
- int iface_addrs(char* iface, input_addr* ip, struct mac_addr* mac)
- {
- int s;
- struct ifreq buffer;
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- return -1;
- memset(&buffer, 0x00, sizeof(buffer));
- strncpy(buffer.ifr_name, iface, sizeof(buffer.ifr_name)-1);
- int res;
- if ((res = ioctl(s, SIOCGIFADDR, &buffer)) < 0)
- goto done;
- struct in_addr localip = ((struct sockaddr_in *)&buffer.ifr_addr)->sin_addr;
- #if defined( WORDS_BIGENDIAN )
- ip->byte1 = (localip.s_addr)>>24;
- ip->byte2 = ((localip.s_addr)>>16)&255;
- ip->byte3 = ((localip.s_addr)>>8)&255;
- ip->byte4 = (localip.s_addr)&255;
- #else
- ip->byte4 = (localip.s_addr)>>24;
- ip->byte3 = ((localip.s_addr)>>16)&255;
- ip->byte2 = ((localip.s_addr)>>8)&255;
- ip->byte1 = (localip.s_addr)&255;
- #endif
- if ((res = ioctl(s, SIOCGIFHWADDR, &buffer)) < 0)
- goto done;
- mac->byte1 = buffer.ifr_hwaddr.sa_data[0];
- mac->byte2 = buffer.ifr_hwaddr.sa_data[1];
- mac->byte3 = buffer.ifr_hwaddr.sa_data[2];
- mac->byte4 = buffer.ifr_hwaddr.sa_data[3];
- mac->byte5 = buffer.ifr_hwaddr.sa_data[4];
- mac->byte6 = buffer.ifr_hwaddr.sa_data[5];
- done:
- close(s);
- return res;
- }
- /**
- * This function rewrites the IPs and MACs of a given packet,
- * creates a newfile.pcap. It returns the number of packets of the newfile.
- * This function only starts rewriting the newfile once it sees the first
- * SYN packet. This is so that the first packet in the newfile is always
- * the first packet to be sent.
- */
- int
- rewrite(input_addr* new_remoteip, struct mac_addr* new_remotemac, input_addr* myip, struct mac_addr* mymac, char* file, unsigned int new_src_port)
- {
- char *newfile = "newfile.pcap";
- int pkt_counter;
- input_addr local_ip;
- input_addr remote_ip;
- const u_char *packet;
- struct pcap_pkthdr *header;
- pcap_dumper_t *dumpfile;
- input_addr sip; /* Source IP */
- int local_packets = 0;
- bool initstep1 = false; /* keep track of successful handshake step */
- bool warned = false;
- local_ip.byte1=0;
- local_ip.byte2=0;
- local_ip.byte3=0;
- local_ip.byte4=0;
- remote_ip.byte1=0;
- remote_ip.byte2=0;
- remote_ip.byte3=0;
- remote_ip.byte4=0;
- pcap_t *pcap = set_offline_filter(file);
- if (!pcap){
- char ErrBuff [1024];
- fprintf (stderr, "Cannot open PCAP file '%s' for reading\n", file);
- fprintf(stderr, "%s\n",ErrBuff);
- return PCAP_OPEN_ERROR;
- }
- dumpfile = pcap_dump_open(pcap, newfile);
- if (!dumpfile) {
- fprintf (stderr, "Cannot open PCAP file '%s' for writing\n", newfile);
- return PCAP_OPEN_ERROR;
- }
- /*Modify each packet's IP & MAC based on the passed args then do a checksum of each packet*/
- for (pkt_counter = 0; safe_pcap_next_ex(pcap, &header, &packet) > 0; pkt_counter++){
- unsigned int flags, size_ip;
- ether_hdr* etherhdr;
- ipv4_hdr *iphdr;
- tcp_hdr *tcphdr;
- unsigned int size_tcp;
- if (!warned && header->len > header->caplen) {
- fprintf(stderr, "warning: packet capture truncated to %d byte packets\n",
- header->caplen);
- warned = true;
- }
- etherhdr = (ether_hdr*)(packet);
- iphdr = (ipv4_hdr *)(packet + SIZE_ETHERNET);
- size_ip = iphdr->ip_hl << 2;
- if (size_ip < 20) {
- printf("ERROR: Invalid IP header length: %u bytes\n", size_ip);
- return ERROR;
- }
- tcphdr = (tcp_hdr *)(packet + SIZE_ETHERNET + size_ip);
- size_tcp = tcphdr->th_off*4;
- if (size_tcp < 20) {
- printf("ERROR: Invalid TCP header length: %u bytes\n", size_tcp);
- return ERROR;
- }
- /* payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp); */
- sip = iphdr->ip_src;
- flags = tcphdr->th_flags;
- /* set IPs who's local and who's remote based on the SYN flag */
- if(flags == TH_SYN){
- local_ip = iphdr->ip_src;
- remote_ip = iphdr->ip_dst;
- initstep1 = true; /* This flag is set to signify the first encounter of the SYN within the pacp*/
- }
- if(compip(&local_ip, &remote_ip, &sip)==LOCAL_IP_MATCH){
- /* Set the source MAC */
- etherhdr->ether_shost[0] = mymac->byte1;
- etherhdr->ether_shost[1] = mymac->byte2;
- etherhdr->ether_shost[2] = mymac->byte3;
- etherhdr->ether_shost[3] = mymac->byte4;
- etherhdr->ether_shost[4] = mymac->byte5;
- etherhdr->ether_shost[5] = mymac->byte6;
- /* Set the source IP */
- iphdr->ip_src = *myip;
- /* Set the destination IP */
- iphdr->ip_dst = *new_remoteip;
- /* Set the destination MAC */
- etherhdr->ether_dhost[0] = new_remotemac->byte1;
- etherhdr->ether_dhost[1] = new_remotemac->byte2;
- etherhdr->ether_dhost[2] = new_remotemac->byte3;
- etherhdr->ether_dhost[3] = new_remotemac->byte4;
- etherhdr->ether_dhost[4] = new_remotemac->byte5;
- etherhdr->ether_dhost[5] = new_remotemac->byte6;
- /* This is to change the source port, whether it is specified as random or as a port # by the user */
- tcphdr->th_sport = htons(new_src_port);
- }
- else if(compip(&local_ip, &remote_ip, &sip)==REMOTE_IP_MATCH){
- /* Set the destination MAC */
- etherhdr->ether_dhost[0] = mymac->byte1;
- etherhdr->ether_dhost[1] = mymac->byte2;
- etherhdr->ether_dhost[2] = mymac->byte3;
- etherhdr->ether_dhost[3] = mymac->byte4;
- etherhdr->ether_dhost[4] = mymac->byte5;
- etherhdr->ether_dhost[5] = mymac->byte6;
- /* Set the destination IP */
- iphdr->ip_dst = *myip;
- /* Set the source IP */
- iphdr->ip_src = *new_remoteip;
- /* Set the source MAC */
- etherhdr->ether_shost[0] = new_remotemac->byte1;
- etherhdr->ether_shost[1] = new_remotemac->byte2;
- etherhdr->ether_shost[2] = new_remotemac->byte3;
- etherhdr->ether_shost[3] = new_remotemac->byte4;
- etherhdr->ether_shost[4] = new_remotemac->byte5;
- etherhdr->ether_shost[5] = new_remotemac->byte6;
- /* This is to change the source port, whether it is specified as random or as a port # by the user */
- tcphdr->th_dport = htons(new_src_port);
- }
- /*Calculate & fix checksum for newly edited-packet*/
- fix_all_checksum_liveplay(iphdr);
- if(initstep1){ /*only start rewriting new pcap with SYN packets on wards*/
- local_packets ++;
- pcap_dump((u_char *)dumpfile, header, packet);
- }
- } /* end of while loop */
- pcap_close (pcap);
- pcap_dump_close(dumpfile);
- return local_packets;
- }
- /**
- * This function extracts the MAC address (from command line format
- * and sets the mac_addr struct)
- *
- */
- int
- extmac(char* new_rmac_ptr, struct mac_addr* new_remotemac)
- {
- u_int8_t new_rmac[6];
- if (sscanf (new_rmac_ptr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &new_rmac[0], &new_rmac[1],
- &new_rmac[2], &new_rmac[3], &new_rmac[4], &new_rmac[5]) != 6)
- return ERROR;
- new_remotemac->byte1 = (unsigned char)new_rmac[0];
- new_remotemac->byte2 = (unsigned char)new_rmac[1];
- new_remotemac->byte3 = (unsigned char)new_rmac[2];
- new_remotemac->byte4 = (unsigned char)new_rmac[3];
- new_remotemac->byte5 = (unsigned char)new_rmac[4];
- new_remotemac->byte6 = (unsigned char)new_rmac[5];
- return SUCCESS;
- }
- /**
- * This function extracts the IP address (from command line format
- * and sets the in_addr struct)
- *
- */
- int
- extip(char *ip_string, input_addr* new_remoteip)
- {
- struct in_addr addr;
- if (inet_aton(ip_string, &addr) == 0)
- return ERROR;
- #if defined( WORDS_BIGENDIAN )
- new_remoteip->byte4 = (unsigned char)addr.s_addr & 0xff;
- new_remoteip->byte3 = (unsigned char)(addr.s_addr >> 8) & 0xff;
- new_remoteip->byte2 = (unsigned char)(addr.s_addr >> 16) & 0xff;
- new_remoteip->byte1 = (unsigned char)(addr.s_addr >> 24) & 0xff;
- #else
- new_remoteip->byte1 = (unsigned char)addr.s_addr & 0xff;
- new_remoteip->byte2 = (unsigned char)(addr.s_addr >> 8) & 0xff;
- new_remoteip->byte3 = (unsigned char)(addr.s_addr >> 16) & 0xff;
- new_remoteip->byte4 = (unsigned char)(addr.s_addr >> 24) & 0xff;
- #endif
- return SUCCESS;
- }
- /**
- * This function calls all the checksum function given the IP Header
- * and edits the checksums fixing them appropriately
- *
- */
- int
- fix_all_checksum_liveplay(ipv4_hdr *iphdr){
- int ret1 = 0, ret2 = 0;
- /*Calculate TCP Checksum*/
- ret2 = do_checksum_liveplay((u_char *) iphdr,iphdr->ip_p, ntohs(iphdr->ip_len) - (iphdr->ip_hl << 2));
- if(ret2==-1){
- printf("*******An Error Occurred calculating TCP Checksum*******\n");
- return -1;
- }
- /*Calculate IP Checksum*/
- ret1 = do_checksum_liveplay((u_char *) iphdr, IPPROTO_IP, ntohs(iphdr->ip_len));
- if(ret1==-1){
- printf("*******An Error Occurred calculating IP Checksum*******\n");
- return -1;
- }
- return 0;
- }
- /************************************************************************************/
- /*[copied from Aaron Turnor's checksum.c, but omitting tcpedit_t structs] */
- /*[The following functions have been slightly modified to be integrated with tcpliveplay code structure] */
- /**
- * This code re-calcs the IP and Layer 4 checksums
- * the IMPORTANT THING is that the Layer 4 header
- * is contiguous in memory after *ip_hdr we're actually
- * writing to the layer 4 header via the ip_hdr ptr.
- * (Yes, this sucks, but that's the way libnet works, and
- * I was too lazy to re-invent the wheel.
- * Returns 0 on success, -1 on error
- */
- /**
- * Returns -1 on error and 0 on success, 1 on warn
- */
- int
- do_checksum_liveplay(u_int8_t *data, int proto, int len) {
- ipv4_hdr *ipv4;
- tcp_hdr *tcp;
- int ip_hl;
- volatile int sum = 0; // <-- volatile works around a PPC g++ bug
- ipv4 = NULL;
- ipv4 = (ipv4_hdr *)data;
- ip_hl = ipv4->ip_hl << 2;
- switch (proto) {
- case IPPROTO_TCP:
- tcp = (tcp_hdr *)(data + ip_hl);
- #ifdef STUPID_SOLARIS_CHECKSUM_BUG
- tcp->th_sum = tcp->th_off << 2;
- return (TCPEDIT_OK);
- #endif
- tcp->th_sum = 0;
- /* Note, we do both src & dst IP's at the same time, that's why the
- * length is 2x a single IP
- */
- sum = do_checksum_math_liveplay((u_int16_t *)&ipv4->ip_src, 8);
- sum += ntohs(IPPROTO_TCP + len);
- sum += do_checksum_math_liveplay((u_int16_t *)tcp, len);
- tcp->th_sum = CHECKSUM_CARRY(sum);
- break;
- case IPPROTO_IP:
- ipv4->ip_sum = 0;
- sum = do_checksum_math_liveplay((u_int16_t *)data, ip_hl);
- ipv4->ip_sum = CHECKSUM_CARRY(sum);
- break;
- default:
- printf("Unsupported protocol for checksum:\n");
- return TCPEDIT_WARN;
- }
- return TCPEDIT_OK;
- }
- /**
- * code to do a ones-compliment checksum
- */
- int
- do_checksum_math_liveplay(u_int16_t *data, int len)
- {
- int sum = 0;
- union {
- u_int16_t s;
- u_int8_t b[2];
- } pad;
- while (len > 1) {
- sum += *data++;
- len -= 2;
- }
- if (len == 1) {
- pad.b[0] = *(u_int8_t *)data;
- pad.b[1] = 0;
- sum += pad.s;
- }
- return (sum);
- }
|