From 5002eeed7b5557abdce3dade8287d837f2900590 Mon Sep 17 00:00:00 2001 From: Anton Kiselev Date: Tue, 1 Nov 2016 04:11:57 +0700 Subject: scapy_service: support {vtype: BYTES, generate: ascii/bytes/template/template code } Signed-off-by: Anton Kiselev --- .../services/scapy_server/unit_tests/test_utils.py | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py (limited to 'scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py new file mode 100644 index 00000000..8ae186a2 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py @@ -0,0 +1,58 @@ +# run with 'nosetests' utility + +from basetest import * +from scapy_service import * + +def test_generate_random_bytes(): + res = generate_random_bytes(10, 333, ord('0'), ord('9')) + print(res) + assert(len(res) == 10) + assert(res == '5390532937') # random value with this seed + +def test_generate_bytes_from_template_empty(): + res = generate_bytes_from_template(5, b"") + print(res) + assert(res == b"") + +def test_generate_bytes_from_template_less(): + res = generate_bytes_from_template(5, b"qwe") + print(res) + assert(res == b"qweqw") + +def test_generate_bytes_from_template_same(): + res = generate_bytes_from_template(5, b"qwert") + print(res) + assert(res == b"qwert") + +def test_generate_bytes_from_template_more(): + res = generate_bytes_from_template(5, b"qwerty") + print(res) + assert(res == b"qwert") + +def test_parse_template_code_with_trash(): + res = parse_template_code("0xDE AD\n be ef \t0xDEAD") + print(res) + assert(res == bytearray.fromhex('DEADBEEFDEAD')) + +def test_generate_bytes(): + res = generate_bytes({"generate":"random_bytes", "seed": 123, "size": 12}) + print(res) + assert(len(res) == 12) + +def test_generate_ascii_default_seed(): + res = generate_bytes({"generate":"random_ascii", "size": 14}) + print(res) + assert(len(res) == 14) + + +def test_generate_template_code(): + res = generate_bytes({"generate":"template_code", "template_code": "0xDEAD 0xBEEF", "size": 6}) + print(res) + assert(res == bytearray.fromhex('DE AD BE EF DE AD')) + +def test_generate_template_code(): + res = generate_bytes({"generate":"template", "template_base64": bytes_to_b64(b'hi'), "size": 5}) + print(res) + assert(res == b'hihih') + + -- cgit 1.2.3-korg From cdbdece3c94e98d2dca2cdddb4aeee4a1f29c5c6 Mon Sep 17 00:00:00 2001 From: Anton Kiselev Date: Tue, 1 Nov 2016 11:49:59 +0700 Subject: scapy_service: support total_bytes for BYTES payload generator Signed-off-by: Anton Kiselev --- .../stl/services/scapy_server/scapy_service.py | 43 ++++++++++++++-------- .../scapy_server/unit_tests/test_scapy_service.py | 29 +++++++++++++++ .../services/scapy_server/unit_tests/test_utils.py | 4 ++ 3 files changed, 60 insertions(+), 16 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py index 16261b8d..79f5d52b 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -320,6 +320,8 @@ def generate_bytes(bytes_definition): return generate_bytes_from_template(bytes_size, b64_to_bytes(bytes_definition["template_base64"])) elif gen_type == 'template_code': return generate_bytes_from_template(bytes_size, bytes_definition["template_code"]) + elif gen_type == None: + return b64_to_bytes(bytes_definition['base64']) class ScapyException(Exception): pass @@ -424,10 +426,7 @@ class Scapy_service(Scapy_service_api): if value_type == 'EXPRESSION': return eval(val['expr'], {}) elif value_type == 'BYTES': # bytes payload(ex Raw.load) - if 'generate' in val: - return generate_bytes(val) - else: - return b64_to_bytes(val['base64']) + return generate_bytes(val) elif value_type == 'OBJECT': return val['value'] else: @@ -437,7 +436,7 @@ class Scapy_service(Scapy_service_api): else: return val - def _field_value_from_def(self, layer, fieldId, val): + def _field_value_from_def(self, scapy_pkt, layer, fieldId, val): field_desc = layer.get_field(fieldId) sample_val = get_sample_field_val(layer, fieldId) # extensions for field values @@ -449,6 +448,16 @@ class Scapy_service(Scapy_service_api): return field_desc.randval() elif value_type == 'MACHINE': # internal machine field repr return field_desc.m2i(layer, b64_to_bytes(val['base64'])) + elif value_type == 'BYTES': + if 'total_size' in val: # custom case for total pkt size + gen = {} + gen.update(val) + total_sz = gen['total_size'] + del gen['total_size'] + gen['size'] = total_sz - len(scapy_pkt) + return generate_bytes(gen) + else: + return generate_bytes(val) if is_number(sample_val) and is_string(val): # human-value. guess the type and convert to internal value # seems setfieldval already does this for some fields, @@ -638,22 +647,24 @@ class Scapy_service(Scapy_service_api): def _verify_version_handler(self,client_v_handler): return (self.server_v_hashed == client_v_handler) - def _parse_packet_dict(self,layer,scapy_layers,scapy_layer_names): - class_name = scapy_layer_names.index(layer['id']) - class_p = scapy_layers[class_name] # class pointer + def _parse_packet_dict(self, layer, layer_classes, base_layer): + class_p = layer_classes[layer['id']] # class id -> class dict scapy_layer = class_p() if isinstance(scapy_layer, Raw): scapy_layer.load = str_to_bytes("dummy") + if base_layer == None: + base_layer = scapy_layer if 'fields' in layer: - self._modify_layer(scapy_layer, layer['fields']) + self._modify_layer(base_layer, scapy_layer, layer['fields']) return scapy_layer def _packet_model_to_scapy_packet(self,data): - layers = Packet.__subclasses__() - layer_names = [ layer.__name__ for layer in layers] - base_layer = self._parse_packet_dict(data[0],layers,layer_names) + layer_classes = {} + for layer_class in Packet.__subclasses__(): + layer_classes[layer_class.__name__] = layer_class + base_layer = self._parse_packet_dict(data[0], layer_classes, None) for i in range(1,len(data),1): - packet_layer = self._parse_packet_dict(data[i],layers,layer_names) + packet_layer = self._parse_packet_dict(data[i], layer_classes, base_layer) base_layer = base_layer/packet_layer return base_layer @@ -798,10 +809,10 @@ class Scapy_service(Scapy_service_api): else: raise ScapyException("Fields DB is not up to date") - def _modify_layer(self, scapy_layer, fields): + def _modify_layer(self, scapy_pkt, scapy_layer, fields): for field in fields: fieldId = str(field['id']) - fieldval = self._field_value_from_def(scapy_layer, fieldId, field['value']) + fieldval = self._field_value_from_def(scapy_pkt, scapy_layer, fieldId, field['value']) if fieldval is not None: scapy_layer.setfieldval(fieldId, fieldval) else: @@ -840,7 +851,7 @@ class Scapy_service(Scapy_service_api): # TODO: support replacing payload, instead of breaking raise ScapyException("Protocol id inconsistent") if 'fields' in model_layer: - self._modify_layer(scapy_layer, model_layer['fields']) + self._modify_layer(scapy_pkt, scapy_layer, model_layer['fields']) return self._pkt_data(scapy_pkt) def read_pcap(self,client_v_handler,pcap_base64): diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py index b2bc8e03..0cecbfef 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py @@ -78,6 +78,35 @@ def test_build_Raw(): ]) assert(str(pkt[Raw].load == "hi")) +def test_build_fixed_pkt_size_bytes_gen(): + pkt = build_pkt_get_scapy([ + layer_def("Ether"), + layer_def("IP"), + layer_def("TCP"), + layer_def("Raw", load={ + "vtype": "BYTES", + "generate": "template", + "total_size": 64, + "template_base64": bytes_to_b64(b"hi") + }) + ]) + print(len(pkt)) + assert(len(pkt) == 64) + +def test_build_fixed_pkt_size_bytes_gen(): + pkt = build_pkt_get_scapy([ + layer_def("Ether"), + layer_def("IP"), + layer_def("TCP"), + layer_def("Raw", load={ + "vtype": "BYTES", + "generate": "random_ascii", + "total_size": 256 + }) + ]) + print(len(pkt)) + assert(len(pkt) == 256) + def test_get_all(): service.get_all(v_handler) diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py index 8ae186a2..82261859 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py @@ -14,6 +14,10 @@ def test_generate_bytes_from_template_empty(): print(res) assert(res == b"") +def test_generate_bytes_from_template_neg(): + res = generate_bytes_from_template(-5, b"qwe") + assert(res == b"") + def test_generate_bytes_from_template_less(): res = generate_bytes_from_template(5, b"qwe") print(res) -- cgit 1.2.3-korg From 3e48c0b5d1b21554eea8d12bc66175a9157a6951 Mon Sep 17 00:00:00 2001 From: Anton Kiselev Date: Tue, 1 Nov 2016 19:19:48 +0700 Subject: scapy server python 3 compatibility fixes(file and pseudo-random generator) Signed-off-by: Anton Kiselev --- .../stl/services/scapy_server/scapy_service.py | 13 +++++++++---- .../stl/services/scapy_server/unit_tests/test_utils.py | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py index 118d7d6e..80e2fc99 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -282,12 +282,17 @@ def get_sample_field_val(scapy_layer, fieldId): def generate_random_bytes(sz, seed, start, end): # generate bytes of specified range with a fixed seed and size - rnd = random.Random(seed) - end = end + 1 # to include end value - res = [rnd.randrange(start, end) for _i in range(sz)] + rnd = random.Random() + n = end - start + 1 if is_python(2): + rnd = random.Random(seed) + res = [start + int(rnd.random()*n) for _i in range(sz)] return ''.join(chr(x) for x in res) else: + rnd = random.Random() + # to generate same random sequence as 2.x + rnd.seed(seed, version=1) + res = [start + int(rnd.random()*n) for _i in range(sz)] return bytes(res) def generate_bytes_from_template(sz, template): @@ -363,7 +368,7 @@ class Scapy_service(Scapy_service_api): def _load_definitions_from_json(self): # load protocol definitions from a json file self.protocol_definitions = {} - with file('protocols.json') as f: + with open('protocols.json', 'r') as f: protocols = json.load(f) for protocol in protocols: self.protocol_definitions[ protocol['id'] ] = protocol diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py index 82261859..c1fb0478 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py @@ -7,7 +7,7 @@ def test_generate_random_bytes(): res = generate_random_bytes(10, 333, ord('0'), ord('9')) print(res) assert(len(res) == 10) - assert(res == '5390532937') # random value with this seed + assert(res == b'5390532937') # random value with this seed def test_generate_bytes_from_template_empty(): res = generate_bytes_from_template(5, b"") -- cgit 1.2.3-korg From 27f7cc1e5e3d750e830253a1986ffb315b3751b7 Mon Sep 17 00:00:00 2001 From: Anton Kiselev Date: Tue, 8 Nov 2016 16:12:47 +0700 Subject: fixup template_code payload generation Signed-off-by: Anton Kiselev --- .../trex_control_plane/stl/services/scapy_server/scapy_service.py | 2 +- .../stl/services/scapy_server/unit_tests/test_utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py index 5a31410a..f889bb93 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -329,7 +329,7 @@ def generate_bytes(bytes_definition): elif gen_type == 'template': return generate_bytes_from_template(bytes_size, b64_to_bytes(bytes_definition["template_base64"])) elif gen_type == 'template_code': - return generate_bytes_from_template(bytes_size, bytes_definition["template_code"]) + return generate_bytes_from_template(bytes_size, parse_template_code(bytes_definition["template_code"])) class ScapyException(Exception): pass diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py index c1fb0478..e9fbcc80 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py @@ -54,7 +54,7 @@ def test_generate_template_code(): print(res) assert(res == bytearray.fromhex('DE AD BE EF DE AD')) -def test_generate_template_code(): +def test_generate_template_base64(): res = generate_bytes({"generate":"template", "template_base64": bytes_to_b64(b'hi'), "size": 5}) print(res) assert(res == b'hihih') -- cgit 1.2.3-korg From 879150e9c79961e07900dfce02c5b53385bc74cb Mon Sep 17 00:00:00 2001 From: Anton Kiselev Date: Tue, 8 Nov 2016 17:09:32 +0700 Subject: scapy_service payload gen: allow template_code without size property Signed-off-by: Anton Kiselev --- .../stl/services/scapy_server/scapy_service.py | 16 +++++++++++----- .../stl/services/scapy_server/unit_tests/test_utils.py | 11 +++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py index f889bb93..88514aa8 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -309,6 +309,11 @@ def parse_template_code(template_code): template_code = re.sub("[\s]", '', template_code) # remove spaces return bytearray.fromhex(template_code) +def verify_payload_size(size): + assert(size != None) + if (size > (1<<20)): # 1Mb ought to be enough for anybody + raise ValueError('size is too large') + def generate_bytes(bytes_definition): # accepts a bytes definition object # {generate: random_bytes or random_ascii, seed: , size: } @@ -317,20 +322,21 @@ def generate_bytes(bytes_definition): gen_type = bytes_definition.get('generate') if gen_type == None: return b64_to_bytes(bytes_definition['base64']) + elif gen_type == 'template_code': + code = parse_template_code(bytes_definition["template_code"]) + bytes_size = int(bytes_definition.get('size') or len(code)) + verify_payload_size(bytes_size) + return generate_bytes_from_template(bytes_size, code) else: bytes_size = int(bytes_definition['size']) # required seed = int(bytes_definition.get('seed') or 12345) # optional - if (bytes_size > (1<<20)): # 1Mb ought to be enough for anybody - raise ValueError('size is too large') + verify_payload_size(bytes_size) if gen_type == 'random_bytes': return generate_random_bytes(bytes_size, seed, 0, 0xFF) elif gen_type == 'random_ascii': return generate_random_bytes(bytes_size, seed, 0x20, 0x7E) elif gen_type == 'template': return generate_bytes_from_template(bytes_size, b64_to_bytes(bytes_definition["template_base64"])) - elif gen_type == 'template_code': - return generate_bytes_from_template(bytes_size, parse_template_code(bytes_definition["template_code"])) - class ScapyException(Exception): pass class Scapy_service(Scapy_service_api): diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py index e9fbcc80..ceb88b47 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_utils.py @@ -49,9 +49,16 @@ def test_generate_ascii_default_seed(): assert(len(res) == 14) -def test_generate_template_code(): +def test_generate_template_code_no_size(): + res = generate_bytes({"generate":"template_code", "template_code": "BE EF"}) + assert(res == bytearray.fromhex('BE EF')) + +def test_generate_template_code_less(): + res = generate_bytes({"generate":"template_code", "template_code": "DE AD BE EF", "size": 2}) + assert(res == bytearray.fromhex('DE AD')) + +def test_generate_template_code_more(): res = generate_bytes({"generate":"template_code", "template_code": "0xDEAD 0xBEEF", "size": 6}) - print(res) assert(res == bytearray.fromhex('DE AD BE EF DE AD')) def test_generate_template_base64(): -- cgit 1.2.3-korg