Logo Search packages:      
Sourcecode: tcpreplay version File versions

edit_packet.c

/* $Id: edit_packet.c 879 2004-11-07 03:32:31Z aturner $ */

/*
 * Copyright (c) 2001-2004 Aaron Turner.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright owners nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include <libnet.h>
#include <pcap.h>

#include "tcpreplay.h"
#include "edit_packet.h"
#include "cidr.h"
#include "sll.h"
#include "err.h"
#include "utils.h"

extern int maxpacket;
extern struct options options;
extern CIDRMAP *cidrmap_data1, *cidrmap_data2;

/*
 * this code re-calcs the IP and Layer 4 checksums
 * the IMPORTANT THING is that the Layer 4 header 
 * is contiguious in memory after *ip_hdr we're actually
 * writing to the layer 4 header via the ip_hdr ptr.
 * (Yes, this sucks, but that's the way libnet works, and
 * I was too lazy to re-invent the wheel.
 */
void
fix_checksums(struct pcap_pkthdr *pkthdr, ip_hdr_t * ip_hdr, libnet_t * l)
{

    /* calc the L4 checksum */
    if (libnet_do_checksum(l, (u_char *) ip_hdr, ip_hdr->ip_p,
                           ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl << 2)) < 0)
        warnx("Layer 4 checksum failed: %s", libnet_geterror(l));

    /* calc IP checksum */
    if (libnet_do_checksum((libnet_t *) l, (u_char *) ip_hdr, IPPROTO_IP,
                           ntohs(ip_hdr->ip_len)) < 0)
        warnx("IP checksum failed: %s", libnet_geterror(l));
}


/*
 * randomizes the source and destination IP addresses based on a 
 * pseudo-random number which is generated via the seed.
 * return 1 since we changed one or more IP addresses
 */
int
randomize_ips(struct pcap_pkthdr *pkthdr, u_char * pktdata,
              ip_hdr_t * ip_hdr, libnet_t * l, int l2len)
{
    /* randomize IP addresses based on the value of random */
    dbg(1, "Old Src IP: 0x%08lx\tOld Dst IP: 0x%08lx",
        ip_hdr->ip_src.s_addr, ip_hdr->ip_dst.s_addr);

    ip_hdr->ip_dst.s_addr =
        (ip_hdr->ip_dst.s_addr ^ options.seed) -
        (ip_hdr->ip_dst.s_addr & options.seed);
    ip_hdr->ip_src.s_addr =
        (ip_hdr->ip_src.s_addr ^ options.seed) -
        (ip_hdr->ip_src.s_addr & options.seed);


    dbg(1, "New Src IP: 0x%08lx\tNew Dst IP: 0x%08lx\n",
        ip_hdr->ip_src.s_addr, ip_hdr->ip_dst.s_addr);

    return(1);
}


/*
 * this code will untruncate a packet via padding it with null
 * or resetting the actual packet len to the snaplen.  In either case
 * it will recalcuate the IP and transport layer checksums.
 * return 0 if no change, 1 if change
 */

int
untrunc_packet(struct pcap_pkthdr *pkthdr, u_char * pktdata,
               ip_hdr_t * ip_hdr, libnet_t * l, int l2len)
{

    /* if actual len == cap len or there's no IP header, don't do anything */
    if ((pkthdr->caplen == pkthdr->len) || (ip_hdr == NULL)) {
        return(0);
    }

    /* Pad packet or truncate it */
    if (options.trunc == PAD_PACKET) {
        /* 
         * this should be an unnecessary check
         * but I've gotten a report that sometimes the caplen > len
         * which seems like a corrupted pcap
         */
        if (pkthdr->len > pkthdr->caplen) {
            memset(pktdata + pkthdr->caplen, 0, pkthdr->len - pkthdr->caplen);
            pkthdr->caplen = pkthdr->len;
        } else {
            /* i guess this is necessary if we've got a bogus pcap */
            ip_hdr->ip_len = htons(pkthdr->caplen);
        }

    }
    else if (options.trunc == TRUNC_PACKET) {
        ip_hdr->ip_len = htons(pkthdr->caplen);
    }
    else {
        errx(1, "Hello!  I'm not supposed to be here!");
    }

    /* fix checksums */
    fix_checksums(pkthdr, ip_hdr, l);
    return(1);
}


/*
 * Do all the layer 2 rewriting: via -2 and DLT_LINUX_SLL
 * return layer 2 length on success or 0 on fail (don't send packet)
 * we fill out pktdata using the nextpkt (original packet) and l2data (user
 * specified layer2 data)
 */
int
rewrite_l2(struct pcap_pkthdr *pkthdr, u_char * pktdata, const u_char * nextpkt,
           u_int32_t linktype, int l2enabled, char *l2data, int l2len)
{
    struct sll_header *sllhdr = NULL;   /* Linux cooked socket header */
    struct cisco_hdlc_header *hdlc_header = NULL; /*Cisco HDLC */
    eth_hdr_t *eth_hdr = NULL;

    /*
     * Depending on the DLT and the various user supplied flags (-2, -I, -J,
     * -k, -K) we need to rewrite the layer two header.  Usually this means
     * we rewrite it to look like 802.3 ethernet, but the user can do crazy
     * stuff and make it look like anything else if they use -2
     */
    switch (linktype) {
    case DLT_EN10MB:       /* Standard 802.3 Ethernet */
        if (l2enabled) {
            /*
             * is new packet too big?
             */
            if ((pkthdr->caplen - LIBNET_ETH_H + l2len) > maxpacket) {
                if (options.truncate) {
                    warnx("Packet length (%u) is greater then MTU; "
                          "truncating packet.",
                          (pkthdr->caplen - LIBNET_ETH_H + l2len));
                    pkthdr->caplen = maxpacket;
                }
                else {
                    warnx("Packet length (%u) is greater then MTU; "
                          "skipping packet.",
                          (pkthdr->caplen - LIBNET_ETH_H + l2len));
                    return (0);
                }
            }
            /*
             * remove ethernet header and copy our header back
             */
            dbg(3, "Rewriting 802.3 via -2...");
            memcpy(pktdata, l2data, l2len);
            memcpy(&pktdata[l2len], (nextpkt + LIBNET_ETH_H),
                   (pkthdr->caplen - LIBNET_ETH_H));
            /* update pkthdr->caplen with the new size */
            pkthdr->caplen = pkthdr->caplen - LIBNET_ETH_H + l2len;
        }

        else {  /* no need to replace L2 */

            /* verify that the packet isn't > maxpacket */
            if (pkthdr->caplen > maxpacket) {
                if (options.truncate) {
                    warnx("Packet length (%u) is greater then MTU; "
                          "truncating packet.",
                          pkthdr->caplen);
                    pkthdr->caplen = maxpacket;
                }
                else {
                    warnx("Packet length (%u) is greater then MTU; "
                          "skipping packet.",
                          pkthdr->caplen);
                    return (0);
                }
            }

            /*
             * since libpcap returns a pointer to a buffer 
             * malloc'd to the snaplen which might screw up
             * an untruncate situation, we have to memcpy
             * the packet to a static buffer
             */
            memcpy(pktdata, nextpkt, pkthdr->caplen);
        }
        break;

    case DLT_LINUX_SLL:    /* Linux Cooked sockets */
        if (l2enabled) {
            
            dbg(3, "Rewriting Linux SLL via -2...");
            if ((pkthdr->caplen - SLL_HDR_LEN + l2len) > maxpacket) {
                if (options.truncate) {
                    warnx("New packet length (%u) is greater then MTU; "
                          "truncating packet.",
                          (pkthdr->caplen - SLL_HDR_LEN + l2len));
                    pkthdr->caplen = maxpacket;
                }
                else {
                    warnx
                        ("New packet length (%u) is greater then MTU; "
                         "skipping packet.",
                         (pkthdr->caplen - SLL_HDR_LEN + l2len));
                    return (0);
                }
            }
            
            /* copy over our new L2 data */
            memcpy(pktdata, l2data, l2len);
            /* copy over the packet data, minus the SLL header */
            memcpy(&pktdata[l2len], (nextpkt + SLL_HDR_LEN),
                   (pkthdr->caplen - SLL_HDR_LEN));
            /* update pktdhr.caplen with new size */
            pkthdr->caplen = pkthdr->caplen - SLL_HDR_LEN + l2len;
        }
        
        else {    /* no need to rewrite L2 */
            /* verify new packet isn't > maxpacket */
            if ((pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H) > maxpacket) {
                if (options.truncate) {
                    warnx("Packet length (%u) is greater then MTU; "
                         "truncating packet.",
                         (pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H));
                    pkthdr->caplen = maxpacket;
                }
                else {
                    warnx("Packet length (%u) is greater then MTU; "
                         "skipping packet.",
                         (pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H));
                    return (0);
                }
            }
            
            /* rewrite as a standard 802.3 header */
            sllhdr = (struct sll_header *)nextpkt;
            
            switch (ntohs(sllhdr->sll_hatype)) {
            case 0x1:          /* out on the wire */
                dbg(3, "Rewriting ethernet Linux SLL header as 802.3...");
                
                /* nothing special to do here... */
                
                /* keep processing beyond case */
                break;
                
            case 0x304:        /* loopback */
                /* 
                 * loopback packets don't have a src/dst MAC, but we don't 
                 * require the SRC mac for SLL (we do require DST mac)
                 */
                if (memcmp(options.intf1_smac, NULL_MAC, ETHER_ADDR_LEN) == 0) {
                    warnx("Skipping SLL loopback packet.");
                    return (0);
                }
                break;
                
            default:
                /* who know what the hell this is */
                warnx("Unknown sll_hatype: 0x%x.  Skipping packet.",
                      ntohs(sllhdr->sll_hatype));
                return (0);
                break;
            }
            
            /*
             * Regardless of out on the wire or a loopback packet
             * there are certain things we've gotta do...
             */

            /* set the SRC MAC which may also get rewritten later */
            memcpy(&pktdata[ETHER_ADDR_LEN], options.intf1_smac, 
                   ETHER_ADDR_LEN);
            
            /* set the Protocol type (IP, ARP, etc) */
            memcpy(&pktdata[12], &sllhdr->sll_protocol, 2);
            
            /* update lengths */
            l2len = LIBNET_ETH_H;
            
            /* copy over the packet data, minus the SLL header */
            memcpy(&pktdata[l2len], (nextpkt + SLL_HDR_LEN), 
                   (pkthdr->caplen - SLL_HDR_LEN));
            
            pkthdr->caplen = pkthdr->caplen - SLL_HDR_LEN + LIBNET_ETH_H;
            pkthdr->len = pkthdr->len - SLL_HDR_LEN + LIBNET_ETH_H;
            
        }
        break;
        
    case DLT_RAW:          /* No ethernet header */
        if (l2enabled) {
            /*
             * is new packet too big?
             */
            dbg(3, "Appending header to RAW frame via -2...");
            if ((pkthdr->caplen + l2len) > maxpacket) {
                if (options.truncate) {
                    warnx("Packet length (%u) is greater then MTU; "
                         "truncating packet.", (pkthdr->caplen + l2len));
                    pkthdr->caplen = maxpacket;
                }
                else {
                    warnx("Packet length (%u) is greater then MTU; "
                         "skipping packet.", (pkthdr->caplen + l2len));
                    return (0);
                }
                
            }
            
            memcpy(pktdata, l2data, l2len);
            memcpy(&pktdata[l2len], nextpkt, pkthdr->caplen);
            pkthdr->caplen += l2len;
            
        }
        
        else {   /* no need to rewrite L2 */
            warnx("rewrite_l2(): WTF?  We can't process DLT_RAW without -2!");
            return(0);
        }
        break;
        
    case DLT_CHDLC:         /* Cisco HDLC */
        /*
         * is new packet too big?
         */
        if (l2enabled) {
            dbg(3, "Rewriting Cisco HDLC via -2...");
            if ((pkthdr->caplen - CISCO_HDLC_LEN + l2len) > maxpacket) {
                if (options.truncate) {
                    warnx("Packet length (%u) is greater then MTU; "
                          "truncating packet.",
                          (pkthdr->caplen - CISCO_HDLC_LEN + l2len));
                    pkthdr->caplen = maxpacket;
                }
                else {
                    warnx("Packet length (%u) is greater then MTU; "
                          "skipping packet.",
                          (pkthdr->caplen - CISCO_HDLC_LEN + l2len));
                    return(0);
                }
            }
            
            memcpy(pktdata, l2data, l2len);
            memcpy(&pktdata[l2len], (nextpkt + CISCO_HDLC_LEN), (pkthdr->caplen - CISCO_HDLC_LEN));
            pkthdr->caplen = pkthdr->caplen - CISCO_HDLC_LEN + l2len;
        }

        else {
        
            /* 
             * Fill out the ethernet protocol field.
             * The source/dest mac addresses which get rewritten in 
             * do_packets.c
             */
            hdlc_header = (struct cisco_hdlc_header *)nextpkt;
            eth_hdr = (eth_hdr_t *)pktdata;
            eth_hdr->ether_type = hdlc_header->protocol;
            
            /* copy over L3 and above */
            memcpy(&pktdata[LIBNET_ETH_H], (nextpkt + CISCO_HDLC_LEN), 
                   (pkthdr->caplen - CISCO_HDLC_LEN));
          
            pkthdr->caplen += LIBNET_ETH_H - CISCO_HDLC_LEN;
            
            /* update lengths */
            l2len = LIBNET_ETH_H;
        }
        break;

    } /* switch (linktype) */

    /* return the updated layer 2 len */
    return (l2len);
}

/*
 * Extracts the layer 7 data from the packet for TCP, UDP, ICMP
 * returns the number of bytes and a pointer to the layer 7 data. 
 * Returns 0 for no data
 */
int
extract_data(u_char * pktdata, int caplen, int l2len, char *l7data[])
{
    int datalen = 0;
    eth_hdr_t *eth_hdr = NULL;
    ip_hdr_t *ip_hdr = NULL;
    tcp_hdr_t *tcp_hdr = NULL;
    udp_hdr_t *udp_hdr = NULL;
#ifdef FORCE_ALIGN
    u_char ipbuff[MAXPACKET];
#endif
    char *dataptr = NULL;

    /* map the ethernet header */
    eth_hdr = (eth_hdr_t *) pktdata;

    /* return zero if not IP */
    if (ntohs(eth_hdr->ether_type) != ETHERTYPE_IP) {
        dbg(2, "Skipping non-IP frame");
        return 0;
    }



#ifdef FORCE_ALIGN
    /* 
     * copy layer 3 and up to our temp packet buffer
     * for now on, we have to edit the packetbuff because
     * just before we send the packet, we copy the packetbuff 
     * back onto the pkt.data + l2len buffer
     * we do all this work to prevent byte alignment issues
     */
    ip_hdr = (ip_hdr_t *) & ipbuff;
    memcpy(ip_hdr, pktdata[l2len], caplen - l2len);
#else
    /*
     * on non-strict byte align systems, don't need to memcpy(), 
     * just point to 14 bytes into the existing buffer
     */
    ip_hdr = (ip_hdr_t *) (pktdata + l2len);
#endif

    dataptr = (char *)ip_hdr;

    /* figure out the actual datalen which might be < the caplen
     * due to ethernet padding 
     */
    if (caplen > ntohs(ip_hdr->ip_len)) {
        datalen = ntohs(ip_hdr->ip_len);
    }
    else {
        datalen = caplen - l2len;
    }

    /* update the datlen to not include the IP header len */
    datalen -= ip_hdr->ip_hl << 2;
    dataptr += ip_hdr->ip_hl << 2;
    if (datalen <= 0)
        goto nodata;

    /* TCP ? */
    if (ip_hdr->ip_p == IPPROTO_TCP) {
        tcp_hdr = (tcp_hdr_t *) get_layer4(ip_hdr);
        datalen -= tcp_hdr->th_off << 2;
        if (datalen <= 0)
            goto nodata;

        dataptr += tcp_hdr->th_off << 2;
    }

    /* UDP ? */
    else if (ip_hdr->ip_p == IPPROTO_UDP) {
        udp_hdr = (udp_hdr_t *) get_layer4(ip_hdr);
        datalen -= LIBNET_UDP_H;
        if (datalen <= 0)
            goto nodata;

        dataptr += LIBNET_UDP_H;
    }

    /* ICMP ? just ignore it for now */
    else if (ip_hdr->ip_p == IPPROTO_ICMP) {
        dbg(2, "Ignoring any possible data in ICMP packet");
        goto nodata;
    }

    /* unknown proto, just dump everything past the IP header */
    else {
        dbg(2, "Unknown protocol, dumping everything past the IP header");
        dataptr = (char *)ip_hdr;
    }

    dbg(2, "packet had %d bytes of layer 7 data", datalen);
    memcpy(l7data, dataptr, datalen);
    return datalen;

  nodata:
    dbg(2, "packet has no data, skipping...");
    return 0;
}

/*
 * takes a CIDR notation netblock and uses that to "remap" given IP
 * onto that netblock.  ie: 10.0.0.0/8 and 192.168.55.123 -> 10.168.55.123
 * while 10.150.9.0/24 and 192.168.55.123 -> 10.150.9.123
 */
u_int32_t
remap_ip(CIDR *cidr, const u_int32_t original)
{
    u_int32_t ipaddr = 0, network = 0, mask = 0, result = 0;

    mask = ~0; /* turn on all the bits */

    /* shift over by correct # of bits */
    mask = mask << (32 - cidr->masklen);

    /* apply the mask to the network */
    network = htonl(cidr->network) & mask;

    /* apply the reverse of the mask to the IP */
    mask = mask ^ ~0;
    ipaddr = ntohl(original) & mask;

    /* merge the network portion and ip portions */
    result = network ^ ipaddr;
    
    /* return the result in network byte order */
    return(htonl(result));
}

/*
 * rewrite IP address (layer3)
 * uses -N to rewrite (map) one subnet onto another subnet
 * return 0 if no change, 1 or 2 if changed
 */
int
rewrite_ipl3(ip_hdr_t * ip_hdr, libnet_t *l)
{
    CIDRMAP *cidrmap1 = NULL, *cidrmap2 = NULL;
    int didsrc = 0, diddst = 0, loop = 1;

    /* anything to rewrite? */
    if (cidrmap_data1 == NULL)
        return(0);

    /* don't play with the main pointers */
    if (l == options.intf1) {
        cidrmap1 = cidrmap_data1;
        cidrmap2 = cidrmap_data2;
    } else {
        cidrmap1 = cidrmap_data2;
        cidrmap2 = cidrmap_data1;
    }
    

    /* loop through the cidrmap to rewrite */
    do {
        if ((! diddst) && ip_in_cidr(cidrmap2->from, ip_hdr->ip_dst.s_addr)) {
            ip_hdr->ip_dst.s_addr = remap_ip(cidrmap2->to, ip_hdr->ip_dst.s_addr);
            dbg(2, "Remapped dst addr to: %s", inet_ntoa(ip_hdr->ip_dst));
            diddst = 1;
        }
        if ((! didsrc) && ip_in_cidr(cidrmap1->from, ip_hdr->ip_src.s_addr)) {
            ip_hdr->ip_src.s_addr = remap_ip(cidrmap1->to, ip_hdr->ip_src.s_addr);
            dbg(2, "Remapped src addr to: %s", inet_ntoa(ip_hdr->ip_src));
            didsrc = 1;
        }

        /*
         * loop while we haven't modified both src/dst AND
         * at least one of the cidr maps have a next pointer
         */
        if ((! (diddst && didsrc)) &&
            (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {

            /* increment our ptr's if possible */
            if (cidrmap1->next != NULL)
                cidrmap1 = cidrmap1->next;

            if (cidrmap2->next != NULL)
                cidrmap2 = cidrmap2->next;

        } else {
            loop = 0;
        }

        /* Later on we should support various IP protocols which embed
         * the IP address in the application layer.  Things like
         * DNS and FTP.
         */

    } while (loop);

    /* return how many changes we made */
    return (diddst + didsrc);
}

/*
 * rewrite IP address (arp)
 * uses -a to rewrite (map) one subnet onto another subnet
 * pointer must point to the WHOLE and CONTIGOUS memory buffer
 * because the arp_hdr_t doesn't have the space for the IP/MAC
 * addresses
 * return 0 if no change, 1 or 2 if changed
 */
int
rewrite_iparp(arp_hdr_t *arp_hdr, libnet_t *l)
{
    u_char *add_hdr = NULL;
    u_int32_t *ip1 = NULL, *ip2 = NULL;
    u_int32_t newip = 0;
    CIDRMAP *cidrmap1 = NULL, *cidrmap2 = NULL;
    int didsrc = 0, diddst = 0, loop = 1;

   /* figure out what mapping to use */
    if (l == options.intf1) {
        cidrmap1 = cidrmap_data1;
        cidrmap2 = cidrmap_data2;
    } else if (l == options.intf2) {
        cidrmap1 = cidrmap_data2;
        cidrmap2 = cidrmap_data1;
    }

    /* anything to rewrite? */
    if (cidrmap1 == NULL || cidrmap2 == NULL)
        return(0);

    /* must be IPv4 and request or reply 
     * Do other op codes use the same subheader stub?
     * If so we won't need to check the op code.
     */
    if ((ntohs(arp_hdr->ar_pro) == ETHERTYPE_IP) &&
        ((ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) ||
         (ntohs(arp_hdr->ar_op) == ARPOP_REPLY)))
        {
        /* jump to the addresses */
        add_hdr = (u_char *)arp_hdr;
        add_hdr += sizeof(arp_hdr_t) + arp_hdr->ar_hln;
        ip1 = (u_int32_t *)add_hdr;
        add_hdr += arp_hdr->ar_pln + arp_hdr->ar_hln;
        ip2 = (u_int32_t *)add_hdr;

        /* loop through the cidrmap to rewrite */
        do {
            /* arp request ? */
            if (ntohs(arp_hdr->ar_op) == ARPOP_REQUEST) {
                if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip1)) {
                    newip = remap_ip(cidrmap2->to, *ip1);
                    memcpy(ip1, &newip, 4);
                    diddst = 1;
                }
                if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip2)) {
                    newip = remap_ip(cidrmap1->to, *ip2);
                    memcpy(ip2, &newip, 4);
                    didsrc = 1;
                }
            } 
            /* else it's an arp reply */
            else {
                if ((!diddst) && ip_in_cidr(cidrmap2->from, *ip2)) {
                    newip = remap_ip(cidrmap2->to, *ip2);
                    memcpy(ip2, &newip, 4);
                    diddst = 1;
                }
                if ((!didsrc) && ip_in_cidr(cidrmap1->from, *ip1)) {
                    newip = remap_ip(cidrmap1->to, *ip1);
                    memcpy(ip1, &newip, 4);
                    didsrc = 1;
                }
            }
            

            /*
             * loop while we haven't modified both src/dst AND
             * at least one of the cidr maps have a next pointer
             */
            if ((! (diddst && didsrc)) &&
                (! ((cidrmap1->next == NULL) && (cidrmap2->next == NULL)))) {
                
                /* increment our ptr's if possible */
                if (cidrmap1->next != NULL)
                    cidrmap1 = cidrmap1->next;
                
                if (cidrmap2->next != NULL)
                    cidrmap2 = cidrmap2->next;
                
            } else {
                loop = 0;
            }

        } while (loop);
        
    } else {
        warnx("ARP packet isn't for IPv4!  Can't rewrite IP's");
    }

    return(didsrc + diddst);
}

Generated by  Doxygen 1.6.0   Back to index