Esempio n. 1
0
/**
 * calculates wether each node in the tree is a client, server, or unknown for each node in the tree
 */
void
tree_calculate(tcpr_data_tree_t *treeroot)
{
    tcpr_tree_t *node;
    tcpprep_opt_t *options = tcpprep->options;

    dbg(1, "Running tree_calculate()");

    RB_FOREACH(node, tcpr_data_tree_s, treeroot) {
        dbgx(4, "Processing %s", get_addr2name4(node->u.ip, RESOLVE));
        if ((node->server_cnt > 0) || (node->client_cnt > 0)) {
            /* type based on: server >= (client*ratio) */
            if ((double)node->server_cnt >= (double)node->client_cnt * options->ratio) {
                node->type = DIR_SERVER;
                dbgx(3, "Setting %s to server", 
                        get_addr2name4(node->u.ip, RESOLVE));
            }
            else {
                node->type = DIR_CLIENT;
                dbgx(3, "Setting %s to client", 
                        get_addr2name4(node->u.ip, RESOLVE));
            }
        }
        else {                  /* IP had no client or server connections */
            node->type = DIR_UNKNOWN;
            dbgx(3, "Setting %s to unknown", 
                    get_addr2name4(node->u.ip, RESOLVE));
        }
    }
Esempio n. 2
0
/*
 * return the length of the L2 header of the current packet
 */
int
dlt_jnpr_ether_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
{
    uint16_t len;
    jnpr_ether_config_t *config;

    assert(ctx);
    assert(packet);
    assert(pktlen);

    config = (jnpr_ether_config_t *)ctx->encoder->config;

    /* first get the Juniper header length */
    memcpy(&len, &packet[JUNIPER_ETHER_EXTLEN_OFFSET], 2);

    len = ntohs(len) + JUNIPER_ETHER_HEADER_LEN;
    dbgx(3, "juniper header len: %u", len);

    /* add the 802.3 length */
    len += tcpedit_dlt_l2len(config->subctx, DLT_EN10MB, (packet + len), (pktlen - len));
    dbgx(3, "total l2len: %u", len);

    /* and return that */
    return len;
}
Esempio n. 3
0
/**
 * returns the next payload or header of the current extention header
 * returns NULL for none/ESP.
 */
void *
get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
{
    int extlen = 0;
    int maxlen;
    void *ptr;
    assert(exthdr);

    maxlen = (int)((u_char *)exthdr + len);

    dbgx(3, "Jumping to next IPv6 header.  Processing 0x%02x", exthdr->ip_nh);
    switch (exthdr->ip_nh) {
    /* no further processing */
    case TCPR_IPV6_NH_NO_NEXT:
    case TCPR_IPV6_NH_ESP:
        dbg(3, "No-Next or ESP... can't go any further...");
        return NULL;
        break;

    /*
     * fragment header is fixed size 
     * FIXME: Frag header has further ext headers (has a ip_nh field)
     * but I don't support it because there's never a full L4 + payload beyond.
     */
    case TCPR_IPV6_NH_FRAGMENT:
        dbg(3, "Looks like were a fragment header. Returning some frag'd data.");
        ptr = (void *)((u_char *)exthdr + sizeof(struct tcpr_ipv6_frag_hdr));
        if ((int)ptr > maxlen)
            return NULL;
        return ptr;
        break;

    /* all the rest require us to go deeper using the ip_len field */
    case TCPR_IPV6_NH_IPV6:
    case TCPR_IPV6_NH_ROUTING:
    case TCPR_IPV6_NH_DESTOPTS:
    case TCPR_IPV6_NH_HBH:
    case TCPR_IPV6_NH_AH:
        extlen = IPV6_EXTLEN_TO_BYTES(exthdr->ip_len);
        dbgx(3, "Looks like we're an ext header (0x%hhx).  Jumping %u bytes"
               " to the next", exthdr->ip_nh, extlen);
        ptr = (void *)((u_char *)exthdr + extlen);
        if ((int)ptr > maxlen)
            return NULL;
        return ptr;
        break;

    default:
        dbg(3, "Must not be a v6 extension header... returning self");
        return (void *)exthdr;
        break;
    }
}
Esempio n. 4
0
/**
 * \brief Build TX ring buffer request structure
 *
 * This builds a ring buffer request structure making sure
 * that we have buffers big enough so that a frame which
 * is the size of the MTU doesn't get truncated. We also
 * need to structure things with minimum memory wastage 
 */
void
txring_mkreq(struct tpacket_req* treq, unsigned int mtu)
{
    unsigned int pg,bs;
    unsigned int s;
    unsigned int mult = 1;
    unsigned nr_blocks = 1000;

    bs = pg = getpagesize();
    s = mtu + TPACKET_HDRLEN;

    memset(treq, 0, sizeof(struct tpacket_req));
    if (bs <= s) {
        while(bs < s) {
            bs += pg;
            mult++;
        }

        treq->tp_block_size = bs;
        treq->tp_frame_size = bs / mult;
        treq->tp_block_nr   = nr_blocks;
        treq->tp_frame_nr   = mult * nr_blocks;
    } else {
        while ((s * (mult + 1)) <=pg) {
            mult++;
        }
        treq->tp_block_size = pg;
        treq->tp_frame_size = pg / mult;
        treq->tp_block_nr   = nr_blocks;
        treq->tp_frame_nr   = mult * nr_blocks;
    }
    dbgx(1, "txring: block_size=%d block_nr=%d frame_size=%d frame_nr=%d", 
            treq->tp_block_size, treq->tp_block_nr, treq->tp_frame_size, 
            treq->tp_frame_nr);
}
Esempio n. 5
0
/*
 * Function to decode the layer 2 header in the packet.
 * You need to fill out:
 * - ctx->l2len
 * - ctx->srcaddr
 * - ctx->dstaddr
 * - ctx->proto
 * - ctx->decoded_extra
 * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
 */
int 
dlt_ieee80211_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
{
    assert(ctx);
    assert(packet);
    assert(pktlen >= dlt_ieee80211_l2len(ctx, packet, pktlen));

    dbgx(3, "Decoding 802.11 packet " COUNTER_SPEC, ctx->tcpedit->runtime.packetnum);
    if (! ieee80211_is_data(ctx, packet, pktlen)) {
        tcpedit_seterr(ctx->tcpedit, "Packet " COUNTER_SPEC " is not a normal 802.11 data frame",
            ctx->tcpedit->runtime.packetnum);
        return TCPEDIT_SOFT_ERROR;
    }
    
    if (ieee80211_is_encrypted(ctx, packet, pktlen)) {
        tcpedit_seterr(ctx->tcpedit, "Packet " COUNTER_SPEC " is encrypted.  Unable to decode frame.",
            ctx->tcpedit->runtime.packetnum);
        return TCPEDIT_SOFT_ERROR;
    }

    ctx->l2len = dlt_ieee80211_l2len(ctx, packet, pktlen);
    memcpy(&(ctx->srcaddr), ieee80211_get_src((ieee80211_hdr_t *)packet), ETHER_ADDR_LEN);
    memcpy(&(ctx->dstaddr), ieee80211_get_dst((ieee80211_hdr_t *)packet), ETHER_ADDR_LEN);
    ctx->proto = dlt_ieee80211_proto(ctx, packet, pktlen);

    return TCPEDIT_OK; /* success */
}
Esempio n. 6
0
/**
 * This task will call send() procedure
 */
void *
txring_send(void *arg)
{
    int ec_send;
    static int total = 0;
    int fd_socket = (int)arg;

    do {
        /* send all buffers with TP_STATUS_SEND_REQUEST */
        ec_send=sendto(fd_socket, NULL, 0, MSG_DONTWAIT,
                (struct sockaddr *)NULL, sizeof(struct sockaddr_ll));

        if (ec_send > 0) {
            total += ec_send;
            dbgx(2, "Sent %d bytes (+%d bytes)", total, ec_send);
        } else  {
            /* nothing to do => schedule : useful if no SMP */
            usleep(100);
        }


    } while (!shutdown_flag);

    //if(blocking) printf("end of task send()\n");
    //printf("end of task send(ec=%x)\n", ec_send);

    return (void*) ec_send;
}
Esempio n. 7
0
/**
 * Closes connection to Quick TX module
 */
static void
sendpacket_close_quick_tx(sendpacket_t *sp)
{
    struct quick_tx* dev;

    assert(sp);

    dev = sp->qtx_dev;
    if (dev) {
        int i;

        for (i = (dev->data->num_mem_blocks - 1); i >= 0; i--) {
            struct quick_tx_mem_block_entry* mem_block = &dev->data->mem_blocks[i];
            if (munmap (mem_block->user_addr, mem_block->length) == -1)
                dbgx(1, "[quick_tx] error while calling munmap for block %d\n", i);
        }

        if (munmap ((void*)dev->data, dev->map_length) == -1)
            dbg(1, "[quick_tx] error while calling munmap\n");

        free(dev);
    }

    close(sp->handle.fd);
}
Esempio n. 8
0
/* 
 * return the length of the L2 header of the current packet
 * based on: http://www.tcpdump.org/lists/workers/2004/07/msg00121.html
 */
int
dlt_ieee80211_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
{
    u_int16_t *frame_control, fc;
    struct tcpr_802_2snap_hdr *hdr;
    int hdrlen = 0;


    assert(ctx);
    assert(packet);
    assert(pktlen);
    
    dbgx(2, "packet = %p\t\tplen = %d", packet, pktlen);

    frame_control = (u_int16_t *)packet;
    fc = ntohs(*frame_control);

    
    if (ieee80211_USE_4(fc)) {
        hdrlen = sizeof(ieee80211_addr4_hdr_t);
    } else {
        hdrlen = sizeof(ieee80211_hdr_t);
    }
    
    /* if Data/QoS, then L2 len is + 2 bytes */
    if ((fc & ieee80211_FC_SUBTYPE_QOS) == ieee80211_FC_SUBTYPE_QOS) {
        dbgx(2, "total header length (fc %04x) (802.11 + QoS data): %d", fc, hdrlen + 2);
        hdrlen += 2;
    }

    if (pktlen >= (hdrlen + (int)sizeof(struct tcpr_802_2snap_hdr))) {
    
        hdr = (struct tcpr_802_2snap_hdr *)&packet[hdrlen];
    
        /* verify the header is 802.2SNAP (8 bytes) not 802.2 (3 bytes) */
        if (hdr->snap_dsap == 0xAA && hdr->snap_ssap == 0xAA) {
            hdrlen += (int)sizeof(struct tcpr_802_2snap_hdr);
            dbgx(2, "total header length (802.11 + 802.2SNAP): %d", hdrlen);
        } else {
            hdrlen += (int)sizeof(struct tcpr_802_2_hdr);
            dbgx(2, "total header length (802.11 + 802.2): %d (%02x/%02x)", hdrlen, hdr->snap_dsap, hdr->snap_ssap);
        }
    }
    
    dbgx(2, "header length: %d", hdrlen);
    return hdrlen;
}
Esempio n. 9
0
/*
 * Function to decode the layer 2 header in the packet.
 * You need to fill out:
 * - ctx->l2len
 * - ctx->srcaddr
 * - ctx->dstaddr
 * - ctx->proto
 * - ctx->decoded_extra
 * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
 */
int
dlt_jnpr_ether_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
{
    int jnpr_header_len = 0;
    const u_char *ethernet = NULL;
    jnpr_ether_config_t *config;


    assert(ctx);
    assert(packet);
    assert(pktlen > JUNIPER_ETHER_HEADER_LEN); /* MAGIC + Static fields + Extension Length */

    config = (jnpr_ether_config_t *)ctx->encoder->config;


    /* first, verify magic */
    if (memcmp(packet, JUNIPER_ETHER_MAGIC, JUNIPER_ETHER_MAGIC_LEN) != 0) {
        tcpedit_seterr(ctx->tcpedit, "Invalid magic 0x%02X%02X%02X",
                       packet[0], packet[1], packet[2]);
        return TCPEDIT_ERROR;
    }

    /* next make sure the L2 header is present */
    if ((packet[JUNIPER_ETHER_OPTIONS_OFFSET] & JUNIPER_ETHER_L2PRESENT)
            != JUNIPER_ETHER_L2PRESENT) {
        tcpedit_seterr(ctx->tcpedit, "Frame is missing L2 Header: %x",
                       packet[JUNIPER_ETHER_OPTIONS_OFFSET]);
        return TCPEDIT_ERROR;
    }

    /* then get the Juniper header length */
    memcpy(&jnpr_header_len, &packet[JUNIPER_ETHER_EXTLEN_OFFSET], 2);

    jnpr_header_len = ntohs(jnpr_header_len) + JUNIPER_ETHER_HEADER_LEN;

    dbgx(1, "jnpr header len: %d", jnpr_header_len);
    /* make sure the packet is big enough to find the Ethernet Header */

    if (pktlen < jnpr_header_len + TCPR_ETH_H) {
        tcpedit_seterr(ctx->tcpedit, "Frame is too short! %d < %d",
                       pktlen, (jnpr_header_len + TCPR_ETH_H));
        return TCPEDIT_ERROR;
    }

    ctx->l2len = jnpr_header_len;

    /* jump to the appropriate offset */
    ethernet = packet + jnpr_header_len;

    /* let the en10mb plugin decode the rest */
    if (tcpedit_dlt_decode(config->subctx, ethernet, (pktlen - jnpr_header_len)) == TCPEDIT_ERROR)
        return TCPEDIT_ERROR;

    /* copy the subdecoder state to our encoder state */
    if (tcpedit_dlt_copy_decoder_state(ctx, config->subctx) == TCPEDIT_ERROR)
        return TCPEDIT_ERROR;

    return TCPEDIT_OK;
}
Esempio n. 10
0
/**
 * returns the protocol of the actual layer4 header by processing through
 * the extension headers
 */
uint8_t 
get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int len)
{
    u_char *ptr = (u_char *)ip6_hdr + TCPR_IPV6_H; /* jump to the end of the IPv6 header */
    uint8_t proto;
    struct tcpr_ipv6_ext_hdr_base *exthdr = NULL;

    proto = ip6_hdr->ip_nh;
    assert(ip6_hdr);

    while (TRUE) {
        dbgx(3, "Processing next proto 0x%02X", proto);
        switch (proto) {
            /* no further processing for IPV6 types with nothing beyond them */
            case TCPR_IPV6_NH_FRAGMENT:
            case TCPR_IPV6_NH_ESP:
                dbg(3, "No-Next or ESP... can't go any further...");
                return proto;
                break;

            /* recurse */
            case TCPR_IPV6_NH_IPV6:
                dbg(3, "Recursing due to v6 in v6");
                return get_ipv6_l4proto((ipv6_hdr_t *)ptr, len);
                break;

            /* loop again */
            case TCPR_IPV6_NH_AH:
            case TCPR_IPV6_NH_ROUTING:
            case TCPR_IPV6_NH_DESTOPTS:
            case TCPR_IPV6_NH_HBH:
                dbgx(3, "Jumping to next extension header (0x%hhx)", proto);
                exthdr = get_ipv6_next((struct tcpr_ipv6_ext_hdr_base *)ptr, len);
                proto = exthdr->ip_nh;
                ptr = (u_char *)exthdr;
                break;

            /* should be TCP, UDP or the like */
            default:
                dbgx(3, "Selecting next L4 Proto as: 0x%02x", proto);
                return proto;
        } /* switch */
    } /* while */
}
Esempio n. 11
0
static void
add_tree_node(tcpr_tree_t *newnode)
{
    tcpr_tree_t *node;

    /* try to find a simular entry in the tree */
    node = RB_FIND(tcpr_data_tree_s, &treeroot, newnode);

    dbgx(3, "%s", tree_printnode("add_tree", node));

    /* new entry required */
    if (node == NULL) {
        /* increment counters */
        if (newnode->type == DIR_SERVER) {
            newnode->server_cnt++;
        }
        else if (newnode->type == DIR_CLIENT) {
            newnode->client_cnt++;
        }
        /* insert it in */
        RB_INSERT(tcpr_data_tree_s, &treeroot, newnode);

    }
    else {
        /* we found something, so update it */
        dbgx(2, "   node: %p\nnewnode: %p", node, newnode);
        dbgx(3, "%s", tree_printnode("update node", node));
        /* increment counter */
        if (newnode->type == DIR_SERVER) {
            node->server_cnt++;
        }
        else if (newnode->type == DIR_CLIENT) {
            /* temp debug code */
            node->client_cnt++;
        }
                    
        /* didn't insert it, so free it */
        safe_free(newnode);
    }

    dbg(2, "------- START NEXT -------");
    dbgx(3, "%s", tree_print(&treeroot));
}
Esempio n. 12
0
/**
 * copy the string of args (*opt) to the vector (**opt_vec)
 * for a max of opt_len.  Returns the number of options
 * in the vector
 */
static int
tcpdump_fill_in_options(char *opt)
{
    char options[256];
    char *arg, *newarg;
    int i = 1, arglen;
    char *token = NULL;

    /* zero out our options_vec for execv() */
    memset(options_vec, '\0', sizeof(options_vec));
    
    /* first arg should be the binary (by convention) */
    options_vec[0] = TCPDUMP_BINARY;
       

    /* prep args */
    memset(options, '\0', 256);
    if (opt != NULL) {
        strlcat(options, opt, sizeof(options));
    }
    strlcat(options, TCPDUMP_ARGS, sizeof(options));
    dbgx(2, "[child] Will execute: tcpdump %s", options);


    /* process args */
    
    /* process the first argument */
    arg = strtok_r(options, OPT_DELIM, &token);
    arglen = strlen(arg) + 2; /* -{arg}\0 */
    newarg = (char *)safe_malloc(arglen);
    strlcat(newarg, "-", arglen); 
    strlcat(newarg, arg, arglen);
    options_vec[i++] = newarg;

    /* process the remaining args 
     * note that i < OPTIONS_VEC_SIZE - 1
     * because: a) we need to add '-' as an option to the end
     * b) because the array has to be null terminated
     */
    while (((arg = strtok_r(NULL, OPT_DELIM, &token)) != NULL) &&
           (i < OPTIONS_VEC_SIZE - 1)) {

        arglen = strlen(arg) + 2;
        newarg = (char *)safe_malloc(arglen);
        strlcat(newarg, "-", arglen);
        strlcat(newarg, arg, arglen);
        options_vec[i++] = newarg;

    }

    /* tell -r to read from stdin */
    options_vec[i] = "-";

    return i;
}
Esempio n. 13
0
/**
 * Put data in TX ring buffer and rotate it if necessary
 */
int
txring_put(txring_t *txp, const void * data, size_t length)
{
    struct tpacket_hdr *ps_header;
    char * to_data;
    int loop = 1;
    int first_loop = 1;
    unsigned int start_index = txp->tx_index;

    do {
        ps_header = ((struct tpacket_hdr *)((void *)txp->tx_head + 
                    (txp->treq->tp_frame_size * txp->tx_index)));
        to_data = ((void*) ps_header) + tdata_offset;

        switch ((volatile uint32_t)ps_header->tp_status) {
            case TP_STATUS_WRONG_FORMAT:
                warnx("TP_STATUS_WRONG_FORMAT occuries O_o. Frame %d, pkt len %d\n", 
                        txp->tx_index, length);
                break;

            case TP_STATUS_AVAILABLE:
                if (length > txp->treq->tp_frame_size) {
                    //TODO Fragment packet
                    warnx("[!] %d bytes from %d packet truncated\n",
                            length-txp->treq->tp_frame_size, length);
                    length = txp->treq->tp_frame_size;
                }
                memcpy(to_data, data, length);
                ps_header->tp_len = length;
                ps_header->tp_status = TP_STATUS_SEND_REQUEST;
                loop = 0;
                break;

            default:
                dbgx(2,"TPACKET status %u at frame %d with length %d\n",
                        ps_header->tp_status, txp->tx_index, ps_header->tp_len);
                usleep(0);
                break;
        }
        txp->tx_index++;

        if (txp->tx_index >= txp->treq->tp_frame_nr) {
            txp->tx_index = 0;
            first_loop = 0;
        }

        /* check if we've ran over all ring */
        if ((txp->tx_index == start_index) && !first_loop) {
            errno = ENOBUFS;
            return -1;
        }
    } while(loop == 1);

    return ps_header->tp_len;
}
Esempio n. 14
0
/**
 * Main entry point to bridging.  Does some initial setup and then calls the 
 * correct loop (unidirectional or bidirectional)
 */
void
do_bridge(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
{
    /* do we apply a bpf filter? */
    if (options->bpf.filter != NULL) {
        /* compile filter */
        dbgx(2, "Try to compile pcap bpf filter: %s", options->bpf.filter);
        if (pcap_compile(options->pcap1, &options->bpf.program, options->bpf.filter, options->bpf.optimize, 0) != 0) {
            errx(-1, "Error compiling BPF filter: %s", pcap_geterr(options->pcap1));
        }

        /* apply filter */
        pcap_setfilter(options->pcap1, &options->bpf.program);

        /* same for other interface if applicable */
        if (options->unidir == 0) {
            /* compile filter */
            dbgx(2, "Try to compile pcap bpf filter: %s", options->bpf.filter);
            if (pcap_compile(options->pcap2, &options->bpf.program, options->bpf.filter, options->bpf.optimize, 0) != 0) {
                errx(-1, "Error compiling BPF filter: %s", pcap_geterr(options->pcap2));
            }

            /* apply filter */
            pcap_setfilter(options->pcap2, &options->bpf.program);
        }
    }

    /* register signals */
    didsig = 0;
    (void)signal(SIGINT, signal_catcher);


    if (options->unidir == 1) {
        do_bridge_unidirectional(options, tcpedit);
    } else {
        do_bridge_bidirectional(options, tcpedit);
    }

    if (gettimeofday(&stats.end_time, NULL) < 0)
        errx(-1, "gettimeofday() failed: %s",  strerror(errno));
    packet_stats(&stats);
}
Esempio n. 15
0
/**
 * Method takes an open "/dev/netmap" file descriptor and returns
 * the netmap version.
 *
 * Returns -1 on error
 */
int
get_netmap_version()
{
    u_int32_t netmap_version = -1;
    nmreq_t nmr;
    int fd;

    if ((fd = open ("/dev/netmap", O_RDWR)) < 0)
        return -1;

    /* netmap version discovery */
    bzero (&nmr, sizeof(nmr));
    nmr.nr_version = NETMAP_API;

    /* attempt using the netmap API version that this was compiled under */
    if(ioctl(fd, NIOCGINFO, &nmr) == 0) {
        netmap_version = nmr.nr_version;
        dbgx(1, "netmap detected API version %d which matches compiled version\n",
                netmap_version);
    } else {
        /* failed.
         *
         * Try other versions in an attempt to find the version
         * that matches this system.
         */
        int x;
        for (x = 0; x < 50; ++x) {
            bzero (&nmr, sizeof(nmr));
            nmr.nr_version = x;
            if(ioctl(fd, NIOCGINFO, &nmr) == 0) {
                netmap_version = nmr.nr_version;
                dbgx(1, "netmap detected API version %d which doesn't match compiled version %d\n",
                        netmap_version, NETMAP_API);
                break;
            }
        }
    }

    close(fd);

    return netmap_version;
}
Esempio n. 16
0
/**
 * Figures out if a MAC is listed in a comma delimited
 * string of MAC addresses.
 * returns TCPR_DIR_C2S if listed
 * returns TCPR_DIR_S2C if not listed
 */
tcpr_dir_t
macinstring(const char *macstring, const u_char *mac)
{
    char *tok, *tempstr, *ourstring;
    u_char tempmac[6];
    int len = 6, ret = TCPR_DIR_S2C;
    
    ourstring = safe_strdup(macstring);
    
    tempstr = strtok_r(ourstring, ",", &tok);
    if (strlen(tempstr)) {
       mac2hex(tempstr, tempmac, len);
       if (memcmp(mac, tempmac, len) == 0) {
           dbgx(3, "Packet matches: " MAC_FORMAT " sending out primary.\n", MAC_STR(tempmac));
           ret = TCPR_DIR_C2S;
           goto EXIT_MACINSTRING;
       }
    } else {
        goto EXIT_MACINSTRING;
    }

    while ((tempstr = strtok_r(NULL, ",", &tok)) != NULL) {
       mac2hex(tempstr, tempmac, len);
       if (memcmp(mac, tempmac, len) == 0) {
           ret = TCPR_DIR_C2S;
           dbgx(3, "Packet matches: " MAC_FORMAT " sending out primary.\n", MAC_STR(tempmac));
           goto EXIT_MACINSTRING;
       }
    }

EXIT_MACINSTRING:
    safe_free(ourstring);
#ifdef DEBUG
    if (ret == TCPR_DIR_S2C)
       dbg(3, "Packet doesn't match any MAC addresses sending out secondary.\n");
#endif
    return ret;
}
Esempio n. 17
0
/*
 * Function returns a pointer to the layer 3 protocol header or NULL on error
 */
u_char *
dlt_ieee80211_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen)
{
    int l2len;
    assert(ctx);
    assert(packet);

    l2len = dlt_ieee80211_l2len(ctx, packet, pktlen);

    assert(pktlen >= l2len);
    dbgx(1, "Getting data for packet " COUNTER_SPEC " from offset: %d", ctx->tcpedit->runtime.packetnum, l2len);
    
    return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len);
}
Esempio n. 18
0
/**
 * processes the tree using rbwalk / tree2cidr to generate a CIDR
 * used for 2nd pass, router mode
 *
 * returns > 0 for success (the mask len), 0 for fail
 */
int
process_tree(void)
{
    int mymask = 0;
    tcpr_buildcidr_t *bcdata;
    tcpprep_opt_t *options = tcpprep->options;


    dbg(1, "Running: process_tree()");

    bcdata = (tcpr_buildcidr_t *)safe_malloc(sizeof(tcpr_buildcidr_t));

    for (mymask = options->max_mask; mymask <= options->min_mask; mymask++) {
        dbgx(1, "Current mask: %u", mymask);

        /* set starting vals */
        bcdata->type = DIR_SERVER;
        bcdata->masklen = mymask;

        /* build cidrdata with servers */
        tree_buildcidr(&treeroot, bcdata);

        /* calculate types of all IP's */
        tree_calculate(&treeroot);

        /* try to find clients in cidrdata */
        bcdata->type = DIR_CLIENT;

        if (! tree_checkincidr(&treeroot, bcdata)) { /* didn't find any clients in cidrdata */
            safe_free(bcdata);
            return (mymask);    /* success! */
        }
        else {
            destroy_cidr(options->cidrdata); /* clean up after our mess */
            options->cidrdata = NULL;
        }
    }

    safe_free(bcdata);
    /* we failed to find a valid cidr list */
    notice("Unable to determine any IP addresses as a clients.");
    notice("Perhaps you should change the --ratio, --minmask/maxmask settings, or try another mode?");
    return (0);
}
Esempio n. 19
0
/**
 * adds an entry to the tree (phase 1 of auto mode).  We add each host
 * to the tree if it doesn't yet exist.  We go through and track:
 * - number of times each host acts as a client or server
 * - the way the host acted the first time we saw it (client or server)
 */
void
add_tree_ipv4(const unsigned long ip, const u_char * data)
{
    tcpr_tree_t *newnode = NULL;
    assert(data);

    newnode = packet2tree(data);

    assert(ip == newnode->u.ip);

    if (newnode->type == DIR_UNKNOWN) {
        /* couldn't figure out if packet was client or server */

        dbgx(2, "%s (%lu) unknown client/server",
            get_addr2name4(newnode->u.ip, RESOLVE), newnode->u.ip);

    }
    add_tree_node(newnode);
}
Esempio n. 20
0
void
add_tree_ipv6(const struct tcpr_in6_addr * addr, const u_char * data)
{
    tcpr_tree_t *newnode = NULL;
    assert(data);

    newnode = packet2tree(data);

    assert(ipv6_cmp(addr, &newnode->u.ip6) == 0);

    if (newnode->type == DIR_UNKNOWN) {
        /* couldn't figure out if packet was client or server */

        dbgx(2, "%s unknown client/server",
            get_addr2name6(&newnode->u.ip6, RESOLVE));
    }

    add_tree_node(newnode);
}
Esempio n. 21
0
/**
 * shutdown tcpdump 
 */
void
tcpdump_close(tcpdump_t *tcpdump)
{
    if (! tcpdump)
        return;

    if (tcpdump->pid <= 0)
        return;

    dbgx(2, "[parent] killing tcpdump pid: %d", tcpdump->pid);

    kill(tcpdump->pid, SIGKILL);
    close(PARENT_READ_FD);
    close(PARENT_WRITE_FD);

    if (waitpid(tcpdump->pid, NULL, 0) != tcpdump->pid)
        errx(-1, "[parent] Error in waitpid: %s", strerror(errno));

    tcpdump->pid = 0;
    PARENT_READ_FD = 0;
    PARENT_WRITE_FD = 0;
}
Esempio n. 22
0
static sendpacket_t *
sendpacket_open_quick_tx(const char *device, char *errbuf)
{
    sendpacket_t *sp;
    struct quick_tx* dev;
    const char *ifname;
    char full_dev_name[256];
    unsigned int map_size = QTX_MASTER_PAGE_NUM * PAGE_SIZE;
    unsigned int *map;
    int blocks;
    int i, fd;

    assert(device);
    assert(errbuf);

    if (strlen(device) > MAX_IFNAMELEN - 8) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto ifacename_invalid;
    }

    /*
     * Sort out interface names
     */
    if (!strncmp(device, "qtx:", 4))
        ifname = &device[4];
    else
        ifname = device;

    /* open device name */
    snprintf(full_dev_name, sizeof(full_dev_name), "%s%s", QTX_FULL_PATH_PREFIX, ifname);
    if ((fd = open(full_dev_name, O_RDWR | O_SYNC)) < 0) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while opening device\n"
                "Check that the QuickTX module is loaded and the interface name is correct \n");
        goto open_failed;
    }

    /* create a memory map to Quick TX kernel module */
    map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while attempting to map memory from device");
        goto map_create_failed;
    }

    /* create device */
    dev = safe_malloc(sizeof(struct quick_tx));
    dev->map_length = map_size;
    dev->fd = fd;
    dev->data = (struct quick_tx_shared_data*)map;
    dev->stop_auto_mapping = false;

    if (quick_tx_mmap_mem_block(dev) < 0) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while mapping block");
        goto map_failed;
    }

    if ((blocks = quick_tx_alloc_mem_space(dev, QTX_QUEUE_SIZE)) < 0) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while allocating memory");
        goto map_alloc_failed;
    }

    dbgx(1, "[quick_tx] mapped %d blocks of memory\n", blocks);

    /* store results */
    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));
    strncpy(sp->device, full_dev_name, sizeof(sp->device));
    sp->handle.fd = fd;
    sp->qtx_dev = dev;
    sp->handle_type = SP_TYPE_QUICK_TX;

    return sp;

map_alloc_failed:
    for (i = (dev->data->num_mem_blocks - 1); i >= 0; i--) {
        struct quick_tx_mem_block_entry* mem_block = &dev->data->mem_blocks[i];
        if (munmap (mem_block->user_addr, mem_block->length) == -1) {
            dbgx(1, "[quick_tx] error while calling munmap for block %d\n", i);
        }
    }

    munmap ((void*)dev->data, dev->map_length);
map_failed:
    free(dev);
map_create_failed:
    close(fd);
open_failed:
ifacename_invalid:
    return NULL;
}
Esempio n. 23
0
/**
 * ioctl support for netmap
 */
static int nm_do_ioctl (sendpacket_t *sp, u_long what, int subcmd) {
    struct ifreq ifr;
    int error;
    int fd;
#ifdef linux
    struct ethtool_value eval;
#endif

    assert(sp);

    fd = socket (AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        dbg(1, "ioctl error: cannot get device control socket.\n");
        return -1;
    }

    bzero (&ifr, sizeof(ifr));
    strncpy (ifr.ifr_name, sp->device, sizeof(ifr.ifr_name));

    switch (what) {
    case SIOCSIFFLAGS:
        ifr.ifr_flags = sp->if_flags >> 16;
        ifr.ifr_flags = sp->if_flags & 0xffff;
        break;

#ifdef linux
    case SIOCETHTOOL:
        eval.cmd = subcmd;
        eval.data = sp->data;
        ifr.ifr_data = (caddr_t)&eval;
        dbgx(1, "ioctl SIOCETHTOOL subcmd=%d data=%u", subcmd, eval.data);
        break;
#endif
    }

    error = ioctl (fd, what, &ifr);
    if (error)
        goto done;

    switch (what) {
    case SIOCGIFFLAGS:
        sp->if_flags = (ifr.ifr_flags << 16) | (0xffff & ifr.ifr_flags);
        dbgx(1, "SIOCGIFFLAGS flags are 0x%x", sp->if_flags);
        break;

#ifdef linux
    case SIOCETHTOOL:
        switch (subcmd) {
        case ETHTOOL_GGSO:
            sp->gso = eval.data;
            dbgx(1, "ioctl SIOCETHTOOL ETHTOOL_GGSO=%u", eval.data);
            break;

        case ETHTOOL_GTSO:
            sp->tso = eval.data;
            dbgx(1, "ioctl SIOCETHTOOL ETHTOOL_GTSO=%u", eval.data);
            break;

        case ETHTOOL_GRXCSUM:
            sp->rxcsum = eval.data;
            dbgx(1, "ioctl SIOCETHTOOL ETHTOOL_GRXCSUM=%u", eval.data);
            break;

        case ETHTOOL_GTXCSUM:
            sp->txcsum = eval.data;
            dbgx(1, "ioctl SIOCETHTOOL ETHTOOL_GTXCSUM=%u", eval.data);
            break;
        }
        break;
#endif

    }

done:
    close (fd);

    if (error)
        warnx("ioctl error %d %lu:%d", error, what, subcmd);
    return error;
}
Esempio n. 24
0
int sendpacket_send_netmap(void *p, const u_char *data, size_t len)
{
    sendpacket_t *sp = p;
    struct netmap_ring *txring;
    struct netmap_slot *slot;
    char *pkt;
    uint32_t cur, avail;

    if (sp->abort)
        return 0;

    txring = NETMAP_TXRING(sp->nm_if, sp->cur_tx_ring);
    while ((avail = nm_ring_space(txring)) == 0) {
        /* out of space on current TX queue - go to next */
        ++sp->cur_tx_ring;
        if (sp->cur_tx_ring > sp->last_tx_ring) {
            /*
             * out of space on all queues
             *
             * we have looped through all configured TX queues
             * so we have to reset to the first queue and
             * wait for available space
             */
            sp->cur_tx_ring = sp->first_tx_ring;

            /* send TX interrupt signal
             *
             * On Linux this makes one slot free on the
             * ring, which increases speed by about 10Mbps.
             *
             * But it will never free up all the slots. For
             * that we must poll and call again.
             */
            ioctl(sp->handle.fd, NIOCTXSYNC, NULL);

            /* loop again */
            return -2;
        }

        txring = NETMAP_TXRING(sp->nm_if, sp->cur_tx_ring);
    }

    /*
     * send
     */
    cur = txring->cur;
    slot = &txring->slot[cur];
    slot->flags = 0;
    pkt = NETMAP_BUF(txring, slot->buf_idx);
    memcpy(pkt, data, min(len, txring->nr_buf_size));
    slot->len = len;

    if (avail <= 1)
        slot->flags = NS_REPORT;

    dbgx(3, "netmap cur=%d slot index=%d flags=0x%x empty=%d avail=%u bufsize=%d\n",
            cur, slot->buf_idx, slot->flags, NETMAP_TX_RING_EMPTY(txring),
            nm_ring_space(txring), txring->nr_buf_size);

    /* let kernel know that packet is available */
    cur = NETMAP_RING_NEXT(txring, cur);
#ifdef HAVE_NETMAP_RING_HEAD_TAIL
    txring->head = cur;
#else
    txring->avail--;
#endif
    txring->cur = cur;

    return len;
}
Esempio n. 25
0
/**
 * Inner sendpacket_open() method for using netmap
 */
void *
sendpacket_open_netmap(const char *device, char *errbuf, void *arg) {
    tcpreplay_t *ctx = (tcpreplay_t*)arg;
    sendpacket_t *sp = NULL;
    nmreq_t nmr;
    char ifname_buf[MAX_IFNAMELEN];
    const char *ifname;
    const char *port = NULL;
    size_t namelen;
    u_int32_t nr_ringid = 0;
    u_int32_t nr_flags = NR_REG_DEFAULT;
    int is_default = 0;

    assert(device);
    assert(errbuf);

    dbg(1, "sendpacket_open_netmap: using netmap");

    bzero(&nmr, sizeof(nmr));

    /* prep & return our sp handle */
    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));

    if (strlen(device) > MAX_IFNAMELEN - 8) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto IFACENAME_INVALID;
    }

    /* get the version of the netmap driver. If < 0, driver is not installed */
    sp->netmap_version = get_netmap_version();
    if (sp->netmap_version < 0) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to determine the running netmap version.\n"
                "See INSTALL document for details on installing or upgrading netmap.");
        goto NETMAP_NOT_INSTALLED;
    }

    /*
     * Sort out interface names
     *
     * ifname   (foo, netmap:foo or vale:foo) is the port name
     *      foo         bind to a single NIC hardware queue
     *      netmap:foo  bind to a single NIC hardware queue
     *      vale:foo    bind to the Vale virtual interface
     *
     * for netmap version 10+ a suffix can indicate the following:
     *      netmap:foo!     bind to all NIC hardware queues (may cause TX reordering)
     *      netmap:foo^     bind to the host (sw) ring pair
     *      netmap:foo*     bind to the host (sw) and NIC ring pairs (transparent)
     *      netmap:foo-NN   bind to the individual NIC ring pair (queue) where NN = the ring number
     *      netmap:foo{NN   bind to the master side of pipe NN
     *      netmap:foo}NN   bind to the slave side of pipe NN
     */
    if (strncmp(device, "netmap:", 7) && strncmp(device, "vale", 4)) {
        snprintf(ifname_buf, sizeof(ifname_buf), "netmap:%s", device);
        ifname = ifname_buf;
    } else {
        ifname = device;
    }

    if (!strncmp("vale", device, 4))
        sp->is_vale = 1;

    if (ifname[0] == 'n')
        ifname += 7;

    /* scan for a separator */
    for (port = ifname; *port && !index("!-*^{}", *port); port++)
        ;

    namelen = port - ifname;
    if (namelen > sizeof(nmr.nr_name)) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto IFACENAME_INVALID;
    }
    /*
     * Open the netmap device to fetch the number of queues of our
     * interface.
     *
     * The first NIOCREGIF also detaches the card from the
     * protocol stack and may cause a reset of the card,
     * which in turn may take some time for the PHY to
     * reconfigure.
     */
    if ((sp->handle.fd = open("/dev/netmap", O_RDWR)) < 0) {
        dbg(1, "sendpacket_open_netmap: Unable to access netmap");
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to access netmap.\n"
                "See INSTALL to learn which NICs are supported and\n"
                "how to set up netmap-capable network drivers.");
        goto OPEN_FAILED;
    }

    /*
     * The nmreq structure must have the NETMAP_API version for the running machine.
     * However the binary may have been compiled on a different machine than the
     * running machine. Discover the true netmap API version, and be careful to call
     * fuctions that are available on all netmap versions.
     */
    if (sp->netmap_version >= 10) {
        switch (*port) {
        case '-': /* one NIC */
            nr_flags = NR_REG_ONE_NIC;
            nr_ringid = atoi(port + 1);
            break;

        case '*': /* NIC and SW, ignore port */
            nr_flags = NR_REG_NIC_SW;
            if (port[1]) {
                snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid netmap port for nic+sw");
                goto NETMAP_IF_PARSE_FAIL;
            }
            break;

        case '^': /* only sw ring */
            nr_flags = NR_REG_SW;
            if (port[1]) {
                snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid port for sw ring");
                goto NETMAP_IF_PARSE_FAIL;
            }
            break;

        case '{':
            nr_flags = NR_REG_PIPE_MASTER;
            nr_ringid = atoi(port + 1);
            break;

        case '}':
            nr_flags = NR_REG_PIPE_SLAVE;
            nr_ringid = atoi(port + 1);
            break;

        case '!':
            nr_flags = NR_REG_ALL_NIC;
            break;

        default:  /* '\0', no suffix */
            nr_flags = NR_REG_ALL_NIC;
            is_default = 1;
            break;
        }

        if (nr_ringid >= NETMAP_RING_MASK) {
            snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid ringid");
            goto NETMAP_IF_PARSE_FAIL;
        }

        nmr.nr_ringid = nr_ringid;
        nmr.nr_flags = nr_flags;
    }

    nmr.nr_version = sp->netmap_version;
    memcpy(nmr.nr_name, ifname, namelen);
    nmr.nr_name[namelen] = '\0';
    strlcpy(sp->device, nmr.nr_name, sizeof(sp->device));

    /*
     * Register the interface on the netmap device: from now on,
     * we can operate on the network interface without any
     * interference from the legacy network stack.
     *
     * Cards take a long time to reset the PHY.
     */
    fprintf(stderr, "Switching network driver for %s to netmap bypass mode... ",
            sp->device);
    fflush(NULL);
    sleep(1);   /* ensure message prints when user is connected via ssh */

    if (ioctl (sp->handle.fd, NIOCREGIF, &nmr)) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Failure accessing netmap.\n"
                "\tRequest for netmap version %u failed.\n\tCompiled netmap driver is version %u.\n\tError=%s\n",
                sp->netmap_version, NETMAP_API, strerror(errno));
        goto NETMAP_IF_FAILED;
    }

    if (!nmr.nr_memsize) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Netmap interface '%s' not configured.\n",
                device);
        goto NETMAP_IF_FAILED;
    }

    sp->mmap_size = nmr.nr_memsize;
    sp->mmap_addr = (struct netmap_d *)mmap (0, sp->mmap_size,
            PROT_WRITE | PROT_READ, MAP_SHARED, sp->handle.fd, 0);

    if (!sp->mmap_addr || sp->mmap_addr == MAP_FAILED) {
        snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "mmap: %s", strerror (errno));
        goto MMAP_FAILED;
    }

    dbgx(1, "sendpacket_open_netmap: mapping %d Kbytes queues=%d",
            sp->mmap_size >> 10, nmr.nr_tx_rings);

    sp->nm_if = NETMAP_IF(sp->mmap_addr, nmr.nr_offset);
    sp->nmr = nmr;
    sp->handle_type = SP_TYPE_NETMAP;

    /* set up ring IDs */
    sp->cur_tx_ring = 0;
    switch(nr_flags) {
    case NR_REG_DEFAULT:    /* only use one queue to prevent TX reordering */
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
        break;

    case NR_REG_ALL_NIC:
        if (is_default) {
            sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
        } else {
            sp->first_tx_ring = sp->cur_tx_ring = 0;
            sp->last_tx_ring = nmr.nr_tx_rings - 1;
        }
        break;

    case NR_REG_SW:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = nmr.nr_tx_rings;
        break;

    case NR_REG_NIC_SW:
        sp->first_tx_ring = sp->cur_tx_ring = 0;
        sp->last_tx_ring = nmr.nr_tx_rings;
        break;

    case NR_REG_ONE_NIC:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = nr_ringid;
        break;

    default:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
    }
    {
        /* debugging code */
        int i;

        dbgx(1, "%s tx first=%d last=%d  num=%d", ifname,
                sp->first_tx_ring, sp->last_tx_ring, sp->nmr.nr_tx_rings);
        for (i = 0; i <= sp->nmr.nr_tx_rings; i++) {
#ifdef HAVE_NETMAP_RING_HEAD_TAIL
            dbgx(1, "TX%d 0x%p head=%d cur=%d tail=%d", i, NETMAP_TXRING(sp->nm_if, i),
                    (NETMAP_TXRING(sp->nm_if, i))->head,
                    (NETMAP_TXRING(sp->nm_if, i))->cur, (NETMAP_TXRING(sp->nm_if, i))->tail);
#else
            dbgx(1, "TX%d 0x%p cur=%d avail=%d", i, NETMAP_TXRING(sp->nm_if, i),
                    (NETMAP_TXRING(sp->nm_if, i))->cur, (NETMAP_TXRING(sp->nm_if, i))->avail);
#endif
        }
    }

    dbgx(2, "Waiting %d seconds for phy reset...", ctx->options->netmap_delay);
    sleep(ctx->options->netmap_delay);
    dbg(2, "Ready!");

    if (!sp->is_vale) {
        if (nm_do_ioctl(sp, SIOCGIFFLAGS, 0) < 0)
            goto NM_DO_IOCTL_FAILED;

        if ((sp->if_flags & IFF_RUNNING) == 0) {
            dbgx(1, "sendpacket_open_netmap: %s is not running", sp->device);
            snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "interface %s is not running - check cables\n", sp->device);
            goto NETMAP_IF_NOT_RUNNING;
        }

        if ((sp->if_flags & IFF_UP) == 0) {
            dbgx(1, "%s is down, bringing up...", sp->device);
            sp->if_flags |= IFF_UP;
        }

        /* set promiscuous mode */
        sp->if_flags |= IFF_PROMISC;
        if (nm_do_ioctl(sp, SIOCSIFFLAGS, 0) < 0)
            goto NM_DO_IOCTL_FAILED;

#ifdef linux
        /* disable:
         * - generic-segmentation-offload
         * - tcp-segmentation-offload
         * - rx-checksumming
         * - tx-checksumming
         */
        if (nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GGSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GTSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GRXCSUM) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GTXCSUM) < 0)
            goto NM_DO_IOCTL_FAILED;

        sp->data = 0;
        if (nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SGSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SRXCSUM) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STXCSUM))
            goto NM_DO_IOCTL_FAILED;
#endif
    }

    if(sp->abort)
        goto NETMAP_ABORT;

    notice("done!");

    return sp;

NM_DO_IOCTL_FAILED:
    snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "nm_do_ioctl: %s", strerror (errno));
NETMAP_IF_NOT_RUNNING:
    notice("failed!");
NETMAP_ABORT:
    fprintf(stderr, " Switching network driver for %s to normal mode... ",
            sp->device);
    fflush(NULL);
    munmap(sp->mmap_addr, sp->mmap_size);
MMAP_FAILED:
#if NETMAP_API < 10
    ioctl(sp->handle.fd, NIOCUNREGIF, NULL);
#endif
NETMAP_IF_FAILED:
NETMAP_IF_PARSE_FAIL:
    close (sp->handle.fd);
OPEN_FAILED:
    safe_free(sp);
IFACENAME_INVALID:
NETMAP_NOT_INSTALLED:

    return NULL;
}
Esempio n. 26
0
/**
 * returns the include_exclude_mode on success placing the CIDR or LIST in mybuf
 * but on failure, returns xXError
 */
int
parse_xX_str(tcpr_xX_t *xX, char *str, tcpr_bpf_t *bpf)
{
    int out = 0;

    dbgx(1, "Parsing string: %s", str);
    dbgx(1, "Switching on: %c", str[0]);

    switch (str[0]) {
    case 'B':                  /* both ip's */
        str = str + 2;
        out = xXBoth;
        if (!parse_cidr(&(xX->cidr), str, ","))
            return xXError;
        break;

    case 'D':                  /* dst ip */
        str = str + 2;
        out = xXDest;
        if (!parse_cidr(&(xX->cidr), str, ","))
            return xXError;
        break;

    case 'E':                  /* either ip */
        str = str + 2;
        out = xXEither;
        if (!parse_cidr(&(xX->cidr), str, ","))
            return xXError;
        break;
        
    case 'F':                  /* bpf filter */
        str = str + 2;
        out = xXBPF;
        bpf->filter = safe_strdup(str);
        /* 
         * note: it's temping to compile the BPF here, but we don't
         * yet know what the link type is for the file, so we have 
         * to compile the BPF once we open the pcap file
         */
        break;
        
    case 'P':                  /* packet id */
        str = str + 2;
        out = xXPacket;
        if (!parse_list(&(xX->list), str))
            return xXError;
        break;

    case 'S':                  /* source ip */
        str = str + 2;
        out = xXSource;
        if (!parse_cidr(&(xX->cidr), str, ","))
            return xXError;
        break;

    default:
        errx(-1, "Invalid -%c option: %c", xX->mode, *str);
        break;
    }

    if (xX->mode == 'X') {          /* run in exclude mode */
        out += xXExclude;
        if (bpf->filter != NULL)
            err(-1, "Using a BPF filter with -X doesn't work.\n"
                "Try using -xF:\"not <filter>\" instead");
    }

    xX->mode = out;
    return xX->mode;
}
Esempio n. 27
0
int 
main(int argc, char *argv[])
{
    int optct, rcode;
    pcap_t *dlt_pcap;
#ifdef ENABLE_FRAGROUTE
    char ebuf[FRAGROUTE_ERRBUF_LEN];
#endif
    tcprewrite_init();

    /* call autoopts to process arguments */
    optct = optionProcess(&tcprewriteOptions, argc, argv);
    argc -= optct;
    argv += optct;

    /* parse the tcprewrite args */
    post_args(argc, argv);

    /* init tcpedit context */
    if (tcpedit_init(&tcpedit, pcap_datalink(options.pin)) < 0) {
        errx(-1, "Error initializing tcpedit: %s", tcpedit_geterr(tcpedit));
    }

    /* parse the tcpedit args */
    rcode = tcpedit_post_args(&tcpedit);
    if (rcode < 0) {
        errx(-1, "Unable to parse args: %s", tcpedit_geterr(tcpedit));
    } else if (rcode == 1) {
        warnx("%s", tcpedit_geterr(tcpedit));
    }


    if (tcpedit_validate(tcpedit) < 0) {
        errx(-1, "Unable to edit packets given options:\n%s",
                tcpedit_geterr(tcpedit));
    }

   /* open up the output file */
    options.outfile = safe_strdup(OPT_ARG(OUTFILE));
    dbgx(1, "Rewriting DLT to %s",
            pcap_datalink_val_to_name(tcpedit_get_output_dlt(tcpedit)));
    if ((dlt_pcap = pcap_open_dead(tcpedit_get_output_dlt(tcpedit), 65535)) == NULL)
        err(-1, "Unable to open dead pcap handle.");

    dbgx(1, "DLT of dlt_pcap is %s",
        pcap_datalink_val_to_name(pcap_datalink(dlt_pcap)));

#ifdef ENABLE_FRAGROUTE
    if (options.fragroute_args) {
        if ((options.frag_ctx = fragroute_init(65535, pcap_datalink(dlt_pcap), options.fragroute_args, ebuf)) == NULL)
            errx(-1, "%s", ebuf);
    }
#endif

#ifdef ENABLE_VERBOSE
    if (options.verbose) {
        tcpdump_open(&tcpdump, dlt_pcap);
    }
#endif

    if ((options.pout = pcap_dump_open(dlt_pcap, options.outfile)) == NULL)
        errx(-1, "Unable to open output pcap file: %s", pcap_geterr(dlt_pcap));
    pcap_close(dlt_pcap);

    /* rewrite packets */
    if (rewrite_packets(tcpedit, options.pin, options.pout) != 0)
        errx(-1, "Error rewriting packets: %s", tcpedit_geterr(tcpedit));


    /* clean up after ourselves */
    pcap_dump_close(options.pout);
    pcap_close(options.pin);

#ifdef ENABLE_VERBOSE
    tcpdump_close(&tcpdump);
#endif

#ifdef ENABLE_DMALLOC
    dmalloc_shutdown();
#endif
    return 0;
}
Esempio n. 28
0
/** 
 * Main loop to rewrite packets
 */
int
rewrite_packets(tcpedit_t *tcpedit, pcap_t *pin, pcap_dumper_t *pout)
{
    tcpr_dir_t cache_result = TCPR_DIR_C2S;     /* default to primary */
    struct pcap_pkthdr pkthdr, *pkthdr_ptr;     /* packet header */
    const u_char *pktconst = NULL;              /* packet from libpcap */
    u_char **pktdata = NULL;
    static u_char *pktdata_buff;
    static char *frag = NULL;
    COUNTER packetnum = 0;
    int rcode, frag_len, i, proto;

    pkthdr_ptr = &pkthdr;

    if (pktdata_buff == NULL)
        pktdata_buff = (u_char *)safe_malloc(MAXPACKET);

    pktdata = &pktdata_buff;

    if (frag == NULL)
        frag = (char *)safe_malloc(MAXPACKET);

    /* MAIN LOOP 
     * Keep sending while we have packets or until
     * we've sent enough packets
     */
    while ((pktconst = pcap_next(pin, pkthdr_ptr)) != NULL) {
        packetnum++;
        dbgx(2, "packet " COUNTER_SPEC " caplen %d", packetnum, pkthdr.caplen);

        /* 
         * copy over the packet so we can pad it out if necessary and
         * because pcap_next() returns a const ptr
         */
        memcpy(*pktdata, pktconst, pkthdr.caplen);

#ifdef ENABLE_VERBOSE
        if (options.verbose)
            tcpdump_print(&tcpdump, pkthdr_ptr, *pktdata);
#endif

        /* Dual nic processing? */
        if (options.cachedata != NULL) {
            cache_result = check_cache(options.cachedata, packetnum);
        }

        /* sometimes we should not send the packet, in such cases
         * no point in editing this packet at all, just write it to the
         * output file (note, we can't just remove it, or the tcpprep cache
         * file will loose it's indexing
         */

        if (cache_result == TCPR_DIR_NOSEND)
            goto WRITE_PACKET; /* still need to write it so cache stays in sync */

        if ((rcode = tcpedit_packet(tcpedit, &pkthdr_ptr, pktdata, cache_result)) == TCPEDIT_ERROR) {
            return -1;
        } else if ((rcode == TCPEDIT_SOFT_ERROR) && HAVE_OPT(SKIP_SOFT_ERRORS)) {
            /* don't write packet */
            dbgx(1, "Packet " COUNTER_SPEC " is suppressed from being written due to soft errors", packetnum);
            continue;
        }


WRITE_PACKET:
#ifdef ENABLE_FRAGROUTE
        if (options.frag_ctx == NULL) {
            /* write the packet when there's no fragrouting to be done */
            pcap_dump((u_char *)pout, pkthdr_ptr, *pktdata);
        } else {
            /* get the L3 protocol of the packet */
            proto = tcpedit_l3proto(tcpedit, AFTER_PROCESS, *pktdata, pkthdr_ptr->caplen);

            /* packet is IPv4/IPv6 AND needs to be fragmented */
            if ((proto ==  ETHERTYPE_IP || proto == ETHERTYPE_IP6) &&
                ((options.fragroute_dir == FRAGROUTE_DIR_BOTH) ||
                 (cache_result == TCPR_DIR_C2S && options.fragroute_dir == FRAGROUTE_DIR_C2S) ||
                 (cache_result == TCPR_DIR_S2C && options.fragroute_dir == FRAGROUTE_DIR_S2C))) {

                if (fragroute_process(options.frag_ctx, *pktdata, pkthdr_ptr->caplen) < 0)
                    errx(-1, "Error processing packet via fragroute: %s", options.frag_ctx->errbuf);

                i = 0;
                while ((frag_len = fragroute_getfragment(options.frag_ctx, &frag)) > 0) {
                    /* frags get the same timestamp as the original packet */
                    dbgx(1, "processing packet " COUNTER_SPEC " frag: %u (%d)", packetnum, i++, frag_len);
                    pkthdr_ptr->caplen = frag_len;
                    pkthdr_ptr->len = frag_len;
                    pcap_dump((u_char *)pout, pkthdr_ptr, (u_char *)frag);
                }
            } else {
                /* write the packet without fragroute */
                pcap_dump((u_char *)pout, pkthdr_ptr, *pktdata);
            }
        }
#else
    /* write the packet when there's no fragrouting to be done */
    pcap_dump((u_char *)pout, pkthdr_ptr, *pktdata);

#endif
    } /* while() */
    return 0;
}
Esempio n. 29
0
/** 
 * Get all available interfaces as an interface_list *
 */
interface_list_t *
get_interface_list(void)
{
    interface_list_t *list_head, *list_ptr;
    char ebuf[PCAP_ERRBUF_SIZE], testnic[255];
    pcap_if_t *pcap_if, *pcap_if_ptr;
    int i = 0;
    DIR *dir;
    struct dirent *dirdata;
#ifdef HAVE_QUICK_TX
    char buf[MAXNAMLEN];
#endif
#ifdef HAVE_NETMAP
    int fd = -1;
    nmreq_t nmr;
#endif
#if defined HAVE_LIBPCAP_NETMAP || defined HAVE_NETMAP
    u_int32_t netmap_version = -1;
#endif
    
#ifndef HAVE_WIN32
	/* Unix just has a warning about being root */
	if (geteuid() != 0)
		warn("May need to run as root to get access to all network interfaces.");
#endif

#ifdef HAVE_NETMAP
    netmap_version = get_netmap_version();
#endif

    if (pcap_findalldevs(&pcap_if, ebuf) < 0)
        errx(-1, "Error: %s", ebuf);
            
    pcap_if_ptr = pcap_if;
    list_head = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
    list_ptr = list_head;
    
    while (pcap_if_ptr != NULL) {
        if (i > 0) {
            list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
            list_ptr = list_ptr->next;
        }
        strlcpy(list_ptr->name, pcap_if_ptr->name, sizeof(list_ptr->name));
        dbgx(3, "Adding %s to interface list", list_ptr->name);
        
        /* description is usually null under Unix */
        if (pcap_if_ptr->description != NULL)
            strlcpy(list_ptr->description, pcap_if_ptr->description, sizeof(list_ptr->description));
            
        sprintf(list_ptr->alias, "%%%d", i++);
        list_ptr->flags = pcap_if_ptr->flags;
#ifdef HAVE_QUICK_TX
        snprintf(buf, sizeof(buf), "%s%s", QTX_FULL_PATH_PREFIX, pcap_if_ptr->name);
        if (!access(buf, R_OK | W_OK)) {
            list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
            list_ptr = list_ptr->next;
            snprintf(list_ptr->name, sizeof(list_ptr->name), "qtx:%s", pcap_if_ptr->name);
            sprintf(list_ptr->alias, "%%%d", i++);
            list_ptr->flags = pcap_if_ptr->flags;
        }
#endif
#ifdef HAVE_LIBPCAP_NETMAP
        /*
         * add the syntaxes supported by netmap-libpcap
         *
         * available at http://code.google.com/p/netmap-libpcap/
         */
        if (!(pcap_if_ptr->flags & PCAP_IF_LOOPBACK)
                && strcmp("any", pcap_if_ptr->name)) {
#endif
#ifdef HAVE_NETMAP
            if (netmap_version != -1 && (fd = open ("/dev/netmap", O_RDWR)) < 0)
                continue;
            bzero(&nmr, sizeof(nmr));
            strncpy(nmr.nr_name, pcap_if_ptr->name, sizeof(nmr.nr_name));
            nmr.nr_version = netmap_version;
            if (ioctl(fd, NIOCGINFO, &nmr) == 0) {
                int x;

#endif /* HAVE_NETMAP */
#if defined HAVE_LIBPCAP_NETMAP || defined HAVE_NETMAP
                list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                list_ptr = list_ptr->next;
                snprintf(list_ptr->name, sizeof(list_ptr->name), "vale:%s", pcap_if_ptr->name);
                sprintf(list_ptr->alias, "%%%d", i++);
                list_ptr->flags = pcap_if_ptr->flags;

                list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                list_ptr = list_ptr->next;
                snprintf(list_ptr->name, sizeof(list_ptr->name), "netmap:%s", pcap_if_ptr->name);
                sprintf(list_ptr->alias, "%%%d", i++);
                list_ptr->flags = pcap_if_ptr->flags;

                if (netmap_version >= 10) {
                    list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                    list_ptr = list_ptr->next;
                    snprintf(list_ptr->name, sizeof(list_ptr->name), "netmap:%s!", pcap_if_ptr->name);
                    sprintf(list_ptr->alias, "%%%d", i++);
                    list_ptr->flags = pcap_if_ptr->flags;

                    list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                    list_ptr = list_ptr->next;
                    snprintf(list_ptr->name, sizeof(list_ptr->name), "netmap:%s*", pcap_if_ptr->name);
                    sprintf(list_ptr->alias, "%%%d", i++);
                    list_ptr->flags = pcap_if_ptr->flags;

                    list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                    list_ptr = list_ptr->next;
                    snprintf(list_ptr->name, sizeof(list_ptr->name), "netmap:%s^", pcap_if_ptr->name);
                    sprintf(list_ptr->alias, "%%%d", i++);
                    list_ptr->flags = pcap_if_ptr->flags;
                }
#endif /* HAVE_LIBPCAP_NETMAP  || HAVE_NETMAP */
#ifdef HAVE_NETMAP
                if (netmap_version >= 10) {
                    for (x = 0; x < nmr.nr_rx_rings; ++x) {
                        list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                        list_ptr = list_ptr->next;
                        snprintf(list_ptr->name, sizeof(list_ptr->name), "netmap:%s-%d", pcap_if_ptr->name, x);
                        sprintf(list_ptr->alias, "%%%d", i++);
                        list_ptr->flags = pcap_if_ptr->flags;
                    }
                }
            }
            close(fd);
#endif /* HAVE_NETMAP */
#ifdef HAVE_LIBPCAP_NETMAP
        }
#endif /* HAVE_LIBPCAP_NETMAP */
#ifdef HAVE_PF_RING_PCAP
        list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
        list_ptr = list_ptr->next;
        snprintf(list_ptr->name, sizeof(list_ptr->name), "zc:%s", pcap_if_ptr->name);
        sprintf(list_ptr->alias, "%%%d", i++);
        list_ptr->flags = pcap_if_ptr->flags;
#endif
        pcap_if_ptr = pcap_if_ptr->next;
    }
    pcap_freealldevs(pcap_if);

    /* look for khial device: https://github.com/boundary/khial */
    if ((dir = opendir("/dev/char")) != NULL) {
        while ((dirdata = readdir(dir)) != NULL) {
            if (strncmp(dirdata->d_name, "testpackets", strlen("testpackets")) == 0) {
                if (i > 0) {
                    list_ptr->next = (interface_list_t *)safe_malloc(sizeof(interface_list_t));
                    list_ptr = list_ptr->next;
                }
                dbgx(3, "Adding %s to interface list", dirdata->d_name);
                snprintf(testnic, 254, "/dev/char/%s", dirdata->d_name);
                strlcpy(list_ptr->name, testnic, 255);
                snprintf(testnic, 255, "khial pseudo-nic: %s", dirdata->d_name);
                strlcpy(list_ptr->description, testnic, 255);
                strlcpy(list_ptr->alias, dirdata->d_name, 255);
                i += 1;
            }
        }

    }

    dbg(1, "xxx get_interface_list end");
    return(list_head);
}
Esempio n. 30
0
int sendpacket_send_netmap(void *p, const u_char *data, size_t len)
{
    int retcode = 0;
    sendpacket_t *sp = p;
    struct netmap_ring *txring;
    struct netmap_slot *slot;
    char *pkt;
    uint32_t cur, avail;

    if (sp->abort)
        return retcode;

    txring = NETMAP_TXRING(sp->nm_if, sp->cur_tx_ring);
    while ((avail = nm_ring_space(txring)) == 0) {
        /* out of space on current TX queue - go to next */
        ++sp->cur_tx_ring;
        if (sp->cur_tx_ring > sp->last_tx_ring) {
            /*
             * out of space on all queues
             *
             * we have looped through all configured TX queues
             * so we have to reset to the first queue and
             * wait for available space
             */
            struct pollfd pfd;

            sp->cur_tx_ring = sp->first_tx_ring;

            /* send TX interrupt signal
             *
             * On Linux this makes one slot free on the
             * ring, which increases speed by about 10Mbps.
             *
             * But it will never free up all the slots. For
             * that we must poll and call again.
             */
            ioctl(sp->handle.fd, NIOCTXSYNC, NULL);

            pfd.fd = sp->handle.fd;
            pfd.events = POLLOUT;
            pfd.revents = 0;
            if (poll(&pfd, 1, 1000) <= 0) {
                if (++sp->tx_timeouts == NETMAP_TX_TIMEOUT_SEC) {
                    return -1;
                }
                return -2;
            }

            sp->tx_timeouts = 0;

            /*
             * Do not remove this even though it looks redundant.
             * Overall performance is increased with this restart
             * of the TX queue.
             *
             * This call increases the number of available slots from
             * 1 to all that are truly available.
             */
            ioctl(sp->handle.fd, NIOCTXSYNC, NULL);
        }

        txring = NETMAP_TXRING(sp->nm_if, sp->cur_tx_ring);
    }

    /*
     * send
     */
    cur = txring->cur;
    slot = &txring->slot[cur];
    slot->flags = 0;
    pkt = NETMAP_BUF(txring, slot->buf_idx);
    memcpy(pkt, data, min(len, txring->nr_buf_size));
    slot->len = len;

    if (avail <= 1)
        slot->flags = NS_REPORT;

    dbgx(3, "netmap cur=%d slot index=%d flags=0x%x empty=%d avail=%u bufsize=%d\n",
            cur, slot->buf_idx, slot->flags, NETMAP_TX_RING_EMPTY(txring),
            nm_ring_space(txring), txring->nr_buf_size);

    /* let kernel know that packet is available */
    cur = NETMAP_RING_NEXT(txring, cur);
#ifdef HAVE_NETMAP_RING_HEAD_TAIL
    txring->head = cur;
#else
    txring->avail--;
#endif
    txring->cur = cur;
    retcode = len;

    return retcode;
}