LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-19-2006, 05:05 PM   #1
AnonyMooseUK
LQ Newbie
 
Registered: Oct 2006
Distribution: Red Hat 9 & Fedora FC5
Posts: 4

Rep: Reputation: 0
Scripting Help needed - IP Enumeration


Hi all,
Total site newbie, but been working on unix for 12 years, but is no longer my primary skillset, so getting rusty.

I am trying to create a bash script to enumerate a series of ip ranges, to individual IP addresses, so i can process them later.

For example; i want to be able to input a start IP and and end IP (using the usual $1 $2 script variables), i then want the script to list all the ip addresses one by one. So if i ran;

# myscript.sh 192.168.1.1 192.168.1.35

it would output;
192.168.10.1.1
192.168.10.1.2
192.168.10.1.3
192.168.10.1.5 ...... etc to .35

now i could work this out quite simply given some time, but the fact i then have to cater for more complex inputs, means i thought i had better ask for help here.

An complex example;
# myscript.sh 10.1.1.1 10.2.5.7

so would need all IP's between this range, so;
10.1.1.1
10.1.1.2
10.1.1.3 ..... etc until

10.1.1.254
10.1.2.1
10.1.2.2 ..... etc until

10.1.254.254
10.2.1.1
10.2.1.2 ...... etc until end


Hope you get the idea, i would appreciate any help on how to achieve this.

Thanks in Advance.
 
Old 10-19-2006, 05:37 PM   #2
tuxdev
Senior Member
 
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012

Rep: Reputation: 115Reputation: 115
So, essentially you want to convert the given IP addresses to their corresponding 32 bit integers, then loop through in between them and then convert the loop iterator back into IP addresses? I can't help you with the actual scripting because I don't bash that well, but I could probably code in C that program Real Quick (c).
 
Old 10-19-2006, 06:36 PM   #3
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
If you have Python

Code:
import socket, struct
start ='192.168.1.1'
end = '192.168.1.10'
startip = struct.unpack('>L',socket.inet_aton(start))[0]
endip = struct.unpack('>L',socket.inet_aton(end))[0]
while startip <= endip:
        print socket.inet_ntoa(struct.pack('>L',startip))
        startip += 1
output:
Code:
/home> python test.py
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10
 
Old 10-19-2006, 10:17 PM   #4
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
It's not elegant, but it works.

myscript.bash
Code:
#!/bin/bash

start_ip=$1
end_ip=$2

s_quartet[0]=$( echo ${start_ip} | cut -f 1 -d . )
s_quartet[1]=$( echo ${start_ip} | cut -f 2 -d . )
s_quartet[2]=$( echo ${start_ip} | cut -f 3 -d . )
s_quartet[3]=$( echo ${start_ip} | cut -f 4 -d . )

e_quartet[0]=$( echo ${end_ip} | cut -f 1 -d . )
e_quartet[1]=$( echo ${end_ip} | cut -f 2 -d . )
e_quartet[2]=$( echo ${end_ip} | cut -f 3 -d . )
e_quartet[3]=$( echo ${end_ip} | cut -f 4 -d . )

echo "Start IP: ${s_quartet[0]}.${s_quartet[1]}.${s_quartet[2]}.${s_quartet[3]}"
echo "End   IP: ${e_quartet[0]}.${e_quartet[1]}.${e_quartet[2]}.${e_quartet[3]}"

counter[0]=${s_quartet[0]}
while [ ${e_quartet[0]} -ge ${counter[0]} ]; do
  counter[1]=${s_quartet[1]}
  while [ ${e_quartet[1]} -ge ${counter[1]} ] ; do
    counter[2]=${s_quartet[2]}
    while [ ${e_quartet[2]} -ge ${counter[2]} ] ; do
      counter[3]=${s_quartet[3]}
      while [ ${e_quartet[3]} -ge ${counter[3]} ] ; do
        echo "${counter[0]}.${counter[1]}.${counter[2]}.${counter[3]}"
        let counter[3]=${counter[3]}+1
      done
      let counter[2]=${counter[2]}+1
    done
    let counter[1]=${counter[1]}+1
  done
  let counter[0]=${counter[0]}+1
done
Sample output
Code:
$ ./myscript.bash  10.0.0.1 10.1.2.3
Start IP: 10.0.0.1
End   IP: 10.1.2.3
10.0.0.1
10.0.0.2
10.0.0.3
10.0.1.1
10.0.1.2
10.0.1.3
10.0.2.1
10.0.2.2
10.0.2.3
10.1.0.1
10.1.0.2
10.1.0.3
10.1.1.1
10.1.1.2
10.1.1.3
10.1.2.1
10.1.2.2
10.1.2.3
 
Old 10-20-2006, 05:28 PM   #5
AnonyMooseUK
LQ Newbie
 
Registered: Oct 2006
Distribution: Red Hat 9 & Fedora FC5
Posts: 4

Original Poster
Rep: Reputation: 0
Dark Helmet - Doesnt quite work, as will only enumerate to the number stated in the end ip.

For example; if i do 10.1.1.1 to 10.1.2.50

it will then only do upto 50 for both 10.1.1.1[-50] and 10.1.2.[-50]

so it misses out the entire 10.1.1.51 to 10.1.1.254 range ....

nice try though. Anyone else?
 
Old 10-20-2006, 05:33 PM   #6
AnonyMooseUK
LQ Newbie
 
Registered: Oct 2006
Distribution: Red Hat 9 & Fedora FC5
Posts: 4

Original Poster
Rep: Reputation: 0
ghostdog74 - that works, but i have no python knowledge, so how would i then change it to allow the script to be run with the startip and endip variables passed on the command line; eg;

python script.py 10.1.1.1 10.1.2.45




thanks people
 
Old 10-20-2006, 06:14 PM   #7
homey
Senior Member
 
Registered: Oct 2003
Posts: 3,057

Rep: Reputation: 61
I took the liberty of editing a handy little scanmac script which a programming guru made for me many moons ago in another world.
Code:
#!/bin/bash
#Example: ./myscript 192.168.0.1 192.168.0.10

if [ -z "$1" -o "$1" == "-?" ] ; then
   echo "Usage: ./myscript starting-ip ending-ip"
   exit 0
fi

startw=$(echo "$1" | cut -d. -f1)
startx=$(echo "$1" | cut -d. -f2)
starty=$(echo "$1" | cut -d. -f3)
startz=$(echo "$1" | cut -d. -f4)

echo "Starting address: $startw.$startx.$starty.$startz"

end_ip="$2"

if [ -z "$end_ip" ] ; then
	if [ $startz -eq 255 ] ; then
		endz=0

		if [ $starty -eq 255 ] ; then
			endy=0

			if [ $startx -eq 255 ] ; then
				endx=0

				if [ $startw -eq 255 ] ; then
					echo "255.255.255.255 is not valid"
					exit 1
				else
					endw=$(($startw+1))
				fi
			else
				endx=$(($startx+1))
			fi
		else
			endy=$(($starty+1))
		fi
	else
		endz=$(($startz+1))
	fi

	end_ip="$endw.$endx.$endy.$endz"
fi

echo "Ending address: $end_ip"

currentw=$startw
currentx=$startx
currenty=$starty
currentz=$startz

currentip="$currentw.$currentx.$currenty.$currentz"

#if [ "$currentz" -ne "0" ] ; then
#   echo "$currentip"
#fi

trap "exit 15" 15
trap "exit 2" 2

while [ "$currentip" != "$end_ip" ] ; do
	currentip="$currentw.$currentx.$currenty.$currentz"

#	if [ "$currentz" -eq "0" ] ; then
#		echo "$currentip"
#	fi

	echo $currentip

	if [ $currentz -eq 255 ] ; then
		currentz=0
	else
		currentz=$(($currentz+1))
		continue
	fi

	if [ $currenty -eq 255 ] ; then
		currenty=0
	else
		currenty=$(($currenty+1))
		continue
	fi

	if [ $currentx -eq 255 ] ; then
		currentx=0
	else
		currentx=$(($currentx+1))
		continue
	fi

	if [ $currentw -eq 255 ] ; then
		break
	else
		currentz=$(($currentz+1))
		continue
	fi
done
Here is the original scanmac script.
Code:
#!/bin/bash

if [ -z "$1" -o "$1" == "-?" ] ; then
	echo "Usage: scanmac starting-ip [ending-ip]"
	echo
	echo "Will list IP and MAC adresses of all active computers"
	echo "within a physical network segment."
	echo
	echo "If ending-ip is omitted, ending-ip = starting-ip+1"
	echo " (so that only the host specified will be scanned)."
	echo
	echo "If you wish to scan from 192.168.2.1 to 192.168.2.31,"
	echo " inclusive, specify ending-ip to be 192.168.2.32."
	echo

	exit 0
fi

startw=$(echo "$1" | cut -d. -f1)
startx=$(echo "$1" | cut -d. -f2)
starty=$(echo "$1" | cut -d. -f3)
startz=$(echo "$1" | cut -d. -f4)

echo "Starting address: $startw.$startx.$starty.$startz"

endip="$2"

if [ -z "$endip" ] ; then
	if [ $startz -eq 255 ] ; then
		endz=0

		if [ $starty -eq 255 ] ; then
			endy=0

			if [ $startx -eq 255 ] ; then
				endx=0

				if [ $startw -eq 255 ] ; then
					echo "Sorry, you cannot just scan 255.255.255.255."
					echo "  Maybe later, or you can try to hack support in."

					exit 1
				else
					endw=$(($startw+1))
				fi
			else
				endx=$(($startx+1))
			fi
		else
			endy=$(($starty+1))
		fi
	else
		endz=$(($startz+1))
	fi

	endip=$endw.$endx.$endy.$endz
fi

echo "Ending address: $endip"

currentw=$startw
currentx=$startx
currenty=$starty
currentz=$startz

currentip=$currentw.$currentx.$currenty.$currentz

# If the bottom octet is zero, it'll get logged inside the while, so
# don't do it here

if [ "$currentz" -ne "0" ] ; then
	echo "$(date): $currentip"
fi

trap "exit 15" 15
trap "exit 2" 2

while [ "$currentip" != "$endip" ] ; do
	currentip=$currentw.$currentx.$currenty.$currentz

	# another log message whenever the bottom octet rolls over

	if [ "$currentz" -eq "0" ] ; then
		echo "$(date): $currentip"
	fi

	ping -c 1 -w 10 $currentip >/dev/null 2>&1

	mac=$(arp -a $currentip | cut -d' ' -f4)

	case "$mac" in
	?incomplete?)
		:  # do nothing -- no MAC for this IP
		;;
	entries)
		:  # again, do nothing -- this is a broadcast address
		;;
	*)
		echo "IP: $currentip -- MAC: $mac"
		;;
	esac

	mac=""   # reset for the next loop iteration

	# now increment the ip values (w,x,y,z)

	if [ $currentz -eq 255 ] ; then
		currentz=0
	else
		currentz=$(($currentz+1))
		continue
	fi

	if [ $currenty -eq 255 ] ; then
		currenty=0
	else
		currenty=$(($currenty+1))
		continue
	fi

	if [ $currentx -eq 255 ] ; then
		currentx=0
	else
		currentx=$(($currentx+1))
		continue
	fi

	if [ $currentw -eq 255 ] ; then
		break
	else
		currentz=$(($currentz+1))
		continue
	fi
done

Last edited by homey; 10-20-2006 at 06:29 PM.
 
Old 10-20-2006, 08:59 PM   #8
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by AnonyMooseUK
ghostdog74 - that works, but i have no python knowledge, so how would i then change it to allow the script to be run with the startip and endip variables passed on the command line; eg;

python script.py 10.1.1.1 10.1.2.45


thanks people
Code:
#!/usr/bin/python
import socket, struct,sys
start = sys.argv[1] #first arg
end = sys.argv[2] #second arg
startip = struct.unpack('>L',socket.inet_aton(start))[0]
endip = struct.unpack('>L',socket.inet_aton(end))[0]
while startip <= endip:
        print socket.inet_ntoa(struct.pack('>L',startip))
        startip += 1
Code:
python yourscript.py 10.0.0.1 10.0.0.10
 
Old 10-21-2006, 01:06 AM   #9
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Quote:
Originally Posted by AnonyMooseUK
Dark Helmet - Doesnt quite work, as will only enumerate to the number stated in the end ip.
Yeah, you're right. I got too focused on setting up the looping that I forgot to add some needed logic. My mistake.

I'll try to remember to post a corrected version later. Right now, I need to sleep.
 
Old 10-21-2006, 11:34 AM   #10
AnonyMooseUK
LQ Newbie
 
Registered: Oct 2006
Distribution: Red Hat 9 & Fedora FC5
Posts: 4

Original Poster
Rep: Reputation: 0
Homey - Thanks for that, works a treat, will make some mods to remove the .0 and .255 out of the ranges though.

As to the scanmac tool, i wrote a similar one a while ago, but mine was just a few lines as it simply pinged the subnet mask, which caused all the local ips in use to reply, then used the arp command to list all the new known ones out.

I also wrote a script to work with this and samba, for linux.
Which then took the list of alive ip addreses and polled them to see who was logged into them (winXP clients). Worked a treat.


Thanks again. Appreciated.
 
Old 10-21-2006, 01:07 PM   #11
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
It turns out my first attempt made things more difficult than they really needed to be. Anyway, here's a bash script that removes the 0 and 255 addresses.

Code:
#!/bin/bash

start_ip=$1
end_ip=$2

counter[0]=$( echo ${start_ip} | cut -f 1 -d . )
counter[1]=$( echo ${start_ip} | cut -f 2 -d . )
counter[2]=$( echo ${start_ip} | cut -f 3 -d . )
counter[3]=$( echo ${start_ip} | cut -f 4 -d . )


while [ "${end_ip}" != "${counter[0]}.${counter[1]}.${counter[2]}.${counter[3]}" ] ; do

  if [ \( ${counter[3]} -ne 0 \) -a          \
       \( ${counter[3]} -ne 255 \) ] ; then
    echo "${counter[0]}.${counter[1]}.${counter[2]}.${counter[3]}"
  fi

  let counter[3]=${counter[3]}+1

  if [ ${counter[3]} -eq 256 ] ; then
    counter[3]=0
    let counter[2]=${counter[2]}+1
  fi

  if [ ${counter[2]} -eq 256 ] ; then
    counter[2]=0
    let counter[1]=${counter[1]}+1
  fi

  if [ ${counter[1]} -eq 256 ] ; then
    counter[1]=0
    let counter[0]=${counter[0]}+1
  fi
done

echo "${end_ip}"
 
Old 10-22-2006, 10:17 AM   #12
Tischbein
Member
 
Registered: Oct 2006
Distribution: debian
Posts: 124

Rep: Reputation: 15
# Using awk:

Code:
echo $min $max |\
sed 's/[:.]/ /g' |\
awk '
{
 a=$1; b=$2; c=$3; d=$4
 for (; a < 256; ++a && b=0)
 for (; b < 256; ++b && c=0)
 for (; c < 256; ++c && d=0)
 for (; d < 256; ++d       )
 {if ( (a < $5) || (b < $6) || (c < $7) || (d <= $8))
     {print a ":" b ":" c ":" d}
  else {exit 0}
 }
}'
# Using bash:

Code:
function print_range_core
{
 a=$1;b=$2;c=$3;d=$4
   for ((; a < 256; ((a=a + 1)) && ((b=0)) ))
 do for ((; b < 256; ((b=b + 1)) && ((c=0)) ))
  do for ((; c < 256; ((c=c + 1)) && ((d=0)) ))
   do for ((; d < 256; ((d=d + 1)) ))
    do if [ $a -lt $5 ] ||
          [ $b -lt $6 ] ||
          [ $c -lt $7 ] ||
          [ $d -le $8 ]
       then echo ${a}:${b}:${c}:${d}
       else return 0
       fi
    done
   done
  done
 done
}


function print_range
{
  args=$(echo "$1" "$2" | sed 's/[.:]/ /g')
  echo $args
  print_range_core $args
}


print_range 1.255.255.60 2.0.1.1
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
shell scripting - help needed jonhewer Linux - Newbie 54 09-09-2005 02:58 PM
bash scripting --- some help needed rajsharma Linux - Software 1 09-09-2005 02:49 AM
Process Enumeration with C++ amitrawal_17 Programming 2 06-08-2004 01:16 AM
Scripting help needed. stonelee Linux - Software 2 09-29-2003 09:47 AM
Shell scripting and background processes - help needed. trafalgar Programming 3 06-08-2003 09:15 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:53 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration