tcpliveplay.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255
  1. /*
  2. * Main Author & Publisher: Yazan H. Siam (tcpliveplay@gmail.com)
  3. * File: tcpliveplay.c
  4. * Started as a Senior Design project @ North Carolina State University
  5. * Last Updated Date: September 5, 2012
  6. *
  7. */
  8. /**
  9. * Program Description:
  10. * This program, 'tcpliveplay' replays a captured set of packets using new TCP connections with the
  11. * captured TCP payloads against a remote host in order to do comprehensive vulnerability testings.
  12. * This program takes in a "*.pcap" file that contains only one tcp flow connection and replays it
  13. * against a live host exactly how the captured packets are laid out. At the beginning, the program
  14. * establishes who the 'client' is and the 'server' is based on who initiates the SYN compares each
  15. * packet's source ip against the ip of the 'client' (which is named local in the code) and the 'server'
  16. * (remote) to correctly determine the expected seqs & acks. This also extracts the MACs of both local
  17. * and remote clients. The program is also capable of rewriting the local and remote MAC & IP so that
  18. * the packets are properly replayed when used on live networks. The current state of the program is that
  19. * it takes in a pcap file on command line and writes a new file called "newfile.pcap" which is used thereafter
  20. * for the rest of the program's calculations and set expectations. The program prints out a summary of the
  21. * new file on the command prompt. Once the program is done, "newfile.pcap" is cleaned up.
  22. * Program Design Overview:
  23. * Before replaying the packets, the program reads in the pcap file that contains one tcp flow,
  24. * and takes the SEQ/ACK #s.
  25. * Based on the number of packets, a struct schedule of events are is set up. Based on
  26. * the SEQ/ACK numbers read in, the schedule is setup to be relative numbers rather than
  27. * absolute. This is done by starting with local packets, subtracting the first SEQ (which
  28. * is that of the first SYN packet) from all the SEQs of the local packets then by subtracting
  29. * the first remote sequence (which is that of the SYN-ACK packet) from all the local packet's
  30. * ACKs. After the local side SEQ/ACK numbers are fixed to relative numbers, 'lseq_adjust'
  31. * the locally generated random number for the SYN packet gets added to all the local SEQs
  32. * to adjust the schedule to absolute number configuration. Then doing the remote side is similar
  33. * except we only fix the remote ACKs based on our locally generated random number because
  34. * we do not yet know the remote random number of the SYN-ACK packet. This means that at this
  35. * point the entire schedule of local packets and remote packets are set in such a way that
  36. * the local packets' SEQ's are absolute, but ACKs are relative and the remote packets' SEQ's are
  37. * relative but ACKs as absolute. Once this is set, the replay starts by sending first SYN packet.
  38. * If the remote host's acks with the SYN packet_SEQ+1 then we save their remote SEQ and adjust
  39. * the local ACKs and remote SEQs in the struct schedule to be absolute based this remote SEQ.
  40. * From this point on forward, we know or 'expect' what the remote host's ACKs and SEQs are exactly.
  41. * If the remote host responds correctly as we expect (checking the schedule position expectation
  42. * as packets are received) then we proceed in the schedule whether the next event is to send a local
  43. * packet or wait for a remote packet to arrive.
  44. *
  45. * 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 #>
  46. *
  47. * Example:
  48. * yhsiam@yhsiam-VirtualBox:~$ tcpliveplay eth0 test1.pcap 192.168.1.4 52:57:01:11:31:92 random
  49. *
  50. * NOTE: This program may not completely replay the packets due to the remote host responding in an unexpected
  51. * fashion such as responding with packets never seen in the given *.pcap file or coupling packets together, etc.
  52. * if you have any suggestion on improving this software or if you find any bugs, please let me know at my
  53. * email: tcpliveplay@gmail.com
  54. *
  55. * Past Contributors (Last contributed May 4, 2012): Andrew Leonard & Beau Luck
  56. *
  57. */
  58. #include "config.h"
  59. #include "defines.h"
  60. #include "common.h"
  61. #include <signal.h>
  62. #include <time.h>
  63. #include <utime.h>
  64. #include <ctype.h>
  65. #include <fcntl.h>
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <sys/types.h>
  70. #include <unistd.h>
  71. #include <errno.h>
  72. #include <stdbool.h>
  73. #include <sys/ioctl.h>
  74. #include <sys/types.h>
  75. #include <sys/socket.h>
  76. #include <net/if.h>
  77. #include <string.h>
  78. #include <sys/ioctl.h>
  79. #include <netinet/in.h>
  80. #include <net/if.h>
  81. #include <arpa/inet.h>
  82. #include "tcpliveplay.h"
  83. #include "tcpliveplay_opts.h"
  84. #include "common/sendpacket.h"
  85. #include "common/utils.h"
  86. #include "send_packets.h"
  87. volatile int didsig;
  88. #ifdef DEBUG /* set -DDEBUG=1 */
  89. int debug = 0;
  90. #endif
  91. pcap_t *set_live_filter(char *dev, input_addr* hostip, unsigned int port);
  92. pcap_t *set_offline_filter(char* file);
  93. pcap_t *live_handle;
  94. u_char *recvd_pkt_data = NULL;
  95. unsigned int buf_write_index = 0;
  96. unsigned int sched_index = 0;
  97. unsigned int initial_rseq=0;
  98. sendpacket_t *sp;
  99. unsigned int seed = 0;
  100. const u_char *packet_keeper_rprev = NULL;
  101. ether_hdr *etherhdr_rprev = NULL; /*g for Global header pointers used in pcap_loop callback*/
  102. tcp_hdr *tcphdr_rprev = NULL;
  103. ipv4_hdr *iphdr_rprev = NULL;
  104. unsigned int size_payload_prev = 0;
  105. unsigned int finack_rindex = 0;
  106. unsigned int acked_index = 0;
  107. unsigned int diff_payload_index = 0;
  108. bool different_payload = false;
  109. volatile sig_atomic_t keep_going = 1;
  110. int random_port();
  111. unsigned int pkts_scheduled=0; /* packet counter */
  112. struct tcp_sched* sched = NULL;
  113. void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
  114. void catch_alarm (int sig);
  115. int iface_addrs(char* iface, input_addr* ip, struct mac_addr* mac);
  116. int extmac(char* new_rmac_ptr, struct mac_addr* new_remotemac);
  117. int extip(char *ip_string, input_addr* new_remoteip);
  118. 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);
  119. int setup_sched(struct tcp_sched* sched);
  120. int relative_sched(struct tcp_sched* sched, u_int32_t first_rseq, int num_packets);
  121. int fix_all_checksum_liveplay(ipv4_hdr *iphdr);
  122. int compip(input_addr* lip, input_addr* rip, input_addr* pkgip);
  123. int do_checksum_liveplay(u_int8_t *data, int proto, int len);
  124. int do_checksum_math_liveplay(u_int16_t *data, int len);
  125. /**
  126. * This is the main function of the program that handles calling other
  127. * functions to implemented the needed operations of the replay functionaily.
  128. */
  129. int
  130. main(int argc, char **argv)
  131. {
  132. unsigned int k;
  133. int num_packets = 0;
  134. static const char random_strg[] = "random";
  135. char* iface = argv[1];
  136. char* new_rmac_ptr;
  137. char* new_rip_ptr;
  138. input_addr new_remoteip;
  139. struct mac_addr new_remotemac;
  140. input_addr myip;
  141. struct mac_addr mymac;
  142. int new_src_port = 0;
  143. unsigned int retransmissions = 0;
  144. pcap_t *local_handle;
  145. char errbuf[PCAP_ERRBUF_SIZE];
  146. char ebuf[SENDPACKET_ERRBUF_SIZE];
  147. int i;
  148. optionProcess(&tcpliveplayOptions, argc, argv); /*Process AutoOpts for manpage options*/
  149. if((argc < 5) || (argv[1]==NULL) || (argv[2]==NULL) || (argv[3]==NULL) || (argv[4]==NULL) || (argv[5]==NULL)){
  150. printf("ERROR: Incorrect Usage!\n");
  151. 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");
  152. printf("Example:\n yhsiam@yhsiam-VirtualBox:~$ sudo tcpliveplay eth0 test1.pcap 192.168.1.4 52:57:01:11:31:92 random\n\n");
  153. exit(0);
  154. }
  155. if (strlen(iface) > IFNAMSIZ - 1)
  156. errx(-1, "Invalid interface name %s\n", iface);
  157. if (iface_addrs(iface, &myip, &mymac) < 0) /* Extract MAC of interface replay is being request on */
  158. errx(-1, "Failed to access interface %s\n", iface);
  159. /* open send function socket*/
  160. if ((sp = sendpacket_open(iface, ebuf, TCPR_DIR_C2S, SP_TYPE_NONE, NULL)) == NULL)
  161. errx(-1, "Can't open %s: %s", argv[1], ebuf);
  162. /*for(int i = 0; i<10; i++) tolower(port_mode[i]);*/
  163. if(strcmp(argv[5], random_strg)==0)
  164. new_src_port = random_port();
  165. else
  166. new_src_port = atoi(argv[5]);
  167. if (new_src_port < 0 || new_src_port > 65535)
  168. errx(new_src_port, "Cannot use source port %d", new_src_port);
  169. printf("new source port:: %d\n", new_src_port);
  170. /* Establish a handler for SIGALRM signals. */
  171. /* This is used as timeout for unresponsive remote hosts */
  172. signal (SIGALRM, catch_alarm);
  173. /* Extract new Remote MAC & IP inputed at command line */
  174. new_rmac_ptr= argv[4];
  175. new_rip_ptr = argv[3];
  176. /* These function setup the MAC & IP addresses in the mac_addr & in_addr structs */
  177. if (extmac(new_rmac_ptr, &new_remotemac) == ERROR)
  178. errx(-1, "failed to parse mac address %s\n", new_rmac_ptr);
  179. if (extip(new_rip_ptr, &new_remoteip) == ERROR)
  180. errx(-1, "failed to parse IP address %s\n", new_rip_ptr);
  181. /* Rewrites the given "*.pcap" file with all the new parameters and returns the number of packets */
  182. /* that need to be replayed */
  183. num_packets = rewrite(&new_remoteip, &new_remotemac, &myip, &mymac, argv[2], new_src_port);
  184. if (num_packets < 2)
  185. errx(-1, "Unable to rewrite PCAP file %s\n",argv[2]);
  186. /* create schedule & set it up */
  187. sched = (struct tcp_sched*) malloc(num_packets*sizeof(struct tcp_sched));
  188. if (!sched)
  189. err(-1, "out of memory\n");
  190. pkts_scheduled = setup_sched(sched); /* Returns number of packets in schedule*/
  191. /* Set up the schedule struct to be relative numbers rather than absolute*/
  192. for (i = 0; i < num_packets; i++) {
  193. sched[i].exp_rseq = 0;
  194. sched[i].exp_rack = 0;
  195. }
  196. relative_sched(sched, sched[1].exp_rseq, num_packets);
  197. printf("Packets Scheduled %u\n", pkts_scheduled);
  198. /* Open socket for savedfile traffic to be sent*/
  199. local_handle = pcap_open_offline("newfile.pcap", errbuf); /*call pcap library function*/
  200. if (local_handle == NULL) {
  201. fprintf(stderr,"Couldn't open pcap file %s: %s\n", "newfile.pcap", errbuf);
  202. free(sched);
  203. return(2);
  204. }
  205. /* Open socket for live traffic to be listed to*/
  206. live_handle = set_live_filter(iface, &myip, new_src_port); /* returns a pcap_t that filters out traffic other than TCP*/
  207. if (live_handle == NULL) {
  208. fprintf(stderr,"Error occurred while listing on traffic: %s\n", errbuf);
  209. free(sched);
  210. return(2);
  211. }
  212. /* Printout when no packets are scheduled */
  213. if(pkts_scheduled==0){
  214. printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  215. printf("+ ERROR:: There are no TCP packets to send +\n");
  216. printf("+ Closing replay... +\n");
  217. printf("+ Thank you for Playing, Play again! +\n");
  218. printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
  219. free(sched);
  220. return ERROR;
  221. }
  222. /* Start replay by sending the first packet, the SYN, from the schedule */
  223. else if(sched[0].local){ /* Send first packet*/
  224. sendpacket(sp, sched[sched_index].packet_ptr, sched[sched_index].pkthdr.len, &sched[sched_index].pkthdr);
  225. printf("Sending Local Packet............... [%u]\n",sched_index+1);
  226. sched_index++; /* Proceed in the schedule */
  227. }
  228. /* Main while loop that handles the decision making and the replay oprations */
  229. while(sched_index<pkts_scheduled){
  230. if(!keep_going) { /*Check the timeout variable */
  231. printf("\n======================================================================\n");
  232. printf("= TIMEOUT:: Remote host is not responding. You may have crashed =\n");
  233. printf("= the host you replayed these packets against OR the packet sequence =\n");
  234. printf("= changed since the capture was taken resulting in differing =\n");
  235. printf("= expectations. Closing replay... =\n");
  236. printf("======================================================================\n\n");
  237. break;
  238. }
  239. /* tcphdr_rprev carries the last remote tcp header */
  240. if(tcphdr_rprev == NULL) {
  241. //printf("FIRST PASS!\n");
  242. }
  243. /* Check if received RST or RST-ACK flagged packets*/
  244. else if((tcphdr_rprev->th_flags==TH_RST) || (tcphdr_rprev->th_flags==(TH_RST|TH_ACK))){
  245. printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  246. printf("+ ERROR:: Remote host has requested to RESET the connection. +\n");
  247. printf("+ Closing replay... +\n");
  248. printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
  249. break;
  250. }
  251. /*Check if received earlier FIN-ACK than expected
  252. else if((sched_index-1 < finack_rindex) && (tcphdr_rprev->th_flags==(TH_FIN|TH_ACK))){
  253. printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  254. printf("+ ERROR:: Remote host sent an earlier FIN-ACK than expected. +\n");
  255. printf("+ Closing replay... +\n");
  256. printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
  257. return;
  258. } */
  259. /* Do the following if we receive a packet that ACKs for the same ACKing of next packet */
  260. 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)){
  261. printf("Received Remote Packet............... [%u]\n",sched_index+1);
  262. printf("Skipping Packet...................... [%u] to Packet [%u]\n",sched_index+1, sched_index+2);
  263. printf("Next Remote Packet Expectation met.\nProceeding in replay...\n");
  264. sched_index++;
  265. }
  266. /* Do the following if payload does not meet expectation and re-attempt with the remote host for 3 tries*/
  267. else if(different_payload){
  268. printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  269. printf("+ WARNING: Remote host is not meeting packet size expectations. +\n");
  270. printf("+ for packet %-u. Application layer data differs from capture being replayed. +\n", diff_payload_index+1);
  271. printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
  272. printf("Requesting retransmission.\n Proceeding...\n");
  273. different_payload = false;
  274. }
  275. /* Local Packets */
  276. if(sched[sched_index].local) {
  277. /*Reset alarm timeout*/
  278. alarm (ALARM_TIMEOUT);
  279. printf("Sending Local Packet............... [%u]\n", sched_index + 1);
  280. /* edit each packet tcphdr before sending based on the schedule*/
  281. if(sched_index>0){
  282. sched[sched_index].tcphdr->th_ack = htonl(sched[sched_index].curr_lack);
  283. fix_all_checksum_liveplay(sched[sched_index].iphdr);
  284. }
  285. /* If 3 attempts of resending was made, then error out to the user */
  286. if(sched[sched_index].sent_counter==3){
  287. printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  288. printf("+ ERROR: Re-sent packet [%-u] 3 times, but remote host is not +\n", sched_index+1);
  289. printf("+ responding as expected. 3 resend attempts are a maximum. +\n");
  290. printf("+ Closing replay... +\n");
  291. printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
  292. break;
  293. }
  294. /* If nothing goes wrong, then send the packet scheduled to be sent, then proceed in the schedule */
  295. sendpacket(sp, sched[sched_index].packet_ptr, sched[sched_index].pkthdr.len, &sched[sched_index].pkthdr);
  296. sched[sched_index].sent_counter++; /* Keep track of how many times this specific packet was attempted */
  297. sched_index++; /* proceed */
  298. }
  299. /* Remote Packets */
  300. else if(sched[sched_index].remote){
  301. alarm (ALARM_TIMEOUT);
  302. printf("Receiving Packets from remote host...\n");
  303. pcap_dispatch(live_handle, 1, got_packet, NULL); /* Listen in on NIC for tcp packets */
  304. //printf("pcap_loop returned\n");
  305. }
  306. } /* end of main while loop*/
  307. pcap_breakloop(live_handle);
  308. pcap_close(live_handle);
  309. sendpacket_close(sp); /* Close Send socket*/
  310. remove("newfile.pcap"); /* Remote the rewritten file that was created*/
  311. for(k=0; k<pkts_scheduled; k++){
  312. retransmissions+=sched[k].sent_counter;
  313. }
  314. /* User Debug Result Printouts*/
  315. if(sched_index==pkts_scheduled){
  316. printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
  317. printf("~ CONGRATS!!! You have successfully Replayed your pcap file '%s'\n", argv[2]);
  318. printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
  319. }
  320. else {
  321. printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
  322. printf("~ Unfortunately an error has occurred halting the replay of\n");
  323. printf("~ the pcap file '%s'. Please see error above for details...\n", argv[2]);
  324. printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
  325. }
  326. printf("----------------TCP Live Play Summary----------------\n");
  327. printf("- Packets Scheduled to be Sent & Received: %-u\n", pkts_scheduled);
  328. printf("- Actual Packets Sent & Received: %-u\n", sched_index);
  329. printf("- Total Local Packet Re-Transmissions due to packet\n");
  330. printf("- loss and/or differing payload size than expected: %-u\n", retransmissions);
  331. printf("- Thank you for Playing, Play again!\n");
  332. printf("----------------------------------------------------------\n\n");
  333. free(sched);
  334. restore_stdin();
  335. return 0;
  336. }
  337. /*end of main() function*/
  338. /**
  339. * This function serves as a timer alarm
  340. */
  341. void
  342. catch_alarm (int sig){
  343. keep_going = 0;
  344. signal (sig, catch_alarm);
  345. }
  346. static int tcplp_rand(void)
  347. {
  348. struct timeval tv;
  349. if (!seed) {
  350. gettimeofday(&tv, NULL);
  351. seed = (unsigned int)tv.tv_sec ^ (unsigned int)tv.tv_usec;
  352. }
  353. return tcpr_random(&seed);
  354. }
  355. /**
  356. * This function returns a random number between 49152 and 65535
  357. */
  358. int
  359. random_port()
  360. {
  361. int random = tcplp_rand();
  362. return (49152 + (random % 16383));
  363. }
  364. /**
  365. * This function sets up the scheduled local ACK and Remote SEQ to be relative numbers,
  366. * While it sets up the local SEQs and remote ACKs to be absolute within the schedule.
  367. */
  368. int
  369. relative_sched(struct tcp_sched* sched, u_int32_t first_rseq, int num_packets){
  370. int i;
  371. u_int32_t lseq_adjust = tcplp_rand();
  372. printf("Random Local SEQ: %u\n",lseq_adjust);
  373. u_int32_t first_lseq = sched[0].curr_lseq; /* SYN Packet SEQ number */
  374. /* Fix schedule to relative and absolute */
  375. for(i = 0; i < num_packets; i++){
  376. if(sched[i].local){
  377. sched[i].curr_lseq = sched[i].curr_lseq - first_lseq; /* Fix current local SEQ to relative */
  378. sched[i].curr_lseq = sched[i].curr_lseq + lseq_adjust; /* Make absolute. lseq_adjust is the locally generated random number */
  379. sched[i].curr_lack = sched[i].curr_lack - first_rseq; /* Fix current local ACK to relative */
  380. if (sched[i].tcphdr)
  381. sched[i].tcphdr->th_seq = htonl(sched[i].curr_lseq); /* Edit the actual packet header data */
  382. fix_all_checksum_liveplay(sched[i].iphdr); /* Fix the checksum */
  383. sched[i].exp_rseq = sched[i].exp_rseq - first_rseq;
  384. sched[i].exp_rack = sched[i].exp_rack - first_lseq;
  385. sched[i].exp_rack = sched[i].exp_rack + lseq_adjust;
  386. }
  387. else if(sched[i].remote){
  388. sched[i].exp_rseq = sched[i].exp_rseq - first_rseq; /* Fix expected remote SEQ to be relative */
  389. sched[i].exp_rack = sched[i].exp_rack - first_lseq; /* Fix expected remote ACK to be relative*/
  390. sched[i].exp_rack = sched[i].exp_rack + lseq_adjust; /* Fix expected remote ACK to be absolute */
  391. }
  392. }
  393. return SUCCESS;
  394. }
  395. /**
  396. * This function sets up the schedule for the rest of the program
  397. * extracting all the needed information from the given pcap file
  398. * and coping into memory (into a struct format)
  399. *
  400. */
  401. int
  402. setup_sched(struct tcp_sched* sched){
  403. input_addr sip, dip; /* Source & Destination IP */
  404. input_addr local_ip, remote_ip; /* ip address of client and server*/
  405. pcap_t *local_handle;
  406. const u_char *packet; /* The actual packet */
  407. unsigned int flags=0;
  408. struct pcap_pkthdr header; // The header that pcap gives us
  409. unsigned int pkt_counter=0;
  410. bool remote = false; /* flags to test if data is from 'client'=local or 'server'=remote */
  411. bool local = false;
  412. unsigned int i = 0;
  413. local_ip.byte1=0;
  414. local_ip.byte2=0;
  415. local_ip.byte3=0;
  416. local_ip.byte4=0;
  417. remote_ip.byte1=0;
  418. remote_ip.byte2=0;
  419. remote_ip.byte3=0;
  420. remote_ip.byte4=0;
  421. char errbuf[PCAP_ERRBUF_SIZE];
  422. local_handle = pcap_open_offline("newfile.pcap", errbuf); /*call pcap library function*/
  423. if (local_handle == NULL) {
  424. fprintf(stderr,"Couldn't open pcap file %s: %s\n", "newfile.pcap", errbuf);
  425. return(2);
  426. }
  427. /*Before sending any packet, setup the schedule with the proper parameters*/
  428. while((packet = safe_pcap_next(local_handle, &header))) {
  429. /*temporary packet buffers*/
  430. ether_hdr *etherhdr;
  431. tcp_hdr *tcphdr;
  432. ipv4_hdr *iphdr;
  433. unsigned int size_ip;
  434. unsigned int size_tcp;
  435. unsigned int size_payload;
  436. pkt_counter++; /*increment number of packets seen*/
  437. memcpy(&sched[i].pkthdr, &header, sizeof(struct pcap_pkthdr));
  438. sched[i].packet_ptr = safe_malloc(sched[i].pkthdr.len);
  439. memcpy(sched[i].packet_ptr, packet, sched[i].pkthdr.len);
  440. /* extract necessary data */
  441. etherhdr = (ether_hdr*)(sched[i].packet_ptr);
  442. iphdr = (ipv4_hdr *)(sched[i].packet_ptr + SIZE_ETHERNET);
  443. size_ip = iphdr->ip_hl << 2;
  444. if (size_ip < 20) {
  445. printf("ERROR: Invalid IP header length: %u bytes\n", size_ip);
  446. return 0;
  447. }
  448. tcphdr = (tcp_hdr *)(sched[i].packet_ptr + SIZE_ETHERNET + size_ip);
  449. size_tcp = tcphdr->th_off*4;
  450. if (size_tcp < 20) {
  451. printf("ERROR: Invalid TCP header length: %u bytes\n", size_tcp);
  452. return 0;
  453. }
  454. /* payload = (u_char *)(sched[i].packet_ptr + SIZE_ETHERNET + size_ip + size_tcp); */
  455. size_payload = ntohs(iphdr->ip_len) - (size_ip + (size_tcp));
  456. /* Source IP and Destination IP */
  457. sip = iphdr->ip_src;
  458. dip = iphdr->ip_dst;
  459. flags = tcphdr->th_flags;
  460. if (flags == TH_SYN){ /* set IPs who's local and who's remote based on the SYN flag */
  461. local_ip = sip;
  462. remote_ip = dip;
  463. }
  464. /*Compare IPs to see which packet is this coming from*/
  465. if(compip(&local_ip, &remote_ip, &sip)==LOCAL_IP_MATCH){
  466. local = true;
  467. remote = false;
  468. }
  469. if(compip(&local_ip, &remote_ip, &sip)==REMOTE_IP_MATCH){
  470. local = false;
  471. remote = true;
  472. }
  473. /* Setup rest of Schedule, parameter by parameter */
  474. /* Refer to header file for details on each of the parameters */
  475. sched[i].etherhdr = etherhdr;
  476. sched[i].iphdr = iphdr;
  477. sched[i].tcphdr = tcphdr;
  478. sched[i].size_ip = size_ip;
  479. sched[i].size_tcp = size_tcp;
  480. sched[i].size_payload = size_payload;
  481. sched[i].sent_counter = 0;
  482. /* Do the following only for the first packet (SYN)*/
  483. if(i==0){
  484. sched[i].length_last_ldata = 0;
  485. sched[i].length_curr_ldata = 0;
  486. sched[i].length_last_rdata = 0;
  487. sched[i].length_curr_rdata = 0;
  488. sched[i].local = true;
  489. sched[i].remote = false;
  490. sched[i].curr_lseq = ntohl(sched[i].tcphdr->th_seq);
  491. sched[i].curr_lack = 0;
  492. sched[i].exp_rseq = 0; /* Keep track of previous remote seq & ack #s*/
  493. sched[i].exp_rack = 0;
  494. }
  495. /* Local Packet operations */
  496. else if(local){
  497. sched[i].length_last_ldata = sched[i-1].length_curr_ldata;
  498. sched[i].length_curr_ldata = size_payload;
  499. sched[i].length_last_rdata = sched[i-1].length_curr_rdata;
  500. sched[i].length_curr_rdata = 0;
  501. sched[i].local = true;
  502. sched[i].remote = false;
  503. sched[i].curr_lseq = ntohl(sched[i].tcphdr->th_seq);
  504. sched[i].curr_lack = ntohl(sched[i].tcphdr->th_ack);
  505. sched[i].exp_rseq = sched[i-1].exp_rseq; /* Keep track of previous remote seq & ack #s*/
  506. sched[i].exp_rack = sched[i-1].exp_rack;
  507. }
  508. /* Remote Packet operations */
  509. else if(remote){
  510. sched[i].length_last_ldata = sched[i-1].length_curr_ldata;
  511. sched[i].length_curr_ldata = 0;
  512. sched[i].length_last_rdata = sched[i-1].length_curr_rdata;
  513. sched[i].length_curr_rdata = size_payload;
  514. sched[i].local = false;
  515. sched[i].remote = true;
  516. sched[i].curr_lseq = sched[i-1].curr_lseq;
  517. sched[i].curr_lack = sched[i-1].curr_lack;
  518. sched[i].exp_rseq = ntohl(sched[i].tcphdr->th_seq); /* Keep track of previous remote seq & ack #s*/
  519. sched[i].exp_rack = ntohl(sched[i].tcphdr->th_ack);
  520. /* Setup global variable where remote FIN-ACK exists*/
  521. if(flags == (TH_FIN|TH_ACK)) finack_rindex = i;
  522. //printf("REMOTE --------%d\n",i+1);
  523. }
  524. i++; /* increment schedule index */
  525. } /*end internal loop for reading packets (all in one file)*/
  526. pcap_close(local_handle); /*close the pcap file*/
  527. return pkt_counter; /* Return number of packets scheduled */
  528. }
  529. /**
  530. * This function returns a pcap_t for the live traffic handler which
  531. * filters out traffic other than TCP
  532. *
  533. */
  534. pcap_t*
  535. set_live_filter(char *dev, input_addr* hostip, unsigned int port)
  536. {
  537. pcap_t *handle = NULL; /* Session handle */
  538. char errbuf[PCAP_ERRBUF_SIZE]; /* Error string buffer */
  539. struct bpf_program fp; /* The compiled filter */
  540. char filter_exp[52];
  541. sprintf(filter_exp,"tcp and dst host %d.%d.%d.%d and dst port %u",
  542. hostip->byte1, hostip->byte2, hostip->byte3, hostip->byte4, port); /* The filter expression */
  543. bpf_u_int32 mask; /* Our network mask */
  544. bpf_u_int32 net; /* Our IP */
  545. /* Define the device */
  546. if (dev == NULL) {
  547. fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
  548. return handle;
  549. }
  550. /* Find the properties for the device */
  551. if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
  552. fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
  553. net = 0;
  554. mask = 0;
  555. }
  556. /* Open the session in promiscuous mode */
  557. handle = pcap_open_live(dev, BUFSIZ_PLUS, PROMISC_OFF, TIMEOUT_ms, errbuf);
  558. if (handle == NULL) {
  559. fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
  560. return handle;
  561. }
  562. /* Compile and apply the filter */
  563. if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
  564. fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
  565. return handle;
  566. }
  567. if (pcap_setfilter(handle, &fp) == -1) {
  568. fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
  569. return handle;
  570. }
  571. pcap_freecode(&fp);
  572. return handle;
  573. }
  574. /**
  575. * This function returns a pcap_t for the savedfile traffic handler which
  576. * filters out traffic other than TCP
  577. *
  578. */
  579. pcap_t*
  580. set_offline_filter(char* file)
  581. {
  582. pcap_t *handle; /* Session handle */
  583. char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
  584. struct bpf_program fp; /* The compiled filter */
  585. char filter_exp[] = "tcp";
  586. bpf_u_int32 net=0; /* Our IP */
  587. /* Open savedfile */
  588. handle = pcap_open_offline(file, errbuf);
  589. if (handle == NULL) {
  590. fprintf(stderr, "Couldn't open file %s\n", errbuf);
  591. return handle;
  592. }
  593. /* Compile and apply the filter */
  594. if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
  595. fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
  596. return handle;
  597. }
  598. if (pcap_setfilter(handle, &fp) == -1) {
  599. fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
  600. return handle;
  601. }
  602. pcap_freecode(&fp);
  603. return handle;
  604. }
  605. /**
  606. * This is the callback function for pcap_loop
  607. * This function is called every time we receive a remote packet
  608. */
  609. void
  610. got_packet(_U_ u_char *args, _U_ const struct pcap_pkthdr *header,
  611. const u_char *packet)
  612. {
  613. ether_hdr *etherhdr;
  614. tcp_hdr *tcphdr;
  615. ipv4_hdr *iphdr;
  616. unsigned int size_ip, size_tcp, size_payload;
  617. unsigned int flags = 0;
  618. /* Extract and examine received packet headers */
  619. etherhdr = (ether_hdr*)(packet);
  620. iphdr = (ipv4_hdr *)(packet + SIZE_ETHERNET);
  621. size_ip = iphdr->ip_hl << 2;
  622. if (size_ip < 20) {
  623. printf("ERROR: Invalid IP header length: %u bytes\n", size_ip);
  624. return;
  625. }
  626. tcphdr = (tcp_hdr *)(packet + SIZE_ETHERNET + size_ip);
  627. size_tcp = tcphdr->th_off*4;
  628. if (size_tcp < 20) {
  629. printf("ERROR: Invalid TCP header length: %u bytes\n", size_tcp);
  630. return;
  631. }
  632. size_payload = ntohs(iphdr->ip_len) - (size_ip + (size_tcp));
  633. flags = tcphdr->th_flags;
  634. /* Check correct SYN-ACK expectation, if so then proceed in fixing entire schedule from relative to absolute SEQs+ACKs */
  635. if((flags == (TH_SYN|TH_ACK)) && (sched_index==1) && (tcphdr->th_ack==htonl(sched[sched_index-1].curr_lseq + 1))){
  636. unsigned int j;
  637. printf("Received Remote Packet............... [%u]\n", sched_index + 1);
  638. printf("Remote Pakcet Expectation met.\nProceeding in replay....\n");
  639. //printf("SYN-ACKed Random SEQ set!\n");
  640. initial_rseq = ntohl(tcphdr->th_seq);
  641. //printf("initial_rseq: %u\n", initial_rseq);
  642. /* After we receiving the first SYN-ACK, then adjust the entire sched to be absolute rather than relative #s*/
  643. sched[1].exp_rseq = sched[1].exp_rseq + initial_rseq;
  644. for(j = 2; j<pkts_scheduled; j++){ /* Based on correctly receiving the random SEQ from the SYN-ACK packet, do the following:*/
  645. if(sched[j].local){ /* Set local ACKs for entire sched to be absolute #s*/
  646. sched[j].curr_lack = sched[j].curr_lack + initial_rseq;
  647. }
  648. else if(sched[j].remote){ /* Set remote SEQs for entire sched to be absolute #s*/
  649. sched[j].exp_rseq = sched[j].exp_rseq + initial_rseq;
  650. }
  651. }
  652. sched_index++; /* Proceed in the schedule*/
  653. return;
  654. }
  655. printf(">Received a Remote Packet\n");
  656. printf(">>Checking Expectations\n");
  657. /* Handle Remote Packet Loss */
  658. if(sched[sched_index].exp_rack > ntohl(tcphdr->th_ack)) {
  659. //printf("Remote Packet Loss! Resending Lost packet\n");
  660. sched_index=acked_index; /* Reset the schedule index back to the last correctly ACKed packet */
  661. //printf("ACKED Index = %d\n", acked_index);
  662. while(!sched[sched_index].local){
  663. sched_index++;
  664. }
  665. return;
  666. }
  667. /* Handle Local Packet Loss <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<COME BACK TO THIS<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
  668. else if((sched[sched_index].exp_rseq < ntohl(tcphdr->th_seq)) && sched[sched_index].remote){
  669. /* Resend immediate previous LOCAL packet */
  670. printf("Local Packet Loss! Resending Lost packet >> DupACK Issued!\n");
  671. sched_index=acked_index; /* Reset the schedule index back to the last correctly ACKed packet */
  672. /*sched[sched_index].sent_counter=0; Reset the re-transmission counter for this ACKed packet?*/
  673. //printf("ACKED Index = %d\n", acked_index);
  674. while(!sched[sched_index].local){
  675. sched_index++;
  676. }
  677. return;
  678. }
  679. /* No Packet Loss... Proceed Normally (if expectations are met!) */
  680. else if((tcphdr->th_seq==htonl(sched[sched_index].exp_rseq)) &&
  681. (tcphdr->th_ack==htonl(sched[sched_index].exp_rack))){
  682. printf("Received Remote Packet............... [%d]\n",sched_index+1);
  683. /* Handles differing payload size and does not trigger on unnecessary ACK + window update issues*/
  684. if((sched[sched_index].size_payload!=size_payload) && (size_payload!=0)){
  685. printf("Payload size of received packet does not meet expectations\n");
  686. /* Resent last local packet, maybe remote host behaves this time*/
  687. different_payload=true;
  688. /* Set global variable of where differing payload size is not meeting expectations*/
  689. diff_payload_index = sched_index;
  690. /*Treat this as packet loss, and attempt resetting index to resend packets where*/
  691. /* packets were received matching expectation*/
  692. sched_index=acked_index; /* Reset the schedule index back to the last correctly ACKed packet */
  693. //printf("ACKED Index = %d\n", acked_index);
  694. while(!sched[sched_index].local){
  695. sched_index++;
  696. }
  697. return;
  698. }
  699. printf("Remote Packet Expectation met.\nProceeding in replay....\n");
  700. sched_index++;
  701. acked_index = sched_index; /*Keep track correctly ACKed packet index*/
  702. }
  703. /* Global variable to keep tack of last received packet info */
  704. packet_keeper_rprev = packet;
  705. etherhdr_rprev = etherhdr;
  706. tcphdr_rprev = tcphdr;
  707. iphdr_rprev = iphdr;
  708. size_payload_prev = size_payload;
  709. return;
  710. }
  711. /**
  712. * This function prints out the ip address, given an in_addr struct pointer
  713. *
  714. */
  715. void
  716. printip(input_addr* IP)
  717. {
  718. printf("[%d.%d.%d.%d]\n", IP->byte1, IP->byte2, IP->byte3, IP->byte4);
  719. return;
  720. }
  721. /**
  722. * This function prints out the mac address, given a mac_addr struct pointer
  723. *
  724. */
  725. void
  726. printmac(struct mac_addr* MAC)
  727. {
  728. printf("[%x:%x:%x:%x:%x:%x]\n", MAC->byte1, MAC->byte2, MAC->byte3, MAC->byte4, MAC->byte5, MAC->byte6);
  729. return;
  730. }
  731. /**
  732. * This function compares two IPs,
  733. * returns 1 if match with local ip
  734. * returns 2 if matches with remote ip
  735. * returns 0 if no match
  736. *
  737. */
  738. int
  739. compip(input_addr* lip, input_addr* rip, input_addr* pkgip)
  740. {
  741. if((lip->byte1==pkgip->byte1)&&(lip->byte2==pkgip->byte2)&&(lip->byte3==pkgip->byte3)&&(lip->byte4==pkgip->byte4))
  742. return LOCAL_IP_MATCH;
  743. else if((rip->byte1==pkgip->byte1)&&(rip->byte2==pkgip->byte2)&&(rip->byte3==pkgip->byte3)&&(rip->byte4==pkgip->byte4))
  744. return REMOTE_IP_MATCH;
  745. else
  746. return NO_MATCH;
  747. }
  748. /**
  749. * This function sets the IP and MAC of a given interface (i.e. eth0)
  750. * into in_addr & mac_addr struct pointers
  751. *
  752. */
  753. int iface_addrs(char* iface, input_addr* ip, struct mac_addr* mac)
  754. {
  755. int s;
  756. struct ifreq buffer;
  757. s = socket(PF_INET, SOCK_DGRAM, 0);
  758. if (s < 0)
  759. return -1;
  760. memset(&buffer, 0x00, sizeof(buffer));
  761. strncpy(buffer.ifr_name, iface, sizeof(buffer.ifr_name)-1);
  762. int res;
  763. if ((res = ioctl(s, SIOCGIFADDR, &buffer)) < 0)
  764. goto done;
  765. struct in_addr localip = ((struct sockaddr_in *)&buffer.ifr_addr)->sin_addr;
  766. #if defined( WORDS_BIGENDIAN )
  767. ip->byte1 = (localip.s_addr)>>24;
  768. ip->byte2 = ((localip.s_addr)>>16)&255;
  769. ip->byte3 = ((localip.s_addr)>>8)&255;
  770. ip->byte4 = (localip.s_addr)&255;
  771. #else
  772. ip->byte4 = (localip.s_addr)>>24;
  773. ip->byte3 = ((localip.s_addr)>>16)&255;
  774. ip->byte2 = ((localip.s_addr)>>8)&255;
  775. ip->byte1 = (localip.s_addr)&255;
  776. #endif
  777. if ((res = ioctl(s, SIOCGIFHWADDR, &buffer)) < 0)
  778. goto done;
  779. mac->byte1 = buffer.ifr_hwaddr.sa_data[0];
  780. mac->byte2 = buffer.ifr_hwaddr.sa_data[1];
  781. mac->byte3 = buffer.ifr_hwaddr.sa_data[2];
  782. mac->byte4 = buffer.ifr_hwaddr.sa_data[3];
  783. mac->byte5 = buffer.ifr_hwaddr.sa_data[4];
  784. mac->byte6 = buffer.ifr_hwaddr.sa_data[5];
  785. done:
  786. close(s);
  787. return res;
  788. }
  789. /**
  790. * This function rewrites the IPs and MACs of a given packet,
  791. * creates a newfile.pcap. It returns the number of packets of the newfile.
  792. * This function only starts rewriting the newfile once it sees the first
  793. * SYN packet. This is so that the first packet in the newfile is always
  794. * the first packet to be sent.
  795. */
  796. int
  797. rewrite(input_addr* new_remoteip, struct mac_addr* new_remotemac, input_addr* myip, struct mac_addr* mymac, char* file, unsigned int new_src_port)
  798. {
  799. char *newfile = "newfile.pcap";
  800. int pkt_counter;
  801. input_addr local_ip;
  802. input_addr remote_ip;
  803. const u_char *packet;
  804. struct pcap_pkthdr *header;
  805. pcap_dumper_t *dumpfile;
  806. input_addr sip; /* Source IP */
  807. int local_packets = 0;
  808. bool initstep1 = false; /* keep track of successful handshake step */
  809. bool warned = false;
  810. local_ip.byte1=0;
  811. local_ip.byte2=0;
  812. local_ip.byte3=0;
  813. local_ip.byte4=0;
  814. remote_ip.byte1=0;
  815. remote_ip.byte2=0;
  816. remote_ip.byte3=0;
  817. remote_ip.byte4=0;
  818. pcap_t *pcap = set_offline_filter(file);
  819. if (!pcap){
  820. char ErrBuff [1024];
  821. fprintf (stderr, "Cannot open PCAP file '%s' for reading\n", file);
  822. fprintf(stderr, "%s\n",ErrBuff);
  823. return PCAP_OPEN_ERROR;
  824. }
  825. dumpfile = pcap_dump_open(pcap, newfile);
  826. if (!dumpfile) {
  827. fprintf (stderr, "Cannot open PCAP file '%s' for writing\n", newfile);
  828. return PCAP_OPEN_ERROR;
  829. }
  830. /*Modify each packet's IP & MAC based on the passed args then do a checksum of each packet*/
  831. for (pkt_counter = 0; safe_pcap_next_ex(pcap, &header, &packet) > 0; pkt_counter++){
  832. unsigned int flags, size_ip;
  833. ether_hdr* etherhdr;
  834. ipv4_hdr *iphdr;
  835. tcp_hdr *tcphdr;
  836. unsigned int size_tcp;
  837. if (!warned && header->len > header->caplen) {
  838. fprintf(stderr, "warning: packet capture truncated to %d byte packets\n",
  839. header->caplen);
  840. warned = true;
  841. }
  842. etherhdr = (ether_hdr*)(packet);
  843. iphdr = (ipv4_hdr *)(packet + SIZE_ETHERNET);
  844. size_ip = iphdr->ip_hl << 2;
  845. if (size_ip < 20) {
  846. printf("ERROR: Invalid IP header length: %u bytes\n", size_ip);
  847. return ERROR;
  848. }
  849. tcphdr = (tcp_hdr *)(packet + SIZE_ETHERNET + size_ip);
  850. size_tcp = tcphdr->th_off*4;
  851. if (size_tcp < 20) {
  852. printf("ERROR: Invalid TCP header length: %u bytes\n", size_tcp);
  853. return ERROR;
  854. }
  855. /* payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp); */
  856. sip = iphdr->ip_src;
  857. flags = tcphdr->th_flags;
  858. /* set IPs who's local and who's remote based on the SYN flag */
  859. if(flags == TH_SYN){
  860. local_ip = iphdr->ip_src;
  861. remote_ip = iphdr->ip_dst;
  862. initstep1 = true; /* This flag is set to signify the first encounter of the SYN within the pacp*/
  863. }
  864. if(compip(&local_ip, &remote_ip, &sip)==LOCAL_IP_MATCH){
  865. /* Set the source MAC */
  866. etherhdr->ether_shost[0] = mymac->byte1;
  867. etherhdr->ether_shost[1] = mymac->byte2;
  868. etherhdr->ether_shost[2] = mymac->byte3;
  869. etherhdr->ether_shost[3] = mymac->byte4;
  870. etherhdr->ether_shost[4] = mymac->byte5;
  871. etherhdr->ether_shost[5] = mymac->byte6;
  872. /* Set the source IP */
  873. iphdr->ip_src = *myip;
  874. /* Set the destination IP */
  875. iphdr->ip_dst = *new_remoteip;
  876. /* Set the destination MAC */
  877. etherhdr->ether_dhost[0] = new_remotemac->byte1;
  878. etherhdr->ether_dhost[1] = new_remotemac->byte2;
  879. etherhdr->ether_dhost[2] = new_remotemac->byte3;
  880. etherhdr->ether_dhost[3] = new_remotemac->byte4;
  881. etherhdr->ether_dhost[4] = new_remotemac->byte5;
  882. etherhdr->ether_dhost[5] = new_remotemac->byte6;
  883. /* This is to change the source port, whether it is specified as random or as a port # by the user */
  884. tcphdr->th_sport = htons(new_src_port);
  885. }
  886. else if(compip(&local_ip, &remote_ip, &sip)==REMOTE_IP_MATCH){
  887. /* Set the destination MAC */
  888. etherhdr->ether_dhost[0] = mymac->byte1;
  889. etherhdr->ether_dhost[1] = mymac->byte2;
  890. etherhdr->ether_dhost[2] = mymac->byte3;
  891. etherhdr->ether_dhost[3] = mymac->byte4;
  892. etherhdr->ether_dhost[4] = mymac->byte5;
  893. etherhdr->ether_dhost[5] = mymac->byte6;
  894. /* Set the destination IP */
  895. iphdr->ip_dst = *myip;
  896. /* Set the source IP */
  897. iphdr->ip_src = *new_remoteip;
  898. /* Set the source MAC */
  899. etherhdr->ether_shost[0] = new_remotemac->byte1;
  900. etherhdr->ether_shost[1] = new_remotemac->byte2;
  901. etherhdr->ether_shost[2] = new_remotemac->byte3;
  902. etherhdr->ether_shost[3] = new_remotemac->byte4;
  903. etherhdr->ether_shost[4] = new_remotemac->byte5;
  904. etherhdr->ether_shost[5] = new_remotemac->byte6;
  905. /* This is to change the source port, whether it is specified as random or as a port # by the user */
  906. tcphdr->th_dport = htons(new_src_port);
  907. }
  908. /*Calculate & fix checksum for newly edited-packet*/
  909. fix_all_checksum_liveplay(iphdr);
  910. if(initstep1){ /*only start rewriting new pcap with SYN packets on wards*/
  911. local_packets ++;
  912. pcap_dump((u_char *)dumpfile, header, packet);
  913. }
  914. } /* end of while loop */
  915. pcap_close (pcap);
  916. pcap_dump_close(dumpfile);
  917. return local_packets;
  918. }
  919. /**
  920. * This function extracts the MAC address (from command line format
  921. * and sets the mac_addr struct)
  922. *
  923. */
  924. int
  925. extmac(char* new_rmac_ptr, struct mac_addr* new_remotemac)
  926. {
  927. u_int8_t new_rmac[6];
  928. if (sscanf (new_rmac_ptr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &new_rmac[0], &new_rmac[1],
  929. &new_rmac[2], &new_rmac[3], &new_rmac[4], &new_rmac[5]) != 6)
  930. return ERROR;
  931. new_remotemac->byte1 = (unsigned char)new_rmac[0];
  932. new_remotemac->byte2 = (unsigned char)new_rmac[1];
  933. new_remotemac->byte3 = (unsigned char)new_rmac[2];
  934. new_remotemac->byte4 = (unsigned char)new_rmac[3];
  935. new_remotemac->byte5 = (unsigned char)new_rmac[4];
  936. new_remotemac->byte6 = (unsigned char)new_rmac[5];
  937. return SUCCESS;
  938. }
  939. /**
  940. * This function extracts the IP address (from command line format
  941. * and sets the in_addr struct)
  942. *
  943. */
  944. int
  945. extip(char *ip_string, input_addr* new_remoteip)
  946. {
  947. struct in_addr addr;
  948. if (inet_aton(ip_string, &addr) == 0)
  949. return ERROR;
  950. #if defined( WORDS_BIGENDIAN )
  951. new_remoteip->byte4 = (unsigned char)addr.s_addr & 0xff;
  952. new_remoteip->byte3 = (unsigned char)(addr.s_addr >> 8) & 0xff;
  953. new_remoteip->byte2 = (unsigned char)(addr.s_addr >> 16) & 0xff;
  954. new_remoteip->byte1 = (unsigned char)(addr.s_addr >> 24) & 0xff;
  955. #else
  956. new_remoteip->byte1 = (unsigned char)addr.s_addr & 0xff;
  957. new_remoteip->byte2 = (unsigned char)(addr.s_addr >> 8) & 0xff;
  958. new_remoteip->byte3 = (unsigned char)(addr.s_addr >> 16) & 0xff;
  959. new_remoteip->byte4 = (unsigned char)(addr.s_addr >> 24) & 0xff;
  960. #endif
  961. return SUCCESS;
  962. }
  963. /**
  964. * This function calls all the checksum function given the IP Header
  965. * and edits the checksums fixing them appropriately
  966. *
  967. */
  968. int
  969. fix_all_checksum_liveplay(ipv4_hdr *iphdr){
  970. int ret1 = 0, ret2 = 0;
  971. /*Calculate TCP Checksum*/
  972. ret2 = do_checksum_liveplay((u_char *) iphdr,iphdr->ip_p, ntohs(iphdr->ip_len) - (iphdr->ip_hl << 2));
  973. if(ret2==-1){
  974. printf("*******An Error Occurred calculating TCP Checksum*******\n");
  975. return -1;
  976. }
  977. /*Calculate IP Checksum*/
  978. ret1 = do_checksum_liveplay((u_char *) iphdr, IPPROTO_IP, ntohs(iphdr->ip_len));
  979. if(ret1==-1){
  980. printf("*******An Error Occurred calculating IP Checksum*******\n");
  981. return -1;
  982. }
  983. return 0;
  984. }
  985. /************************************************************************************/
  986. /*[copied from Aaron Turnor's checksum.c, but omitting tcpedit_t structs] */
  987. /*[The following functions have been slightly modified to be integrated with tcpliveplay code structure] */
  988. /**
  989. * This code re-calcs the IP and Layer 4 checksums
  990. * the IMPORTANT THING is that the Layer 4 header
  991. * is contiguous in memory after *ip_hdr we're actually
  992. * writing to the layer 4 header via the ip_hdr ptr.
  993. * (Yes, this sucks, but that's the way libnet works, and
  994. * I was too lazy to re-invent the wheel.
  995. * Returns 0 on success, -1 on error
  996. */
  997. /**
  998. * Returns -1 on error and 0 on success, 1 on warn
  999. */
  1000. int
  1001. do_checksum_liveplay(u_int8_t *data, int proto, int len) {
  1002. ipv4_hdr *ipv4;
  1003. tcp_hdr *tcp;
  1004. int ip_hl;
  1005. volatile int sum = 0; // <-- volatile works around a PPC g++ bug
  1006. ipv4 = NULL;
  1007. ipv4 = (ipv4_hdr *)data;
  1008. ip_hl = ipv4->ip_hl << 2;
  1009. switch (proto) {
  1010. case IPPROTO_TCP:
  1011. tcp = (tcp_hdr *)(data + ip_hl);
  1012. #ifdef STUPID_SOLARIS_CHECKSUM_BUG
  1013. tcp->th_sum = tcp->th_off << 2;
  1014. return (TCPEDIT_OK);
  1015. #endif
  1016. tcp->th_sum = 0;
  1017. /* Note, we do both src & dst IP's at the same time, that's why the
  1018. * length is 2x a single IP
  1019. */
  1020. sum = do_checksum_math_liveplay((u_int16_t *)&ipv4->ip_src, 8);
  1021. sum += ntohs(IPPROTO_TCP + len);
  1022. sum += do_checksum_math_liveplay((u_int16_t *)tcp, len);
  1023. tcp->th_sum = CHECKSUM_CARRY(sum);
  1024. break;
  1025. case IPPROTO_IP:
  1026. ipv4->ip_sum = 0;
  1027. sum = do_checksum_math_liveplay((u_int16_t *)data, ip_hl);
  1028. ipv4->ip_sum = CHECKSUM_CARRY(sum);
  1029. break;
  1030. default:
  1031. printf("Unsupported protocol for checksum:\n");
  1032. return TCPEDIT_WARN;
  1033. }
  1034. return TCPEDIT_OK;
  1035. }
  1036. /**
  1037. * code to do a ones-compliment checksum
  1038. */
  1039. int
  1040. do_checksum_math_liveplay(u_int16_t *data, int len)
  1041. {
  1042. int sum = 0;
  1043. union {
  1044. u_int16_t s;
  1045. u_int8_t b[2];
  1046. } pad;
  1047. while (len > 1) {
  1048. sum += *data++;
  1049. len -= 2;
  1050. }
  1051. if (len == 1) {
  1052. pad.b[0] = *(u_int8_t *)data;
  1053. pad.b[1] = 0;
  1054. sum += pad.s;
  1055. }
  1056. return (sum);
  1057. }