edit_packet.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /* $Id: edit_packet.c 1895 2007-08-22 04:24:33Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2007 Aaron Turner.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include "defines.h"
  33. #include "common.h"
  34. #include "tcpedit-int.h"
  35. #include "edit_packet.h"
  36. #include "checksum.h"
  37. #include "lib/sll.h"
  38. #include "dlt.h"
  39. #include <string.h>
  40. #include <stdlib.h>
  41. #include <sys/types.h>
  42. #include <sys/socket.h>
  43. #include <netinet/in.h>
  44. #include <arpa/inet.h>
  45. static u_int32_t randomize_ipv4_addr(tcpedit_t *tcpedit, u_int32_t ip);
  46. static u_int32_t remap_ipv4(tcpedit_t *tcpedit, tcpr_cidr_t *cidr, const u_int32_t original);
  47. static int is_unicast_ipv4(tcpedit_t *tcpedit, u_int32_t ip);
  48. /**
  49. * this code re-calcs the IP and Layer 4 checksums
  50. * the IMPORTANT THING is that the Layer 4 header
  51. * is contiguious in memory after *ip_hdr we're actually
  52. * writing to the layer 4 header via the ip_hdr ptr.
  53. * (Yes, this sucks, but that's the way libnet works, and
  54. * I was too lazy to re-invent the wheel.
  55. * Returns 0 on sucess, -1 on error
  56. */
  57. int
  58. fix_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ipv4_hdr_t *ip_hdr)
  59. {
  60. int ret1 = 0, ret2 = 0;
  61. assert(tcpedit);
  62. assert(pkthdr);
  63. assert(ip_hdr);
  64. /* calc the L4 checksum if we have the whole packet && not a frag or first frag */
  65. if (pkthdr->caplen == pkthdr->len && (htons(ip_hdr->ip_off) & IP_OFFMASK) == 0) {
  66. ret1 = do_checksum(tcpedit, (u_char *) ip_hdr,
  67. ip_hdr->ip_p, ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl << 2));
  68. if (ret1 < 0)
  69. return TCPEDIT_ERROR;
  70. }
  71. /* calc IP checksum */
  72. ret2 = do_checksum(tcpedit, (u_char *) ip_hdr, IPPROTO_IP, ntohs(ip_hdr->ip_len));
  73. if (ret2 < 0)
  74. return TCPEDIT_ERROR;
  75. /* what do we return? */
  76. if (ret1 == TCPEDIT_WARN || ret2 == TCPEDIT_WARN)
  77. return TCPEDIT_WARN;
  78. return TCPEDIT_OK;
  79. }
  80. /**
  81. * returns a new 32bit integer which is the randomized IP
  82. * based upon the user specified seed
  83. */
  84. static u_int32_t
  85. randomize_ipv4_addr(tcpedit_t *tcpedit, u_int32_t ip)
  86. {
  87. assert(tcpedit);
  88. /* don't rewrite broadcast addresses */
  89. if (tcpedit->skip_broadcast && !is_unicast_ipv4(tcpedit, ip))
  90. return ip;
  91. return ((ip ^ htonl(tcpedit->seed)) - (ip & htonl(tcpedit->seed)));
  92. }
  93. /**
  94. * randomizes the source and destination IP addresses based on a
  95. * pseudo-random number which is generated via the seed.
  96. * return 1 since we changed one or more IP addresses
  97. */
  98. int
  99. randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  100. u_char *pktdata, ipv4_hdr_t *ip_hdr)
  101. {
  102. char srcip[16], dstip[16];
  103. assert(tcpedit);
  104. assert(pkthdr);
  105. assert(pktdata);
  106. assert(ip_hdr);
  107. #ifdef DEBUG
  108. strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr,
  109. RESOLVE), 16);
  110. strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr,
  111. RESOLVE), 16);
  112. #endif
  113. /* randomize IP addresses based on the value of random */
  114. dbgx(1, "Old Src IP: %s\tOld Dst IP: %s", srcip, dstip);
  115. /* don't rewrite broadcast addresses */
  116. if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_dst.s_addr))
  117. || !tcpedit->skip_broadcast) {
  118. ip_hdr->ip_dst.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_dst.s_addr);
  119. }
  120. if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_src.s_addr))
  121. || !tcpedit->skip_broadcast) {
  122. ip_hdr->ip_src.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_src.s_addr);
  123. }
  124. #ifdef DEBUG
  125. strlcpy(srcip, get_addr2name4(ip_hdr->ip_src.s_addr,
  126. RESOLVE), 16);
  127. strlcpy(dstip, get_addr2name4(ip_hdr->ip_dst.s_addr,
  128. RESOLVE), 16);
  129. #endif
  130. dbgx(1, "New Src IP: %s\tNew Dst IP: %s\n", srcip, dstip);
  131. return(1);
  132. }
  133. /**
  134. * this code will untruncate a packet via padding it with null
  135. * or resetting the actual IPv4 packet len to the snaplen - L2 header.
  136. * return 0 if no change, 1 if change, -1 on error.
  137. */
  138. int
  139. untrunc_packet(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  140. u_char *pktdata, ipv4_hdr_t *ip_hdr)
  141. {
  142. int l2len;
  143. assert(tcpedit);
  144. assert(pkthdr);
  145. assert(pktdata);
  146. assert(ip_hdr);
  147. /* if actual len == cap len or there's no IP header, don't do anything */
  148. if ((pkthdr->caplen == pkthdr->len) || (ip_hdr == NULL)) {
  149. return(0);
  150. }
  151. if ((l2len = layer2len(tcpedit)) < 0) {
  152. tcpedit_seterr(tcpedit, "Non-sensical layer 2 length: %d", l2len);
  153. return -1;
  154. }
  155. /* Pad packet or truncate it */
  156. if (tcpedit->fixlen == TCPEDIT_FIXLEN_PAD) {
  157. /*
  158. * this should be an unnecessary check
  159. * but I've gotten a report that sometimes the caplen > len
  160. * which seems like a corrupted pcap
  161. */
  162. if (pkthdr->len > pkthdr->caplen) {
  163. memset(pktdata + pkthdr->caplen, '\0', pkthdr->len - pkthdr->caplen);
  164. pkthdr->caplen = pkthdr->len;
  165. } else if (pkthdr->len < pkthdr->caplen) {
  166. /* i guess this is necessary if we've got a bogus pcap */
  167. //ip_hdr->ip_len = htons(pkthdr->caplen - l2len);
  168. tcpedit_seterr(tcpedit, "%s", "WTF? Why is your packet larger then the capture len?");
  169. return -1;
  170. }
  171. }
  172. else if (tcpedit->fixlen == TCPEDIT_FIXLEN_TRUNC) {
  173. if (pkthdr->len != pkthdr->caplen)
  174. ip_hdr->ip_len = htons(pkthdr->caplen - l2len);
  175. pkthdr->len = pkthdr->caplen;
  176. }
  177. else {
  178. tcpedit_seterr(tcpedit, "Invalid fixlen value: 0x%x", tcpedit->fixlen);
  179. return -1;
  180. }
  181. return(1);
  182. }
  183. /**
  184. * Extracts the layer 7 data from the packet for TCP, UDP, ICMP
  185. * returns the number of bytes and a pointer to the layer 7 data.
  186. * Returns 0 for no data
  187. */
  188. int
  189. extract_data(tcpedit_t *tcpedit, const u_char *pktdata, int caplen,
  190. char *l7data[])
  191. {
  192. int datalen = 0;
  193. ipv4_hdr_t *ip_hdr = NULL;
  194. tcp_hdr_t *tcp_hdr = NULL;
  195. udp_hdr_t *udp_hdr = NULL;
  196. u_char ipbuff[MAXPACKET];
  197. u_char *dataptr = NULL;
  198. assert(tcpedit);
  199. assert(pktdata);
  200. assert(l7data);
  201. /* grab our IPv4 header */
  202. dataptr = ipbuff;
  203. if ((ip_hdr = (ipv4_hdr_t*)get_ipv4(pktdata, caplen,
  204. tcpedit->runtime.dlt1, &dataptr)) == NULL)
  205. return 0;
  206. /* figure out the actual datalen which might be < the caplen
  207. * due to ethernet padding
  208. */
  209. if (caplen > ntohs(ip_hdr->ip_len)) {
  210. datalen = ntohs(ip_hdr->ip_len);
  211. } else {
  212. datalen = caplen - tcpedit->dlt_ctx->l2len;
  213. }
  214. /* update the datlen to not include the IP header len */
  215. datalen -= ip_hdr->ip_hl << 2;
  216. dataptr += ip_hdr->ip_hl << 2;
  217. if (datalen <= 0)
  218. goto nodata;
  219. /* TCP ? */
  220. if (ip_hdr->ip_p == IPPROTO_TCP) {
  221. tcp_hdr = (tcp_hdr_t *) get_layer4(ip_hdr);
  222. datalen -= tcp_hdr->th_off << 2;
  223. if (datalen <= 0)
  224. goto nodata;
  225. dataptr += tcp_hdr->th_off << 2;
  226. }
  227. /* UDP ? */
  228. else if (ip_hdr->ip_p == IPPROTO_UDP) {
  229. udp_hdr = (udp_hdr_t *) get_layer4(ip_hdr);
  230. datalen -= TCPR_UDP_H;
  231. if (datalen <= 0)
  232. goto nodata;
  233. dataptr += TCPR_UDP_H;
  234. }
  235. /* ICMP ? just ignore it for now */
  236. else if (ip_hdr->ip_p == IPPROTO_ICMP) {
  237. dbg(2, "Ignoring any possible data in ICMP packet");
  238. goto nodata;
  239. }
  240. /* unknown proto, just dump everything past the IP header */
  241. else {
  242. dbg(2, "Unknown protocol, dumping everything past the IP header");
  243. dataptr = (u_char *)ip_hdr;
  244. }
  245. dbgx(2, "packet had %d bytes of layer 7 data", datalen);
  246. memcpy(l7data, dataptr, datalen);
  247. return datalen;
  248. nodata:
  249. dbg(2, "packet has no data, skipping...");
  250. return 0;
  251. }
  252. /**
  253. * takes a CIDR notation netblock and uses that to "remap" given IP
  254. * onto that netblock. ie: 10.0.0.0/8 and 192.168.55.123 -> 10.168.55.123
  255. * while 10.150.9.0/24 and 192.168.55.123 -> 10.150.9.123
  256. */
  257. static u_int32_t
  258. remap_ipv4(tcpedit_t *tcpedit, tcpr_cidr_t *cidr, const u_int32_t original)
  259. {
  260. u_int32_t ipaddr = 0, network = 0, mask = 0, result = 0;
  261. assert(tcpedit);
  262. assert(cidr);
  263. /* don't rewrite broadcast addresses */
  264. if (tcpedit->skip_broadcast && !is_unicast_ipv4(tcpedit, original))
  265. return original;
  266. mask = 0xffffffff; /* turn on all the bits */
  267. /* shift over by correct # of bits */
  268. mask = mask << (32 - cidr->masklen);
  269. /* apply the mask to the network */
  270. network = htonl(cidr->network) & mask;
  271. /* apply the reverse of the mask to the IP */
  272. mask = mask ^ 0xffffffff;
  273. ipaddr = ntohl(original) & mask;
  274. /* merge the network portion and ip portions */
  275. result = network ^ ipaddr;
  276. /* return the result in network byte order */
  277. return(htonl(result));
  278. }
  279. /**
  280. * rewrite IP address (layer3)
  281. * uses -N to rewrite (map) one subnet onto another subnet
  282. * also support --srcipmap and --dstipmap
  283. * return 0 if no change, 1 or 2 if changed
  284. */
  285. int
  286. rewrite_ipv4l3(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr, tcpr_dir_t direction)
  287. {
  288. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  289. int didsrc = 0, diddst = 0, loop = 1;
  290. assert(tcpedit);
  291. assert(ip_hdr);
  292. /* first check the src/dst IP maps */
  293. if (tcpedit->srcipmap != NULL) {
  294. if (ip_in_cidr(tcpedit->srcipmap->from, ip_hdr->ip_src.s_addr)) {
  295. ip_hdr->ip_src.s_addr = remap_ipv4(tcpedit, tcpedit->srcipmap->to, ip_hdr->ip_src.s_addr);
  296. dbgx(2, "Remapped src addr to: %s", get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE));
  297. }
  298. }
  299. if (tcpedit->dstipmap != NULL) {
  300. if (ip_in_cidr(tcpedit->dstipmap->from, ip_hdr->ip_dst.s_addr)) {
  301. ip_hdr->ip_dst.s_addr = remap_ipv4(tcpedit, tcpedit->dstipmap->to, ip_hdr->ip_dst.s_addr);
  302. dbgx(2, "Remapped src addr to: %s", get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE));
  303. }
  304. }
  305. /* anything else to rewrite? */
  306. if (tcpedit->cidrmap1 == NULL)
  307. return(0);
  308. /* don't play with the main pointers */
  309. if (direction == TCPR_DIR_C2S) {
  310. cidrmap1 = tcpedit->cidrmap1;
  311. cidrmap2 = tcpedit->cidrmap2;
  312. } else {
  313. cidrmap1 = tcpedit->cidrmap2;
  314. cidrmap2 = tcpedit->cidrmap1;
  315. }
  316. /* loop through the cidrmap to rewrite */
  317. do {
  318. if ((! diddst) && ip_in_cidr(cidrmap2->from, ip_hdr->ip_dst.s_addr)) {
  319. ip_hdr->ip_dst.s_addr = remap_ipv4(tcpedit, cidrmap2->to, ip_hdr->ip_dst.s_addr);
  320. dbgx(2, "Remapped dst addr to: %s", get_addr2name4(ip_hdr->ip_dst.s_addr, RESOLVE));
  321. diddst = 1;
  322. }
  323. if ((! didsrc) && ip_in_cidr(cidrmap1->from, ip_hdr->ip_src.s_addr)) {
  324. ip_hdr->ip_src.s_addr = remap_ipv4(tcpedit, cidrmap1->to, ip_hdr->ip_src.s_addr);
  325. dbgx(2, "Remapped src addr to: %s", get_addr2name4(ip_hdr->ip_src.s_addr, RESOLVE));
  326. didsrc = 1;
  327. }
  328. /*
  329. * loop while we haven't modified both src/dst AND
  330. * at least one of the cidr maps have a next pointer
  331. */
  332. if ((! (diddst && didsrc)) &&
  333. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  334. /* increment our ptr's if possible */
  335. if (cidrmap1->next != NULL)
  336. cidrmap1 = cidrmap1->next;
  337. if (cidrmap2->next != NULL)
  338. cidrmap2 = cidrmap2->next;
  339. } else {
  340. loop = 0;
  341. }
  342. /* Later on we should support various IP protocols which embed
  343. * the IP address in the application layer. Things like
  344. * DNS and FTP.
  345. */
  346. } while (loop);
  347. /* return how many changes we made */
  348. return (diddst + didsrc);
  349. }
  350. /**
  351. * Randomize the IP addresses in an ARP packet based on the user seed
  352. * return 0 if no change, or 1 for a change
  353. */
  354. int
  355. randomize_iparp(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  356. u_char *pktdata, int datalink)
  357. {
  358. arp_hdr_t *arp_hdr = NULL;
  359. int l2len = 0;
  360. u_int32_t *ip, tempip;
  361. u_char *add_hdr;
  362. assert(tcpedit);
  363. assert(pkthdr);
  364. assert(pktdata);
  365. l2len = get_l2len(pktdata, pkthdr->caplen, datalink);
  366. arp_hdr = (arp_hdr_t *)(pktdata + l2len);
  367. /*
  368. * only rewrite IP addresses from REPLY/REQUEST's
  369. */
  370. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  371. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  372. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY))) {
  373. /* jump to the addresses */
  374. add_hdr = (u_char *)arp_hdr;
  375. add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
  376. ip = (u_int32_t *)add_hdr;
  377. tempip = randomize_ipv4_addr(tcpedit, *ip);
  378. memcpy(ip, &tempip, sizeof(u_int32_t));
  379. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  380. ip = (u_int32_t *)add_hdr;
  381. tempip = randomize_ipv4_addr(tcpedit, *ip);
  382. memcpy(ip, &tempip, sizeof(u_int32_t));
  383. }
  384. return 1; /* yes we changed the packet */
  385. }
  386. /**
  387. * rewrite IP address (arp)
  388. * uses -a to rewrite (map) one subnet onto another subnet
  389. * pointer must point to the WHOLE and CONTIGOUS memory buffer
  390. * because the arp_hdr_t doesn't have the space for the IP/MAC
  391. * addresses
  392. * return 0 if no change, 1 or 2 if changed
  393. */
  394. int
  395. rewrite_iparp(tcpedit_t *tcpedit, arp_hdr_t *arp_hdr, int cache_mode)
  396. {
  397. u_char *add_hdr = NULL;
  398. u_int32_t *ip1 = NULL, *ip2 = NULL;
  399. u_int32_t newip = 0;
  400. tcpr_cidrmap_t *cidrmap1 = NULL, *cidrmap2 = NULL;
  401. int didsrc = 0, diddst = 0, loop = 1;
  402. assert(tcpedit);
  403. assert(arp_hdr);
  404. /* figure out what mapping to use */
  405. if (cache_mode == TCPR_DIR_C2S) {
  406. cidrmap1 = tcpedit->cidrmap1;
  407. cidrmap2 = tcpedit->cidrmap2;
  408. } else if (cache_mode == TCPR_DIR_S2C) {
  409. cidrmap1 = tcpedit->cidrmap2;
  410. cidrmap2 = tcpedit->cidrmap1;
  411. }
  412. /* anything to rewrite? */
  413. if (cidrmap1 == NULL || cidrmap2 == NULL)
  414. return(0);
  415. /*
  416. * must be IPv4 and request or reply
  417. * Do other op codes use the same subheader stub?
  418. * If so we won't need to check the op code.
  419. */
  420. if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
  421. ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
  422. (ntohs(arp_hdr->ar_op) == ARPOP_REPLY)))
  423. {
  424. /* jump to the addresses */
  425. add_hdr = (u_char *)arp_hdr;
  426. add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
  427. ip1 = (u_int32_t *)add_hdr;
  428. add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
  429. ip2 = (u_int32_t *)add_hdr;
  430. /* loop through the cidrmap to rewrite */
  431. do {
  432. /* arp request ? */
  433. if (ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) {
  434. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip1)) {
  435. newip = remap_ipv4(tcpedit, cidrmap2->to, *ip1);
  436. memcpy(ip1, &newip, 4);
  437. diddst = 1;
  438. }
  439. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip2)) {
  440. newip = remap_ipv4(tcpedit, cidrmap1->to, *ip2);
  441. memcpy(ip2, &newip, 4);
  442. didsrc = 1;
  443. }
  444. }
  445. /* else it's an arp reply */
  446. else {
  447. if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip2)) {
  448. newip = remap_ipv4(tcpedit, cidrmap2->to, *ip2);
  449. memcpy(ip2, &newip, 4);
  450. diddst = 1;
  451. }
  452. if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip1)) {
  453. newip = remap_ipv4(tcpedit, cidrmap1->to, *ip1);
  454. memcpy(ip1, &newip, 4);
  455. didsrc = 1;
  456. }
  457. }
  458. /*
  459. * loop while we haven't modified both src/dst AND
  460. * at least one of the cidr maps have a next pointer
  461. */
  462. if ((! (diddst && didsrc)) &&
  463. (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
  464. /* increment our ptr's if possible */
  465. if (cidrmap1->next != NULL)
  466. cidrmap1 = cidrmap1->next;
  467. if (cidrmap2->next != NULL)
  468. cidrmap2 = cidrmap2->next;
  469. } else {
  470. loop = 0;
  471. }
  472. } while (loop);
  473. } else {
  474. warn("ARP packet isn't for IPv4! Can't rewrite IP's");
  475. }
  476. return(didsrc + diddst);
  477. }
  478. /**
  479. * returns 1 if the IP address is a unicast address, otherwise, returns 0
  480. * for broadcast/multicast addresses. Returns -1 on error
  481. */
  482. static int
  483. is_unicast_ipv4(tcpedit_t *tcpedit, u_int32_t ip)
  484. {
  485. assert(tcpedit);
  486. /* multicast/broadcast is 224.0.0.0 or greater */
  487. if (ip > 3758096384)
  488. return 0;
  489. return 1;
  490. }
  491. /*
  492. Local Variables:
  493. mode:c
  494. indent-tabs-mode:nil
  495. c-basic-offset:4
  496. End:
  497. */