diameter: initial commit with a generic Diameter encoder / decode
This commit is contained in:
parent
da0e9157fe
commit
8441a2c261
|
@ -0,0 +1,271 @@
|
|||
# -*- 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/Diameter.py
|
||||
# * Created : 2019-07-30
|
||||
# * Authors : Benoit Michau
|
||||
# *--------------------------------------------------------
|
||||
#*/
|
||||
|
||||
#__all__ = [
|
||||
# ]
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# IETF RFC 6733
|
||||
# https://tools.ietf.org/html/rfc6733
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
import datetime
|
||||
|
||||
from pycrate_core.utils import *
|
||||
from pycrate_core.elt import *
|
||||
from pycrate_core.base import *
|
||||
from pycrate_core.repr import *
|
||||
|
||||
try:
|
||||
from .parse_iana_diameter_xml import *
|
||||
AppID_dict, Cmd_dict, AVPCodes_dict, AVPSpecVal_dict = build_dict_from_xml(FILENAME_aaa_parameters)
|
||||
AddrFamNums_dict = build_dict_from_xml(FILENAME_address_family_numbers)
|
||||
except Exception as err:
|
||||
log('warning: unable to extract Diameter dict from xml files, %s' % err)
|
||||
AppID_dict, Cmd_dict, AVPCodes_dict, AVPSpecVal_dict = {}, {}, {}, {}
|
||||
AddrFamNums_dict = {}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# 4.2. Basic AVP Data Formats
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
# Basic AVP Data formats with direct pycrate correspondence:
|
||||
#
|
||||
# OctetString: Buf()
|
||||
# Integer32: Int32()
|
||||
# Integer64: Int64()
|
||||
# Unsigned32: Uint32()
|
||||
# Unsigned64: Uint64()
|
||||
|
||||
class OctetString(Buf):
|
||||
pass
|
||||
|
||||
class Integer32(Int32):
|
||||
pass
|
||||
|
||||
class Integer64(Int64):
|
||||
pass
|
||||
|
||||
class Unsigned32(Uint32):
|
||||
pass
|
||||
|
||||
class Unsigned64(Uint64):
|
||||
pass
|
||||
|
||||
|
||||
# Float32 and Float64 require IEEE-754-1985 format definition
|
||||
|
||||
class _IEEE_754_1985(Envelope):
|
||||
# TODO: define set_val() and get_val() to handle floating / scientific numbers
|
||||
pass
|
||||
|
||||
|
||||
class Float32(_IEEE_754_1985):
|
||||
_GEN = (
|
||||
Uint('S', bl=1, dic={0: '+', 1: '-'}),
|
||||
Uint('E', bl=8),
|
||||
Uint('F', bl=23)
|
||||
)
|
||||
|
||||
|
||||
class Float64(_IEEE_754_1985):
|
||||
_GEN = (
|
||||
Uint('S', bl=1, dic={0: '+', 1: '-'}),
|
||||
Uint('E', bl=11),
|
||||
Uint('F', bl=52)
|
||||
)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# 4.3. Derived AVP Data Formats
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
# Derived AVP Data formats with direct pycrate correspondence:
|
||||
#
|
||||
# UTF8String: UTF8String()
|
||||
# DiameterIdentity: Buf(), ascii-encoded FQDN / Realm
|
||||
# DiameterURI: UTF8String(), ascii or UTF8-encoded URI
|
||||
# Enumerated: Int32(), with a dict provided
|
||||
# IPFilterRule: Buf(), ascii-encoded filter rule
|
||||
|
||||
class DiameterIdentity(Buf):
|
||||
pass
|
||||
|
||||
class DiameterURI(UTF8String):
|
||||
pass
|
||||
|
||||
class Enumerated(Int32):
|
||||
pass
|
||||
|
||||
class IPFiterRule(Buf):
|
||||
pass
|
||||
|
||||
|
||||
class Address(Envelope):
|
||||
# TODO: provides a better Value representation, at least for IPv4 and IPv6
|
||||
_GEN = (
|
||||
Uint16('AddressType', dic=AddrFamNums_dict),
|
||||
Buf('Value', rep=REPR_HEX)
|
||||
)
|
||||
|
||||
|
||||
class Time(Buf):
|
||||
# TODO: provides a way to set time and represent it correctly
|
||||
# see Python ntplib source, e.g. https://github.com/remh/ntplib
|
||||
_bl = 32
|
||||
_rep = REPR_HEX
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# 4.1. AVP Header
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
class AVPHdr(Envelope):
|
||||
|
||||
ENV_SEL_TRANS = False
|
||||
|
||||
_GEN = (
|
||||
Uint32('Code', dic=AVPCodes_dict),
|
||||
Uint('V', bl=1),
|
||||
Uint('M', bl=1),
|
||||
Uint('P', bl=1),
|
||||
Uint('reserved', bl=5),
|
||||
Uint24('Len'),
|
||||
Uint32('VendorID')
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Envelope.__init__(self, *args, **kwargs)
|
||||
self[6].set_transauto(lambda: False if self[1].get_val() else True)
|
||||
|
||||
|
||||
class AVP(Envelope):
|
||||
_GEN = (
|
||||
AVPHdr(),
|
||||
Buf('AVPData', rep=REPR_HEX, hier=1),
|
||||
Buf('AVPPad', rep=REPR_HEX)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Envelope.__init__(self, *args, **kwargs)
|
||||
self[0][5].set_valauto(lambda: 12 + self[1].get_len() if self[0][1].get_val() else \
|
||||
8 + self[1].get_len())
|
||||
self[1].set_blauto(lambda: (self[0][5].get_val() - 12) << 3 if self[0][1].get_val() else \
|
||||
(self[0][5].get_val() - 8) << 3)
|
||||
self[2].set_blauto(lambda: (-self[1].get_len()%4) << 3)
|
||||
|
||||
|
||||
def GenerateAVP(Code, DataType, M=0, P=0, VendorID=None):
|
||||
"""generate a specific Diameter AVP with the appropriate Code and Data type
|
||||
"""
|
||||
val_hdr = {'Code': Code, 'M': M, 'P': P}
|
||||
if VendorID is not None:
|
||||
val_hdr['V'] = 1
|
||||
val_hdr['VendorID'] = VendorID
|
||||
#
|
||||
if isinstance(DataType._bl, integer_types) and DataType._bl % 32 == 0:
|
||||
# fixed length AVP, no padding required
|
||||
class AVP(Envelope):
|
||||
_GEN = (
|
||||
AVPHdr(val=val_hdr),
|
||||
DataType('AVPData', hier=1)
|
||||
)
|
||||
def __init__(self, *args, **kwargs):
|
||||
Envelope.__init__(self, *args, **kwargs)
|
||||
self[0][5].set_valauto(lambda: 12 + (self[1]._bl >> 3) if self[0][1].get_val() else \
|
||||
8 + (self[1]._bl >> 3))
|
||||
else:
|
||||
# variable length AVP, padding may be required
|
||||
class AVP(Envelope):
|
||||
_GEN = (
|
||||
AVPHdr(val=val_hdr),
|
||||
DataType('AVPData', hier=1),
|
||||
Buf('AVPPad', rep=REPR_HEX)
|
||||
)
|
||||
def __init__(self, *args, **kwargs):
|
||||
Envelope.__init__(self, *args, **kwargs)
|
||||
self[0][5].set_valauto(lambda: 12 + self[1].get_len() if self[0][1].get_val() else \
|
||||
8 + self[1].get_len())
|
||||
self[1].set_blauto(lambda: (self[0][5].get_val() - 12) << 3 if self[0][1].get_val() else \
|
||||
(self[0][5].get_val() - 8) << 3)
|
||||
self[2].set_blauto(lambda: (-self[1].get_len()%4) << 3)
|
||||
#
|
||||
return AVP
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# 3. Diameter Header
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
class DiameterHdr(Envelope):
|
||||
_GEN = (
|
||||
Uint8('Vers', val=1),
|
||||
Uint24('Len'),
|
||||
Uint('R', bl=1),
|
||||
Uint('P', bl=1),
|
||||
Uint('E', bl=1),
|
||||
Uint('T', bl=1),
|
||||
Uint('reserved', bl=4),
|
||||
Uint24('Cmd', dic=Cmd_dict),
|
||||
Uint32('AppID', dic=AppID_dict),
|
||||
Uint32('HHID', rep=REPR_HEX),
|
||||
Uint32('EEID', rep=REPR_HEX)
|
||||
)
|
||||
|
||||
|
||||
class DiameterGeneric(Envelope):
|
||||
_GEN = (
|
||||
DiameterHdr(),
|
||||
Sequence('AVPs', GEN=AVP(), hier=1)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Envelope.__init__(self, *args, **kwargs)
|
||||
self[0][1].set_valauto(lambda: 20 + self[1].get_len())
|
||||
|
||||
def _from_char(self, char):
|
||||
if self.get_trans():
|
||||
return
|
||||
self[0]._from_char(char)
|
||||
#
|
||||
avps_len = self[0][1].get_val() - 20
|
||||
char_len = char.len_byte()
|
||||
if char_len > avps_len:
|
||||
char._len_bit -= 8*(char_len - avps_len)
|
||||
restore_char_len = True
|
||||
char_bl = char._len_bit
|
||||
else:
|
||||
restore_char_len = False
|
||||
#
|
||||
self[1]._from_char(char)
|
||||
#
|
||||
if restore_char_len:
|
||||
char._len_bit = char_bl
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,330 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="address-family-numbers.xsl"?>
|
||||
<?oxygen RNGSchema="address-family-numbers.rng" type="xml"?>
|
||||
<registry xmlns="http://www.iana.org/assignments" id="address-family-numbers">
|
||||
<title>Address Family Numbers</title>
|
||||
<updated>2018-04-02</updated>
|
||||
<registry id="address-family-numbers-2">
|
||||
<title>Address Family Numbers</title>
|
||||
<xref type="rfc" data="rfc2453"/>
|
||||
<xref type="rfc" data="rfc2677"/>
|
||||
<xref type="rfc" data="rfc2858"/>
|
||||
<note>Registrations also appear in <xref type="registry" data="ianaaddressfamilynumbers-mib">ianaaddressfamilynumbers-mib</xref>.
|
||||
</note>
|
||||
<note>When this registry is modified, the YANG module <xref type="registry" data="iana-routing-types">iana-routing-types</xref>
|
||||
must be updated as defined in <xref type="rfc" data="rfc8294"/>.
|
||||
</note>
|
||||
<range>
|
||||
<value>1-16383</value>
|
||||
<registration_rule>Standards Action</registration_rule>
|
||||
</range>
|
||||
<range>
|
||||
<value>16384-32767</value>
|
||||
<registration_rule>First Come First Served</registration_rule>
|
||||
</range>
|
||||
<record>
|
||||
<value>0</value>
|
||||
<description>Reserved</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>1</value>
|
||||
<description>IP (IP version 4)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>2</value>
|
||||
<description>IP6 (IP version 6)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>3</value>
|
||||
<description>NSAP</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>4</value>
|
||||
<description>HDLC (8-bit multidrop)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>5</value>
|
||||
<description>BBN 1822</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>6</value>
|
||||
<description>802 (includes all 802 media plus Ethernet "canonical format")</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>7</value>
|
||||
<description>E.163</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>8</value>
|
||||
<description>E.164 (SMDS, Frame Relay, ATM)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>9</value>
|
||||
<description>F.69 (Telex)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>10</value>
|
||||
<description>X.121 (X.25, Frame Relay)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>11</value>
|
||||
<description>IPX</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>12</value>
|
||||
<description>Appletalk</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>13</value>
|
||||
<description>Decnet IV</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>14</value>
|
||||
<description>Banyan Vines</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="1995-10">
|
||||
<value>15</value>
|
||||
<description>E.164 with NSAP format subaddress</description>
|
||||
<xref type="text">ATM Forum UNI 3.1. October 1995.</xref>
|
||||
<xref type="person" data="Andy_Malis"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>16</value>
|
||||
<description>DNS (Domain Name System)</description>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2000-03">
|
||||
<value>17</value>
|
||||
<description>Distinguished Name</description>
|
||||
<xref type="person" data="Charles_Lynn"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2000-03">
|
||||
<value>18</value>
|
||||
<description>AS Number</description>
|
||||
<xref type="person" data="Charles_Lynn"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2000-09">
|
||||
<value>19</value>
|
||||
<description>XTP over IP version 4</description>
|
||||
<xref type="person" data="Mike_Saul"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2000-09">
|
||||
<value>20</value>
|
||||
<description>XTP over IP version 6</description>
|
||||
<xref type="person" data="Mike_Saul"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2000-09">
|
||||
<value>21</value>
|
||||
<description>XTP native mode XTP</description>
|
||||
<xref type="person" data="Mike_Saul"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2002-03">
|
||||
<value>22</value>
|
||||
<description>Fibre Channel World-Wide Port Name</description>
|
||||
<xref type="person" data="Mark_Bakke"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2002-03">
|
||||
<value>23</value>
|
||||
<description>Fibre Channel World-Wide Node Name</description>
|
||||
<xref type="person" data="Mark_Bakke"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2002-03">
|
||||
<value>24</value>
|
||||
<description>GWID</description>
|
||||
<xref type="person" data="Subra_Hegde"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>25</value>
|
||||
<description>AFI for L2VPN information</description>
|
||||
<xref type="rfc" data="rfc4761"/>
|
||||
<xref type="rfc" data="rfc6074"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>26</value>
|
||||
<description>MPLS-TP Section Endpoint Identifier</description>
|
||||
<xref type="rfc" data="rfc7212"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>27</value>
|
||||
<description>MPLS-TP LSP Endpoint Identifier</description>
|
||||
<xref type="rfc" data="rfc7212"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>28</value>
|
||||
<description>MPLS-TP Pseudowire Endpoint Identifier</description>
|
||||
<xref type="rfc" data="rfc7212"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2014-04-29">
|
||||
<value>29</value>
|
||||
<description>MT IP: Multi-Topology IP version 4</description>
|
||||
<xref type="rfc" data="rfc7307"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2014-04-29">
|
||||
<value>30</value>
|
||||
<description>MT IPv6: Multi-Topology IP version 6</description>
|
||||
<xref type="rfc" data="rfc7307"/>
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>31-16383</value>
|
||||
<description>Unassigned</description>
|
||||
|
||||
<registration/>
|
||||
</record>
|
||||
<record date="2008-05-13">
|
||||
<value>16384</value>
|
||||
<description>EIGRP Common Service Family</description>
|
||||
<xref type="person" data="Donnie_Savage"/>
|
||||
<registration>2008-05-13</registration>
|
||||
</record>
|
||||
<record date="2008-05-13">
|
||||
<value>16385</value>
|
||||
<description>EIGRP IPv4 Service Family</description>
|
||||
<xref type="person" data="Donnie_Savage"/>
|
||||
<registration>2008-05-13</registration>
|
||||
</record>
|
||||
<record date="2008-05-13">
|
||||
<value>16386</value>
|
||||
<description>EIGRP IPv6 Service Family</description>
|
||||
<xref type="person" data="Donnie_Savage"/>
|
||||
<registration>2008-05-13</registration>
|
||||
</record>
|
||||
<record date="2009-11-12">
|
||||
<value>16387</value>
|
||||
<description>LISP Canonical Address Format (LCAF)</description>
|
||||
<xref type="person" data="David_Meyer"/>
|
||||
<registration>2009-11-12</registration>
|
||||
</record>
|
||||
<record date="2013-03-20" updated="2016-03-22">
|
||||
<value>16388</value>
|
||||
<description>BGP-LS</description>
|
||||
<xref type="rfc" data="rfc7752"/>
|
||||
<registration>2013-03-20</registration>
|
||||
</record>
|
||||
<record date="2013-05-06">
|
||||
<value>16389</value>
|
||||
<description>48-bit MAC</description>
|
||||
<xref type="rfc" data="rfc7042"/>
|
||||
<registration>2013-05-06</registration>
|
||||
</record>
|
||||
<record date="2013-05-06">
|
||||
<value>16390</value>
|
||||
<description>64-bit MAC</description>
|
||||
<xref type="rfc" data="rfc7042"/>
|
||||
<registration>2013-05-06</registration>
|
||||
</record>
|
||||
<record date="2013-09-25">
|
||||
<value>16391</value>
|
||||
<description>OUI</description>
|
||||
<xref type="rfc" data="rfc7961"/>
|
||||
<registration>2013-09-25</registration>
|
||||
</record>
|
||||
<record date="2013-09-25">
|
||||
<value>16392</value>
|
||||
<description>MAC/24</description>
|
||||
<xref type="rfc" data="rfc7961"/>
|
||||
<registration>2013-09-25</registration>
|
||||
</record>
|
||||
<record date="2013-09-25">
|
||||
<value>16393</value>
|
||||
<description>MAC/40</description>
|
||||
<xref type="rfc" data="rfc7961"/>
|
||||
<registration>2013-09-25</registration>
|
||||
</record>
|
||||
<record date="2013-09-25">
|
||||
<value>16394</value>
|
||||
<description>IPv6/64</description>
|
||||
<xref type="rfc" data="rfc7961"/>
|
||||
<registration>2013-09-25</registration>
|
||||
</record>
|
||||
<record date="2013-09-25">
|
||||
<value>16395</value>
|
||||
<description>RBridge Port ID</description>
|
||||
<xref type="rfc" data="rfc7961"/>
|
||||
<registration>2013-09-25</registration>
|
||||
</record>
|
||||
<record date="2014-09-02" updated="2014-11-07">
|
||||
<value>16396</value>
|
||||
<description>TRILL Nickname</description>
|
||||
<xref type="rfc" data="rfc7455"/>
|
||||
<registration>2014-09-02</registration>
|
||||
</record>
|
||||
<record>
|
||||
<value>16397-65534</value>
|
||||
<description>Unassigned</description>
|
||||
|
||||
<registration/>
|
||||
</record>
|
||||
<record>
|
||||
<value>65535</value>
|
||||
<description>Reserved</description>
|
||||
<registration/>
|
||||
</record>
|
||||
</registry>
|
||||
<people>
|
||||
<person id="Andy_Malis">
|
||||
<name>Andy Malis</name>
|
||||
<uri>mailto:agmalis&gmail.com</uri>
|
||||
<updated>2013-05-28</updated>
|
||||
</person>
|
||||
<person id="Charles_Lynn">
|
||||
<name>Charles Lynn</name>
|
||||
<uri>mailto:clynn&bbn.com</uri>
|
||||
<updated>2000-03</updated>
|
||||
</person>
|
||||
<person id="David_Meyer">
|
||||
<name>David Meyer</name>
|
||||
<uri>mailto:dmm&1-4-5.net</uri>
|
||||
<updated>2009-11-12</updated>
|
||||
</person>
|
||||
<person id="Donnie_Savage">
|
||||
<name>Donnie Savage</name>
|
||||
<uri>mailto:dsavage&cisco.com</uri>
|
||||
<updated>2008-05-13</updated>
|
||||
</person>
|
||||
<person id="Mark_Bakke">
|
||||
<name>Mark Bakke</name>
|
||||
<uri>mailto:mbakke&cisco.com</uri>
|
||||
<updated>2002-03</updated>
|
||||
</person>
|
||||
<person id="Mike_Saul">
|
||||
<name>Mike Saul</name>
|
||||
<uri>mailto:mike&nentat.com</uri>
|
||||
<updated>2000-09</updated>
|
||||
</person>
|
||||
<person id="Subra_Hegde">
|
||||
<name>Subra Hegde</name>
|
||||
<uri>mailto:subrah&cisco.com</uri>
|
||||
<updated>2002-03</updated>
|
||||
</person>
|
||||
</people>
|
||||
</registry>
|
|
@ -0,0 +1,148 @@
|
|||
# -*- 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
|
||||
|
Loading…
Reference in New Issue