add a tool for listing GTP messages structure and context
This commit is contained in:
parent
ae3df5b25d
commit
347a31b6de
|
@ -0,0 +1,213 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# -*- coding: UTF-8 -*-
|
||||
#/**
|
||||
# * Software Name : pycrate
|
||||
# * Version : 0.4
|
||||
# *
|
||||
# * Copyright 2022. Benoit Michau. P1sec
|
||||
# *
|
||||
# * This program is free software: you can redistribute it and/or modify
|
||||
# * it under the terms of the GNU General Public License version 2 as published
|
||||
# * by the Free Software Foundation.
|
||||
# *
|
||||
# * This program 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 General Public License for more details.
|
||||
# *
|
||||
# * You will find a copy of the terms and conditions of the GNU General Public
|
||||
# * License version 2 in the "license.txt" file or
|
||||
# * see http://www.gnu.org/licenses/ or write to the Free Software Foundation,
|
||||
# * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
# *
|
||||
# *--------------------------------------------------------
|
||||
# * File Name : tools/pycrate_gtp_type_info.py
|
||||
# * Created : 2022-12-13
|
||||
# * Authors : Benoit Michau
|
||||
# *--------------------------------------------------------
|
||||
#*/
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
from pycrate_mobile.TS29060_GTP import * # GTPv1-C
|
||||
from pycrate_mobile.TS29274_GTPC import * # GTPv2-C
|
||||
from pycrate_mobile.TS29281_GTPU import * # GTP-U
|
||||
|
||||
|
||||
def _print_msgtype_info(cls):
|
||||
Msg = cls()
|
||||
Msg[1].init_ies(wopt=True, wpriv=True)
|
||||
print(' ' + Msg.show().replace('\n', '\n '))
|
||||
#
|
||||
if isinstance(Msg[1].MAND, set):
|
||||
# GTPv1-C
|
||||
print('\n mandatory IE(s): %s' % ', '.join(Msg[1].MAND))
|
||||
else:
|
||||
# GTPv2-C
|
||||
print('\n mandatory IE(s): %s' % ', '.join(['%s (%i, %i)' % (v[1], k[0], k[1]) for k, v in Msg[1].MAND.items()]))
|
||||
|
||||
|
||||
GTPv1CCtxt = {
|
||||
'Path' : 'path management',
|
||||
'Tun' : 'tunnel management',
|
||||
'Loc' : 'location management',
|
||||
'Mob' : 'mobility management',
|
||||
'MB_UE' : 'UE-related MBMS management',
|
||||
'MB_Serv' : 'MBMS service management',
|
||||
'MSInfo' : 'MS-related charging notification',
|
||||
'GTPp' : 'charging with GTP\''
|
||||
}
|
||||
|
||||
|
||||
def _print_msgctxt_info(vers, typ):
|
||||
prot, inf = [], []
|
||||
if vers == 1:
|
||||
if typ in GTPDispatcherSGSN:
|
||||
prot.append('GTPv1-C')
|
||||
if typ in GTPUDispatcher:
|
||||
prot.append('GTP-U')
|
||||
else:
|
||||
if typ in GTPCDispatcher:
|
||||
prot.append('GTPv2-C')
|
||||
if typ in GTPUDispatcher:
|
||||
prot.append('GTP-U')
|
||||
print(' Message used in %s' % ' and '.join(prot))
|
||||
#
|
||||
if 'GTPv1-C' in prot:
|
||||
# transactional ctxt
|
||||
for ctxt, ctxt_dict in GTPReqResp.items():
|
||||
for ini, dst in ctxt_dict.items():
|
||||
if ini[0] == typ:
|
||||
if ini[1] == 'SGSN':
|
||||
disp_ini, disp_resp = GTPDispatcherGGSN, GTPDispatcherSGSN
|
||||
else:
|
||||
disp_ini, disp_resp = GTPDispatcherSGSN, GTPDispatcherGGSN
|
||||
inf.append('%s (type %i) initiated by %s, sent to %s and responded with %s (type %s), used for %s'\
|
||||
% (disp_ini[ini[0]].__name__, ini[0], ini[1], dst[1], disp_resp[dst[0]].__name__ if dst[0] else 'None', dst[0], GTPv1CCtxt[ctxt]))
|
||||
elif dst[0] == typ:
|
||||
if dst[1] == 'SGSN':
|
||||
disp_ini, disp_resp = GTPDispatcherSGSN, GTPDispatcherGGSN
|
||||
else:
|
||||
disp_ini, disp_resp = GTPDispatcherGGSN, GTPDispatcherSGSN
|
||||
inf.append('%s (type %i) initiated by %s, sent to %s in response to %s (type %s), used for %s'\
|
||||
% (disp_ini[dst[0]].__name__, dst[0], dst[1], ini[1], disp_resp[ini[0]].__name__, ini[0], GTPv1CCtxt[ctxt]))
|
||||
if inf:
|
||||
print(' - ' + '\n - '.join(inf))
|
||||
#
|
||||
elif 'GTPv2-C' in prot:
|
||||
# transactional ctxt
|
||||
for req, resps in GTPCReqResp.items():
|
||||
if req == typ:
|
||||
inf.append('%s (type %i), responded with' % (GTPCDispatcher[req].__name__, req))
|
||||
if resps[0] is not None:
|
||||
inf[-1] += ' %s (type %s) for success' % (GTPCDispatcher[resps[0]].__name__, resps[0])
|
||||
else:
|
||||
inf[-1] += ' None for success'
|
||||
if len(resps) > 1:
|
||||
inf[-1] += ', %s (type %s) for error' % (GTPCDispatcher[resps[1]].__name__, resps[1])
|
||||
elif resps[0] == typ:
|
||||
# success
|
||||
inf.append('%s (type %i) in successful response to %s (type %i)'\
|
||||
% (GTPCDispatcher[resps[0]].__name__, resps[0], GTPCDispatcher[req].__name__, req))
|
||||
elif len(resps) > 1 and resps[1] == typ:
|
||||
# error
|
||||
inf.append('%s (type %i) in error response to %s (type %i)'\
|
||||
% (GTPCDispatcher[resps[1]].__name__, resps[1], GTPCDispatcher[req].__name__, req))
|
||||
if inf:
|
||||
print(' ' + '\n '.join(inf))
|
||||
#
|
||||
ift = []
|
||||
for ifn, ifts in GTPC_IF_ALL.items():
|
||||
if typ in ifts:
|
||||
ift.append(ifn)
|
||||
print(' Used in interfaces: %s' % ', '.join(ift))
|
||||
|
||||
|
||||
# the entry for the app is the protocol version (V1 or V2) and the message type
|
||||
|
||||
def print_msgtype_infos(vers, typ):
|
||||
if vers == 1:
|
||||
if typ is None:
|
||||
# list all GTPv1-C messages
|
||||
for t in GTPDispatcherSGSN:
|
||||
if t in {18, 19}:
|
||||
print('- %3i: %s' % (t, GTPDispatcherSGSN[t].__name__))
|
||||
print('- %3i: %s' % (t, GTPDispatcherGGSN[t].__name__))
|
||||
else:
|
||||
print('- %3i: %s' % (t, GTPDispatcherSGSN[t].__name__))
|
||||
else:
|
||||
for t in typ:
|
||||
if t not in GTPDispatcherSGSN:
|
||||
if t in GTPUDispatcher:
|
||||
cls = GTPUDispatcher(t)
|
||||
print('- %3i: %s\n' % (t, cls.__name__))
|
||||
_print_msgctxt_info(vers, t)
|
||||
print('')
|
||||
print(' ' + cls().show().replace('\n', '\n '))
|
||||
print('')
|
||||
else:
|
||||
# non-existent message
|
||||
print('- %3i: type does not exist for GTPv1\n' % t)
|
||||
elif t in {18, 19}:
|
||||
# can be both SGSN and GGSN-initiated, with different struct
|
||||
cls = GTPDispatcherSGSN[t]
|
||||
print('- %3i: %s\n' % (t, cls.__name__))
|
||||
_print_msgctxt_info(vers, t)
|
||||
print('')
|
||||
_print_msgtype_info(cls)
|
||||
print('')
|
||||
#
|
||||
cls = GTPDispatcherGGSN[t]
|
||||
print('- %3i: %s\n' % (t, cls.__name__))
|
||||
_print_msgtype_info(cls)
|
||||
print('')
|
||||
else:
|
||||
# get the msg
|
||||
cls = GTPDispatcherSGSN[t]
|
||||
print('- %3i: %s\n' % (t, cls.__name__))
|
||||
_print_msgctxt_info(vers, t)
|
||||
print('')
|
||||
_print_msgtype_info(cls)
|
||||
print('')
|
||||
#
|
||||
elif vers == 2:
|
||||
if typ is None:
|
||||
# list all GTPv2-C messages
|
||||
for t in GTPCDispatcher:
|
||||
print('- %3i: %s' % (t, GTPCDispatcher[t].__name__))
|
||||
else:
|
||||
for t in typ:
|
||||
if t not in GTPCDispatcher:
|
||||
print('- %3i: type does not exist for GTPv2\n' % t)
|
||||
else:
|
||||
# get the msg
|
||||
cls = GTPCDispatcher[t]
|
||||
print('- %3i: %s\n' % (t, cls.__name__))
|
||||
_print_msgctxt_info(vers, t)
|
||||
print('')
|
||||
_print_msgtype_info(cls)
|
||||
print('')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='print information related to GTP-C '\
|
||||
'messages structure and context')
|
||||
parser.add_argument('-v2', action='store_true', help='GTPv2 (TS 29.274, 29.276 and 29.280) instead of GTPv1 (TS 29.060 and TS 32.295)')
|
||||
parser.add_argument('-t', type=int, nargs='+', help='GTP-C message type (0..255)')
|
||||
args = parser.parse_args()
|
||||
#
|
||||
if args.v2:
|
||||
vers = 2
|
||||
else:
|
||||
vers = 1
|
||||
#
|
||||
print_msgtype_infos(vers, args.t)
|
||||
#
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
Loading…
Reference in New Issue