Logo Search packages:      
Sourcecode: tcpreplay version File versions

portmap.c

/*
 * 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.
 */

/*
 * This file contains routines to manipulate port maps, in which
 * one port number is mapped to another.
 */

#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "config.h"
#include "tcpreplay.h"
#include "utils.h"
#include "err.h"
#include "portmap.h"

#define EBUF_SIZE 256


PORTMAP *
new_portmap()
{
    PORTMAP *newportmap;

    newportmap = (PORTMAP *) malloc(sizeof(PORTMAP));
    if (newportmap == NULL)
        errx(1, "unable to malloc memory for new_portmap()");

    memset(newportmap, 0, sizeof(PORTMAP));
    return (newportmap);
}

/*
 * parses a string <port>:<port> and returns a new
 * PORTMAP datastruct
 */
static PORTMAP *
ports2PORT(char *ports)
{
    PORTMAP *portmap = NULL;
    char *from_s, *to_s, *badchar;
    long from_l, to_l;
    char *token = NULL;

    /* first split the port numbers */
    from_s = strtok_r(ports, ":", &token);
      to_s = strtok_r(NULL, ":", &token);

    /* if there's anything left, it's a syntax error */
    if (strtok_r(NULL, ":", &token) != NULL)
        return NULL;

    /* if either of the parsed strings is NULL, we have a problem */
    if (from_s == NULL || to_s == NULL)
        return NULL;

    /* convert the strings to longs: if badchar points to anything
     * after, then it was a bad string
     */
    from_l = strtol(from_s, &badchar, 10);
    if (strlen(badchar) != 0)
        return NULL;

    to_l = strtol(to_s, &badchar, 10);
    if (strlen(badchar) != 0)
        return NULL;

    portmap = new_portmap();

    /* put the new portmap info into the new node 
     * while we convert to network-byte order, b/c its better
     * to do it once now, rather then each time we have to do a lookup
     */
    portmap->from = htons(from_l);
    portmap->to = htons(to_l);

    /* return 1 for success */
    return portmap;
}

/*
 * Processes a string (ourstr) containing the portmap ("2000:4000" for
 * example) and places the data in **portmapdata and finally returns 1 for 
 * success, 0 for fail.
 */
int
parse_portmap(PORTMAP ** portmap, char *ourstr)
{
    PORTMAP *portmap_ptr;
    char *substr = NULL, *token = NULL;

    /* first iteration of input */
    substr = strtok_r(ourstr, ",", &token);

    if ((*portmap = ports2PORT(substr)) == NULL)
        return 0;

    portmap_ptr = *portmap;
    while (1) {
        substr = strtok_r(NULL, ",", &token);
        /* if that was the last one, kick out */
        if (substr == NULL)
            break;

        /* next record */
        portmap_ptr->next = ports2PORT(substr);
        portmap_ptr = portmap_ptr->next;
    }

    return 1;
}


/*
 * Free's all the memory associated with the given portmap chain
 */
void
free_portmap(PORTMAP * portmap)
{

    /* recursively go down the portmaps */
    if (portmap->next != NULL)
        free_portmap(portmap->next);

    free(portmap);
}


/* This function takes a pointer to a portmap list and prints each node */
void
print_portmap(PORTMAP *portmap_data)
{
    PORTMAP *portmap_ptr;

    portmap_ptr = portmap_data;
    while (portmap_ptr != NULL) {
        printf("from: %ld  to: %ld\n", portmap_ptr->from, portmap_ptr->to);
        portmap_ptr = portmap_ptr->next;
    }

    printf("\n");
}


/* This function takes a portmap and a port, and returns the mapped port,
 * or the original port if it isn't mapped to anything.
 */
long
map_port(PORTMAP *portmap_data, long port)
{
    PORTMAP *portmap_ptr;
    long newport;

    portmap_ptr = portmap_data;
    newport = port;

    /* step through the nodes, resetting newport if a match is found */
    while (portmap_ptr != NULL) {
        if (portmap_ptr->from == port)
            newport = portmap_ptr->to;

        portmap_ptr = portmap_ptr->next;
    }

    return(newport);
}

/*
 * rewrites the TCP or UDP ports based on a portmap
 * returns 1 for changes made or 0 for none
 */

int
rewrite_ports(PORTMAP * portmap, ip_hdr_t **ip_hdr)
{
    tcp_hdr_t *tcp_hdr = NULL;
    udp_hdr_t *udp_hdr = NULL;
    int changes = 0;
    u_int16_t newport;

    if (*ip_hdr == NULL) {
        return 0;
    } else if ((*ip_hdr)->ip_p == IPPROTO_TCP) {
        tcp_hdr = (tcp_hdr_t *)get_layer4(*ip_hdr);

        /* check if we need to remap the destination port */
        newport = map_port(portmap, tcp_hdr->th_dport);
        if (newport != tcp_hdr->th_dport) {
            tcp_hdr->th_dport = newport;
            changes ++;
        }

        /* check if we need to remap the source port */
        newport = map_port(portmap, tcp_hdr->th_sport);
        if (newport != tcp_hdr->th_sport) {
            tcp_hdr->th_sport = newport;
            changes ++;
        }
        
    } else if ((*ip_hdr)->ip_p == IPPROTO_UDP) {
        udp_hdr = (udp_hdr_t *)get_layer4(*ip_hdr);

        /* check if we need to remap the destination port */
        newport = map_port(portmap, udp_hdr->uh_dport);
        if (newport != udp_hdr->uh_dport) {
            udp_hdr->uh_dport = newport;
            changes ++;
        }

        /* check if we need to remap the source port */
        newport = map_port(portmap, udp_hdr->uh_sport);
        if (newport != udp_hdr->uh_sport) {
            udp_hdr->uh_sport = newport;
            changes ++;
        }
        

    }
    return changes;
}

Generated by  Doxygen 1.6.0   Back to index