edit_packet.c 17 KB

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