#!/bin/bash

##
## NOTE: this is in the "works for me" state. Tested in OS X 10.6 and CentOS 5.5
##       any feeback: jullrich@sans.edu
## 
## quick overview:
##   this script will use multicast pings to find IPv6 devices, then
##   it will check all of your IPv4 devices to see if they are dual 
##   stack. To find the IPv6 address of dual stack devices the script
##   will first figure out the MAC address and then try to ping the
##   EUI-64 derived link local address. 
##   This will only work on you local subnet
##
##   TODO: Right now this assumes you are using a /24 IPv4 subnet.
##
##   PGP signature can be found at ipv6finder.asc (same location as this file)
#
#  Lets get the default interface
# 


if uname -a | grep -q Darwin; then
  OS=MAC
else
  OS=LINUX
fi
echo
echo Operating System: $OS
echo
IFCONFIG=/sbin/ifconfig
if [ "$OS" == "LINUX" ]; then
ARPING=/sbin/arping            # LINUX
else 
ARPING=/opt/local/bin/arping   # Mac
fi
ARP="/sbin/arp -an"

default=`netstat -nr | egrep '(default)|(^0.0.0.0)' | awk '{print $NF}' | head -1`
#
# or we can specify an interface name on the command line
#
if [ "$1" != "" ]; then
  if=$1
else
  if=$default
fi



#
# we need an IPv6 address on the interface. Otherwise, this script
# does not make sense.

if ! $IFCONFIG $if | grep -q inet6 ; then
  echo "No IPv6 Support. This script needs IPv6 support on $if to work."
  exit
fi
#
# and we need the IPv4 address later.
ip4addr=`$IFCONFIG $if | grep 'inet ' | awk '{print $2}' | sed 's/.*://'`
#
# first we send a "ping" to ff02::1, which corresponds to "all hosts"
# this should give us a good list of hosts.
#
echo "Interface: $if (IPv4 $ip4addr)"
echo "---"
echo " Devices responding to All Hosts multicast (ff02::1)"
echo 
ping6 -I $if -c3 ff02::1 | cut -f4 -d' ' | cut -f1 -d'%' | sed -e 's/:$//' | sort -u | grep 'fe80::'
#
# next we check for mDNS responses. For example, OS X systems usually respond
# as well as some unix systems (with Avahi running).
#
echo "---"
echo " Devices responding to All DNS Servers multicast (ff02::fb)"
echo
ping6 -I $if -c3 ff02::fb | cut -f4 -d' ' | cut -f1 -d'%' | sed -e 's/:$//' | sort -u | grep 'fe80::'
#
# and finally we are looking for routers. You need at least one for
# global IPv6 access
#
echo "---"
echo " Devices responding to All Routers multicast (ff02::2)"
echo
ping6 -I $if -c3 ff02::2 | cut -f4 -d' ' | cut -f1 -d'%' | sed -e 's/:$//' | sort -u | grep 'fe80::'
echo "---"
net=`echo $ip4addr | cut -f1-3 -d'.'`
echo Scanning Network $net.0/24
echo   "(if you are not running as root, you will be prompted for your password by sudo)"
echo 
for b in {1..254}; do
  if [ "$OS" == "LINUX" ] ; then    
  mac=`sudo $ARPING -c3 -I $if $net.$b | egrep '(bytes from)|(Unicast reply from)' | tail -1 | cut -f5 -d' ' | tr -d '\[\]'`
  else 
  mac=`sudo $ARPING -c3 -I $if $net.$b | egrep '(bytes from)|(Unicast reply from)' | tail -1 | cut -f4 -d' ' | tr -d '\[\]'`
  fi
  if echo $mac | grep -q ':' ; then
     echo $net.$b $mac

     if echo $mac | grep -q '^.0:' ; then
       nmac=`echo $mac | sed -e 's/^\(.\)0:\(.*\)/\12:\2/'`
     elif echo $mac | grep -q '^.1:' ; then
       nmac=`echo $mac | sed -e 's/^\(.\)3:\(.*\)/\12:\2/'`
     elif echo $mac | grep -q '^.4:' ; then
       nmac=`echo $mac | sed -e 's/^\(.\)4:\(.*\)/\16:\2/'` 
     elif echo $mac | grep -q '^.5:' ; then 
       nmac=`echo $mac | sed -e 's/^\(.\)5:\(.*\)/\17:\2/'` 
     elif echo $mac | grep -q '^.8:' ; then 
       nmac=`echo $mac | sed -e 's/^\(.\)8:\(.*\)/\1a:\2/'` 
     elif echo $mac | grep -q '^.c:' ; then 
       nmac=`echo $mac | sed -e 's/^\(.\)c:\(.*\)/\1e:\2/'` 
     elif echo $mac | grep -q '^.d:' ; then 
       nmac=`echo $mac | sed -e 's/^\(.\)d:\(.*\)/\1f:\2/'` 
     else
       echo $mac
       exit;
     fi
     mac1=`echo $nmac | cut -f-3 -d':' | sed 's/://' `
     mac2=`echo $nmac | cut -f4,5,6 -d':' | sed -e 's/:\(..\)$/\1/'`
     byteorder='ff:fe'
     ipv6addr="fe80::$mac1$byteorder$mac2"
     if ping6 -c3 -I $if $ipv6addr | grep -q 'bytes from'; then 
       echo  "$ipv6addr (same host as $net.$b) " 
     else
       echo  "no ipv6 for $net.$b MAC $mac IPv6 $ipv6addr" 
     fi
  fi
done

