wiresharkpacketpcapeditcap

How to remove data link layer from pcap file?


I'm making a script that is inspecting packets, but headers giving me a headache. I have a DSL connection/Wireless at home, and the data link layer is appearing in Wireshark capture, either PPP or WLAN depending on which one I am currently using.

I've been searching for a thsark, editcap or tcpdump or whatever tutorial but I couldn't find any.

Basically all I need: < program_name_which_nicely_removes_transport_layer > input.pcap < output.pcap_only_containing_ethernet_header+ip+tcp+data > or something similar.

I have found a program named bittwiste, but it's operating with fixed sizes as I realized, but I need something 'universal', where I don't have to determine the used link type + size.

Any help is appreciated!

Thank you in advance.


Solution

  • With Perl and the libraries Net::Pcap and Net::PcapWriter you could do the following to remove the PPPoE layer. This works at least for my router (fritz.box). This needs to be adapted to other encapsulations:

    #!/usr/bin/perl
    # usage: pcap_remove_pppoe.pl infile.pcap outfile.pcap
    
    use strict;
    use warnings;
    use Net::Pcap qw(pcap_open_offline pcap_loop pcap_datalink :datalink);
    use Net::PcapWriter;
    
    my $infile = shift or die "no input file";
    my $outfile = shift;  # use stdout if not given
    
    my $err;
    my $pcap = pcap_open_offline($infile,\$err) or
        die "failed to open $infile: $err";
    my $ll = pcap_datalink($pcap);
    die "expected DLT_EN10MB, got $ll" if $ll != DLT_EN10MB;
    my $offset = 14; # DLT_EN10MB
    
    # open and initialize output
    my $pw = Net::PcapWriter->new($outfile);
    
    # process packets
    pcap_loop($pcap, -1, sub {
        my (undef,$hdr,$data) = @_;
        my $dl = substr($data,0,$offset,''); # remove data link layer
        my $etype = unpack("n",substr($dl,-2,2)); # get ethernet type
        $etype == 0x8864 or return; # ignore any type except PPPoE Session
    
        substr($data,0,8,''); # remove 8 byte PPPoE layer
        substr($data,-2,2,pack("n",0x0800)); # set ethernet type to IPv4
    
        # output: data link layer with IP type + IP layer (PPPoE removed)
        $pw->packet($data, [ $hdr->{tv_sec},$hdr->{tv_usec} ]);
    },undef);