Kodama's home / tips.

ネット上のマシンの ハ−ドウエアアドレス一覧を作る

IP-address と ハ−ドウエアアドレスの対応表を作りたい. アイデアとしてはマシンに ping してから, arp コマンドで arp キャッシュを見る. 当然だけど, ル−タ−を越えた所の MACアドレス(HW-address) はこれでは分からない. それと, 自分自身も. 自分の MACアドレス(HW-address) を知るには ifconfig を使う.

作ったリストは arp.list とでもしてファイルに取っておく. cron で定期的に動かしても good.

手抜きでありあわせの arp コマンドを使ったけど, ほんとは, パケットをモニタするだけで, 分かるはずだよね.

#!/bin/bash
## etherlist.sh
## scan ether address
# K.Kodama 1999-04
# format:  ip-address  host_name ether-address

### definitions ###
net="10"
broadcast="10.255.255.255"
PATH="/usr/bin:/bin:/usr/sbin:/sbin"

# IP-address/Ether-address list file
list="/root/arp.list"

# work file
wfile="/tmp/`basename $0`.$$"
###################

# ether address list の統計を表示 
function arp.count(){
echo From IP/Ether address list $list:
echo '(# of hosts)=' `wc -l <$list`
echo '(# of ARP-known hosts)=' `grep -v unknown $list|wc -l`
echo '(# of ARP-unknown hosts)=' `grep unknown $list|wc -l`
echo '(# of hosts of noname)=' `grep noname $list|wc -l`
}

# merge list and sort by ip-address
function merge.list(){
gawk '{ # e[ip-address]=ether-address, n[ip-address]=name
	if((!($1 in e))||($3!="unknown")){e[$1]=$3}
	if((!($1 in n))||($2!="noname")){n[$1]=$2}
	}
END{for(i in e){print i" "n[i]" "e[i]}}' | sort -nt '.' +0 -1 +1 -2 +2 -3 +3
}

# /etc/hosts から引用
function eth.hosts(){
grep "^$net\." /etc/hosts | gawk '{sub(/\..*/,"",$2);print $1" "$2" unknown"}'
}

# broadcast ping で hosts に無いマシンも引っかかるかも.
function eth.broadcast(){
ping -nc3 $broadcast|gawk '$3~/from/{sub(/:/,"");print $4" noname unknown"}'|sort|uniq
}

# ARPキャッシュを引く.
# ether-address が不明の場合 00:00:00:00 か incomplete を表示する
# 例: arp -na の結果 2種.
# ? (10.2.1.8) at 00:E0:18:A8:14:BC [ether] on eth0
# 10.30.12.10  ether  00:90:CC:A2:22:AF  C  *  eth0
function eth.arp(){
arp -an | gawk '
  /^?/{gsub(/\(|\)/," ");print $2" noname "$4;next}
  /^[0-9]/{print $1" noname "$3;next}
' | grep -v '00:00:00:00:00:00'| grep -v 'incomplete'
}

# ping をかけて arp キャッシュに載せる
function eth.ping(){
gawk '{system("ping -nc1 "$1" >/dev/null 2>/dev/null &")}'
}


if [ ! -f $list ];then touch $list;fi

# broadcast と /etc/hosts で拡充. 優先順位に注意
(eth.broadcast;cat $list;eth.hosts)|merge.list > $wfile && cp $wfile $list

# eth.broadcast | eth.ping
grep unknown $list | eth.ping
# cat $list | eth.ping

sleep 10
(cat $list;eth.arp)|merge.list > $wfile && cp $wfile $list
rm $wfile
# end of script.


Kodama's home / tips.