423 lines
13 KiB
Plaintext
423 lines
13 KiB
Plaintext
|
#!/usr/bin/perl -w
|
||
|
#==============================================================================
|
||
|
# lat-hosts
|
||
|
# =========
|
||
|
# 0.9.0 (2004-09-08)
|
||
|
# (c)2003-2004 Altiplano bvba
|
||
|
#==============================================================================
|
||
|
package esmith;
|
||
|
use strict;
|
||
|
use esmith::config;
|
||
|
use esmith::db;
|
||
|
use esmith::util;
|
||
|
use Getopt::Long;
|
||
|
use Pod::Usage;
|
||
|
my %conf;
|
||
|
tie %conf, 'esmith::config';
|
||
|
my %accounts;
|
||
|
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
|
||
|
my %hosts;
|
||
|
tie %hosts, 'esmith::config', '/home/e-smith/db/hosts';
|
||
|
my %domains;
|
||
|
tie %domains, 'esmith::config', '/home/e-smith/db/domains';
|
||
|
my ($Hlp, $Cml, $Frc, $Inp);
|
||
|
my $Add =0;
|
||
|
my $Del =0;
|
||
|
|
||
|
#==============================================================================
|
||
|
# Main
|
||
|
#==============================================================================
|
||
|
sub performCreateLocalHostEntry ($$$$$$$);
|
||
|
|
||
|
# Analyze commandline options
|
||
|
GetOptions ("help" => \$Hlp,
|
||
|
"add" => \$Add,
|
||
|
"delete" => \$Del,
|
||
|
"force" => \$Frc,
|
||
|
"command-line=s" => \$Cml,
|
||
|
"input-file=s" => \$Inp);
|
||
|
|
||
|
if ( $Hlp ) { &PrintPod(9); exit; }
|
||
|
|
||
|
# We need one argument or the other, but not both
|
||
|
if ((($Cml && $Inp) || (! $Cml && ! $Inp)) ||
|
||
|
($Add + $Del != 1))
|
||
|
{ &PrintPod(1); exit; }
|
||
|
|
||
|
my @records;
|
||
|
if ($Inp) {
|
||
|
open(LIST,"< $Inp") || die "Can't find $Inp.\n";
|
||
|
@records = grep(!/(^\s*#)|(^\s*$)/,<LIST>);
|
||
|
close(LIST); }
|
||
|
elsif ($Cml) { @records=($Cml); }
|
||
|
else { &PrintPod(1); exit; }
|
||
|
|
||
|
if ($Add) {
|
||
|
# Process each user
|
||
|
foreach my $record (@records)
|
||
|
{
|
||
|
my @fields=split(/\|/,$record);
|
||
|
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
|
||
|
|
||
|
performCreateLocalHostEntry ($fields[0], # HostName
|
||
|
$fields[1], # DomainName
|
||
|
$fields[2], # Location
|
||
|
$fields[3], # Visibility
|
||
|
$fields[4], # Local IP
|
||
|
$fields[5], # Global IP
|
||
|
$fields[6]); # Mac Address
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($Del) {
|
||
|
&ExpandWildCard; # Check for wildcards and expand if necessary
|
||
|
|
||
|
# Process each user
|
||
|
foreach my $record (@records)
|
||
|
{
|
||
|
my @fields=split(/\|/,$record);
|
||
|
for (my $cnt=0; $cnt <= $#fields; ++$cnt) { for ($fields[$cnt]) { s/^\s+//; s/\s+$//; }}
|
||
|
|
||
|
if (! $fields[1] ) { $fields[1] = db_get(\%conf, 'DomainName') }
|
||
|
my $FullHostName = lc($fields[0]).".".lc($fields[1]);
|
||
|
|
||
|
if ((db_get(\%hosts, $FullHostName)) &&
|
||
|
(db_get_type(\%hosts, $FullHostName)) eq "host") {
|
||
|
my $yn = 'yes';
|
||
|
if (! $Frc) {
|
||
|
print "Do you want to delete host '$FullHostName' [yes/NO/all]? ";
|
||
|
$yn = <STDIN>;
|
||
|
if ($yn =~ /^a/i) { $Frc = -1; $yn="yes"; }
|
||
|
}
|
||
|
if ($yn =~ /^y/i) {
|
||
|
print "Deleting '$FullHostName'...\n";
|
||
|
db_delete(\%hosts, $FullHostName);
|
||
|
system ("/sbin/e-smith/signal-event", "host-delete", "$FullHostName") == 0
|
||
|
or die ("Error occurred while deleting '$FullHostName'.\n");
|
||
|
}
|
||
|
}
|
||
|
else { print "Can't find host '$FullHostName'.\n\a";}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#==============================================================================
|
||
|
# Subroutines
|
||
|
#==============================================================================
|
||
|
# Create local host
|
||
|
sub performCreateLocalHostEntry ($$$$$$$)
|
||
|
{
|
||
|
my $REGEXPMACAddress = '([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f]){5})';
|
||
|
my $REGEXPIPAddress = '(self|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})';
|
||
|
my $REGEXPHostname = '([a-z0-9][a-z0-9-]*)';
|
||
|
|
||
|
my ($q) = @_;
|
||
|
my ($HostName, $DomainName, $Location, $Visibility, $InternalIP, $ExternalIP, $MACAddress) = @_;
|
||
|
my %hostProperties;
|
||
|
|
||
|
#------------------------------------------------------------
|
||
|
# Validate parameters and untaint them
|
||
|
#------------------------------------------------------------
|
||
|
# Hostname
|
||
|
$HostName = lc($HostName);
|
||
|
if ($HostName =~ /^$REGEXPHostname$/) {
|
||
|
$HostName = $1;
|
||
|
}
|
||
|
else {
|
||
|
print "Bad hostname ($HostName).\a\n";
|
||
|
return;
|
||
|
}
|
||
|
if (length $HostName > 32) {
|
||
|
print "Hostname too long.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
# Domainname
|
||
|
if (! $DomainName) { $DomainName = db_get(\%conf, 'DomainName') }
|
||
|
$DomainName = lc($DomainName);
|
||
|
if ((! db_get(\%domains, $DomainName)) &&
|
||
|
( db_get(\%conf, 'DomainName') ne $DomainName)) {
|
||
|
print "\nThe domainname '$DomainName' is not hosted on this server.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
if ($DomainName =~ /^([a-z0-9\-\.]+)$/) {
|
||
|
$DomainName = $1;
|
||
|
}
|
||
|
else {
|
||
|
print "Unexpected characters in '$DomainName'.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
print "\nCreating $HostName.$DomainName...\n";
|
||
|
|
||
|
# Location
|
||
|
if (! $Location) { $Location = "Self" }
|
||
|
if ( $Location =~ /(local)|(remote)|(self)/i ) {
|
||
|
$Location = ucfirst lc $Location;
|
||
|
}
|
||
|
else { $Location = "Self" }
|
||
|
|
||
|
# Visibility
|
||
|
if ( ! $Visibility ) {
|
||
|
$Visibility = "Local";
|
||
|
$ExternalIP = "";
|
||
|
}
|
||
|
if ( $Visibility =~ /(local)|(global)/i ) {
|
||
|
$Visibility = ucfirst lc $Visibility;
|
||
|
}
|
||
|
else { $Visibility = "Local" }
|
||
|
if ($Visibility eq "Local") { $ExternalIP = "" }
|
||
|
|
||
|
# Internal IP address
|
||
|
if (! $InternalIP) { $InternalIP = ''; }
|
||
|
if ($Location eq 'Self') { $InternalIP = '' }
|
||
|
elsif ($InternalIP =~ /^$REGEXPIPAddress$/ ) { $InternalIP = $1; }
|
||
|
else {
|
||
|
print "Error: IP Address '$InternalIP' is invalid. Did not create hostname.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
# MAC address
|
||
|
if (( ! $MACAddress ) || ($Location ne "Local")) { $MACAddress = "" }
|
||
|
if ( length($MACAddress) == 0 )
|
||
|
{
|
||
|
# They don't want one
|
||
|
}
|
||
|
elsif ($MACAddress =~ /^$REGEXPMACAddress$/i )
|
||
|
{
|
||
|
$MACAddress = $1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
print "Invalid Mac Address \n";
|
||
|
return;
|
||
|
}
|
||
|
# External IP
|
||
|
if ( ! $ExternalIP ) { $ExternalIP = "" }
|
||
|
if ($Visibility eq 'Global') # Wants externally visible - needs external IP
|
||
|
{
|
||
|
if ( length ($ExternalIP) == 0 )
|
||
|
{
|
||
|
print "Error: You did not enter a Global IP value for '$HostName'.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
elsif ($ExternalIP =~ /^$REGEXPIPAddress$/ )
|
||
|
{
|
||
|
$ExternalIP = $1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
print "Error: IP Address '$ExternalIP' is invalid. Did not create hostname.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else # Wants internally visible - optional external IP
|
||
|
{
|
||
|
if ( length ($ExternalIP) == 0 )
|
||
|
{
|
||
|
# They didn't specify one
|
||
|
}
|
||
|
elsif ($ExternalIP =~ /^$REGEXPIPAddress$/ )
|
||
|
{
|
||
|
$ExternalIP = $1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
print "Error: IP Address '$ExternalIP' is invalid. Did not create hostname.\a\n";
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#------------------------------------------------------------
|
||
|
# Looks good. Find out if this entry has been taken
|
||
|
#------------------------------------------------------------
|
||
|
|
||
|
my $fullHostName = join (".", $HostName, $DomainName);
|
||
|
|
||
|
if (defined (db_get(\%hosts, $fullHostName)) )
|
||
|
{
|
||
|
print "HostName '$fullHostName' already exists. \n";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#------------------------------------------------------------
|
||
|
# Host entry is available! Update hosts database.
|
||
|
#------------------------------------------------------------
|
||
|
print "HostName : $HostName\n";
|
||
|
print "DomainName : $DomainName\n";
|
||
|
print "Location : $Location\n";
|
||
|
print "Visibility : $Visibility\n";
|
||
|
print "Local IP : $InternalIP\n";
|
||
|
print "Global IP : $ExternalIP\n";
|
||
|
print "Mac Address : $MACAddress\n";
|
||
|
|
||
|
$hostProperties{'Visibility'} = $Visibility;
|
||
|
$hostProperties{'HostType'} = $Location;
|
||
|
$hostProperties{'InternalIP'} = $InternalIP;
|
||
|
$hostProperties{'ExternalIP'} = $ExternalIP;
|
||
|
$hostProperties{'MACAddress'} = $MACAddress;
|
||
|
db_set(\%hosts, $fullHostName, 'host', \%hostProperties);
|
||
|
|
||
|
#------------------------------------------------------------
|
||
|
# Signal the create-host event.
|
||
|
#------------------------------------------------------------
|
||
|
|
||
|
system ("/sbin/e-smith/signal-event", "host-create", "$HostName") == 0
|
||
|
or die ("Error occurred while creating hostname.\n");
|
||
|
}
|
||
|
#==============================================================================
|
||
|
# Test for wildcards in the hostname. If any wildecards are found, the array
|
||
|
# @records is expanded with the hostnames that meet the conditions.
|
||
|
sub ExpandWildCard {
|
||
|
my $ctrec = 0;
|
||
|
foreach my $record (@records)
|
||
|
{
|
||
|
my @fld=split(/\|/,$record);
|
||
|
for (my $cnt=0; $cnt <= $#fld; ++$cnt) { for ($fld[$cnt]) { s/^\s+//; s/\s+$//; }}
|
||
|
|
||
|
if ($fld[0] =~ /\*|\?/) { # Does it contain the wildcards?
|
||
|
$fld[0] =~ s/\*/\.\*/g; # Replace * with .* to allow for grep.
|
||
|
$fld[0] =~ s/\?/\./g; # Replace ? with . to allow for grep.
|
||
|
|
||
|
if (! $fld[1]) { $fld[1] = db_get(\%conf, 'DomainName'); }
|
||
|
|
||
|
open USRS, "</home/e-smith/db/hosts" or die "Can't open /home/e-smith/db/hosts: $!";
|
||
|
my @match = grep /^$fld[0]\.$fld[1]=host\|/i, <USRS>;
|
||
|
close(USRS);
|
||
|
|
||
|
my $cu = 0;
|
||
|
foreach my $tst (@match) {
|
||
|
$tst =~ /\.$fld[1]\=/; $tst = $`;
|
||
|
for (my $cnt=1; $cnt <= $#fld; ++$cnt) { $tst = $tst." | ".$fld[$cnt]; };
|
||
|
if ($cu == 0 ) {
|
||
|
$records[$ctrec] = $tst;
|
||
|
$cu =1;
|
||
|
}
|
||
|
else {
|
||
|
push(@records, $tst);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
++$ctrec;
|
||
|
}
|
||
|
}
|
||
|
#==============================================================================
|
||
|
# Print the pod text as a help screen
|
||
|
sub PrintPod {
|
||
|
my ($verbose, $message) = @_;
|
||
|
pod2usage(-verbose => $verbose, -message => $message, -exitval => 64);
|
||
|
}
|
||
|
|
||
|
#==============================================================================
|
||
|
|
||
|
=pod
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
B<lat-hosts> - The lazy administrator's tool to manage hostnames
|
||
|
|
||
|
=head1 DESCRIPTION
|
||
|
|
||
|
Creates or deletes hosnames on Mitel's SME servers.
|
||
|
This tool is functionally equivalent to the 'Hostnames and addresses' option in the server-manager, but can be run from the command line or called from an other script.
|
||
|
It allows you, for example, to create a large number of hostnames in a batch process, or delete hostnames on a remote machine via an ssh console.
|
||
|
|
||
|
See F</usr/doc/lazy-admin-tools/example.hosts> for the format of the input file.
|
||
|
|
||
|
=head1 SYNOPSIS
|
||
|
|
||
|
B<lat-hosts> -a -c "host| domain| loc. | visib. | loc.ip | glob.ip | mac"
|
||
|
|
||
|
B<lat-hosts> -a -i /path/to/hosts.list
|
||
|
|
||
|
B<lat-hosts> -d [-f] -c "Host | Domain"
|
||
|
|
||
|
B<lat-hosts> -d [-f] -i /path/to/hosts.list
|
||
|
|
||
|
=head1 OPTIONS
|
||
|
|
||
|
The following options are supported:
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item B<-a>, B<--add>
|
||
|
|
||
|
Add a host name to the server
|
||
|
|
||
|
=item B<-c "Arguments">, B<--command-line="Arguments">
|
||
|
|
||
|
Take arguments from the command line. See below for the various arguments that are accepted.
|
||
|
|
||
|
=item B<-d>, B<--delete>
|
||
|
|
||
|
Delete a hostname from the server. Wildcards (* and ?) are accepted.
|
||
|
|
||
|
=item B<-f>, B<--force>
|
||
|
|
||
|
Don't prompt before deleting.
|
||
|
|
||
|
=item B<-h>, B<--help>
|
||
|
|
||
|
Extended help for this tool
|
||
|
|
||
|
=item B<-i FILE>, B<--input-file=FILE>
|
||
|
|
||
|
Use the information from F<FILE> to create or delete the hostname(s).
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head2 Arguments:
|
||
|
|
||
|
host* : Must contain only letters, numbers, and hyphens,
|
||
|
and must start with a letter or number. Wildcards
|
||
|
(* and ?) can only be used to delete hostnames.
|
||
|
domain : Must be an existing (virtual) domain name. If
|
||
|
omitted, the primary site is assumed.
|
||
|
loc. : Location of the server:
|
||
|
'Local' (on the LAN)
|
||
|
'Remote' (on the Internet)
|
||
|
'Self' (alias for the SME server)
|
||
|
visib. : 'Local' (only visible on the LAN)
|
||
|
'Global' (visible on the entire Internet).
|
||
|
loc.ip : Internal IP number
|
||
|
glob.ip : Public IP number
|
||
|
mac : The ethernet address is optional and causes the
|
||
|
DHCP server to statically bind the local IP address
|
||
|
to the computer with this ethernet address.
|
||
|
|
||
|
* mandatory field
|
||
|
|
||
|
=head1 EXAMPLES
|
||
|
|
||
|
B<lat-hosts -a -c "ntp | hogwarts.net | self | local">
|
||
|
|
||
|
Creates host name 'ntp.hogwarts.net' on the SME server. The host name will be visible only on the LAN.
|
||
|
|
||
|
B<lat-hosts -a -i /root/hosts.list>
|
||
|
|
||
|
Creates the host names defined in F</root/hosts.list>. Refer to F</usr/doc/lazy-admin-tools/example.hosts> for an example of an input file.
|
||
|
|
||
|
B<lat-hosts -d -f -c "ftp*">
|
||
|
|
||
|
Deletes all host names that start with 'ftp'. The host names will be deleted without prompting (-f).
|
||
|
|
||
|
=head1 SEE ALSO
|
||
|
|
||
|
lat-group(8), lat-pseudonyms(8), lat-ibays(8), lat-quota(8), lat-domains(8), lat-users(8), lat-procmail(8), lat-pptp(8), lat-dump(8)
|
||
|
|
||
|
=head1 VERSION
|
||
|
|
||
|
Version 0.9.0 (2004-09-08). The latest version is hosted at B<http://www.contribs.org/contribs/mblotwijk/>
|
||
|
|
||
|
=head1 COPYRIGHT
|
||
|
|
||
|
(c)2003-2004, Altiplano bvba (B<http://www.altiplano.be>). Released under the terms of the GNU license.
|
||
|
|
||
|
|
||
|
=head1 BUGS
|
||
|
|
||
|
Please report bugs to <Bugs@Altiplano.Be>
|
||
|
|
||
|
=cut
|
||
|
|
||
|
#==============================================================================
|