edit_packet.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2022 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "config.h"
  20. #include "defines.h"
  21. #include "common.h"
  22. #include "tcpedit.h"
  23. #include "edit_packet.h"
  24. #include "checksum.h"
  25. #include "incremental_checksum.h"
  26. #include "lib/sll.h"
  27. #include "dlt.h"
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <arpa/inet.h>
  34. static uint32_t randomize_ipv4_addr(tcpedit_t *tcpedit, uint32_t ip);
  35. static uint32_t remap_ipv4(tcpedit_t *tcpedit, tcpr_cidr_t *cidr, const uint32_t original);
  36. static int is_unicast_ipv4(tcpedit_t *tcpedit, uint32_t ip);
  37. static void randomize_ipv6_addr(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr);
  38. static int remap_ipv6(tcpedit_t *tcpedit, tcpr_cidr_t *cidr, struct tcpr_in6_addr *addr);
  39. static int is_multicast_ipv6(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr);
  40. static int ipv6_header_length(ipv6_hdr_t const * ip6_hdr, const size_t pkt_len,
  41. const size_t l2len);
  42. /**
  43. * this code re-calcs the IP and Layer 4 checksums
  44. * the IMPORTANT THING is that the Layer 4 header
  45. * is contiguous in memory after *ip_hdr we're actually
  46. * writing to the layer 4 header via the ip_hdr ptr.
  47. * (Yes, this sucks, but that's the way libnet works, and
  48. * I was too lazy to re-invent the wheel.
  49. * Returns 0 on success, -1 on error
  50. */
  51. int
  52. fix_ipv4_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  53. ipv4_hdr_t *ip_hdr, const size_t l2len)
  54. {
  55. int ret1 = 0, ret2 = 0, ip_len;
  56. assert(tcpedit);
  57. assert(pkthdr);
  58. assert(ip_hdr);
  59. if (pkthdr->caplen < (sizeof(*ip_hdr) + l2len)) {
  60. tcpedit_setwarn(tcpedit, "caplen too small to read IPv4 header: caplen=%u: pkt=" COUNTER_SPEC,
  61. pkthdr->caplen, tcpedit->runtime.packetnum);
  62. return TCPEDIT_WARN;
  63. }
  64. if (ip_hdr->ip_v != 4) {
  65. tcpedit_seterr(tcpedit, "Invalid packet: Expected IPv4 packet: got %u: pkt=" COUNTER_SPEC,
  66. ip_hdr->ip_v, tcpedit->runtime.packetnum);
  67. return TCPEDIT_ERROR;
  68. }
  69. ip_len = (int)ntohs(ip_hdr->ip_len);
  70. /* calc the L4 checksum if we have the whole packet && not a frag or first frag */
  71. if (pkthdr->caplen == pkthdr->len &&
  72. (htons(ip_hdr->ip_off) & (IP_MF | IP_OFFMASK)) == 0) {
  73. if (ip_len != (int)(pkthdr->caplen - l2len)) {
  74. tcpedit_seterr(tcpedit,
  75. "caplen minus L2 length %u does IPv4 header length %u: pkt=" COUNTER_SPEC,
  76. pkthdr->caplen - l2len, ip_len,
  77. tcpedit->runtime.packetnum);
  78. return TCPEDIT_ERROR;
  79. }
  80. ret1 = do_checksum(tcpedit,
  81. (u_char*)ip_hdr,
  82. ip_hdr->ip_p,
  83. ip_len - (ip_hdr->ip_hl << 2),
  84. (u_char*)ip_hdr + pkthdr->caplen - l2len);
  85. if (ret1 < 0)
  86. return TCPEDIT_ERROR;
  87. }
  88. /* calc IP checksum */
  89. ret2 = do_checksum(tcpedit,
  90. (u_char*)ip_hdr,
  91. IPPROTO_IP,
  92. ip_len,
  93. (u_char*)ip_hdr + pkthdr->caplen - l2len);
  94. if (ret2 < 0)
  95. return TCPEDIT_ERROR;
  96. /* what do we return? */
  97. if (ret1 == TCPEDIT_WARN || ret2 == TCPEDIT_WARN)
  98. return TCPEDIT_WARN;
  99. return TCPEDIT_OK;
  100. }
  101. /**
  102. * Returns ipv6 header length with all ipv6 options on success
  103. * -1 on error
  104. */
  105. static int
  106. ipv6_header_length(ipv6_hdr_t const * ip6_hdr, const size_t pkt_len,
  107. const size_t l2len)
  108. {
  109. struct tcpr_ipv6_ext_hdr_base const * nhdr;
  110. uint8_t next_header;
  111. int offset;
  112. offset = sizeof(*ip6_hdr);
  113. next_header = ip6_hdr->ip_nh;
  114. while (sizeof(*nhdr) + offset + l2len < (size_t)pkt_len) {
  115. if (next_header != TCPR_IPV6_NH_HBH
  116. && next_header != TCPR_IPV6_NH_ROUTING
  117. && next_header != TCPR_IPV6_NH_FRAGMENT) {
  118. return offset;
  119. }
  120. nhdr = (struct tcpr_ipv6_ext_hdr_base const *) (((uint8_t const *)ip6_hdr) + offset);
  121. next_header = nhdr->ip_nh;
  122. offset += ((nhdr->ip_len + 1) << 3);
  123. }
  124. return -1;
  125. }
  126. int
  127. fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  128. ipv6_hdr_t *ip6_hdr, const size_t l2len)
  129. {
  130. int ret = 0;
  131. assert(tcpedit);
  132. assert(pkthdr);
  133. assert(ip6_hdr);
  134. if (pkthdr->caplen < (sizeof(*ip6_hdr) + l2len)) {
  135. tcpedit_setwarn(tcpedit, "caplen too small to read IPv6 header: caplen=%u pkt=" COUNTER_SPEC,
  136. pkthdr->caplen, tcpedit->runtime.packetnum);
  137. return TCPEDIT_WARN;
  138. }
  139. ipv4_hdr_t *ip_hdr = (ipv4_hdr_t*)ip6_hdr;
  140. if (ip_hdr->ip_v != 6) {
  141. tcpedit_seterr(tcpedit, "Invalid packet: Expected IPv6 packet: got %u", ip_hdr->ip_v);
  142. return TCPEDIT_ERROR;
  143. }
  144. /* calc the L4 checksum if we have the whole packet && not a frag or first frag */
  145. if (pkthdr->caplen == pkthdr->len) {
  146. int ip6_len = ipv6_header_length(ip6_hdr, pkthdr->len, l2len);
  147. if (ip6_hdr->ip_len < ip6_len) {
  148. tcpedit_setwarn(tcpedit, "Unable to checksum IPv6 packet with invalid: pkt=" COUNTER_SPEC " IP length=%u caplen=" COUNTER_SPEC,
  149. tcpedit->runtime.packetnum, ip6_hdr->ip_len, pkthdr->caplen);
  150. return TCPEDIT_WARN;
  151. }
  152. ret = do_checksum(tcpedit,
  153. (u_char*)ip6_hdr,
  154. ip6_hdr->ip_nh,
  155. htons(ip6_hdr->ip_len),
  156. (u_char*)ip6_hdr + pkthdr->caplen - l2len);
  157. if (ret < 0)
  158. return TCPEDIT_ERROR;
  159. }
  160. /* what do we return? */
  161. if (ret == TCPEDIT_WARN)
  162. return TCPEDIT_WARN;
  163. return TCPEDIT_OK;
  164. }
  165. static void ipv4_l34_csum_replace(uint8_t *data, uint8_t protocol,
  166. uint32_t old, uint32_t new)
  167. {
  168. ipv4_hdr_t *ipv4;
  169. tcp_hdr_t *tcp_hdr;
  170. udp_hdr_t *udp_hdr;
  171. assert(data);
  172. switch (protocol) {
  173. case IPPROTO_IP:
  174. ipv4 = (ipv4_hdr_t *)data;
  175. csum_replace4(&ipv4->ip_sum, old, new);
  176. break;
  177. case IPPROTO_TCP:
  178. tcp_hdr = (tcp_hdr_t *)data;
  179. csum_replace4(&tcp_hdr->th_sum, old, new);
  180. break;
  181. case IPPROTO_UDP:
  182. udp_hdr = (udp_hdr_t *)data;
  183. if (udp_hdr->uh_sum)
  184. csum_replace4(&udp_hdr->uh_sum, old, new);
  185. break;
  186. default:
  187. assert(false);
  188. }
  189. }
  190. static void ipv6_l34_csum_replace(uint8_t *data, uint8_t protocol,
  191. uint32_t *old, uint32_t *new)
  192. {
  193. tcp_hdr_t *tcp_hdr;
  194. udp_hdr_t *udp_hdr;
  195. icmpv4_hdr_t *icmp;
  196. icmpv6_hdr_t *icmp6;
  197. assert(data);
  198. switch (protocol) {
  199. case IPPROTO_TCP:
  200. tcp_hdr = (tcp_hdr_t *)data;
  201. csum_replace16(&tcp_hdr->th_sum, old, new);
  202. break;
  203. case IPPROTO_UDP:
  204. udp_hdr = (udp_hdr_t *)data;
  205. if (udp_hdr->uh_sum)
  206. csum_replace16(&udp_hdr->uh_sum, old, new);
  207. break;
  208. case IPPROTO_ICMP:
  209. icmp = (icmpv4_hdr_t *)data;
  210. csum_replace16(&icmp->icmp_sum, old, new);
  211. break;
  212. case IPPROTO_ICMP6:
  213. icmp6 = (icmpv6_hdr_t *)data;
  214. csum_replace16(&icmp6->icmp_sum, old, new);
  215. break;
  216. default:
  217. assert(false);
  218. }
  219. }
  220. static void ipv4_addr_csum_replace(ipv4_hdr_t *ip_hdr, uint32_t old_ip,
  221. uint32_t new_ip, const int l3len)
  222. {
  223. uint8_t *l4, protocol;
  224. int len = l3len;
  225. assert(ip_hdr);
  226. if ((size_t)len < sizeof(*ip_hdr))
  227. return;
  228. ipv4_l34_csum_replace((uint8_t*)ip_hdr, IPPROTO_IP, old_ip, new_ip);
  229. protocol = ip_hdr->ip_p;
  230. switch (protocol) {
  231. case IPPROTO_UDP:
  232. l4 = get_layer4_v4(ip_hdr, (u_char *)ip_hdr + l3len);
  233. len -= ip_hdr->ip_hl << 2;
  234. len -= TCPR_UDP_H;
  235. break;
  236. case IPPROTO_TCP:
  237. l4 = get_layer4_v4(ip_hdr, (u_char *)ip_hdr + l3len);
  238. len -= ip_hdr->ip_hl << 2;
  239. len -= TCPR_TCP_H;
  240. break;
  241. default:
  242. l4 = NULL;
  243. }
  244. if (!l4 || len < 0)
  245. return;
  246. /* if this is a fragment, don't attempt to checksum the Layer4 header */
  247. if ((htons(ip_hdr->ip_off) & IP_OFFMASK) == 0)
  248. ipv4_l34_csum_replace(l4, protocol, old_ip, new_ip);
  249. }
  250. static void ipv6_addr_csum_replace(ipv6_hdr_t *ip6_hdr,
  251. struct tcpr_in6_addr *old_ip, struct tcpr_in6_addr *new_ip,
  252. const int l3len)
  253. {
  254. uint8_t *l4, protocol;
  255. assert(ip6_hdr);
  256. if ((size_t)l3len < sizeof(*ip6_hdr))
  257. return;
  258. protocol = get_ipv6_l4proto(ip6_hdr, (u_char*)ip6_hdr + l3len);
  259. switch (protocol) {
  260. case IPPROTO_UDP:
  261. l4 = get_layer4_v6(ip6_hdr, (u_char*)ip6_hdr + l3len);
  262. break;
  263. case IPPROTO_TCP:
  264. l4 = get_layer4_v6(ip6_hdr, (u_char*)ip6_hdr + l3len);
  265. break;
  266. default:
  267. l4 = NULL;
  268. }
  269. if (!l4)
  270. return;
  271. ipv6_l34_csum_replace(l4, protocol, (uint32_t*)old_ip, (uint32_t*)new_ip);
  272. }
  273. /**
  274. * returns a new 32bit integer which is the randomized IP
  275. * based upon the user specified seed
  276. */
  277. static uint32_t
  278. randomize_ipv4_addr(tcpedit_t *tcpedit, uint32_t ip)
  279. {
  280. assert(tcpedit);
  281. /* don't rewrite broadcast addresses */
  282. if (tcpedit->skip_broadcast && !is_unicast_ipv4(tcpedit, ip))
  283. return ip;
  284. return ((ip ^ htonl(tcpedit->seed)) - (ip & htonl(tcpedit->seed)));
  285. }
  286. static void
  287. randomize_ipv6_addr(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr)
  288. {
  289. uint32_t *p;
  290. int i;
  291. u_char was_multicast;
  292. assert(tcpedit);
  293. p = &addr->__u6_addr.__u6_addr32[0];
  294. was_multicast = is_multicast_ipv6(tcpedit, addr);
  295. for (i = 0; i < 4; ++i) {
  296. p[i] = ((p[i] ^ htonl(tcpedit->seed)) - (p[i] & htonl(tcpedit->seed)));
  297. }
  298. if (was_multicast) {
  299. addr->tcpr_s6_addr[0] = 0xff;
  300. } else if (is_multicast_ipv6(tcpedit, addr)) {
  301. addr->tcpr_s6_addr[0] = 0xaa;
  302. }
  303. }
  304. int fix_ipv4_length(struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr,
  305. const size_t l2len)
  306. {
  307. int ip_len = (int)ntohs(ip_hdr->ip_len);
  308. int ip_len_want = (int)(pkthdr->len - l2len);
  309. if (pkthdr->caplen < l2len + sizeof(*ip_hdr))
  310. return -1;
  311. if ((htons(ip_hdr->ip_off) & (IP_MF | IP_OFFMASK)) == 0 &&
  312. ip_len != ip_len_want) {
  313. ip_hdr->ip_len = htons(ip_len_want);
  314. return 1;
  315. }
  316. return 0;
  317. }
  318. int fix_ipv6_length(struct pcap_pkthdr *pkthdr, ipv6_hdr_t *ip6_hdr,
  319. const size_t l2len)
  320. {
  321. int ip_len = ntohs((uint16_t)ip6_hdr->ip_len);
  322. int ip_len_want = (int)(pkthdr->len - l2len - sizeof(*ip6_hdr));
  323. if (pkthdr->caplen < l2len + sizeof(*ip6_hdr))
  324. return -1;
  325. if (ip_len != ip_len_want) {
  326. ip6_hdr->ip_len = htons((uint16_t)ip_len_want);
  327. return 1;
  328. }
  329. return 0;
  330. }
  331. /**
  332. * randomizes the source and destination IP addresses based on a
  333. * pseudo-random number which is generated via the seed.
  334. * return 1 since we changed one or more IP addresses
  335. */
  336. int
  337. randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  338. u_char *pktdata, ipv4_hdr_t *ip_hdr, const int l3len)
  339. {
  340. #ifdef DEBUG
  341. char srcip[16], dstip[16];
  342. #endif
  343. assert(tcpedit);
  344. assert(pkthdr);
  345. assert(pktdata);
  346. assert(ip_hdr);
  347. #ifdef DEBUG
  348. strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE), 16);
  349. strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE), 16);
  350. #endif
  351. /* randomize IP addresses based on the value of random */
  352. dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
  353. if (l3len < (int)ip_hdr->ip_hl << 2) {
  354. tcpedit_seterr(tcpedit, "Unable to randomize IP header due to packet capture snap length %u",
  355. pkthdr->caplen);
  356. return TCPEDIT_ERROR;
  357. }
  358. /* don't rewrite broadcast addresses */
  359. if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_dst.s_addr))
  360. || !tcpedit->skip_broadcast) {
  361. uint32_t old_ip = ip_hdr->ip_dst.s_addr;
  362. ip_hdr->ip_dst.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_dst.s_addr);
  363. ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_dst.s_addr, l3len);
  364. }
  365. if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_src.s_addr))
  366. || !tcpedit->skip_broadcast) {
  367. uint32_t old_ip = ip_hdr->ip_src.s_addr;
  368. ip_hdr->ip_src.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_src.s_addr);
  369. ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_src.s_addr, l3len);
  370. }
  371. #ifdef DEBUG
  372. strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE), 16);
  373. strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE), 16);
  374. #endif
  375. dbgx(1, "New Src IP: %s\tNew Dst IP: %s\n", srcip, dstip);
  376. return 0;
  377. }
  378. int
  379. randomize_ipv6(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  380. u_char *pktdata, ipv6_hdr_t *ip6_hdr, const int l3len)
  381. {
  382. #ifdef DEBUG
  383. char srcip[INET6_ADDRSTRLEN], dstip[INET6_ADDRSTRLEN];
  384. #endif
  385. assert(tcpedit);
  386. assert(pkthdr);
  387. assert(pktdata);
  388. assert(ip6_hdr);
  389. #ifdef DEBUG
  390. strlcpy(srcip, get_addr2name6(&ip6_hdr->ip_src, RESOLVE), INET6_ADDRSTRLEN);
  391. strlcpy(dstip, get_addr2name6(&ip6_hdr->ip_dst, RESOLVE), INET6_ADDRSTRLEN);
  392. #endif
  393. /* randomize IP addresses based on the value of random */
  394. dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
  395. if (l3len < (int)sizeof(ipv6_hdr_t)) {
  396. tcpedit_seterr(tcpedit, "Unable to randomize IPv6 header due to packet capture snap length %u: pkt=" COUNTER_SPEC,
  397. pkthdr->caplen, tcpedit->runtime.packetnum);
  398. return TCPEDIT_ERROR;
  399. }
  400. /* don't rewrite broadcast addresses */
  401. if ((tcpedit->skip_broadcast && !is_multicast_ipv6(tcpedit, &ip6_hdr->ip_dst))
  402. || !tcpedit->skip_broadcast) {
  403. struct tcpr_in6_addr old_ip6;
  404. memcpy(&old_ip6, &ip6_hdr->ip_dst, sizeof(old_ip6));
  405. randomize_ipv6_addr(tcpedit, &ip6_hdr->ip_dst);
  406. ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, l3len);
  407. }
  408. if ((tcpedit->skip_broadcast && !is_multicast_ipv6(tcpedit, &ip6_hdr->ip_src))
  409. || !tcpedit->skip_broadcast) {
  410. struct tcpr_in6_addr old_ip6;
  411. memcpy(&old_ip6, &ip6_hdr->ip_src, sizeof(old_ip6));
  412. randomize_ipv6_addr(tcpedit, &ip6_hdr->ip_src);
  413. ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, l3len);
  414. }
  415. #ifdef DEBUG
  416. strlcpy(srcip, get_addr2name6(&ip6_hdr->ip_src, RESOLVE), INET6_ADDRSTRLEN);
  417. strlcpy(dstip, get_addr2name6(&ip6_hdr->ip_dst, RESOLVE), INET6_ADDRSTRLEN);
  418. #endif
  419. dbgx(1, "New Src IP: %s\tNew Dst IP: %s\n", srcip, dstip);
  420. return 0;
  421. }
  422. /**
  423. * this code will untruncate a packet via padding it with null
  424. * or resetting the actual IPv4 packet len to the snaplen - L2 header.
  425. * return 0 if no change, 1 if change, -1 on error.
  426. */
  427. int
  428. untrunc_packet(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  429. u_char **pktdata, ipv4_hdr_t *ip_hdr, ipv6_hdr_t *ip6_hdr)
  430. {
  431. int l2len;
  432. int chksum = 1;
  433. u_char *packet;
  434. udp_hdr_t *udp_hdr;
  435. u_char *dataptr = NULL;
  436. assert(tcpedit);
  437. assert(pkthdr);
  438. assert(pktdata);
  439. packet = *pktdata;
  440. assert(packet);
  441. /* if actual len == cap len or there's no IP header, don't do anything */
  442. if ((pkthdr->caplen == pkthdr->len) || (ip_hdr == NULL && ip6_hdr == NULL)) {
  443. /* unless we're in MTU truncate mode */
  444. if (! tcpedit->mtu_truncate)
  445. return(0);
  446. }
  447. if ((l2len = layer2len(tcpedit, packet, pkthdr->caplen)) < 0) {
  448. tcpedit_seterr(tcpedit, "Non-sensical layer 2 length: %d", l2len);
  449. return -1;
  450. }
  451. /*
  452. * cannot checksum fragments, but we can do some
  453. * work on UDP fragments. Setting checksum to 0
  454. * means checksum will be ignored.
  455. */
  456. if (ip_hdr) {
  457. if ((htons(ip_hdr->ip_off) & IP_OFFMASK) != 0) {
  458. chksum = 0;
  459. } else if (ip_hdr->ip_p == IPPROTO_UDP &&
  460. (htons(ip_hdr->ip_off) & IP_MF) != 0) {
  461. dataptr = (u_char*)ip_hdr;
  462. dataptr += ip_hdr->ip_hl << 2;
  463. udp_hdr = (udp_hdr_t*)dataptr;
  464. udp_hdr->uh_sum = 0;
  465. chksum = 0;
  466. }
  467. }
  468. /* Pad packet or truncate it */
  469. if (tcpedit->fixlen == TCPEDIT_FIXLEN_PAD) {
  470. /*
  471. * this should be an unnecessary check
  472. * but I've gotten a report that sometimes the caplen > len
  473. * which seems like a corrupted pcap
  474. */
  475. if (pkthdr->len > pkthdr->caplen) {
  476. packet = safe_realloc(packet, pkthdr->len + PACKET_HEADROOM);
  477. memset(packet + pkthdr->caplen, '\0', pkthdr->len - pkthdr->caplen);
  478. pkthdr->caplen = pkthdr->len;
  479. } else if (pkthdr->len < pkthdr->caplen) {
  480. /* i guess this is necessary if we've got a bogus pcap */
  481. //ip_hdr->ip_len = htons(pkthdr->caplen - l2len);
  482. tcpedit_seterr(tcpedit, "%s", "WTF? Why is your packet larger then the capture len?");
  483. chksum = -1;
  484. goto done;
  485. }
  486. }
  487. else if (tcpedit->fixlen == TCPEDIT_FIXLEN_TRUNC) {
  488. if (ip_hdr && pkthdr->len != pkthdr->caplen)
  489. ip_hdr->ip_len = htons(pkthdr->caplen - l2len);
  490. pkthdr->len = pkthdr->caplen;
  491. }
  492. else if (tcpedit->mtu_truncate) {
  493. if (pkthdr->len > (uint32_t)(tcpedit->mtu + l2len)) {
  494. /* first truncate the packet */
  495. pkthdr->len = pkthdr->caplen = l2len + tcpedit->mtu;
  496. /* if ip_hdr exists, update the length */
  497. if (ip_hdr != NULL) {
  498. ip_hdr->ip_len = htons(tcpedit->mtu);
  499. } else if (ip6_hdr != NULL) {
  500. ip6_hdr->ip_len = htons(tcpedit->mtu - sizeof(*ip6_hdr));
  501. } else {
  502. /* for non-IP frames, don't try to fix checksums */
  503. chksum = 0;
  504. goto done;
  505. }
  506. }
  507. }
  508. else {
  509. tcpedit_seterr(tcpedit, "Invalid fixlen value: 0x%x", tcpedit->fixlen);
  510. chksum = -1;
  511. goto done;
  512. }
  513. done:
  514. *pktdata = packet;
  515. return chksum;
  516. }
  517. /**
  518. * rewrites an IPv4 packet's TTL based on the rules
  519. * return 0 if no change, 1 if changed
  520. */
  521. int
  522. rewrite_ipv4_ttl(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr)
  523. {
  524. volatile uint16_t oldval, newval;
  525. assert(tcpedit);
  526. /* make sure there's something to edit */
  527. if (ip_hdr == NULL || tcpedit->ttl_mode == false)
  528. return(0);
  529. oldval = (uint16_t)ip_hdr->ip_ttl;
  530. switch(tcpedit->ttl_mode) {
  531. case TCPEDIT_TTL_MODE_SET:
  532. if (ip_hdr->ip_ttl == tcpedit->ttl_value)
  533. return 0; /* no change required */
  534. ip_hdr->ip_ttl = tcpedit->ttl_value;
  535. break;
  536. case TCPEDIT_TTL_MODE_ADD:
  537. if (((int)ip_hdr->ip_ttl + tcpedit->ttl_value) > 255) {
  538. ip_hdr->ip_ttl = 255;
  539. } else {
  540. ip_hdr->ip_ttl += tcpedit->ttl_value;
  541. }
  542. break;
  543. case TCPEDIT_TTL_MODE_SUB:
  544. if (ip_hdr->ip_ttl <= tcpedit->ttl_value) {
  545. ip_hdr->ip_ttl = 1;
  546. } else {
  547. ip_hdr->ip_ttl -= tcpedit->ttl_value;
  548. }
  549. break;
  550. default:
  551. errx(1, "invalid ttl_mode: %d", tcpedit->ttl_mode);
  552. }
  553. newval = (uint16_t)ip_hdr->ip_ttl;
  554. csum_replace2(&ip_hdr->ip_sum, oldval, newval);
  555. return 0;
  556. }
  557. /**
  558. * rewrites an IPv6 packet's hop limit based on the rules
  559. * return 0 if no change, 1 if changed
  560. */
  561. int
  562. rewrite_ipv6_hlim(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr)
  563. {
  564. assert(tcpedit);
  565. /* make sure there's something to edit */
  566. if (ip6_hdr == NULL || tcpedit->ttl_mode == TCPEDIT_TTL_MODE_OFF)
  567. return(0);
  568. switch(tcpedit->ttl_mode) {
  569. case TCPEDIT_TTL_MODE_SET:
  570. if (ip6_hdr->ip_hl == tcpedit->ttl_value)
  571. return(0); /* no change required */
  572. ip6_hdr->ip_hl = tcpedit->ttl_value;
  573. break;
  574. case TCPEDIT_TTL_MODE_ADD:
  575. if (((int)ip6_hdr->ip_hl + tcpedit->ttl_value) > 255) {
  576. ip6_hdr->ip_hl = 255;
  577. } else {
  578. ip6_hdr->ip_hl += tcpedit->ttl_value;
  579. }
  580. break;
  581. case TCPEDIT_TTL_MODE_SUB:
  582. if (ip6_hdr->ip_hl <= tcpedit->ttl_value) {
  583. ip6_hdr->ip_hl = 1;
  584. } else {
  585. ip6_hdr->ip_hl -= tcpedit->ttl_value;
  586. }
  587. break;
  588. default:
  589. errx(1, "invalid ttl_mode: %d", tcpedit->ttl_mode);
  590. }
  591. return 0;
  592. }
  593. /**
  594. * takes a CIDR notation netblock and uses that to "remap" given IP
  595. * onto that netblock. ie: 10.0.0.0/8 and 192.168.55.123 -> 10.168.55.123
  596. * while 10.150.9.0/24 and 192.168.55.123 -> 10.150.9.123
  597. */
  598. static uint32_t
  599. remap_ipv4(tcpedit_t *tcpedit, tcpr_cidr_t *cidr, const uint32_t original)
  600. {
  601. uint32_t ipaddr = 0, network = 0, mask = 0, result = 0;
  602. assert(tcpedit);
  603. assert(cidr);
  604. if (cidr->family != AF_INET) {
  605. return 0;
  606. }
  607. /* don't rewrite broadcast addresses */
  608. if (tcpedit->skip_broadcast && !is_unicast_ipv4(tcpedit, original))
  609. return original;
  610. mask = 0xffffffff; /* turn on all the bits */
  611. /* shift over by correct # of bits */
  612. mask = mask << (32 - cidr->masklen);
  613. /* apply the mask to the network */
  614. network = htonl(cidr->u.network) & mask;
  615. /* apply the reverse of the mask to the IP */
  616. mask = mask ^ 0xffffffff;
  617. ipaddr = ntohl(original) & mask;
  618. /* merge the network portion and ip portions */
  619. result = network ^ ipaddr;
  620. /* return the result in network byte order */
  621. return(htonl(result));
  622. }
  623. static int
  624. remap_ipv6(tcpedit_t *tcpedit, tcpr_cidr_t *cidr, struct tcpr_in6_addr *addr)
  625. {
  626. uint32_t i, j, k;
  627. assert(tcpedit);
  628. assert(cidr);
  629. if (cidr->family != AF_INET6) {
  630. return 0;
  631. }
  632. /* don't rewrite broadcast addresses */
  633. if (tcpedit->skip_broadcast && is_multicast_ipv6(tcpedit, addr))
  634. return 0;
  635. j = cidr->masklen / 8;
  636. for (i = 0; i < j; i++)
  637. addr->tcpr_s6_addr[i] = cidr->u.network6.tcpr_s6_addr[i];
  638. if ((k = cidr->masklen % 8) == 0)
  639. return 1;
  640. k = (uint32_t)~0 << (8 - k);
  641. i = addr->tcpr_s6_addr[i] & k;
  642. addr->tcpr_s6_addr[i] = (cidr->u.network6.tcpr_s6_addr[j] & (0xff << (8 - k))) |
  643. (addr->tcpr_s6_addr[i] & (0xff >> k));
  644. return 1;
  645. }
  646. /**
  647. * rewrite IP address (layer3)
  648. * uses -N to rewrite (map) one subnet onto another subnet
  649. * also support --srcipmap and --dstipmap
  650. * return 0 if no change, 1 or 2 if changed
  651. */
  652. int
  653. rewrite_ipv4l3(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr, tcpr_dir_t direction,
  654. int len)
  655. {
  656. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  657. int didsrc = 0, diddst = 0, loop = 1;
  658. tcpr_cidrmap_t *ipmap;
  659. assert(tcpedit);
  660. assert(ip_hdr);
  661. /* first check the src/dst IP maps */
  662. ipmap = tcpedit->srcipmap;
  663. while (ipmap != NULL) {
  664. if (ip_in_cidr(ipmap->from, ip_hdr->ip_src.s_addr)) {
  665. uint32_t old_ip = ip_hdr->ip_src.s_addr;
  666. ip_hdr->ip_src.s_addr = remap_ipv4(tcpedit, ipmap->to, ip_hdr->ip_src.s_addr);
  667. ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_src.s_addr, len);
  668. dbgx(2, "Remapped src addr to: %s", get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE));
  669. break;
  670. }
  671. ipmap = ipmap->next;
  672. }
  673. ipmap = tcpedit->dstipmap;
  674. while (ipmap != NULL) {
  675. if (ip_in_cidr(ipmap->from, ip_hdr->ip_dst.s_addr)) {
  676. uint32_t old_ip = ip_hdr->ip_dst.s_addr;
  677. ip_hdr->ip_dst.s_addr = remap_ipv4(tcpedit, ipmap->to, ip_hdr->ip_dst.s_addr);
  678. ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_dst.s_addr, len);
  679. dbgx(2, "Remapped dst addr to: %s", get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE));
  680. break;
  681. }
  682. ipmap = ipmap->next;
  683. }
  684. /* anything else to rewrite? */
  685. if (tcpedit->cidrmap1 == NULL)
  686. return(0);
  687. /* don't play with the main pointers */
  688. if (direction == TCPR_DIR_C2S) {
  689. cidrmap1 = tcpedit->cidrmap1;
  690. cidrmap2 = tcpedit->cidrmap2;
  691. } else {
  692. cidrmap1 = tcpedit->cidrmap2;
  693. cidrmap2 = tcpedit->cidrmap1;
  694. }
  695. /* loop through the cidrmap to rewrite */
  696. do {
  697. if ((! diddst) && ip_in_cidr(cidrmap2->from, ip_hdr->ip_dst.s_addr)) {
  698. uint32_t old_ip = ip_hdr->ip_dst.s_addr;
  699. ip_hdr->ip_dst.s_addr = remap_ipv4(tcpedit, cidrmap2->to, ip_hdr->ip_dst.s_addr);
  700. ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_dst.s_addr, len);
  701. dbgx(2, "Remapped dst addr to: %s", get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE));
  702. diddst = 1;
  703. }
  704. if ((! didsrc) && ip_in_cidr(cidrmap1->from, ip_hdr->ip_src.s_addr)) {
  705. uint32_t old_ip = ip_hdr->ip_src.s_addr;
  706. ip_hdr->ip_src.s_addr = remap_ipv4(tcpedit, cidrmap1->to, ip_hdr->ip_src.s_addr);
  707. ipv4_addr_csum_replace(ip_hdr, old_ip, ip_hdr->ip_src.s_addr, len);
  708. dbgx(2, "Remapped src addr to: %s", get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE));
  709. didsrc = 1;
  710. }
  711. /*
  712. * loop while we haven't modified both src/dst AND
  713. * at least one of the cidr maps have a next pointer
  714. */
  715. if ((! (diddst && didsrc)) &&
  716. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  717. /* increment our ptr's if possible */
  718. if (cidrmap1->next != NULL)
  719. cidrmap1 = cidrmap1->next;
  720. if (cidrmap2->next != NULL)
  721. cidrmap2 = cidrmap2->next;
  722. } else {
  723. loop = 0;
  724. }
  725. /* Later on we should support various IP protocols which embed
  726. * the IP address in the application layer. Things like
  727. * DNS and FTP.
  728. */
  729. } while (loop);
  730. /* return how many changes we require checksum updates (none) */
  731. return 0;
  732. }
  733. int
  734. rewrite_ipv6l3(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr, tcpr_dir_t direction,
  735. int l3len)
  736. {
  737. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  738. int didsrc = 0, diddst = 0, loop = 1;
  739. tcpr_cidrmap_t *ipmap;
  740. assert(tcpedit);
  741. assert(ip6_hdr);
  742. /* first check the src/dst IP maps */
  743. ipmap = tcpedit->srcipmap;
  744. while (ipmap != NULL) {
  745. if (ip6_in_cidr(ipmap->from, &ip6_hdr->ip_src)) {
  746. struct tcpr_in6_addr old_ip6;
  747. memcpy(&old_ip6, &ip6_hdr->ip_src, sizeof(old_ip6));
  748. remap_ipv6(tcpedit, ipmap->to, &ip6_hdr->ip_src);
  749. ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, l3len);
  750. dbgx(2, "Remapped src addr to: %s", get_addr2name6(&ip6_hdr->ip_src, RESOLVE));
  751. break;
  752. }
  753. ipmap = ipmap->next;
  754. }
  755. ipmap = tcpedit->dstipmap;
  756. while (ipmap != NULL) {
  757. if (ip6_in_cidr(ipmap->from, &ip6_hdr->ip_dst)) {
  758. struct tcpr_in6_addr old_ip6;
  759. memcpy(&old_ip6, &ip6_hdr->ip_dst, sizeof(old_ip6));
  760. remap_ipv6(tcpedit, ipmap->to, &ip6_hdr->ip_dst);
  761. ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, l3len);
  762. dbgx(2, "Remapped dst addr to: %s", get_addr2name6(&ip6_hdr->ip_dst, RESOLVE));
  763. break;
  764. }
  765. ipmap = ipmap->next;
  766. }
  767. /* anything else to rewrite? */
  768. if (tcpedit->cidrmap1 == NULL)
  769. return(0);
  770. /* don't play with the main pointers */
  771. if (direction == TCPR_DIR_C2S) {
  772. cidrmap1 = tcpedit->cidrmap1;
  773. cidrmap2 = tcpedit->cidrmap2;
  774. } else {
  775. cidrmap1 = tcpedit->cidrmap2;
  776. cidrmap2 = tcpedit->cidrmap1;
  777. }
  778. /* loop through the cidrmap to rewrite */
  779. do {
  780. if ((! diddst) && ip6_in_cidr(cidrmap2->from, &ip6_hdr->ip_dst)) {
  781. struct tcpr_in6_addr old_ip6;
  782. memcpy(&old_ip6, &ip6_hdr->ip_dst, sizeof(old_ip6));
  783. remap_ipv6(tcpedit, cidrmap2->to, &ip6_hdr->ip_dst);
  784. ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_dst, l3len);
  785. dbgx(2, "Remapped dst addr to: %s", get_addr2name6(&ip6_hdr->ip_dst, RESOLVE));
  786. diddst = 1;
  787. }
  788. if ((! didsrc) && ip6_in_cidr(cidrmap1->from, &ip6_hdr->ip_src)) {
  789. struct tcpr_in6_addr old_ip6;
  790. memcpy(&old_ip6, &ip6_hdr->ip_src, sizeof(old_ip6));
  791. remap_ipv6(tcpedit, cidrmap1->to, &ip6_hdr->ip_src);
  792. ipv6_addr_csum_replace(ip6_hdr, &old_ip6, &ip6_hdr->ip_src, l3len);
  793. dbgx(2, "Remapped src addr to: %s", get_addr2name6(&ip6_hdr->ip_src, RESOLVE));
  794. didsrc = 1;
  795. }
  796. /*
  797. * loop while we haven't modified both src/dst AND
  798. * at least one of the cidr maps have a next pointer
  799. */
  800. if ((! (diddst && didsrc)) &&
  801. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  802. /* increment our ptr's if possible */
  803. if (cidrmap1->next != NULL)
  804. cidrmap1 = cidrmap1->next;
  805. if (cidrmap2->next != NULL)
  806. cidrmap2 = cidrmap2->next;
  807. } else {
  808. loop = 0;
  809. }
  810. /* Later on we should support various IP protocols which embed
  811. * the IP address in the application layer. Things like
  812. * DNS and FTP.
  813. */
  814. } while (loop);
  815. /* return how many changes we made (none) */
  816. return 0;
  817. }
  818. /**
  819. * Randomize the IP addresses in an ARP packet based on the user seed
  820. * return 0 if no change, or 1 for a change
  821. */
  822. int
  823. randomize_iparp(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  824. u_char *pktdata, int datalink, const int l3len)
  825. {
  826. arp_hdr_t *arp_hdr ;
  827. int l2len;
  828. #ifdef FORCE_ALIGN
  829. uint32_t iptemp;
  830. #endif
  831. assert(tcpedit);
  832. assert(pkthdr);
  833. assert(pktdata);
  834. if (l3len < (int)sizeof(arp_hdr_t)) {
  835. tcpedit_seterr(tcpedit, "Unable to randomize ARP packet due to packet capture snap length %u",
  836. pkthdr->caplen);
  837. return TCPEDIT_ERROR;
  838. }
  839. l2len = get_l2len(pktdata, pkthdr->caplen, datalink);
  840. arp_hdr = (arp_hdr_t *)(pktdata + l2len);
  841. /*
  842. * only rewrite IP addresses from REPLY/REQUEST's
  843. */
  844. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  845. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  846. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY))) {
  847. /* jump to the addresses */
  848. uint32_t *ip;
  849. u_char *add_hdr = ((u_char *)arp_hdr) + sizeof(arp_hdr_t) +
  850. arp_hdr->ar_hln;
  851. #ifdef FORCE_ALIGN
  852. /* copy IP to a temporary buffer for processing */
  853. memcpy(&iptemp, add_hdr, sizeof(uint32_t));
  854. ip = &iptemp;
  855. #else
  856. ip = (uint32_t *)add_hdr;
  857. #endif
  858. *ip = randomize_ipv4_addr(tcpedit, *ip);
  859. #ifdef FORCE_ALIGN
  860. memcpy(add_hdr, &iptemp, sizeof(uint32_t));
  861. #endif
  862. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  863. #ifdef FORCE_ALIGN
  864. /* copy IP2 to a temporary buffer for processing */
  865. memcpy(&iptemp, add_hdr, sizeof(uint32_t));
  866. ip = &iptemp;
  867. #else
  868. ip = (uint32_t *)add_hdr;
  869. #endif
  870. *ip = randomize_ipv4_addr(tcpedit, *ip);
  871. #ifdef FORCE_ALIGN
  872. memcpy(add_hdr, &iptemp, sizeof(uint32_t));
  873. #endif
  874. }
  875. return 1; /* yes we changed the packet */
  876. }
  877. /**
  878. * rewrite IP address (arp)
  879. * uses -a to rewrite (map) one subnet onto another subnet
  880. * pointer must point to the WHOLE and CONTIGUOUS memory buffer
  881. * because the arp_hdr_t doesn't have the space for the IP/MAC
  882. * addresses
  883. * return 0 if no change, 1 or 2 if changed
  884. */
  885. int
  886. rewrite_iparp(tcpedit_t *tcpedit, arp_hdr_t *arp_hdr, int cache_mode)
  887. {
  888. u_char *add_hdr = NULL;
  889. uint32_t *ip1 = NULL, *ip2 = NULL;
  890. uint32_t newip = 0;
  891. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  892. int didsrc = 0, diddst = 0, loop = 1;
  893. #ifdef FORCE_ALIGN
  894. uint32_t iptemp;
  895. #endif
  896. assert(tcpedit);
  897. assert(arp_hdr);
  898. /* figure out what mapping to use */
  899. if (cache_mode == TCPR_DIR_C2S) {
  900. cidrmap1 = tcpedit->cidrmap1;
  901. cidrmap2 = tcpedit->cidrmap2;
  902. } else if (cache_mode == TCPR_DIR_S2C) {
  903. cidrmap1 = tcpedit->cidrmap2;
  904. cidrmap2 = tcpedit->cidrmap1;
  905. }
  906. /* anything to rewrite? */
  907. if (cidrmap1 == NULL || cidrmap2 == NULL)
  908. return(0);
  909. /*
  910. * must be IPv4 and request or reply
  911. * Do other op codes use the same subheader stub?
  912. * If so we won't need to check the op code.
  913. */
  914. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  915. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  916. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY)))
  917. {
  918. /* jump to the addresses */
  919. add_hdr = (u_char *)arp_hdr;
  920. add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
  921. ip1 = (uint32_t *)add_hdr;
  922. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  923. #ifdef FORCE_ALIGN
  924. /* copy IP2 to a temporary buffer for processing */
  925. memcpy(&iptemp, add_hdr, sizeof(uint32_t));
  926. ip2 = &iptemp;
  927. #else
  928. ip2 = (uint32_t *)add_hdr;
  929. #endif
  930. /* loop through the cidrmap to rewrite */
  931. do {
  932. /* arp request ? */
  933. if (ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) {
  934. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip1)) {
  935. newip = remap_ipv4(tcpedit, cidrmap2->to, *ip1);
  936. memcpy(ip1, &newip, 4);
  937. diddst = 1;
  938. }
  939. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip2)) {
  940. newip = remap_ipv4(tcpedit, cidrmap1->to, *ip2);
  941. memcpy(ip2, &newip, 4);
  942. didsrc = 1;
  943. }
  944. }
  945. /* else it's an arp reply */
  946. else {
  947. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip2)) {
  948. newip = remap_ipv4(tcpedit, cidrmap2->to, *ip2);
  949. memcpy(ip2, &newip, 4);
  950. diddst = 1;
  951. }
  952. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip1)) {
  953. newip = remap_ipv4(tcpedit, cidrmap1->to, *ip1);
  954. memcpy(ip1, &newip, 4);
  955. didsrc = 1;
  956. }
  957. }
  958. #ifdef FORCE_ALIGN
  959. /* copy temporary IP to IP2 location in buffer */
  960. memcpy(add_hdr, &iptemp, sizeof(uint32_t));
  961. #endif
  962. /*
  963. * loop while we haven't modified both src/dst AND
  964. * at least one of the cidr maps have a next pointer
  965. */
  966. if ((! (diddst && didsrc)) &&
  967. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  968. /* increment our ptr's if possible */
  969. if (cidrmap1->next != NULL)
  970. cidrmap1 = cidrmap1->next;
  971. if (cidrmap2->next != NULL)
  972. cidrmap2 = cidrmap2->next;
  973. } else {
  974. loop = 0;
  975. }
  976. } while (loop);
  977. } else {
  978. warn("ARP packet isn't for IPv4! Can't rewrite IP's");
  979. }
  980. return(didsrc + diddst);
  981. }
  982. /**
  983. * returns 1 if the IP address is a unicast address, otherwise, returns 0
  984. * for broadcast/multicast addresses. Returns -1 on error
  985. */
  986. static int
  987. is_unicast_ipv4(tcpedit_t *tcpedit, uint32_t ip)
  988. {
  989. assert(tcpedit);
  990. /* multicast/broadcast is 224.0.0.0 to 239.255.255.255 */
  991. if ((ntohl(ip) & 0xf0000000) == 0xe0000000)
  992. return 0;
  993. return 1;
  994. }
  995. /**
  996. * returns 1 if the IPv6 address is a multicast address, otherwise, returns 0
  997. * for unicast/anycast addresses. Returns -1 on error
  998. */
  999. static int
  1000. is_multicast_ipv6(tcpedit_t *tcpedit, struct tcpr_in6_addr *addr)
  1001. {
  1002. assert(tcpedit);
  1003. if (addr->tcpr_s6_addr[0] == 0xff)
  1004. return 1;
  1005. return 0;
  1006. }