149 lines
4.9 KiB
Python
149 lines
4.9 KiB
Python
# -*- coding: UTF-8 -*-
|
|
#/**
|
|
# * Software Name : pycrate
|
|
# * Version : 0.4
|
|
# *
|
|
# * Copyright 2019. Benoit Michau. P1Sec.
|
|
# *
|
|
# * This library is free software; you can redistribute it and/or
|
|
# * modify it under the terms of the GNU Lesser General Public
|
|
# * License as published by the Free Software Foundation; either
|
|
# * version 2.1 of the License, or (at your option) any later version.
|
|
# *
|
|
# * This library is distributed in the hope that it will be useful,
|
|
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# * Lesser General Public License for more details.
|
|
# *
|
|
# * You should have received a copy of the GNU Lesser General Public
|
|
# * License along with this library; if not, write to the Free Software
|
|
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
# * MA 02110-1301 USA
|
|
# *
|
|
# *--------------------------------------------------------
|
|
# * File Name : pycrate_diameter/parse_iana_diameter_xml.py
|
|
# * Created : 2019-07-30
|
|
# * Authors : Benoit Michau
|
|
# *--------------------------------------------------------
|
|
#*/
|
|
|
|
__all__ = [
|
|
'FILENAME_aaa_parameters',
|
|
'FILENAME_address_family_numbers',
|
|
'build_dict_from_xml'
|
|
]
|
|
|
|
|
|
import os
|
|
import re
|
|
from lxml import etree
|
|
|
|
|
|
FILENAME_aaa_parameters = os.path.dirname(__file__) + '/aaa-parameters.xml'
|
|
FILENAME_address_family_numbers = os.path.dirname(__file__) + '/address-family-numbers.xml'
|
|
|
|
|
|
'''
|
|
xml file structure for aaa-parameters.xml
|
|
|
|
AVP Codes:
|
|
AVP Code -> Attribute Name
|
|
AVP Specific Values:
|
|
Attribute Name, AVP Code:
|
|
AVP Value -> Value Name
|
|
...
|
|
AVP Flags Value
|
|
Bit -> Name
|
|
Application ID
|
|
ID Value -> Name
|
|
Command Codes
|
|
Code Value -> Name
|
|
|
|
|
|
xml file structure for address-family-numbers.xml
|
|
|
|
Address Family Numbers:
|
|
Number -> Description
|
|
'''
|
|
|
|
|
|
# some regexp
|
|
RE_INT = re.compile(r'[1-9]{1}[0-9]{0,}')
|
|
RE_HEX = re.compile(r'0x[0-9]{2,4,6,8,10,12,14,16}')
|
|
RE_SV_CODE = re.compile(r'\(code (%s)\)' % RE_INT.pattern)
|
|
|
|
|
|
def build_dict_from_xml(filename=FILENAME_aaa_parameters):
|
|
if filename == FILENAME_aaa_parameters:
|
|
T = etree.parse(filename).getroot()
|
|
for child in T.getchildren():
|
|
subchild_list = child.getchildren()
|
|
if not subchild_list:
|
|
pass
|
|
elif subchild_list[0].text == 'AVP Codes':
|
|
dict_avp_codes = build_dict_from_val_name(
|
|
[i for i in subchild_list if i.tag == '{http://www.iana.org/assignments}record'])
|
|
elif subchild_list[0].text == 'AVP Specific Values':
|
|
dict_avp_spec_val = build_dict_from_avp_spec_val(
|
|
[i for i in subchild_list if i.tag == '{http://www.iana.org/assignments}registry'])
|
|
elif subchild_list[0].text == 'Application IDs':
|
|
dict_app_id = build_dict_from_val_name(
|
|
[i for i in subchild_list if i.tag == '{http://www.iana.org/assignments}record'])
|
|
elif subchild_list[0].text == 'Command Codes':
|
|
dict_cmd_codes = build_dict_from_val_name(
|
|
[i for i in subchild_list if i.tag == '{http://www.iana.org/assignments}record'])
|
|
#
|
|
return (dict_app_id,
|
|
dict_cmd_codes,
|
|
dict_avp_codes,
|
|
dict_avp_spec_val)
|
|
#
|
|
elif filename == FILENAME_address_family_numbers:
|
|
T = etree.parse(filename).getroot()
|
|
for child in T.getchildren():
|
|
subchild_list = child.getchildren()
|
|
if not subchild_list:
|
|
pass
|
|
elif subchild_list[0].text == 'Address Family Numbers':
|
|
dict_addr_fam_nums = build_dict_from_val_name(
|
|
[i for i in subchild_list if i.tag == '{http://www.iana.org/assignments}record'])
|
|
#
|
|
return dict_addr_fam_nums
|
|
#
|
|
else:
|
|
print('error: invalid filename')
|
|
|
|
|
|
def build_dict_from_val_name(recordlist):
|
|
d = {}
|
|
for rec in recordlist:
|
|
code, name = rec.getchildren()[:2]
|
|
m = RE_INT.match(code.text)
|
|
if m:
|
|
d[int(m.group())] = name.text
|
|
return d
|
|
|
|
|
|
def build_dict_from_avp_spec_val(registrylist):
|
|
d = {}
|
|
for reg in registrylist:
|
|
childlist = reg.getchildren()
|
|
m = RE_SV_CODE.search(childlist[0].text)
|
|
if m:
|
|
code = int(m.group(1))
|
|
if code not in d:
|
|
d[code] = {}
|
|
subd = d[code]
|
|
for rec in [i for i in childlist if i.tag == '{http://www.iana.org/assignments}record']:
|
|
val, name = rec.getchildren()[:2]
|
|
m = RE_INT.match(val.text)
|
|
if m:
|
|
subd[int(m.group())] = name.text
|
|
# can also have flag values, e.g. 0x0000000000000020
|
|
else:
|
|
m = RE_HEX.match(val.text)
|
|
if m:
|
|
subd[int(m.group(), 16)] = name.text
|
|
return d
|
|
|