In the latest firmware versions, the functionality of saving and restoring a device configuration from a binary file was implemented for NetPing devices with the aim to simplify configuration cloning for a group of devices in the network. On default, this functionality is available on the page «SETUP» of a device web interface.
It is possible to read more detailed information on using this feature through a web interface in a firmware description.
Configuration cloning via a web interface has a disadvantage of a lack of simultaneous distribution of a configuration file for a group of devices in the network. To avoid this disadvantage, there is a need to use the script for uploading a binary configuration file that will be launched for example, from a command line.
PowerShell Script
PowerShell script for uploading a configuration file can be downloaded via the link: Script_PowerShell.zip.
PowerShell Script Code
param(
[Parameter(Mandatory=$True)]
[string]$List
)Write-Host $Async
Function Error($errMessage, $errState)
{
Write-Host "[ERROR]" $errMessage $errState -ForegroundColor Red
}Function Info($infoMessage, $infoState)
{
Write-Host '[INFO]' $infoMessage $infoState -ForegroundColor Green
}Function CreateWebClient($Hostname, $Username, $Password)
{
$WebClient = New-Object System.Net.WebClient
$WebClient.BaseAddress = $Hostname
$WebClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)
# Try to access
$TryDownload = $WebClient.DownloadString('/index.html')Return $WebClient
}Function CreateBinaryStream($FullPath) {
$Bytes = [System.IO.File]::ReadAllBytes($FullPath)
Return $Bytes
}Function GetHardwareVersion($WebClient, $StringID)
{
$Result = $false$DevnameString = $WebClient.DownloadString('/devname.cgi')
foreach ($line in $DevnameString -Split ';') {
if ($line -like $StringID) {
$RegexMatch = $line -match "'(v.*)'"
if (($RegexMatch -eq $true) -and ($matches.Count -gt 1)) {
$Result = $matches[1]
break;
}
}
}Return $Result
}Function GetBinaryVersion($BinaryStream)
{
$b = $BinaryStream[16..23]$ByteString = (($b[0] -bor $b[1]), ($b[2] -bor $b[3]), ($b[4] -bor $b[5]))
$ProcString = ($ByteString -Join '.') + '.*-' + $b[7]$ResultString = 'v' + $ProcString
Return $ResultString
}Function UploadEEPROM($WebClient, $BinaryStream)
{
$curr = 0;
$iter = 1;
$step = 1024;While (($curr + 24) -lt $BinaryStream.Length) {
$next = ($step * $iter) - 1
# Bytes transform
$HeaderBytes = @(0xFA, 0xDE, 0x00, 0x00, ($curr -band 0XFF), (($curr -shr 8) -band 0XFF), (($curr -shr 16) -band 0XFF), 0x00)
$BinaryPayload = $HeaderBytes + $BinaryStream[($curr + 24)..($next + 24)]
# Print progress
$p = [math]::Round(($curr/$BinaryStream.Length) * 100)
$t = [math]::Round(($BinaryStream.Length - 24) / 1024)
Write-Progress -Status "$p% Complete ($iter of $t)" -Activity "Uploading.." -PercentComplete $p
$Upload = $WebClient.UploadData('/eeprom_clone_set.cgi', $BinaryPayload)
$curr = $next + 1
$iter = $iter + 1}
}Function Processing ($Hostname, $Username, $Password, $BinaryFile) {
Info "Remote hardware URL:" $Hostname
# Normalize path
$FullPath = [IO.Path]::GetFullPath($BinaryFile)# Check file exists
if (-not (Test-Path $FullPath)) {
return Error "Specified binary file not found:" $FullPath
}# Create WebClient or fails if credentions are not valid
try {
$WebClient = CreateWebClient $Hostname $Username $Password
} catch [Net.WebException] {
return Error "[HTTP]" $_
}Info "Remote hardware is online, auth success"
# Open binary file as byte array
$BinaryStream = CreateBinaryStream $FullPathif (($BinaryStream[0..15] -Join '') -ne $BINARY_VERIFICATION_CODE) {
return Error "Specified binary file doesn't contains useful settings:" $FullPath
}Info "Binary file is verified successful:" $FullPath
# Get binary file version
$BinaryVersion = GetBinaryVersion $BinaryStream
Info "Binary file version received:" $BinaryVersion# Get remote hardware version
try {
$HardwareVersion = GetHardwareVersion $WebClient "*fwver*"
if ($HardwareVersion -eq $false) {
return Error "Failed to parse remote hardware version"
}
} catch [Net.WebException] {
return Error "[HTTP] Failed connection on remote hardware:" $_
}Info "Remote hardware version received:" $HardwareVersion
# Compare both versions
if (-not ($HardwareVersion -like $BinaryVersion)) {
return Error "Remote hardware and binary file versions are not matching"
}try {
UploadEEPROM $WebClient $BinaryStream
Info "Binary upload has finished successful"# $Params = New-Object System.Collections.Specialized.NameValueCollection
# $Params.Add('reboot', '%21')
# $WebClient = CreateWebClient $Hostname $Username $Password
# $Upload = $WebClient.UploadValues('/reboot.cgi', $Params)
# Write-Host 'Rebooting remote hardware..'
# Info 'Upload complete'} catch [Net.WebException] {
return Error '[HTTP] Failed to upload binaries:' $_.Exception.Message
}
}$BINARY_VERIFICATION_CODE = '5471107106488311010949995710965995353'
$HostList = Import-Csv $List
ForEach ($item in $HostList) {
try {
Processing $item.Hostname $item.Username $item.Password $item.File
} catch [Exception] {
Write-Error $_
}
}
Launching the PowerShell Script
On default, it is prohibited to execute PowerShell scenarios in the system because the scripts may have a malicious code, which can damage the system. For the time of uploading a configuration, there is a need to disable checking the execution of local scripts. To do this, launch the PowerShell console on the behalf of the administrator and enter the next command:
Set-ExecutionPolicy RemoteSigned
More information is available here: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-6
To successfully run the script, you must upgrade PowerShell to version 3.0 or higher: https://www.microsoft.com/en-us/download/details.aspx?id=50395.
Before launching the script, there is a need to specify IP address/DNS name of a NetPing device, a user name and a password for authorization, path to a binary configuration file (one line for each device) in the file list.txt in the next format:
Hostname,Username,Password,File
Example of the file list.txt:
Afterwards, open a Windows PowerShell console using the command run (combination of the keys Windows+R), and enter «Open:» powershell in the line and click the button «OK»:
In a PowerShell console specify the next command:
%PATH_TO_SCRIPT%\eeprom-upload-lbs.ps1 -List %PATH_TO_FILE%\list.txt
Example:
As a result, a script will be run and it will launch uploading a configuration to a group of NetPing devices in the network.
Errors that may take place when running the PowerShell script
Script is successfully executed when there are no errors in a report (no red lines):
The error «[ERROR] [HTTP] Unable to connect to the remote server» means that most probably, IP address/DNS name of a device is specified incorrectly, or a device is unavailable in the network because of another reason:
The error «[ERROR] [HTTP] The remote server returned an error: (401) Unauthorized.» means that user name and password for authorization on a device are specified incorrectly:
The error «[ERROR] Specified binary file not found: C:\temp1\conf\USSv3-SMS_setup_v70.6.6.A-1.bin» means that a path to a configuration binary file is specified incorrectly:
The error «The path is not of a legal form.» means that the path to a configuration binary file is not specified in the file list.txt:
The error «[ERROR] Remote hardware and binary file versions are not matching» means that the indicated configuration file is not compatible with a firmware version installed on a NetPing device.
Before uploading a configuration to EEPROM, the version identity of a «donor» and an «acceptor» are checked automatically. If a «donor» version are not matching, uploading is not performed, an error notification is displayed.
Python Script
Python script for uploading a configuration file can be downloaded from the link: Script_Python.zip.
Python Script Code
#!python
# -*- coding: cp1251 -*-from sys import argv, stderr, exit
import struct # for packing-unpacing of binary headers
import urllib2 # HTTP client
import base64 # for Http Basic Auth
import re
with open(argv[1], mode='rb') as file: # b is mandatory! it's binary file!
data = file.read()# parse file header with signature and version
hdr = struct.unpack_from("<16sHHHcB", data)
if hdr[0] != '6Gkj0Snm1c9mAc55':
stderr.write('\nWrong file content! It\'s not NetPing EEPROM image: ' + argv[1] + '\n\n')
exit(1)
ee_file_ver = 'v%u.%u.%u' % hdr[1:4] + '.*-%u' % hdr[5];# skip file header, remainder is binary EEPROM image
data = data[24:]if(argv[2]) == '-f':
# read and split targets list file
try:
with open(argv[3], mode='r') as file:
targets = file.read()
except:
stderr.write('\nWrong target list file!\n\n')
exit(2)
targets = targets.splitlines()
# filter out comments (; at line start)
targets = [k for k in targets if not k.startswith(';')]
else:
# make single-item list for single target from cmd-line args
if len(argv) < 5:
stderr.write('\nInsufficient arguments!\n\n')
exit(2)
targets = [' '.join(argv[2:5])]def add_basic_authorization_header(req, uname, passwd):
b64pass = base64.encodestring(uname + ':' + passwd)
b64pass = b64pass.replace('\n', '') # strip CR at the end added by encodestring()
req.add_header('Authorization', 'Basic ' + b64pass)# define procedure for EEPROM image upload
def upload(data, target):
try:
address, uname, passwd = target.split()
except:
return 'wrong target list string, must be \'address username password\''
# check compatibility of EEPROM image
http_req = urllib2.Request('http://' + address + '/devname.cgi')
add_basic_authorization_header(http_req, uname, passwd)
try:
devname_data = urllib2.urlopen(http_req).read()
except Exception, e:
return 'HTTP error: ' + str(e)
devname_data = re.sub(r'\.[A-Z]\-', '.*-', devname_data)
if "var fwver='" + ee_file_ver + "';" not in devname_data:
return 'EEPROM image is not appropriate'
# upload image with consecutive HTTP POST calls
offset = 0
while offset < len(data):
data_header = struct.pack("<II", 0xDEFA, offset)
data_block = data[offset : offset + 1024]
offset += 1024
http_req = urllib2.Request('http://' + address + '/eeprom_clone_set.cgi', data_header + data_block)
http_req.add_header('Content-Type', 'application/octet-stream')
add_basic_authorization_header(http_req, uname, passwd)
try:
urllib2.urlopen(http_req).read()
except Exception, e:
return 'HTTP Client error: ' + str(e) + '\n' +\
'Attention! Setup of host ' + address + ' has damaged! It must be manually initialized\n'+\
' to the default factory setup with Reset button!'
return 'success'# process list of targets (or 1-item list made from program arguments in command line)
for t in targets:
address = t.split()[0]
stderr.write('Uploading to ' + address + '... ')
stderr.flush()
result = upload(data, t)
stderr.write(result + '\n')
exit(0)
Launching the Python Script in Windows OS
Before launching the script, there is a need to install the component Python 2.x from the official web site.
After the Python 2.x installation, there is a need to specify IP address/DNS name of a NetPing device, user name and password for authorization (one line for each device) in the file targets.txt in the next format:
; Description
Hostname Username Password
An example of the file targets.txt:
Afterwards, open a command line using a command run (a combination of the keys Windows+R), enter «Open:» cmd into the line and click the button «OK»:
In a Windows command line specify a command:
python %PATH_TO_SCRIPT%\ee-upload.py %PATH_TO_CONFIGURATION_FILE%\file.bin -f %PATH_TO_FILE%\targets.txt
Example:
As a result, the script will be launched and it will start uploading a configuration to the group of NetPing devices in the network.
Launching the Python Script in CentOS 6.5 OS
The script in CentOS 6.5 OS is launched the same as in Windows OS. The only difference is, there is no need to install additional components.
Firstly, there is a need to configure the file targets.txt (see the section «Launching the Python Script in Windows OS») and then launch the script in a command line:
python %PATH_TO_SCRIPT%\ee-upload.py %PATH_TO_CONFIGURATION_FILE%\file.bin -f %PATH_TO_FILE%\targets.txt
Example:
Errors that appear when running the Python Script
The script is executed successfully when there is a notification «Uploading to 192.168.0.21... success» in a report:
The error «HTTP error: <urlopen error [Errno 110] Connection limed out>» means that most probably IP address/DNS name of a device, or a device is not available in the network because of any other reason or was specified incorrectly:
The error «Uploading to 192.168.0.21... HTTP error: HTTP Error 401: Unauthorized» means that user name and password for authorization on a device are specified incorrectly:
The error «IOError: [Errno 2] No such file or directory: '/tmp/python1/USSv3-SMS_setup_v70.6.6.A-1.bin'» means that the path to a configuration binary file is specified incorrectly:
The error «Uploading to 192.168.0.21... EEPROM image is not appropriate» means that the specified configuration file is not compatible with a firmware version, installed on a NetPing device.
Before uploading a configuration to EEPROM, the version identity of a «donor» and an «acceptor» of a configuration is checked. If a «donor» version does not match, uploading is not performed, and an error notification is displayed.