#!/usr/bin/perl -w # #@(#) smb2lmhost.pl Description: #@(#) A perl script which allows you collect the windows machine names #@(#) with the corresponding IP adress (IPv4 only) using #@(#) the 'smbstatus' command. #@(#) It should write these pairs to the file "lmhosts", because other #@(#) scripts are functional only if the machine-name/IP mapping #@(#) works fine. #@(#) Based on the script "smb-wall.pl" by Keith Farrar #@(#) # #============================================================================= # # Modified by # Heiko Teichmeier # 2003-11-19 v. 0.0.1 # 2003-11-20 v. 0.1.1 # # 2004-02-25 v. 0.1.2 (with help by Peter Reinhart, correct my bad english, thanks to him) # # Glauchau/Sa., Germany # use strict; #=== definitions of your environment === # # location and name of the lmhost-file my $lm_file = "/etc/samba/lmhosts"; # location and name of safety-copy of the original lmhost-file my $lm_backup = "/etc/samba/lmhosts.orig"; # location and name of the temporarily changed lmhost-file my $lm_tmp = "/etc/samba/lmhosts.tmp"; # write to the 'lmhosts' file - yes=1, no=0 or nothing my $lm_write = 1; # write the message-header to the lmhosts-file - yes=1, no=0 or nothing my $write_msg = 1; # create the 'lmhosts' file if not existing - yes=1, no=0 or nothing my $lm_create = 1; my $dat = localtime(time); # a message to write to the begin of the lmhosts-file to let the user know # how the file hase been created # the user should know, that a bad user, who use a faked IP adress, would through this # script automatically push to the 'lmhosts' file! my $lm_msg = "# \n"; $lm_msg .= "# This 'lmhosts' file whas automatically generated by\n"; $lm_msg .= "# the $0-Script\n"; $lm_msg .= "# +---------------------------+\n"; $lm_msg .= "# last run on: \| $dat \n"; $lm_msg .= "# +---------------------------+\n"; $lm_msg .= "# The Windows name/IP adress pairs are based on calls from\n"; $lm_msg .= "# the 'smbstatus' script\n"; $lm_msg .= "# \n"; # read the name-IP-pairs from the original lmhosts-file to insert in the # new created file my $lm_read_old = 1; my $smbstatus = "/usr/bin/smbstatus"; my $proid = 0; my $mach_name = ""; my $mach_ip = ""; # #=== end of definitions ================ my (%machines,@clients,@message,$client,@mach_names,@proc_ids,@save_rows); my $count = 0; my $lm_miss = 0; # test - does the "lmhosts" file already exist? if (! -e $lm_file) { print "File \'$lm_file\' not found!\n"; $lm_miss = "1"; if (not ($lm_create eq 1)) { print "\'$lm_file\' creation not wish!\n"; print "See options in the script!\n\n"; exit 1; } } else { open(RDFILE, "<$lm_file") || die "Open of \$lm_file failed!.\n$!\n"; while() { my $inp = $_; $count++; # saving the rows of the file to the array '@save_rows' my $anz = push(@save_rows,$inp); # rows select - no comments, no space or NULL rows # leere und Kommentar-Zeilen ueberspringen next if $inp =~ /^\#/; next if $inp =~ /^$/; next if $inp =~ /^ /; next unless $inp =~ /^[0-9]+/; my @data = split(' ', $inp, 2); # do not accept this line if it consists of less then two fields next unless $data[1]; my $key = $data[0]; my $value = $data[1]; $machines{$key} = $value; } close(RDFILE); } # save the rows of the $lm_file to the $lm_backup-file open(WRFILE, ">$lm_backup") || die "Open of \$lm_backup failed!.\n$!\n"; while(@save_rows) { my $row = shift(@save_rows); printf WRFILE $row; } close(WRFILE); # call 'smbstatus' to look for Windows client name/IP adress pairs open(PCLIST, "$smbstatus |") || die "$smbstatus failed!.\n$!\n"; while() { last if /^Locked files:/; my @arr = split(" ", $_, 6); # do not accept this line if it consists of less than six fields next unless $arr[5]; # Reads out and saves PID # PID auslesen und speichern $proid = $arr[3]; push(@proc_ids, $proid); $client = $arr[4]; next unless $client =~ /[^.]/; # expect 'dot' in a client name next if grep($_ eq $client, @clients); # we only want this name once push (@clients,$client); # Reads and stores machine name/IP adress raw my $mach_ip_raw = $arr[5]; my @ip_arr = split(" ", $mach_ip_raw, 6); my $mach_ip_raw1= $ip_arr[0]; my $len = length $mach_ip_raw1; my $mach_ip = substr($mach_ip_raw1, 1, $len-2); $machines{$mach_ip}=$client; } if ($lm_miss) { $machines{"127.0.0.1"}="localhost"; } close(PCLIST); # write the key pairs from the hash %machines to tmp-file if (not open(WRFILE, ">$lm_tmp")) { die "Open of \$lm_tmp failed!.\n$!\n"; } else { if ($write_msg) { printf WRFILE "$lm_msg"; } foreach my $key (keys %machines) { printf WRFILE "$key\t$machines{$key}\n"; } close(WRFILE); } # read the comlete $lm_tmp file in the array @save_rows @save_rows = ""; my $row = ""; open(RDFILE, "<$lm_tmp") || die "Open of \$lm_file failed!.\n$!\n"; while() { $row = $_; my $anz = push(@save_rows,$row); } close(RDFILE); # write NULL string and then the array @save_rows to $lm_file open(WRFILE, ">$lm_file") || die "Open of \$lm_file failed!.\n$!\n"; printf WRFILE ""; while(@save_rows) { my $row = shift(@save_rows); printf WRFILE $row; } close(WRFILE); exit 0;