Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on encoding TCAP message with invoke component without linkedId #23

Closed
alishir opened this issue Feb 7, 2024 · 4 comments · Fixed by #25
Closed

Error on encoding TCAP message with invoke component without linkedId #23

alishir opened this issue Feb 7, 2024 · 4 comments · Fixed by #25
Assignees
Labels
wontfix This will not be worked on

Comments

@alishir
Copy link

alishir commented Feb 7, 2024

Thanks for the great library, I've tried to encode the following tcap:map message, but I got some error. Here is the snippet:

    {ok, Arg} = file:read_file("/home/ali/arg.bin"),

    Map = #{
        operation => anyTimeInterrogation,
        component_type => invoke,
        invokeId => 0,
        opcode => {local, 71},
        argument => Arg
    },

    Tcap = #{
        protocol => tcap,
        otid => <<"000001B3">>,
        type => 'begin',
        dialogue =>
            #{
                type => dialogueRequest,
                application_context_family => map,
                user_information => undefined,
                application_context_name => 'anyTimeInfoEnquiryContext-v3',
                supported_versions => [version1]
            }
    },

    {ok, TcapBin} = otc:encode({Tcap, [Map]}),

And here is the error message:

error: {badmatch,
               {error,
                   {asn1,
                       {badarg,
                           [{erlang,element,
                                [1,absent],
                                [{error_info,#{module => erl_erts_errors}}]},
                            {'TCAP-OTC',enc_Invoke_linkedId,2,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,787}]},
                            {'TCAP-OTC',enc_Invoke,2,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,760}]},
                            {'TCAP-OTC',enc_ROS,2,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,684}]},
                            {'TCAP-OTC',enc_Component,2,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,632}]},
                            {'TCAP-OTC',enc_ComponentPortion_components,3,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,605}]},
                            {'TCAP-OTC',enc_ComponentPortion,2,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,598}]},
                            {'TCAP-OTC',enc_Begin,2,
                                [{file,
                                     "/home/ali/workspace/ehod/_build/default/lib/otc/src/TCAP-OTC.erl"},
                                 {line,300}]}]}}}}
    stack: [{otc_tcap,encode,1,
                      [{file,"/home/ali/workspace/ehod/_build/default/lib/otc/src/otc_tcap.erl"},
                       {line,46}]},
            {otc,enc_safe,2,
                 [{file,"/home/ali/workspace/ehod/_build/default/lib/otc/src/otc.erl"},
                  {line,192}]},
            {hlr_client,handle_continue,2,
                        [{file,"/home/ali/workspace/ehod/apps/ehod/src/hlr_client.erl"},
                         {line,208}]},
            {gen_server,try_handle_continue,3,
                        [{file,"gen_server.erl"},{line,1085}]},
            {gen_server,loop,7,[{file,"gen_server.erl"},{line,995}]},
            {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,241}]}]

I've modified the compose_invoke_id function to return a tuple if linked_id is not set, but wireshark claims that the packet is malformed. Here is the change that I've made in otc_tcap.erl:

compose_invoke_id(I) when is_integer(I) ->
    {present, I};
compose_invoke_id(absent) ->
    {absent, 0}.
@sebastiw
Copy link
Owner

sebastiw commented Jun 2, 2024

sorry I completely missed this one. I've confirmed that I'm too see this one.
I've added a PR #25, does this solve it for you?

@alishir
Copy link
Author

alishir commented Jun 3, 2024

Unfortunately, I was unable to test your solution at this time. However, here is the modification that worked for me:

main...alishir:otc:linked-id-bugfix

@sebastiw
Copy link
Owner

sebastiw commented Jun 5, 2024

I've checked a bit more, and it seems Wireshark ASN.1 implementation differs and generates this issue.

GSM-ASN.1 is from prior to ASN.1-spec removed support of macros, so everyone who are implementing this will have to modify the specification for it to work.

The original ITU-T X.880 ASN.1 defines the following for Invoke

Invoke{InvokeId:InvokeIdSet, OPERATION]:Operations} ::= SEQUENCE {
  invokeId
    InvokeId(InvokeIdSet)
      (CONSTRAINED BY { -- must be unambiguous --} !
       RejectProblem,
  linkedId
    CHOICE {present  [0] IMPLICIT present < InvokeId,
            absent   [1] IMPLICIT NULL
  }
  (CONSTRAINED BY { -- must identify an outstanding operation --} !
   RejectProblem:invoke-unrecognizedLinkedId)
  (CONSTRAINED BY { -- which has one or more linked operations--} !
   RejectProblem OPTIONAL,
  opcode
    OPERATION.&operationCode
      ({Operations} !RejectProblem:invoke-unrecognizedOperation),
  argument
    OPERATION.&ArgumentType
      ({Operations}{@opcode} !RejectProblem OPTIONAL
}
(CONSTRAINED BY { -- must conform to the above definition --} !
 RejectProblem
(WITH COMPONENTS {
   ...,
   linkedId  ABSENT
 } |
 WITH COMPONENTS {
   ...,
   linkedId  PRESENT,
   opcode    (CONSTRAINED BY { -- must be in the &Linked field of the associated operation --
                } !RejectProblem:invoke-unexpectedLinkedOperation)
 })
 
 InvokeId ::= CHOICE {present  INTEGER,
                     absent   NULL
}

What Wireshark has done in this regard is to remove absent-type, and remove the implicit tags.
see GSMMAP.asn

Invoke ::=		SEQUENCE {
				invokeID			InvokeIdType,
				linkedID			[0] InvokeIdType OPTIONAL,
				opCode				MAP-OPERATION,
				invokeparameter	 	InvokeParameter OPTIONAL
}
InvokeIdType ::=	INTEGER (-128..127)

Which is much different from original and from OTC implementation.

Invoke ::= SEQUENCE
{
   invokeId InvokeId,
   linkedId CHOICE {
                     present [0] IMPLICIT present < InvokeId,
                     absent  [1] IMPLICIT NULL
                   } OPTIONAL,
   opcode Code,
   argument ANY DEFINED BY opcode OPTIONAL
}
InvokeId ::= CHOICE
{
   present INTEGER,
   absent NULL
}

I think this is a bug in the wireshark dissector, and you should raise a bug-report there. Because absent is allowed on the wire.

BTW I created a function to write a payload to pcap, it can be used in the following way.

MAPBin = <<48,19,160,9,128,7,1,2,3,4,5,6,7,161,0,131,4,9,8,7,6>>,
M3ua = #{protocol => m3ua,
         message_type => data,
         message_class => transfer,
         protocol_data =>
             #{service_indicator => sccp,
               originating_point_code => <<0,0,5,4>>,
               destination_point_code => <<0,0,53,167>>,
               network_indicator => national_spare,
               message_priority => 0,
               signalling_link_selection => 8}},
Sccp = #{protocol => sccp,
         message_type => xudt,
         called_party_address =>
             #{subsystem_number => msc,
               routing_indicator => global_title,
               global_title =>
                   #{address => "46777777777",
                     nature_of_address_indicator => 4,
                     numbering_plan => 1,
                     translation_type => 0,
                     odd_even_indicator => odd,
                     encoding_scheme => bcd},
               national_use_indicator => false,
               point_code => undefined},
         calling_party_address =>
             #{subsystem_number => msc,
               routing_indicator => global_title,
               global_title =>
                   #{address => "46777777777",
                     nature_of_address_indicator => 4,
                     numbering_plan => 1,
                     translation_type => 0,
                     odd_even_indicator => odd,
                     encoding_scheme => bcd},
               national_use_indicator => false,
               point_code => undefined},
         protocol_class => #{options => return_on_error,class => 0},
         hop_counter => 15},
InvokeComponent = #{
    component_type => invoke,
    invokeId => 0,
    opcode => {local, 71},
    argument => MAPBin
},
Tcap = #{dialogue =>
           #{type => dialogueRequest,
             application_context_family => map,
             user_information => undefined,
             application_context_name => 'anyTimeInfoEnquiryContext-v3',
             supported_versions => [version1]},
        otid => <<"000001B3">>,
        components =>
           [InvokeComponent],
        type => 'begin'},
TcapBin = otc_tcap:encode(Tcap),
{ok, M3uaPkt} = otc:encode({[M3ua, Sccp], TcapBin}),
otc_util:write_to_pcap("test.pcap", M3uaPkt).

@sebastiw sebastiw added the wontfix This will not be worked on label Jun 5, 2024
@sebastiw sebastiw self-assigned this Jun 5, 2024
@alishir
Copy link
Author

alishir commented Jul 19, 2024

Sorry for the late reply; I missed your answer. Thank you very much for your detailed explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants