bddc97f1a0bb4a0ca26126981c56a6844be3d4d0
[obnox/wireshark/wip.git] / asn1 / pres / packet-pres-template.c
1 /* packet-pres.c
2  * Routine to dissect ISO 8823 OSI Presentation Protocol packets
3  * Based on the dissector by 
4  * Yuriy Sidelnikov <YSidelnikov@hotmail.com>
5  *
6  * $Id$
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include <epan/conversation.h>
34 #include <epan/emem.h>
35
36 #include <stdio.h>
37 #include <string.h>
38
39 #include "packet-ber.h"
40 #include "packet-ses.h"
41 #include "packet-pres.h"
42
43
44 #define PNAME  "ISO 8823 OSI Presentation Protocol"
45 #define PSNAME "PRES"
46 #define PFNAME "pres"
47
48 /* Initialize the protocol and registered fields */
49 int proto_pres = -1;
50 /*   type of session envelop */
51 static struct SESSION_DATA_STRUCTURE* session = NULL;
52
53 /*      pointers for acse dissector  */
54 proto_tree *global_tree  = NULL;
55 packet_info *global_pinfo = NULL;
56
57 /* dissector for data */
58 static dissector_handle_t data_handle;
59
60 static char abstract_syntax_name_oid[BER_MAX_OID_STR_LEN];
61 static guint32 presentation_context_identifier;
62
63 /* to keep track of presentation context identifiers and protocol-oids */
64 typedef struct _pres_ctx_oid_t {
65         /* XXX here we should keep track of ADDRESS/PORT as well */
66         guint32 ctx_id;
67         char *oid;
68 } pres_ctx_oid_t;
69 static GHashTable *pres_ctx_oid_table = NULL;
70
71 #include "packet-pres-hf.c"
72
73 /* Initialize the subtree pointers */
74 static gint ett_pres           = -1;
75
76 #include "packet-pres-ett.c"
77
78
79 static guint
80 pres_ctx_oid_hash(gconstpointer k)
81 {
82         pres_ctx_oid_t *pco=(pres_ctx_oid_t *)k;
83         return pco->ctx_id;
84 }
85 /* XXX this one should be made ADDRESS/PORT aware */
86 static gint
87 pres_ctx_oid_equal(gconstpointer k1, gconstpointer k2)
88 {
89         pres_ctx_oid_t *pco1=(pres_ctx_oid_t *)k1;
90         pres_ctx_oid_t *pco2=(pres_ctx_oid_t *)k2;
91         return pco1->ctx_id==pco2->ctx_id;
92 }
93
94 static void
95 pres_init(void)
96 {
97         if( pres_ctx_oid_table ){
98                 g_hash_table_destroy(pres_ctx_oid_table);
99                 pres_ctx_oid_table = NULL;
100         }
101         pres_ctx_oid_table = g_hash_table_new(pres_ctx_oid_hash,
102                         pres_ctx_oid_equal);
103
104 }
105
106 static void
107 register_ctx_id_and_oid(packet_info *pinfo _U_, guint32 idx, char *oid)
108 {
109         pres_ctx_oid_t *pco, *tmppco;
110         pco=se_alloc(sizeof(pres_ctx_oid_t));
111         pco->ctx_id=idx;
112         pco->oid=se_strdup(oid);
113
114         /* if this ctx already exists, remove the old one first */
115         tmppco=(pres_ctx_oid_t *)g_hash_table_lookup(pres_ctx_oid_table, pco);
116         if(tmppco){
117                 g_hash_table_remove(pres_ctx_oid_table, tmppco);
118
119         }
120         g_hash_table_insert(pres_ctx_oid_table, pco, pco);
121 }
122 char *
123 find_oid_by_pres_ctx_id(packet_info *pinfo _U_, guint32 idx)
124 {
125         pres_ctx_oid_t pco, *tmppco;
126         pco.ctx_id=idx;
127         tmppco=(pres_ctx_oid_t *)g_hash_table_lookup(pres_ctx_oid_table, &pco);
128         if(tmppco){
129                 return tmppco->oid;
130         }
131         return NULL;
132 }
133
134
135 #include "packet-pres-fn.c"
136
137
138 /*
139  * Dissect an PPDU.
140  */
141 static int
142 dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
143 {
144   proto_item *ti;
145   proto_tree *pres_tree = NULL;
146   guint s_type;
147 /* do we have spdu type from the session dissector?  */
148         if( !pinfo->private_data ){
149                 if(tree){
150                         proto_tree_add_text(tree, tvb, offset, -1,
151                                 "Internal error:can't get spdu type from session dissector.");
152                         return  FALSE;
153                 }
154         }else{
155                 session  = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
156                 if(session->spdu_type == 0 ){
157                         if(tree){
158                                 proto_tree_add_text(tree, tvb, offset, -1,
159                                         "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
160                                 return  FALSE;
161                         }
162                 }
163         }
164 /* get type of tag      */
165         s_type = tvb_get_guint8(tvb, offset);
166                 /*  set up type of Ppdu */
167         if (check_col(pinfo->cinfo, COL_INFO))
168                                         col_add_str(pinfo->cinfo, COL_INFO,
169                                                 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
170   if (tree){
171           ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1,
172                     FALSE);
173           pres_tree = proto_item_add_subtree(ti, ett_pres);
174   }
175
176         switch(session->spdu_type){
177                 case SES_REFUSE:
178                         break;
179                 case SES_CONNECTION_REQUEST:
180                         offset = dissect_pres_CP_type(FALSE, tvb, offset, pinfo, pres_tree, -1);
181                         break;
182                 case SES_CONNECTION_ACCEPT:
183                         offset = dissect_pres_CPA_PPDU(FALSE, tvb, offset, pinfo, pres_tree, -1);
184                         break;
185                 case SES_ABORT:
186                         offset = dissect_pres_Abort_type(FALSE, tvb, offset, pinfo, pres_tree, -1);
187                         break;
188                 case SES_DATA_TRANSFER:
189                         offset = dissect_pres_CPC_type(FALSE, tvb, offset, pinfo, pres_tree, -1);
190                         break;
191                 default:
192                         break;
193         }
194
195         return offset;
196 }
197
198 void
199 dissect_pres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
200 {
201         int offset = 0, old_offset;
202 /* first, try to check length   */
203 /* do we have at least 4 bytes  */
204         if (!tvb_bytes_exist(tvb, 0, 4)){
205                 proto_tree_add_text(parent_tree, tvb, offset, 
206                         tvb_reported_length_remaining(tvb,offset),"User data");
207                 return;  /* no, it isn't a presentation PDU */
208         }
209
210         /*  we can't make any additional checking here   */
211         /*  postpone it before dissector will have more information */
212
213         if (check_col(pinfo->cinfo, COL_PROTOCOL))
214                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
215         if (check_col(pinfo->cinfo, COL_INFO))
216                 col_clear(pinfo->cinfo, COL_INFO);
217         /* save pointers for calling the acse dissector  */
218         global_tree = parent_tree;
219         global_pinfo = pinfo;
220
221         while (tvb_reported_length_remaining(tvb, offset) > 0){
222                 old_offset = offset;
223                 offset = dissect_ppdu(tvb, offset, pinfo, parent_tree);
224                 if(offset <= old_offset){
225                         proto_tree_add_text(parent_tree, tvb, offset, -1,"Invalid offset");
226                         THROW(ReportedBoundsError);
227                 }
228         }
229 }
230
231
232 /*--- proto_register_pres -------------------------------------------*/
233 void proto_register_pres(void) {
234
235   /* List of fields */
236   static hf_register_info hf[] = {
237
238 #include "packet-pres-hfarr.c"
239   };
240
241   /* List of subtrees */
242   static gint *ett[] = {
243                 &ett_pres,
244 #include "packet-pres-ettarr.c"
245   };
246
247   /* Register protocol */
248   proto_pres = proto_register_protocol(PNAME, PSNAME, PFNAME);
249   register_dissector("pres", dissect_pres, proto_pres);
250   /* Register fields and subtrees */
251   proto_register_field_array(proto_pres, hf, array_length(hf));
252   proto_register_subtree_array(ett, array_length(ett));
253   register_init_routine(pres_init);
254
255 }
256
257
258 /*--- proto_reg_handoff_pres ---------------------------------------*/
259 void proto_reg_handoff_pres(void) {
260
261 /*      register_ber_oid_dissector("0.4.0.0.1.1.1.1", dissect_pres, proto_pres, 
262           "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) abstractSyntax(1) pres(1) version1(1)"); */
263
264         data_handle = find_dissector("data");
265
266 }