tcprewrite.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /* $Id:$ */
  2. /*
  3. * Copyright (c) 2004-2005 Aaron Turner.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /*
  32. * Purpose: Modify packets in a pcap file based on rules provided by the
  33. * user to offload work from tcpreplay and provide a easier means of
  34. * reproducing traffic for testing purposes.
  35. */
  36. #include "config.h"
  37. #include "defines.h"
  38. #include "common.h"
  39. #include <ctype.h>
  40. #include <fcntl.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <sys/types.h>
  45. #include <unistd.h>
  46. #include "tcprewrite.h"
  47. #include "tcprewrite_opts.h"
  48. #include "portmap.h"
  49. #include "edit_packet.h"
  50. #include "mac.h"
  51. #include "rewrite_l2.h"
  52. #ifdef DEBUG
  53. int debug;
  54. #endif
  55. #ifdef HAVE_TCPDUMP
  56. /* tcpdump handle */
  57. tcpdump_t tcpdump;
  58. #endif
  59. COUNTER total_bytes, pkts_edited;
  60. tcprewrite_opt_t options;
  61. /* local functions */
  62. void validate_l2(pcap_t *pcap, char *filename, l2_t *l2);
  63. void init(void);
  64. void post_args(int argc, char *argv[]);
  65. void rewrite_packets(pcap_t *inpcap, pcap_dumper_t *outpcap);
  66. void verify_input_pcap(pcap_t *pcap);
  67. int main(int argc, char *argv[])
  68. {
  69. int optct;
  70. char ebuf[LIBNET_ERRBUF_SIZE];
  71. init();
  72. /* call autoopts to process arguments */
  73. optct = optionProcess(&tcprewriteOptions, argc, argv);
  74. argc -= optct;
  75. argv += optct;
  76. post_args(argc, argv);
  77. if ((options.l = libnet_init(LIBNET_RAW4, NULL, ebuf)) == NULL)
  78. errx(1, "Unable to open raw socket for libnet: %s", ebuf);
  79. #ifdef HAVE_TCPDUMP
  80. if (options.verbose) {
  81. tcpdump.filename = options.infile;
  82. tcpdump_open(&tcpdump);
  83. }
  84. #endif
  85. validate_l2(options.pin, options.infile, &options.l2);
  86. rewrite_packets(options.pin, options.pout);
  87. /* clean up after ourselves */
  88. libnet_destroy(options.l);
  89. pcap_dump_close(options.pout);
  90. pcap_close(options.pin);
  91. #ifdef HAVE_TCPDUMP
  92. tcpdump_close(&tcpdump);
  93. #endif
  94. return 0;
  95. }
  96. void
  97. init(void)
  98. {
  99. total_bytes = 0;
  100. memset(&options, 0, sizeof(options));
  101. options.mtu = DEFAULT_MTU; /* assume 802.3 Ethernet */
  102. options.l2.len = LIBNET_ETH_H;
  103. total_bytes = pkts_edited = 0;
  104. options.l2.linktype = LINKTYPE_ETHER;
  105. options.l2proto = ETHERTYPE_IP;
  106. #ifdef HAVE_TCPDUMP
  107. /* clear out tcpdump struct */
  108. memset(&tcpdump, '\0', sizeof(tcpdump_t));
  109. #endif
  110. if (fcntl(STDERR_FILENO, F_SETFL, O_NONBLOCK) < 0)
  111. warnx("Unable to set STDERR to non-blocking: %s", strerror(errno));
  112. }
  113. void
  114. post_args(int argc, char *argv[])
  115. {
  116. #ifdef DEBUG
  117. if (HAVE_OPT(DBUG))
  118. debug = OPT_VALUE_DBUG;
  119. #else
  120. if (HAVE_OPT(DBUG))
  121. warn("not configured with --enable-debug. Debugging disabled.");
  122. #endif
  123. #ifdef HAVE_TCPDUMP
  124. if (HAVE_OPT(VERBOSE))
  125. options.verbose = 1;
  126. if (HAVE_OPT(DECODE))
  127. tcpdump.args = safe_strdup(OPT_ARG(DECODE));
  128. #endif
  129. /* layer two protocol */
  130. if (HAVE_OPT(PROTO)) {
  131. options.l2proto = OPT_VALUE_PROTO;
  132. }
  133. /* open up the output file */
  134. options.outfile = safe_strdup(OPT_ARG(OUTFILE));
  135. if ((options.pout = pcap_dump_open(options.pin, options.outfile)) == NULL)
  136. errx(1, "Unable to open output pcap file: %s", pcap_geterr(options.pin));
  137. /*
  138. * If we have one and only one -N, then use the same map data
  139. * for both interfaces/files
  140. */
  141. if ((options.cidrmap1 != NULL) && (options.cidrmap2 == NULL))
  142. options.cidrmap2 = options.cidrmap1;
  143. /*
  144. * validate 802.1q vlan args and populate options.vlan_record
  145. */
  146. if (options.vlan) {
  147. if ((options.vlan == VLAN_ADD) && (HAVE_OPT(VLAN_TAG) == 0))
  148. err(1, "Must specify a new 802.1q VLAN tag if vlan mode is add");
  149. /*
  150. * fill out the 802.1q header
  151. */
  152. options.l2.linktype = LINKTYPE_VLAN;
  153. /* if VLAN_ADD then 802.1q header, else 802.3 header len */
  154. options.l2.len = options.vlan == VLAN_ADD ? LIBNET_802_1Q_H : LIBNET_ETH_H;
  155. dbg(1, "We will %s 802.1q headers", options.vlan == VLAN_DEL ? "delete" : "add/modify");
  156. }
  157. /*
  158. * IP address rewriting processing
  159. */
  160. if (HAVE_OPT(SEED)) {
  161. options.rewrite_ip ++;
  162. options.seed = OPT_VALUE_SEED;
  163. }
  164. if (HAVE_OPT(ENDPOINTS)) {
  165. options.rewrite_ip ++;
  166. if (!parse_endpoints(&options.cidrmap1, &options.cidrmap2, OPT_ARG(ENDPOINTS)))
  167. errx(1, "Unable to parse endpoints: %s", OPT_ARG(ENDPOINTS));
  168. }
  169. /*
  170. * Figure out the maxpacket len
  171. */
  172. if (options.l2.enabled) {
  173. /* custom L2 header */
  174. dbg(1, "Using custom L2 header to calculate max frame size");
  175. options.maxpacket = options.mtu + options.l2.len;
  176. }
  177. else if (options.l2.linktype == LINKTYPE_ETHER) {
  178. /* ethernet */
  179. dbg(1, "Using Ethernet to calculate max frame size");
  180. options.maxpacket = options.mtu + LIBNET_ETH_H;
  181. }
  182. else {
  183. /* oh fuck, we don't know what the hell this is, we'll just assume ethernet */
  184. options.maxpacket = options.mtu + LIBNET_ETH_H;
  185. warn("Unable to determine layer 2 encapsulation, assuming ethernet\n"
  186. "You may need to increase the MTU (-t <size>) if you get errors");
  187. }
  188. }
  189. /*
  190. * we can rewrite a number of linktypes into DLT_EN10MB (with or without 802.1q tags)
  191. * maybe in the future, we'll support outputs into other linktypes. But for now
  192. * we just need to make sure we have enough information (packet + user options)
  193. * to generate a valid ethernet frame
  194. */
  195. void
  196. validate_l2(pcap_t *pcap, char *filename, l2_t *l2)
  197. {
  198. dbg(1, "File linktype is %s",
  199. pcap_datalink_val_to_description(pcap_datalink(pcap)));
  200. /*
  201. * user specified a full L2 header, so we're all set!
  202. */
  203. if (l2->enabled)
  204. return;
  205. /*
  206. * compare the linktype of the capture file to the information
  207. * provided on the CLI (src/dst MAC addresses)
  208. */
  209. switch (pcap_datalink(pcap)) {
  210. case DLT_EN10MB:
  211. /* nothing to do here */
  212. return;
  213. break;
  214. case DLT_LINUX_SLL:
  215. /*
  216. * DLT_LINUX_SLL
  217. * Linux cooked socket has the source mac but not the destination mac
  218. * hence we look for the destination mac(s)
  219. */
  220. /* single output mode */
  221. if (! options.cache_packets) {
  222. /* if SLL, then either --dlink or --dmac are ok */
  223. if ((options.mac_mask & DMAC1) == 0) {
  224. errx(1, "%s requires --dlink or --dmac <mac>: %s",
  225. pcap_datalink_val_to_description(pcap_datalink(pcap)), filename);
  226. }
  227. }
  228. /* dual output mode */
  229. else {
  230. /* if using dual interfaces, make sure we have both dest MAC's */
  231. if (((options.mac_mask & DMAC1) == 0) || ((options.mac_mask & DMAC2) == 0)) {
  232. errx(1, "%s with --cachefile requires --dlink or\n"
  233. "\t--dmac <mac1>:<mac2>: %s",
  234. pcap_datalink_val_to_description(pcap_datalink(pcap)), filename);
  235. }
  236. }
  237. break;
  238. case DLT_C_HDLC:
  239. case DLT_RAW:
  240. /*
  241. * DLT_C_HDLC
  242. * Cisco HDLC doesn't contain a source or destination mac,
  243. * but it does contain the L3 protocol type (just like an ethernet header
  244. * does) so we require either a full L2 or both src/dst mac's
  245. *
  246. * DLT_RAW is assumed always IP, so we know the protocol type
  247. */
  248. /* single output mode */
  249. if (! options.cache_packets) {
  250. /* Need both src/dst MAC's */
  251. if (((options.mac_mask & DMAC1) == 0) || ((options.mac_mask & DMAC2) == 0)) {
  252. errx(1, "%s requires --dlink or --smac <mac> and --dmac <mac>: %s",
  253. pcap_datalink_val_to_description(pcap_datalink(pcap)), filename);
  254. }
  255. }
  256. /* dual output mode */
  257. else {
  258. /* Need to have src/dst MAC's for both directions */
  259. if (options.mac_mask != SMAC1 + SMAC2 + DMAC1 + DMAC2) {
  260. errx(1, "%s with --cachefile requires --dlink or\n"
  261. "\t--smac <mac1>:<mac2> and --dmac <mac1>:<mac2>: %s",
  262. pcap_datalink_val_to_description(pcap_datalink(pcap)), filename);
  263. }
  264. }
  265. break;
  266. default:
  267. errx(1, "Unsupported datalink %s (0x%x): %s",
  268. pcap_datalink_val_to_description(pcap_datalink(pcap)),
  269. pcap_datalink(pcap), filename);
  270. break;
  271. }
  272. }
  273. void
  274. rewrite_packets(pcap_t * inpcap, pcap_dumper_t *outpcap)
  275. {
  276. eth_hdr_t *eth_hdr = NULL;
  277. ip_hdr_t *ip_hdr = NULL;
  278. arp_hdr_t *arp_hdr = NULL;
  279. int cache_result = CACHE_PRIMARY; /* default to primary */
  280. struct pcap_pkthdr pkthdr; /* packet header */
  281. u_char newpkt[MAXPACKET] = ""; /* our new packet after editing */
  282. const u_char *pktdata = NULL; /* packet from libpcap */
  283. #ifdef FORCE_ALIGN
  284. u_char *ipbuff = NULL; /* IP header and above buffer */
  285. #endif
  286. int l2len = 0, l2proto;
  287. COUNTER packetnum = 0;
  288. int needtorecalc = 0; /* did the packet change? if so, checksum */
  289. struct pcap_pkthdr *pkthdr_ptr;
  290. #ifdef FORCE_ALIGN
  291. ipbuff = (u_char *)safe_malloc(MAXPACKET);
  292. #endif
  293. /* MAIN LOOP
  294. * Keep sending while we have packets or until
  295. * we've sent enough packets
  296. */
  297. while ((pktdata = pcap_next(inpcap, &pkthdr)) != NULL) {
  298. /* zero out the old packet info */
  299. memset(newpkt, 0, MAXPACKET);
  300. /*
  301. * copy the packet data to a buffer which allows us
  302. * to edit the contents of
  303. */
  304. memcpy(newpkt, pktdata, pkthdr.caplen);
  305. packetnum++;
  306. dbg(2, "packet " COUNTER_SPEC " caplen %d", packetnum, pkthdr.caplen);
  307. #ifdef HAVE_TCPDUMP
  308. if (options.verbose)
  309. tcpdump_print(&tcpdump, &pkthdr, newpkt);
  310. #endif
  311. /* Dual nic processing? */
  312. if (options.cachedata != NULL) {
  313. cache_result = check_cache(options.cachedata, packetnum);
  314. }
  315. /* sometimes we should not send the packet, in such cases
  316. * no point in editing this packet at all, just write it to the
  317. * output file (note, we can't just remove it, or the tcpprep cache
  318. * file will loose it's indexing
  319. */
  320. if (cache_result == CACHE_NOSEND)
  321. goto WRITE_PACKET;
  322. needtorecalc = 0;
  323. /*
  324. * remove the Ethernet FCS (checksum)?
  325. * note that this feature requires the end user to be smart and
  326. * only set this flag IFF the pcap has the FCS. If not, then they
  327. * just removed 2 bytes of ACTUAL PACKET DATA. Sucks to be them.
  328. */
  329. if (options.efcs)
  330. pkthdr.caplen -= 2;
  331. pkthdr_ptr = &pkthdr;
  332. /* Rewrite any Layer 2 data */
  333. if ((l2len = rewrite_l2(inpcap, &pkthdr_ptr, newpkt, cache_result)) == 0)
  334. continue; /* packet is too long and we didn't trunc, so skip it */
  335. l2proto = get_l2protocol(newpkt, pkthdr.caplen, pcap_datalink(inpcap));
  336. /* does packet have an IP header? if so set our pointer to it */
  337. if (l2proto == ETHERTYPE_IP) {
  338. dbg(3, "Packet has an IP header...");
  339. #ifdef FORCE_ALIGN
  340. /*
  341. * copy layer 3 and up to our temp packet buffer
  342. * for now on, we have to edit the packetbuff because
  343. * just before we send the packet, we copy the packetbuff
  344. * back onto the pkt.data + l2len buffer
  345. * we do all this work to prevent byte alignment issues
  346. */
  347. ip_hdr = (ip_hdr_t *) ipbuff;
  348. memcpy(ip_hdr, (&newpkt[l2len]), pkthdr.caplen - l2len);
  349. #else
  350. /*
  351. * on non-strict byte align systems, don't need to memcpy(),
  352. * just point to 14 bytes into the existing buffer
  353. */
  354. ip_hdr = (ip_hdr_t *) (&newpkt[l2len]);
  355. #endif
  356. } else {
  357. dbg(3, "Packet isn't IP...");
  358. /* non-IP packets have a NULL ip_hdr struct */
  359. ip_hdr = NULL;
  360. }
  361. /* rewrite IP addresses */
  362. if (options.rewrite_ip) {
  363. /* IP packets */
  364. if (ip_hdr != NULL) {
  365. needtorecalc += rewrite_ipl3(ip_hdr, cache_result);
  366. }
  367. /* ARP packets */
  368. else if (l2proto == ETHERTYPE_ARP) {
  369. arp_hdr = (arp_hdr_t *)(&newpkt[l2len]);
  370. /* unlike, rewrite_ipl3, we don't care if the packet changed
  371. * because we never need to recalc the checksums for an ARP
  372. * packet. So ignore the return value
  373. */
  374. rewrite_iparp(arp_hdr, cache_result);
  375. }
  376. }
  377. /* rewrite ports */
  378. if (options.portmap != NULL && (ip_hdr != NULL)) {
  379. needtorecalc += rewrite_ports(options.portmap, &ip_hdr);
  380. }
  381. /* Untruncate packet? Only for IP packets */
  382. if ((options.fixlen) && (ip_hdr != NULL)) {
  383. needtorecalc += untrunc_packet(&pkthdr, newpkt, ip_hdr);
  384. }
  385. /* do we need to spoof the src/dst IP address? */
  386. if (options.seed) {
  387. if (ip_hdr != NULL) {
  388. needtorecalc += randomize_ipv4(&pkthdr, newpkt, ip_hdr);
  389. } else {
  390. randomize_iparp(&pkthdr, newpkt, pcap_datalink(inpcap));
  391. }
  392. }
  393. /* do we need to force fixing checksums? */
  394. if ((options.fixcsum || needtorecalc) && (ip_hdr != NULL)) {
  395. fix_checksums(&pkthdr, ip_hdr);
  396. }
  397. #ifdef STRICT_ALIGN
  398. /*
  399. * put back the layer 3 and above back in the pkt.data buffer
  400. * we can't edit the packet at layer 3 or above beyond this point
  401. */
  402. memcpy(&newpkt[l2len], ip_hdr, pkthdr.caplen - l2len);
  403. #endif
  404. /* do we need to print the packet via tcpdump? */
  405. #ifdef HAVE_TCPDUMP
  406. if (options.verbose)
  407. tcpdump_print(&tcpdump, &pkthdr, newpkt);
  408. #endif
  409. WRITE_PACKET:
  410. /* write the packet */
  411. pcap_dump((u_char *) outpcap, &pkthdr, newpkt);
  412. total_bytes += pkthdr.caplen;
  413. pkts_edited ++;
  414. } /* while() */
  415. /* free buffers */
  416. #ifdef FORCE_ALIGN
  417. free(ipbuff);
  418. #endif
  419. }
  420. /*
  421. Local Variables:
  422. mode:c
  423. indent-tabs-mode:nil
  424. c-basic-offset:4
  425. End:
  426. */