#!/usr/bin/perl

use Packet::Definitions;
my @flags =qw/UP BROADCAST DEBUG LOOPBACK POINTOPOINT SMART RUNNING NOARP PROMISC ALLMULTI OACTIVE SIMPLEX LINK0 LINK1 LINK2 
ALTPHYS MULTICAST/;
$iffbits = "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" .
"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" .
"\20MULTICAST\0";

  my $len = pack('I', 0);
  my @mib = (
        &Packet::Definitions::CTL_NET,
        &Packet::Definitions::AF_ROUTE,
        0,
        &Packet::Definitions::AF_LINK,
        &Packet::Definitions::NET_RT_IFLIST,
        0
  );
  my $mib = pack('iiiiii', @mib);
  if (syscall(&Packet::Definitions::SYS___sysctl, $mib, 6, 0, $len, 0, 0) == -1) {
    return 0;
  }

  my $buf = pack('a' . unpack('I', $len), '');
  if (syscall(&Packet::Definitions::SYS___sysctl, $mib, 6, $buf, $len, 0, 0) == -1) {
    return 0;
  }
 
  my $tlen = unpack('I', $len);
  $buf =~ /(.*?)(\w{2,5}\d{1})/;
  my $val = (length($1) - 5);
  my ($msglen, $nlen, $dv);
  for (my $i = 0; $i < $tlen; $i += $msglen) {
   ($msglen, $nlen, $dv) = unpack("S x$val C x2 a12", substr($buf, $i));
   my %ifr = %{&Packet::Definitions::unp_ifreq(substr($buf, $i, $msglen))};
   my %ifm = %{&Packet::Definitions::unp_if_msghdr(substr($buf, $i, $msglen))};
   my $devname = sprintf("%s", substr($dv, 0, $nlen));
   my $mac = sprintf("%x:%x:%x:%x:%x:%x", unpack('CCCCCC', substr($dv, $nlen, 6)));
   print "$ifr{ifr_name}: ";
   printb("flags", $ifm{ifm_flags}, $iffbits);
   if ($ifm{ifm_data}{ifi_metric}) { printf(" mtu %ld", $ifm{ifm_data}{ifi_metric}); }
#   if ($ifm{ifm_data}{ifi_metric}) { printf(" mtu %ld", $ifm{ifm_data}{ifi_mtu}); }
   print "\n";


  }


sub printb {
 my ($s, $v, $bits) = @_;
 my $i;
 my $any = 0;
 my $c;
 my @bits = split(//, $bits);
 $bits = 0;
 if (@bits && @bits == 8) {
  printf("%s=%o", $s, $v);   
 }
 else {
  printf("%s=%x", $s, $v);
 }
 $bits++;
 if (@bits) {
  print "<";
  while (($i = $bits[$bits++]) ne "\0") {
   if ($v & (1 << (ord($i)-1))) {
    if ($any) {
     print ",";
    }
    $any = 1;
    for (; ord($c = $bits[$bits]) > 32; $bits++) {
     print $c;
    }
   }
   else {
    for (; ord($bits[$bits]) > 32; $bits++) { }
   }
  }
  print ">";
 }
}

__DATA__
dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	inet 63.199.194.66 netmask 0xfffffff8 broadcast 255.255.255.248
	inet6 fe80::2c0:f0ff:fe49:d8a0%dc0 prefixlen 64 scopeid 0x1 
	ether 00:c0:f0:49:d8:a0 
	media: Ethernet autoselect (10baseT/UTP)
	status: active
lp0: flags=8810<POINTOPOINT,SIMPLEX,MULTICAST> mtu 1500
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
	inet6 ::1 prefixlen 128 
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 
	inet 127.0.0.1 netmask 0xff000000 
	inet 127.0.0.2 netmask 0xff000000 
	inet 127.0.0.3 netmask 0xff000000 
	inet 127.0.0.4 netmask 0xff000000 
	inet 127.0.0.5 netmask 0xff000000 
	inet 127.0.0.6 netmask 0xff000000 
ppp0: flags=8010<POINTOPOINT,MULTICAST> mtu 1500
sl0: flags=c010<POINTOPOINT,LINK2,MULTICAST> mtu 552
faith0: flags=8002<BROADCAST,MULTICAST> mtu 1500
