@ -1,11 +1,11 @@
#!/usr/bin/env python3
#!/usr/bin/env python3
from dvrip import DVRIPCam
from dvrip import DVRIPCam
from telnetlib import Telnet
import argparse
import argparse
import datetime
import datetime
import json
import json
import os
import os
import re
import socket
import socket
import time
import time
import requests
import requests
@ -63,14 +63,8 @@ conf = {
def add_flashes ( desc , swver ) :
def add_flashes ( desc , swver ) :
board = conf . get ( swver )
board = conf . get ( swver , XMV4 )
if board is None :
desc [ " SupportFlashType " ] = [ { " FlashID " : fid } for fid in board [ " flashes " ] ]
return
fls = [ ]
for i in board [ " flashes " ] :
fls . append ( { " FlashID " : i } )
desc [ " SupportFlashType " ] = fls
def get_envtool ( swver ) :
def get_envtool ( swver ) :
@ -112,14 +106,63 @@ def cmd_telnetd(port):
}
}
def cmd_backup ( ) :
def _read_until ( sock , token , timeout ) :
return [
deadline = time . monotonic ( ) + timeout
{
buf = bytearray ( )
" Command " : " Shell " ,
sock . settimeout ( 0.5 )
" Script " : " mount -o nolock 95.217.179.189:/srv/ro /utils/ " ,
while time . monotonic ( ) < deadline :
} ,
try :
{ " Command " : " Shell " , " Script " : " /utils/ipctool -w " } ,
chunk = sock . recv ( 4096 )
]
except socket . timeout :
if token in buf :
break
continue
if not chunk :
break
buf . extend ( chunk )
if token in buf :
break
return bytes ( buf )
def do_backup_via_telnet ( host_ip , nfs_share , mount_point = " /utils " ) :
if not check_port ( host_ip , 23 ) :
print ( f " Telnet (port 23) is not open on { host_ip } . " )
print ( " Enable it first by running: "
f " python3 telnet_opener.py { host_ip } " )
return
print ( f " Connecting to { host_ip } :23 as root/xmhdipc " )
s = socket . create_connection ( ( host_ip , 23 ) , timeout = 10 )
_read_until ( s , b " login: " , 5 )
s . sendall ( b " root \n " )
_read_until ( s , b " assword: " , 5 )
s . sendall ( b " xmhdipc \n " )
_read_until ( s , b " # " , 5 )
s . sendall ( f " mkdir -p { mount_point } \n " . encode ( ) )
_read_until ( s , b " # " , 5 )
s . sendall ( f " mount -o nolock { nfs_share } { mount_point } \n " . encode ( ) )
out = _read_until ( s , b " # " , 10 ) . decode ( errors = " replace " )
print ( out . strip ( ) )
s . sendall ( b " cat /sys/class/net/eth0/address \n " )
out = _read_until ( s , b " # " , 5 ) . decode ( errors = " replace " )
m = re . search ( r " ([0-9a-f] {2} (?::[0-9a-f] {2} ) {5} ) " , out . lower ( ) )
mac = m . group ( 1 ) if m else " unknown "
backup_path = f " { mount_point } /backup- { mac } "
print ( f " Running ipctool backup -> { backup_path } " )
s . sendall ( f " { mount_point } /ipctool backup { backup_path } \n " . encode ( ) )
out = _read_until ( s , b " # " , 120 ) . decode ( errors = " replace " )
print ( out . strip ( ) )
s . sendall ( f " umount { mount_point } \n " . encode ( ) )
_read_until ( s , b " # " , 5 )
s . sendall ( b " exit \n " )
s . close ( )
print ( f " Done. Backup file is at { nfs_share . rstrip ( ' / ' ) } /backup- { mac } "
" on your NFS server. " )
def downgrade_old_version ( cam , buildtime , swver ) :
def downgrade_old_version ( cam , buildtime , swver ) :
@ -158,9 +201,18 @@ def downgrade_old_version(cam, buildtime, swver):
def open_telnet ( host_ip , port , * * kwargs ) :
def open_telnet ( host_ip , port , * * kwargs ) :
make_telnet = kwargs . get ( " telnet " , False )
make_telnet = kwargs . get ( " telnet " , False )
make_backup = kwargs . get ( " backup " , False )
make_backup = kwargs . get ( " backup " , False )
nfs_share = kwargs . get ( " nfs " )
user = kwargs . get ( " username " , " admin " )
user = kwargs . get ( " username " , " admin " )
password = kwargs . get ( " password " , " " )
password = kwargs . get ( " password " , " " )
if make_backup :
if not nfs_share :
print ( " --backup requires --nfs HOST:/exported/path "
" (NFS share with ipctool, where the backup will be written) " )
return
do_backup_via_telnet ( host_ip , nfs_share )
return
cam = DVRIPCam ( host_ip , user = user , password = password )
cam = DVRIPCam ( host_ip , user = user , password = password )
if not cam . login ( ) :
if not cam . login ( ) :
print ( f " Cannot connect { host_ip } " )
print ( f " Cannot connect { host_ip } " )
@ -186,8 +238,6 @@ def open_telnet(host_ip, port, **kwargs):
upcmd = [ ]
upcmd = [ ]
if make_telnet :
if make_telnet :
upcmd . append ( cmd_telnetd ( port ) )
upcmd . append ( cmd_telnetd ( port ) )
elif make_backup :
upcmd = cmd_backup ( )
else :
else :
upcmd . append ( cmd_armebenv ( swver ) )
upcmd . append ( cmd_armebenv ( swver ) )
desc [ " UpgradeCommand " ] = upcmd
desc [ " UpgradeCommand " ] = upcmd
@ -199,10 +249,6 @@ def open_telnet(host_ip, port, **kwargs):
cam . close ( )
cam . close ( )
os . remove ( zipfname )
os . remove ( zipfname )
if make_backup :
print ( " Check backup " )
return
if not make_telnet :
if not make_telnet :
port = 23
port = 23
print ( " Waiting for camera is rebooting... " )
print ( " Waiting for camera is rebooting... " )
@ -228,7 +274,11 @@ def main():
" -p " , " --password " , default = " " , help = " Password for camera login "
" -p " , " --password " , default = " " , help = " Password for camera login "
)
)
parser . add_argument (
parser . add_argument (
" -b " , " --backup " , action = " store_true " , help = " Make backup to the cloud "
" -b " ,
" --backup " ,
action = " store_true " ,
help = " Telnet in (root/xmhdipc), mount NFS, run ipctool backup "
" (requires --nfs and telnet already enabled on the camera) " ,
)
)
parser . add_argument (
parser . add_argument (
" -t " ,
" -t " ,
@ -236,6 +286,11 @@ def main():
action = " store_true " ,
action = " store_true " ,
help = " Open telnet port without rebooting camera " ,
help = " Open telnet port without rebooting camera " ,
)
)
parser . add_argument (
" --nfs " ,
help = " NFS share for --backup, e.g. 10.0.0.1:/srv/ipctool. "
" Must contain the ipctool binary; backup-<MAC> is written here. " ,
)
args = parser . parse_args ( )
args = parser . parse_args ( )
open_telnet ( args . hostname , TELNET_PORT , * * vars ( args ) )
open_telnet ( args . hostname , TELNET_PORT , * * vars ( args ) )