Add support for SNA-over-X.25. Add QLLC dissector. I still need to
[obnox/wireshark/wip.git] / packet-tns.c
1 /* packet-tns.c
2  * Routines for Oracle TNS packet dissection
3  *
4  * $Id: packet-tns.c,v 1.21 2001/10/08 14:32:06 nneul Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * Copied from packet-tftp.c
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 <stdio.h>
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
39 #endif
40
41 #include <string.h>
42 #include <glib.h>
43 #include "packet.h"
44 #include "packet-tns.h"
45
46 static int proto_tns = -1;
47 static int hf_tns_request = -1;
48 static int hf_tns_response = -1;
49 static int hf_tns_length = -1;
50 static int hf_tns_packet_checksum = -1;
51 static int hf_tns_header_checksum = -1;
52 static int hf_tns_packet_type = -1;
53 static int hf_tns_reserved_byte = -1;
54 static int hf_tns_connect = -1;
55 static int hf_tns_version = -1;
56 static int hf_tns_compat_version = -1;
57 static int hf_tns_service_options = -1;
58 static int hf_tns_sdu_size = -1;
59 static int hf_tns_max_tdu_size = -1;
60 static int hf_tns_nt_proto_characteristics = -1;
61 static int hf_tns_line_turnaround = -1;
62 static int hf_tns_value_of_one = -1;
63 static int hf_tns_connect_data_length = -1;
64 static int hf_tns_connect_data_offset = -1;
65 static int hf_tns_connect_data_max = -1;
66 static int hf_tns_connect_flags0 = -1;
67 static int hf_tns_connect_flags1 = -1;
68 static int hf_tns_connect_data = -1;
69 static int hf_tns_trace_cf1 = -1;
70 static int hf_tns_trace_cf2 = -1;
71 static int hf_tns_trace_cid = -1;
72
73 static int hf_tns_accept = -1;
74 static int hf_tns_accept_data_length = -1;
75 static int hf_tns_accept_data_offset = -1;
76 static int hf_tns_accept_data = -1;
77
78 static int hf_tns_refuse = -1;
79 static int hf_tns_refuse_reason_user = -1;
80 static int hf_tns_refuse_reason_system = -1;
81 static int hf_tns_refuse_data_length = -1;
82 static int hf_tns_refuse_data = -1;
83
84 static int hf_tns_abort = -1;
85 static int hf_tns_abort_reason_user = -1;
86 static int hf_tns_abort_reason_system = -1;
87 static int hf_tns_abort_data = -1;
88
89 static int hf_tns_marker = -1;
90 static int hf_tns_marker_type = -1;
91 static int hf_tns_marker_data_byte = -1;
92 static int hf_tns_marker_data = -1;
93
94 static int hf_tns_redirect = -1;
95 static int hf_tns_redirect_data_length = -1;
96 static int hf_tns_redirect_data = -1;
97
98 static int hf_tns_control = -1;
99 static int hf_tns_control_cmd = -1;
100 static int hf_tns_control_data = -1;
101
102 static int hf_tns_data_flag = -1;
103 static int hf_tns_data_flag_send = -1;
104 static int hf_tns_data_flag_rc = -1;
105 static int hf_tns_data_flag_c = -1;
106 static int hf_tns_data_flag_reserved = -1;
107 static int hf_tns_data_flag_more = -1;
108 static int hf_tns_data_flag_eof = -1;
109 static int hf_tns_data_flag_dic = -1;
110 static int hf_tns_data_flag_rts = -1;
111 static int hf_tns_data_flag_sntt = -1;
112 static int hf_tns_data = -1;
113
114 static gint ett_tns = -1;
115 static gint ett_tns_connect = -1;
116 static gint ett_tns_accept = -1;
117 static gint ett_tns_refuse = -1;
118 static gint ett_tns_abort = -1;
119 static gint ett_tns_redirect = -1;
120 static gint ett_tns_marker = -1;
121 static gint ett_tns_attention = -1;
122 static gint ett_tns_control = -1;
123 static gint ett_tns_data = -1;
124 static gint ett_tns_data_flag = -1;
125 static gint ett_sql = -1;
126
127 #define TCP_PORT_TNS                    1521
128
129 static const value_string tns_type_vals[] = {
130         {TNS_TYPE_CONNECT,   "Connect" },
131         {TNS_TYPE_ACCEPT,    "Accept" },
132         {TNS_TYPE_ACK,       "Acknowledge" },
133         {TNS_TYPE_REFUSE,    "Refuse" },
134         {TNS_TYPE_REDIRECT,  "Redirect" },
135         {TNS_TYPE_DATA,      "Data" },
136         {TNS_TYPE_NULL,      "Null" },
137         {TNS_TYPE_ABORT,     "Abort" },
138         {TNS_TYPE_RESEND,    "Resend"},
139         {TNS_TYPE_MARKER,    "Marker"},
140         {TNS_TYPE_ATTENTION, "Attention"},
141         {TNS_TYPE_CONTROL,   "Control"},
142         {0, NULL}
143 };
144
145 static const value_string tns_marker_types[] = {
146         {0, "Data Marker - 0 Data Bytes"},
147         {1, "Data Marker - 1 Data Bytes"},
148         {2, "Attention Marker"},
149         {0, NULL}
150 };
151
152 static const value_string tns_control_cmds[] = {
153         {1, "Oracle Trace Command"},
154         {0, NULL}
155 };
156
157 static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
158         proto_tree *tree, proto_tree *tns_tree)
159 {
160         proto_tree *data_tree = NULL, *ti;
161         int is_sns = 0;
162         
163         if ( tvb_bytes_exist(tvb, offset+2, 4) )
164         {
165                 if ( tvb_get_guint8(tvb, offset+2) == 0xDE &&
166                      tvb_get_guint8(tvb, offset+3) == 0xAD &&
167                      tvb_get_guint8(tvb, offset+4) == 0xBE &&
168                      tvb_get_guint8(tvb, offset+5) == 0xEF )
169                 {
170                         is_sns = 1;
171                 }
172         }
173
174         if ( tree )
175         {
176                 if ( is_sns )
177                 {
178                         ti = proto_tree_add_text(tns_tree, tvb, offset,
179                             tvb_length_remaining(tvb, offset), "Secure Network Services");
180                 }
181                 else
182                 {
183                         ti = proto_tree_add_text(tns_tree, tvb, offset,
184                             tvb_length_remaining(tvb, offset), "Data");         
185                 }
186                 data_tree = proto_item_add_subtree(ti, ett_tns_data);
187
188                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_data, tvb, 0, 0,
189                                 TRUE);
190         }
191
192         if ( tree )
193         {
194                 proto_tree *df_tree = NULL;
195                 
196                 ti = proto_tree_add_uint(data_tree, hf_tns_data_flag, tvb, offset, 2, FALSE);
197                 
198                 df_tree = proto_item_add_subtree(ti, ett_tns_data_flag);
199                 proto_tree_add_uint(df_tree, hf_tns_data_flag_send, tvb, offset, 2, FALSE);
200                 proto_tree_add_uint(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, FALSE);
201                 proto_tree_add_uint(df_tree, hf_tns_data_flag_c, tvb, offset, 2, FALSE);
202                 proto_tree_add_uint(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, FALSE);
203                 proto_tree_add_uint(df_tree, hf_tns_data_flag_more, tvb, offset, 2, FALSE);
204                 proto_tree_add_uint(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, FALSE);
205                 proto_tree_add_uint(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, FALSE);
206                 proto_tree_add_uint(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, FALSE);
207                 proto_tree_add_uint(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, FALSE);
208         }
209         offset += 2;
210
211         if ( check_col(pinfo->fd, COL_INFO) )
212         {
213                 if ( is_sns )
214                 {
215                         col_append_fstr(pinfo->fd, COL_INFO, ", SNS");
216                 }
217                 else
218                 {
219                         col_append_fstr(pinfo->fd, COL_INFO, ", Data");
220                 }       
221         }
222         
223         if ( data_tree )
224         {
225                 dissect_data(tvb,offset,pinfo,data_tree);
226         }
227
228         return;
229 }
230
231 static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo,
232         proto_tree *tree, proto_tree *tns_tree)
233 {
234         proto_tree *connect_tree = NULL, *ti;
235         int cd_offset;
236         int cd_len;
237         int tns_offset = offset-8;
238
239         if ( tree )
240         {
241                 ti = proto_tree_add_text(tns_tree, tvb, offset,
242                     tvb_length_remaining(tvb, offset), "Connect");
243                 connect_tree = proto_item_add_subtree(ti, ett_tns_connect);
244
245                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_connect, tvb,
246                     0, 0, TRUE);
247         }
248                 
249         if ( check_col(pinfo->fd, COL_INFO) )
250         {
251                 col_append_str(pinfo->fd, COL_INFO, ", Connect");
252         }
253
254         if ( connect_tree )
255         {
256                 proto_tree_add_item(connect_tree, hf_tns_version, tvb,
257                         offset, 2, FALSE);
258         }
259         offset += 2;
260         
261         if ( connect_tree )
262         {
263                 proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
264                         offset, 2, FALSE);
265         }
266         offset += 2;
267
268         if ( connect_tree )
269         {
270                 /* need to break down w/ bitfield */
271                 proto_tree_add_uint(connect_tree, hf_tns_service_options, tvb,
272                         offset, 2, tvb_get_ntohs(tvb, offset));
273         }
274         offset += 2;
275
276         if ( connect_tree )
277         {
278                 proto_tree_add_uint(connect_tree, hf_tns_sdu_size, tvb,
279                         offset, 2, tvb_get_ntohs(tvb, offset));
280         }
281         offset += 2;
282
283         if ( connect_tree )
284         {
285                 proto_tree_add_uint(connect_tree, hf_tns_max_tdu_size, tvb,
286                         offset, 2, tvb_get_ntohs(tvb, offset));
287         }
288         offset += 2;
289
290         if ( connect_tree )
291         {
292                 proto_tree_add_uint(connect_tree, hf_tns_nt_proto_characteristics, tvb,
293                         offset, 2, tvb_get_ntohs(tvb, offset));
294         }
295         offset += 2;
296
297         if ( connect_tree )
298         {
299                 proto_tree_add_uint(connect_tree, hf_tns_line_turnaround, tvb,
300                         offset, 2, tvb_get_ntohs(tvb, offset));
301         }
302         offset += 2;
303
304         if ( connect_tree )
305         {
306                 proto_tree_add_bytes(connect_tree, hf_tns_value_of_one, tvb,
307                         offset, 2, tvb_get_ptr(tvb, offset, 2));
308         }
309         offset += 2;
310
311         cd_len = tvb_get_ntohs(tvb, offset);
312         if ( connect_tree )
313         {
314                 proto_tree_add_uint(connect_tree, hf_tns_connect_data_length, tvb,
315                         offset, 2, cd_len);
316         }
317         offset += 2;
318
319         cd_offset = tvb_get_ntohs(tvb, offset);
320         if ( connect_tree )
321         {
322                 proto_tree_add_uint(connect_tree, hf_tns_connect_data_offset, tvb,
323                         offset, 2, cd_offset);
324         }
325         offset += 2;
326
327         if ( connect_tree )
328         {
329                 proto_tree_add_uint(connect_tree, hf_tns_connect_data_max, tvb,
330                         offset, 4, tvb_get_ntohl(tvb, offset));
331         }
332         offset += 4;
333
334         if ( connect_tree )
335         {
336                 proto_tree_add_uint(connect_tree, hf_tns_connect_flags0, tvb,
337                         offset, 1, tvb_get_guint8(tvb, offset));
338         }
339         offset += 1;
340
341         if ( connect_tree )
342         {
343                 proto_tree_add_uint(connect_tree, hf_tns_connect_flags1, tvb,
344                         offset, 1, tvb_get_guint8(tvb, offset));
345         }
346         offset += 1;
347
348         if ( connect_tree )
349         {
350                 proto_tree_add_uint(connect_tree, hf_tns_trace_cf1, tvb,
351                         offset, 2, tvb_get_ntohs(tvb, offset));
352         }
353         offset += 2;
354
355         if ( connect_tree )
356         {
357                 proto_tree_add_uint(connect_tree, hf_tns_trace_cf2, tvb,
358                         offset, 2, tvb_get_ntohs(tvb, offset));
359         }
360         offset += 2;
361
362         if ( connect_tree )
363         {
364                 proto_tree_add_uint(connect_tree, hf_tns_trace_cid, tvb,
365                         offset, 2, tvb_get_ntohs(tvb, offset));
366         }
367         offset += 2;
368
369         if ( connect_tree && cd_len > 0)
370         {
371                 proto_tree_add_string(connect_tree, hf_tns_connect_data, tvb,
372                         tns_offset+cd_offset, tvb_length(tvb)-(tns_offset+cd_offset), 
373                         tvb_get_ptr(tvb, tns_offset+cd_offset,
374                         tvb_length(tvb)-(tns_offset+cd_offset)));
375         }
376         return;
377 }
378
379 static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo,
380         proto_tree *tree, proto_tree *tns_tree)
381 {
382         proto_tree *accept_tree = NULL, *ti;
383         int accept_offset;
384         int accept_len;
385         int tns_offset = offset-8;
386
387         if ( tree )
388         {
389                 ti = proto_tree_add_text(tns_tree, tvb, offset,
390                     tvb_length_remaining(tvb, offset), "Accept");
391                 accept_tree = proto_item_add_subtree(ti, ett_tns_accept);
392
393                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_accept, tvb,
394                     0, 0, TRUE);
395         }
396                 
397         if ( check_col(pinfo->fd, COL_INFO) )
398         {
399                 col_append_str(pinfo->fd, COL_INFO, ", Accept");
400         }
401
402         if ( accept_tree )
403         {
404                 proto_tree_add_item(accept_tree, hf_tns_version, tvb,
405                         offset, 2, FALSE);
406         }
407         offset += 2;
408         
409         if ( accept_tree )
410         {
411                 proto_tree_add_uint(accept_tree, hf_tns_service_options, tvb,
412                         offset, 2, tvb_get_ntohs(tvb, offset));
413         }
414         offset += 2;
415
416         if ( accept_tree )
417         {
418                 proto_tree_add_uint(accept_tree, hf_tns_sdu_size, tvb,
419                         offset, 2, tvb_get_ntohs(tvb, offset));
420         }
421         offset += 2;
422
423         if ( accept_tree )
424         {
425                 proto_tree_add_uint(accept_tree, hf_tns_max_tdu_size, tvb,
426                         offset, 2, tvb_get_ntohs(tvb, offset));
427         }
428         offset += 2;
429
430         if ( accept_tree )
431         {
432                 proto_tree_add_bytes(accept_tree, hf_tns_value_of_one, tvb,
433                         offset, 2, tvb_get_ptr(tvb, offset, 2));
434         }
435         offset += 2;
436
437         accept_len = tvb_get_ntohs(tvb, offset);
438         if ( accept_tree )
439         {
440                 proto_tree_add_uint(accept_tree, hf_tns_accept_data_length, tvb,
441                         offset, 2, accept_len);
442         }
443         offset += 2;
444
445         accept_offset = tvb_get_ntohs(tvb, offset);
446         if ( accept_tree )
447         {
448                 proto_tree_add_uint(accept_tree, hf_tns_accept_data_offset, tvb,
449                         offset, 2, accept_offset);
450         }
451         offset += 2;
452
453         if ( accept_tree )
454         {
455                 proto_tree_add_uint(accept_tree, hf_tns_connect_flags0, tvb,
456                         offset, 1, tvb_get_guint8(tvb, offset));
457         }
458         offset += 1;
459
460         if ( accept_tree )
461         {
462                 proto_tree_add_uint(accept_tree, hf_tns_connect_flags1, tvb,
463                         offset, 1, tvb_get_guint8(tvb, offset));
464         }
465         offset += 1;
466
467         if ( accept_tree && accept_len > 0)
468         {
469                 proto_tree_add_string(accept_tree, hf_tns_accept_data, tvb,
470                         tns_offset+accept_offset, tvb_length(tvb)-(tns_offset+accept_offset), 
471                         tvb_get_ptr(tvb, tns_offset+accept_offset,
472                         tvb_length(tvb)-(tns_offset+accept_offset)));
473         }
474         return;
475 }
476
477
478 static void dissect_tns_refuse(tvbuff_t *tvb, int offset, packet_info *pinfo,
479         proto_tree *tree, proto_tree *tns_tree)
480 {
481         proto_tree *refuse_tree = NULL, *ti;
482
483         if ( tree )
484         {
485                 ti = proto_tree_add_text(tns_tree, tvb, offset,
486                     tvb_length_remaining(tvb, offset), "Refuse");
487                 refuse_tree = proto_item_add_subtree(ti, ett_tns_refuse);
488
489                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_refuse, tvb,
490                     0, 0, TRUE);
491         }
492                 
493         if ( check_col(pinfo->fd, COL_INFO) )
494         {
495                 col_append_str(pinfo->fd, COL_INFO, ", Refuse");
496         }
497
498         if ( refuse_tree )
499         {
500                 proto_tree_add_uint(refuse_tree, hf_tns_refuse_reason_user, tvb,
501                         offset, 1, tvb_get_guint8(tvb, offset));
502         }
503         offset += 1;
504
505         if ( refuse_tree )
506         {
507                 proto_tree_add_uint(refuse_tree, hf_tns_refuse_reason_system, tvb,
508                         offset, 1, tvb_get_guint8(tvb, offset));
509         }
510         offset += 1;
511
512         if ( refuse_tree )
513         {
514                 proto_tree_add_uint(refuse_tree, hf_tns_refuse_data_length, tvb,
515                         offset, 2, tvb_get_ntohs(tvb, offset));
516         }
517         offset += 2;
518
519         if ( refuse_tree )
520         {
521                 proto_tree_add_string(refuse_tree, hf_tns_refuse_data, tvb,
522                         offset, tvb_length(tvb)-offset, 
523                         tvb_get_ptr(tvb, offset, tvb_length(tvb)-offset));
524         }
525         return;
526 }
527
528
529 static void dissect_tns_abort(tvbuff_t *tvb, int offset, packet_info *pinfo,
530         proto_tree *tree, proto_tree *tns_tree)
531 {
532         proto_tree *abort_tree = NULL, *ti;
533
534         if ( tree )
535         {
536                 ti = proto_tree_add_text(tns_tree, tvb, offset,
537                     tvb_length_remaining(tvb, offset), "Abort");
538                 abort_tree = proto_item_add_subtree(ti, ett_tns_abort);
539
540                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_abort, tvb,
541                     0, 0, TRUE);
542         }
543                 
544         if ( check_col(pinfo->fd, COL_INFO) )
545         {
546                 col_append_str(pinfo->fd, COL_INFO, ", Abort");
547         }
548
549         if ( abort_tree )
550         {
551                 proto_tree_add_uint(abort_tree, hf_tns_abort_reason_user, tvb,
552                         offset, 1, tvb_get_guint8(tvb, offset));
553         }
554         offset += 1;
555
556         if ( abort_tree )
557         {
558                 proto_tree_add_uint(abort_tree, hf_tns_abort_reason_system, tvb,
559                         offset, 1, tvb_get_guint8(tvb, offset));
560         }
561         offset += 1;
562
563         if ( abort_tree )
564         {
565                 proto_tree_add_string(abort_tree, hf_tns_abort_data, tvb,
566                         offset, tvb_length_remaining(tvb,offset), 
567                         tvb_get_ptr(tvb, offset, tvb_length_remaining(tvb,offset)));
568         }
569         return;
570 }
571
572
573 static void dissect_tns_marker(tvbuff_t *tvb, int offset, packet_info *pinfo,
574         proto_tree *tree, proto_tree *tns_tree, int is_attention)
575 {
576         proto_tree *marker_tree = NULL, *ti;
577
578         if ( tree )
579         {
580                 if ( is_attention )
581                 {
582                         ti = proto_tree_add_text(tns_tree, tvb, offset,
583                             tvb_length_remaining(tvb, offset), "Marker");
584                 }
585                 else
586                 {
587                         ti = proto_tree_add_text(tns_tree, tvb, offset,
588                             tvb_length_remaining(tvb, offset), "Attention");
589                 }
590
591                 marker_tree = proto_item_add_subtree(ti, ett_tns_marker);
592                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_marker, tvb,
593                     0, 0, TRUE);
594         }
595                 
596         if ( check_col(pinfo->fd, COL_INFO) )
597         {
598                 if ( is_attention )
599                 {
600                         col_append_str(pinfo->fd, COL_INFO, ", Marker");
601                 }
602                 else
603                 {
604                         col_append_str(pinfo->fd, COL_INFO, ", Attention");
605                 }
606         }
607
608         if ( marker_tree )
609         {
610                 proto_tree_add_uint(marker_tree, hf_tns_marker_type, tvb,
611                         offset, 1, tvb_get_guint8(tvb, offset));
612         }
613         offset += 1;
614
615         if ( marker_tree )
616         {
617                 proto_tree_add_uint(marker_tree, hf_tns_marker_data_byte, tvb,
618                         offset, 1, tvb_get_guint8(tvb, offset));
619         }
620         offset += 1;
621
622         if ( marker_tree )
623         {
624                 proto_tree_add_uint(marker_tree, hf_tns_marker_data_byte, tvb,
625                         offset, 1, tvb_get_ntohs(tvb, offset));
626         }
627         offset += 1;
628
629         return;
630 }
631
632 static void dissect_tns_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
633         proto_tree *tree, proto_tree *tns_tree)
634 {
635         proto_tree *redirect_tree = NULL, *ti;
636
637         if ( tree )
638         {
639                 ti = proto_tree_add_text(tns_tree, tvb, offset,
640                     tvb_length_remaining(tvb, offset), "Redirect");
641                 redirect_tree = proto_item_add_subtree(ti, ett_tns_redirect);
642
643                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_redirect, tvb,
644                     0, 0, TRUE);
645         }
646                 
647         if ( check_col(pinfo->fd, COL_INFO) )
648         {
649                 col_append_str(pinfo->fd, COL_INFO, ", Redirect");
650         }
651
652         if ( redirect_tree )
653         {
654                 proto_tree_add_uint(redirect_tree, hf_tns_redirect_data_length, tvb,
655                         offset, 2, tvb_get_ntohs(tvb, offset));
656         }
657         offset += 2;
658
659         if ( redirect_tree )
660         {
661                 proto_tree_add_string(redirect_tree, hf_tns_redirect_data, tvb,
662                         offset, tvb_length(tvb)-offset, 
663                         tvb_get_ptr(tvb, offset, tvb_length(tvb)-offset));
664         }
665         return;
666 }
667
668 static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
669         proto_tree *tree, proto_tree *tns_tree)
670 {
671         proto_tree *control_tree = NULL, *ti;
672
673         if ( tree )
674         {
675                 ti = proto_tree_add_text(tns_tree, tvb, offset,
676                     tvb_length_remaining(tvb, offset), "Control");
677                 control_tree = proto_item_add_subtree(ti, ett_tns_control);
678
679                 proto_tree_add_boolean_hidden(tns_tree, hf_tns_control, tvb,
680                     0, 0, TRUE);
681         }
682                 
683         if ( check_col(pinfo->fd, COL_INFO) )
684         {
685                 col_append_str(pinfo->fd, COL_INFO, ", Control");
686         }
687
688         if ( control_tree )
689         {
690                 proto_tree_add_uint(control_tree, hf_tns_control_cmd, tvb,
691                         offset, 2, tvb_get_ntohs(tvb, offset));
692         }
693         offset += 2;
694
695         if ( control_tree )
696         {
697                 proto_tree_add_string(control_tree, hf_tns_control_data, tvb,
698                         offset, tvb_length(tvb)-offset, 
699                         tvb_get_ptr(tvb, offset, tvb_length(tvb)-offset));
700         }
701         return;
702 }
703
704
705
706 static void
707 dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
708 {
709         proto_tree      *tns_tree = NULL, *ti;
710         int offset = 0;
711         guint16 length;
712         guint16 type;
713
714         if (check_col(pinfo->fd, COL_PROTOCOL))
715                 col_set_str(pinfo->fd, COL_PROTOCOL, "TNS");
716
717         if (check_col(pinfo->fd, COL_INFO))
718         {
719                 col_add_str(pinfo->fd, COL_INFO,
720                         (pinfo->match_port == pinfo->destport) ? "Request" : "Response");         
721         }
722
723         if (tree) 
724         {
725                 ti = proto_tree_add_item(tree, proto_tns, tvb, 0,
726                     tvb_length(tvb), FALSE);
727                 tns_tree = proto_item_add_subtree(ti, ett_tns);
728
729                 if (pinfo->match_port == pinfo->destport)
730                 {
731                         proto_tree_add_boolean_hidden(tns_tree, hf_tns_request,
732                            tvb, offset, tvb_length(tvb), TRUE);
733                 }
734                 else
735                 {
736                         proto_tree_add_boolean_hidden(tns_tree, hf_tns_response,
737                             tvb, offset, tvb_length(tvb), TRUE);
738                 }
739         }
740
741         length = tvb_get_ntohs(tvb, offset);
742         if (tree)
743         {
744                 proto_tree_add_uint(tns_tree, hf_tns_length, tvb,
745                         offset, 2, length);
746         }
747         offset += 2;
748
749         if ( tree )
750         {
751                 proto_tree_add_item(tns_tree, hf_tns_packet_checksum, tvb,
752                         offset, 2, FALSE);
753         }
754         offset += 2;
755
756         type = tvb_get_guint8(tvb, offset);
757         if ( tree )
758         {
759                 proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
760                         offset, 1, type);
761         }
762         offset += 1;
763
764         if ( check_col(pinfo->fd, COL_INFO))
765         {
766                 col_append_fstr(pinfo->fd, COL_INFO, ", %s (%u)",
767                         val_to_str(type, tns_type_vals, "Unknown"), type);
768         }
769
770         if ( tree )
771         {
772                 proto_tree_add_item(tns_tree, hf_tns_reserved_byte, tvb,
773                         offset, 1, FALSE);
774         }
775         offset += 1;
776
777         if ( tree )
778         {
779                 proto_tree_add_item(tns_tree, hf_tns_header_checksum, tvb,
780                         offset, 2, FALSE);
781         }
782         offset += 2;
783
784         switch (type)
785         {
786                 case TNS_TYPE_CONNECT:
787                         dissect_tns_connect(tvb,offset,pinfo,tree,tns_tree);
788                         break;
789                 case TNS_TYPE_ACCEPT:
790                         dissect_tns_accept(tvb,offset,pinfo,tree,tns_tree);
791                         break;
792                 case TNS_TYPE_REFUSE:
793                         dissect_tns_refuse(tvb,offset,pinfo,tree,tns_tree);
794                         break;
795                 case TNS_TYPE_REDIRECT:
796                         dissect_tns_redirect(tvb,offset,pinfo,tree,tns_tree);
797                         break;
798                 case TNS_TYPE_ABORT:
799                         dissect_tns_abort(tvb,offset,pinfo,tree,tns_tree);
800                         break;
801                 case TNS_TYPE_MARKER:
802                         dissect_tns_marker(tvb,offset,pinfo,tree,tns_tree, 0);
803                         break;
804                 case TNS_TYPE_ATTENTION:
805                         dissect_tns_marker(tvb,offset,pinfo,tree,tns_tree, 1);
806                         break;
807                 case TNS_TYPE_CONTROL:
808                         dissect_tns_control(tvb,offset,pinfo,tree,tns_tree);
809                         break;
810                 case TNS_TYPE_DATA:
811                         dissect_tns_data(tvb,offset,pinfo,tree,tns_tree);
812                         break;
813                 default:
814                         dissect_data(tvb,offset,pinfo,tns_tree);
815         }
816 }
817
818 void proto_register_tns(void)
819 {
820         static hf_register_info hf[] = {
821                 { &hf_tns_response, { 
822                         "Response", "tns.response", FT_BOOLEAN, BASE_NONE, 
823                         NULL, 0x0, "TRUE if TNS response", HFILL }},
824                 { &hf_tns_request, { 
825                         "Request", "tns.request", FT_BOOLEAN, BASE_NONE, 
826                         NULL, 0x0, "TRUE if TNS request", HFILL }},
827                 { &hf_tns_length, {     
828                         "Packet Length", "tns.length", FT_UINT32, BASE_DEC, 
829                         NULL, 0x0, "Length of TNS packet", HFILL }},
830                 { &hf_tns_packet_checksum, {    
831                         "Packet Checksum", "tns.packet_checksum", FT_UINT16, BASE_HEX, 
832                         NULL, 0x0, "Checksum of Packet Data", HFILL }},
833                 { &hf_tns_header_checksum, {    
834                         "Header Checksum", "tns.header_checksum", FT_UINT16, BASE_HEX, 
835                         NULL, 0x0, "Checksum of Header Data", HFILL }},
836                         
837                 { &hf_tns_version, {    
838                         "Version", "tns.version", FT_UINT16, BASE_DEC, 
839                         NULL, 0x0, "Version", HFILL }},
840                 { &hf_tns_compat_version, {     
841                         "Version (Compatible)", "tns.compat_version", FT_UINT16, BASE_DEC, 
842                         NULL, 0x0, "Version (Compatible)", HFILL }},
843                 { &hf_tns_service_options, {    
844                         "Service Options", "tns.service_options", FT_UINT16, BASE_HEX, 
845                         NULL, 0x0, "Service Options", HFILL }},
846                 { &hf_tns_sdu_size, {   
847                         "Session Data Unit Size", "tns.sdu_size", FT_UINT16, BASE_DEC, 
848                         NULL, 0x0, "Session Data Unit Size", HFILL }},
849                 { &hf_tns_max_tdu_size, {       
850                         "Maximum Transmission Data Unit Size", "tns.max_tdu_size", FT_UINT16, BASE_DEC, 
851                         NULL, 0x0, "Maximum Transmission Data Unit Size", HFILL }},
852                 { &hf_tns_nt_proto_characteristics, {   
853                         "NT Protocol Characteristics", "tns.nt_proto_characteristics", FT_UINT16, BASE_HEX, 
854                         NULL, 0x0, "NT Protocol Characteristics", HFILL }},
855                 { &hf_tns_line_turnaround, {    
856                         "Line Turnaround Value", "tns.line_turnaround", FT_UINT16, BASE_DEC, 
857                         NULL, 0x0, "Line Turnaround Value", HFILL }},
858                 { &hf_tns_value_of_one, {       
859                         "Value of 1 in Hardware", "tns.value_of_one", FT_BYTES, BASE_NONE, 
860                         NULL, 0x0, "Value of 1 in Hardware", HFILL }},          
861
862                 { &hf_tns_connect, { 
863                         "Connect", "tns.connect", FT_BOOLEAN, BASE_NONE, 
864                         NULL, 0x0, "Connect", HFILL }},
865                 { &hf_tns_connect_data_length, {        
866                         "Length of Connect Data", "tns.connect_data_length", FT_UINT16, BASE_DEC, 
867                         NULL, 0x0, "Length of Connect Data", HFILL }},
868                 { &hf_tns_connect_data_offset, {        
869                         "Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC, 
870                         NULL, 0x0, "Offset to Connect Data", HFILL }},
871                 { &hf_tns_connect_data_max, {   
872                         "Maximum Receivable Connect Data", "tns.connect_data_max", FT_UINT32, BASE_DEC, 
873                         NULL, 0x0, "Maximum Receivable Connect Data", HFILL }},
874                 { &hf_tns_connect_flags0, {     
875                         "Connect Flags 0", "tns.connect_flags0", FT_UINT8, BASE_HEX, 
876                         NULL, 0x0, "Connect Flags 0", HFILL }},
877                 { &hf_tns_connect_flags1, {     
878                         "Connect Flags 1", "tns.connect_flags1", FT_UINT8, BASE_HEX, 
879                         NULL, 0x0, "Connect Flags 1", HFILL }},
880                 { &hf_tns_trace_cf1, {  
881                         "Trace Cross Facility Item 1", "tns.trace_cf1", FT_UINT16, BASE_HEX, 
882                         NULL, 0x0, "Trace Cross Facility Item 1", HFILL }},
883                 { &hf_tns_trace_cf2, {  
884                         "Trace Cross Facility Item 2", "tns.trace_cf2", FT_UINT16, BASE_HEX, 
885                         NULL, 0x0, "Trace Cross Facility Item 2", HFILL }},
886                 { &hf_tns_trace_cid, {  
887                         "Trace Unique Connection ID", "tns.trace_cid", FT_UINT16, BASE_HEX, 
888                         NULL, 0x0, "Trace Unique Connection ID", HFILL }},
889                 { &hf_tns_connect_data, {       
890                         "Connect Data", "tns.connect_data", FT_STRING, BASE_NONE, 
891                         NULL, 0x0, "Connect Data", HFILL }},
892
893                 { &hf_tns_accept, { 
894                         "Accept", "tns.accept", FT_BOOLEAN, BASE_NONE, 
895                         NULL, 0x0, "Accept", HFILL }},          
896                 { &hf_tns_accept_data_length, {         
897                         "Accept Data Length", "tns.accept_data_length", FT_UINT16, BASE_HEX, 
898                         NULL, 0x0, "Length of Accept Data", HFILL }},
899                 { &hf_tns_accept_data, {        
900                         "Accept Data", "tns.accept_data", FT_STRING, BASE_NONE, 
901                         NULL, 0x0, "Accept Data", HFILL }},
902                 { &hf_tns_accept_data_offset, {         
903                         "Offset to Accept Data", "tns.accept_data_offset", FT_UINT16, BASE_DEC, 
904                         NULL, 0x0, "Offset to Accept Data", HFILL }},
905
906
907                 { &hf_tns_refuse, { 
908                         "Refuse", "tns.refuse", FT_BOOLEAN, BASE_NONE, 
909                         NULL, 0x0, "Refuse", HFILL }},          
910                 { &hf_tns_refuse_reason_user, {         
911                         "Refuse Reason (User)", "tns.refuse_reason_user", FT_UINT8, BASE_HEX, 
912                         NULL, 0x0, "Refuse Reason from Application", HFILL }},
913                 { &hf_tns_refuse_reason_system, {       
914                         "Refuse Reason (User)", "tns.refuse_reason_system", FT_UINT8, BASE_HEX, 
915                         NULL, 0x0, "Refuse Reason from System", HFILL }},
916                 { &hf_tns_refuse_data_length, {         
917                         "Refuse Data Length", "tns.refuse_data_length", FT_UINT16, BASE_HEX, 
918                         NULL, 0x0, "Length of Refuse Data", HFILL }},
919                 { &hf_tns_refuse_data, {        
920                         "Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE, 
921                         NULL, 0x0, "Refuse Data", HFILL }},
922
923                 { &hf_tns_abort, { 
924                         "Abort", "tns.abort", FT_BOOLEAN, BASE_NONE, 
925                         NULL, 0x0, "Abort", HFILL }},           
926                 { &hf_tns_abort_reason_user, {  
927                         "Abort Reason (User)", "tns.abort_reason_user", FT_UINT8, BASE_HEX, 
928                         NULL, 0x0, "Abort Reason from Application", HFILL }},
929                 { &hf_tns_abort_reason_system, {        
930                         "Abort Reason (User)", "tns.abort_reason_system", FT_UINT8, BASE_HEX, 
931                         NULL, 0x0, "Abort Reason from System", HFILL }},
932                 { &hf_tns_abort_data, {         
933                         "Abort Data", "tns.abort_data", FT_STRING, BASE_NONE, 
934                         NULL, 0x0, "Abort Data", HFILL }},
935
936                 { &hf_tns_marker, { 
937                         "Marker", "tns.marker", FT_BOOLEAN, BASE_NONE, 
938                         NULL, 0x0, "Marker", HFILL }},                          
939                 { &hf_tns_marker_type, {        
940                         "Marker Type", "tns.marker.type", FT_UINT8, BASE_HEX, 
941                         VALS(tns_marker_types), 0x0, "Marker Type", HFILL }},
942                 { &hf_tns_marker_data_byte, {   
943                         "Marker Data Byte", "tns.marker.databyte", FT_UINT8, BASE_HEX, 
944                         NULL, 0x0, "Marker Data Byte", HFILL }},
945                 { &hf_tns_marker_data, {        
946                         "Marker Data", "tns.marker.data", FT_UINT16, BASE_HEX, 
947                         NULL, 0x0, "Marker Data", HFILL }},
948
949                 { &hf_tns_control, { 
950                         "Control", "tns.control", FT_BOOLEAN, BASE_NONE, 
951                         NULL, 0x0, "Control", HFILL }},         
952                 { &hf_tns_control_cmd, {        
953                         "Control Command", "tns.control.cmd", FT_UINT16, BASE_HEX, 
954                         VALS(tns_control_cmds), 0x0, "Control Command", HFILL }},
955                 { &hf_tns_control_data, {       
956                         "Control Data", "tns.control.data", FT_BYTES, BASE_HEX, 
957                         NULL, 0x0, "Control Data", HFILL }},
958
959                 { &hf_tns_redirect, { 
960                         "Redirect", "tns.redirect", FT_BOOLEAN, BASE_NONE, 
961                         NULL, 0x0, "Redirect", HFILL }},                
962                 { &hf_tns_redirect_data_length, {       
963                         "Redirect Data Length", "tns.redirect_data_length", FT_UINT16, BASE_HEX, 
964                         NULL, 0x0, "Length of Redirect Data", HFILL }},
965                 { &hf_tns_redirect_data, {      
966                         "Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE, 
967                         NULL, 0x0, "Redirect Data", HFILL }},
968
969                 { &hf_tns_data, { 
970                         "Data", "tns.data", FT_BOOLEAN, BASE_NONE, 
971                         NULL, 0x0, "Data", HFILL }},            
972                 { &hf_tns_data_flag, {  
973                         "Data Flag", "tns.data_flag", FT_UINT16, BASE_HEX, 
974                         NULL, 0x0, "Data Flag", HFILL }},
975                 { &hf_tns_data_flag_send, {     
976                         "Send Token", "tns.data_flag.send", FT_UINT16, BASE_BIN, 
977                         NULL, 0x1, "Send Token", HFILL }},
978                 { &hf_tns_data_flag_rc, {       
979                         "Request Confirmation", "tns.data_flag.rc", FT_UINT16, BASE_BIN, 
980                         NULL, 0x2, "Request Confirmation", HFILL }},
981                 { &hf_tns_data_flag_c, {        
982                         "Confirmation", "tns.data_flag.c", FT_UINT16, BASE_BIN, 
983                         NULL, 0x4, "Confirmation", HFILL }},
984                 { &hf_tns_data_flag_reserved, {         
985                         "Reserved", "tns.data_flag.reserved", FT_UINT16, BASE_BIN, 
986                         NULL, 0x8, "Reserved", HFILL }},
987                 { &hf_tns_data_flag_more, {     
988                         "More Data to Come", "tns.data_flag.more", FT_UINT16, BASE_BIN, 
989                         NULL, 0x20, "More Data to Come", HFILL }},
990                 { &hf_tns_data_flag_eof, {      
991                         "End of File", "tns.data_flag.eof", FT_UINT16, BASE_BIN, 
992                         NULL, 0x40, "End of File", HFILL }},
993                 { &hf_tns_data_flag_dic, {      
994                         "Do Immediate Confirmation", "tns.data_flag.dic", FT_UINT16, BASE_BIN, 
995                         NULL, 0x80, "Do Immediate Confirmation", HFILL }},
996                 { &hf_tns_data_flag_rts, {      
997                         "Request To Send", "tns.data_flag.rts", FT_UINT16, BASE_BIN, 
998                         NULL, 0x100, "Request To Send", HFILL }},
999                 { &hf_tns_data_flag_sntt, {     
1000                         "Send NT Trailer", "tns.data_flag.sntt", FT_UINT16, BASE_BIN, 
1001                         NULL, 0x200, "Send NT Trailer", HFILL }},
1002
1003
1004                 { &hf_tns_reserved_byte, {      
1005                         "Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_HEX, 
1006                         NULL, 0x0, "Reserved Byte", HFILL }},
1007                 { &hf_tns_packet_type, {        
1008                         "Packet Type", "tns.type", FT_UINT8, BASE_DEC, 
1009                         VALS(tns_type_vals), 0x0, "Type of TNS packet", HFILL }}        
1010
1011         };
1012
1013         static gint *ett[] = {
1014                 &ett_tns,
1015                 &ett_tns_connect,
1016                 &ett_tns_accept,
1017                 &ett_tns_refuse,
1018                 &ett_tns_abort,
1019                 &ett_tns_redirect,
1020                 &ett_tns_marker,
1021                 &ett_tns_attention,
1022                 &ett_tns_control,
1023                 &ett_tns_data,
1024                 &ett_tns_data_flag,
1025                 &ett_sql
1026         };
1027         proto_tns = proto_register_protocol(
1028                 "Transparent Network Substrate Protocol", "TNS", "tns");
1029         proto_register_field_array(proto_tns, hf, array_length(hf));
1030         proto_register_subtree_array(ett, array_length(ett));
1031 }
1032
1033 void
1034 proto_reg_handoff_tns(void)
1035 {
1036         dissector_add("tcp.port", TCP_PORT_TNS, dissect_tns, proto_tns);
1037 }