#!/usr/bin/perl use Sys::Hostname; use Socket; use Getopt::Long; GetOptions("1" => \$ssh1, "2" => \$ssh2); $ssh1 = ! $ssh2; $nf = $ssh1 ? 3 : 2; sub getkey { my $file = shift; for $dir (qw(/etc/ssh /etc /usr/local/etc)) { if (open HOSTKEY, "$dir/$file") { local $_ = ; close HOSTKEY; return join(" ", (split ' ', $_, $nf + 1)[0 .. $nf - 1]) . "\n"; } } return undef; } for $file ($ssh1 ? ("ssh_host_key.pub") : ("ssh_host_dsa_key.pub", "ssh_host_rsa_key.pub")) { my $hostkey = getkey $file; push @hostkeys, $hostkey if defined $hostkey; } sub _SYS_SOCKET_H () { 1; } sub _SYS_TYPES_H () { 1; } sub BSD_COMP () { 1; } # for Solaris BEGIN { eval { require "sys/ioctl.ph"; }; defined &SIOCGIFCONF or *SIOCGIFCONF = sub () { 0x8912; }; eval { require "net/if.ph"; }; defined &IFNAMSIZ or *IFNAMSIZ = sub () { 16; }; } sub sizeof_struct_sockaddr () { 16; } sub sizeof_struct_ifreq () { IFNAMSIZ + sizeof_struct_sockaddr; } sub pat_struct_ifreq () { sprintf "a%d a%d", IFNAMSIZ, sizeof_struct_sockaddr; } # for *.ph %sizeof = ('struct ifconf' => length pack("ip", 0, ""), 'struct ifreq' => sizeof_struct_ifreq, 'struct sockaddr' => sizeof_struct_sockaddr); BEGIN { *sizeof_addr_ifreq = defined &_SIZEOF_ADDR_IFREQ ? sub ($) { my $sa = shift; my $len = unpack "C", $sa; $len > sizeof_struct_sockaddr ? IFNAMSIZ + $len : sizeof_struct_ifreq; } : sub ($) { sizeof_struct_ifreq; }; } socket S, PF_INET, SOCK_DGRAM, 0; $bufsiz = 256; $ifreq = pack "\@$bufsiz"; $ifc = pack "ip", $bufsiz, $ifreq; if (ioctl S, SIOCGIFCONF, $ifc) { close S; ($ifc_len) = unpack "i", $ifc; for (my $i = 0; $i < $ifc_len; $i += sizeof_addr_ifreq($ifr_addr)) { ($ifr_name, $ifr_addr) = unpack pat_struct_ifreq, substr $ifreq, $i, sizeof_struct_ifreq; ($sin_port, $sin_addr) = eval { sockaddr_in $ifr_addr; } or next; unless ($sin_addr eq INADDR_LOOPBACK) { push @addrs, $sin_addr ; push @names, (gethostbyaddr $sin_addr, AF_INET)[0]; } } } unless (@addrs) { ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname hostname; @names = ($name); } ($shortname) = hostname =~ /^([^.]+)/; @addrs = sort @addrs; $addr = $addrs[0]; $hostnames = join(",", map(inet_ntoa($_), @addrs), $shortname, @names); @entries = map "$hostnames $_", @hostkeys; while (<>) { if (defined @entries) { $cur = inet_aton((/^([^,\s]+)/)[0]); if ($cur eq $addr) { next; } elsif ($cur gt $addr) { print @entries; undef @entries; } } print; } if (defined @entries) { print @entries; }