diff options
Diffstat (limited to 'VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl')
-rwxr-xr-x | VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl b/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl new file mode 100755 index 00000000..8e42eeba --- /dev/null +++ b/VNFs/DPPD-PROX/helper-scripts/ipv6_tun/gen_4over6.pl @@ -0,0 +1,271 @@ +#!/usr/bin/perl + +## +## Copyright (c) 2010-2017 Intel Corporation +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## + +use strict vars; +use Getopt::Long; +use Pod::Usage; +use Net::Pcap; +use Net::Frame::Layer; +use Net::Frame::Layer::ETH qw(:consts); +use Net::Frame::Layer::IPv6 qw(:consts); +use Net::Frame::Layer::IPv4 qw(:consts); +use Net::Frame::Layer::UDP; +use Socket qw(AF_INET AF_INET6 inet_ntop inet_pton); + +use constant NUM_PACKETS => 30000; + +use constant ETHER_ADDR_LEN => 6; +use constant ETHER_TYPE_LEN => 2; +use constant ETHER_HDR_LEN => ( 2 * ETHER_ADDR_LEN ) + ETHER_TYPE_LEN; +use constant ETHER_STATIC_MAC => "78acdddddddd"; + +use constant UDP_HDR_LEN => 8; +use constant UDP_STATIC_PORT => 0x6666; + +use constant IPv6_HOP_LIMIT => 4; +use constant IPv6_STATIC_IP => "2222:2222:2222:2222:2222:2222:2222:2222"; + +use constant IPv4_TIME_TO_LIVE => 32; +use constant IPv4_STATIC_IP => "68.68.68.68"; + +srand; + +my $type = 'tun'; +my $pkt_count = NUM_PACKETS; + +GetOptions( + 'inet' => sub { $type = 'inet'}, + 'tun' => sub { $type = 'tun'}, + 'count=i' => \$pkt_count, + 'in=s' => \(my $in = 'ip6_tun_bind.lua'), + 'out=s' => \(my $out = 'output.pcap'), + 'size=s' => \(my $size = 0) +) or exit; + +my $pcap = pcap_open_dead( DLT_EN10MB, 65535 ); +my $dumper = pcap_dump_open($pcap, $out ) or die 'Could not create output file: ' . $out; + +if( $type eq 'inet' ) { + gen_inet_pcap( $in, $pkt_count ); +} +if( $type eq 'tun' ) { + gen_tun_pcap( $in, $pkt_count ); +} + +pcap_close( $pcap ); + +# Trim string +sub trim { + my ( $str ) = @_; + + $str =~ s/^\s+|\s+$//g; + + return $str; +} + +# Generate random port based on $port and $port_mask +sub rand_port { + my ( $port, $port_mask ) = @_; + + return ( $port | int( rand( 0xFFFF ) & $port_mask ) ); +} + +# Generate packet originating from CPE +sub gen_tun_packet { + my ( $sz, $ether, $ipv6, $ipv4, $udp ) = @_; + + my $hdr_ether = Net::Frame::Layer::ETH->new( + src => $ether->{'src'}, + dst => $ether->{'dst'}, + type => NF_ETH_TYPE_IPv6 + )->pack; + + my $hdr_ipv6 = Net::Frame::Layer::IPv6->new( + nextHeader => NF_IPv6_PROTOCOL_IPIP, + hopLimit => IPv6_HOP_LIMIT, + src => $ipv6->{'src'}, + dst => $ipv6->{'dst'}, + payloadLength => $sz + NF_IPv4_HDR_LEN + UDP_HDR_LEN + )->pack; + + my $hdr_ipv4 = Net::Frame::Layer::IPv4->new( + length => $sz + UDP_HDR_LEN + NF_IPv4_HDR_LEN, + ttl => IPv4_TIME_TO_LIVE, + protocol => NF_IPv4_PROTOCOL_UDP, + src => $ipv4->{'src'}, + dst => $ipv4->{'dst'} + )->pack; + + my $hdr_udp = Net::Frame::Layer::UDP->new( + src => $udp->{'src'}, + dst => $udp->{'dst'}, + length => $sz + UDP_HDR_LEN + )->pack; + + my $pkt = pack( "H*", "de" x $sz ); + $pkt = $hdr_ether . $hdr_ipv6 . $hdr_ipv4 . $hdr_udp . $pkt; + + my $pkt_size = length( $pkt ); + + my $hdr = { + tv_sec => 0, + tv_usec => 0, + len => $pkt_size, + caplen => $pkt_size + }; + + return ( $hdr, $pkt ); +} + +# Generate packet originating from the internet +sub gen_inet_packet { + my ( $sz, $ether, $ipv4, $udp ) = @_; + + my $hdr_ether = Net::Frame::Layer::ETH->new( + src => $ether->{'src'}, + dst => $ether->{'dst'}, + type => NF_ETH_TYPE_IPv4 + )->pack; + + my $hdr_ipv4 = Net::Frame::Layer::IPv4->new( + length => $sz + UDP_HDR_LEN + NF_IPv4_HDR_LEN, + ttl => IPv4_TIME_TO_LIVE, + protocol => NF_IPv4_PROTOCOL_UDP, + src => $ipv4->{'src'}, + dst => $ipv4->{'dst'} + )->pack; + + my $hdr_udp = Net::Frame::Layer::UDP->new( + src => $udp->{'src'}, + dst => $udp->{'dst'}, + length => $sz + UDP_HDR_LEN + )->pack; + + my $pkt = pack( "H*", "de" x $sz ); + $pkt = $hdr_ether . $hdr_ipv4 . $hdr_udp . $pkt; + + my $pkt_size = length( $pkt ); + + my $hdr = { + tv_sec => 0, + tv_usec => 0, + len => $pkt_size, + caplen => $pkt_size + }; + + return ( $hdr, $pkt ); +} + +# Read bindings file +sub read_bindings { + my ( $file ) = @_; + + print "Reading bindings file...\n"; + + my @rows; + + open my $fh, "<:encoding(utf8)", $file or die $file . ": $!"; +LINE: while ( my $line = <$fh> ) { + next if ($line =~ /^--.*/); # Skip comments + + my ($ip6, $mac, $ip4, $port); + if ($line =~ /\s*\{.*\},\s*$/) { # Weak check for a data line... + + $line =~ /ip6\s*=\s*ip6\("([^\)]*)"\)/ && do { $ip6 = trim($1); }; + unless ( inet_pton( AF_INET6, $ip6 ) ) { print "ERROR - Invalid ipv6: $ip6\n"; next LINE; } + + $line =~ /ip\s*=\s*ip\("([^\)]*)"\)/ && do { $ip4 = trim($1); }; + unless ( inet_pton( AF_INET, $ip4 ) ) { print "ERROR - Invalid ipv4: $ip4\n"; next LINE; } + + $line =~ /mac\s*=\s*mac\("([^\)]*)"\)/ && do { $mac = trim($1); }; + unless ( $mac =~ /^([0-9a-f]{2}([:-]|$)){6}$/i ) { print "ERROR - Invalid mac: $mac\n"; next LINE; } + + $line =~ /port\s*=\s*([0-9]*)/ && do { $port = trim($1); }; + unless ( int($port) ) { print "ERROR - Invalid port number: $port\n"; next LINE; } + + push @rows, { + ipv6 => $ip6, + mac => $mac, + ipv4 => $ip4, + port => $port + } + } + } + close $fh; + + return @rows; +} + +# Generate packets originating from CPE +sub gen_tun_pcap { + my ( $binding_file, $pkt_count ) = @_; + my @bind = read_bindings($binding_file); + my $idx = 0; + my $row; + my $public_port = 0; + + print "Generating $pkt_count Tunnel packets...\n"; + + my $max = @bind; + for( my $i=0; $i<$pkt_count; $i++ ) { + + $idx = rand $max; + $row = @bind[$idx]; + + $public_port = rand_port( $row->{port}, 0x3f ); + + my ( $hdr, $pkt ) = gen_tun_packet( + $size, + { src => $row->{mac}, dst => ETHER_STATIC_MAC }, + { src => $row->{ipv6}, dst => IPv6_STATIC_IP }, + { src => $row->{ipv4}, dst => IPv4_STATIC_IP }, + { src => $public_port, dst => UDP_STATIC_PORT } + ); + + pcap_dump( $dumper, $hdr, $pkt ); + } +} + +# Generate packets originating from the internet +sub gen_inet_pcap { + my ( $binding_file, $pkt_count ) = @_; + my @bind = read_bindings($binding_file); + my $idx = 0; + my $row; + my $public_port = 0; + + print "Generating $pkt_count Internet packets...\n"; + + my $max = @bind; + for( my $i=0; $i<$pkt_count; $i++ ) { + + $idx = rand $max; + $row = @bind[$idx]; + + $public_port = rand_port( $row->{port}, 0x3f ); + + my ( $hdr, $pkt ) = gen_inet_packet( + $size, + { src => ETHER_STATIC_MAC, dst => $row->{mac} }, + { src => IPv4_STATIC_IP, dst => $row->{ipv4} }, + { src => UDP_STATIC_PORT, dst => $public_port } + ); + + pcap_dump( $dumper, $hdr, $pkt ); + } +} |