Tag Archives: Perl

vSphere CLI libeay32.dll error on 64bit Windows 7

If you install the latest build of vSphere CLI 4.1 on Windows 7 x64 some of the commands will fail, with perl.exe throwing the following error:

The ordinal 3212 could not be located in the dynamic link library LIBEAY32.dll

There isn’t much to go on when you look up the error – just a lot of people saying you should delete all older copies of LIBEAY32.dll from your system.

Fortunately there is a neater solution, and I’m surprised VMware haven’t fixed this problem yet (4.0 also had the same issue).

  • Open your CLI command prompt as Administrator. Type ppm and hit enter (Perl Package Manager).
  • Now look for a module called Crypt-SSLeay. You’ll see that CLI’s bundled ActivePerl distribution includes version 0.53, but there is a newer version 0.57 available:ActiveState Perl PPM
  • Remove this as shown, then go to File -> Run Marked Actions
  • Click on the grey box icon on the left of the toolbar. These are available packages which are not currently installed. Search for Crypt-SSLeay once again, install, and Run Marked Actions. Exit.

Problem solved!

Wake on LAN for VPN users

In the absence of a Terminal Server, having users remotely use the software on their desktop PCs is often easier than having to manage software packages on laptops which may be part of a generic pool. In an energy conscious business there is the problem of what to do if one of your remote users wants to get at their desktop PC while it’s asleep or powered down. Wake on LAN works by sending a magic packet – featuring the target PC’s MAC address – to the network broadcast address. A MAC address is pretty unwieldy, so the ideal solution is an intranet page allowing users to wake a PC by hostname once they’re connected to the VPN.

To do this you will need some kind of host database to link hostnames to MAC addresses (remember – the machines could be switched off, so the DHCP database is no good). Your intranet server must also be on the same subnet as the machines you intend to wake. I have only used this in a single subnet so I haven’t investigated scalability, but it just looks like a case of enabling directed broadcasts on your routers. My login script updates host database entries and collects other WMI info such as make & model, tag number, spec, etc.

I implemented this Wake on LAN four years ago so there may be neater ways of doing it by now. At the time I couldn’t do the whole thing in ASP because there was no free socket library for VBScript, so I used Perl to create the magic packet. I used a generic wakeonlan.pl script by José Pedro Oliveira and tweaked it to post back to the ASP page.

Here are the required scripts – the first is ASP part you would need for the Intranet page:

<% Language=VBScript %>
<p>Wake your PC to allow you to connect to it remotely.</p>
<form method="get" action="./default.asp">Name of PC to power on: <input name="hostname" maxlength=14><input type="submit" value="wake"><br>
<%
Dim strHostname
strHostname = Request.QueryString("hostname")

'check query string from form above
If Not strHostname = "" Then
  'remove potential SQL injection attack characters
  strHostname = killChars(strHostname)
  Dim strConnection, objConnection, objRecordSet, objCommand, objResult

  'create connection object
  strConnection = "Provider=SQLOLEDB; Data Source=sqlsvr.domain.com; Initial Catalog=HostDB;User Id=HostDB_RO;Password=yourpassword"
  Set objConnection = CreateObject("ADODB.Connection")
  objConnection.Open strConnection

  'create command object
  set objCommand = CreateObject("ADODB.Command")
  objCommand.ActiveConnection = objConnection

  'check to see if a MAC exists for this hostname - you'll need to customize this depending on your database
  objCommand.CommandText = "SELECT * FROM Inventory WHERE Hostname='" & strHostname & "'"
  set objRecordSet = objCommand.Execute
  If Not objRecordSet.EOF Then
    'if it does exist then wake it
    Response.Redirect ("./wakeonlan.plx?MAC=" & objRecordSet.Fields.Item("MAC").value)
  Else
    Response.Write ("<em>Unknown computer: '" & strHostname & "'.</em>")
  End If
  objRecordSet.Close
  Set objCommand = nothing
  objConnection.Close
  Set objConnection = nothing
End If

'check query string for result from wakeonlan.plx
Dim strResult, strMAC
strResult = Request.QueryString("result")
If strResult = "True" Then
  Response.Write("<em>Wake-up packet sent. Wait around one minute before connecting.</em>")
End If
If strResult = "False" Then
  Response.Write("<em>Invalid MAC.</em>")
End If

'sanitize against SQL injection attacks
Function killChars(strWords)
  Dim arrBadChars, strNewChars
  arrBadChars = array("select", "drop", ";", "--", "insert", "delete", "xp_", "'", "=", " ")
  strNewChars = strWords
  For i = 0 To uBound(arrBadChars)
    strNewChars = replace(strNewChars, arrBadChars(i), "")
  Next
  killChars = strNewChars
End Function
%>
</form>

And this is wakeonlan.plx:

#!/usr/bin/perl
#
# wakeonlan.plx
# based on José Pedro Oliveira's wakeonlan.pl v1.4.2.3 <jpo@di.uminho.pt>

use strict;
use Env "QUERY_STRING";
use Socket;

# your LAN broadcast address
my $DEFAULT_IP = '172.16.1.255';
my $DEFAULT_PORT = getservbyname('discard', 'udp');
my %FORM;
my $result;

&parse_query_string;
&wake($FORM{MAC});

print 'Status: 302 Moved', "\r\n", 'Location: ./default.asp?result=', $result, "\r\n\r\n";

sub parse_query_string {
  my ($buffer, @pairs, $pair, $name, $value);
  if (length ($ENV{'QUERY_STRING'}) > 0){
    $buffer = $ENV{'QUERY_STRING'};
    @pairs = split(/&/, $buffer);
    foreach $pair (@pairs){
      ($name, $value) = split(/=/, $pair);
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      $FORM{$name} = $value;
    }
  }
}

sub wake {
  my $hwaddr  = shift;
  my $ipaddr  = $DEFAULT_IP;
  my $port    = $DEFAULT_PORT;
  my ($raddr, $them, $proto);
  my ($hwaddr_re, $pkt);

  # Validate hardware address (ethernet address)
  $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
  if ($hwaddr !~ m/^$hwaddr_re$/) {
    $result = "False";
    return undef;
  }

  # Generate magic packet
  foreach (split /:/, $hwaddr) {
    $pkt .= chr(hex($_));
  }
  $pkt = chr(0xFF) x 6 . $pkt x 16;

  # Allocate socket and send packet
  $raddr = gethostbyname($ipaddr);
  $them = pack_sockaddr_in($port, $raddr);
  $proto = getprotobyname('udp');

  socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
  setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";

  $result = "True";

  send(S, $pkt, 0, $them) or die "send : $!";
  close S;
}