Changeset 7428ab2


Ignore:
Timestamp:
06/22/15 17:44:39 (5 years ago)
Author:
Shane Alcock <salcock@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
84d137d, d280f48
Parents:
8b12caf
Message:

Add trace_strip_packet to libtrace API

This function will allow callers to strip MPLS and VLAN headers from
libtrace packets. Some analysis tools (especially those written with
libpcap in the days before these technologies were popular) don't
work so well when these headers are present.

Stripping VLAN headers also makes BPF filtering easier.

Location:
lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • lib/libtrace.h.in

    rc5ac872 r7428ab2  
    16031603void *trace_get_link(const libtrace_packet_t *packet);
    16041604
     1605/**
     1606 * Supported masks for stripping headers from packets.
     1607 */
     1608enum {
     1609        TRACE_STRIP_VLAN = 0x01, /**< Strip 802.1Q (VLAN tag) headers */
     1610        TRACE_STRIP_MPLS = 0x02  /**< Strip MPLS headers */
     1611};
     1612
     1613/** Strips certain headers from a given packet.
     1614 * @param packet        The packet to strip headers from.
     1615 * @param stripopts     A mask to indicate which headers should be stripped.
     1616 * If multiple header types are to be stripped, these should be ORed together
     1617 * to create the full mask. A mask of zero will strip all strippable headers.
     1618 *
     1619 * @return The packet with the requested headers removed (if they were
     1620 * present).
     1621 *
     1622 * This function is intended for removing those pesky layer 2.5 headers
     1623 * that are not supported by other packet analysis applications, e.g. VLAN
     1624 * and MPLS headers. If successful, the resulting packet will be a simple
     1625 * Ethernet-IP-Transport packet that just about anything should be able to
     1626 * parse without difficulty.
     1627 *
     1628 * If this function encounters a layer 2 or 2.5 header that it does not
     1629 * support, stripping will cease and the packet returning will be stripped
     1630 * up to but not including the unsupported header.
     1631 *
     1632 * New in libtrace 4.0.0
     1633 *
     1634 * @note This function only supports stripping headers from Ethernet packets
     1635 * for now. Passing in packets of other link types will simply result in
     1636 * the original packet being returned unmodified.
     1637 *
     1638 * @note Depending on the input source, this function may need to copy the
     1639 * original packet to be able to safely modify the contents. This may have
     1640 * a major impact on performance so avoid stripping packets unless absolutely
     1641 * necessary.
     1642 */
     1643DLLEXPORT libtrace_packet_t *trace_strip_packet(libtrace_packet_t *packet,
     1644                int stripopts);
     1645
    16051646/** Get a pointer to the IPv4 header (if any) for a given packet
    16061647 * @param packet        The packet to get the IPv4 header for
  • lib/protocols_l2.c

    rf7bcbfb r7428ab2  
    3737#include <assert.h>
    3838#include <stdlib.h>
     39#include <string.h>
    3940
    4041
     
    9798
    9899        return (void*)((char *)ethernet + sizeof(*vlanhdr));
     100
     101}
     102
     103libtrace_packet_t *trace_strip_packet(libtrace_packet_t *packet,
     104                int stripopts) {
     105
     106        libtrace_ether_t *ethernet;
     107        libtrace_linktype_t linktype;
     108        uint16_t ethertype;
     109        uint32_t remaining;
     110        libtrace_packet_t *copy;
     111        void *payload;
     112        uint16_t finalethertype = 0;
     113        uint16_t caplen, removed = 0;
     114        char *dest;
     115        uint8_t done = 0;
     116        uint32_t oldrem;
     117
     118        /* For now, this will just work for Ethernet packets. */
     119        ethernet = (libtrace_ether_t *)trace_get_layer2(packet,
     120                        &linktype, &remaining);
     121
     122        if (linktype != TRACE_TYPE_ETH) {
     123                return packet;
     124        }
     125
     126        /* No headers to strip, return the original packet */
     127        if (ethernet->ether_type == TRACE_ETHERTYPE_IP ||
     128                        ethernet->ether_type == TRACE_ETHERTYPE_IPV6) {
     129                return packet;
     130        }
     131
     132        /* Copy the packet as we need to be sure that the packet
     133         * payload is contiguous. This won't be guaranteed for live
     134         * formats, for instance.
     135         */
     136        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
     137                copy = trace_copy_packet(packet);
     138                trace_destroy_packet(packet);
     139                packet = copy;
     140
     141                /* Re-grab the ethernet header from the copy */
     142                ethernet = (libtrace_ether_t *)trace_get_layer2(packet,
     143                        &linktype, &remaining);
     144
     145        }
     146
     147        payload = trace_get_payload_from_layer2(ethernet, linktype,
     148                        &ethertype, &remaining);
     149
     150        dest = ((char *)ethernet) + sizeof(libtrace_ether_t);
     151        caplen = trace_get_capture_length(packet);
     152        while (!done) {
     153
     154                if (payload == NULL || remaining == 0)
     155                        break;
     156
     157                oldrem = remaining;
     158                switch (ethertype) {
     159
     160                case TRACE_ETHERTYPE_8021Q:
     161                        payload = (void *)trace_get_payload_from_vlan(payload,
     162                                        &ethertype, &remaining);
     163                        if (stripopts == 0 || (stripopts & TRACE_STRIP_VLAN))
     164                        {
     165                                removed += (oldrem - remaining);
     166                                memmove(dest, payload, remaining);
     167                                payload = dest;
     168
     169                        } else {
     170                                if (finalethertype == 0) {
     171                                        finalethertype = TRACE_ETHERTYPE_8021Q;
     172                                }
     173                                dest = payload;
     174                        }
     175                        break;
     176
     177                case TRACE_ETHERTYPE_MPLS:
     178                        payload = (void *)trace_get_payload_from_mpls(payload,
     179                                        &ethertype, &remaining);
     180                        if (stripopts == 0 || (stripopts & TRACE_STRIP_MPLS))
     181                        {
     182                                removed += (oldrem - remaining);
     183                                memmove(dest, payload, remaining);
     184                                payload = dest;
     185
     186                        } else {
     187                                if (finalethertype == 0) {
     188                                        finalethertype = TRACE_ETHERTYPE_MPLS;
     189                                }
     190                                dest = payload;
     191                        }
     192                        break;
     193
     194                case TRACE_ETHERTYPE_IP:
     195                case TRACE_ETHERTYPE_IPV6:
     196                default:
     197                        if (finalethertype == 0)
     198                                finalethertype = ethertype;
     199                        done = true;
     200                        break;
     201                }
     202        }
     203
     204        /* Update the preceding headers to match the new packet contents */
     205        ethernet->ether_type = ntohs(finalethertype);
     206        trace_set_capture_length(packet, caplen - removed);
     207        return packet;
    99208
    100209}
Note: See TracChangeset for help on using the changeset viewer.