edit_packet.c 35 KB

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