Guest User

openspace.pl

a guest
Nov 2nd, 2015
549
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/perl
  2.  
  3. ### Show list of used/unused subnets in a given supernet
  4. ###
  5. ### Usage ./openspace.pl [<username>@]<router_addresss> <supernet>
  6.  
  7. use strict;
  8. use Net::OpenSSH;
  9. use Term::ReadKey;
  10. use Net::CIDR;
  11. use Term::ANSIColor;
  12.  
  13. my $router;
  14. my $user;
  15.  
  16. ### Validate argument count
  17. if (@ARGV != 2) {
  18.   print "Usage ./openspace.pl [<username>@]<router_addresss> <supernet>\n";
  19.   exit;
  20. }
  21.  
  22. ### Unbuffer STDOUT so we can tee and watch this live
  23. $|=1;
  24.  
  25. ### First argument may include username; handle that
  26. if ($ARGV[0] =~ /\@/) {
  27.   my @ssh_info = split ('@', $ARGV[0]);
  28.   $user = $ssh_info[0];
  29.   $router = $ssh_info[1];
  30. } else {
  31.   $user = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<);
  32.   $router = $ARGV[0];
  33. }
  34.  
  35. my $supernet = $ARGV[1]; ### Supernet to break down subnet usage
  36. my @subnets = (); ### Array to hold used subnets
  37.  
  38. ### Get user's password
  39. print STDERR "Password ($user): ";
  40. ReadMode('noecho');
  41. chomp(my $pass = ReadLine(0));
  42. print STDERR "\n";
  43. ReadMode('restore');
  44.  
  45. ### SSH to router
  46. my $ssh = Net::OpenSSH->new($user.":".$pass."@".$router, master_stderr_discard => 1, master_opts => [-o => "StrictHostKeyChecking=no"]);
  47. $ssh->error and
  48. die "Couldn't establish SSH connection to $user"."@"."$router:\n".$ssh->error;
  49.  
  50. ### Get routes in given supernet
  51. chomp(my @routes = $ssh->capture("show route $supernet | grep ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/ | except \/32"));
  52.  
  53. ### If there are no routes, print the supernet in green and exit
  54. if (!@routes) {
  55.   print color('green');
  56.   print "$supernet\n";
  57.   print color('reset');
  58.   exit;
  59. }
  60.  
  61. ### Trim the routes to grab just the subnets
  62. foreach (@routes) {
  63.   if ($_ =~ /(^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2})/) {
  64.     push (@subnets, $1);
  65.   }
  66. }
  67.  
  68. ### Deduplicate the list of subnets
  69. my %dedupe = map { $_ => 1 } @subnets;
  70. my @subnets = keys %dedupe;
  71.  
  72. ### Sort the subnets
  73. my @sorted_subnets = ();;
  74. @sorted_subnets = sort {
  75.   my @a = $a =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)/;
  76.   my @b = $b =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)/;
  77.   $a[0] <=> $b[0] ||
  78.   $a[1] <=> $b[1] ||
  79.   $a[2] <=> $b[2] ||
  80.   $a[3] <=> $b[3] ||
  81.   $a[4] <=> $b[4]
  82. } @subnets;
  83.  
  84. ### Find any subnets that appear to be aggregates
  85. my @aggregate_subnets = ();
  86. for (my $i = 0; $i < @sorted_subnets-1; $i++) {
  87.   ### Find out the first and last IP in the next element's range
  88.   my @range = Net::CIDR::cidr2range($sorted_subnets[$i+1]);
  89.   my @endpoints = split('-', $range[0]);
  90.   my @cidr_list = ();
  91.   $cidr_list[0] = $sorted_subnets[$i];
  92.   if (Net::CIDR::cidrlookup($endpoints[0], @cidr_list) && Net::CIDR::cidrlookup($endpoints[1], @cidr_list)) {
  93.     print color('red');
  94.     print "### NOTICE: $sorted_subnets[$i] overlaps $sorted_subnets[$i+1] and is marked as aggregate.\n";
  95.     print color('reset');
  96.     push (@aggregate_subnets, $sorted_subnets[$i]);
  97.   }
  98. }
  99.  
  100. ### Remove @aggregate_subnets from @sorted_subnets
  101. %dedupe = ();
  102. $dedupe{$_}=1 foreach (@aggregate_subnets);
  103. @sorted_subnets = grep { not exists $dedupe{$_} } @sorted_subnets;
  104.  
  105. ###DEBUG
  106. #print "SORTED: @sorted_subnets\n";
  107. #print "AGGREGATE: @aggregate_subnets\n";
  108.  
  109. ### Get the start/end addresses to report on
  110. my @range = Net::CIDR::cidr2range($supernet);
  111. my @endpoints = split('-', $range[0]);
  112. my $supernet_start = $endpoints[0];
  113. my $supernet_end = $endpoints[1];
  114. my $supernet_start_in_subnets =  Net::CIDR::cidrlookup($supernet_start, @sorted_subnets);
  115. my $supernet_end_in_subnets = Net::CIDR::cidrlookup($supernet_end, @sorted_subnets);
  116.  
  117. my %results = (); ### Hash to hold results with key being the subnet
  118.                   ### and the value being red (used), yellow (part of supernet), green (available)
  119.  
  120. ###  Add first range of available subnets to %results if first IP in $supernet is not in @sorted_subnets
  121. if (!$supernet_start_in_subnets) {
  122.   my $start = $supernet_start;
  123.   my @split_end = split (/\//,$sorted_subnets[0]);
  124.   my $end = $split_end[0];
  125.   my @gap_subnets = Net::CIDR::range2cidr("$start-$end");
  126.   @gap_subnets = grep { $_ !~ /\/32/ } @gap_subnets;
  127.   foreach my $gap_subnet (@gap_subnets) {
  128.     if (Net::CIDR::cidrlookup($gap_subnet, @aggregate_subnets)) {
  129.       $results{$gap_subnet} = "yellow";
  130.     } else {
  131.       $results{$gap_subnet} = "green";
  132.     }
  133.   }
  134. }
  135.  
  136. ### Add other ranges
  137. for (my $i = 0; $i < @sorted_subnets; $i++) {
  138.   $results{$sorted_subnets[$i]} = "red";
  139.   if (defined ($sorted_subnets[$i+1])) {
  140.     my @range = Net::CIDR::cidr2range($sorted_subnets[$i]);
  141.     my @endpoints = split('-', $range[0]);
  142.     my $start = @endpoints[1];
  143.     @range = Net::CIDR::cidr2range($sorted_subnets[$i+1]);
  144.     @endpoints = split('-', $range[0]);
  145.     my $end = @endpoints[0];
  146.     my @gap_subnets=Net::CIDR::range2cidr("$start-$end");
  147.     @gap_subnets = grep { $_ !~ /\/32/ } @gap_subnets;
  148.     foreach my $gap_subnet (@gap_subnets) {
  149.       if (Net::CIDR::cidrlookup($gap_subnet, @aggregate_subnets)) {
  150.         $results{$gap_subnet} = "yellow";
  151.       } else {
  152.         $results{$gap_subnet} = "green";
  153.       }
  154.     }
  155.   }
  156. }  
  157.  
  158. ### Add last range if last IP in $supernet is not in @sorted_subnets
  159. if (!$supernet_end_in_subnets) {
  160.   my @range = Net::CIDR::cidr2range($sorted_subnets[-1]);
  161.   my @endpoints = split('-', $range[0]);
  162.   my $last_subnet_end = @endpoints[1];
  163.   my @gap_subnets = Net::CIDR::range2cidr("$last_subnet_end-$supernet_end");
  164.   @gap_subnets = grep { $_ !~ /\/32/ } @gap_subnets;
  165.   foreach my $gap_subnet (@gap_subnets) {
  166.     if (Net::CIDR::cidrlookup($gap_subnet, @aggregate_subnets)) {
  167.       $results{$gap_subnet} = "yellow";
  168.     } else {
  169.       $results{$gap_subnet} = "green";
  170.     }
  171.   }
  172. }
  173.  
  174. ### Print the sorted hash
  175. for my $subnet (sort {  
  176.                   my @a = $a =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)/;
  177.                   my @b = $b =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)/;
  178.                   $a[0] <=> $b[0] ||
  179.                   $a[1] <=> $b[1] ||
  180.                   $a[2] <=> $b[2] ||
  181.                   $a[3] <=> $b[3] ||
  182.                   $a[4] <=> $b[4]
  183.                 } (keys %results)) {
  184.   print color($results{$subnet});
  185.   print "$subnet\n";
  186.   print color('reset');
  187. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×