edit_packet.c 35 KB

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