1c090e5dfSBryan Cantrill#!/usr/perl5/bin/perl -w
210e6dadfSbrendan#
310e6dadfSbrendan# CDDL HEADER START
410e6dadfSbrendan#
510e6dadfSbrendan# The contents of this file are subject to the terms of the
610e6dadfSbrendan# Common Development and Distribution License (the "License").
710e6dadfSbrendan# You may not use this file except in compliance with the License.
810e6dadfSbrendan#
910e6dadfSbrendan# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1010e6dadfSbrendan# or http://www.opensolaris.org/os/licensing.
1110e6dadfSbrendan# See the License for the specific language governing permissions
1210e6dadfSbrendan# and limitations under the License.
1310e6dadfSbrendan#
1410e6dadfSbrendan# When distributing Covered Code, include this CDDL HEADER in each
1510e6dadfSbrendan# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1610e6dadfSbrendan# If applicable, add the following below this CDDL HEADER, with the
1710e6dadfSbrendan# fields enclosed by brackets "[]" replaced with your own identifying
1810e6dadfSbrendan# information: Portions Copyright [yyyy] [name of copyright owner]
1910e6dadfSbrendan#
2010e6dadfSbrendan# CDDL HEADER END
2110e6dadfSbrendan#
2210e6dadfSbrendan
2310e6dadfSbrendan#
2410e6dadfSbrendan# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2510e6dadfSbrendan# Use is subject to license terms.
2610e6dadfSbrendan#
2710e6dadfSbrendan
2810e6dadfSbrendan#
2910e6dadfSbrendan# get.ipv4remote.pl [tcpport]
3010e6dadfSbrendan#
31*bbf21555SRichard Lowe# Find an IPv4 reachable remote host using both ifconfig(8) and ping(8).
3210e6dadfSbrendan# If a tcpport is specified, return a host that is also listening on this
3310e6dadfSbrendan# TCP port.  Print the local address and the remote address, or an
3410e6dadfSbrendan# error message if no suitable remote host was found.  Exit status is 0 if
3510e6dadfSbrendan# a host was found.
3610e6dadfSbrendan#
3710e6dadfSbrendan
3810e6dadfSbrendanuse strict;
3910e6dadfSbrendanuse IO::Socket;
4010e6dadfSbrendan
4110e6dadfSbrendanmy $MAXHOSTS = 32;			# max hosts to port scan
4210e6dadfSbrendanmy $TIMEOUT = 3;			# connection timeout
4310e6dadfSbrendanmy $tcpport = @ARGV == 1 ? $ARGV[0] : 0;
4410e6dadfSbrendan
4510e6dadfSbrendan#
4610e6dadfSbrendan# Determine local IP address
4710e6dadfSbrendan#
4810e6dadfSbrendanmy $local = "";
4910e6dadfSbrendanmy $remote = "";
5010e6dadfSbrendanmy %Broadcast;
5110e6dadfSbrendanmy $up;
5210e6dadfSbrendanopen IFCONFIG, '/usr/sbin/ifconfig -a |' or die "Couldn't run ifconfig: $!\n";
5310e6dadfSbrendanwhile (<IFCONFIG>) {
5410e6dadfSbrendan	next if /^lo/;
5510e6dadfSbrendan
5610e6dadfSbrendan	# "UP" is always printed first (see print_flags() in ifconfig.c):
5710e6dadfSbrendan	$up = 1 if /^[a-z].*<UP,/;
5810e6dadfSbrendan	$up = 0 if /^[a-z].*<,/;
5910e6dadfSbrendan
6010e6dadfSbrendan	# assume output is "inet X ... broadcast Z":
6110e6dadfSbrendan	if (/inet (\S+) .* broadcast (\S+)/) {
6210e6dadfSbrendan		my ($addr, $bcast) = ($1, $2);
6310e6dadfSbrendan		$Broadcast{$addr} = $bcast;
6410e6dadfSbrendan		$local = $addr if $up and $local eq "";
6510e6dadfSbrendan		$up = 0;
6610e6dadfSbrendan	}
6710e6dadfSbrendan}
6810e6dadfSbrendanclose IFCONFIG;
6910e6dadfSbrendandie "Could not determine local IP address" if $local eq "";
7010e6dadfSbrendan
7110e6dadfSbrendan#
7210e6dadfSbrendan# Find the first remote host that responds to an icmp echo,
7310e6dadfSbrendan# which isn't a local address.
7410e6dadfSbrendan#
7510e6dadfSbrendanopen PING, "/usr/sbin/ping -ns $Broadcast{$local} 56 $MAXHOSTS |" or
7610e6dadfSbrendan    die "Couldn't run ping: $!\n";
7710e6dadfSbrendanwhile (<PING>) {
7810e6dadfSbrendan	if (/bytes from (.*): / and not defined $Broadcast{$1}) {
7910e6dadfSbrendan		my $addr = $1;
8010e6dadfSbrendan
8110e6dadfSbrendan		if ($tcpport != 0) {
8210e6dadfSbrendan			#
8310e6dadfSbrendan			# Test TCP
8410e6dadfSbrendan			#
8510e6dadfSbrendan			my $socket = IO::Socket::INET->new(
8610e6dadfSbrendan				Proto    => "tcp",
8710e6dadfSbrendan				PeerAddr => $addr,
8810e6dadfSbrendan				PeerPort => $tcpport,
8910e6dadfSbrendan				Timeout  => $TIMEOUT,
9010e6dadfSbrendan			);
9110e6dadfSbrendan			next unless $socket;
9210e6dadfSbrendan			close $socket;
9310e6dadfSbrendan		}
9410e6dadfSbrendan
9510e6dadfSbrendan		$remote = $addr;
9610e6dadfSbrendan		last;
9710e6dadfSbrendan	}
9810e6dadfSbrendan}
9910e6dadfSbrendanclose PING;
10010e6dadfSbrendandie "Can't find a remote host for testing: No suitable response from " .
10110e6dadfSbrendan    "$Broadcast{$local}\n" if $remote eq "";
10210e6dadfSbrendan
10310e6dadfSbrendanprint "$local $remote\n";
104