You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

210 regels
5.7 KiB

  1. #!/usr/bin/env perl
  2. #
  3. # Because ifconfig output is... overly verbose.
  4. #
  5. # Output information from ifconfig -a like so:
  6. # interface:mtu ipv4/cidr mac_address ipv6_addr(if applicable)
  7. # ipv6 is not yet in place due to a: lazy, b: can't use it yet.
  8. #
  9. use strict;
  10. use Socket;
  11. use Sys::Hostname;
  12. $ENV{'PATH'}='/sbin:/usr/sbin:/bin:/usr/bin';
  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 = "$1.$2.$3.$4";
  52. };
  53. #
  54. # Handle the netmask/cidr for the right hand side,
  55. #
  56. # All input netmasks are converted to a cidr address for notation
  57. if ($rhs =~ qr/^(\d+)$/){ # /cidr
  58. $ucidr = $1;
  59. die "FATAL: Invalid CIDR <$ucidr>.$!\n" if (($ucidr > 32) or ($ucidr < 0));
  60. }elsif ($rhs =~ qr/(0[xX])?([0-9,a-f,A-F]{7})/){ # /0xhexnetmask
  61. my $trimmed = $2;
  62. my $insane = 0;
  63. foreach my $byte (split('', unpack("B32", pack("H*", $trimmed)))){
  64. ($byte) ? $ucidr++ : $insane++;
  65. die "FATAL: $rhs is not a valid hex netmask.$!\n" if ($insane and $byte);
  66. };
  67. }elsif ($rhs =~ qr/(\d+)\.(\d+)\.(\d+)\.(\d+)/){ # /255.255.255.0 form
  68. my @a = ($1, $2, $3, $4);
  69. my $insane = 0;
  70. foreach my $t (@a){
  71. die "FATAL: Netmask out of range. Input <$rhs> Invalid <$t>$!\n" if (($t < 0) or ($t > 255));
  72. };
  73. foreach my $byte (split('', unpack("B32", pack("C4", @a)))){
  74. ($byte) ? $ucidr++ : $insane++;
  75. die "FATAL: $rhs is not a valid netmask.$!\n" if ($insane and $byte);
  76. };
  77. }else{
  78. die "FATAL: Unknown or invalid netmask value entered. <$rhs>\n";
  79. };
  80. #
  81. # Network math GO! This is the meat of the function.
  82. my (@uip) = split(/\./, $uip);
  83. $network = 0;
  84. for ($j = 0; $j <= $#uip; $j++){
  85. $network += int($uip[$j])<<((3-$j)*8);
  86. };
  87. $bits = 0; $j = 0;
  88. for ($j = 31 - $ucidr; $j >= 0; $j--){
  89. $bits |= 1<<$j;
  90. };
  91. $netmask = 0xffffffff^$bits;
  92. $low = ($network&$netmask);
  93. $high = ($network&$netmask)+$bits-1;
  94. $broadcast = ($network&$netmask)|$bits;
  95. #
  96. # Throw the info back, they get a hash with zie info they may/may not need.
  97. # All up to the caller what they want to use.
  98. #
  99. return ("inet4" => $uip,
  100. "netmask" => int2ip($netmask),
  101. "broadcast" => int2ip($broadcast),
  102. "cidr" => $ucidr,
  103. "router" => int2ip($low+1),
  104. "network" => int2ip($low),
  105. "high" => int2ip($high),
  106. );
  107. };
  108. my @ifout;
  109. if ($ENV{'TESTING'} ne '') {
  110. while(<>){
  111. chomp($_);
  112. last if ($_ eq '');
  113. push(@ifout, $_);
  114. # sleep 1;
  115. # print STDERR $_ . "\n";
  116. }
  117. }else{
  118. open IFCONFIG, "ifconfig -a |";
  119. @ifout = <IFCONFIG>;
  120. close IFCONFIG;
  121. }
  122. # This seems wrong but it makes parsing easier due to solaris
  123. # non root ifconfig not displaying the mac address. Reverse the output.
  124. #
  125. @ifout = reverse(@ifout);
  126. my @output = ();
  127. my ($ifname, $ifether, $ifmtu, $ifipv4, $ifnetmask, $ifipv6) = (undef,undef,undef,undef,undef,undef);
  128. sub printiface{
  129. # assume a /32 if we don't know it
  130. unless (defined($ifnetmask)) {
  131. warn "$ifname has indeterminant netmask assuming /32\n";
  132. $ifnetmask = '32';
  133. }
  134. unless (defined($ifnetmask)) {
  135. $ifether = 'unknown';
  136. }
  137. unless ($ifname =~ m/lo.*/){
  138. my %netinfo = cidr2raw("$ifipv4\/$ifnetmask");
  139. $ifnetmask = $netinfo{"cidr"};
  140. $ifether = lc($ifether);
  141. my $line = sprintf "%-16s %-18s %-17s\n", "$ifname\@$ifmtu", "$ifipv4\/$ifnetmask", $ifether;
  142. push @output, $line;
  143. }
  144. # reset vars
  145. ($ifname, $ifether, $ifmtu, $ifipv4, $ifnetmask, $ifipv6) = (undef,undef,undef,undef,undef,undef);
  146. };
  147. foreach my $line (@ifout) {
  148. if ($line =~ /inet\s+(\d+[.]\d+[.]\d+[.]\d+)\s+/){
  149. $ifipv4 = $1;
  150. }
  151. if ($line =~ m/ether\s([:,0-9,a-f,A-F]{11,})/){
  152. $ifether =$1;
  153. }
  154. if ($line =~ m/^([\w,\:\d+]+)\s+.*HWaddr\s([:,0-9,a-f,A-F]{11,})/){
  155. $ifname = $1;
  156. $ifether = $2;
  157. }
  158. if ($line =~ m/^(.*)\:\s+.*mtu\s(\d+)/){
  159. $ifname = $1;
  160. $ifmtu = $2;
  161. }
  162. if ($line =~ m/MTU[:](\d+)/){
  163. $ifmtu = $1;
  164. }
  165. if ($line =~ m/inet\saddr\:(\d+[.]\d+[.]\d+[.]\d+)/){
  166. $ifipv4 = $1;
  167. }
  168. if ($line =~ m/netmask\s+(0[xX])?([a-f,A-F,0-9]{8})/){
  169. $ifnetmask = $2;
  170. }
  171. if ($line =~ m/Mask[:](\d+\.\d+\.\d+\.\d+)/){
  172. $ifnetmask = $1;
  173. }
  174. if ($line =~ m/netmask\s+(\d+[.]\d+[.]\d+[.]\d+)/){
  175. $ifnetmask = $1;
  176. }
  177. if ($line =~ m/netmask\s+0\s+broadcast/){
  178. $ifnetmask = '0';
  179. }
  180. print ":$ifether:$ifname:$ifmtu:$ifipv4:$ifnetmask:$ifipv6:\n" if ($ENV{'DEBUG'} ne '');
  181. printiface() if ($ifname and $ifmtu and $ifipv4 );
  182. };
  183. if (scalar(@output) < 1){
  184. warn "No interfaces? Scripts busted yo.\n";
  185. }else{
  186. foreach my $line (reverse(@output)){
  187. print $line;
  188. }
  189. }