From b8b5ad76e441e9e2793d25ba048a1e3398be3a73 Mon Sep 17 00:00:00 2001 From: itraviv Date: Wed, 3 Aug 2016 11:35:42 +0300 Subject: 1) changed location. from examples to services 2) added wrapper scapy server class --- .../stl/services/scapy_server/scapy_server.py | 275 +++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py new file mode 100755 index 00000000..2460b584 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py @@ -0,0 +1,275 @@ + +import os +stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir, 'trex_control_plane','stl','trex_stl_lib')) +import trex_stl_lib +from trex_stl_lib.api import * +from copy import deepcopy +import sys +import tempfile +import hashlib +import binascii + + +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO + +""" + **** output redirection template **** +old_stdout = sys.stdout +sys.stdout = mystdout = StringIO() + +ls() + +sys.stdout = old_stdout + +a= mystdout.getvalue() + +f = open('scapy_supported_formats.txt','w') +f.write(a) +f.close() +""" + +class scapy_server: + +#---------------------------------------------------------------------------------------------------- + class scapyRegex: + def __init__(self,FieldName,regex='empty'): + self.FieldName = FieldName + self.regex = regex + + def stringRegex(self): + return self.regex + + class pktResult(BaseException): + def __init__(self,result,errorCode,errorDesc): + self.result = result + self.errorCode = errorCode + self.errorDesc = errorDesc + + def convert2tuple(self): + return tuple([self.result,self.errorCode,self.errorDesc]) +#---------------------------------------------------------------------------------------------------- + + def __init__(self): + self.Raw = {'Raw':''} + self.high_level_protocols = ['Raw'] + self.transport_protocols = {'TCP':self.Raw,'UDP':self.Raw} + self.network_protocols = {'IP':self.transport_protocols ,'ARP':''} + self.low_level_protocols = { 'Ether': self.network_protocols } + self.regexDB= {'MACField' : self.scapyRegex('MACField','^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$'), + 'IPField' : self.scapyRegex('IPField','^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')} + self.all_protocols = self.build_lib() + self.protocol_tree = self.build_tree() + +#-------------------------------------------------------TREE IMPLEMENTATION ------------------------ + class node(object): + def __init__(self, value):#, children = []): + self.value = value + self.children = [] + + def __str__(self, level=0): + ret = "\t"*level+repr(self.value)+"\n" + for child in self.children: + ret += child.__str__(level+1) + return ret + + def build_nodes(self,data,dictionary): + n = self.node(data) + if len(dictionary)==0: + n.children=[] + return n + for obj in dictionary.keys(): + if not (obj==''): + x = self.build_nodes(obj,dictionary[obj]) + n.children.append(x) + return n + + def build_tree(self): + root = self.node('ALL') + root.children = [] + root = self.build_nodes('ALL',self.low_level_protocols) + return root + + def protocol_struct(self,protocol=''): + if '_' in protocol: + return [] + if not protocol=='': + if protocol not in self.all_protocols: + return 'protocol not supported' + protocol = eval(protocol) + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + if not protocol=='': + ls(protocol) + else: + ls() + sys.stdout = old_stdout + protocol_data= mystdout.getvalue() + return protocol_data + + def build_lib(self): + lib = self.protocol_struct() + lib = lib.split('\n') + all_protocols=[] + for entry in lib: + entry = entry.split(':') + all_protocols.append(entry[0].strip()) + del all_protocols[len(all_protocols)-1] + return all_protocols + + def parse_description_line(self,line): + line_arr = [x.strip() for x in re.split(': | = ',line)] + return tuple(line_arr) + + def parse_entire_description(self,description): + description = description.split('\n') + description_list = [self.parse_description_line(x) for x in description] + del description_list[len(description_list)-1] + return description_list + + def get_protocol_details(self,p_name): + protocol_str = self.protocol_struct(p_name) + if protocol_str=='protocol not supported': + return 'protocol not supported' + if len(protocol_str) is 0: + return [] + tupled_protocol = self.parse_entire_description(protocol_str) + return tupled_protocol + + def print_tree_level(self,root,level=0): + output = "\t"*level+str(root.value) + print (output) + if len(root.children)==0: + return + for child in root.children: + self.print_tree_level(child,level+1) + + def print_tree(self): + self.print_tree_level(self.protocol_tree) + + def get_all_protocols(self): + return self.all_protocols + + def get_tree(self): + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + print_tree(t) + sys.stdout = old_stdout + a= mystdout.getvalue() + return a + + def get_all_db(self): + db = {} + for pro in self.all_protocols: + details = self.get_protocol_details(pro) + db[pro] = details + return db + + def get_all_fields(self): + fields = [] + for pro in self.all_protocols: + details = self.get_protocol_details(pro) + for i in range(0,len(details),1): + if len(details[i]) is 3: + fields.append(details[i][1]) + uniqeFields = list(set(fields)) + fieldDict = {} + for f in uniqeFields: + if f in self.regexDB: + fieldDict[f] = self.regexDB[f].stringRegex() + else: + fieldDict[f] = self.scapyRegex(f).stringRegex() + return fieldDict + + def show2toDict(self,pkt): + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + pkt.show2() + sys.stdout = old_stdout + show2data = mystdout.getvalue() #show2 data + listedShow2Data = show2data.split('###') + show2Dict = {} + for i in range(1,len(listedShow2Data)-1,2): + protocol_fields = listedShow2Data[i+1] + protocol_fields = protocol_fields.split('\n')[1:-1] + protocol_fields = [f.strip() for f in protocol_fields] + layer_name = re.sub(r'\W+', '',listedShow2Data[i]) #clear layer name to include only alpha-numeric + show2Dict[layer_name] = protocol_fields + return show2Dict + +#pkt_desc as string +#dictionary of offsets per protocol. tuple for each field: (name, offset, size) at json format + def get_all_pkt_offsets(self,pkt_desc): + pkt_protocols = pkt_desc.split('/') + scapy_pkt = eval(pkt_desc) + total_protocols = len(pkt_protocols) + res = {} + for i in range(total_protocols): + fields = [] + for field in scapy_pkt.fields_desc: + size = field.get_size_bytes() + if field.name is 'load': + size = len(scapy_pkt) + fields.append([field.name, field.offset, size]) + layer_name = pkt_protocols[i].partition('(')[0] #clear layer name to include only alpha-numeric + layer_name = re.sub(r'\W+', '',layer_name) + res[layer_name] = fields + scapy_pkt=scapy_pkt.payload + return res + + +# pkt_descriptor in string format + + def build_pkt(self,pkt_descriptor): + pkt = eval(pkt_descriptor) + show2data = self.show2toDict(pkt) + bufferData = str(pkt) #pkt buffer + bufferData = binascii.b2a_base64(bufferData) + pkt_offsets = self.get_all_pkt_offsets(pkt_descriptor) + res = [show2data,bufferData,pkt_offsets] + return res + + +#input: container +#output: md5 encoded in base64 + def getMD5(self,container): + container = json.dumps(container) + m = hashlib.md5() + m.update(container.encode('ascii')) + res_md5 = binascii.b2a_base64(m.digest()) + return res_md5 + + + def get_all(self): + fields=self.get_all_fields() + db=self.get_all_db() + fields_md5 = self.getMD5(fields) + db_md5 = self.getMD5(db) + res = {} + res['db'] = db + res['fields'] = fields + res['db_md5'] = db_md5 + res['fields_md5'] = fields_md5 + return res + +#input in string encoded base64 + def check_update(self,db_md5,field_md5): + fields=self.get_all_fields() + db=self.get_all_db() + current_db_md5 = self.getMD5(db) + current_field_md5 = self.getMD5(fields) + res = [] + if field_md5 == current_field_md5: + if db_md5 == current_db_md5: + return True + else: + raise Exception("Protocol DB is not up to date") + else: + raise Exception("Fields DB is not up to date") + + def get_version(self): + return {'built_by':'itraviv','version':'v1.0'} + + -- cgit From 36f1db884d653f077bdafab908cbbf65833e8772 Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 4 Aug 2016 16:07:04 +0300 Subject: 1) changed class name to 'scapy_service' 2) changed returned values to be dictionaries instead of arrays --- .../stl/services/scapy_server/scapy_server.py | 49 ++++++--- .../services/scapy_server/zmq_for_scapy_server.py | 118 +++++++++++++++++++++ .../scapy_server/zmq_for_scapy_server_test.py | 14 +++ 3 files changed, 166 insertions(+), 15 deletions(-) create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py index 2460b584..ca09333c 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py @@ -1,6 +1,8 @@ import os -stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir, 'trex_control_plane','stl','trex_stl_lib')) +import sys +stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir)) +sys.path.append(stl_pathname) import trex_stl_lib from trex_stl_lib.api import * from copy import deepcopy @@ -31,7 +33,9 @@ f.write(a) f.close() """ -class scapy_server: +class ScapyException(Exception): pass + +class scapy_service: #---------------------------------------------------------------------------------------------------- class scapyRegex: @@ -183,7 +187,7 @@ class scapy_server: fieldDict[f] = self.scapyRegex(f).stringRegex() return fieldDict - def show2toDict(self,pkt): + def show2_to_dict(self,pkt): old_stdout = sys.stdout sys.stdout = mystdout = StringIO() pkt.show2() @@ -195,8 +199,14 @@ class scapy_server: protocol_fields = listedShow2Data[i+1] protocol_fields = protocol_fields.split('\n')[1:-1] protocol_fields = [f.strip() for f in protocol_fields] + protocol_fields_dict = {} + for f in protocol_fields: + field_data = f.split('=') + if len(field_data)!= 1 : + field_name = field_data[0].strip() + protocol_fields_dict[field_name] = field_data[1].strip() layer_name = re.sub(r'\W+', '',listedShow2Data[i]) #clear layer name to include only alpha-numeric - show2Dict[layer_name] = protocol_fields + show2Dict[layer_name] = protocol_fields_dict return show2Dict #pkt_desc as string @@ -207,12 +217,12 @@ class scapy_server: total_protocols = len(pkt_protocols) res = {} for i in range(total_protocols): - fields = [] + fields = {} for field in scapy_pkt.fields_desc: size = field.get_size_bytes() if field.name is 'load': size = len(scapy_pkt) - fields.append([field.name, field.offset, size]) + fields[field.name]=[field.offset, size] layer_name = pkt_protocols[i].partition('(')[0] #clear layer name to include only alpha-numeric layer_name = re.sub(r'\W+', '',layer_name) res[layer_name] = fields @@ -224,17 +234,20 @@ class scapy_server: def build_pkt(self,pkt_descriptor): pkt = eval(pkt_descriptor) - show2data = self.show2toDict(pkt) + show2data = self.show2_to_dict(pkt) bufferData = str(pkt) #pkt buffer bufferData = binascii.b2a_base64(bufferData) pkt_offsets = self.get_all_pkt_offsets(pkt_descriptor) - res = [show2data,bufferData,pkt_offsets] + res = {} + res['show2'] = show2data + res['buffer'] = bufferData + res['offsets'] = pkt_offsets return res #input: container #output: md5 encoded in base64 - def getMD5(self,container): + def get_md5(self,container): container = json.dumps(container) m = hashlib.md5() m.update(container.encode('ascii')) @@ -245,8 +258,8 @@ class scapy_server: def get_all(self): fields=self.get_all_fields() db=self.get_all_db() - fields_md5 = self.getMD5(fields) - db_md5 = self.getMD5(db) + fields_md5 = self.get_md5(fields) + db_md5 = self.get_md5(db) res = {} res['db'] = db res['fields'] = fields @@ -258,18 +271,24 @@ class scapy_server: def check_update(self,db_md5,field_md5): fields=self.get_all_fields() db=self.get_all_db() - current_db_md5 = self.getMD5(db) - current_field_md5 = self.getMD5(fields) + current_db_md5 = self.get_md5(db) + current_field_md5 = self.get_md5(fields) res = [] if field_md5 == current_field_md5: if db_md5 == current_db_md5: return True else: - raise Exception("Protocol DB is not up to date") + raise ScapyException("Protocol DB is not up to date") else: - raise Exception("Fields DB is not up to date") + raise ScapyException("Fields DB is not up to date") def get_version(self): return {'built_by':'itraviv','version':'v1.0'} + def supported_methods(self,method_name): + if method_name in dir(scapy_service): + return True + return False + + diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py new file mode 100755 index 00000000..82118bb9 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py @@ -0,0 +1,118 @@ +# +# Hello World server in Python +# Binds REP socket to tcp://*:5555 +# Expects b"Hello" from client, replies with b"World" +# + +import time +import sys +sys.path.append(sys.path.append('/auto/srg-sce-swinfra-usr/emb/users/itraviv/trex/trex-core/scripts/external_libs/pyzmq-14.5.0/python2/fedora18/64bit')) +sys.path.append(sys.path.append('/auto/srg-sce-swinfra-usr/emb/users/itraviv/trex/trex-core/scripts/automation/trex_control_plane/stl/')) +import zmq +import inspect +from scapy_server import * + +server_file_name = 'zmq_server_hello_world_server' + +context = zmq.Context() +socket = context.socket(zmq.REP) +socket.bind("tcp://*:5555") + + +class ParseException(Exception): pass +class InvalidRequest(Exception): pass +class MethodNotFound(Exception): pass +class InvalidParams(Exception): pass +#def error_response() + +class Scapy_wrapper: + def __init__(self): + self.scapy_master = scapy_service() + + def parse_req_msg(self,JSON_req): + try: + req = json.loads(JSON_req) + req_id='null' + if (type(req)!= type({})): + raise ParseException(req_id) + json_rpc_keys = ['jsonrpc','id','method'] + if ((set(req.keys())!=set(json_rpc_keys)) and (set(req.keys())!=set(json_rpc_keys+['params']))) : + if 'id' in req.keys(): + req_id = req['id'] + raise InvalidRequest(req_id) + req_id = req['id'] + if not (self.scapy_master.supported_methods(req['method'])): + raise MethodNotFound(req_id) + scapy_method = eval("self.scapy_master."+req['method']) + arg_num_for_method = len(inspect.getargspec(scapy_method)[0]) + if (arg_num_for_method>1) : + if not ('params' in req.keys()): + raise InvalidRequest(req_id) + params_len = len(req['params'])+1 # +1 because "self" is considered parameter in args for method + if not (params_len==arg_num_for_method): + raise InvalidParams(req_id) + return req['method'],req['params'],req_id + else: + return req['method'],[],req_id + except ValueError: + raise ParseException(req_id) + + def create_error_response(self,error_code,error_msg,req_id='null'): + return {"jsonrpc": "2.0", "error": {"code": error_code, "message:": error_msg}, "id": req_id} + + def create_success_response(self,result,req_id='null'): + return {"jsonrpc": "2.0", "result": result, "id": req_id } + + def getException(self): + return sys.exc_info() + + def metaraise(self,exc_info): + raise exc_info[0], exc_info[1], exc_info[2] + + + def error_handler(self,exception_obj): + try: + self.metaraise(exception_obj) + except ParseException as e: + response = self.create_error_response(-32700,'Parse error',e.message) + except InvalidRequest as e: + response = self.create_error_response(-32600,'Invalid Request',e.message) + except MethodNotFound as e: + response = self.create_error_response(-32601,'Method not found',e.message) + except InvalidParams as e: + response = self.create_error_response(-32603,'Invalid params',e.message) + except SyntaxError as e: + response = self.create_error_response(-32097,'SyntaxError') + except Exception as e: + response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) + finally: + return response + + +scapy_wrapper = Scapy_wrapper() +try: + while True: + # Wait for next request from client + message = socket.recv() +# print("Received request: %s" % message) +# print ("message type is: %s" % type(message)) +# print("message is now: %s" % message) + try: + method,params,req_id = scapy_wrapper.parse_req_msg(message) + if len(params)>0: + result = eval('scapy_wrapper.scapy_master.'+method+'(*'+str(params)+')') + else: + result = eval('scapy_wrapper.scapy_master.'+method+'()') + response = scapy_wrapper.create_success_response(result,req_id) + except: + print 'got exception' + e = scapy_wrapper.getException() + response = scapy_wrapper.error_handler(e) + finally: + json_response = json.dumps(response) + time.sleep(1) + + # Send reply back to client + socket.send(json_response) +except KeyboardInterrupt: + print('Ctrl+C pressed') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py new file mode 100755 index 00000000..8f7f7b01 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server_test.py @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + -- cgit From 930120461225e602e366a404180a48cdaf657dcf Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 4 Aug 2016 16:07:45 +0300 Subject: 1) added build_pkt when calculating offsets --- .../trex_control_plane/stl/services/scapy_server/scapy_server.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py index ca09333c..14cc0bfe 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py @@ -214,6 +214,7 @@ class scapy_service: def get_all_pkt_offsets(self,pkt_desc): pkt_protocols = pkt_desc.split('/') scapy_pkt = eval(pkt_desc) + scapy_pkt.build() total_protocols = len(pkt_protocols) res = {} for i in range(total_protocols): -- cgit From 28b09fb263445b1c73e3119d17feb5cc6f954ee6 Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 4 Aug 2016 17:44:50 +0300 Subject: 1) made a class Scapy_server encapsulating scapy_wrapper and scapy_service 2) fixed some exception handling --- .../stl/services/scapy_server/scapy_server.py | 69 +++------------------- .../services/scapy_server/zmq_for_scapy_server.py | 5 +- 2 files changed, 9 insertions(+), 65 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py index 14cc0bfe..07dc7427 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py @@ -10,6 +10,7 @@ import sys import tempfile import hashlib import binascii +from pprint import pprint try: @@ -35,7 +36,7 @@ f.close() class ScapyException(Exception): pass -class scapy_service: +class Scapy_service: #---------------------------------------------------------------------------------------------------- class scapyRegex: @@ -44,18 +45,8 @@ class scapy_service: self.regex = regex def stringRegex(self): - return self.regex - - class pktResult(BaseException): - def __init__(self,result,errorCode,errorDesc): - self.result = result - self.errorCode = errorCode - self.errorDesc = errorDesc - - def convert2tuple(self): - return tuple([self.result,self.errorCode,self.errorDesc]) + return self.regex #---------------------------------------------------------------------------------------------------- - def __init__(self): self.Raw = {'Raw':''} self.high_level_protocols = ['Raw'] @@ -65,37 +56,8 @@ class scapy_service: self.regexDB= {'MACField' : self.scapyRegex('MACField','^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$'), 'IPField' : self.scapyRegex('IPField','^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')} self.all_protocols = self.build_lib() - self.protocol_tree = self.build_tree() + self.protocol_tree = {'ALL':{'Ether':{'ARP':{},'IP':{'TCP':{'RAW':'payload'},'UDP':{'RAW':'payload'}}}}} -#-------------------------------------------------------TREE IMPLEMENTATION ------------------------ - class node(object): - def __init__(self, value):#, children = []): - self.value = value - self.children = [] - - def __str__(self, level=0): - ret = "\t"*level+repr(self.value)+"\n" - for child in self.children: - ret += child.__str__(level+1) - return ret - - def build_nodes(self,data,dictionary): - n = self.node(data) - if len(dictionary)==0: - n.children=[] - return n - for obj in dictionary.keys(): - if not (obj==''): - x = self.build_nodes(obj,dictionary[obj]) - n.children.append(x) - return n - - def build_tree(self): - root = self.node('ALL') - root.children = [] - root = self.build_nodes('ALL',self.low_level_protocols) - return root - def protocol_struct(self,protocol=''): if '_' in protocol: return [] @@ -142,27 +104,14 @@ class scapy_service: tupled_protocol = self.parse_entire_description(protocol_str) return tupled_protocol - def print_tree_level(self,root,level=0): - output = "\t"*level+str(root.value) - print (output) - if len(root.children)==0: - return - for child in root.children: - self.print_tree_level(child,level+1) - def print_tree(self): - self.print_tree_level(self.protocol_tree) + pprint(self.protocol_tree) def get_all_protocols(self): return self.all_protocols def get_tree(self): - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - print_tree(t) - sys.stdout = old_stdout - a= mystdout.getvalue() - return a + return self.protocol_tree def get_all_db(self): db = {} @@ -230,7 +179,6 @@ class scapy_service: scapy_pkt=scapy_pkt.payload return res - # pkt_descriptor in string format def build_pkt(self,pkt_descriptor): @@ -245,7 +193,6 @@ class scapy_service: res['offsets'] = pkt_offsets return res - #input: container #output: md5 encoded in base64 def get_md5(self,container): @@ -255,7 +202,6 @@ class scapy_service: res_md5 = binascii.b2a_base64(m.digest()) return res_md5 - def get_all(self): fields=self.get_all_fields() db=self.get_all_db() @@ -286,9 +232,8 @@ class scapy_service: def get_version(self): return {'built_by':'itraviv','version':'v1.0'} - def supported_methods(self,method_name): - if method_name in dir(scapy_service): + if method_name in dir(Scapy_service): return True return False diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py index 82118bb9..853db69e 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py @@ -27,7 +27,7 @@ class InvalidParams(Exception): pass class Scapy_wrapper: def __init__(self): - self.scapy_master = scapy_service() + self.scapy_master = Scapy_service() def parse_req_msg(self,JSON_req): try: @@ -104,8 +104,7 @@ try: else: result = eval('scapy_wrapper.scapy_master.'+method+'()') response = scapy_wrapper.create_success_response(result,req_id) - except: - print 'got exception' + except Exception as e: e = scapy_wrapper.getException() response = scapy_wrapper.error_handler(e) finally: -- cgit From 20691575dbdb9ba899c7d818caeca80902279554 Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 4 Aug 2016 17:45:55 +0300 Subject: server was made as an object with execute function --- .../services/scapy_server/zmq_for_scapy_server.py | 73 ++++++++++++---------- 1 file changed, 39 insertions(+), 34 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py index 853db69e..4f5fab36 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py @@ -12,18 +12,10 @@ import zmq import inspect from scapy_server import * -server_file_name = 'zmq_server_hello_world_server' - -context = zmq.Context() -socket = context.socket(zmq.REP) -socket.bind("tcp://*:5555") - - class ParseException(Exception): pass class InvalidRequest(Exception): pass class MethodNotFound(Exception): pass class InvalidParams(Exception): pass -#def error_response() class Scapy_wrapper: def __init__(self): @@ -63,9 +55,18 @@ class Scapy_wrapper: def create_success_response(self,result,req_id='null'): return {"jsonrpc": "2.0", "result": result, "id": req_id } - def getException(self): + def get_exception(self): return sys.exc_info() + + def execute(self,method,params): + if len(params)>0: + result = eval('self.scapy_master.'+method+'(*'+str(params)+')') + else: + result = eval('self.scapy_master.'+method+'()') + return result + + def metaraise(self,exc_info): raise exc_info[0], exc_info[1], exc_info[2] @@ -83,35 +84,39 @@ class Scapy_wrapper: response = self.create_error_response(-32603,'Invalid params',e.message) except SyntaxError as e: response = self.create_error_response(-32097,'SyntaxError') - except Exception as e: + except BaseException as e: response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) finally: return response +class Scapy_server(): + def __init__(self,port): + self.scapy_wrapper = Scapy_wrapper() + self.port = port + self.context = zmq.Context() + self.socket = self.context.socket(zmq.REP) + self.socket.bind("tcp://*:"+str(port)) -scapy_wrapper = Scapy_wrapper() -try: - while True: - # Wait for next request from client - message = socket.recv() -# print("Received request: %s" % message) -# print ("message type is: %s" % type(message)) -# print("message is now: %s" % message) + def activate(self): try: - method,params,req_id = scapy_wrapper.parse_req_msg(message) - if len(params)>0: - result = eval('scapy_wrapper.scapy_master.'+method+'(*'+str(params)+')') - else: - result = eval('scapy_wrapper.scapy_master.'+method+'()') - response = scapy_wrapper.create_success_response(result,req_id) - except Exception as e: - e = scapy_wrapper.getException() - response = scapy_wrapper.error_handler(e) - finally: - json_response = json.dumps(response) - time.sleep(1) + while True: + message = self.socket.recv() + try: + method,params,req_id = self.scapy_wrapper.parse_req_msg(message) + result = self.scapy_wrapper.execute(method,params) + response = self.scapy_wrapper.create_success_response(result,req_id) + except Exception as e: + exception_details = self.scapy_wrapper.get_exception() + response = self.scapy_wrapper.error_handler(exception_details) + finally: + json_response = json.dumps(response) + time.sleep(1) + + # Send reply back to client + self.socket.send(json_response) + except KeyboardInterrupt: + print('Terminated By Ctrl+C') + - # Send reply back to client - socket.send(json_response) -except KeyboardInterrupt: - print('Ctrl+C pressed') +s = Scapy_server(5555) +s.activate() -- cgit From cb24f0f0ca09881de3754dbfb7f37d1f08f4b306 Mon Sep 17 00:00:00 2001 From: itraviv Date: Tue, 9 Aug 2016 11:27:49 +0300 Subject: changed file name from scapy_server to scapy_service changed file for scapy_zmq_server changed functionality for scapy_server, added support for port with -s flag. scapy_service now functions as a service for the server wrapper --- .../stl/services/scapy_server/scapy_service.py | 248 +++++++++++++++++++++ .../stl/services/scapy_server/scapy_zmq_server.py | 148 ++++++++++++ 2 files changed, 396 insertions(+) create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py create mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py (limited to 'scripts/automation/trex_control_plane/stl/services') 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 new file mode 100755 index 00000000..6fe8dcc7 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -0,0 +1,248 @@ + +import os +import sys +stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir)) +sys.path.append(stl_pathname) +import trex_stl_lib +from trex_stl_lib.api import * +from copy import deepcopy +import sys +import tempfile +import hashlib +import binascii +from pprint import pprint + + +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO + +""" + **** output redirection template **** +old_stdout = sys.stdout +sys.stdout = mystdout = StringIO() + +ls() + +sys.stdout = old_stdout + +a= mystdout.getvalue() + +f = open('scapy_supported_formats.txt','w') +f.write(a) +f.close() +""" + +class ScapyException(Exception): pass + +class Scapy_service: + +#---------------------------------------------------------------------------------------------------- + class scapyRegex: + def __init__(self,FieldName,regex='empty'): + self.FieldName = FieldName + self.regex = regex + + def stringRegex(self): + return self.regex +#---------------------------------------------------------------------------------------------------- + def __init__(self): + self.Raw = {'Raw':''} + self.high_level_protocols = ['Raw'] + self.transport_protocols = {'TCP':self.Raw,'UDP':self.Raw} + self.network_protocols = {'IP':self.transport_protocols ,'ARP':''} + self.low_level_protocols = { 'Ether': self.network_protocols } + self.regexDB= {'MACField' : self.scapyRegex('MACField','^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$'), + 'IPField' : self.scapyRegex('IPField','^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')} + self.all_protocols = self.build_lib() + self.protocol_tree = {'ALL':{'Ether':{'ARP':{},'IP':{'TCP':{'RAW':'payload'},'UDP':{'RAW':'payload'}}}}} + + def protocol_struct(self,protocol=''): + if '_' in protocol: + return [] + if not protocol=='': + if protocol not in self.all_protocols: + return 'protocol not supported' + protocol = eval(protocol) + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + if not protocol=='': + ls(protocol) + else: + ls() + sys.stdout = old_stdout + protocol_data= mystdout.getvalue() + return protocol_data + + def build_lib(self): + lib = self.protocol_struct() + lib = lib.split('\n') + all_protocols=[] + for entry in lib: + entry = entry.split(':') + all_protocols.append(entry[0].strip()) + del all_protocols[len(all_protocols)-1] + return all_protocols + + def parse_description_line(self,line): + line_arr = [x.strip() for x in re.split(': | = ',line)] + return tuple(line_arr) + + def parse_entire_description(self,description): + description = description.split('\n') + description_list = [self.parse_description_line(x) for x in description] + del description_list[len(description_list)-1] + return description_list + + def get_protocol_details(self,p_name): + protocol_str = self.protocol_struct(p_name) + if protocol_str=='protocol not supported': + return 'protocol not supported' + if len(protocol_str) is 0: + return [] + tupled_protocol = self.parse_entire_description(protocol_str) + return tupled_protocol + + def print_tree(self): + pprint(self.protocol_tree) + + def get_all_protocols(self): + return self.all_protocols + + def get_tree(self): + return self.protocol_tree + + def get_all_db(self): + db = {} + for pro in self.all_protocols: + details = self.get_protocol_details(pro) + db[pro] = details + return db + + def get_all_fields(self): + fields = [] + for pro in self.all_protocols: + details = self.get_protocol_details(pro) + for i in range(0,len(details),1): + if len(details[i]) is 3: + fields.append(details[i][1]) + uniqeFields = list(set(fields)) + fieldDict = {} + for f in uniqeFields: + if f in self.regexDB: + fieldDict[f] = self.regexDB[f].stringRegex() + else: + fieldDict[f] = self.scapyRegex(f).stringRegex() + return fieldDict + + def show2_to_dict(self,pkt): + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + pkt.show2() + sys.stdout = old_stdout + show2data = mystdout.getvalue() #show2 data + listedShow2Data = show2data.split('###') + show2Dict = {} + for i in range(1,len(listedShow2Data)-1,2): + protocol_fields = listedShow2Data[i+1] + protocol_fields = protocol_fields.split('\n')[1:-1] + protocol_fields = [f.strip() for f in protocol_fields] + protocol_fields_dict = {} + for f in protocol_fields: + field_data = f.split('=') + if len(field_data)!= 1 : + field_name = field_data[0].strip() + protocol_fields_dict[field_name] = field_data[1].strip() + layer_name = re.sub(r'\W+', '',listedShow2Data[i]) #clear layer name to include only alpha-numeric + show2Dict[layer_name] = protocol_fields_dict + return show2Dict + +#pkt_desc as string +#dictionary of offsets per protocol. tuple for each field: (name, offset, size) at json format + def get_all_pkt_offsets(self,pkt_desc): + pkt_protocols = pkt_desc.split('/') + scapy_pkt = eval(pkt_desc) + scapy_pkt.build() + total_protocols = len(pkt_protocols) + res = {} + for i in range(total_protocols): + fields = {} + for field in scapy_pkt.fields_desc: + size = field.get_size_bytes() + layer_name = pkt_protocols[i].partition('(')[0] #clear layer name to include only alpha-numeric + layer_name = re.sub(r'\W+', '',layer_name) + if field.name is 'load': + layer_name ='Raw' + size = len(scapy_pkt) + fields[field.name]=[field.offset, size] + fields['global_offset'] = scapy_pkt.offset + res[layer_name] = fields + scapy_pkt=scapy_pkt.payload + return res + +# pkt_descriptor in string format + + def build_pkt(self,pkt_descriptor): + pkt = eval(pkt_descriptor) + show2data = self.show2_to_dict(pkt) + bufferData = str(pkt) #pkt buffer + bufferData = binascii.b2a_base64(bufferData) + pkt_offsets = self.get_all_pkt_offsets(pkt_descriptor) + res = {} + res['show2'] = show2data + res['buffer'] = bufferData + res['offsets'] = pkt_offsets + return res + +#input: container +#output: md5 encoded in base64 + def get_md5(self,container): + container = json.dumps(container) + m = hashlib.md5() + m.update(container.encode('ascii')) + res_md5 = binascii.b2a_base64(m.digest()) + return res_md5 + + def get_all(self): + fields=self.get_all_fields() + db=self.get_all_db() + fields_md5 = self.get_md5(fields) + db_md5 = self.get_md5(db) + res = {} + res['db'] = db + res['fields'] = fields + res['db_md5'] = db_md5 + res['fields_md5'] = fields_md5 + return res + +#input in string encoded base64 + def check_update(self,db_md5,field_md5): + fields=self.get_all_fields() + db=self.get_all_db() + current_db_md5 = self.get_md5(db) + current_field_md5 = self.get_md5(fields) + res = [] + if field_md5 == current_field_md5: + if db_md5 == current_db_md5: + return True + else: + raise ScapyException("Protocol DB is not up to date") + else: + raise ScapyException("Fields DB is not up to date") + + def get_version(self): + return {'built_by':'itraviv','version':'v1.0'} + + def supported_methods(self,method_name=''): + if method_name=='': + methods = {} + for f in dir(Scapy_service): + if inspect.ismethod(eval('Scapy_service.'+f)): + methods[f] = inspect.getargspec(eval('Scapy_service.'+f))[0] + return methods + if method_name in dir(Scapy_service): + return True + return False + + diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py new file mode 100755 index 00000000..f494d1db --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -0,0 +1,148 @@ + +import time +import sys +import os + +python2_zmq_path = os.path.abspath(os.path.join(os.pardir,os.pardir,os.pardir,os.pardir, + os.pardir,'external_libs','pyzmq-14.5.0','python2','fedora18','64bit')) +stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir)) +sys.path.append(stl_pathname) +sys.path.append(python2_zmq_path) +import zmq +import inspect +from scapy_service import * +from argparse import * +import socket + + +class ParseException(Exception): pass +class InvalidRequest(Exception): pass +class MethodNotFound(Exception): pass +class InvalidParams(Exception): pass + +class Scapy_wrapper: + def __init__(self): + self.scapy_master = Scapy_service() + + def parse_req_msg(self,JSON_req): + try: + req = json.loads(JSON_req) + req_id='null' + if (type(req)!= type({})): + raise ParseException(req_id) + json_rpc_keys = ['jsonrpc','id','method'] + if ((set(req.keys())!=set(json_rpc_keys)) and (set(req.keys())!=set(json_rpc_keys+['params']))) : + if 'id' in req.keys(): + req_id = req['id'] + raise InvalidRequest(req_id) + req_id = req['id'] + if not (self.scapy_master.supported_methods(req['method'])): + raise MethodNotFound(req_id) + scapy_method = eval("self.scapy_master."+req['method']) + arg_num_for_method = len(inspect.getargspec(scapy_method)[0]) + if (arg_num_for_method>1) : + if not ('params' in req.keys()): + raise InvalidRequest(req_id) + params_len = len(req['params'])+1 # +1 because "self" is considered parameter in args for method + if not (params_len==arg_num_for_method): + raise InvalidParams(req_id) + return req['method'],req['params'],req_id + else: + return req['method'],[],req_id + except ValueError: + raise ParseException(req_id) + + def create_error_response(self,error_code,error_msg,req_id='null'): + return {"jsonrpc": "2.0", "error": {"code": error_code, "message:": error_msg}, "id": req_id} + + def create_success_response(self,result,req_id='null'): + return {"jsonrpc": "2.0", "result": result, "id": req_id } + + def get_exception(self): + return sys.exc_info() + + + def execute(self,method,params): + if len(params)>0: + result = eval('self.scapy_master.'+method+'(*'+str(params)+')') + else: + result = eval('self.scapy_master.'+method+'()') + return result + + + def metaraise(self,exc_info): + raise exc_info[0], exc_info[1], exc_info[2] + + + def error_handler(self,exception_obj,req_id): + try: + self.metaraise(exception_obj) + except ParseException as e: + response = self.create_error_response(-32700,'Parse error ',req_id) + except InvalidRequest as e: + response = self.create_error_response(-32600,'Invalid Request',req_id) + except MethodNotFound as e: + response = self.create_error_response(-32601,'Method not found',req_id) + except InvalidParams as e: + response = self.create_error_response(-32603,'Invalid params',req_id) + except SyntaxError as e: + response = self.create_error_response(-32097,'SyntaxError',req_id) + except BaseException as e: + response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) + except: + response = self.create_error_response(-32096,'Scapy Server: Unknown Error',req_id) + finally: + return response + + + +parser = ArgumentParser(description=' Runs Scapy Server ') +parser.add_argument('-s','--scapy-port',type=int, default = 4507, dest='scapy_port', + help='Select port to which Scapy Server will listen to.\n default is 4507\n',action='store') +args = parser.parse_args() + +port = args.scapy_port + +class Scapy_server(): + def __init__(self, port=4507): + self.scapy_wrapper = Scapy_wrapper() + self.port = port + self.context = zmq.Context() + self.socket = self.context.socket(zmq.REP) + self.socket.bind("tcp://*:"+str(port)) + self.IP_address = socket.gethostbyname(socket.gethostname()) + + def activate(self): + print '***Scapy Server Started***\nListening on port: %d' % self.port + print 'Server IP address: %s' % self.IP_address + try: + while True: + message = self.socket.recv() + try: + method,params,req_id = self.scapy_wrapper.parse_req_msg(message) + result = self.scapy_wrapper.execute(method,params) + response = self.scapy_wrapper.create_success_response(result,req_id) + except Exception as e: + exception_details = self.scapy_wrapper.get_exception() + response = self.scapy_wrapper.error_handler(exception_details,req_id) + finally: + json_response = json.dumps(response) + # Send reply back to client + self.socket.send(json_response) + except KeyboardInterrupt: + print('Terminated By Ctrl+C') + + +#s = Scapy_server(port) +#s.activate() + +#arg1 is port number for the server to listen to +def main(arg1=4507): + s = Scapy_server(arg1) + s.activate() + +if __name__=='__main__': + if len(sys.argv)>1: + sys.exit(main(int(sys.argv[2]))) + else: + sys.exit(main()) -- cgit From b3dc958ce81dcb5634be9c9088d6ab48816624a7 Mon Sep 17 00:00:00 2001 From: itraviv Date: Wed, 10 Aug 2016 15:12:58 +0300 Subject: 1) fixed "main function": mechanism for running this script as a stand-alone program and running it from another python script 2) added closure of sockets and context explicitly (counting on python garbage-collector caused errors) 3) added support for 'remote shutdown' feature. now the server can be shut-down using 'shut_down' method as RPC from client --- .../stl/services/scapy_server/scapy_zmq_server.py | 46 ++++++++++++++-------- 1 file changed, 29 insertions(+), 17 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py index f494d1db..659a7f6c 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -36,6 +36,8 @@ class Scapy_wrapper: req_id = req['id'] raise InvalidRequest(req_id) req_id = req['id'] + if (req['method']=='shut_down'): + return 'shut_down',[],req_id if not (self.scapy_master.supported_methods(req['method'])): raise MethodNotFound(req_id) scapy_method = eval("self.scapy_master."+req['method']) @@ -94,14 +96,24 @@ class Scapy_wrapper: finally: return response +#arg1 is port number for the server to listen to +def main(arg1=4507): + s = Scapy_server(arg1) + s.activate() + +if __name__=='__main__': + if len(sys.argv)>1: + parser = ArgumentParser(description=' Runs Scapy Server ') + parser.add_argument('-s','--scapy-port',type=int, default = 4507, dest='scapy_port', + help='Select port to which Scapy Server will listen to.\n default is 4507\n',action='store') + args = parser.parse_args() + port = args.scapy_port + sys.exit(main(port)) + else: + sys.exit(main()) -parser = ArgumentParser(description=' Runs Scapy Server ') -parser.add_argument('-s','--scapy-port',type=int, default = 4507, dest='scapy_port', - help='Select port to which Scapy Server will listen to.\n default is 4507\n',action='store') -args = parser.parse_args() -port = args.scapy_port class Scapy_server(): def __init__(self, port=4507): @@ -120,7 +132,11 @@ class Scapy_server(): message = self.socket.recv() try: method,params,req_id = self.scapy_wrapper.parse_req_msg(message) - result = self.scapy_wrapper.execute(method,params) + if (method == 'shut_down'): + print 'Shut down by remote user' + result = 'Server shut down command received - server has shut down' + else: + result = self.scapy_wrapper.execute(method,params) response = self.scapy_wrapper.create_success_response(result,req_id) except Exception as e: exception_details = self.scapy_wrapper.get_exception() @@ -129,20 +145,16 @@ class Scapy_server(): json_response = json.dumps(response) # Send reply back to client self.socket.send(json_response) + if (method =='shut_down'): + break + except KeyboardInterrupt: print('Terminated By Ctrl+C') + finally: + self.socket.close() + self.context.destroy() + -#s = Scapy_server(port) -#s.activate() -#arg1 is port number for the server to listen to -def main(arg1=4507): - s = Scapy_server(arg1) - s.activate() -if __name__=='__main__': - if len(sys.argv)>1: - sys.exit(main(int(sys.argv[2]))) - else: - sys.exit(main()) -- cgit From 661d27af339a57319d41655b6bfa71810e4e60ba Mon Sep 17 00:00:00 2001 From: itraviv Date: Wed, 10 Aug 2016 15:53:30 +0300 Subject: move 'main' function to bottom of file --- .../stl/services/scapy_server/scapy_zmq_server.py | 33 +++++++++------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py index 659a7f6c..b2f2d526 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -96,25 +96,6 @@ class Scapy_wrapper: finally: return response -#arg1 is port number for the server to listen to -def main(arg1=4507): - s = Scapy_server(arg1) - s.activate() - -if __name__=='__main__': - if len(sys.argv)>1: - parser = ArgumentParser(description=' Runs Scapy Server ') - parser.add_argument('-s','--scapy-port',type=int, default = 4507, dest='scapy_port', - help='Select port to which Scapy Server will listen to.\n default is 4507\n',action='store') - args = parser.parse_args() - port = args.scapy_port - sys.exit(main(port)) - else: - sys.exit(main()) - - - - class Scapy_server(): def __init__(self, port=4507): self.scapy_wrapper = Scapy_wrapper() @@ -157,4 +138,18 @@ class Scapy_server(): +#arg1 is port number for the server to listen to +def main(arg1=4507): + s = Scapy_server(arg1) + s.activate() +if __name__=='__main__': + if len(sys.argv)>1: + parser = ArgumentParser(description=' Runs Scapy Server ') + parser.add_argument('-s','--scapy-port',type=int, default = 4507, dest='scapy_port', + help='Select port to which Scapy Server will listen to.\n default is 4507\n',action='store') + args = parser.parse_args() + port = args.scapy_port + sys.exit(main(port)) + else: + sys.exit(main()) -- cgit From 72171290152897fac1a149fe4f9d1cbf0ae914c4 Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 11 Aug 2016 16:59:29 +0300 Subject: 1)removed unnecessary files from repository 2)fixed bug in checking update of data-base --- .../stl/services/scapy_server/scapy_server.py | 240 --------------------- .../stl/services/scapy_server/scapy_service.py | 4 +- .../services/scapy_server/zmq_for_scapy_server.py | 122 ----------- 3 files changed, 2 insertions(+), 364 deletions(-) delete mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py delete mode 100755 scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py deleted file mode 100755 index 07dc7427..00000000 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_server.py +++ /dev/null @@ -1,240 +0,0 @@ - -import os -import sys -stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir)) -sys.path.append(stl_pathname) -import trex_stl_lib -from trex_stl_lib.api import * -from copy import deepcopy -import sys -import tempfile -import hashlib -import binascii -from pprint import pprint - - -try: - from cStringIO import StringIO -except ImportError: - from io import StringIO - -""" - **** output redirection template **** -old_stdout = sys.stdout -sys.stdout = mystdout = StringIO() - -ls() - -sys.stdout = old_stdout - -a= mystdout.getvalue() - -f = open('scapy_supported_formats.txt','w') -f.write(a) -f.close() -""" - -class ScapyException(Exception): pass - -class Scapy_service: - -#---------------------------------------------------------------------------------------------------- - class scapyRegex: - def __init__(self,FieldName,regex='empty'): - self.FieldName = FieldName - self.regex = regex - - def stringRegex(self): - return self.regex -#---------------------------------------------------------------------------------------------------- - def __init__(self): - self.Raw = {'Raw':''} - self.high_level_protocols = ['Raw'] - self.transport_protocols = {'TCP':self.Raw,'UDP':self.Raw} - self.network_protocols = {'IP':self.transport_protocols ,'ARP':''} - self.low_level_protocols = { 'Ether': self.network_protocols } - self.regexDB= {'MACField' : self.scapyRegex('MACField','^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$'), - 'IPField' : self.scapyRegex('IPField','^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')} - self.all_protocols = self.build_lib() - self.protocol_tree = {'ALL':{'Ether':{'ARP':{},'IP':{'TCP':{'RAW':'payload'},'UDP':{'RAW':'payload'}}}}} - - def protocol_struct(self,protocol=''): - if '_' in protocol: - return [] - if not protocol=='': - if protocol not in self.all_protocols: - return 'protocol not supported' - protocol = eval(protocol) - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - if not protocol=='': - ls(protocol) - else: - ls() - sys.stdout = old_stdout - protocol_data= mystdout.getvalue() - return protocol_data - - def build_lib(self): - lib = self.protocol_struct() - lib = lib.split('\n') - all_protocols=[] - for entry in lib: - entry = entry.split(':') - all_protocols.append(entry[0].strip()) - del all_protocols[len(all_protocols)-1] - return all_protocols - - def parse_description_line(self,line): - line_arr = [x.strip() for x in re.split(': | = ',line)] - return tuple(line_arr) - - def parse_entire_description(self,description): - description = description.split('\n') - description_list = [self.parse_description_line(x) for x in description] - del description_list[len(description_list)-1] - return description_list - - def get_protocol_details(self,p_name): - protocol_str = self.protocol_struct(p_name) - if protocol_str=='protocol not supported': - return 'protocol not supported' - if len(protocol_str) is 0: - return [] - tupled_protocol = self.parse_entire_description(protocol_str) - return tupled_protocol - - def print_tree(self): - pprint(self.protocol_tree) - - def get_all_protocols(self): - return self.all_protocols - - def get_tree(self): - return self.protocol_tree - - def get_all_db(self): - db = {} - for pro in self.all_protocols: - details = self.get_protocol_details(pro) - db[pro] = details - return db - - def get_all_fields(self): - fields = [] - for pro in self.all_protocols: - details = self.get_protocol_details(pro) - for i in range(0,len(details),1): - if len(details[i]) is 3: - fields.append(details[i][1]) - uniqeFields = list(set(fields)) - fieldDict = {} - for f in uniqeFields: - if f in self.regexDB: - fieldDict[f] = self.regexDB[f].stringRegex() - else: - fieldDict[f] = self.scapyRegex(f).stringRegex() - return fieldDict - - def show2_to_dict(self,pkt): - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - pkt.show2() - sys.stdout = old_stdout - show2data = mystdout.getvalue() #show2 data - listedShow2Data = show2data.split('###') - show2Dict = {} - for i in range(1,len(listedShow2Data)-1,2): - protocol_fields = listedShow2Data[i+1] - protocol_fields = protocol_fields.split('\n')[1:-1] - protocol_fields = [f.strip() for f in protocol_fields] - protocol_fields_dict = {} - for f in protocol_fields: - field_data = f.split('=') - if len(field_data)!= 1 : - field_name = field_data[0].strip() - protocol_fields_dict[field_name] = field_data[1].strip() - layer_name = re.sub(r'\W+', '',listedShow2Data[i]) #clear layer name to include only alpha-numeric - show2Dict[layer_name] = protocol_fields_dict - return show2Dict - -#pkt_desc as string -#dictionary of offsets per protocol. tuple for each field: (name, offset, size) at json format - def get_all_pkt_offsets(self,pkt_desc): - pkt_protocols = pkt_desc.split('/') - scapy_pkt = eval(pkt_desc) - scapy_pkt.build() - total_protocols = len(pkt_protocols) - res = {} - for i in range(total_protocols): - fields = {} - for field in scapy_pkt.fields_desc: - size = field.get_size_bytes() - if field.name is 'load': - size = len(scapy_pkt) - fields[field.name]=[field.offset, size] - layer_name = pkt_protocols[i].partition('(')[0] #clear layer name to include only alpha-numeric - layer_name = re.sub(r'\W+', '',layer_name) - res[layer_name] = fields - scapy_pkt=scapy_pkt.payload - return res - -# pkt_descriptor in string format - - def build_pkt(self,pkt_descriptor): - pkt = eval(pkt_descriptor) - show2data = self.show2_to_dict(pkt) - bufferData = str(pkt) #pkt buffer - bufferData = binascii.b2a_base64(bufferData) - pkt_offsets = self.get_all_pkt_offsets(pkt_descriptor) - res = {} - res['show2'] = show2data - res['buffer'] = bufferData - res['offsets'] = pkt_offsets - return res - -#input: container -#output: md5 encoded in base64 - def get_md5(self,container): - container = json.dumps(container) - m = hashlib.md5() - m.update(container.encode('ascii')) - res_md5 = binascii.b2a_base64(m.digest()) - return res_md5 - - def get_all(self): - fields=self.get_all_fields() - db=self.get_all_db() - fields_md5 = self.get_md5(fields) - db_md5 = self.get_md5(db) - res = {} - res['db'] = db - res['fields'] = fields - res['db_md5'] = db_md5 - res['fields_md5'] = fields_md5 - return res - -#input in string encoded base64 - def check_update(self,db_md5,field_md5): - fields=self.get_all_fields() - db=self.get_all_db() - current_db_md5 = self.get_md5(db) - current_field_md5 = self.get_md5(fields) - res = [] - if field_md5 == current_field_md5: - if db_md5 == current_db_md5: - return True - else: - raise ScapyException("Protocol DB is not up to date") - else: - raise ScapyException("Fields DB is not up to date") - - def get_version(self): - return {'built_by':'itraviv','version':'v1.0'} - - def supported_methods(self,method_name): - if method_name in dir(Scapy_service): - return True - return False - - 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 6fe8dcc7..638d35f2 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 @@ -223,8 +223,8 @@ class Scapy_service: current_db_md5 = self.get_md5(db) current_field_md5 = self.get_md5(fields) res = [] - if field_md5 == current_field_md5: - if db_md5 == current_db_md5: + if (field_md5.decode("base64") == current_field_md5.decode("base64")): + if (db_md5.decode("base64") == current_db_md5.decode("base64")): return True else: raise ScapyException("Protocol DB is not up to date") diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py deleted file mode 100755 index 4f5fab36..00000000 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/zmq_for_scapy_server.py +++ /dev/null @@ -1,122 +0,0 @@ -# -# Hello World server in Python -# Binds REP socket to tcp://*:5555 -# Expects b"Hello" from client, replies with b"World" -# - -import time -import sys -sys.path.append(sys.path.append('/auto/srg-sce-swinfra-usr/emb/users/itraviv/trex/trex-core/scripts/external_libs/pyzmq-14.5.0/python2/fedora18/64bit')) -sys.path.append(sys.path.append('/auto/srg-sce-swinfra-usr/emb/users/itraviv/trex/trex-core/scripts/automation/trex_control_plane/stl/')) -import zmq -import inspect -from scapy_server import * - -class ParseException(Exception): pass -class InvalidRequest(Exception): pass -class MethodNotFound(Exception): pass -class InvalidParams(Exception): pass - -class Scapy_wrapper: - def __init__(self): - self.scapy_master = Scapy_service() - - def parse_req_msg(self,JSON_req): - try: - req = json.loads(JSON_req) - req_id='null' - if (type(req)!= type({})): - raise ParseException(req_id) - json_rpc_keys = ['jsonrpc','id','method'] - if ((set(req.keys())!=set(json_rpc_keys)) and (set(req.keys())!=set(json_rpc_keys+['params']))) : - if 'id' in req.keys(): - req_id = req['id'] - raise InvalidRequest(req_id) - req_id = req['id'] - if not (self.scapy_master.supported_methods(req['method'])): - raise MethodNotFound(req_id) - scapy_method = eval("self.scapy_master."+req['method']) - arg_num_for_method = len(inspect.getargspec(scapy_method)[0]) - if (arg_num_for_method>1) : - if not ('params' in req.keys()): - raise InvalidRequest(req_id) - params_len = len(req['params'])+1 # +1 because "self" is considered parameter in args for method - if not (params_len==arg_num_for_method): - raise InvalidParams(req_id) - return req['method'],req['params'],req_id - else: - return req['method'],[],req_id - except ValueError: - raise ParseException(req_id) - - def create_error_response(self,error_code,error_msg,req_id='null'): - return {"jsonrpc": "2.0", "error": {"code": error_code, "message:": error_msg}, "id": req_id} - - def create_success_response(self,result,req_id='null'): - return {"jsonrpc": "2.0", "result": result, "id": req_id } - - def get_exception(self): - return sys.exc_info() - - - def execute(self,method,params): - if len(params)>0: - result = eval('self.scapy_master.'+method+'(*'+str(params)+')') - else: - result = eval('self.scapy_master.'+method+'()') - return result - - - def metaraise(self,exc_info): - raise exc_info[0], exc_info[1], exc_info[2] - - - def error_handler(self,exception_obj): - try: - self.metaraise(exception_obj) - except ParseException as e: - response = self.create_error_response(-32700,'Parse error',e.message) - except InvalidRequest as e: - response = self.create_error_response(-32600,'Invalid Request',e.message) - except MethodNotFound as e: - response = self.create_error_response(-32601,'Method not found',e.message) - except InvalidParams as e: - response = self.create_error_response(-32603,'Invalid params',e.message) - except SyntaxError as e: - response = self.create_error_response(-32097,'SyntaxError') - except BaseException as e: - response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) - finally: - return response - -class Scapy_server(): - def __init__(self,port): - self.scapy_wrapper = Scapy_wrapper() - self.port = port - self.context = zmq.Context() - self.socket = self.context.socket(zmq.REP) - self.socket.bind("tcp://*:"+str(port)) - - def activate(self): - try: - while True: - message = self.socket.recv() - try: - method,params,req_id = self.scapy_wrapper.parse_req_msg(message) - result = self.scapy_wrapper.execute(method,params) - response = self.scapy_wrapper.create_success_response(result,req_id) - except Exception as e: - exception_details = self.scapy_wrapper.get_exception() - response = self.scapy_wrapper.error_handler(exception_details) - finally: - json_response = json.dumps(response) - time.sleep(1) - - # Send reply back to client - self.socket.send(json_response) - except KeyboardInterrupt: - print('Terminated By Ctrl+C') - - -s = Scapy_server(5555) -s.activate() -- cgit From 2c575880c6b5bd0a6c4f1df91f819118af800699 Mon Sep 17 00:00:00 2001 From: itraviv Date: Mon, 15 Aug 2016 17:52:38 +0300 Subject: scapy_server_test: added cases for testing: GRE, VXML, DNS, IPv6 changed test functions to include only the testted object and created other functions as testing engines. scapy_service: added api class. added documentry for api class changed method functions to include underscore --- .../stl/services/scapy_server/scapy_service.py | 214 ++++++++++++++------- .../stl/services/scapy_server/scapy_zmq_server.py | 8 +- 2 files changed, 149 insertions(+), 73 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services') 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 638d35f2..3519bb58 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 @@ -2,7 +2,9 @@ import os import sys stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir)) +additional_stl_udp_pkts = os.path.abspath(os.path.join(os.pardir, os.pardir,'stl')) sys.path.append(stl_pathname) +sys.path.append(additional_stl_udp_pkts) import trex_stl_lib from trex_stl_lib.api import * from copy import deepcopy @@ -11,32 +13,106 @@ import tempfile import hashlib import binascii from pprint import pprint - +from scapy.layers.dns import * +from udp_1pkt_vxlan import VXLAN +from udp_1pkt_mpls import MPLS try: from cStringIO import StringIO except ImportError: from io import StringIO -""" - **** output redirection template **** -old_stdout = sys.stdout -sys.stdout = mystdout = StringIO() -ls() -sys.stdout = old_stdout -a= mystdout.getvalue() +class Scapy_service_api(): + """ get_all(self) -f = open('scapy_supported_formats.txt','w') -f.write(a) -f.close() -""" + Sends all the protocols and fields that Scapy Service supports. + also sends the md5 of the Protocol DB and Fields DB used to check if the DB's are up to date -class ScapyException(Exception): pass + Parameters + ---------- + None + + Returns + ------- + Dictionary (of protocol DB and scapy fields DB) + + Raises + ------ + Raises an exception when a DB error occurs (i.e a layer is not loaded properly and has missing components) + """ + def get_all(self): + pass + + """ check_update(self,db_md5,field_md5) + Checks if the Scapy Service running on the server has a newer version of the databases that the client has + + Parameters + ---------- + db_md5 - The md5 that was delivered with the protocol database that the client owns, when first received at the client + field_md5 - The md5 that was delivered with the fields database that the client owns, when first received at the client + + Returns + ------- + True/False according the Databases version(determined by their md5) + + Raises + ------ + Raises an exception (ScapyException) when protocol DB/Fields DB is not up to date + + """ -class Scapy_service: + def check_update(self,db_md5,field_md5): + pass + + """ build_pkt(self,pkt_descriptor) -> Dictionary (of Offsets,Show2 and Buffer) + + Performs calculations on the given packet and returns results for that packet. + + Parameters + ---------- + pkt_descriptor - A string describing a network packet, in Scapy Format + + Returns + ------- + - The packets offsets: each field in every layer is mapped inside the Offsets Dictionary + - The Show2: A description of each field and its value in every layer of the packet + - The Buffer: The Hexdump of packet encoded in base64 + + Raises + ------ + will raise an exception when the Scapy string format is illegal, contains syntax error, contains non-supported + protocl, etc. + """ + def build_pkt(self,pkt_descriptor): + pass + + """ get_tree(self) -> Dictionary describing an example of hierarchy in layers + + Scapy service holds a tree of layers that can be stacked to a recommended packet + according to the hierarchy + + Parameters + ---------- + None + + Returns + ------- + Returns an example hierarchy tree of layers that can be stacked to a packet + + Raises + ------ + None + """ + def get_tree(self): + pass + + + +class ScapyException(Exception): pass +class Scapy_service(Scapy_service_api): #---------------------------------------------------------------------------------------------------- class scapyRegex: @@ -55,10 +131,10 @@ class Scapy_service: self.low_level_protocols = { 'Ether': self.network_protocols } self.regexDB= {'MACField' : self.scapyRegex('MACField','^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$'), 'IPField' : self.scapyRegex('IPField','^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$')} - self.all_protocols = self.build_lib() + self.all_protocols = self._build_lib() self.protocol_tree = {'ALL':{'Ether':{'ARP':{},'IP':{'TCP':{'RAW':'payload'},'UDP':{'RAW':'payload'}}}}} - def protocol_struct(self,protocol=''): + def _protocol_struct(self,protocol=''): if '_' in protocol: return [] if not protocol=='': @@ -75,8 +151,8 @@ class Scapy_service: protocol_data= mystdout.getvalue() return protocol_data - def build_lib(self): - lib = self.protocol_struct() + def _build_lib(self): + lib = self._protocol_struct() lib = lib.split('\n') all_protocols=[] for entry in lib: @@ -85,45 +161,39 @@ class Scapy_service: del all_protocols[len(all_protocols)-1] return all_protocols - def parse_description_line(self,line): + def _parse_description_line(self,line): line_arr = [x.strip() for x in re.split(': | = ',line)] return tuple(line_arr) - def parse_entire_description(self,description): + def _parse_entire_description(self,description): description = description.split('\n') - description_list = [self.parse_description_line(x) for x in description] + description_list = [self._parse_description_line(x) for x in description] del description_list[len(description_list)-1] return description_list - def get_protocol_details(self,p_name): - protocol_str = self.protocol_struct(p_name) + def _get_protocol_details(self,p_name): + protocol_str = self._protocol_struct(p_name) if protocol_str=='protocol not supported': return 'protocol not supported' if len(protocol_str) is 0: return [] - tupled_protocol = self.parse_entire_description(protocol_str) + tupled_protocol = self._parse_entire_description(protocol_str) return tupled_protocol - def print_tree(self): + def _print_tree(self): pprint(self.protocol_tree) - def get_all_protocols(self): - return self.all_protocols - - def get_tree(self): - return self.protocol_tree - - def get_all_db(self): + def _get_all_db(self): db = {} for pro in self.all_protocols: - details = self.get_protocol_details(pro) + details = self._get_protocol_details(pro) db[pro] = details return db - def get_all_fields(self): + def _get_all_fields(self): fields = [] for pro in self.all_protocols: - details = self.get_protocol_details(pro) + details = self._get_protocol_details(pro) for i in range(0,len(details),1): if len(details[i]) is 3: fields.append(details[i][1]) @@ -136,7 +206,7 @@ class Scapy_service: fieldDict[f] = self.scapyRegex(f).stringRegex() return fieldDict - def show2_to_dict(self,pkt): + def _show2_to_dict(self,pkt): old_stdout = sys.stdout sys.stdout = mystdout = StringIO() pkt.show2() @@ -160,7 +230,7 @@ class Scapy_service: #pkt_desc as string #dictionary of offsets per protocol. tuple for each field: (name, offset, size) at json format - def get_all_pkt_offsets(self,pkt_desc): + def _get_all_pkt_offsets(self,pkt_desc): pkt_protocols = pkt_desc.split('/') scapy_pkt = eval(pkt_desc) scapy_pkt.build() @@ -181,34 +251,51 @@ class Scapy_service: scapy_pkt=scapy_pkt.payload return res -# pkt_descriptor in string format +#input: container +#output: md5 encoded in base64 + def _get_md5(self,container): + container = json.dumps(container) + m = hashlib.md5() + m.update(container.encode('ascii')) + res_md5 = binascii.b2a_base64(m.digest()) + return res_md5 + def get_version(self): + return {'built_by':'itraviv','version':'v1.0'} + + def supported_methods(self,method_name=''): + if method_name=='': + methods = {} + for f in dir(Scapy_service): + if inspect.ismethod(eval('Scapy_service.'+f)): + methods[f] = inspect.getargspec(eval('Scapy_service.'+f))[0] + return methods + if method_name in dir(Scapy_service): + return True + return False + +#--------------------------------------------API implementation------------- + def get_tree(self): + return self.protocol_tree + +# pkt_descriptor in string format def build_pkt(self,pkt_descriptor): pkt = eval(pkt_descriptor) - show2data = self.show2_to_dict(pkt) + show2data = self._show2_to_dict(pkt) bufferData = str(pkt) #pkt buffer bufferData = binascii.b2a_base64(bufferData) - pkt_offsets = self.get_all_pkt_offsets(pkt_descriptor) + pkt_offsets = self._get_all_pkt_offsets(pkt_descriptor) res = {} res['show2'] = show2data res['buffer'] = bufferData res['offsets'] = pkt_offsets return res -#input: container -#output: md5 encoded in base64 - def get_md5(self,container): - container = json.dumps(container) - m = hashlib.md5() - m.update(container.encode('ascii')) - res_md5 = binascii.b2a_base64(m.digest()) - return res_md5 - def get_all(self): - fields=self.get_all_fields() - db=self.get_all_db() - fields_md5 = self.get_md5(fields) - db_md5 = self.get_md5(db) + fields=self._get_all_fields() + db=self._get_all_db() + fields_md5 = self._get_md5(fields) + db_md5 = self._get_md5(db) res = {} res['db'] = db res['fields'] = fields @@ -218,10 +305,10 @@ class Scapy_service: #input in string encoded base64 def check_update(self,db_md5,field_md5): - fields=self.get_all_fields() - db=self.get_all_db() - current_db_md5 = self.get_md5(db) - current_field_md5 = self.get_md5(fields) + fields=self._get_all_fields() + db=self._get_all_db() + current_db_md5 = self._get_md5(db) + current_field_md5 = self._get_md5(fields) res = [] if (field_md5.decode("base64") == current_field_md5.decode("base64")): if (db_md5.decode("base64") == current_db_md5.decode("base64")): @@ -231,18 +318,7 @@ class Scapy_service: else: raise ScapyException("Fields DB is not up to date") - def get_version(self): - return {'built_by':'itraviv','version':'v1.0'} - def supported_methods(self,method_name=''): - if method_name=='': - methods = {} - for f in dir(Scapy_service): - if inspect.ismethod(eval('Scapy_service.'+f)): - methods[f] = inspect.getargspec(eval('Scapy_service.'+f))[0] - return methods - if method_name in dir(Scapy_service): - return True - return False +#--------------------------------------------------------------------------- diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py index b2f2d526..408f1daf 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -106,16 +106,16 @@ class Scapy_server(): self.IP_address = socket.gethostbyname(socket.gethostname()) def activate(self): - print '***Scapy Server Started***\nListening on port: %d' % self.port - print 'Server IP address: %s' % self.IP_address + print ('***Scapy Server Started***\nListening on port: %d' % self.port) + print ('Server IP address: %s' % self.IP_address) try: while True: message = self.socket.recv() try: method,params,req_id = self.scapy_wrapper.parse_req_msg(message) if (method == 'shut_down'): - print 'Shut down by remote user' - result = 'Server shut down command received - server has shut down' + print ('Shut down by remote user') + result = 'Server shut down command received - server had shut down' else: result = self.scapy_wrapper.execute(method,params) response = self.scapy_wrapper.create_success_response(result,req_id) -- cgit From 46b8104b0c4576994971adbdef0569007649fdc2 Mon Sep 17 00:00:00 2001 From: itraviv Date: Mon, 15 Aug 2016 18:15:45 +0300 Subject: fixed an issue in exception handling --- .../stl/services/scapy_server/scapy_zmq_server.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/services') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py index 408f1daf..295315e6 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -72,13 +72,11 @@ class Scapy_wrapper: return result - def metaraise(self,exc_info): - raise exc_info[0], exc_info[1], exc_info[2] - - - def error_handler(self,exception_obj,req_id): + def error_handler(self,e,req_id): + print('exception message is %s' % e.message) + print('exception type is: %s' % type(e)) try: - self.metaraise(exception_obj) + raise e except ParseException as e: response = self.create_error_response(-32700,'Parse error ',req_id) except InvalidRequest as e: @@ -94,6 +92,7 @@ class Scapy_wrapper: except: response = self.create_error_response(-32096,'Scapy Server: Unknown Error',req_id) finally: + print(response) return response class Scapy_server(): @@ -112,6 +111,7 @@ class Scapy_server(): while True: message = self.socket.recv() try: + req_id = 'null' method,params,req_id = self.scapy_wrapper.parse_req_msg(message) if (method == 'shut_down'): print ('Shut down by remote user') @@ -120,8 +120,7 @@ class Scapy_server(): result = self.scapy_wrapper.execute(method,params) response = self.scapy_wrapper.create_success_response(result,req_id) except Exception as e: - exception_details = self.scapy_wrapper.get_exception() - response = self.scapy_wrapper.error_handler(exception_details,req_id) + response = self.scapy_wrapper.error_handler(e,req_id) finally: json_response = json.dumps(response) # Send reply back to client -- cgit From 6796bb99573f15c77a007434feabb30291ac1670 Mon Sep 17 00:00:00 2001 From: itraviv Date: Thu, 18 Aug 2016 15:23:01 +0300 Subject: scapy_server_test: skiping python3 tests scapy_service.py: minor changes to protocol_struct function zmq_client: added zmq_server: minor changes in exception handling --- .../stl/services/scapy_server/scapy_service.py | 36 +++++++++++------- .../stl/services/scapy_server/scapy_zmq_client.py | 44 ++++++++++++++++++++++ .../stl/services/scapy_server/scapy_zmq_server.py | 24 ++++++------ 3 files changed, 78 insertions(+), 26 deletions(-) create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_client.py (limited to 'scripts/automation/trex_control_plane/stl/services') 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 3519bb58..311dc8bd 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 @@ -134,26 +134,32 @@ class Scapy_service(Scapy_service_api): self.all_protocols = self._build_lib() self.protocol_tree = {'ALL':{'Ether':{'ARP':{},'IP':{'TCP':{'RAW':'payload'},'UDP':{'RAW':'payload'}}}}} - def _protocol_struct(self,protocol=''): + + def _all_protocol_structs(self): + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + ls() + sys.stdout = old_stdout + all_protocol_data= mystdout.getvalue() + return all_protocol_data + + def _protocol_struct(self,protocol): if '_' in protocol: return [] if not protocol=='': if protocol not in self.all_protocols: return 'protocol not supported' - protocol = eval(protocol) + protocol = eval(protocol) old_stdout = sys.stdout sys.stdout = mystdout = StringIO() - if not protocol=='': - ls(protocol) - else: - ls() + ls(protocol) sys.stdout = old_stdout protocol_data= mystdout.getvalue() return protocol_data def _build_lib(self): - lib = self._protocol_struct() - lib = lib.split('\n') + lib = self._all_protocol_structs() + lib = lib.splitlines() all_protocols=[] for entry in lib: entry = entry.split(':') @@ -195,11 +201,11 @@ class Scapy_service(Scapy_service_api): for pro in self.all_protocols: details = self._get_protocol_details(pro) for i in range(0,len(details),1): - if len(details[i]) is 3: + if len(details[i]) == 3: fields.append(details[i][1]) - uniqeFields = list(set(fields)) + uniqueFields = list(set(fields)) fieldDict = {} - for f in uniqeFields: + for f in uniqueFields: if f in self.regexDB: fieldDict[f] = self.regexDB[f].stringRegex() else: @@ -261,14 +267,18 @@ class Scapy_service(Scapy_service_api): return res_md5 def get_version(self): - return {'built_by':'itraviv','version':'v1.0'} + return {'built_by':'itraviv','version':'v1.01'} def supported_methods(self,method_name=''): if method_name=='': methods = {} for f in dir(Scapy_service): if inspect.ismethod(eval('Scapy_service.'+f)): - methods[f] = inspect.getargspec(eval('Scapy_service.'+f))[0] + param_list = inspect.getargspec(eval('Scapy_service.'+f))[0] + del param_list[0] #deleting the parameter "self" that appears in every method + #because the server automatically operates on an instance, + #and this can cause confusion + methods[f] = (len(param_list), param_list) return methods if method_name in dir(Scapy_service): return True diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_client.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_client.py new file mode 100644 index 00000000..24e1593e --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_client.py @@ -0,0 +1,44 @@ + + +import zmq +import json + + +class Scapy_server_wrapper(): + def __init__(self,dest_scapy_port=5555,server_ip_address='localhost'): + self.context = zmq.Context() + self.socket = self.context.socket(zmq.REQ) + self.dest_scapy_port =dest_scapy_port + self.socket.connect("tcp://"+str(server_ip_address)+":"+str(self.dest_scapy_port)) #ip address of csi-trex-11 + + def call_method(self,method_name,method_params): + json_rpc_req = { "jsonrpc":"2.0","method": method_name ,"params": method_params, "id":"1"} + request = json.dumps(json_rpc_req) + self.socket.send_string(request) + # Get the reply. + message = self.socket.recv_string() + message_parsed = json.loads(message) + if 'result' in message_parsed.keys(): + result = message_parsed['result'] + else: + result = {'error':message_parsed['error']} + return result + + def get_all(self): + return self.call_method('get_all',[]) + + def check_update(self,db_md5,field_md5): + result = self.call_method('check_update',[db_md5,field_md5]) + if result!=True: + if 'error' in result.keys(): + if "Fields DB is not up to date" in result['error']['message:']: + raise Exception("Fields DB is not up to date") + if "Protocol DB is not up to date" in result['error']['message:']: + raise Exception("Protocol DB is not up to date") + return result + + def build_pkt(self,pkt_descriptor): + return self.call_method('build_pkt',[pkt_descriptor]) + + def _get_all_pkt_offsets(self,pkt_desc): + return self.call_method('_get_all_pkt_offsets',[pkt_desc]) diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py index 295315e6..0b88668a 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -27,7 +27,7 @@ class Scapy_wrapper: def parse_req_msg(self,JSON_req): try: req = json.loads(JSON_req) - req_id='null' + req_id=b'null' if (type(req)!= type({})): raise ParseException(req_id) json_rpc_keys = ['jsonrpc','id','method'] @@ -57,7 +57,7 @@ class Scapy_wrapper: def create_error_response(self,error_code,error_msg,req_id='null'): return {"jsonrpc": "2.0", "error": {"code": error_code, "message:": error_msg}, "id": req_id} - def create_success_response(self,result,req_id='null'): + def create_success_response(self,result,req_id=b'null'): return {"jsonrpc": "2.0", "result": result, "id": req_id } def get_exception(self): @@ -73,8 +73,6 @@ class Scapy_wrapper: def error_handler(self,e,req_id): - print('exception message is %s' % e.message) - print('exception type is: %s' % type(e)) try: raise e except ParseException as e: @@ -87,12 +85,12 @@ class Scapy_wrapper: response = self.create_error_response(-32603,'Invalid params',req_id) except SyntaxError as e: response = self.create_error_response(-32097,'SyntaxError',req_id) - except BaseException as e: - response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) - except: - response = self.create_error_response(-32096,'Scapy Server: Unknown Error',req_id) + except Exception as e: + if hasattr(e,'message'): + response = self.create_error_response(-32098,'Scapy Server: '+str(e.message),req_id) + else: + response = self.create_error_response(-32096,'Scapy Server: Unknown Error',req_id) finally: - print(response) return response class Scapy_server(): @@ -109,7 +107,7 @@ class Scapy_server(): print ('Server IP address: %s' % self.IP_address) try: while True: - message = self.socket.recv() + message = self.socket.recv_string() try: req_id = 'null' method,params,req_id = self.scapy_wrapper.parse_req_msg(message) @@ -124,12 +122,12 @@ class Scapy_server(): finally: json_response = json.dumps(response) # Send reply back to client - self.socket.send(json_response) - if (method =='shut_down'): + self.socket.send_string(json_response) + if (method == 'shut_down'): break except KeyboardInterrupt: - print('Terminated By Ctrl+C') + print(b'Terminated By Ctrl+C') finally: self.socket.close() -- cgit