P1sec / pycrate

A Python library to ease the development of encoders and decoders for various protocols and file formats; contains ASN.1 and CSN.1 compilers.
GNU Lesser General Public License v2.1
381 stars 132 forks source link

Need sample example for GTP-Cv2 encoding #148

Closed akibsayyed closed 2 years ago

akibsayyed commented 3 years ago

I am using pycrate for internal study and research. I am trying to use pycreate for encoding GTP-Cv2.

I am able to perform echo request and response but developing further is bit complicated.Can you please guide me how to use pycrate for GTP-Cv2 encoding with short example.

p1-bmu commented 3 years ago

I just pushed a commit that provide a way to initialize IEs in GTP-C messages. This is however far from automatically setting well-formed message, and there is unfortunately no automatic or easy way to set proper GTP-C messages without reading through the TS 29.274 specification. When you set a GTP-C message, you need to know which optional IEs are required for your need, and you need to set appropriate values into those IEs according to their specific structures.

There is the method init_ies() that you can use to initialize all mandatory (plus eventually optional) IEs in the message. Here is an example:

In [1]: from pycrate_mobile.TS29274_GTPC import *                                                                                                         

In [2]: m = CreateBearerRequest()                                                                                                                         

In [3]: print(m.show())                                                                                                                                   
### CreateBearerRequest ###
 ### GTPCHdr ###
  <Version : 2>
  <P : 0>
  <T : 1>
  <MP : 0>
  <spare : 0>
  <Type : 95 (Create Bearer Request)>
  <Len : 8>
  <TEID : 0x00000000>
  <SeqNum : 0>
  <spare : 0>
     ### CreateBearerRequestIEs ###

In [4]: m[1].init_ies() # setting all mandatory IEs with dummy values                                                                                     

In [5]: print(m.show())                                                                                                                                   
### CreateBearerRequest ###
 ### GTPCHdr ###
  <Version : 2>
  <P : 0>
  <T : 1>
  <MP : 0>
  <spare : 0>
  <Type : 95 (Create Bearer Request)>
  <Len : 53>
  <TEID : 0x00000000>
  <SeqNum : 0>
  <spare : 0>
     ### CreateBearerRequestIEs ###
      ### LinkedEPSBearerID ###
       ### GTPCIEHdr ###
        <Type : 73 (EPS Bearer ID (EBI))>
        <Len : 1>
        <spare : 0>
        <Inst : 0>
           ### EBI ###
            <spare : 0>
            <Val : 5>
            <ext : 0x>
      ### BearerContext ###
       ### GTPCIEHdr ###
        <Type : 93>
        <Len : 36>
        <spare : 0>
        <Inst : 0>
           ### CreateBearerRequest_BearerContext ###
            ### EPSBearerID ###
             ### GTPCIEHdr ###
              <Type : 73 (EPS Bearer ID (EBI))>
              <Len : 1>
              <spare : 0>
              <Inst : 0>
                 ### EBI ###
                  <spare : 0>
                  <Val : 5>
                  <ext : 0x>
            ### BearerLevelQoS ###
             ### GTPCIEHdr ###
              <Type : 80 (Bearer Level Quality of Service (Bearer QoS))>
              <Len : 22>
              <spare : 0>
              <Inst : 0>
                 ### BearerQoS ###
                  <spare : 0>
                  <PCI : 0>
                  <PL : 0>
                  <spare : 0>
                  <PVI : 0>
                  <QCI : 9>
                  <MaxBitRateUL : 10000>
                  <MaxBitRateDL : 10000>
                  <GuaranteedBitRateUL : 0>
                  <GuaranteedBitRateDL : 0>
                  <ext : 0x>
            ### TFT ###
             ### GTPCIEHdr ###
              <Type : 84 (EPS Bearer Level Traffic Flow Template (Bearer TFT))>
              <Len : 1>
              <spare : 0>
              <Inst : 0>
                 ### BearerTFT ###
                  <Opcode : 0 (Ignore this IE)>
                  <E : 0 (no parameters list)>
                  <NumPktFilters : 0>
                  ### PktFilters ###

Here, you have 2 IEs ; you can check there content by calling them by their index:

In [9]: m[1][0][1]                                                                                                                                        
Out[9]: <EBI : <spare : 0><Val : 5><ext : 0x>>

In [10]: m[1][1][1]                                                                                                                                       
Out[10]: <CreateBearerRequest_BearerContext : <EPSBearerID : <GTPCIEHdr : <Type : 73 (EPS Bearer ID (EBI))><Len : 1><spare : 0><Inst : 0><TypeExt [transparent] : 0>><EBI : <spare : 0><Val : 5><ext : 0x>>><BearerLevelQoS : <GTPCIEHdr : <Type : 80 (Bearer Level Quality of Service (Bearer QoS))><Len : 22><spare : 0><Inst : 0><TypeExt [transparent] : 0>><BearerQoS : <spare : 0><PCI : 0><PL : 0><spare : 0><PVI : 0><QCI : 9><MaxBitRateUL : 10000><MaxBitRateDL : 10000><GuaranteedBitRateUL : 0><GuaranteedBitRateDL : 0><ext : 0x>>><TFT : <GTPCIEHdr : <Type : 84 (EPS Bearer Level Traffic Flow Template (Bearer TFT))><Len : 1><spare : 0><Inst : 0><TypeExt [transparent] : 0>><BearerTFT : <Opcode : 0 (Ignore this IE)><E : 0 (no parameters list)><NumPktFilters : 0><PktFilterIds [transparent] : ><PktFilters : ><Parameters [transparent] : >>>>

As you have here GTPCIEs into GTPCIEs (also called Grouped IEs in the spec) , you can do the same for the content of the BearerContext:

In [15]: m[1][1][1][0][1]                                                                                                                                 
Out[15]: <EBI : <spare : 0><Val : 5><ext : 0x>>

In [16]: m[1][1][1][1][1]                                                                                                                                 
Out[16]: <BearerQoS : <spare : 0><PCI : 0><PL : 0><spare : 0><PVI : 0><QCI : 9><MaxBitRateUL : 10000><MaxBitRateDL : 10000><GuaranteedBitRateUL : 0><GuaranteedBitRateDL : 0><ext : 0x>>

In [17]: m[1][1][1][2][1]                                                                                                                                 
Out[17]: <BearerTFT : <Opcode : 0 (Ignore this IE)><E : 0 (no parameters list)><NumPktFilters : 0><PktFilterIds [transparent] : ><PktFilters : ><Parameters [transparent] : >>

You can set each IE content by providing values according to each IE structure, e.g.

In [23]: m[1][1][1][1][1].set_val({'PCI': 1, 'PL': 1, 'PVI': 1, 'QCI': 7, 'MaxBitRateUL': 100000, 'MaxBitRateDL': 100000})                                

In [24]: m[1][1][1][1][1]                                                                                                                                 
Out[24]: <BearerQoS : <spare : 0><PCI : 1><PL : 1><spare : 0><PVI : 1><QCI : 7><MaxBitRateUL : 100000><MaxBitRateDL : 100000><GuaranteedBitRateUL : 0><GuaranteedBitRateDL : 0><ext : 0x>>

If you want to set the infamous BearerTFT, you need however to go through the complex structure at: https://github.com/P1sec/pycrate/blob/034be6d918cb4599673919bde0d5f2fab592c3ac/pycrate_mobile/TS24008_IE.py#L3424

Finally, if you want to set the biggest message possible, you can initialize all IEs, including all optionals. This will certainly not correspond to any concrete signaling scenario from the spec, but can be useful to discover all defined IEs for a given message:

In [27]: m[1].init_ies(wopt=True)                                                                                                                         

In [28]: print(m.show())                                                                                                                                  
### CreateBearerRequest ###
 ### GTPCHdr ###
  <Version : 2>
  <P : 0>
  <T : 1>
  <MP : 0>
  <spare : 0>
  <Type : 95 (Create Bearer Request)>
  <Len : 328>
  <TEID : 0x00000000>
  <SeqNum : 0>
  <spare : 0>
     ### CreateBearerRequestIEs ###
      ### LinkedEPSBearerID ###
       ### GTPCIEHdr ###
        <Type : 73 (EPS Bearer ID (EBI))>
        <Len : 1>
        <spare : 0>
        <Inst : 0>
           ### EBI ###
            <spare : 0>
            <Val : 5>
            <ext : 0x>
      ### BearerContext ###
       ### GTPCIEHdr ###
        <Type : 93>
        <Len : 142>
        <spare : 0>
        <Inst : 0>
           ### CreateBearerRequest_BearerContext ###
            ### EPSBearerID ###
             ### GTPCIEHdr ###
              <Type : 73 (EPS Bearer ID (EBI))>
              <Len : 1>
              <spare : 0>
              <Inst : 0>
                 ### EBI ###
                  <spare : 0>
                  <Val : 5>
                  <ext : 0x>
            [...]
            ### PGWSetFQDN ###
             ### GTPCIEHdr ###
              <Type : 215 (PGW Set FQDN)>
              <Len : 0>
              <spare : 0>
              <Inst : 0>
                 ### PGWSetFQDN ###
                  ### FQDN ###
                  <ext : 0x>

You can also add / remove IE one by one within a message, by using the add_ie() and rem_ie() methods, providing the IE type and optionally instance and value.

You can finally create a dict with all required values for you message, and pass it during message initialization, similar to this:

In [34]: from socket import inet_aton 

In [35]: m = CreateBearerRequest(val={'CreateBearerRequestIEs': [ 
    ...:     {'GTPCIEHdr': {'Type': 73}, 'EBI': {'Val': 12}}, 
    ...:     {'GTPCIEHdr': {'Type': 93}, 'CreateBearerRequest_BearerContext': [ 
    ...:         {'GTPCIEHdr': {'Type': 73}, 'EBI': {'Val': 12}}, 
    ...:         {'GTPCIEHdr': {'Type': 80}, 'BearerQoS': {'PCI': 1, 'PL': 1, 'PVI': 1, 'QCI': 7, 'MaxBitRateUL': 100000, 'MaxBitRateDL': 100000}}, 
    ...:         {'GTPCIEHdr': {'Type': 84}, 'BearerTFT': {'Opcode': 1}}]}, 
    ...:     {'GTPCIEHdr': {'Type': 87}, 'FTEID': {'V4': 1, 'IPv4Addr': inet_aton('10.11.12.13'), 'TEID_GREKey': 0x99887766}} 
    ...:     ]}) 
    ...:                                                                                                                                                  

In [36]: print(m.show())                                                                                                                                  
### CreateBearerRequest ###
 ### GTPCHdr ###
  <Version : 2>
  <P : 0>
  <T : 1>
  <MP : 0>
  <spare : 0>
  <Type : 95 (Create Bearer Request)>
  <Len : 66>
  <TEID : 0x00000000>
  <SeqNum : 0>
  <spare : 0>
     ### CreateBearerRequestIEs ###
      ### LinkedEPSBearerID ###
       ### GTPCIEHdr ###
        <Type : 73 (EPS Bearer ID (EBI))>
        <Len : 1>
        <spare : 0>
        <Inst : 0>
           ### EBI ###
            <spare : 0>
            <Val : 12>
            <ext : 0x>
      ### BearerContext ###
       ### GTPCIEHdr ###
        <Type : 93>
        <Len : 36>
        <spare : 0>
        <Inst : 0>
           ### CreateBearerRequest_BearerContext ###
            ### EPSBearerID ###
             ### GTPCIEHdr ###
              <Type : 73 (EPS Bearer ID (EBI))>
              <Len : 1>
              <spare : 0>
              <Inst : 0>
                 ### EBI ###
                  <spare : 0>
                  <Val : 12>
                  <ext : 0x>
            ### BearerLevelQoS ###
             ### GTPCIEHdr ###
              <Type : 80 (Bearer Level Quality of Service (Bearer QoS))>
              <Len : 22>
              <spare : 0>
              <Inst : 0>
                 ### BearerQoS ###
                  <spare : 0>
                  <PCI : 1>
                  <PL : 1>
                  <spare : 0>
                  <PVI : 1>
                  <QCI : 7>
                  <MaxBitRateUL : 100000>
                  <MaxBitRateDL : 100000>
                  <GuaranteedBitRateUL : 0>
                  <GuaranteedBitRateDL : 0>
                  <ext : 0x>
            ### TFT ###
             ### GTPCIEHdr ###
              <Type : 84 (EPS Bearer Level Traffic Flow Template (Bearer TFT))>
              <Len : 1>
              <spare : 0>
              <Inst : 0>
                 ### BearerTFT ###
                  <Opcode : 1 (Create new TFT)>
                  <E : 0 (no parameters list)>
                  <NumPktFilters : 0>
                  ### PktFilters ###
      ### GTPCIE ###
       ### GTPCIEHdr ###
        <Type : 87 (Fully Qualified Tunnel Endpoint Identifier (F-TEID))>
        <Len : 9>
        <spare : 0>
        <Inst : 0>
           ### FTEID ###
            <V4 : 1>
            <V6 : 0>
            <IF : 0 (S1-U eNodeB GTP-U interface)>
            <TEID_GREKey : 0x99887766>
            <IPv4Addr : 0x0a0b0c0d>
            <ext : 0x>

In [37]: m.to_bytes()                                                                                                                                     
Out[37]: b'H_\x00B\x00\x00\x00\x00\x00\x00\x00\x00I\x00\x01\x00\x0c]\x00$\x00I\x00\x01\x00\x0cP\x00\x16\x00E\x07\x00\x00\x01\x86\xa0\x00\x00\x01\x86\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x01\x00 W\x00\t\x00\x80\x99\x88wf\n\x0b\x0c\r'

All GTP-C messages from the few specifications related to this protocol are defined in the second part of the TS29274_GTPC.py file, and can be access through the GTPCDispatcher dict.

That's all I can provide to you. In case you come with more / better explanations or methods to work with GTP-C, please do not hesitate to write a new section for the pycrate wiki here: https://github.com/P1sec/pycrate/wiki/The-pycrate-wiki

akibsayyed commented 3 years ago

Thank you @p1-bmu for quick response

Let me test again with modified version

p1-bmu commented 2 years ago

I just wrote this: https://github.com/P1sec/pycrate/wiki/Working-with-GTPC Now closing this issue.