edit_packet.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /* $Id: edit_packet.c 879 2004-11-07 03:32:31Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2004 Aaron Turner.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include <libnet.h>
  33. #include <pcap.h>
  34. #include "tcpreplay.h"
  35. #include "edit_packet.h"
  36. #include "cidr.h"
  37. #include "sll.h"
  38. #include "err.h"
  39. #include "utils.h"
  40. extern int maxpacket;
  41. extern struct options options;
  42. extern CIDRMAP *cidrmap_data1, *cidrmap_data2;
  43. /*
  44. * this code re-calcs the IP and Layer 4 checksums
  45. * the IMPORTANT THING is that the Layer 4 header
  46. * is contiguious in memory after *ip_hdr we're actually
  47. * writing to the layer 4 header via the ip_hdr ptr.
  48. * (Yes, this sucks, but that's the way libnet works, and
  49. * I was too lazy to re-invent the wheel.
  50. */
  51. void
  52. fix_checksums(struct pcap_pkthdr *pkthdr, ip_hdr_t * ip_hdr, libnet_t * l)
  53. {
  54. /* calc the L4 checksum */
  55. if (libnet_do_checksum(l, (u_char *) ip_hdr, ip_hdr->ip_p,
  56. ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl << 2)) < 0)
  57. warnx("Layer 4 checksum failed: %s", libnet_geterror(l));
  58. /* calc IP checksum */
  59. if (libnet_do_checksum((libnet_t *) l, (u_char *) ip_hdr, IPPROTO_IP,
  60. ntohs(ip_hdr->ip_len)) < 0)
  61. warnx("IP checksum failed: %s", libnet_geterror(l));
  62. }
  63. /*
  64. * randomizes the source and destination IP addresses based on a
  65. * pseudo-random number which is generated via the seed.
  66. * return 1 since we changed one or more IP addresses
  67. */
  68. int
  69. randomize_ips(struct pcap_pkthdr *pkthdr, u_char * pktdata,
  70. ip_hdr_t * ip_hdr, libnet_t * l, int l2len)
  71. {
  72. /* randomize IP addresses based on the value of random */
  73. dbg(1, "Old Src IP: 0x%08lx\tOld Dst IP: 0x%08lx",
  74. ip_hdr->ip_src.s_addr, ip_hdr->ip_dst.s_addr);
  75. ip_hdr->ip_dst.s_addr =
  76. (ip_hdr->ip_dst.s_addr ^ options.seed) -
  77. (ip_hdr->ip_dst.s_addr & options.seed);
  78. ip_hdr->ip_src.s_addr =
  79. (ip_hdr->ip_src.s_addr ^ options.seed) -
  80. (ip_hdr->ip_src.s_addr & options.seed);
  81. dbg(1, "New Src IP: 0x%08lx\tNew Dst IP: 0x%08lx\n",
  82. ip_hdr->ip_src.s_addr, ip_hdr->ip_dst.s_addr);
  83. return(1);
  84. }
  85. /*
  86. * this code will untruncate a packet via padding it with null
  87. * or resetting the actual packet len to the snaplen. In either case
  88. * it will recalcuate the IP and transport layer checksums.
  89. * return 0 if no change, 1 if change
  90. */
  91. int
  92. untrunc_packet(struct pcap_pkthdr *pkthdr, u_char * pktdata,
  93. ip_hdr_t * ip_hdr, libnet_t * l, int l2len)
  94. {
  95. /* if actual len == cap len or there's no IP header, don't do anything */
  96. if ((pkthdr->caplen == pkthdr->len) || (ip_hdr == NULL)) {
  97. return(0);
  98. }
  99. /* Pad packet or truncate it */
  100. if (options.trunc == PAD_PACKET) {
  101. /*
  102. * this should be an unnecessary check
  103. * but I've gotten a report that sometimes the caplen > len
  104. * which seems like a corrupted pcap
  105. */
  106. if (pkthdr->len > pkthdr->caplen) {
  107. memset(pktdata + pkthdr->caplen, 0, pkthdr->len - pkthdr->caplen);
  108. pkthdr->caplen = pkthdr->len;
  109. } else {
  110. /* i guess this is necessary if we've got a bogus pcap */
  111. ip_hdr->ip_len = htons(pkthdr->caplen);
  112. }
  113. }
  114. else if (options.trunc == TRUNC_PACKET) {
  115. ip_hdr->ip_len = htons(pkthdr->caplen);
  116. }
  117. else {
  118. errx(1, "Hello! I'm not supposed to be here!");
  119. }
  120. /* fix checksums */
  121. fix_checksums(pkthdr, ip_hdr, l);
  122. return(1);
  123. }
  124. /*
  125. * Do all the layer 2 rewriting: via -2 and DLT_LINUX_SLL
  126. * return layer 2 length on success or 0 on fail (don't send packet)
  127. * we fill out pktdata using the nextpkt (original packet) and l2data (user
  128. * specified layer2 data)
  129. */
  130. int
  131. rewrite_l2(struct pcap_pkthdr *pkthdr, u_char * pktdata, const u_char * nextpkt,
  132. u_int32_t linktype, int l2enabled, char *l2data, int l2len)
  133. {
  134. struct sll_header *sllhdr = NULL; /* Linux cooked socket header */
  135. struct cisco_hdlc_header *hdlc_header = NULL; /*Cisco HDLC */
  136. eth_hdr_t *eth_hdr = NULL;
  137. /*
  138. * Depending on the DLT and the various user supplied flags (-2, -I, -J,
  139. * -k, -K) we need to rewrite the layer two header. Usually this means
  140. * we rewrite it to look like 802.3 ethernet, but the user can do crazy
  141. * stuff and make it look like anything else if they use -2
  142. */
  143. switch (linktype) {
  144. case DLT_EN10MB: /* Standard 802.3 Ethernet */
  145. if (l2enabled) {
  146. /*
  147. * is new packet too big?
  148. */
  149. if ((pkthdr->caplen - LIBNET_ETH_H + l2len) > maxpacket) {
  150. if (options.truncate) {
  151. warnx("Packet length (%u) is greater then MTU; "
  152. "truncating packet.",
  153. (pkthdr->caplen - LIBNET_ETH_H + l2len));
  154. pkthdr->caplen = maxpacket;
  155. }
  156. else {
  157. warnx("Packet length (%u) is greater then MTU; "
  158. "skipping packet.",
  159. (pkthdr->caplen - LIBNET_ETH_H + l2len));
  160. return (0);
  161. }
  162. }
  163. /*
  164. * remove ethernet header and copy our header back
  165. */
  166. dbg(3, "Rewriting 802.3 via -2...");
  167. memcpy(pktdata, l2data, l2len);
  168. memcpy(&pktdata[l2len], (nextpkt + LIBNET_ETH_H),
  169. (pkthdr->caplen - LIBNET_ETH_H));
  170. /* update pkthdr->caplen with the new size */
  171. pkthdr->caplen = pkthdr->caplen - LIBNET_ETH_H + l2len;
  172. }
  173. else { /* no need to replace L2 */
  174. /* verify that the packet isn't > maxpacket */
  175. if (pkthdr->caplen > maxpacket) {
  176. if (options.truncate) {
  177. warnx("Packet length (%u) is greater then MTU; "
  178. "truncating packet.",
  179. pkthdr->caplen);
  180. pkthdr->caplen = maxpacket;
  181. }
  182. else {
  183. warnx("Packet length (%u) is greater then MTU; "
  184. "skipping packet.",
  185. pkthdr->caplen);
  186. return (0);
  187. }
  188. }
  189. /*
  190. * since libpcap returns a pointer to a buffer
  191. * malloc'd to the snaplen which might screw up
  192. * an untruncate situation, we have to memcpy
  193. * the packet to a static buffer
  194. */
  195. memcpy(pktdata, nextpkt, pkthdr->caplen);
  196. }
  197. break;
  198. case DLT_LINUX_SLL: /* Linux Cooked sockets */
  199. if (l2enabled) {
  200. dbg(3, "Rewriting Linux SLL via -2...");
  201. if ((pkthdr->caplen - SLL_HDR_LEN + l2len) > maxpacket) {
  202. if (options.truncate) {
  203. warnx("New packet length (%u) is greater then MTU; "
  204. "truncating packet.",
  205. (pkthdr->caplen - SLL_HDR_LEN + l2len));
  206. pkthdr->caplen = maxpacket;
  207. }
  208. else {
  209. warnx
  210. ("New packet length (%u) is greater then MTU; "
  211. "skipping packet.",
  212. (pkthdr->caplen - SLL_HDR_LEN + l2len));
  213. return (0);
  214. }
  215. }
  216. /* copy over our new L2 data */
  217. memcpy(pktdata, l2data, l2len);
  218. /* copy over the packet data, minus the SLL header */
  219. memcpy(&pktdata[l2len], (nextpkt + SLL_HDR_LEN),
  220. (pkthdr->caplen - SLL_HDR_LEN));
  221. /* update pktdhr.caplen with new size */
  222. pkthdr->caplen = pkthdr->caplen - SLL_HDR_LEN + l2len;
  223. }
  224. else { /* no need to rewrite L2 */
  225. /* verify new packet isn't > maxpacket */
  226. if ((pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H) > maxpacket) {
  227. if (options.truncate) {
  228. warnx("Packet length (%u) is greater then MTU; "
  229. "truncating packet.",
  230. (pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H));
  231. pkthdr->caplen = maxpacket;
  232. }
  233. else {
  234. warnx("Packet length (%u) is greater then MTU; "
  235. "skipping packet.",
  236. (pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H));
  237. return (0);
  238. }
  239. }
  240. /* rewrite as a standard 802.3 header */
  241. sllhdr = (struct sll_header *)nextpkt;
  242. switch (ntohs(sllhdr->sll_hatype)) {
  243. case 0x1: /* out on the wire */
  244. dbg(3, "Rewriting ethernet Linux SLL header as 802.3...");
  245. /* nothing special to do here... */
  246. /* keep processing beyond case */
  247. break;
  248. case 0x304: /* loopback */
  249. /*
  250. * loopback packets don't have a src/dst MAC, but we don't
  251. * require the SRC mac for SLL (we do require DST mac)
  252. */
  253. if (memcmp(options.intf1_smac, NULL_MAC, ETHER_ADDR_LEN) == 0) {
  254. warnx("Skipping SLL loopback packet.");
  255. return (0);
  256. }
  257. break;
  258. default:
  259. /* who know what the hell this is */
  260. warnx("Unknown sll_hatype: 0x%x. Skipping packet.",
  261. ntohs(sllhdr->sll_hatype));
  262. return (0);
  263. break;
  264. }
  265. /*
  266. * Regardless of out on the wire or a loopback packet
  267. * there are certain things we've gotta do...
  268. */
  269. /* set the SRC MAC which may also get rewritten later */
  270. memcpy(&pktdata[ETHER_ADDR_LEN], options.intf1_smac,
  271. ETHER_ADDR_LEN);
  272. /* set the Protocol type (IP, ARP, etc) */
  273. memcpy(&pktdata[12], &sllhdr->sll_protocol, 2);
  274. /* update lengths */
  275. l2len = LIBNET_ETH_H;
  276. /* copy over the packet data, minus the SLL header */
  277. memcpy(&pktdata[l2len], (nextpkt + SLL_HDR_LEN),
  278. (pkthdr->caplen - SLL_HDR_LEN));
  279. pkthdr->caplen = pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H;
  280. pkthdr->len = pkthdr->len - SLL_HDR_LEN + LIBNET_ETH_H;
  281. }
  282. break;
  283. case DLT_RAW: /* No ethernet header */
  284. if (l2enabled) {
  285. /*
  286. * is new packet too big?
  287. */
  288. dbg(3, "Appending header to RAW frame via -2...");
  289. if ((pkthdr->caplen + l2len) > maxpacket) {
  290. if (options.truncate) {
  291. warnx("Packet length (%u) is greater then MTU; "
  292. "truncating packet.", (pkthdr->caplen + l2len));
  293. pkthdr->caplen = maxpacket;
  294. }
  295. else {
  296. warnx("Packet length (%u) is greater then MTU; "
  297. "skipping packet.", (pkthdr->caplen + l2len));
  298. return (0);
  299. }
  300. }
  301. memcpy(pktdata, l2data, l2len);
  302. memcpy(&pktdata[l2len], nextpkt, pkthdr->caplen);
  303. pkthdr->caplen += l2len;
  304. }
  305. else { /* no need to rewrite L2 */
  306. warnx("rewrite_l2(): WTF? We can't process DLT_RAW without -2!");
  307. return(0);
  308. }
  309. break;
  310. case DLT_CHDLC: /* Cisco HDLC */
  311. /*
  312. * is new packet too big?
  313. */
  314. if (l2enabled) {
  315. dbg(3, "Rewriting Cisco HDLC via -2...");
  316. if ((pkthdr->caplen - CISCO_HDLC_LEN + l2len) > maxpacket) {
  317. if (options.truncate) {
  318. warnx("Packet length (%u) is greater then MTU; "
  319. "truncating packet.",
  320. (pkthdr->caplen - CISCO_HDLC_LEN + l2len));
  321. pkthdr->caplen = maxpacket;
  322. }
  323. else {
  324. warnx("Packet length (%u) is greater then MTU; "
  325. "skipping packet.",
  326. (pkthdr->caplen - CISCO_HDLC_LEN + l2len));
  327. return(0);
  328. }
  329. }
  330. memcpy(pktdata, l2data, l2len);
  331. memcpy(&pktdata[l2len], (nextpkt + CISCO_HDLC_LEN), (pkthdr->caplen - CISCO_HDLC_LEN));
  332. pkthdr->caplen = pkthdr->caplen - CISCO_HDLC_LEN + l2len;
  333. }
  334. else {
  335. /*
  336. * Fill out the ethernet protocol field.
  337. * The source/dest mac addresses which get rewritten in
  338. * do_packets.c
  339. */
  340. hdlc_header = (struct cisco_hdlc_header *)nextpkt;
  341. eth_hdr = (eth_hdr_t *)pktdata;
  342. eth_hdr->ether_type = hdlc_header->protocol;
  343. /* copy over L3 and above */
  344. memcpy(&pktdata[LIBNET_ETH_H], (nextpkt + CISCO_HDLC_LEN),
  345. (pkthdr->caplen - CISCO_HDLC_LEN));
  346. pkthdr->caplen += LIBNET_ETH_H - CISCO_HDLC_LEN;
  347. /* update lengths */
  348. l2len = LIBNET_ETH_H;
  349. }
  350. break;
  351. } /* switch (linktype) */
  352. /* return the updated layer 2 len */
  353. return (l2len);
  354. }
  355. /*
  356. * Extracts the layer 7 data from the packet for TCP, UDP, ICMP
  357. * returns the number of bytes and a pointer to the layer 7 data.
  358. * Returns 0 for no data
  359. */
  360. int
  361. extract_data(u_char * pktdata, int caplen, int l2len, char *l7data[])
  362. {
  363. int datalen = 0;
  364. eth_hdr_t *eth_hdr = NULL;
  365. ip_hdr_t *ip_hdr = NULL;
  366. tcp_hdr_t *tcp_hdr = NULL;
  367. udp_hdr_t *udp_hdr = NULL;
  368. #ifdef FORCE_ALIGN
  369. u_char ipbuff[MAXPACKET];
  370. #endif
  371. char *dataptr = NULL;
  372. /* map the ethernet header */
  373. eth_hdr = (eth_hdr_t *) pktdata;
  374. /* return zero if not IP */
  375. if (ntohs(eth_hdr->ether_type) != ETHERTYPE_IP) {
  376. dbg(2, "Skipping non-IP frame");
  377. return 0;
  378. }
  379. #ifdef FORCE_ALIGN
  380. /*
  381. * copy layer 3 and up to our temp packet buffer
  382. * for now on, we have to edit the packetbuff because
  383. * just before we send the packet, we copy the packetbuff
  384. * back onto the pkt.data + l2len buffer
  385. * we do all this work to prevent byte alignment issues
  386. */
  387. ip_hdr = (ip_hdr_t *) & ipbuff;
  388. memcpy(ip_hdr, pktdata[l2len], caplen - l2len);
  389. #else
  390. /*
  391. * on non-strict byte align systems, don't need to memcpy(),
  392. * just point to 14 bytes into the existing buffer
  393. */
  394. ip_hdr = (ip_hdr_t *) (pktdata + l2len);
  395. #endif
  396. dataptr = (char *)ip_hdr;
  397. /* figure out the actual datalen which might be < the caplen
  398. * due to ethernet padding
  399. */
  400. if (caplen > ntohs(ip_hdr->ip_len)) {
  401. datalen = ntohs(ip_hdr->ip_len);
  402. }
  403. else {
  404. datalen = caplen - l2len;
  405. }
  406. /* update the datlen to not include the IP header len */
  407. datalen -= ip_hdr->ip_hl << 2;
  408. dataptr += ip_hdr->ip_hl << 2;
  409. if (datalen <= 0)
  410. goto nodata;
  411. /* TCP ? */
  412. if (ip_hdr->ip_p == IPPROTO_TCP) {
  413. tcp_hdr = (tcp_hdr_t *) get_layer4(ip_hdr);
  414. datalen -= tcp_hdr->th_off << 2;
  415. if (datalen <= 0)
  416. goto nodata;
  417. dataptr += tcp_hdr->th_off << 2;
  418. }
  419. /* UDP ? */
  420. else if (ip_hdr->ip_p == IPPROTO_UDP) {
  421. udp_hdr = (udp_hdr_t *) get_layer4(ip_hdr);
  422. datalen -= LIBNET_UDP_H;
  423. if (datalen <= 0)
  424. goto nodata;
  425. dataptr += LIBNET_UDP_H;
  426. }
  427. /* ICMP ? just ignore it for now */
  428. else if (ip_hdr->ip_p == IPPROTO_ICMP) {
  429. dbg(2, "Ignoring any possible data in ICMP packet");
  430. goto nodata;
  431. }
  432. /* unknown proto, just dump everything past the IP header */
  433. else {
  434. dbg(2, "Unknown protocol, dumping everything past the IP header");
  435. dataptr = (char *)ip_hdr;
  436. }
  437. dbg(2, "packet had %d bytes of layer 7 data", datalen);
  438. memcpy(l7data, dataptr, datalen);
  439. return datalen;
  440. nodata:
  441. dbg(2, "packet has no data, skipping...");
  442. return 0;
  443. }
  444. /*
  445. * takes a CIDR notation netblock and uses that to "remap" given IP
  446. * onto that netblock. ie: 10.0.0.0/8 and 192.168.55.123 -> 10.168.55.123
  447. * while 10.150.9.0/24 and 192.168.55.123 -> 10.150.9.123
  448. */
  449. u_int32_t
  450. remap_ip(CIDR *cidr, const u_int32_t original)
  451. {
  452. u_int32_t ipaddr = 0, network = 0, mask = 0, result = 0;
  453. mask = ~0; /* turn on all the bits */
  454. /* shift over by correct # of bits */
  455. mask = mask << (32 - cidr->masklen);
  456. /* apply the mask to the network */
  457. network = htonl(cidr->network) & mask;
  458. /* apply the reverse of the mask to the IP */
  459. mask = mask ^ ~0;
  460. ipaddr = ntohl(original) & mask;
  461. /* merge the network portion and ip portions */
  462. result = network ^ ipaddr;
  463. /* return the result in network byte order */
  464. return(htonl(result));
  465. }
  466. /*
  467. * rewrite IP address (layer3)
  468. * uses -N to rewrite (map) one subnet onto another subnet
  469. * return 0 if no change, 1 or 2 if changed
  470. */
  471. int
  472. rewrite_ipl3(ip_hdr_t * ip_hdr, libnet_t *l)
  473. {
  474. CIDRMAP *cidrmap1 = NULL, *cidrmap2 = NULL;
  475. int didsrc = 0, diddst = 0, loop = 1;
  476. /* anything to rewrite? */
  477. if (cidrmap_data1 == NULL)
  478. return(0);
  479. /* don't play with the main pointers */
  480. if (l == options.intf1) {
  481. cidrmap1 = cidrmap_data1;
  482. cidrmap2 = cidrmap_data2;
  483. } else {
  484. cidrmap1 = cidrmap_data2;
  485. cidrmap2 = cidrmap_data1;
  486. }
  487. /* loop through the cidrmap to rewrite */
  488. do {
  489. if ((! diddst) && ip_in_cidr(cidrmap2->from, ip_hdr->ip_dst.s_addr)) {
  490. ip_hdr->ip_dst.s_addr = remap_ip(cidrmap2->to, ip_hdr->ip_dst.s_addr);
  491. dbg(2, "Remapped dst addr to: %s", inet_ntoa(ip_hdr->ip_dst));
  492. diddst = 1;
  493. }
  494. if ((! didsrc) && ip_in_cidr(cidrmap1->from, ip_hdr->ip_src.s_addr)) {
  495. ip_hdr->ip_src.s_addr = remap_ip(cidrmap1->to, ip_hdr->ip_src.s_addr);
  496. dbg(2, "Remapped src addr to: %s", inet_ntoa(ip_hdr->ip_src));
  497. didsrc = 1;
  498. }
  499. /*
  500. * loop while we haven't modified both src/dst AND
  501. * at least one of the cidr maps have a next pointer
  502. */
  503. if ((! (diddst && didsrc)) &&
  504. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  505. /* increment our ptr's if possible */
  506. if (cidrmap1->next != NULL)
  507. cidrmap1 = cidrmap1->next;
  508. if (cidrmap2->next != NULL)
  509. cidrmap2 = cidrmap2->next;
  510. } else {
  511. loop = 0;
  512. }
  513. /* Later on we should support various IP protocols which embed
  514. * the IP address in the application layer. Things like
  515. * DNS and FTP.
  516. */
  517. } while (loop);
  518. /* return how many changes we made */
  519. return (diddst + didsrc);
  520. }
  521. /*
  522. * rewrite IP address (arp)
  523. * uses -a to rewrite (map) one subnet onto another subnet
  524. * pointer must point to the WHOLE and CONTIGOUS memory buffer
  525. * because the arp_hdr_t doesn't have the space for the IP/MAC
  526. * addresses
  527. * return 0 if no change, 1 or 2 if changed
  528. */
  529. int
  530. rewrite_iparp(arp_hdr_t *arp_hdr, libnet_t *l)
  531. {
  532. u_char *add_hdr = NULL;
  533. u_int32_t *ip1 = NULL, *ip2 = NULL;
  534. u_int32_t newip = 0;
  535. CIDRMAP *cidrmap1 = NULL, *cidrmap2 = NULL;
  536. int didsrc = 0, diddst = 0, loop = 1;
  537. /* figure out what mapping to use */
  538. if (l == options.intf1) {
  539. cidrmap1 = cidrmap_data1;
  540. cidrmap2 = cidrmap_data2;
  541. } else if (l == options.intf2) {
  542. cidrmap1 = cidrmap_data2;
  543. cidrmap2 = cidrmap_data1;
  544. }
  545. /* anything to rewrite? */
  546. if (cidrmap1 == NULL || cidrmap2 == NULL)
  547. return(0);
  548. /* must be IPv4 and request or reply
  549. * Do other op codes use the same subheader stub?
  550. * If so we won't need to check the op code.
  551. */
  552. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  553. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  554. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY)))
  555. {
  556. /* jump to the addresses */
  557. add_hdr = (u_char *)arp_hdr;
  558. add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
  559. ip1 = (u_int32_t *)add_hdr;
  560. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  561. ip2 = (u_int32_t *)add_hdr;
  562. /* loop through the cidrmap to rewrite */
  563. do {
  564. /* arp request ? */
  565. if (ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) {
  566. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip1)) {
  567. newip = remap_ip(cidrmap2->to, *ip1);
  568. memcpy(ip1, &newip, 4);
  569. diddst = 1;
  570. }
  571. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip2)) {
  572. newip = remap_ip(cidrmap1->to, *ip2);
  573. memcpy(ip2, &newip, 4);
  574. didsrc = 1;
  575. }
  576. }
  577. /* else it's an arp reply */
  578. else {
  579. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip2)) {
  580. newip = remap_ip(cidrmap2->to, *ip2);
  581. memcpy(ip2, &newip, 4);
  582. diddst = 1;
  583. }
  584. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip1)) {
  585. newip = remap_ip(cidrmap1->to, *ip1);
  586. memcpy(ip1, &newip, 4);
  587. didsrc = 1;
  588. }
  589. }
  590. /*
  591. * loop while we haven't modified both src/dst AND
  592. * at least one of the cidr maps have a next pointer
  593. */
  594. if ((! (diddst && didsrc)) &&
  595. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  596. /* increment our ptr's if possible */
  597. if (cidrmap1->next != NULL)
  598. cidrmap1 = cidrmap1->next;
  599. if (cidrmap2->next != NULL)
  600. cidrmap2 = cidrmap2->next;
  601. } else {
  602. loop = 0;
  603. }
  604. } while (loop);
  605. } else {
  606. warnx("ARP packet isn't for IPv4! Can't rewrite IP's");
  607. }
  608. return(didsrc + diddst);
  609. }