edit_packet.c 19 KB

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