HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / plugins / irda / packet-irda.c
blob4e245239b5de0eeb2ea2f1504b09b095c5ea1cc7
1 /* packet-irda.c
2 * Routines for IrDA dissection
3 * By Shaun Jackman <sjackman@pathwayconnect.com>
4 * Copyright 2000 Shaun Jackman
6 * Extended by Jan Kiszka <jan.kiszka@web.de>
7 * Copyright 2003 Jan Kiszka
9 * $Id$
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "config.h"
32 #include <string.h>
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include <epan/conversation.h>
37 #include <epan/wmem/wmem.h>
38 #include <epan/xdlc.h>
40 #include "irda-appl.h"
41 #include <epan/dissectors/packet-sll.h>
44 * This plugin dissects infrared data transmissions as defined by the IrDA
45 * specification (www.irda.org). See
47 * http://www.irda.org/standards/specifications.asp
49 * for various IrDA specifications.
51 * The plugin operates both offline with libpcap files and online on supported
52 * platforms. Live dissection is currently available for Linux-IrDA
53 * (irda.sourceforge.net) and for Windows if the Linux-IrDA port IrCOMM2k
54 * (www.ircomm2k.de) is installed.
58 * LAP
61 /* Frame types and templates */
62 #define INVALID 0xff
65 * XXX - the IrDA spec gives XID as 0x2c; HDLC (and other HDLC-derived
66 * protocolc) use 0xAC.
68 #define IRDA_XID_CMD 0x2c /* Exchange Station Identification */
70 #define CMD_FRAME 0x01
71 #define RSP_FRAME 0x00
73 /* Discovery Flags */
74 #define S_MASK 0x03
75 #define CONFLICT 0x04
77 /* Negotiation Parameters */
78 #define PI_BAUD_RATE 0x01
79 #define PI_MAX_TURN_TIME 0x82
80 #define PI_DATA_SIZE 0x83
81 #define PI_WINDOW_SIZE 0x84
82 #define PI_ADD_BOFS 0x85
83 #define PI_MIN_TURN_TIME 0x86
84 #define PI_LINK_DISC 0x08
88 * LMP
91 /* IrLMP frame opcodes */
92 #define CONNECT_CMD 0x01
93 #define CONNECT_CNF 0x81
94 #define DISCONNECT 0x02
95 #define ACCESSMODE_CMD 0x03
96 #define ACCESSMODE_CNF 0x83
98 #define CONTROL_BIT 0x80
99 #define RESERVED_BIT 0x80
101 /* LSAP-SEL's */
102 #define LSAP_MASK 0x7f
103 #define LSAP_IAS 0x00
104 #define LSAP_ANY 0xff
105 #define LSAP_MAX 0x6f /* 0x70-0x7f are reserved */
106 #define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */
110 * IAP
113 /* IrIAP Op-codes */
114 #define GET_INFO_BASE 0x01
115 #define GET_OBJECTS 0x02
116 #define GET_VALUE 0x03
117 #define GET_VALUE_BY_CLASS 0x04
118 #define GET_OBJECT_INFO 0x05
119 #define GET_ATTRIB_NAMES 0x06
121 #define IAP_LST 0x80
122 #define IAP_ACK 0x40
123 #define IAP_OP 0x3F
125 #define IAS_SUCCESS 0
126 #define IAS_CLASS_UNKNOWN 1
127 #define IAS_ATTRIB_UNKNOWN 2
128 #define IAS_ATTR_TOO_LONG 3
129 #define IAS_DISCONNECT 10
130 #define IAS_UNSUPPORTED 0xFF
134 * TTP
137 #define TTP_PARAMETERS 0x80
138 #define TTP_MORE 0x80
140 static dissector_handle_t data_handle;
142 /* Initialize the protocol and registered fields */
143 static int proto_irlap = -1;
144 static int hf_lap_a = -1;
145 static int hf_lap_a_cr = -1;
146 static int hf_lap_a_address = -1;
147 static int hf_lap_c = -1;
148 static int hf_lap_c_nr = -1;
149 static int hf_lap_c_ns = -1;
150 static int hf_lap_c_p = -1;
151 static int hf_lap_c_f = -1;
152 static int hf_lap_c_s = -1;
153 static int hf_lap_c_u_cmd = -1;
154 static int hf_lap_c_u_rsp = -1;
155 static int hf_lap_c_i = -1;
156 static int hf_lap_c_s_u = -1;
157 static int hf_lap_i = -1;
158 static int hf_snrm_saddr = -1;
159 static int hf_snrm_daddr = -1;
160 static int hf_snrm_ca = -1;
161 static int hf_ua_saddr = -1;
162 static int hf_ua_daddr = -1;
163 static int hf_negotiation_param = -1;
164 static int hf_param_pi = -1;
165 static int hf_param_pl = -1;
166 static int hf_param_pv = -1;
167 static int hf_xid_ident = -1;
168 static int hf_xid_saddr = -1;
169 static int hf_xid_daddr = -1;
170 static int hf_xid_flags = -1;
171 static int hf_xid_s = -1;
172 static int hf_xid_conflict = -1;
173 static int hf_xid_slotnr = -1;
174 static int hf_xid_version = -1;
176 static int proto_irlmp = -1;
177 static int hf_lmp_xid_hints = -1;
178 static int hf_lmp_xid_charset = -1;
179 static int hf_lmp_xid_name = -1;
180 static int hf_lmp_xid_name_no_ascii = -1;
181 static int hf_lmp_dst = -1;
182 static int hf_lmp_dst_control = -1;
183 static int hf_lmp_dst_lsap = -1;
184 static int hf_lmp_src = -1;
185 static int hf_lmp_src_r = -1;
186 static int hf_lmp_src_lsap = -1;
187 static int hf_lmp_opcode = -1;
188 static int hf_lmp_rsvd = -1;
189 static int hf_lmp_reason = -1;
190 static int hf_lmp_mode = -1;
191 static int hf_lmp_status = -1;
193 static int proto_iap = -1;
194 static int hf_iap_ctl = -1;
195 static int hf_iap_ctl_lst = -1;
196 static int hf_iap_ctl_ack = -1;
197 static int hf_iap_ctl_opcode = -1;
198 static int hf_iap_class_name = -1;
199 static int hf_iap_attr_name = -1;
200 static int hf_iap_return = -1;
201 static int hf_iap_list_len = -1;
202 static int hf_iap_list_entry = -1;
203 static int hf_iap_obj_id = -1;
204 static int hf_iap_attr_type = -1;
205 static int hf_iap_int = -1;
206 static int hf_iap_seq_len = -1;
207 static int hf_iap_oct_seq = -1;
208 static int hf_iap_char_set = -1;
209 static int hf_iap_string = -1;
210 static int hf_iap_invaloctet = -1;
211 static int hf_iap_invallsap = -1;
213 static int proto_ttp = -1;
214 static int hf_ttp_p = -1;
215 static int hf_ttp_icredit = -1;
216 static int hf_ttp_m = -1;
217 static int hf_ttp_dcredit = -1;
219 static int proto_log = -1;
220 static int hf_log_msg = -1;
221 static int hf_log_missed = -1;
223 /* Initialize the subtree pointers */
224 static gint ett_irlap = -1;
225 static gint ett_lap_a = -1;
226 static gint ett_lap_c = -1;
227 static gint ett_lap_i = -1;
228 static gint ett_xid_flags = -1;
229 static gint ett_log = -1;
230 static gint ett_irlmp = -1;
231 static gint ett_lmp_dst = -1;
232 static gint ett_lmp_src = -1;
233 static gint ett_iap = -1;
234 static gint ett_iap_ctl = -1;
235 static gint ett_ttp = -1;
237 #define MAX_PARAMETERS 32
238 static gint ett_param[MAX_PARAMETERS];
240 static gint ett_iap_entry[MAX_IAP_ENTRIES];
242 static const xdlc_cf_items irlap_cf_items = {
243 &hf_lap_c_nr,
244 &hf_lap_c_ns,
245 &hf_lap_c_p,
246 &hf_lap_c_f,
247 &hf_lap_c_s,
248 &hf_lap_c_u_cmd,
249 &hf_lap_c_u_rsp,
250 &hf_lap_c_i,
251 &hf_lap_c_s_u
254 /* IAP conversation type */
255 typedef struct iap_conversation {
256 struct iap_conversation* pnext;
257 guint32 iap_query_frame;
258 ias_attr_dissector_t* pattr_dissector;
259 } iap_conversation_t;
261 /* IrLMP conversation type */
262 typedef struct lmp_conversation {
263 struct lmp_conversation* pnext;
264 guint32 iap_result_frame;
265 gboolean ttp;
266 dissector_t proto_dissector;
267 } lmp_conversation_t;
269 static const true_false_string lap_cr_vals = {
270 "Command",
271 "Response"
274 static const true_false_string set_notset = {
275 "Set",
276 "Not set"
279 static const value_string lap_c_ftype_vals[] = {
280 { XDLC_I, "Information frame" },
281 { XDLC_S, "Supervisory frame" },
282 { XDLC_U, "Unnumbered frame" },
283 { 0, NULL }
286 static const value_string lap_c_u_cmd_abbr_vals[] = {
287 { XDLC_SNRM, "SNRM" },
288 { XDLC_DISC, "DISC" },
289 { XDLC_UI, "UI" },
290 { IRDA_XID_CMD, "XID" },
291 { XDLC_TEST, "TEST" },
292 { 0, NULL }
295 static const value_string lap_c_u_rsp_abbr_vals[] = {
296 { XDLC_SNRM, "RNRM" },
297 { XDLC_UA, "UA" },
298 { XDLC_FRMR, "FRMR" },
299 { XDLC_DM, "DM" },
300 { XDLC_RD, "RD" },
301 { XDLC_UI, "UI" },
302 { XDLC_XID, "XID" },
303 { XDLC_TEST, "TEST" },
304 { 0, NULL }
307 static const value_string lap_c_u_cmd_vals[] = {
308 { XDLC_SNRM>>2, "Set Normal Response Mode" },
309 { XDLC_DISC>>2, "Disconnect" },
310 { XDLC_UI>>2, "Unnumbered Information" },
311 { IRDA_XID_CMD>>2, "Exchange Station Identification" },
312 { XDLC_TEST>>2, "Test" },
313 { 0, NULL }
316 static const value_string lap_c_u_rsp_vals[] = {
317 { XDLC_SNRM>>2, "Request Normal Response Mode" },
318 { XDLC_UA>>2, "Unnumbered Acknowledge" },
319 { XDLC_FRMR>>2, "Frame Reject" },
320 { XDLC_DM>>2, "Disconnect Mode" },
321 { XDLC_RD>>2, "Request Disconnect" },
322 { XDLC_UI>>2, "Unnumbered Information" },
323 { XDLC_XID>>2, "Exchange Station Identification" },
324 { XDLC_TEST>>2, "Test" },
325 { 0, NULL }
328 static const value_string lap_c_s_vals[] = {
329 { XDLC_RR>>2, "Receiver ready" },
330 { XDLC_RNR>>2, "Receiver not ready" },
331 { XDLC_REJ>>2, "Reject" },
332 { XDLC_SREJ>>2, "Selective reject" },
333 { 0, NULL }
336 static const value_string xid_slot_numbers[] = {
337 /* Number of XID slots */
338 { 0, "1" },
339 { 1, "6" },
340 { 2, "8" },
341 { 3, "16" },
342 { 0, NULL }
345 static const value_string lmp_opcode_vals[] = {
346 /* IrLMP frame opcodes */
347 { CONNECT_CMD, "Connect Command" },
348 { CONNECT_CNF, "Connect Confirm" },
349 { DISCONNECT, "Disconnect" },
350 { ACCESSMODE_CMD, "Access Mode Command" },
351 { ACCESSMODE_CNF, "Access Mode Confirm" },
352 { 0, NULL }
355 static const value_string lmp_reason_vals[] = {
356 /* IrLMP disconnect reasons */
357 { 0x01, "User Request" },
358 { 0x02, "Unexpected IrLAP Disconnect" },
359 { 0x03, "Failed to establish IrLAP connection" },
360 { 0x04, "IrLAP Reset" },
361 { 0x05, "Link Management Initiated Disconnect" },
362 { 0x06, "Data delivered on disconnected LSAP-Connection"},
363 { 0x07, "Non Responsive LM-MUX Client" },
364 { 0x08, "No available LM-MUX Client" },
365 { 0x09, "Connection Half Open" },
366 { 0x0A, "Illegal Source Address" },
367 { 0xFF, "Unspecified Disconnect Reason" },
368 { 0, NULL }
371 static const value_string lmp_mode_vals[] = {
372 /* IrLMP modes */
373 { 0x00, "Multiplexed" },
374 { 0x01, "Exclusive" },
375 { 0, NULL }
378 static const value_string lmp_status_vals[] = {
379 /* IrLMP status */
380 { 0x00, "Success" },
381 { 0x01, "Failure" },
382 { 0xFF, "Unsupported" },
383 { 0, NULL }
386 static const value_string iap_opcode_vals[] = {
387 /* IrIAP Op-codes */
388 { GET_INFO_BASE, "GetInfoBase" },
389 { GET_OBJECTS, "GetObjects" },
390 { GET_VALUE, "GetValue" },
391 { GET_VALUE_BY_CLASS, "GetValueByClass" },
392 { GET_OBJECT_INFO, "GetObjectInfo" },
393 { GET_ATTRIB_NAMES, "GetAttributeNames" },
394 { 0, NULL }
397 static const value_string iap_return_vals[] = {
398 /* IrIAP Return-codes */
399 { IAS_SUCCESS, "Success" },
400 { IAS_CLASS_UNKNOWN, "Class/Object Unknown" },
401 { IAS_ATTRIB_UNKNOWN, "Attribute Unknown" },
402 { IAS_ATTR_TOO_LONG, "Attribute List Too Long" },
403 { IAS_DISCONNECT, "Disconnect (Linux-IrDA only)" },
404 { IAS_UNSUPPORTED, "Unsupported Optional Operation" },
405 { 0, NULL }
408 static const value_string iap_attr_type_vals[] = {
409 /* LM-IAS Attribute types */
410 { IAS_MISSING, "Missing" },
411 { IAS_INTEGER, "Integer" },
412 { IAS_OCT_SEQ, "Octet Sequence" },
413 { IAS_STRING, "String" },
414 { 0, NULL }
417 static ias_attr_dissector_t device_attr_dissector[] = {
418 /* Device attribute dissectors */
419 /* { "IrLMPSupport", xxx }, not implemented yet... */
420 { NULL, NULL }
423 /* IAS class dissectors */
424 static ias_class_dissector_t class_dissector[] = { CLASS_DISSECTORS };
428 * Dissect parameter tuple
430 guint dissect_param_tuple(tvbuff_t* tvb, proto_tree* tree, guint offset)
432 guint8 len = tvb_get_guint8(tvb, offset + 1);
434 if (tree)
435 proto_tree_add_item(tree, hf_param_pi, tvb, offset, 1, ENC_BIG_ENDIAN);
436 offset++;
438 if (tree)
439 proto_tree_add_item(tree, hf_param_pl, tvb, offset, 1, ENC_BIG_ENDIAN);
440 offset++;
442 if (len > 0)
444 if (tree)
445 proto_tree_add_item(tree, hf_param_pv, tvb, offset, len, ENC_NA);
446 offset += len;
449 return offset;
454 * Dissect TTP
456 static guint dissect_ttp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, gboolean data)
458 guint offset = 0;
459 guint8 head;
460 char buf[128];
462 if (tvb_length(tvb) == 0)
463 return 0;
465 /* Make entries in Protocol column on summary display */
466 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TTP");
468 head = tvb_get_guint8(tvb, offset);
470 g_snprintf(buf, 128, ", Credit=%d", head & ~TTP_PARAMETERS);
471 col_append_str(pinfo->cinfo, COL_INFO, buf);
473 if (root)
475 /* create display subtree for the protocol */
476 proto_item* ti = proto_tree_add_item(root, proto_ttp, tvb, 0, -1, ENC_NA);
477 proto_tree* tree = proto_item_add_subtree(ti, ett_ttp);
479 if (data)
481 proto_tree_add_item(tree, hf_ttp_m, tvb, offset, 1, ENC_BIG_ENDIAN);
482 proto_tree_add_item(tree, hf_ttp_dcredit, tvb, offset, 1, ENC_BIG_ENDIAN);
483 offset++;
485 else
487 proto_tree_add_item(tree, hf_ttp_p, tvb, offset, 1, ENC_BIG_ENDIAN);
488 proto_tree_add_item(tree, hf_ttp_icredit, tvb, offset, 1, ENC_BIG_ENDIAN);
489 offset++;
491 proto_item_set_len(tree, offset);
493 else
494 offset++;
496 return offset;
501 * Dissect IAP request
503 static void dissect_iap_request(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
505 guint offset = 0;
506 guint8 op;
507 guint8 clen = 0;
508 guint8 alen = 0;
509 guint8 src;
510 address srcaddr;
511 address destaddr;
512 conversation_t* conv;
513 iap_conversation_t* iap_conv;
514 char buf[128];
516 if (tvb_length(tvb) == 0)
517 return;
519 /* Make entries in Protocol column on summary display */
520 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAP");
522 op = tvb_get_guint8(tvb, offset) & IAP_OP;
524 switch (op)
526 case GET_VALUE_BY_CLASS:
527 clen = MIN(tvb_get_guint8(tvb, offset + 1), 60);
528 alen = MIN(tvb_get_guint8(tvb, offset + 1 + 1 + clen), 60);
530 /* create conversation entry */
531 src = pinfo->circuit_id ^ CMD_FRAME;
532 srcaddr.type = AT_NONE;
533 srcaddr.len = 1;
534 srcaddr.data = (guint8*)&src;
536 destaddr.type = AT_NONE;
537 destaddr.len = 1;
538 destaddr.data = (guint8*)&pinfo->circuit_id;
540 conv = find_conversation(pinfo->fd->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0);
541 if (conv)
543 iap_conv = (iap_conversation_t*)conversation_get_proto_data(conv, proto_iap);
544 while (1)
546 if (iap_conv->iap_query_frame == pinfo->fd->num)
548 iap_conv = NULL;
549 break;
551 if (iap_conv->pnext == NULL)
553 iap_conv->pnext = wmem_new(wmem_file_scope(), iap_conversation_t);
554 iap_conv = iap_conv->pnext;
555 break;
557 iap_conv = iap_conv->pnext;
560 else
562 conv = conversation_new(pinfo->fd->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0);
563 iap_conv = wmem_new(wmem_file_scope(), iap_conversation_t);
564 conversation_add_proto_data(conv, proto_iap, (void*)iap_conv);
567 /* Dissect IAP query if it is new */
568 if (iap_conv)
570 int i, j;
571 char class_name[256];
572 char attr_name[256];
575 iap_conv->pnext = NULL;
576 iap_conv->iap_query_frame = pinfo->fd->num;
577 iap_conv->pattr_dissector = NULL;
579 tvb_memcpy(tvb, class_name, offset + 1 + 1, clen);
580 class_name[clen] = 0;
581 tvb_memcpy(tvb, attr_name, offset + 1 + 1 + clen + 1, alen);
582 attr_name[alen] = 0;
584 /* Find the attribute dissector */
585 for (i = 0; class_dissector[i].class_name != NULL; i++)
586 if (strcmp(class_name, class_dissector[i].class_name) == 0)
588 for (j = 0; class_dissector[i].pattr_dissector[j].attr_name != NULL; j++)
589 if (strcmp(attr_name, class_dissector[i].pattr_dissector[j].attr_name) == 0)
591 iap_conv->pattr_dissector = &class_dissector[i].pattr_dissector[j];
592 break;
594 break;
598 col_set_str(pinfo->cinfo, COL_INFO, "GetValueByClass: \"");
600 tvb_memcpy(tvb, buf, offset + 1 + 1, clen);
601 memcpy(&buf[clen], "\" \"", 3);
602 tvb_memcpy(tvb, buf + clen + 3, offset + 1 + 1 + clen + 1, alen);
603 buf[clen + 3 + alen] = '\"';
604 buf[clen + 3 + alen + 1] = 0;
605 col_append_str(pinfo->cinfo, COL_INFO, buf);
608 if (root)
610 /* create display subtree for the protocol */
611 proto_item* ti = proto_tree_add_item(root, proto_iap, tvb, 0, -1, ENC_NA);
612 proto_tree* tree = proto_item_add_subtree(ti, ett_iap);
614 proto_tree* ctl_tree;
617 ti = proto_tree_add_item(tree, hf_iap_ctl, tvb, offset, 1, ENC_BIG_ENDIAN);
618 ctl_tree = proto_item_add_subtree(ti, ett_iap_ctl);
619 proto_tree_add_item(ctl_tree, hf_iap_ctl_lst, tvb, offset, 1, ENC_BIG_ENDIAN);
620 proto_tree_add_item(ctl_tree, hf_iap_ctl_ack, tvb, offset, 1, ENC_BIG_ENDIAN);
621 proto_tree_add_item(ctl_tree, hf_iap_ctl_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
622 offset++;
624 switch (op)
626 case GET_VALUE_BY_CLASS:
627 proto_tree_add_item(tree, hf_iap_class_name, tvb, offset, 1, ENC_ASCII|ENC_NA);
628 offset += 1 + clen;
630 proto_tree_add_item(tree, hf_iap_attr_name, tvb, offset, 1, ENC_ASCII|ENC_NA);
631 offset += 1 + alen;
632 break;
635 else
637 offset++;
638 switch (op)
640 case GET_VALUE_BY_CLASS:
641 offset += 1 + clen + 1 + alen;
642 break;
646 /* If any bytes remain, send it to the generic data dissector */
647 tvb = tvb_new_subset_remaining(tvb, offset);
648 call_dissector(data_handle, tvb, pinfo, root);
653 * Dissect IAP result
655 static void dissect_iap_result(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
657 guint offset = 0;
658 guint len = tvb_length(tvb);
659 guint n = 0;
660 guint list_len;
661 guint8 op;
662 guint8 retcode;
663 guint8 type;
664 guint16 attr_len;
665 char buf[300];
666 guint8 src;
667 address srcaddr;
668 address destaddr;
669 conversation_t* conv;
670 iap_conversation_t* cur_iap_conv;
671 iap_conversation_t* iap_conv = NULL;
672 guint32 num;
675 if (tvb_length(tvb) == 0)
676 return;
678 /* Make entries in Protocol column on summary display */
679 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAP");
681 op = tvb_get_guint8(tvb, offset) & IAP_OP;
682 retcode = tvb_get_guint8(tvb, offset + 1);
684 src = pinfo->circuit_id ^ CMD_FRAME;
685 srcaddr.type = AT_NONE;
686 srcaddr.len = 1;
687 srcaddr.data = (guint8*)&src;
689 destaddr.type = AT_NONE;
690 destaddr.len = 1;
691 destaddr.data = (guint8*)&pinfo->circuit_id;
693 /* Find result value dissector */
694 conv = find_conversation(pinfo->fd->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0);
695 if (conv)
697 num = pinfo->fd->num;
699 iap_conv = (iap_conversation_t*)conversation_get_proto_data(conv, proto_iap);
700 while (iap_conv && (iap_conv->iap_query_frame >= num))
701 iap_conv = iap_conv->pnext;
703 if (iap_conv)
705 cur_iap_conv = iap_conv->pnext;
706 while (cur_iap_conv)
708 if ((cur_iap_conv->iap_query_frame < num) &&
709 (cur_iap_conv->iap_query_frame > iap_conv->iap_query_frame))
711 iap_conv = cur_iap_conv;
714 cur_iap_conv = cur_iap_conv->pnext;
719 col_set_str(pinfo->cinfo, COL_INFO, "Result: ");
720 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(retcode, iap_return_vals, "0x%02X"));
722 switch (op)
724 case GET_VALUE_BY_CLASS:
725 if (retcode == 0)
727 guint8 *string;
728 switch (tvb_get_guint8(tvb, offset + 6))
730 case IAS_MISSING:
731 g_snprintf(buf, 300, ", Missing");
732 break;
734 case IAS_INTEGER:
735 g_snprintf(buf, 300, ", Integer: %d", tvb_get_ntohl(tvb, offset + 7));
736 break;
738 case IAS_OCT_SEQ:
739 g_snprintf(buf, 300, ", %d Octets", tvb_get_ntohs(tvb, offset + 7));
740 break;
742 case IAS_STRING:
743 n = tvb_get_guint8(tvb, offset + 8);
744 string = tvb_get_string(wmem_packet_scope(), tvb, offset + 9, n);
745 g_snprintf(buf, 300, ", \"%s\"", string);
746 break;
748 col_append_str(pinfo->cinfo, COL_INFO, buf);
749 if (tvb_get_ntohs(tvb, offset + 2) > 1)
750 col_append_str(pinfo->cinfo, COL_INFO, ", ...");
752 break;
755 if (root)
757 /* create display subtree for the protocol */
758 proto_item* ti = proto_tree_add_item(root, proto_iap, tvb, 0, -1, ENC_NA);
759 proto_tree* tree = proto_item_add_subtree(ti, ett_iap);
761 proto_tree* ctl_tree;
762 proto_tree* entry_tree;
765 ti = proto_tree_add_item(tree, hf_iap_ctl, tvb, offset, 1, ENC_BIG_ENDIAN);
766 ctl_tree = proto_item_add_subtree(ti, ett_iap_ctl);
767 proto_tree_add_item(ctl_tree, hf_iap_ctl_lst, tvb, offset, 1, ENC_BIG_ENDIAN);
768 proto_tree_add_item(ctl_tree, hf_iap_ctl_ack, tvb, offset, 1, ENC_BIG_ENDIAN);
769 proto_tree_add_item(ctl_tree, hf_iap_ctl_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
770 offset++;
772 proto_tree_add_item(tree, hf_iap_return, tvb, offset, 1, ENC_BIG_ENDIAN);
773 offset++;
775 switch (op)
777 case GET_VALUE_BY_CLASS:
778 if (retcode == 0)
780 list_len = tvb_get_ntohs(tvb, offset);
782 proto_tree_add_item(tree, hf_iap_list_len, tvb, offset, 2, ENC_BIG_ENDIAN);
783 offset += 2;
785 while ((offset < len) && (n < list_len))
787 type = tvb_get_guint8(tvb, offset + 2);
788 switch (type)
790 case IAS_INTEGER:
791 attr_len = 4;
792 break;
794 case IAS_OCT_SEQ:
795 attr_len = tvb_get_ntohs(tvb, offset + 2 + 1) + 2;
796 break;
798 case IAS_STRING:
799 attr_len = tvb_get_guint8(tvb, offset + 2 + 1 + 1) + 2;
800 break;
802 default:
803 attr_len = 0;
806 ti = proto_tree_add_item(tree, hf_iap_list_entry, tvb, offset, 2 + 1 + attr_len, ENC_NA);
807 proto_item_append_text(ti, "%d", n + 1);
808 entry_tree = proto_item_add_subtree(ti, ett_iap_entry[n]);
810 proto_tree_add_item(entry_tree, hf_iap_obj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
811 offset += 2;
813 proto_tree_add_item(entry_tree, hf_iap_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
814 offset++;
816 switch (type)
818 case IAS_INTEGER:
819 if (!iap_conv || !iap_conv->pattr_dissector ||
820 !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree,
821 n, type))
822 proto_tree_add_item(entry_tree, hf_iap_int, tvb, offset, 4, ENC_BIG_ENDIAN);
823 break;
825 case IAS_OCT_SEQ:
826 proto_tree_add_item(entry_tree, hf_iap_seq_len, tvb, offset, 2, ENC_BIG_ENDIAN);
827 if (!iap_conv || !iap_conv->pattr_dissector ||
828 !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree,
829 n, type))
830 proto_tree_add_item(entry_tree, hf_iap_oct_seq, tvb, offset + 2,
831 attr_len - 2, ENC_NA);
832 break;
834 case IAS_STRING:
835 proto_tree_add_item(entry_tree, hf_iap_char_set, tvb, offset, 1, ENC_BIG_ENDIAN);
836 if (!iap_conv || !iap_conv->pattr_dissector ||
837 !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree,
838 n, type))
839 proto_tree_add_item(entry_tree, hf_iap_string, tvb, offset + 1, 1, ENC_ASCII|ENC_NA);
840 break;
842 offset += attr_len;
844 n++;
847 break;
850 else
852 offset += 2;
853 switch (op)
855 case GET_VALUE_BY_CLASS:
856 if (retcode == 0)
858 offset += 2;
860 while (offset < len)
862 offset += 2;
863 type = tvb_get_guint8(tvb, offset);
864 offset++;
866 switch (type)
868 case IAS_INTEGER:
869 attr_len = 4;
870 if (iap_conv && iap_conv->pattr_dissector)
871 iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0,
872 n, type);
873 break;
875 case IAS_OCT_SEQ:
876 attr_len = tvb_get_ntohs(tvb, offset) + 2;
877 if (iap_conv && iap_conv->pattr_dissector)
878 iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0,
879 n, type);
880 break;
882 case IAS_STRING:
883 attr_len = tvb_get_guint8(tvb, offset + 1) + 2;
884 if (iap_conv && iap_conv->pattr_dissector)
885 iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0,
886 n, type);
887 break;
889 default:
890 attr_len = 0;
892 offset += attr_len;
894 n++;
897 break;
901 /* If any bytes remain, send it to the generic data dissector */
902 tvb = tvb_new_subset_remaining(tvb, offset);
903 call_dissector(data_handle, tvb, pinfo, root);
908 * Check if IAP result is octet sequence
910 gboolean check_iap_octet_result(tvbuff_t* tvb, proto_tree* tree, guint offset,
911 const char* attr_name, guint8 attr_type)
913 if (attr_type != IAS_OCT_SEQ)
915 if (tree)
917 proto_item* ti = proto_tree_add_item(tree, hf_iap_invaloctet, tvb, offset, 0, ENC_NA);
918 proto_item_append_text(ti, "%s", attr_name);
919 proto_item_append_text(ti, "\" attribute must be octet sequence!");
922 return FALSE;
924 else
925 return TRUE;
930 * Check if IAP result is correct LsapSel
932 guint8 check_iap_lsap_result(tvbuff_t* tvb, proto_tree* tree, guint offset,
933 const char* attr_name, guint8 attr_type)
935 guint32 lsap;
938 if ((attr_type != IAS_INTEGER) || ((lsap = tvb_get_ntohl(tvb, offset)) < 0x01) ||
939 (lsap > 0x6F))
941 if (tree)
943 proto_item* ti = proto_tree_add_item(tree, hf_iap_invallsap, tvb, offset, 0, ENC_NA);
944 proto_item_append_text(ti, "%s", attr_name);
945 proto_item_append_text(ti, "\" attribute must be integer value between 0x01 and 0x6F!");
948 return 0;
950 else
951 return lsap;
956 * Dissect IrDA application protocol
958 static void dissect_appl_proto(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, pdu_type_t pdu_type)
960 guint offset = 0;
961 guint8 src;
962 address srcaddr;
963 address destaddr;
964 conversation_t* conv;
965 lmp_conversation_t* cur_lmp_conv;
966 lmp_conversation_t* lmp_conv = NULL;
967 guint32 num;
970 src = pinfo->circuit_id ^ CMD_FRAME;
971 srcaddr.type = AT_NONE;
972 srcaddr.len = 1;
973 srcaddr.data = (guint8*)&src;
975 destaddr.type = AT_NONE;
976 destaddr.len = 1;
977 destaddr.data = (guint8*)&pinfo->circuit_id;
979 /* Find result value dissector */
980 conv = find_conversation(pinfo->fd->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0);
981 if (conv)
983 num = pinfo->fd->num;
985 lmp_conv = (lmp_conversation_t*)conversation_get_proto_data(conv, proto_irlmp);
986 while (lmp_conv && (lmp_conv->iap_result_frame >= num))
987 lmp_conv = lmp_conv->pnext;
989 if (lmp_conv)
991 cur_lmp_conv = lmp_conv->pnext;
992 while (cur_lmp_conv)
994 if ((cur_lmp_conv->iap_result_frame < num) &&
995 (cur_lmp_conv->iap_result_frame > lmp_conv->iap_result_frame))
997 lmp_conv = cur_lmp_conv;
1000 cur_lmp_conv = cur_lmp_conv->pnext;
1005 if (lmp_conv)
1007 /*g_message("%x:%d->%x:%d = %p\n", src, pinfo->srcport, pinfo->circuit_id, pinfo->destport, lmp_conv); */
1008 /*g_message("->%d: %d %d %p\n", pinfo->fd->num, lmp_conv->iap_result_frame, lmp_conv->ttp, lmp_conv->proto_dissector); */
1009 if ((lmp_conv->ttp) && (pdu_type != DISCONNECT_PDU))
1011 offset += dissect_ttp(tvb, pinfo, root, (pdu_type == DATA_PDU));
1013 tvb = tvb_new_subset_remaining(tvb, offset);
1016 pinfo->private_data = (void *)pdu_type;
1018 lmp_conv->proto_dissector(tvb, pinfo, root);
1020 else
1021 call_dissector(data_handle, tvb, pinfo, root);
1026 * Dissect LMP
1028 static void dissect_irlmp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
1030 guint offset = 0;
1031 guint8 dlsap;
1032 guint8 slsap;
1033 guint8 cbit;
1034 guint8 opcode = 0;
1037 /* Make entries in Protocol column on summary display */
1038 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrLMP");
1040 dlsap = tvb_get_guint8(tvb, offset);
1041 cbit = dlsap & CONTROL_BIT;
1042 dlsap &= ~CONTROL_BIT;
1044 slsap = tvb_get_guint8(tvb, offset+1) & ~CONTROL_BIT;
1046 /* save Lsaps in pinfo */
1047 pinfo->srcport = slsap;
1048 pinfo->destport = dlsap;
1050 if (cbit != 0)
1052 opcode = tvb_get_guint8(tvb, offset+2);
1054 col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d, ", slsap, dlsap);
1055 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, lmp_opcode_vals, "0x%02X"));
1056 if ((opcode == ACCESSMODE_CMD) || (opcode == ACCESSMODE_CNF))
1058 col_append_str(pinfo->cinfo, COL_INFO, " (");
1059 col_append_str(pinfo->cinfo, COL_INFO,
1060 val_to_str(tvb_get_guint8(tvb, offset+4), lmp_mode_vals, "0x%02X"));
1061 col_append_str(pinfo->cinfo, COL_INFO, ")");
1064 else
1065 col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d, Len=%d", slsap, dlsap,
1066 tvb_length(tvb) - 2);
1068 if (root)
1070 /* create display subtree for the protocol */
1071 proto_item* ti = proto_tree_add_item(root, proto_irlmp, tvb, 0, -1, ENC_NA);
1072 proto_tree* tree = proto_item_add_subtree(ti, ett_irlmp);
1074 proto_tree* dst_tree;
1075 proto_tree* src_tree;
1078 ti = proto_tree_add_item(tree, hf_lmp_dst, tvb, offset, 1, ENC_BIG_ENDIAN);
1079 dst_tree = proto_item_add_subtree(ti, ett_lmp_dst);
1080 proto_tree_add_item(dst_tree, hf_lmp_dst_control, tvb, offset, 1, ENC_BIG_ENDIAN);
1081 proto_tree_add_item(dst_tree, hf_lmp_dst_lsap, tvb, offset, 1, ENC_BIG_ENDIAN);
1082 offset++;
1084 ti = proto_tree_add_item(tree, hf_lmp_src, tvb, offset, 1, ENC_BIG_ENDIAN);
1085 src_tree = proto_item_add_subtree(ti, ett_lmp_src);
1086 proto_tree_add_item(src_tree, hf_lmp_src_r, tvb, offset, 1, ENC_BIG_ENDIAN);
1087 proto_tree_add_item(src_tree, hf_lmp_src_lsap, tvb, offset, 1, ENC_BIG_ENDIAN);
1088 offset++;
1090 if (cbit != 0)
1092 proto_tree_add_item(tree, hf_lmp_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
1093 offset++;
1095 switch (opcode)
1097 case CONNECT_CMD:
1098 case CONNECT_CNF:
1099 if (offset < tvb_length(tvb))
1101 proto_tree_add_item(tree, hf_lmp_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN);
1102 offset++;
1104 break;
1106 case DISCONNECT:
1107 proto_tree_add_item(tree, hf_lmp_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
1108 offset++;
1109 break;
1111 case ACCESSMODE_CMD:
1112 proto_tree_add_item(tree, hf_lmp_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN);
1113 offset++;
1115 proto_tree_add_item(tree, hf_lmp_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1116 offset++;
1117 break;
1119 case ACCESSMODE_CNF:
1120 proto_tree_add_item( tree, hf_lmp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1121 offset++;
1123 proto_tree_add_item(tree, hf_lmp_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1124 offset++;
1125 break;
1129 tvb = tvb_new_subset_remaining(tvb, offset);
1130 proto_item_set_len(tree, offset);
1132 else
1134 offset += 2;
1135 if (cbit != 0)
1137 offset += 1;
1139 switch (opcode)
1141 case CONNECT_CMD:
1142 case CONNECT_CNF:
1143 if (offset < tvb_length(tvb))
1144 offset++;
1145 break;
1147 case DISCONNECT:
1148 offset++;
1149 break;
1151 case ACCESSMODE_CMD:
1152 case ACCESSMODE_CNF:
1153 offset += 2;
1154 break;
1158 tvb = tvb_new_subset_remaining(tvb, offset);
1161 if (cbit == 0)
1163 if (dlsap == LSAP_IAS)
1164 dissect_iap_request(tvb, pinfo, root);
1165 else if (slsap == LSAP_IAS)
1166 dissect_iap_result(tvb, pinfo, root);
1167 else
1168 dissect_appl_proto(tvb, pinfo, root, DATA_PDU);
1170 else
1172 if ((dlsap == LSAP_IAS) || (slsap == LSAP_IAS))
1173 call_dissector(data_handle, tvb, pinfo, root);
1174 else
1175 switch (opcode)
1177 case CONNECT_CMD:
1178 case CONNECT_CNF:
1179 dissect_appl_proto(tvb, pinfo, root, CONNECT_PDU);
1180 break;
1182 case DISCONNECT:
1183 dissect_appl_proto(tvb, pinfo, root, DISCONNECT_PDU);
1184 break;
1186 default:
1187 call_dissector(data_handle, tvb, pinfo, root);
1194 * Add LMP conversation
1196 void add_lmp_conversation(packet_info* pinfo, guint8 dlsap, gboolean ttp, dissector_t proto_dissector)
1198 guint8 dest;
1199 address srcaddr;
1200 address destaddr;
1201 conversation_t* conv;
1202 lmp_conversation_t* lmp_conv = NULL;
1205 /*g_message("%d: add_lmp_conversation(%p, %d, %d, %p) = ", pinfo->fd->num, pinfo, dlsap, ttp, proto_dissector); */
1206 srcaddr.type = AT_NONE;
1207 srcaddr.len = 1;
1208 srcaddr.data = (guint8*)&pinfo->circuit_id;
1210 dest = pinfo->circuit_id ^ CMD_FRAME;
1211 destaddr.type = AT_NONE;
1212 destaddr.len = 1;
1213 destaddr.data = (guint8*)&dest;
1215 conv = find_conversation(pinfo->fd->num, &destaddr, &srcaddr, PT_NONE, dlsap, 0, NO_PORT_B);
1216 if (conv)
1218 lmp_conv = (lmp_conversation_t*)conversation_get_proto_data(conv, proto_irlmp);
1219 while (1)
1221 /* Does entry already exist? */
1222 if (lmp_conv->iap_result_frame == pinfo->fd->num)
1223 return;
1225 if (lmp_conv->pnext == NULL)
1227 lmp_conv->pnext = wmem_new(wmem_file_scope(), lmp_conversation_t);
1228 lmp_conv = lmp_conv->pnext;
1229 break;
1231 lmp_conv = lmp_conv->pnext;
1234 else
1236 conv = conversation_new(pinfo->fd->num, &destaddr, &srcaddr, PT_NONE, dlsap, 0, NO_PORT_B);
1237 lmp_conv = wmem_new(wmem_file_scope(), lmp_conversation_t);
1238 conversation_add_proto_data(conv, proto_irlmp, (void*)lmp_conv);
1241 lmp_conv->pnext = NULL;
1242 lmp_conv->iap_result_frame = pinfo->fd->num;
1243 lmp_conv->ttp = ttp;
1244 lmp_conv->proto_dissector = proto_dissector;
1246 /*g_message("%p\n", lmp_conv); */
1251 * Dissect Negotiation Parameters
1253 static guint dissect_negotiation(tvbuff_t* tvb, proto_tree* tree, guint offset)
1255 guint n = 0;
1256 proto_item* ti;
1257 proto_tree* p_tree;
1258 char buf[256];
1259 guint8 pv;
1261 while (tvb_reported_length_remaining(tvb, offset) > 0)
1263 guint8 p_len = tvb_get_guint8(tvb, offset + 1);
1265 if (tree)
1267 ti = proto_tree_add_item(tree, hf_negotiation_param, tvb, offset, p_len + 2, ENC_NA);
1268 p_tree = proto_item_add_subtree(ti, ett_param[n]);
1270 pv = tvb_get_guint8(tvb, offset+2);
1271 buf[0] = 0;
1273 switch (tvb_get_guint8(tvb, offset))
1275 case PI_BAUD_RATE:
1276 proto_item_append_text(ti, ": Baud Rate (");
1278 if (pv & 0x01)
1279 g_strlcat(buf, ", 2400", 256);
1280 if (pv & 0x02)
1281 g_strlcat(buf, ", 9600", 256);
1282 if (pv & 0x04)
1283 g_strlcat(buf, ", 19200", 256);
1284 if (pv & 0x08)
1285 g_strlcat(buf, ", 38400", 256);
1286 if (pv & 0x10)
1287 g_strlcat(buf, ", 57600", 256);
1288 if (pv & 0x20)
1289 g_strlcat(buf, ", 115200", 256);
1290 if (pv & 0x40)
1291 g_strlcat(buf, ", 576000", 256);
1292 if (pv & 0x80)
1293 g_strlcat(buf, ", 1152000", 256);
1294 if ((p_len > 1) && (tvb_get_guint8(tvb, offset+3) & 0x01))
1295 g_strlcat(buf, ", 4000000", 256);
1297 g_strlcat(buf, " bps)", 256);
1299 proto_item_append_text(ti, "%s", buf+2);
1301 break;
1303 case PI_MAX_TURN_TIME:
1304 proto_item_append_text(ti, ": Maximum Turn Time (");
1306 if (pv & 0x01)
1307 g_strlcat(buf, ", 500", 256);
1308 if (pv & 0x02)
1309 g_strlcat(buf, ", 250", 256);
1310 if (pv & 0x04)
1311 g_strlcat(buf, ", 100", 256);
1312 if (pv & 0x08)
1313 g_strlcat(buf, ", 50", 256);
1315 g_strlcat(buf, " ms)", 256);
1317 proto_item_append_text(ti, "%s", buf+2);
1319 break;
1321 case PI_DATA_SIZE:
1322 proto_item_append_text(ti, ": Data Size (");
1324 if (pv & 0x01)
1325 g_strlcat(buf, ", 64", 256);
1326 if (pv & 0x02)
1327 g_strlcat(buf, ", 128", 256);
1328 if (pv & 0x04)
1329 g_strlcat(buf, ", 256", 256);
1330 if (pv & 0x08)
1331 g_strlcat(buf, ", 512", 256);
1332 if (pv & 0x10)
1333 g_strlcat(buf, ", 1024", 256);
1334 if (pv & 0x20)
1335 g_strlcat(buf, ", 2048", 256);
1337 g_strlcat(buf, " bytes)", 256);
1339 proto_item_append_text(ti, "%s", buf+2);
1341 break;
1343 case PI_WINDOW_SIZE:
1344 proto_item_append_text(ti, ": Window Size (");
1346 if (pv & 0x01)
1347 g_strlcat(buf, ", 1", 256);
1348 if (pv & 0x02)
1349 g_strlcat(buf, ", 2", 256);
1350 if (pv & 0x04)
1351 g_strlcat(buf, ", 3", 256);
1352 if (pv & 0x08)
1353 g_strlcat(buf, ", 4", 256);
1354 if (pv & 0x10)
1355 g_strlcat(buf, ", 5", 256);
1356 if (pv & 0x20)
1357 g_strlcat(buf, ", 6", 256);
1358 if (pv & 0x40)
1359 g_strlcat(buf, ", 7", 256);
1361 g_strlcat(buf, " frame window)", 256);
1363 proto_item_append_text(ti, "%s", buf+2);
1365 break;
1367 case PI_ADD_BOFS:
1368 proto_item_append_text(ti, ": Additional BOFs (");
1370 if (pv & 0x01)
1371 g_strlcat(buf, ", 48", 256);
1372 if (pv & 0x02)
1373 g_strlcat(buf, ", 24", 256);
1374 if (pv & 0x04)
1375 g_strlcat(buf, ", 12", 256);
1376 if (pv & 0x08)
1377 g_strlcat(buf, ", 5", 256);
1378 if (pv & 0x10)
1379 g_strlcat(buf, ", 3", 256);
1380 if (pv & 0x20)
1381 g_strlcat(buf, ", 2", 256);
1382 if (pv & 0x40)
1383 g_strlcat(buf, ", 1", 256);
1384 if (pv & 0x80)
1385 g_strlcat(buf, ", 0", 256);
1387 g_strlcat(buf, " additional BOFs at 115200)", 256);
1389 proto_item_append_text(ti, "%s", buf+2);
1391 break;
1393 case PI_MIN_TURN_TIME:
1394 proto_item_append_text(ti, ": Minimum Turn Time (");
1396 if (pv & 0x01)
1397 g_strlcat(buf, ", 10", 256);
1398 if (pv & 0x02)
1399 g_strlcat(buf, ", 5", 256);
1400 if (pv & 0x04)
1401 g_strlcat(buf, ", 1", 256);
1402 if (pv & 0x08)
1403 g_strlcat(buf, ", 0.5", 256);
1404 if (pv & 0x10)
1405 g_strlcat(buf, ", 0.1", 256);
1406 if (pv & 0x20)
1407 g_strlcat(buf, ", 0.05", 256);
1408 if (pv & 0x40)
1409 g_strlcat(buf, ", 0.01", 256);
1410 if (pv & 0x80)
1411 g_strlcat(buf, ", 0", 256);
1413 g_strlcat(buf, " ms)", 256);
1415 proto_item_append_text(ti, "%s", buf+2);
1417 break;
1419 case PI_LINK_DISC:
1420 proto_item_append_text(ti, ": Link Disconnect/Threshold Time (");
1422 if (pv & 0x01)
1423 g_strlcat(buf, ", 3/0", 256);
1424 if (pv & 0x02)
1425 g_strlcat(buf, ", 8/3", 256);
1426 if (pv & 0x04)
1427 g_strlcat(buf, ", 12/3", 256);
1428 if (pv & 0x08)
1429 g_strlcat(buf, ", 16/3", 256);
1430 if (pv & 0x10)
1431 g_strlcat(buf, ", 20/3", 256);
1432 if (pv & 0x20)
1433 g_strlcat(buf, ", 25/3", 256);
1434 if (pv & 0x40)
1435 g_strlcat(buf, ", 30/3", 256);
1436 if (pv & 0x80)
1437 g_strlcat(buf, ", 40/3", 256);
1439 g_strlcat(buf, " s)", 256);
1441 proto_item_append_text(ti, "%s", buf+2);
1443 break;
1445 default:
1446 proto_item_append_text(ti, ": unknown");
1448 } else
1449 p_tree = NULL;
1451 offset = dissect_param_tuple(tvb, p_tree, offset);
1452 n++;
1455 return offset;
1460 * Dissect XID packet
1462 static void dissect_xid(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, proto_tree* lap_tree, gboolean is_command)
1464 int offset = 0;
1465 proto_item* ti = NULL;
1466 proto_tree* i_tree = NULL;
1467 proto_tree* flags_tree;
1468 guint32 saddr, daddr;
1469 guint8 s;
1470 proto_tree* lmp_tree = NULL;
1472 if (lap_tree)
1474 ti = proto_tree_add_item(lap_tree, hf_lap_i, tvb, offset, -1, ENC_NA);
1475 i_tree = proto_item_add_subtree(ti, ett_lap_i);
1477 proto_tree_add_item(i_tree, hf_xid_ident, tvb, offset, 1, ENC_BIG_ENDIAN);
1479 offset++;
1481 saddr = tvb_get_letohl(tvb, offset);
1482 col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr);
1483 if (lap_tree)
1484 proto_tree_add_uint(i_tree, hf_xid_saddr, tvb, offset, 4, saddr);
1485 offset += 4;
1487 daddr = tvb_get_letohl(tvb, offset);
1488 col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr);
1489 if (lap_tree)
1490 proto_tree_add_uint(i_tree, hf_xid_daddr, tvb, offset, 4, daddr);
1491 offset += 4;
1493 if (lap_tree)
1495 ti = proto_tree_add_item(i_tree, hf_xid_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1496 flags_tree = proto_item_add_subtree(ti, ett_xid_flags);
1497 proto_tree_add_item(flags_tree, hf_xid_s, tvb, offset, 1, ENC_BIG_ENDIAN);
1498 proto_tree_add_item(flags_tree, hf_xid_conflict, tvb, offset, 1, ENC_BIG_ENDIAN);
1500 offset++;
1502 if (is_command)
1504 s = tvb_get_guint8(tvb, offset);
1505 if (s == 0xFF)
1506 col_append_str(pinfo->cinfo, COL_INFO, ", s=final");
1507 else
1508 col_append_fstr(pinfo->cinfo, COL_INFO, ", s=%u", s);
1509 if (lap_tree)
1511 ti = proto_tree_add_uint(i_tree, hf_xid_slotnr, tvb, offset, 1, s);
1512 if (s == 0xFF)
1513 proto_item_append_text(ti, " (final)");
1516 offset++;
1518 if (lap_tree)
1519 proto_tree_add_item(i_tree, hf_xid_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1520 offset++;
1522 if (lap_tree)
1524 proto_item_set_end(lap_tree, tvb, offset);
1525 proto_item_set_end(i_tree, tvb, offset);
1528 if (tvb_reported_length_remaining(tvb, offset) > 0)
1530 guint hints_len;
1531 guint8 hint1 = 0;
1532 guint8 hint2 = 0;
1533 char buf[23];
1535 if (root)
1537 ti = proto_tree_add_item(root, proto_irlmp, tvb, offset, -1, ENC_NA);
1538 lmp_tree = proto_item_add_subtree(ti, ett_irlmp);
1541 for (hints_len = 0;;)
1543 guint8 hint = tvb_get_guint8(tvb, offset + hints_len++);
1545 if (hints_len == 1)
1546 hint1 = hint;
1547 else if (hints_len == 2)
1548 hint2 = hint;
1550 if ((hint & 0x80) == 0)
1551 break;
1554 if (root)
1556 ti = proto_tree_add_item(lmp_tree, hf_lmp_xid_hints, tvb, offset, hints_len, ENC_NA);
1557 if ((hint1 | hint2) != 0)
1559 char service_hints[256];
1561 service_hints[0] = 0;
1563 if (hint1 & 0x01)
1564 g_strlcat(service_hints, ", PnP Compatible", 256);
1565 if (hint1 & 0x02)
1566 g_strlcat(service_hints, ", PDA/Palmtop", 256);
1567 if (hint1 & 0x04)
1568 g_strlcat(service_hints, ", Computer", 256);
1569 if (hint1 & 0x08)
1570 g_strlcat(service_hints, ", Printer", 256);
1571 if (hint1 & 0x10)
1572 g_strlcat(service_hints, ", Modem", 256);
1573 if (hint1 & 0x20)
1574 g_strlcat(service_hints, ", Fax", 256);
1575 if (hint1 & 0x40)
1576 g_strlcat(service_hints, ", LAN Access", 256);
1577 if (hint2 & 0x01)
1578 g_strlcat(service_hints, ", Telephony", 256);
1579 if (hint2 & 0x02)
1580 g_strlcat(service_hints, ", File Server", 256);
1581 if (hint2 & 0x04)
1582 g_strlcat(service_hints, ", IrCOMM", 256);
1583 if (hint2 & 0x20)
1584 g_strlcat(service_hints, ", OBEX", 256);
1586 g_strlcat(service_hints, ")", 256);
1587 service_hints[0] = ' ';
1588 service_hints[1] = '(';
1590 proto_item_append_text(ti, "%s", service_hints);
1593 offset += hints_len;
1595 if (tvb_reported_length_remaining(tvb, offset) > 0)
1597 guint8 cset;
1598 gint name_len;
1600 cset = tvb_get_guint8(tvb, offset);
1601 if (root)
1602 proto_tree_add_uint(lmp_tree, hf_lmp_xid_charset, tvb, offset, 1, cset);
1603 offset++;
1604 name_len = tvb_reported_length_remaining(tvb, offset);
1605 if (name_len > 0)
1607 if (cset == 0x00)
1610 if (name_len > 22)
1611 name_len = 22;
1612 tvb_memcpy(tvb, buf, offset, name_len);
1613 buf[name_len] = 0;
1614 col_append_str(pinfo->cinfo, COL_INFO, ", \"");
1615 col_append_str(pinfo->cinfo, COL_INFO, buf);
1616 col_append_str(pinfo->cinfo, COL_INFO, "\"");
1617 if (root)
1618 proto_tree_add_item(lmp_tree, hf_lmp_xid_name, tvb, offset,
1619 -1, ENC_ASCII|ENC_NA);
1621 else
1623 if (root)
1624 proto_tree_add_item(lmp_tree, hf_lmp_xid_name_no_ascii, tvb, offset,
1625 -1, ENC_NA);
1634 * Dissect Log Messages
1636 static void dissect_log(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
1638 /* Make entries in Protocol column on summary display */
1639 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Log");
1641 /* missed messages? */
1642 if (pinfo->pseudo_header->irda.pkttype == IRDA_MISSED_MSG)
1644 col_set_str(pinfo->cinfo, COL_INFO, "WARNING: Missed one or more messages while capturing!");
1646 else
1648 guint length;
1649 char buf[256];
1652 length = tvb_length(tvb);
1653 if (length > sizeof(buf)-1)
1654 length = sizeof(buf)-1;
1655 tvb_memcpy(tvb, buf, 0, length);
1656 buf[length] = 0;
1657 if (buf[length-1] == '\n')
1658 buf[length-1] = 0;
1659 else if (buf[length-2] == '\n')
1660 buf[length-2] = 0;
1662 col_add_str(pinfo->cinfo, COL_INFO, buf);
1665 if (root)
1667 proto_item* ti = proto_tree_add_item(root, proto_log, tvb, 0, -1, ENC_NA);
1668 proto_tree* tree = proto_item_add_subtree(ti, ett_log);
1670 if (pinfo->pseudo_header->irda.pkttype == IRDA_MISSED_MSG)
1671 proto_tree_add_item(tree, hf_log_missed, tvb, 0, 0, ENC_NA);
1672 else
1673 proto_tree_add_item(tree, hf_log_msg, tvb, 0, -1, ENC_ASCII|ENC_NA);
1679 * Dissect IrLAP
1681 static void dissect_irlap(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
1683 int offset = 0;
1684 guint8 a, c;
1685 gboolean is_response;
1686 char addr[9];
1687 proto_item* ti = NULL;
1688 proto_tree* tree = NULL;
1689 proto_tree* i_tree = NULL;
1690 guint32 saddr, daddr;
1691 guint8 ca;
1693 /* Make entries in Protocol column on summary display */
1694 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrLAP");
1696 /* Clear Info column */
1697 col_clear(pinfo->cinfo, COL_INFO);
1699 /* set direction column */
1700 switch (pinfo->pseudo_header->irda.pkttype)
1702 case IRDA_OUTGOING:
1703 col_set_str(pinfo->cinfo, COL_IF_DIR, "Out");
1704 break;
1706 case IRDA_INCOMING:
1707 col_set_str(pinfo->cinfo, COL_IF_DIR, "In");
1708 break;
1711 /* decode values used for demuxing */
1712 a = tvb_get_guint8(tvb, 0);
1714 /* save connection address field in pinfo */
1715 pinfo->circuit_id = a;
1717 /* initially set address columns to connection address */
1718 g_snprintf(addr, sizeof(addr)-1, "0x%02X", a >> 1);
1719 col_add_str(pinfo->cinfo, COL_DEF_SRC, addr);
1720 col_add_str(pinfo->cinfo, COL_DEF_DST, addr);
1722 if (root)
1724 proto_tree* a_tree;
1725 proto_item* addr_item;
1727 /* create display subtree for the protocol */
1728 ti = proto_tree_add_item(root, proto_irlap, tvb, 0, -1, ENC_NA);
1729 tree = proto_item_add_subtree(ti, ett_irlap);
1731 /* create subtree for the address field */
1732 ti = proto_tree_add_item(tree, hf_lap_a, tvb, offset, 1, ENC_BIG_ENDIAN);
1733 a_tree = proto_item_add_subtree(ti, ett_lap_a);
1734 proto_tree_add_item(a_tree, hf_lap_a_cr, tvb, offset, 1, ENC_BIG_ENDIAN);
1735 addr_item = proto_tree_add_item(a_tree, hf_lap_a_address, tvb, offset, 1, ENC_BIG_ENDIAN);
1736 switch (a & ~CMD_FRAME)
1738 case 0:
1739 proto_item_append_text(addr_item, " (NULL Address)");
1740 break;
1741 case 0xFE:
1742 proto_item_append_text(addr_item, " (Broadcast)");
1743 break;
1746 is_response = ((a & CMD_FRAME) == 0);
1747 offset++;
1749 /* process the control field */
1750 c = dissect_xdlc_control(tvb, 1, pinfo, tree, hf_lap_c,
1751 ett_lap_c, &irlap_cf_items, NULL, lap_c_u_cmd_abbr_vals,
1752 lap_c_u_rsp_abbr_vals, is_response, FALSE, FALSE);
1753 offset++;
1755 if ((c & XDLC_I_MASK) == XDLC_I) {
1756 /* I frame */
1757 proto_item_set_len(tree, offset);
1758 tvb = tvb_new_subset_remaining(tvb, offset);
1759 dissect_irlmp(tvb, pinfo, root);
1760 return;
1763 if ((c & 0x03) == XDLC_U) {
1764 /* U frame */
1765 switch (c & XDLC_U_MODIFIER_MASK)
1767 case XDLC_SNRM:
1768 if (root)
1770 ti = proto_tree_add_item(tree, hf_lap_i, tvb, offset, -1, ENC_NA);
1771 i_tree = proto_item_add_subtree(ti, ett_lap_i);
1774 saddr = tvb_get_letohl(tvb, offset);
1775 if (!is_response)
1777 col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr);
1779 if (root)
1780 proto_tree_add_uint(i_tree, hf_snrm_saddr, tvb, offset, 4, saddr);
1781 offset += 4;
1783 daddr = tvb_get_letohl(tvb, offset);
1784 if (!is_response)
1786 col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr);
1788 if (root)
1789 proto_tree_add_uint(i_tree, hf_snrm_daddr, tvb, offset, 4, daddr);
1790 offset += 4;
1792 ca = tvb_get_guint8(tvb, offset);
1793 if (!is_response)
1795 col_append_fstr(pinfo->cinfo, COL_INFO, ", ca=0x%02X",
1796 ca >> 1);
1798 if (root)
1799 proto_tree_add_uint(i_tree, hf_snrm_ca, tvb, offset, 1, ca >> 1);
1800 offset++;
1802 offset = dissect_negotiation(tvb, i_tree, offset);
1803 if (root)
1804 proto_item_set_end(ti, tvb, offset);
1805 break;
1807 case IRDA_XID_CMD:
1808 tvb = tvb_new_subset_remaining(tvb, offset);
1809 dissect_xid(tvb, pinfo, root, tree, TRUE);
1810 return;
1812 case XDLC_UA:
1813 if (tvb_reported_length_remaining(tvb, offset) > 0)
1815 if (root)
1817 ti = proto_tree_add_item(tree, hf_lap_i, tvb, offset, -1, ENC_NA);
1818 i_tree = proto_item_add_subtree(ti, ett_lap_i);
1821 saddr = tvb_get_letohl(tvb, offset);
1822 col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr);
1823 if (root)
1824 proto_tree_add_uint(i_tree, hf_ua_saddr, tvb, offset, 4, saddr);
1825 offset += 4;
1827 daddr = tvb_get_letohl(tvb, offset);
1828 col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr);
1829 if (root)
1830 proto_tree_add_uint(i_tree, hf_ua_daddr, tvb, offset, 4, daddr);
1831 offset += 4;
1833 offset = dissect_negotiation(tvb, i_tree, offset);
1834 if (root)
1835 proto_item_set_end(ti, tvb, offset);
1837 break;
1839 case XDLC_XID:
1840 tvb = tvb_new_subset_remaining(tvb, offset);
1841 dissect_xid(tvb, pinfo, root, tree, FALSE);
1842 return;
1846 /* If any bytes remain, send it to the generic data dissector */
1847 if (tvb_reported_length_remaining(tvb, offset) > 0)
1849 tvb = tvb_new_subset_remaining(tvb, offset);
1850 call_dissector(data_handle, tvb, pinfo, root);
1856 * Dissect IrDA protocol
1858 static void dissect_irda(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
1860 /* load the display labels */
1861 pinfo->current_proto = "IrDA";
1863 /* check if log message */
1864 if ((pinfo->pseudo_header->irda.pkttype & IRDA_CLASS_MASK) == IRDA_CLASS_LOG)
1866 dissect_log(tvb, pinfo, root);
1867 return;
1871 dissect_irlap(tvb, pinfo, root);
1876 * Register the protocol with Wireshark
1877 * This format is required because a script is used to build the C function
1878 * that calls all the protocol registrations.
1880 void proto_register_irda(void)
1882 guint i;
1884 /* Setup list of header fields */
1885 static hf_register_info hf_lap[] = {
1886 { &hf_lap_a,
1887 { "Address Field", "irlap.a",
1888 FT_UINT8, BASE_HEX, NULL, 0,
1889 NULL, HFILL }},
1890 { &hf_lap_a_cr,
1891 { "C/R", "irlap.a.cr",
1892 FT_BOOLEAN, 8, TFS(&lap_cr_vals), CMD_FRAME,
1893 NULL, HFILL }},
1894 { &hf_lap_a_address,
1895 { "Address", "irlap.a.address",
1896 FT_UINT8, BASE_HEX, NULL, ~CMD_FRAME,
1897 NULL, HFILL }},
1898 { &hf_lap_c,
1899 { "Control Field", "irlap.c",
1900 FT_UINT8, BASE_HEX, NULL, 0,
1901 NULL, HFILL }},
1902 { &hf_lap_c_nr,
1903 { "N(R)", "irlap.c.n_r",
1904 FT_UINT8, BASE_DEC, NULL, XDLC_N_R_MASK,
1905 NULL, HFILL }},
1906 { &hf_lap_c_ns,
1907 { "N(S)", "irlap.c.n_s",
1908 FT_UINT8, BASE_DEC, NULL, XDLC_N_S_MASK,
1909 NULL, HFILL }},
1910 { &hf_lap_c_p,
1911 { "Poll", "irlap.c.p",
1912 FT_BOOLEAN, 8, TFS(&set_notset), XDLC_P_F,
1913 NULL, HFILL }},
1914 { &hf_lap_c_f,
1915 { "Final", "irlap.c.f",
1916 FT_BOOLEAN, 8, TFS(&set_notset), XDLC_P_F,
1917 NULL, HFILL }},
1918 { &hf_lap_c_s,
1919 { "Supervisory frame type", "irlap.c.s_ftype",
1920 FT_UINT8, BASE_HEX, VALS(lap_c_s_vals), XDLC_S_FTYPE_MASK,
1921 NULL, HFILL }},
1922 { &hf_lap_c_u_cmd,
1923 { "Command", "irlap.c.u_modifier_cmd",
1924 FT_UINT8, BASE_HEX, VALS(lap_c_u_cmd_vals), XDLC_U_MODIFIER_MASK,
1925 NULL, HFILL }},
1926 { &hf_lap_c_u_rsp,
1927 { "Response", "irlap.c.u_modifier_resp",
1928 FT_UINT8, BASE_HEX, VALS(lap_c_u_rsp_vals), XDLC_U_MODIFIER_MASK,
1929 NULL, HFILL }},
1930 { &hf_lap_c_i,
1931 { "Frame Type", "irlap.c.ftype",
1932 FT_UINT8, BASE_HEX, VALS(lap_c_ftype_vals), XDLC_I_MASK,
1933 NULL, HFILL }},
1934 { &hf_lap_c_s_u,
1935 { "Frame Type", "irlap.c.ftype",
1936 FT_UINT8, BASE_HEX, VALS(lap_c_ftype_vals), XDLC_S_U_MASK,
1937 NULL, HFILL }},
1938 { &hf_lap_i,
1939 { "Information Field", "irlap.i",
1940 FT_NONE, BASE_NONE, NULL, 0,
1941 NULL, HFILL }},
1942 { &hf_snrm_saddr,
1943 { "Source Device Address", "irlap.snrm.saddr",
1944 FT_UINT32, BASE_HEX, NULL, 0,
1945 NULL, HFILL }},
1946 { &hf_snrm_daddr,
1947 { "Destination Device Address", "irlap.snrm.daddr",
1948 FT_UINT32, BASE_HEX, NULL, 0,
1949 NULL, HFILL }},
1950 { &hf_snrm_ca,
1951 { "Connection Address", "irlap.snrm.ca",
1952 FT_UINT8, BASE_HEX, NULL, 0,
1953 NULL, HFILL }},
1954 { &hf_negotiation_param,
1955 { "Negotiation Parameter", "irlap.negotiation",
1956 FT_NONE, BASE_NONE, NULL, 0,
1957 NULL, HFILL }},
1958 { &hf_param_pi,
1959 { "Parameter Identifier", "irlap.pi",
1960 FT_UINT8, BASE_HEX, NULL, 0,
1961 NULL, HFILL }},
1962 { &hf_param_pl,
1963 { "Parameter Length", "irlap.pl",
1964 FT_UINT8, BASE_HEX, NULL, 0,
1965 NULL, HFILL }},
1966 { &hf_param_pv,
1967 { "Parameter Value", "irlap.pv",
1968 FT_BYTES, BASE_NONE, NULL, 0,
1969 NULL, HFILL }},
1970 { &hf_ua_saddr,
1971 { "Source Device Address", "irlap.ua.saddr",
1972 FT_UINT32, BASE_HEX, NULL, 0,
1973 NULL, HFILL }},
1974 { &hf_ua_daddr,
1975 { "Destination Device Address", "irlap.ua.daddr",
1976 FT_UINT32, BASE_HEX, NULL, 0,
1977 NULL, HFILL }},
1978 { &hf_xid_ident,
1979 { "Format Identifier", "irlap.xid.fi",
1980 FT_UINT8, BASE_HEX, NULL, 0,
1981 NULL, HFILL }},
1982 { &hf_xid_saddr,
1983 { "Source Device Address", "irlap.xid.saddr",
1984 FT_UINT32, BASE_HEX, NULL, 0,
1985 NULL, HFILL }},
1986 { &hf_xid_daddr,
1987 { "Destination Device Address", "irlap.xid.daddr",
1988 FT_UINT32, BASE_HEX, NULL, 0,
1989 NULL, HFILL }},
1990 { &hf_xid_flags,
1991 { "Discovery Flags", "irlap.xid.flags",
1992 FT_UINT8, BASE_HEX, NULL, 0,
1993 NULL, HFILL }},
1994 { &hf_xid_s,
1995 { "Number of Slots", "irlap.xid.s",
1996 FT_UINT8, BASE_DEC, VALS(xid_slot_numbers), S_MASK,
1997 NULL, HFILL }},
1998 { &hf_xid_conflict,
1999 { "Conflict", "irlap.xid.conflict",
2000 FT_BOOLEAN, 8, TFS(&set_notset), CONFLICT,
2001 NULL, HFILL }},
2002 { &hf_xid_slotnr,
2003 { "Slot Number", "irlap.xid.slotnr",
2004 FT_UINT8, BASE_DEC, NULL, 0,
2005 NULL, HFILL }},
2006 { &hf_xid_version,
2007 { "Version Number", "irlap.xid.version",
2008 FT_UINT8, BASE_HEX, NULL, 0,
2009 NULL, HFILL }}
2012 static hf_register_info hf_log[] = {
2013 { &hf_log_msg,
2014 { "Message", "log.msg",
2015 FT_STRING, BASE_NONE, NULL, 0,
2016 NULL, HFILL }},
2017 { &hf_log_missed,
2018 { "WARNING: Missed one or more messages while capturing!", "log.missed",
2019 FT_NONE, BASE_NONE, NULL, 0,
2020 NULL, HFILL }}
2023 static hf_register_info hf_lmp[] = {
2024 { &hf_lmp_xid_hints,
2025 { "Service Hints", "irlmp.xid.hints",
2026 FT_BYTES, BASE_NONE, NULL, 0,
2027 NULL, HFILL }},
2028 { &hf_lmp_xid_charset,
2029 { "Character Set", "irlmp.xid.charset",
2030 FT_UINT8, BASE_HEX, NULL, 0,
2031 NULL, HFILL }},
2032 { &hf_lmp_xid_name,
2033 { "Device Nickname", "irlmp.xid.name",
2034 FT_STRING, BASE_NONE, NULL, 0,
2035 NULL, HFILL }},
2036 { &hf_lmp_xid_name_no_ascii,
2037 { "Device Nickname (unsupported character set)", "irlmp.xid.name",
2038 FT_BYTES, BASE_NONE, NULL, 0,
2039 NULL, HFILL }},
2040 { &hf_lmp_dst,
2041 { "Destination", "irlmp.dst",
2042 FT_UINT8, BASE_HEX, NULL, 0,
2043 NULL, HFILL }},
2044 { &hf_lmp_dst_control,
2045 { "Control Bit", "irlmp.dst.c",
2046 FT_BOOLEAN, 8, TFS(&set_notset), CONTROL_BIT,
2047 NULL, HFILL }},
2048 { &hf_lmp_dst_lsap,
2049 { "Destination LSAP", "irlmp.dst.lsap",
2050 FT_UINT8, BASE_DEC, NULL, ~CONTROL_BIT,
2051 NULL, HFILL }},
2052 { &hf_lmp_src,
2053 { "Source", "irlmp.src",
2054 FT_UINT8, BASE_HEX, NULL, 0,
2055 NULL, HFILL }},
2056 { &hf_lmp_src_r,
2057 { "reserved", "irlmp.src.r",
2058 FT_UINT8, BASE_DEC, NULL, RESERVED_BIT,
2059 NULL, HFILL }},
2060 { &hf_lmp_src_lsap,
2061 { "Source LSAP", "irlmp.src.lsap",
2062 FT_UINT8, BASE_DEC, NULL, ~RESERVED_BIT,
2063 NULL, HFILL }},
2064 { &hf_lmp_opcode,
2065 { "Opcode", "irlmp.opcode",
2066 FT_UINT8, BASE_HEX, VALS(lmp_opcode_vals), 0x0,
2067 NULL, HFILL }},
2068 { &hf_lmp_rsvd,
2069 { "Reserved", "irlmp.rsvd",
2070 FT_UINT8, BASE_HEX, NULL, 0x0,
2071 NULL, HFILL }},
2072 { &hf_lmp_reason,
2073 { "Reason", "irlmp.reason",
2074 FT_UINT8, BASE_HEX, VALS(lmp_reason_vals), 0x0,
2075 NULL, HFILL }},
2076 { &hf_lmp_mode,
2077 { "Mode", "irlmp.mode",
2078 FT_UINT8, BASE_HEX, VALS(lmp_mode_vals), 0x0,
2079 NULL, HFILL }},
2080 { &hf_lmp_status,
2081 { "Status", "irlmp.status",
2082 FT_UINT8, BASE_HEX, VALS(lmp_status_vals), 0x0,
2083 NULL, HFILL }}
2086 static hf_register_info hf_iap[] = {
2087 { &hf_iap_ctl,
2088 { "Control Field", "iap.ctl",
2089 FT_UINT8, BASE_HEX, NULL, 0,
2090 NULL, HFILL }},
2091 { &hf_iap_ctl_lst,
2092 { "Last Frame", "iap.ctl.lst",
2093 FT_BOOLEAN, 8, TFS(&set_notset), IAP_LST,
2094 NULL, HFILL }},
2095 { &hf_iap_ctl_ack,
2096 { "Acknowledge", "iap.ctl.ack",
2097 FT_BOOLEAN, 8, TFS(&set_notset), IAP_ACK,
2098 NULL, HFILL }},
2099 { &hf_iap_ctl_opcode,
2100 { "Opcode", "iap.ctl.opcode",
2101 FT_UINT8, BASE_HEX, VALS(iap_opcode_vals), IAP_OP,
2102 NULL, HFILL }},
2103 { &hf_iap_class_name,
2104 { "Class Name", "iap.classname",
2105 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2106 NULL, HFILL }},
2107 { &hf_iap_attr_name,
2108 { "Attribute Name", "iap.attrname",
2109 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2110 NULL, HFILL }},
2111 { &hf_iap_return,
2112 { "Return", "iap.return",
2113 FT_UINT8, BASE_HEX, VALS(iap_return_vals), 0x0,
2114 NULL, HFILL }},
2115 { &hf_iap_list_len,
2116 { "List Length", "iap.listlen",
2117 FT_UINT16, BASE_DEC, NULL, 0x0,
2118 NULL, HFILL }},
2119 { &hf_iap_list_entry,
2120 { "List Entry", "iap.listentry",
2121 FT_NONE, BASE_NONE, NULL, 0x0,
2122 NULL, HFILL }},
2123 { &hf_iap_obj_id,
2124 { "Object Identifier", "iap.objectid",
2125 FT_UINT16, BASE_HEX, NULL, 0x0,
2126 NULL, HFILL }},
2127 { &hf_iap_attr_type,
2128 { "Type", "iap.attrtype",
2129 FT_UINT8, BASE_DEC, VALS(iap_attr_type_vals), 0x0,
2130 NULL, HFILL }},
2131 { &hf_iap_int,
2132 { "Value", "iap.int",
2133 FT_INT32, BASE_DEC, NULL, 0x0,
2134 NULL, HFILL }},
2135 { &hf_iap_seq_len,
2136 { "Sequence Length", "iap.seqlen",
2137 FT_UINT16, BASE_DEC, NULL, 0x0,
2138 NULL, HFILL }},
2139 { &hf_iap_oct_seq,
2140 { "Sequence", "iap.octseq",
2141 FT_BYTES, BASE_NONE, NULL, 0x0,
2142 NULL, HFILL }},
2143 { &hf_iap_char_set,
2144 { "Character Set", "iap.charset",
2145 FT_UINT8, BASE_HEX, NULL, 0x0,
2146 NULL, HFILL }},
2147 { &hf_iap_string,
2148 { "String", "iap.string",
2149 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2150 NULL, HFILL }},
2151 { &hf_iap_invaloctet,
2152 { "Malformed IAP result: \"", "iap.invaloctet",
2153 FT_NONE, BASE_NONE, NULL, 0,
2154 NULL, HFILL }},
2155 { &hf_iap_invallsap,
2156 { "Malformed IAP result: \"", "iap.invallsap",
2157 FT_NONE, BASE_NONE, NULL, 0,
2158 NULL, HFILL }}
2161 static hf_register_info hf_ttp[] = {
2162 { &hf_ttp_p,
2163 { "Parameter Bit", "ttp.p",
2164 FT_BOOLEAN, 8, TFS(&set_notset), TTP_PARAMETERS,
2165 NULL, HFILL }},
2166 { &hf_ttp_icredit,
2167 { "Initial Credit", "ttp.icredit",
2168 FT_UINT8, BASE_DEC, NULL, ~TTP_PARAMETERS,
2169 NULL, HFILL }},
2170 { &hf_ttp_m,
2171 { "More Bit", "ttp.m",
2172 FT_BOOLEAN, 8, TFS(&set_notset), TTP_MORE,
2173 NULL, HFILL }},
2174 { &hf_ttp_dcredit,
2175 { "Delta Credit", "ttp.dcredit",
2176 FT_UINT8, BASE_DEC, NULL, ~TTP_MORE,
2177 NULL, HFILL }}
2180 /* Setup protocol subtree arrays */
2181 static gint* ett[] = {
2182 &ett_irlap,
2183 &ett_lap_a,
2184 &ett_lap_c,
2185 &ett_lap_i,
2186 &ett_xid_flags,
2187 &ett_log,
2188 &ett_irlmp,
2189 &ett_lmp_dst,
2190 &ett_lmp_src,
2191 &ett_iap,
2192 &ett_iap_ctl,
2193 &ett_ttp
2196 gint* ett_p[MAX_PARAMETERS];
2197 gint* ett_iap_e[MAX_IAP_ENTRIES];
2200 /* Register protocol names and descriptions */
2201 proto_irlap = proto_register_protocol("IrDA Link Access Protocol", "IrLAP", "irlap");
2202 proto_log = proto_register_protocol("Log Message", "Log", "log");
2203 proto_irlmp = proto_register_protocol("IrDA Link Management Protocol", "IrLMP", "irlmp");
2204 proto_iap = proto_register_protocol("Information Access Protocol", "IAP", "iap");
2205 proto_ttp = proto_register_protocol("Tiny Transport Protocol", "TTP", "ttp");
2207 /* Register the dissector */
2208 register_dissector("irda", dissect_irda, proto_irlap);
2210 /* Required function calls to register the header fields */
2211 proto_register_field_array(proto_irlap, hf_lap, array_length(hf_lap));
2212 proto_register_field_array(proto_log, hf_log, array_length(hf_log));
2213 proto_register_field_array(proto_irlmp, hf_lmp, array_length(hf_lmp));
2214 proto_register_field_array(proto_iap, hf_iap, array_length(hf_iap));
2215 proto_register_field_array(proto_ttp, hf_ttp, array_length(hf_ttp));
2217 /* Register subtrees */
2218 proto_register_subtree_array(ett, array_length(ett));
2219 for (i = 0; i < MAX_PARAMETERS; i++)
2221 ett_param[i] = -1;
2222 ett_p[i] = &ett_param[i];
2224 proto_register_subtree_array(ett_p, MAX_PARAMETERS);
2225 for (i = 0; i < MAX_IAP_ENTRIES; i++)
2227 ett_iap_entry[i] = -1;
2228 ett_iap_e[i] = &ett_iap_entry[i];
2230 proto_register_subtree_array(ett_iap_e, MAX_IAP_ENTRIES);
2234 /* If this dissector uses sub-dissector registration add a registration routine.
2235 This format is required because a script is used to find these routines and
2236 create the code that calls these routines.
2239 void proto_reg_handoff_irda(void)
2241 dissector_handle_t irda_handle;
2243 irda_handle = find_dissector("irda");
2244 dissector_add_uint("wtap_encap", WTAP_ENCAP_IRDA, irda_handle);
2245 dissector_add_uint("sll.ltype", LINUX_SLL_P_IRDA_LAP, irda_handle);
2246 data_handle = find_dissector("data");