edit_packet.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /* $Id: edit_packet.c 1501 2006-07-17 02:31:58Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2004 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. #include "config.h"
  32. #include "defines.h"
  33. #include "common.h"
  34. #include "tcpedit.h"
  35. #include "edit_packet.h"
  36. #include "lib/sll.h"
  37. #include "dlt.h"
  38. extern int maxpacket;
  39. /*
  40. * this code re-calcs the IP and Layer 4 checksums
  41. * the IMPORTANT THING is that the Layer 4 header
  42. * is contiguious in memory after *ip_hdr we're actually
  43. * writing to the layer 4 header via the ip_hdr ptr.
  44. * (Yes, this sucks, but that's the way libnet works, and
  45. * I was too lazy to re-invent the wheel.
  46. */
  47. void
  48. fix_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ip_hdr_t * ip_hdr)
  49. {
  50. assert(tcpedit);
  51. assert(pkthdr);
  52. assert(ip_hdr);
  53. /* calc the L4 checksum if we have the whole packet */
  54. if (pkthdr->caplen == pkthdr->len) {
  55. if (libnet_do_checksum(tcpedit->runtime.lnet, (u_char *) ip_hdr,
  56. ip_hdr->ip_p,
  57. ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl << 2)) < 0)
  58. warnx("Layer 4 checksum failed: %s",
  59. libnet_geterror(tcpedit->runtime.lnet));
  60. }
  61. /* calc IP checksum */
  62. if (libnet_do_checksum(tcpedit->runtime.lnet, (u_char *) ip_hdr,
  63. IPPROTO_IP, ntohs(ip_hdr->ip_len)) < 0)
  64. warnx("IP checksum failed: %s",
  65. libnet_geterror(tcpedit->runtime.lnet));
  66. }
  67. /*
  68. * returns a new 32bit integer which is the randomized IP
  69. * based upon the user specified seed
  70. */
  71. u_int32_t
  72. randomize_ip(tcpedit_t *tcpedit, u_int32_t ip)
  73. {
  74. assert(tcpedit);
  75. return ((ip ^ tcpedit->seed) - (ip & tcpedit->seed));
  76. }
  77. /*
  78. * randomizes the source and destination IP addresses based on a
  79. * pseudo-random number which is generated via the seed.
  80. * return 1 since we changed one or more IP addresses
  81. */
  82. int
  83. randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  84. u_char * pktdata, ip_hdr_t * ip_hdr)
  85. {
  86. char srcip[16], dstip[16];
  87. assert(tcpedit);
  88. assert(pkthdr);
  89. assert(pktdata);
  90. assert(ip_hdr);
  91. strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr,
  92. RESOLVE), 16);
  93. strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr,
  94. RESOLVE), 16);
  95. /* randomize IP addresses based on the value of random */
  96. dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
  97. ip_hdr->ip_dst.s_addr = randomize_ip(tcpedit, ip_hdr->ip_dst.s_addr);
  98. ip_hdr->ip_src.s_addr = randomize_ip(tcpedit, ip_hdr->ip_src.s_addr);
  99. strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr,
  100. RESOLVE), 16);
  101. strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr,
  102. RESOLVE), 16);
  103. dbgx(1, "New Src IP: %s\tNew Dst IP: %s\n", srcip, dstip);
  104. return(1);
  105. }
  106. /*
  107. * this code will untruncate a packet via padding it with null
  108. * or resetting the actual packet len to the snaplen. In either case
  109. * it will recalcuate the IP and transport layer checksums.
  110. * return 0 if no change, 1 if change
  111. */
  112. int
  113. untrunc_packet(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  114. u_char * pktdata, ip_hdr_t * ip_hdr)
  115. {
  116. assert(tcpedit);
  117. assert(pkthdr);
  118. assert(pktdata);
  119. assert(ip_hdr);
  120. /* if actual len == cap len or there's no IP header, don't do anything */
  121. if ((pkthdr->caplen == pkthdr->len) || (ip_hdr == NULL)) {
  122. return(0);
  123. }
  124. /* Pad packet or truncate it */
  125. if (tcpedit->fixlen == TCPEDIT_FIXLEN_PAD) {
  126. /*
  127. * this should be an unnecessary check
  128. * but I've gotten a report that sometimes the caplen > len
  129. * which seems like a corrupted pcap
  130. */
  131. if (pkthdr->len > pkthdr->caplen) {
  132. memset(pktdata + pkthdr->caplen, 0, pkthdr->len - pkthdr->caplen);
  133. pkthdr->caplen = pkthdr->len;
  134. } else {
  135. /* i guess this is necessary if we've got a bogus pcap */
  136. ip_hdr->ip_len = htons(pkthdr->caplen);
  137. }
  138. }
  139. else if (tcpedit->fixlen == TCPEDIT_FIXLEN_TRUNC) {
  140. ip_hdr->ip_len = htons(pkthdr->caplen);
  141. }
  142. else {
  143. errx(1, "Invalid fixlen value: 0x%x", tcpedit->fixlen);
  144. }
  145. /* fix checksums */
  146. fix_checksums(tcpedit, pkthdr, ip_hdr);
  147. return(1);
  148. }
  149. /*
  150. * Extracts the layer 7 data from the packet for TCP, UDP, ICMP
  151. * returns the number of bytes and a pointer to the layer 7 data.
  152. * Returns 0 for no data
  153. */
  154. int
  155. extract_data(tcpedit_t *tcpedit, const u_char *pktdata, int caplen,
  156. char *l7data[])
  157. {
  158. int datalen = 0;
  159. ip_hdr_t *ip_hdr = NULL;
  160. tcp_hdr_t *tcp_hdr = NULL;
  161. udp_hdr_t *udp_hdr = NULL;
  162. u_char ipbuff[MAXPACKET];
  163. u_char *dataptr = NULL;
  164. assert(tcpedit);
  165. assert(pktdata);
  166. assert(l7data);
  167. /* grab our IPv4 header */
  168. dataptr = ipbuff;
  169. if ((ip_hdr = (ip_hdr_t*)get_ipv4(pktdata, caplen,
  170. pcap_datalink(tcpedit->runtime.pcap1), &dataptr)) == NULL)
  171. return 0;
  172. /* figure out the actual datalen which might be < the caplen
  173. * due to ethernet padding
  174. */
  175. if (caplen > ntohs(ip_hdr->ip_len)) {
  176. datalen = ntohs(ip_hdr->ip_len);
  177. } else {
  178. datalen = caplen - tcpedit->l2.len;
  179. }
  180. /* update the datlen to not include the IP header len */
  181. datalen -= ip_hdr->ip_hl << 2;
  182. dataptr += ip_hdr->ip_hl << 2;
  183. if (datalen <= 0)
  184. goto nodata;
  185. /* TCP ? */
  186. if (ip_hdr->ip_p == IPPROTO_TCP) {
  187. tcp_hdr = (tcp_hdr_t *) get_layer4(ip_hdr);
  188. datalen -= tcp_hdr->th_off << 2;
  189. if (datalen <= 0)
  190. goto nodata;
  191. dataptr += tcp_hdr->th_off << 2;
  192. }
  193. /* UDP ? */
  194. else if (ip_hdr->ip_p == IPPROTO_UDP) {
  195. udp_hdr = (udp_hdr_t *) get_layer4(ip_hdr);
  196. datalen -= LIBNET_UDP_H;
  197. if (datalen <= 0)
  198. goto nodata;
  199. dataptr += LIBNET_UDP_H;
  200. }
  201. /* ICMP ? just ignore it for now */
  202. else if (ip_hdr->ip_p == IPPROTO_ICMP) {
  203. dbg(2, "Ignoring any possible data in ICMP packet");
  204. goto nodata;
  205. }
  206. /* unknown proto, just dump everything past the IP header */
  207. else {
  208. dbg(2, "Unknown protocol, dumping everything past the IP header");
  209. dataptr = (u_char *)ip_hdr;
  210. }
  211. dbgx(2, "packet had %d bytes of layer 7 data", datalen);
  212. memcpy(l7data, dataptr, datalen);
  213. return datalen;
  214. nodata:
  215. dbg(2, "packet has no data, skipping...");
  216. return 0;
  217. }
  218. /*
  219. * takes a CIDR notation netblock and uses that to "remap" given IP
  220. * onto that netblock. ie: 10.0.0.0/8 and 192.168.55.123 -> 10.168.55.123
  221. * while 10.150.9.0/24 and 192.168.55.123 -> 10.150.9.123
  222. */
  223. u_int32_t
  224. remap_ip(tcpr_cidr_t *cidr, const u_int32_t original)
  225. {
  226. u_int32_t ipaddr = 0, network = 0, mask = 0, result = 0;
  227. assert(cidr);
  228. mask = 0xffffffff; /* turn on all the bits */
  229. /* shift over by correct # of bits */
  230. mask = mask << (32 - cidr->masklen);
  231. /* apply the mask to the network */
  232. network = htonl(cidr->network) & mask;
  233. /* apply the reverse of the mask to the IP */
  234. mask = mask ^ 0xffffffff;
  235. ipaddr = ntohl(original) & mask;
  236. /* merge the network portion and ip portions */
  237. result = network ^ ipaddr;
  238. /* return the result in network byte order */
  239. return(htonl(result));
  240. }
  241. /*
  242. * rewrite IP address (layer3)
  243. * uses -N to rewrite (map) one subnet onto another subnet
  244. * return 0 if no change, 1 or 2 if changed
  245. */
  246. int
  247. rewrite_ipl3(tcpedit_t *tcpedit, ip_hdr_t *ip_hdr, int direction)
  248. {
  249. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  250. int didsrc = 0, diddst = 0, loop = 1;
  251. assert(tcpedit);
  252. assert(ip_hdr);
  253. /* anything to rewrite? */
  254. if (tcpedit->cidrmap1 == NULL)
  255. return(0);
  256. /* don't play with the main pointers */
  257. if (direction == CACHE_PRIMARY) {
  258. cidrmap1 = tcpedit->cidrmap1;
  259. cidrmap2 = tcpedit->cidrmap2;
  260. } else {
  261. cidrmap1 = tcpedit->cidrmap2;
  262. cidrmap2 = tcpedit->cidrmap1;
  263. }
  264. /* loop through the cidrmap to rewrite */
  265. do {
  266. if ((! diddst) && ip_in_cidr(cidrmap2->from, ip_hdr->ip_dst.s_addr)) {
  267. ip_hdr->ip_dst.s_addr = remap_ip(cidrmap2->to, ip_hdr->ip_dst.s_addr);
  268. dbgx(2, "Remapped dst addr to: %s", inet_ntoa(ip_hdr->ip_dst));
  269. diddst = 1;
  270. }
  271. if ((! didsrc) && ip_in_cidr(cidrmap1->from, ip_hdr->ip_src.s_addr)) {
  272. ip_hdr->ip_src.s_addr = remap_ip(cidrmap1->to, ip_hdr->ip_src.s_addr);
  273. dbgx(2, "Remapped src addr to: %s", inet_ntoa(ip_hdr->ip_src));
  274. didsrc = 1;
  275. }
  276. /*
  277. * loop while we haven't modified both src/dst AND
  278. * at least one of the cidr maps have a next pointer
  279. */
  280. if ((! (diddst && didsrc)) &&
  281. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  282. /* increment our ptr's if possible */
  283. if (cidrmap1->next != NULL)
  284. cidrmap1 = cidrmap1->next;
  285. if (cidrmap2->next != NULL)
  286. cidrmap2 = cidrmap2->next;
  287. } else {
  288. loop = 0;
  289. }
  290. /* Later on we should support various IP protocols which embed
  291. * the IP address in the application layer. Things like
  292. * DNS and FTP.
  293. */
  294. } while (loop);
  295. /* return how many changes we made */
  296. return (diddst + didsrc);
  297. }
  298. /*
  299. * Randomize the IP addresses in an ARP packet based on the user seed
  300. * return 0 if no change, or 1 for a change
  301. */
  302. int
  303. randomize_iparp(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  304. u_char *pktdata, int datalink)
  305. {
  306. arp_hdr_t *arp_hdr = NULL;
  307. int l2len = 0;
  308. u_int32_t *ip, tempip;
  309. u_char *add_hdr;
  310. assert(tcpedit);
  311. assert(pkthdr);
  312. assert(pktdata);
  313. l2len = get_l2len(pktdata, pkthdr->caplen, datalink);
  314. arp_hdr = (arp_hdr_t *)(pktdata + l2len);
  315. /*
  316. * only rewrite IP addresses from REPLY/REQUEST's
  317. */
  318. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  319. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  320. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY))) {
  321. /* jump to the addresses */
  322. add_hdr = (u_char *)arp_hdr;
  323. add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
  324. ip = (u_int32_t *)add_hdr;
  325. tempip = randomize_ip(tcpedit, *ip);
  326. memcpy(ip, &tempip, sizeof(u_int32_t));
  327. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  328. ip = (u_int32_t *)add_hdr;
  329. tempip = randomize_ip(tcpedit, *ip);
  330. memcpy(ip, &tempip, sizeof(u_int32_t));
  331. }
  332. return 1; /* yes we changed the packet */
  333. }
  334. /*
  335. * rewrite IP address (arp)
  336. * uses -a to rewrite (map) one subnet onto another subnet
  337. * pointer must point to the WHOLE and CONTIGOUS memory buffer
  338. * because the arp_hdr_t doesn't have the space for the IP/MAC
  339. * addresses
  340. * return 0 if no change, 1 or 2 if changed
  341. */
  342. int
  343. rewrite_iparp(tcpedit_t *tcpedit, arp_hdr_t *arp_hdr, int cache_mode)
  344. {
  345. u_char *add_hdr = NULL;
  346. u_int32_t *ip1 = NULL, *ip2 = NULL;
  347. u_int32_t newip = 0;
  348. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  349. int didsrc = 0, diddst = 0, loop = 1;
  350. assert(tcpedit);
  351. assert(arp_hdr);
  352. /* figure out what mapping to use */
  353. if (cache_mode == CACHE_PRIMARY) {
  354. cidrmap1 = tcpedit->cidrmap1;
  355. cidrmap2 = tcpedit->cidrmap2;
  356. } else if (cache_mode == CACHE_SECONDARY) {
  357. cidrmap1 = tcpedit->cidrmap2;
  358. cidrmap2 = tcpedit->cidrmap1;
  359. }
  360. /* anything to rewrite? */
  361. if (cidrmap1 == NULL || cidrmap2 == NULL)
  362. return(0);
  363. /*
  364. * must be IPv4 and request or reply
  365. * Do other op codes use the same subheader stub?
  366. * If so we won't need to check the op code.
  367. */
  368. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  369. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  370. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY)))
  371. {
  372. /* jump to the addresses */
  373. add_hdr = (u_char *)arp_hdr;
  374. add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
  375. ip1 = (u_int32_t *)add_hdr;
  376. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  377. ip2 = (u_int32_t *)add_hdr;
  378. /* loop through the cidrmap to rewrite */
  379. do {
  380. /* arp request ? */
  381. if (ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) {
  382. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip1)) {
  383. newip = remap_ip(cidrmap2->to, *ip1);
  384. memcpy(ip1, &newip, 4);
  385. diddst = 1;
  386. }
  387. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip2)) {
  388. newip = remap_ip(cidrmap1->to, *ip2);
  389. memcpy(ip2, &newip, 4);
  390. didsrc = 1;
  391. }
  392. }
  393. /* else it's an arp reply */
  394. else {
  395. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip2)) {
  396. newip = remap_ip(cidrmap2->to, *ip2);
  397. memcpy(ip2, &newip, 4);
  398. diddst = 1;
  399. }
  400. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip1)) {
  401. newip = remap_ip(cidrmap1->to, *ip1);
  402. memcpy(ip1, &newip, 4);
  403. didsrc = 1;
  404. }
  405. }
  406. /*
  407. * loop while we haven't modified both src/dst AND
  408. * at least one of the cidr maps have a next pointer
  409. */
  410. if ((! (diddst && didsrc)) &&
  411. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  412. /* increment our ptr's if possible */
  413. if (cidrmap1->next != NULL)
  414. cidrmap1 = cidrmap1->next;
  415. if (cidrmap2->next != NULL)
  416. cidrmap2 = cidrmap2->next;
  417. } else {
  418. loop = 0;
  419. }
  420. } while (loop);
  421. } else {
  422. warn("ARP packet isn't for IPv4! Can't rewrite IP's");
  423. }
  424. return(didsrc + diddst);
  425. }
  426. /*
  427. Local Variables:
  428. mode:c
  429. indent-tabs-mode:nil
  430. c-basic-offset:4
  431. End:
  432. */