mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
Sync with IOU tools (nvram import/export).
This commit is contained in:
parent
65e7f61f96
commit
815b7d226c
@ -439,8 +439,10 @@ class IOUVM(BaseVM):
|
|||||||
try:
|
try:
|
||||||
if not os.path.exists(nvram_file):
|
if not os.path.exists(nvram_file):
|
||||||
open(nvram_file, "a").close()
|
open(nvram_file, "a").close()
|
||||||
with open(nvram_file, "rb") as file:
|
nvram_content = None
|
||||||
nvram_content = file.read()
|
else:
|
||||||
|
with open(nvram_file, "rb") as file:
|
||||||
|
nvram_content = file.read()
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise IOUError("Cannot read nvram file {}: {}".format(nvram_file, e))
|
raise IOUError("Cannot read nvram file {}: {}".format(nvram_file, e))
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ optional arguments:
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
from array import array
|
|
||||||
|
|
||||||
|
|
||||||
# Uncompress data in .Z file format.
|
# Uncompress data in .Z file format.
|
||||||
@ -49,12 +48,12 @@ def uncompress_LZC(data):
|
|||||||
LZC_NUM_BITS_MIN = 9
|
LZC_NUM_BITS_MIN = 9
|
||||||
LZC_NUM_BITS_MAX = 16
|
LZC_NUM_BITS_MAX = 16
|
||||||
|
|
||||||
in_data = array('B', data)
|
in_data = bytearray(data)
|
||||||
in_len = len(in_data)
|
in_len = len(in_data)
|
||||||
out_data = array('B')
|
out_data = bytearray()
|
||||||
|
|
||||||
if in_len == 0:
|
if in_len == 0:
|
||||||
return out_data.tostring()
|
return out_data
|
||||||
if in_len < 3:
|
if in_len < 3:
|
||||||
raise ValueError('invalid length')
|
raise ValueError('invalid length')
|
||||||
if in_data[0] != 0x1F or in_data[1] != 0x9D:
|
if in_data[0] != 0x1F or in_data[1] != 0x9D:
|
||||||
@ -66,9 +65,8 @@ def uncompress_LZC(data):
|
|||||||
if maxbits < LZC_NUM_BITS_MIN or maxbits > LZC_NUM_BITS_MAX:
|
if maxbits < LZC_NUM_BITS_MIN or maxbits > LZC_NUM_BITS_MAX:
|
||||||
raise ValueError('not supported')
|
raise ValueError('not supported')
|
||||||
|
|
||||||
parents = array('H', [0] * numItems)
|
parents = [0] * numItems
|
||||||
suffixes = array('B', [0] * numItems)
|
suffixes = [0] * numItems
|
||||||
stack = array('B', [0] * numItems)
|
|
||||||
|
|
||||||
in_pos = 3
|
in_pos = 3
|
||||||
numBits = LZC_NUM_BITS_MIN
|
numBits = LZC_NUM_BITS_MIN
|
||||||
@ -83,7 +81,7 @@ def uncompress_LZC(data):
|
|||||||
parents[256] = 0
|
parents[256] = 0
|
||||||
suffixes[256] = 0
|
suffixes[256] = 0
|
||||||
|
|
||||||
buf_extend = array('B', [0] * 3)
|
buf_extend = bytearray([0] * 3)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# fill buffer, when empty
|
# fill buffer, when empty
|
||||||
@ -114,19 +112,18 @@ def uncompress_LZC(data):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# convert symbol to string
|
# convert symbol to string
|
||||||
|
stack = []
|
||||||
cur = symbol
|
cur = symbol
|
||||||
i = len(stack)
|
|
||||||
while cur >= 256:
|
while cur >= 256:
|
||||||
i -= 1
|
stack.append(suffixes[cur])
|
||||||
stack[i] = suffixes[cur]
|
|
||||||
cur = parents[cur]
|
cur = parents[cur]
|
||||||
i -= 1
|
stack.append(cur)
|
||||||
stack[i] = cur
|
|
||||||
if needPrev:
|
if needPrev:
|
||||||
suffixes[head - 1] = cur
|
suffixes[head - 1] = cur
|
||||||
if symbol == head - 1:
|
if symbol == head - 1:
|
||||||
stack[-1] = cur
|
stack[0] = cur
|
||||||
out_data.extend(stack[i:])
|
stack.reverse()
|
||||||
|
out_data.extend(stack)
|
||||||
|
|
||||||
# update parents, check for numBits change
|
# update parents, check for numBits change
|
||||||
if head < numItems:
|
if head < numItems:
|
||||||
@ -140,7 +137,7 @@ def uncompress_LZC(data):
|
|||||||
else:
|
else:
|
||||||
needPrev = 0
|
needPrev = 0
|
||||||
|
|
||||||
return out_data.tostring()
|
return out_data
|
||||||
|
|
||||||
|
|
||||||
# extract 16 bit unsigned int from data
|
# extract 16 bit unsigned int from data
|
||||||
@ -155,7 +152,7 @@ def get_uint32(data, off):
|
|||||||
|
|
||||||
# export IOU NVRAM
|
# export IOU NVRAM
|
||||||
def nvram_export(nvram):
|
def nvram_export(nvram):
|
||||||
nvram = array('B', nvram)
|
nvram = bytearray(nvram)
|
||||||
|
|
||||||
# extract startup config
|
# extract startup config
|
||||||
offset = 0
|
offset = 0
|
||||||
@ -168,7 +165,7 @@ def nvram_export(nvram):
|
|||||||
offset += 36
|
offset += 36
|
||||||
if len(nvram) < offset + length:
|
if len(nvram) < offset + length:
|
||||||
raise ValueError('invalid length')
|
raise ValueError('invalid length')
|
||||||
startup = nvram[offset:offset+length].tostring()
|
startup = nvram[offset:offset+length]
|
||||||
|
|
||||||
# compressed startup config
|
# compressed startup config
|
||||||
if format == 2:
|
if format == 2:
|
||||||
@ -192,7 +189,7 @@ def nvram_export(nvram):
|
|||||||
length = get_uint32(nvram, offset + 12)
|
length = get_uint32(nvram, offset + 12)
|
||||||
offset += 16
|
offset += 16
|
||||||
if len(nvram) >= offset + length:
|
if len(nvram) >= offset + length:
|
||||||
private = nvram[offset:offset+length].tostring()
|
private = nvram[offset:offset+length]
|
||||||
|
|
||||||
return (startup, private)
|
return (startup, private)
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ optional arguments:
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
from array import array
|
|
||||||
|
|
||||||
|
|
||||||
# extract 16 bit unsigned int from data
|
# extract 16 bit unsigned int from data
|
||||||
@ -96,15 +95,20 @@ def nvram_import(nvram, startup, private, size):
|
|||||||
BASE_ADDRESS = 0x10000000
|
BASE_ADDRESS = 0x10000000
|
||||||
DEFAULT_IOS = 0x0F04 # IOS 15.4
|
DEFAULT_IOS = 0x0F04 # IOS 15.4
|
||||||
|
|
||||||
if size is None:
|
# check size parameter
|
||||||
nvram = array('B', nvram)
|
if size is not None and (size < 8 or size > 1024):
|
||||||
|
raise ValueError('invalid size')
|
||||||
|
|
||||||
|
# create new nvram if nvram is empty or has wrong size
|
||||||
|
if nvram is None or (size is not None and len(nvram) != size*1024):
|
||||||
|
nvram = bytearray([0] * (size*1024))
|
||||||
else:
|
else:
|
||||||
nvram = array('B', [0] * (size*1024))
|
nvram = bytearray(nvram)
|
||||||
|
|
||||||
# check nvram size
|
# check nvram size
|
||||||
nvram_len = len(nvram)
|
nvram_len = len(nvram)
|
||||||
if nvram_len < 8*1024 or nvram_len > 1024*1024 or nvram_len % 1024 != 0:
|
if nvram_len < 8*1024 or nvram_len > 1024*1024 or nvram_len % 1024 != 0:
|
||||||
raise ValueError('invalid length')
|
raise ValueError('invalid NVRAM length')
|
||||||
nvram_len = nvram_len // 2
|
nvram_len = nvram_len // 2
|
||||||
|
|
||||||
# get size of current config
|
# get size of current config
|
||||||
@ -125,7 +129,7 @@ def nvram_import(nvram, startup, private, size):
|
|||||||
# calculate max. config size
|
# calculate max. config size
|
||||||
max_config = nvram_len - 2*1024 # reserve 2k for files
|
max_config = nvram_len - 2*1024 # reserve 2k for files
|
||||||
idx = max_config
|
idx = max_config
|
||||||
empty_sector = array('B', [0] * 1024)
|
empty_sector = bytearray([0] * 1024)
|
||||||
while True:
|
while True:
|
||||||
idx -= 1024
|
idx -= 1024
|
||||||
if idx < config_len:
|
if idx < config_len:
|
||||||
@ -139,14 +143,14 @@ def nvram_import(nvram, startup, private, size):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# import startup config
|
# import startup config
|
||||||
startup = array('B', startup)
|
startup = bytearray(startup)
|
||||||
if ios is None:
|
if ios is None:
|
||||||
# Target IOS version is unknown. As some IOU don't work nicely with
|
# Target IOS version is unknown. As some IOU don't work nicely with
|
||||||
# the padding of a different version, the startup config is padded
|
# the padding of a different version, the startup config is padded
|
||||||
# with '\n' to the alignment of 4.
|
# with '\n' to the alignment of 4.
|
||||||
ios = DEFAULT_IOS
|
ios = DEFAULT_IOS
|
||||||
startup.extend([ord('\n')] * ((4 - len(startup) % 4) % 4))
|
startup.extend([ord('\n')] * ((4 - len(startup) % 4) % 4))
|
||||||
new_nvram = array('B', [0] * 36) # startup hdr
|
new_nvram = bytearray([0] * 36) # startup hdr
|
||||||
put_uint16(new_nvram, 0, 0xABCD) # magic
|
put_uint16(new_nvram, 0, 0xABCD) # magic
|
||||||
put_uint16(new_nvram, 2, 1) # raw data
|
put_uint16(new_nvram, 2, 1) # raw data
|
||||||
put_uint16(new_nvram, 6, ios) # IOS version
|
put_uint16(new_nvram, 6, ios) # IOS version
|
||||||
@ -158,9 +162,9 @@ def nvram_import(nvram, startup, private, size):
|
|||||||
|
|
||||||
# import private config
|
# import private config
|
||||||
if private is None:
|
if private is None:
|
||||||
private = array('B')
|
private = bytearray()
|
||||||
else:
|
else:
|
||||||
private = array('B', private)
|
private = bytearray(private)
|
||||||
offset = len(new_nvram)
|
offset = len(new_nvram)
|
||||||
new_nvram.extend([0] * 16) # private hdr
|
new_nvram.extend([0] * 16) # private hdr
|
||||||
put_uint16(new_nvram, 0 + offset, 0xFEDC) # magic
|
put_uint16(new_nvram, 0 + offset, 0xFEDC) # magic
|
||||||
@ -180,7 +184,7 @@ def nvram_import(nvram, startup, private, size):
|
|||||||
|
|
||||||
checksum(new_nvram, 0, nvram_len)
|
checksum(new_nvram, 0, nvram_len)
|
||||||
|
|
||||||
return new_nvram.tostring()
|
return new_nvram
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user