1#!/usr/local/bin/perl -w
2
3# Copyright 2005 Thomas A. Limoncelli
4#
5#     This program is free software; you can redistribute it and/or modify
6#     it under the terms of the GNU General Public License as published by
7#     the Free Software Foundation; either version 2 of the License, or
8#     (at your option) any later version.
9#     This program is distributed in the hope that it will be useful,
10#     but WITHOUT ANY WARRANTY; without even the implied warranty of
11#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12#     GNU General Public License for more details.
13#
14#
15#     You should have received a copy of the GNU General Public License
16#     along with this program; if not, write to the Free Software
17#     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18
19use strict;
20
21# Defaults and formats:
22my @FORMATS = (
23		'#$ip\tUNUSED$hex.$DOMAIN',
24		'$ip\tUNUSED$hex.$DOMAIN',
25		'$ip\tUNUSED-$hex.$DOMAIN',
26		'$ip\th-$ipsep.$DOMAIN',
27		'$ip\tdyn-$ip.$DOMAIN\@EXTERNAL',
28		);
29my $DOMAIN  = 'domain.com';
30my $DEFAULT_IPSEPARATOR = '-';
31
32# Process command line info::
33use Getopt::Std;
34my %opts;
35getopts("hd:1234s:", \%opts);
36sub usage {
37        print <<HERE
38
39Prints a range of IP addresses in a specifed format.
40
41$0 [-h] [-1234] [-d domain] [-s str] startip count [format]
42   or
43$0 [-h] [-1234] [-d domain] [-s str] startip endip [format]
44
45  startip      The starting IP address.
46  count        How many IP following to print.
47  endip        Last IP address to list.
48  format       The format to use (defaults to $FORMATS[0])
49  Format strings may include:
50                \$ip     ip address in 1.2.3.4 format
51                \$ipsep  ip address in 1x2x3x4 format where "x" is defined by -s
52                \$hex    ip address as a hex string: A016406
53                \$a \$b \$c \$d    the a.b.c.d of the IP address
54
55  -h          This help menu.
56  -d domain   The domain to use. Default is $DOMAIN
57  -s str      Use str instead of "." in \$ipsep addresses (default $DEFAULT_IPSEPARATOR)
58
59Pre-defined formats:
60Default  $FORMATS[0]
61         #10.1.100.4	UNUSED0A016404.domain.com
62     -1  $FORMATS[1]
63         10.1.100.4	UNUSED0A016404.domain.com
64     -2  $FORMATS[2]
65         10.1.100.4	UNUSED-0A016404.domain.com
66     -3  $FORMATS[3]
67         10.1.100.4	h-10-1-100-4.domain.com
68     -4  $FORMATS[4]
69         10.1.100.4	dyn-10.1.100.4.domain.com\@EXTERNAL
70
71Examples:
72	Generate a Class C sized set of hosts:
73		$0    10.1.100.0 256
74	Generate a range of external addresses:
75		$0 -4 64.32.179.65 64.32.179.68
76	Generate a custom format to make hostnames ending with the 4th octet:
77		$0    64.32.179.65 4 \$ip\\thost\$d.mydomain.com'
78	Generate using a very serious custom format:
79		$0    64.32.179.65 4 '\$ip\\thost\$hex.mydomain.com'
80	Generate using a very silly custom format:
81		$0    64.32.179.65 1 '\$ip is \$hex in hex'
82HERE
83;
84        exit 1;
85}
86
87# Process the options:
88
89# Help
90&usage if $#ARGV < 1 or $opts{'h'};
91
92# Parameters:
93my $STARTIP=shift @ARGV; #print "IP=$STARTIP\n";
94my $COUNT=shift @ARGV; #print "COUNT=$COUNT\n";
95
96# Domain:
97$DOMAIN = $opts{'d'} if $opts{'d'};
98my $IPSEPARATOR = $opts{'s'} || $DEFAULT_IPSEPARATOR;
99
100# Select the format string:
101my $FORMAT = $FORMATS[0];		# default
102$FORMAT = $FORMATS[1] if $opts{'1'};	# preset #1
103$FORMAT = $FORMATS[2] if $opts{'2'};	# preset #2
104$FORMAT = $FORMATS[3] if $opts{'3'};	# preset #3
105$FORMAT = $FORMATS[4] if $opts{'4'};	# preset #4
106$FORMAT=shift @ARGV if $#ARGV > -1;	# on the command line
107#print "FORMAT=$FORMAT\n";
108
109# Calculate the start and end IP address and numeric equiv:
110my $startnum = ip2num($STARTIP);
111
112my $endnum;
113if ($COUNT =~ /\./) {		# does value include a "."?
114	# it's an IP addr:
115	$endnum = ip2num($COUNT);
116} else {
117	# it's a count:
118	$endnum = $startnum + $COUNT - 1;
119	$endnum = 0xffffffff if $endnum > 0xffffffff;
120}
121
122my($ip, $ipsep, $hex);
123my($a, $b, $c, $d);
124for (my $i = $startnum; $i <= $endnum; $i++ ) {
125	$ip = num2ip($i);
126	($a, $b, $c, $d) = split(/\./, $ip);
127	$ipsep = num2ipsep($i, $IPSEPARATOR);
128	$hex = num2hex($i);
129	#print "#", $ip, "\tUNUSED", $hex, ".", $DOMAIN, "\n";
130	eval print eval qq{"$FORMAT\n";};
131}
132
133# --------------
134
135sub ip2num {
136	my ($ip) = @_;
137	# I'm sure there's a better way to convert an IP address into an integer but...
138	my @parts = split(/\./, $ip);
139	return	($parts[0] << 24) +
140		($parts[1] << 16) +
141		($parts[2] << 8 ) +
142		$parts[3];
143}
144
145sub num2ip {
146	my ($num) = @_;
147	return	         ($num >> 24)
148		. '.' . (($num >> 16) % 256)
149		. '.' . (($num >>  8) % 256)
150		. '.' .  ($num        % 256);
151}
152
153sub num2ipsep {
154	my ($num, $sep) = @_;
155	return	          ($num >> 24)
156		. $sep . (($num >> 16) % 256)
157		. $sep . (($num >>  8) % 256)
158		. $sep .  ($num        % 256);
159}
160
161sub num2hex {
162	my ($num) = @_;
163	return sprintf("%08X", $num);
164}
165