edit_packet.c 20 KB

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