Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

143 wiersze
4.4 KiB

  1. #!/usr/bin/env perl
  2. #
  3. # Convert input ip/cidr|netmask|hexnetmask to useable network information.
  4. #
  5. use strict;
  6. use warnings;
  7. use Socket;
  8. use Sys::Hostname;
  9. #
  10. # Globalish vars
  11. #
  12. $ENV{PATH} = '/usr/bin:/bin:/usr/sbin:/sbin'; # Paranoia, know thy name!
  13. my ($fqdn_regexp) = qr/([0-9,a-z,A-Z,\-,\_]+)\.([0-9,a-z,A-Z,\-,\_]+)\.(com|gov)/;
  14. #
  15. # converts a 1-word (4 byte) signed or unsigned integer into a dotted decimal
  16. # ip address.
  17. #
  18. sub int2ip {
  19. my $n=int(pop);
  20. return(sprintf("%d.%d.%d.%d", ($n>>24)&0xff,($n>>16)&0xff,
  21. ($n>>8)&0xff,$n&0xff));
  22. };
  23. #
  24. # Convert a host/ip/netmask/cidr/etc.... to a hash of information
  25. # Example: host.domain.tld/24 will get the ip and calculate the netmask info
  26. # equally if host.domain.tld corresponds with 1.2.3.4 the following is valid
  27. # 1.2.3.4/255.255.255.0 would obtain the same information.
  28. #
  29. # die()'s if anything isn't kosher.
  30. #
  31. # Ultra long function, probably needs to be looked at for condensing/splitting.
  32. #
  33. sub cidr2raw {
  34. my $rawinput = pop;
  35. my ($lhs, $rhs, $j, $uip) = (undef, undef, undef, undef);
  36. my ($ucidr) = 0;
  37. my ($network, $bits, $netmask, $broadcast, $low, $high);
  38. if ($rawinput =~ qr/(.*)\/(.*)/){
  39. $lhs = $1; $rhs = $2;
  40. }else{
  41. die "Input: $rawinput not expected.\n";
  42. };
  43. #
  44. # Handle ip/hostname for left hand side.
  45. if ($lhs =~ qr/(\d+)\.(\d+)\.(\d+)\.(\d+)/){
  46. foreach my $dotted (($1,$2,$3,$4)){
  47. if (($dotted > 255) or ($dotted < 0)){
  48. die "FATAL: ipv4 address entered, $lhs entered is impossible, $dotted is not between 0-255.\n";
  49. };
  50. };
  51. $uip = inet_ntoa(scalar gethostbyname($lhs));
  52. die "FATAL: Cannot determine hostname for $lhs$!\n" if (!defined($lhs));
  53. }elsif ($lhs =~ $fqdn_regexp){
  54. my $tmp = gethostbyname($lhs);
  55. die "FATAL: Cannot determine ip for $lhs" if (!defined($tmp));
  56. $uip = inet_ntoa($tmp);
  57. }else{
  58. die "FATAL: host value not fully qualified, or not an ip <$lhs>\n";
  59. };
  60. #
  61. # Handle the netmask/cidr for the right hand side,
  62. #
  63. # All input netmasks are converted to a cidr address for notation
  64. if ($rhs =~ qr/^(\d+)$/){ # /cidr
  65. $ucidr = $1;
  66. die "FATAL: Invalid CIDR <$ucidr>.$!\n" if (($ucidr > 32) or ($ucidr < 0));
  67. }elsif ($rhs =~ qr/(0[xX])?([0-9,a-f,A-F]{7})/){ # /0xhexnetmask
  68. my $trimmed = $2;
  69. my $insane = 0;
  70. foreach my $byte (split('', unpack("B32", pack("H*", $trimmed)))){
  71. ($byte) ? $ucidr++ : $insane++;
  72. die "FATAL: $rhs is not a valid hex netmask.$!\n" if ($insane and $byte);
  73. };
  74. }elsif ($rhs =~ qr/(\d+)\.(\d+)\.(\d+)\.(\d+)/){ # /255.255.255.0 form
  75. my @a = ($1, $2, $3, $4);
  76. my $insane = 0;
  77. foreach my $t (@a){
  78. die "FATAL: Netmask out of range. Input <$rhs> Invalid <$t>$!\n" if (($t < 0) or ($t > 255));
  79. };
  80. foreach my $byte (split('', unpack("B32", pack("C4", @a)))){
  81. ($byte) ? $ucidr++ : $insane++;
  82. die "FATAL: $rhs is not a valid netmask.$!\n" if ($insane and $byte);
  83. };
  84. }else{
  85. die "FATAL: Unknown or invalid netmask value entered. <$rhs>\n";
  86. };
  87. #
  88. # Network math GO! This is the meat of the function.
  89. my (@uip) = split(/\./, $uip);
  90. $network = 0;
  91. for ($j = 0; $j <= $#uip; $j++){
  92. $network += int($uip[$j])<<((3-$j)*8);
  93. };
  94. $bits = 0; $j = 0;
  95. for ($j = 31 - $ucidr; $j >= 0; $j--){
  96. $bits |= 1<<$j;
  97. };
  98. $netmask = 0xffffffff^$bits;
  99. $low = ($network&$netmask);
  100. $high = ($network&$netmask)+$bits-1;
  101. $broadcast = ($network&$netmask)|$bits;
  102. my ($guessed_hostname,undef,undef,undef,undef) = gethostbyaddr(inet_aton($uip), AF_INET);
  103. #
  104. # Throw the info back, they get a hash with zie info they may/may not need.
  105. # All up to the caller what they want to use.
  106. #
  107. return ("inet4" => $uip,
  108. "netmask" => int2ip($netmask),
  109. "broadcast" => int2ip($broadcast),
  110. "cidr" => $ucidr,
  111. "router" => int2ip($low+1),
  112. "network" => int2ip($low),
  113. "high" => int2ip($high),
  114. "hostname" => $guessed_hostname,
  115. );
  116. };
  117. #package Main; # future use
  118. foreach my $arg (@ARGV){
  119. my %stuff = cidr2raw($arg);
  120. printf("%s/%s is %s/%s\n%-12s\t%s\n%-12s\t%s\n%-12s\t%s\n%-12s\t%s\n%-12s\t%s\n",
  121. $stuff{"inet4"},$stuff{"cidr"},
  122. $stuff{"network"},$stuff{"cidr"},
  123. "Netmask",$stuff{"netmask"},
  124. "Broadcast",$stuff{"broadcast"},
  125. "Network",$stuff{"network"},
  126. "Router",$stuff{"router"},
  127. "HighUsable",$stuff{"high"},
  128. );
  129. };