Skip to content

Commit

Permalink
adding IPv6 option
Browse files Browse the repository at this point in the history
enables Netspoc to work on IPv6 topologies
IPv6 Testsuite can be generated via included makefile
  • Loading branch information
mbruns committed Mar 15, 2017
1 parent 360eed0 commit f2c1b7e
Show file tree
Hide file tree
Showing 20 changed files with 1,129 additions and 490 deletions.
8 changes: 6 additions & 2 deletions bin/add-to-netspoc
Expand Up @@ -110,6 +110,8 @@ sub setup_add_to {
return;
}

my $ip_pattern;

# Find occurence of typed name in list of objects:
# - group:<name> = <typed name>, ... <typed name>;
# - src =
Expand Down Expand Up @@ -173,7 +175,7 @@ sub process {
$input =~ /\G ( \s* managed \s* & )/gcx or

# IP for automatic group.
$input =~ /\G ( \s* ip \s* = \s* [0-9.\/]+ \s* & )/gcx or
$input =~ /\G ( \s* ip \s* = \s* $ip_pattern \s* & )/gcx or

# End of automatic group.
$input =~ /\G (\s* \])/gcx or
Expand Down Expand Up @@ -261,9 +263,10 @@ sub read_pairs {
# Make @ARGV utf-8.
$_ = Encode::decode('UTF-8' , $_) for @ARGV;

my ($from_file, $help, $man);
my ($from_file, $help, $man, $ipv6);
GetOptions ( 'f=s' => \$from_file,
'q!' => \$quiet,
'ipv6' => \$ipv6,
'help|?' => \$help,
man => \$man,
) or pod2usage(2);
Expand All @@ -272,6 +275,7 @@ pod2usage(-exitstatus => 0, -verbose => 2) if $man;

my $path = shift @ARGV or pod2usage(2);
$from_file or @ARGV or pod2usage(2);
$ip_pattern = $ipv6? "[a-f:\/0-9]+" : "[0-9.\/]+";

####################################################################
# Main program
Expand Down
9 changes: 6 additions & 3 deletions bin/cut-netspoc
Expand Up @@ -69,8 +69,10 @@ use Encode qw(decode_utf8);
####################################################################
# Argument processing
####################################################################
my ($quiet, $help, $man);
my ($quiet, $help, $man, $ipv6);

GetOptions ( 'quiet!' => \$quiet,
'ipv6' => \$ipv6,
'help|?' => \$help,
man => \$man,
) or pod2usage(2);
Expand Down Expand Up @@ -261,7 +263,8 @@ sub get_zones {

my $file_config = read_config($path);
$config = combine_config($file_config,
{time_stamps => 1, max_errors => 9999, verbose => !$quiet});
{time_stamps => 1, max_errors => 9999, verbose => !$quiet,
ipv6 => $ipv6? 1 : 0 });
init_global_vars();
show_version();

Expand Down Expand Up @@ -329,7 +332,7 @@ sub process_rules {
# debug "Used $obj->{name}";
$obj->{router}->{is_used} = 1;
$obj->{network}->{is_used} = 1;
}
}
}
&path_walk($rule, \&mark_topology);
for my $prt (@$prt_list) {
Expand Down
10 changes: 6 additions & 4 deletions bin/export-netspoc
Expand Up @@ -39,9 +39,10 @@ sub usage {
die "Usage: $0 [-q] netspoc-data out-directory\n";
}
my $quiet;
my $ipv6;

# Argument processing.
GetOptions ('quiet!' => \$quiet) or usage();
GetOptions ('quiet!' => \$quiet, 'ipv6' => \$ipv6 ) or usage();
my $netspoc_data = shift @ARGV or usage();
my $out_dir = shift @ARGV or usage();
@ARGV and usage();
Expand Down Expand Up @@ -404,7 +405,7 @@ my %all_objects;
# Split service, if 'user' has different values in normalized rules.
sub normalize_services_for_export {
progress("Normalize services for export");
my @result;
my @result;
for my $service (sort by_name values %services) {
next if $service->{disabled};
my $sname = $service->{name};
Expand Down Expand Up @@ -494,7 +495,7 @@ sub normalize_services_for_export {
sub setup_service_info {
my ($normalized_services) = @_;
progress("Setup service info");

for my $service (@$normalized_services) {
my $users = $service->{user};

Expand Down Expand Up @@ -1185,7 +1186,8 @@ sub copy_policy_file {
# Initialize Netspoc data
####################################################################
$config =
combine_config({time_stamps => 1, max_errors => 9999, verbose => !$quiet});
combine_config({time_stamps => 1, max_errors => 9999,
verbose => !$quiet, ipv6 => $ipv6? 1 : 0 });
init_global_vars();
read_file_or_dir($netspoc_data);
order_protocols();
Expand Down
19 changes: 13 additions & 6 deletions bin/print-group
Expand Up @@ -123,7 +123,8 @@ sub print_address {
}
else {
my $prefix = mask2prefix($obj->{mask});
return print_ip($ip) . ($prefix == 32 ? '' : "/$prefix");
return print_ip($ip) . ($prefix == ($config->{ipv6} == 1? 128 : 32)
? '' : "/$prefix");
}
}
elsif ($type eq 'Host' or $type eq 'Interface') {
Expand All @@ -143,7 +144,9 @@ sub print_address {
# Dynamic NAT, take whole network.
my $ip = $network->{ip};
my $prefix = mask2prefix($network->{mask});
return print_ip($ip) . ($prefix == 32 ? '' : "/$prefix");
return print_ip($ip) . ($prefix ==
($config->{ipv6} == 1? 128 : 32)
? '' : "/$prefix");
}
}
elsif (my $range = $obj->{range}) {
Expand All @@ -158,7 +161,8 @@ sub print_address {
# Take whole network.
my $ip = $network->{ip};
my $prefix = mask2prefix($network->{mask});
return print_ip($ip) . ($prefix == 32 ? '' : "/$prefix");
return print_ip($ip) . ($prefix == ($config->{ipv6} == 1? 128 : 32)
? '' : "/$prefix");
}
else {
return print_ip(nat($obj->{ip}, $network));
Expand All @@ -173,8 +177,9 @@ sub print_address {
# Argument processing
####################################################################

my ($nat_net, $show_unused, $show_ip, $show_name, $show_owner, $groups_file,
$quiet, $help, $man);
my ($nat_net, $show_unused, $show_ip, $show_name, $show_owner, $groups_file,
$quiet, $help, $ipv6, $man);

GetOptions ( 'nat=s' => \$nat_net,
'unused' => \$show_unused,
'ip!' => \$show_ip,
Expand All @@ -183,6 +188,7 @@ GetOptions ( 'nat=s' => \$nat_net,
'f=s' => \$groups_file,
'quiet!' => \$quiet,
'help|?' => \$help,
'ipv6' => \$ipv6,
man => \$man,
) or pod2usage(2);
pod2usage(1) if $help;
Expand Down Expand Up @@ -211,7 +217,8 @@ else {
####################################################################

my $file_config = &read_config($in_path);
$config = combine_config($file_config, { verbose => !$quiet });
$config = combine_config($file_config, { verbose => !$quiet,
ipv6 => $ipv6? 1 : 0 });
init_global_vars();

# Parse group definition(s).
Expand Down
10 changes: 7 additions & 3 deletions bin/print-service
Expand Up @@ -77,8 +77,10 @@ use Pod::Usage;
# Argument processing
####################################################################

my ($nat_net, $quiet, $help, $man);
my ($nat_net, $ipv6, $quiet, $help, $man);

GetOptions ( 'nat=s' => \$nat_net,
'ipv6' => \$ipv6,
'quiet!' => \$quiet,
'help|?' => \$help,
man => \$man,
Expand All @@ -99,7 +101,8 @@ sub ip_info {
my ($obj) = @_;
my ($ip, $mask) = @{ address($obj, $no_nat_set) };
my $prefix_len = mask2prefix($mask);
return(print_ip($ip) . ($prefix_len == 32 ? '' : "/$prefix_len"));
return(print_ip($ip) . ($prefix_len == ($config->{ipv6} == 1? 128 : 32 )?
'' : "/$prefix_len"));
}

sub prt_info {
Expand Down Expand Up @@ -146,7 +149,8 @@ sub prt_info {
####################################################################

my $file_config = &read_config($in_path);
$config = combine_config($file_config, { verbose => !$quiet });
$config = combine_config($file_config, { verbose => !$quiet,
ipv6 => $ipv6? 1 : 0 });
init_global_vars();

# Read and process Netspoc configuration file or directory.
Expand Down
9 changes: 6 additions & 3 deletions bin/remove-from-netspoc
Expand Up @@ -106,6 +106,7 @@ sub setup_objects {
return;
}

my $ip_pattern;
# Find occurence of typed name in list of objects:
# - group:<name> = <typed name>, ... <typed name>;
# - src = ...;
Expand Down Expand Up @@ -201,7 +202,7 @@ sub process {
$input =~ /\G ( \s* managed \s* & )/gcx or

# IP for automatic group.
$input =~ /\G ( \s* ip \s* = \s* [0-9.\/]+ \s* & )/gcx or
$input =~ /\G ( \s* ip \s* = \s* $ip_pattern \s* & )/gcx or

# End of automatic group.
$input =~ /\G (\s* \])/gcx or
Expand Down Expand Up @@ -279,9 +280,11 @@ sub read_objects {
# Make @ARGV utf-8.
$_ = Encode::decode('UTF-8' , $_) for @ARGV;

my ($from_file, $help, $man);
my ($from_file, $help, $man, $ipv6);

GetOptions ( 'f=s' => \$from_file,
'q!' => \$quiet,
'ipv6' => \$ipv6,
'help|?' => \$help,
man => \$man,
) or pod2usage(2);
Expand All @@ -290,7 +293,7 @@ pod2usage(-exitstatus => 0, -verbose => 2) if $man;

my $path = shift @ARGV or pod2usage(2);
$from_file or @ARGV or pod2usage(2);

$ip_pattern = $ipv6? "[a-f:\/0-9]+" : "[0-9.\/]+";
####################################################################
# Main program
####################################################################
Expand Down
91 changes: 81 additions & 10 deletions lib/Netspoc/Compiler/Common.pm
Expand Up @@ -39,6 +39,8 @@ our @EXPORT = qw(
$zero_ip $max_ip
increment_ip
mask2prefix prefix2mask match_ip
init_mask_prefix_lookups
init_zero_and_max_ip
);

# Enable printing of diagnostic messages by
Expand Down Expand Up @@ -98,25 +100,88 @@ sub progress {

sub ip2bitstr {
my ($ip) = @_;
if ($config->{ipv6} == 1) {
return NetAddr::IP::Util::ipv6_aton($ip);
}
else {
my ($i1,$i2,$i3,$i4) = split '\.', $ip;

# Create bit string with 32 bits.
return pack 'C4', $i1, $i2, $i3, $i4;
}
}

## no critic (RequireArgUnpacking)
sub bitstr2ip {
if ($config->{ipv6} == 1) {
return NetAddr::IP::Util::ipv6_ntoa($_[0]);
}
else {
return sprintf "%vd", $_[0];
}
}

## use critic

our $zero_ip = pack('N', 0);
our $max_ip = pack('N', 0xffffffff);
our $zero_ip;
our $max_ip;
sub init_zero_and_max_ip {
if ($config->{ipv6} == 1) {
$zero_ip = NetAddr::IP::Util::ipv6_aton('0:0:0:0:0:0:0:0');
$max_ip = NetAddr::IP::Util::ipv6_aton(
'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff');
}
else {
$zero_ip = pack('N', 0);
$max_ip = pack('N', 0xffffffff);

}
}

# Bitwise functions use vec() to access single bits. vec() has a
# mixed-endian behaviour tough: While it is little-endian regarding a
# sequence of bytes (lowest byte first/left), it is big-endian within
# the byte (biggest bit first/left). Tis array is used to transform
# the big-endianness within bytes to little-endianness. Thus,
# positions 0..x in the following functions refer to the position from
# left to right, with leftmost bit is position 0, rightmost bit
# position x.
my @big_to_little_endian = (7,5,3,1,-1,-3,-5,-7);

sub check_bit {
my ($bitstring, $position) = @_;
my $bitpos = $position + $big_to_little_endian[$position % 8];
return vec($bitstring, $bitpos, 1);
}

sub set_bit {
my ($bitstring, $position) = @_;
my $bitpos = $position + $big_to_little_endian[$position % 8];
vec($bitstring, $bitpos, 1) = 1;
return $bitstring;
}

sub unset_bit {
my ($bitstring, $position) = @_;
my $bitpos = $position + $big_to_little_endian[$position % 8];
vec($bitstring, $bitpos, 1) = 0;
return $bitstring;
}

sub increment_ip {
my ($ip) = @_;
pack('N', 1 + unpack('N', $ip));
my ($bitstring) = @_;
my $prefix = $config->{ipv6} == 1? 128 : 32;
while(1) {
last if $prefix == 0;
$prefix--;
if (check_bit($bitstring, $prefix) == 0) {
$bitstring = set_bit($bitstring, $prefix);
return $bitstring;
}
else {
$bitstring = unset_bit($bitstring, $prefix);
}
}
}

# Conversion from netmask to prefix and vice versa.
Expand All @@ -125,16 +190,22 @@ sub increment_ip {
# Initialize private variables of this block.
my %mask2prefix;
my %prefix2mask;
my $mask = pack('N', 0x00000000);
my $bit = 0x80000000;

sub init_mask_prefix_lookups {
my $prefix = 0;
while(1) {
my $prefixlen = $config->{ipv6} == 1? 128 : 32;
my $mask = $config->{ipv6} == 1
? NetAddr::IP::Util::ipv6_aton('0:0:0:0:0:0:0:0')
: pack('N', 0x00000000);

while (1) {
$mask2prefix{$mask} = $prefix;
$prefix2mask{$prefix} = $mask;
last if $prefix == 32;
last if $prefix == $prefixlen;
my $bitpos = $prefix + $big_to_little_endian[$prefix % 8];
vec($mask, $bitpos, 1) = 1;
$prefix++;
$mask |= pack('N', $bit);
$bit /= 2;
}
}

# Convert a network mask to a prefix ranging from 0 to 32.
Expand Down
4 changes: 4 additions & 0 deletions lib/Netspoc/Compiler/GetArgs.pm
Expand Up @@ -63,6 +63,9 @@ our %config_type = (

our %config = (

# Use IPv4 version as default
ipv6 => 0,

# Check for unused groups and protocolgroups.
check_unused_groups => 'warn',

Expand Down Expand Up @@ -203,6 +206,7 @@ sub parse_options {
$options{"$key$opt"} = $setopt;
}
$options{quiet} = sub { $result{verbose} = 0 };
$options{ipv6} = sub { $result{ipv6} = 1 };
$options{'help|?'} = sub { pod2usage(1) };
$options{man} = sub { pod2usage(-exitstatus => 0, -verbose => 2) };

Expand Down

0 comments on commit f2c1b7e

Please sign in to comment.