As ponted out by Stig Bjørlykke change a whole bunch of dissector_handle_t to static.
[obnox/wireshark/wip.git] / asn1 / inap / packet-inap-template.c
1 /* packet-inap-template.c
2  * Routines for INAP
3  * Copyright 2004, Tim Endean <endeant@hotmail.com>
4  * Built from the gsm-map dissector Copyright 2004, Anders Broman <anders.broman@ericsson.com>
5  *
6  * $Id$
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  * References: ETSI 300 374
25  * ITU Q.1218
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/prefs.h>
35 #include <epan/conversation.h>
36
37 #include <stdio.h>
38 #include <string.h>
39
40 #include "packet-ber.h"
41 #include "packet-inap.h"
42 #include "packet-q931.h"
43 #include "packet-e164.h"
44 #include "packet-isup.h"
45 #include "packet-tcap.h"
46
47 #define PNAME  "Intelligent Network Application Protocol"
48 #define PSNAME "INAP"
49 #define PFNAME "inap"
50
51 /* Initialize the protocol and registered fields */
52 int proto_inap = -1;
53 static int hf_inap_invokeCmd = -1;             /* Opcode */
54 static int hf_inap_invokeid = -1;              /* INTEGER */
55 static int hf_inap_linkedid = -1;              /* INTEGER */
56 static int hf_inap_absent = -1;                /* NULL */
57 static int hf_inap_invokeId = -1;              /* InvokeId */
58 static int hf_inap_invoke = -1;                /* InvokePDU */
59 static int hf_inap_ReturnError = -1;           /* InvokePDU */
60 static int hf_inap_returnResult = -1;          /* InvokePDU */
61 static int hf_inap_returnResult_result = -1;
62 static int hf_inap_getPassword = -1;  
63 static int hf_inap_currentPassword = -1;  
64 static int hf_inap_genproblem = -1;
65 #include "packet-inap-hf.c"
66
67 #define MAX_SSN 254
68 static range_t *global_ssn_range;
69 static range_t *ssn_range;
70
71 static dissector_handle_t       inap_handle;
72
73 /* Initialize the subtree pointers */
74 static gint ett_inap = -1;
75 static gint ett_inap_InvokeId = -1;
76 static gint ett_inap_InvokePDU = -1;
77 static gint ett_inap_ReturnErrorPDU = -1;
78 static gint ett_inap_ReturnResultPDU = -1;
79 static gint ett_inap_ReturnResult_result = -1;
80 static gint ett_inap_INAPPDU = -1;
81 static gint ett_inapisup_parameter = -1;
82 #include "packet-inap-ett.c"
83
84 static int  dissect_invokeCmd(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
85
86 #include "packet-inap-fn.c"
87
88
89 const value_string inap_opr_code_strings[] = {
90
91         {0,"InitialDP"},
92         {1, "OriginationAttemptAuthorized"},
93         {2, "CollectedInformation"},
94         {3, "AnalysedInformation"},
95         {4, "RouteSelectFailure"},
96         {5, "oCalledPartyBusy"},
97         {6, "oNoAnswer"},
98         {7, "oAnswer"},
99         {8, "oDisconnect"},
100         {9, "TermAttemptAuthorized"},
101         {10, "tBusy"},
102         {11, "tNoAnswer"},
103         {12, "tAnswer"},
104         {13, "tDisconnect"},
105         {14, "oMidCall"},
106         {15, "tMidCall"},
107         {16, "AssistRequestInstructions"},
108         {17,"EstablishTemporaryConnection"},
109         {18, "DisconnectForwardConnection"},
110         {19,"ConnectToResource"},
111         {20, "Connect"},
112         {21,"HoldCallInNetwork"},
113         {22, "ReleaseCall"},
114         {23, "RequestReportBCSMEven"},
115         {23,"RequestReportBCSMEvent"},
116         {24,"EventReportBCSM"},
117         {25, "RequestNotificationChargingEvent"},
118         {26, "EventNotificationCharging"},
119         {27, "CollectInformation"},
120         {28, "AnalyseInformation"},
121         {29, "SelectRoute"},
122         {30, "SelectFacility"},
123         {31, "Continue"},
124         {32, "InitiateCallAttempt"},
125         {33,"ResetTimer"},
126         {34,"FurnishChargingInformation"},
127         {35, "ApplyCharging"},
128         {36, "ApplyChargingReport"},
129         {37, "RequestCurrentStatusReport"},
130         {38, "RequestEveryStatusChangeReport"},
131         {39, "RequestFirstStatusMatchReport"},
132         {40, "StatusReport"},
133         {41, "CallGap"},
134         {42, "ActivateServiceFiltering"},
135         {43, "ServiceFilteringResponse"},
136         {44, "CallInformationReport"},
137         {45, "CallInformationRequest"},
138         {46, "SendChargingInformation"},
139         {47,"PlayAnnouncement"},
140         {48,"PromptAndCollectUserInformation"},
141         {49,"SpecializedResourceReport"},
142         {53, "Cancel"},
143         {55, "ActivityTest"},
144         {99,"ReceivedInformation"}, /*???????*/
145         {0, NULL}
146 };
147
148 const value_string inap_error_code_strings[] = {
149
150 {0,"cancelled"},
151 {1,"cancelFailed"},
152 {3,"etcFailed"},
153 {4,"improperCallerResponse"},
154 {6,"missingCustomerRecord"},
155 {7,"missingParameter"},
156 {8,"parameterOutOfRange"},
157 {10,"RequestedInfoError"},
158 {11,"SystemFailure"},
159 {12,"TaskRefused"},
160 {13,"UnavailableResource"},
161 {14,"UnexpectedComponentSequence"},
162 {15,"UnexpectedDataValue"},
163 {16,"UnexpectedParameter"},
164 {17,"UnknownLegID"},
165 {18,"UnknownResource"},
166 {0, NULL}
167 };
168
169 const value_string inap_general_problem_strings[] = {
170 {0,"General Problem Unrecognized Component"},
171 {1,"General Problem Mistyped Component"},
172 {3,"General Problem Badly Structured Component"},
173 {0, NULL}
174 };
175
176
177
178 static guint32 opcode=0;
179
180 static int
181 dissect_inap_Opcode(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
182   offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, offset, hf_index, &opcode);
183
184   if (check_col(pinfo->cinfo, COL_INFO)){
185     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(opcode, inap_opr_code_strings, "Unknown Inap (%u)"));
186   }
187
188   return offset;
189 }
190
191
192
193 static int
194 dissect_inap_errorCode(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
195   offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, offset, hf_index, &opcode);
196
197   if (check_col(pinfo->cinfo, COL_INFO)){
198     col_set_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, inap_error_code_strings, "Unknown Inap (%u)"));
199   }
200
201   return offset;
202 }
203
204 /*
205 TC-Invokable OPERATION ::=
206   {activateServiceFiltering | activityTest | analysedInformation |
207    analyseInformation | applyCharging | applyChargingReport |
208    assistRequestInstructions | callGap | callInformationReport |
209    callInformationRequest | cancel | cancelStatusReportRequest |
210    collectedInformation | collectInformation | connect | connectToResource |
211    continue | disconnectForwardConnection | establishTemporaryConnection |
212    eventNotificationCharging | eventReportBCSM | furnishChargingInformation |
213    holdCallInNetwork | initialDP | initiateCallAttempt | oAnswer |
214    oCalledPartyBusy | oDisconnect | oMidCall | oNoAnswer |
215    originationAttemptAuthorized | releaseCall | requestCurrentStatusReport |
216    requestEveryStatusChangeReport | requestFirstStatusMatchReport |
217    requestNotificationChargingEvent | requestReportBCSMEvent | resetTimer |
218    routeSelectFailure | selectFacility | selectRoute | sendChargingInformation
219    | serviceFilteringResponse | statusReport | tAnswer | tBusy | tDisconnect |
220    termAttemptAuthorized | tMidCall | tNoAnswer | playAnnouncement |
221    promptAndCollectUserInformation}
222 */
223
224 static int dissect_invokeData(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
225   switch(opcode){
226   case 0: /*InitialDP*/
227     offset=dissect_inap_InitialDP(FALSE, tvb, offset, pinfo, tree, hf_inap_InitialDP_PDU);
228     break;
229   case 1: /*1 OriginationAttemptAuthorized */
230     offset=dissect_inap_OriginationAttemptAuthorizedArg(FALSE, tvb, offset, pinfo, tree, hf_inap_OriginationAttemptAuthorizedArg_PDU);
231     break;
232   case 2: /*2 CollectedInformation */
233     offset=dissect_inap_CollectedInformationArg(FALSE, tvb, offset, pinfo, tree, hf_inap_CollectedInformationArg_PDU);
234     break;
235   case 3: /*3 AnalysedInformation */
236     offset=dissect_inap_AnalysedInformationArg(FALSE, tvb, offset, pinfo, tree, hf_inap_AnalysedInformationArg_PDU);
237     break;
238   case 4: /*4 RouteSelectFailure */
239     offset=dissect_inap_RouteSelectFailureArg(FALSE, tvb, offset, pinfo, tree, hf_inap_RouteSelectFailureArg_PDU);
240     break;
241   case 5: /*5 oCalledPartyBusy */
242     offset=dissect_inap_OCalledPartyBusyArg(FALSE, tvb, offset, pinfo, tree, hf_inap_OCalledPartyBusyArg_PDU);
243     break;       
244   case 6: /*6 oNoAnswer */
245     offset=dissect_inap_ONoAnswer(FALSE, tvb, offset, pinfo, tree, hf_inap_ONoAnswer_PDU);
246     break;
247   case 7: /*7 oAnswer */
248     offset=dissect_inap_OAnswerArg(FALSE, tvb, offset, pinfo, tree, hf_inap_OAnswerArg_PDU);
249     break;
250   case 8: /*8 oDisconnect */
251     offset=dissect_inap_ODisconnectArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ODisconnectArg_PDU);
252     break;
253   case 9: /*9 TermAttemptAuthorized */
254     offset=dissect_inap_TermAttemptAuthorizedArg(FALSE, tvb, offset, pinfo, tree, hf_inap_TermAttemptAuthorizedArg_PDU);
255     break;
256   case 10: /*10 tBusy */
257     offset=dissect_inap_TBusyArg(FALSE, tvb, offset, pinfo, tree, hf_inap_TBusyArg_PDU);
258     break;
259   case 11: /*11 tNoAnswer */
260     offset=dissect_inap_TNoAnswerArg(FALSE, tvb, offset, pinfo, tree, hf_inap_TNoAnswerArg_PDU);
261     break;
262   case 12: /*12 tAnswer */
263     offset=dissect_inap_TAnswerArg(FALSE, tvb, offset, pinfo, tree, hf_inap_TAnswerArg_PDU);
264     break;
265   case 13: /*13 tDisconnect */
266     offset=dissect_inap_TDisconnectArg(FALSE, tvb, offset, pinfo, tree, hf_inap_TDisconnectArg_PDU);
267     break;
268   case 14: /*14 oMidCall */
269     offset=dissect_inap_MidCallArg(FALSE, tvb, offset, pinfo, tree, hf_inap_MidCallArg_PDU);
270     break;
271   case 15: /*15 tMidCall */
272     offset=dissect_inap_MidCallArg(FALSE, tvb, offset, pinfo, tree, hf_inap_MidCallArg_PDU);
273     break;
274   case  16: /*AssistRequestInstructions*/
275     offset=dissect_inap_AssistRequestInstructionsArg(FALSE, tvb, offset, pinfo, tree, hf_inap_AssistRequestInstructionsArg_PDU);
276     break;
277   case  17: /*EstablishTemporaryConnection*/
278     offset=dissect_inap_EstablishTemporaryConnectionArg(FALSE, tvb, offset, pinfo, tree, hf_inap_EstablishTemporaryConnectionArg_PDU);
279     break;
280   case  18: /*DisconnectForwardConnections*/
281     proto_tree_add_text(tree, tvb, offset, -1, "Disconnect Forward Connection");
282     break;
283   case  19: /*ConnectToResource*/
284     offset=dissect_inap_ConnectToResourceArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ConnectToResourceArg_PDU);
285     break;
286   case  20: /*Connect*/
287     offset=dissect_inap_ConnectArg(FALSE, tvb, offset, pinfo, tree,hf_inap_ConnectArg_PDU);
288     break;      
289   case  21: /* 21 HoldCallInNetwork */
290     offset=dissect_inap_HoldCallInNetworkArg(FALSE, tvb, offset, pinfo, tree,hf_inap_HoldCallInNetworkArg_PDU);
291     break;
292
293    case 22: /*ReleaseCall*/
294     offset=dissect_inap_ReleaseCallArg(FALSE, tvb, offset, pinfo, tree,hf_inap_ReleaseCallArg_PDU);
295     break;
296     case 23: /*InitialDP*/
297     offset=dissect_inap_RequestReportBCSMEventArg(FALSE, tvb, offset, pinfo, tree, hf_inap_RequestReportBCSMEventArg_PDU);
298     break;
299   case  24: /*EventReportBCSM*/
300     offset=dissect_inap_EventReportBCSMArg(FALSE, tvb, offset, pinfo, tree, hf_inap_EventReportBCSMArg_PDU);
301     break;
302   case  25: /*25, "RequestNotificationChargingEvent */
303     offset=dissect_inap_RequestNotificationChargingEvent(FALSE, tvb, offset, pinfo, tree, hf_inap_RequestNotificationChargingEvent_PDU);
304     break;
305   case  26: /*26, "EventNotificationCharging */
306     offset=dissect_inap_EventNotificationChargingArg(FALSE, tvb, offset, pinfo, tree, hf_inap_EventNotificationChargingArg_PDU);
307     break;
308   case  27: /*27, "CollectInformation */
309     offset=dissect_inap_CollectInformationArg(FALSE, tvb, offset, pinfo, tree, hf_inap_CollectInformationArg_PDU);
310     break;
311   case  28: /*28, "AnalyseInformation */
312     offset=dissect_inap_AnalyseInformationArg(FALSE, tvb, offset, pinfo, tree, hf_inap_AnalyseInformationArg_PDU);
313     break;
314   case  29: /*29, "SelectRoute */
315     offset=dissect_inap_SelectRouteArg(FALSE, tvb, offset, pinfo, tree, hf_inap_SelectRouteArg_PDU);
316     break;
317   case  30: /*30, "SelectFacility */
318     offset=dissect_inap_SelectFacilityArg(FALSE, tvb, offset, pinfo, tree, hf_inap_SelectFacilityArg_PDU);
319     break;
320         /*31, "Continue */
321   case  32: /*32, InitiateCallAttempt*/
322     offset=dissect_inap_InitiateCallAttemptArg(FALSE, tvb, offset, pinfo, tree, hf_inap_InitiateCallAttemptArg_PDU);
323     break;
324   case 33: /*ResetTimer*/
325     offset=dissect_inap_ResetTimerArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ResetTimerArg_PDU);
326     break;
327   case 34: /*FurnishChargingInformation*/
328     offset=dissect_inap_FurnishChargingInformationArg(FALSE, tvb, offset, pinfo, tree, hf_inap_FurnishChargingInformationArg_PDU);
329     break;
330   case 35: /*35, ApplyCharging */
331     offset=dissect_inap_ApplyChargingArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ApplyChargingArg_PDU);
332     break;      
333   case 36: /*36, "ApplyChargingReport */
334     offset=dissect_inap_ApplyChargingReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ApplyChargingReportArg_PDU);
335     break;
336   case 37: /*37, "RequestCurrentStatusReport */
337     offset=dissect_inap_RequestCurrentStatusReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_RequestCurrentStatusReportArg_PDU);
338     break;
339   case 38:/*38, "RequestEveryStatusChangeReport */
340     offset=dissect_inap_RequestEveryStatusChangeReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_RequestEveryStatusChangeReportArg_PDU);
341     break;
342   case 39:/*39, "RequestFirstStatusMatchReport */
343     offset=dissect_inap_RequestFirstStatusMatchReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_RequestFirstStatusMatchReportArg_PDU);
344     break;
345   case 40:/*40, "StatusReport */
346     offset=dissect_inap_StatusReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_StatusReportArg_PDU);
347     break;
348   case 41:/*41, "CallGap */
349     offset=dissect_inap_CallGapArg(FALSE, tvb, offset, pinfo, tree, hf_inap_CallGapArg_PDU);
350     break;
351   case 42:/*42, "ActivateServiceFiltering */
352     offset=dissect_inap_ActivateServiceFilteringArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ActivateServiceFilteringArg_PDU);
353     break;
354   case 43:/*43, "ServiceFilteringResponse */
355     offset=dissect_inap_ServiceFilteringResponseArg(FALSE, tvb, offset, pinfo, tree, hf_inap_ServiceFilteringResponseArg_PDU);
356     break;    
357   case  44: /*CallInformationReport*/
358     offset=dissect_inap_CallInformationReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_CallInformationReportArg_PDU);
359     break;
360   case  45: /*CallInformationRequest*/
361     offset=dissect_inap_CallInformationRequestArg(FALSE, tvb, offset, pinfo, tree, hf_inap_CallInformationRequestArg_PDU);
362     break;
363   case 47: /*PlayAnnouncement*/
364     offset=dissect_inap_PlayAnnouncementArg(FALSE, tvb, offset, pinfo, tree, hf_inap_PlayAnnouncementArg_PDU);
365     break;
366   case 48: /*PromptAndCollectUserInformation*/
367     offset=dissect_inap_PromptAndCollectUserInformationArg(FALSE, tvb, offset, pinfo, tree, hf_inap_PromptAndCollectUserInformationArg_PDU);
368     break;
369   case 49: /* 49 SpecializedResourceReport */
370     offset=dissect_inap_SpecializedResourceReportArg(FALSE, tvb, offset, pinfo, tree, hf_inap_SpecializedResourceReportArg_PDU);
371     break;
372   case  53: /*Cancel*/
373     offset=dissect_inap_CancelArg(FALSE, tvb, offset, pinfo, tree, hf_inap_CancelArg_PDU);
374     break;
375         /*55 ActivityTest*/
376    default:
377     proto_tree_add_text(tree, tvb, offset, -1, "Unknown invokeData blob");
378     /* todo call the asn.1 dissector */
379   }
380   return offset;
381 }
382
383 /*
384 TC-Returnable OPERATION ::=
385   {activateServiceFiltering | activityTest | requestCurrentStatusReport |
386    requestEveryStatusChangeReport | requestFirstStatusMatchReport |
387    promptAndCollectUserInformation}
388
389    activateServiceFiltering                     - No arg
390    activityTest                                         - No Arg
391    requestCurrentStatusReport           - RESULT         RequestCurrentStatusReportResultArg
392    requestEveryStatusChangeReport       - No arg
393    requestFirstStatusMatchReport        - No Arg 
394    promptAndCollectUserInformation      - RESULT         ReceivedInformationArg
395         
396 */
397 static int dissect_returnResultData(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
398   switch(opcode){
399    case 37: /*requestCurrentStatusReport*/
400     offset=dissect_inap_RequestCurrentStatusReportResultArg(FALSE, tvb, offset, pinfo, tree, -1);
401     break;
402    case 48: /*PromptAndCollectUserInformation*/
403     offset=dissect_inap_ReceivedInformationArg(FALSE, tvb, offset, pinfo, tree, -1);
404     break;
405   default:
406     proto_tree_add_text(tree, tvb, offset, -1, "Unknown returnResultData blob");
407   }
408   return offset;
409 }
410
411 static int 
412 dissect_invokeCmd(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
413   return dissect_inap_Opcode(FALSE, tvb, offset, pinfo, tree, hf_inap_invokeCmd);
414 }
415
416
417 static int 
418 dissect_errorCode(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
419   return dissect_inap_errorCode(FALSE, tvb, offset, pinfo, tree, hf_inap_ReturnError);
420 }
421
422 static int dissect_invokeid(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
423   return dissect_ber_integer(FALSE, pinfo, tree, tvb, offset, hf_inap_invokeid, NULL);
424 }
425
426
427 static const value_string InvokeId_vals[] = {
428   {   0, "invokeid" },
429   {   1, "absent" },
430   { 0, NULL }
431 };
432
433 static int dissect_absent(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
434   return dissect_inap_NULL(FALSE, tvb, offset, pinfo, tree, hf_inap_absent);
435 }
436
437
438 static const ber_choice_t InvokeId_choice[] = {
439   {   0, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_invokeid },
440   {   1, BER_CLASS_UNI, BER_UNI_TAG_NULL, BER_FLAGS_NOOWNTAG, dissect_absent },
441   { 0, 0, 0, 0, NULL }
442 };
443
444 static int
445 dissect_inap_InvokeId(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
446   offset = dissect_ber_choice(pinfo, tree, tvb, offset,
447                               InvokeId_choice, hf_index, ett_inap_InvokeId, NULL);
448
449   return offset;
450 }
451 static int dissect_invokeId(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
452   return dissect_inap_InvokeId(FALSE, tvb, offset, pinfo, tree, hf_inap_invokeId);
453 }
454 static int dissect_linkedID_impl(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
455         return dissect_ber_integer(TRUE, pinfo, tree, tvb, offset, hf_inap_linkedid, NULL);
456 }
457
458
459 static const ber_sequence_t InvokePDU_sequence[] = {
460   { BER_CLASS_UNI, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_invokeId },
461   { BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_linkedID_impl },
462   { BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_invokeCmd },
463   { BER_CLASS_UNI, -1/*depends on Cmd*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_invokeData },
464   { 0, 0, 0, NULL }
465 };
466
467 static int
468 dissect_inap_InvokePDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
469   offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
470                                 InvokePDU_sequence, hf_index, ett_inap_InvokePDU);
471
472   return offset;
473 }
474
475
476 static const ber_sequence_t returnErrorPDU_sequence[] = {
477   { BER_CLASS_UNI, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_invokeId },
478   { BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_errorCode },
479   { 0, 0, 0, NULL }
480 };
481
482 static int
483 dissect_inap_returnErrorPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
484   offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
485                                 returnErrorPDU_sequence, hf_index, ett_inap_ReturnErrorPDU);
486
487   return offset;
488 }
489
490
491 static int dissect_invoke_impl(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
492   return dissect_inap_InvokePDU(TRUE, tvb, offset, pinfo, tree, hf_inap_invoke);
493 }
494
495 static int dissect_returnError_impl(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
496   return dissect_inap_returnErrorPDU(TRUE, tvb, offset, pinfo, tree, hf_inap_invoke);
497 }
498
499 static const ber_sequence_t ReturnResult_result_sequence[] = {
500   { BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_invokeCmd },
501   { BER_CLASS_UNI, -1/*depends on Cmd*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_returnResultData },
502   { 0, 0, 0, NULL }
503 };
504 static int
505 dissect_returnResult_result(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
506   offset = dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset,
507                                 ReturnResult_result_sequence, hf_inap_returnResult_result, ett_inap_ReturnResult_result);
508
509   return offset;
510 }
511
512 static const ber_sequence_t ReturnResultPDU_sequence[] = {
513   { BER_CLASS_UNI, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_invokeId },
514   { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_returnResult_result },
515   { 0, 0, 0, NULL }
516 };
517
518 static int
519 dissect_inap_returnResultPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
520   offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
521                                 ReturnResultPDU_sequence, hf_index, ett_inap_ReturnResultPDU);
522
523   return offset;
524 }
525 static int dissect_returnResult_impl(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
526   return dissect_inap_returnResultPDU(TRUE, tvb, offset, pinfo, tree, hf_inap_returnResult);
527 }
528
529
530 static int dissect_reject_impl(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
531   return dissect_inap_RejectPDU(TRUE, tvb, offset, pinfo, tree, -1);
532 }
533
534 static const value_string INAPPDU_vals[] = {
535   {   1, "invoke" },
536   {   2, "returnResult" },
537   {   3, "returnError" },
538   {   4, "reject" },
539   { 0, NULL }
540 };
541
542 static const ber_choice_t INAPPDU_choice[] = {
543   {   1, BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_invoke_impl },
544   {   2, BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_returnResult_impl },
545   {   3, BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_returnError_impl },
546   {   4, BER_CLASS_CON, 4, BER_FLAGS_IMPLTAG, dissect_reject_impl },
547   { 0, 0, 0, 0, NULL }
548 };
549
550 static guint8 inap_pdu_type = 0;
551 static guint8 inap_pdu_size = 0;
552
553 static int
554 dissect_inap_INAPPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
555
556   inap_pdu_type = tvb_get_guint8(tvb, offset)&0x0f;
557   /* Get the length and add 2 */
558   inap_pdu_size = tvb_get_guint8(tvb, offset+1)+2;
559
560   offset = dissect_ber_choice(pinfo, tree, tvb, offset,
561                               INAPPDU_choice, hf_index, ett_inap_INAPPDU, NULL);
562 /*
563   if (check_col(pinfo->cinfo, COL_INFO)){
564     col_prepend_fstr(pinfo->cinfo, COL_INFO, val_to_str(opcode, inap_opr_code_strings, "Unknown INAP (%u)"));
565   }
566 */
567   return offset;
568 }
569
570
571
572
573 static void
574 dissect_inap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
575 {
576     proto_item          *item=NULL;
577     proto_tree          *tree=NULL;
578
579
580     if (check_col(pinfo->cinfo, COL_PROTOCOL))
581     {
582         col_set_str(pinfo->cinfo, COL_PROTOCOL, "INAP");
583     }
584
585     /* create display subtree for the protocol */
586     if(parent_tree){
587        item = proto_tree_add_item(parent_tree, proto_inap, tvb, 0, -1, FALSE);
588        tree = proto_item_add_subtree(item, ett_inap);
589     }
590
591     dissect_inap_INAPPDU(FALSE, tvb, 0, pinfo, tree, -1);
592
593
594 }
595
596 /*--- proto_reg_handoff_inap ---------------------------------------*/
597 static void range_delete_callback(guint32 ssn)
598 {
599     if (ssn) {
600         delete_itu_tcap_subdissector(ssn, inap_handle);
601     }
602 }
603
604 static void range_add_callback(guint32 ssn)
605 {
606     if (ssn) {
607         add_itu_tcap_subdissector(ssn, inap_handle);
608     }
609 }
610
611 void proto_reg_handoff_inap(void) {
612
613     static int inap_prefs_initialized = FALSE;
614     
615     inap_handle = create_dissector_handle(dissect_inap, proto_inap);
616         
617     if (!inap_prefs_initialized) {
618             inap_prefs_initialized = TRUE;
619     }
620     else {
621             range_foreach(ssn_range, range_delete_callback);
622     }
623
624     g_free(ssn_range);
625     ssn_range = range_copy(global_ssn_range);
626
627     range_foreach(ssn_range, range_add_callback);
628 }
629
630
631 void proto_register_inap(void) {
632         module_t *inap_module;
633   /* List of fields */
634   static hf_register_info hf[] = {
635     { &hf_inap_invokeCmd,
636       { "invokeCmd", "inap.invokeCmd",
637         FT_UINT32, BASE_DEC, VALS(inap_opr_code_strings), 0,
638         "InvokePDU/invokeCmd", HFILL }},
639    { &hf_inap_ReturnError,
640       { "ReturnError", "inap.ReturnError",
641         FT_UINT32, BASE_DEC, VALS(inap_error_code_strings), 0,
642         "InvokePDU/ReturnError", HFILL }},
643      { &hf_inap_invokeid,
644       { "invokeid", "inap.invokeid",
645         FT_INT32, BASE_DEC, NULL, 0,
646         "InvokeId/invokeid", HFILL }},
647         { &hf_inap_linkedid,
648       { "linkedid", "inap.linkedid",
649         FT_INT32, BASE_DEC, NULL, 0,
650         "LinkedId/linkedid", HFILL }},
651
652     { &hf_inap_absent,
653       { "absent", "inap.absent",
654         FT_NONE, BASE_NONE, NULL, 0,
655         "InvokeId/absent", HFILL }},
656     { &hf_inap_invokeId,
657       { "invokeId", "inap.invokeId",
658         FT_UINT32, BASE_DEC, VALS(InvokeId_vals), 0,
659         "InvokePDU/invokeId", HFILL }},
660     { &hf_inap_invoke,
661       { "invoke", "inap.invoke",
662         FT_NONE, BASE_NONE, NULL, 0,
663         "INAPPDU/invoke", HFILL }},
664     { &hf_inap_returnResult,
665       { "returnResult", "inap.returnResult",
666         FT_NONE, BASE_NONE, NULL, 0,
667         "INAPPDU/returnResult", HFILL }},
668      
669
670 #include "packet-inap-hfarr.c"
671   };
672
673
674
675
676
677
678   /* List of subtrees */
679   static gint *ett[] = {
680     &ett_inap,
681     &ett_inap_InvokeId,
682     &ett_inap_InvokePDU,
683     &ett_inap_ReturnErrorPDU,
684     &ett_inap_ReturnResultPDU,
685     &ett_inap_ReturnResult_result,
686     &ett_inap_INAPPDU,
687     &ett_inapisup_parameter,
688 #include "packet-inap-ettarr.c"
689   };
690
691   /* Register protocol */
692   proto_inap = proto_register_protocol(PNAME, PSNAME, PFNAME);
693 /*XXX  register_dissector("inap", dissect_inap, proto_inap);*/
694   /* Register fields and subtrees */
695   proto_register_field_array(proto_inap, hf, array_length(hf));
696   proto_register_subtree_array(ett, array_length(ett));
697   
698   /* Set default SSNs */
699   range_convert_str(&global_ssn_range, "106,241", MAX_SSN);
700   ssn_range = range_empty();
701   
702   inap_module = prefs_register_protocol(proto_inap, proto_reg_handoff_inap);
703
704   prefs_register_obsolete_preference(inap_module, "tcap.itu_ssn");
705  
706   prefs_register_obsolete_preference(inap_module, "tcap.itu_ssn1");
707
708   prefs_register_range_preference(inap_module, "ssn", "TCAP SSNs",
709                                   "TCAP Subsystem numbers used for INAP",
710                                   &global_ssn_range, MAX_SSN);
711 }
712
713
714