1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-25 01:38:08 +00:00

Sync with IOU tools (nvram import/export).

This commit is contained in:
grossmj 2015-06-08 10:07:54 -06:00
parent 65e7f61f96
commit 815b7d226c
3 changed files with 35 additions and 32 deletions

View File

@ -439,6 +439,8 @@ 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()
nvram_content = None
else:
with open(nvram_file, "rb") as file: with open(nvram_file, "rb") as file:
nvram_content = file.read() nvram_content = file.read()
except OSError as e: except OSError as e:

View File

@ -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)

View File

@ -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__':