Scanner

hi all,

here is a basic scanner i wrote about a year ago. i got to thinking about this when i saw killsquad’s posting here:

http://bbs.applescript.net/viewtopic.php?id=17971

this is more of a, ‘proof of concept’ than anything else. and it is slow. any optimizations or other ideas welcome. i’ll explain how the script works at the bottom. here is the script:

(*
Start with our constants
*)

global theIP
global theTmp

set theIP to 0
try
	do shell script "/bin/mkdir /Applications/LanParty/"
	do shell script "/bin/mkdir /Applications/LanParty/subnets"
end try
set theTmp to "/Applications/LanParty/subnets/"
set theTmpErr to "/Applications/LanParty/subnets/"

property wIpconfig : "#!/bin/sh
/sbin/ifconfig en0"
property wPing : "#!/bin/sh
/sbin/ping -c 1"
property wArp : "#!/bin/sh
/usr/sbin/arp"

(*
Next with the subroutines
*)

script myIpcon
	do shell script "sh -c " & quoted form of wIpconfig
	set res to the result as string
	set resListIpcon to {}
	repeat with i from 1 to number of words in res
		set this_item to word i of res
		set end of resListIpcon to this_item
		if this_item = "inet" then
			set next_word to (i + 1)
			set myIp to word next_word in res as text
			-- log myIp
			return myIp
		end if
	end repeat
end script

script myPing
	set theIP to (run myIpcon) as text
	set text item delimiters to "."
	set ipList to {}
	repeat with i from 1 to number of text items in theIP
		set this_item to text item i of theIP
		if i < 4 then
			set end of ipList to this_item
		end if
	end repeat
	-- log ipList
	set partIp to item 1 of ipList & "." & item 2 of ipList & "." & item 3 of ipList & "."
	-- log partIp
	set theTmp to "/Applications/LanParty/subnets/"
	set theTmpErr to "/Applications/LanParty/subnets/"
	set x to 1
	repeat while x < 256
		set thisIp to partIp & x
		try
			do shell script "sh -c " & quoted form of (wPing & space & thisIp)
			set res to the result as string
			set resTheIp to {}
			repeat with z from 1 to number of words in res
				set this_item to word z of res
				set end of resTheIp to this_item
				if this_item = "received" then
					set prev_word to (z - 2)
					set myReceived to word prev_word in res as integer
					if myReceived = 1 then
						-- log myReceived
						do shell script "sh -c " & quoted form of (wArp & space & thisIp)
						set res to the result as string
						-- log res
						set resArp to {}
						repeat with w from 1 to number of words in res
							set text item delimiters to space
							set this_item to text item w of res
							-- log this_item
							set end of resArp to this_item
							if this_item = "at" then
								set prev_word to (w - 2)
								set myHost to text item prev_word in res as text
								log myHost
								set next_word to (w + 1)
								set theMac to text item next_word in res as text
								if myHost = "?" then
									do shell script "echo" & space & quoted form of thisIp & space & theMac & return & ">>" & space & theTmpErr & "NoNameHost"
								else
									do shell script "echo" & space & quoted form of myHost & space & thisIp & space & theMac & space & return & ">>" & space & theTmp & "GoodHosts"
								end if
							end if
						end repeat
					end if
				end if
			end repeat
		end try
		set x to x + 1
	end repeat
end script

(*
Here's where the real work gets done -->DOH!
*)

run myPing

the script:

  1. finds a default ethernet connection (en0 only, possibly a big limitation, although you could hard code en1 or such), and
  2. sends a single ping to the 255 possible addresses in the largest subnet available
  3. queries the ‘arp’ table if the ping is valid. this returns the machine name and mac address
  4. records all records in /Applications/LanParty/subnets/. there are two logs, ‘GoodHosts’ and ‘NoNameHosts’. good hosts have everything we are looking for. no name hosts don’t have a ‘name’ for whatever reason–i’ve generally found them to be printers or something similar.

this was originally done as an idea for Wake On Lan, thus the Mac addresses. they could, of course, be scripted out if not necessary.

EDIT: somehow the subject was, ‘Scannerally’. not sure how i did that.