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 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <epan/packet.h>
21 #include <epan/address_types.h>
22 #include <epan/to_str.h>
23 #include <epan/strutil.h>
24 #include <epan/conversation.h>
25 #include <epan/xdlc.h>
27 #include <wsutil/array.h>
28 #include <wiretap/wtap.h>
30 #include <epan/dissectors/packet-sll.h>
31 #include "irda-appl.h"
34 * This plugin dissects infrared data transmissions as defined by IrDA
37 * https://web.archive.org/web/20040405053146/http://www.irda.org/standards/specifications.asp
41 * https://archive.org/search?query=creator%3A%22Infrared+Data+Association%22
43 * for various IrDA specifications, including a zip archive of the IrPHY
44 * 1.4, IrLAP 1.1, IrLMP 1.1, IrDA Tiny TP 1.1, and IrDA Point and Shoot
45 * Profile 1.1 and Test Specification 1.0 at
47 * https://web.archive.org/web/20040405053146/http://www.irda.org/standards/pubs/IrData.zip
49 * or the the IrLAP 1.1 specification at
51 * https://archive.org/details/ir-lap-11
53 * The plugin operates both offline with libpcap files and online on supported
54 * platforms. Live dissection is currently available for Linux-IrDA
55 * (irda.sourceforge.net) and for Windows if the Linux-IrDA port IrCOMM2k
56 * (www.ircomm2k.de) is installed.
63 /* Frame types and templates */
67 * XXX - the IrDA spec gives XID as 0x2c; HDLC (and other HDLC-derived
68 * protocolc) use 0xAC.
70 #define IRDA_XID_CMD 0x2c /* Exchange Station Identification */
72 #define CMD_FRAME 0x01
73 #define RSP_FRAME 0x00
79 /* Negotiation Parameters */
80 #define PI_BAUD_RATE 0x01
81 #define PI_MAX_TURN_TIME 0x82
82 #define PI_DATA_SIZE 0x83
83 #define PI_WINDOW_SIZE 0x84
84 #define PI_ADD_BOFS 0x85
85 #define PI_MIN_TURN_TIME 0x86
86 #define PI_LINK_DISC 0x08
93 /* IrLMP frame opcodes */
94 #define CONNECT_CMD 0x01
95 #define CONNECT_CNF 0x81
96 #define DISCONNECT 0x02
97 #define ACCESSMODE_CMD 0x03
98 #define ACCESSMODE_CNF 0x83
100 #define CONTROL_BIT 0x80
101 #define RESERVED_BIT 0x80
104 #define LSAP_MASK 0x7f
105 #define LSAP_IAS 0x00
106 #define LSAP_ANY 0xff
107 #define LSAP_MAX 0x6f /* 0x70-0x7f are reserved */
108 #define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */
116 #define GET_INFO_BASE 0x01
117 #define GET_OBJECTS 0x02
118 #define GET_VALUE 0x03
119 #define GET_VALUE_BY_CLASS 0x04
120 #define GET_OBJECT_INFO 0x05
121 #define GET_ATTRIB_NAMES 0x06
127 #define IAS_SUCCESS 0
128 #define IAS_CLASS_UNKNOWN 1
129 #define IAS_ATTRIB_UNKNOWN 2
130 #define IAS_ATTR_TOO_LONG 3
131 #define IAS_DISCONNECT 10
132 #define IAS_UNSUPPORTED 0xFF
139 #define TTP_PARAMETERS 0x80
140 #define TTP_MORE 0x80
142 void proto_reg_handoff_irda(void);
143 void proto_register_irda(void);
145 /* Initialize the protocol and registered fields */
146 static int proto_irlap
;
148 static int hf_lap_a_cr
;
149 static int hf_lap_a_address
;
151 static int hf_lap_c_nr
;
152 static int hf_lap_c_ns
;
153 static int hf_lap_c_p
;
154 static int hf_lap_c_f
;
155 static int hf_lap_c_s
;
156 static int hf_lap_c_u_cmd
;
157 static int hf_lap_c_u_rsp
;
158 static int hf_lap_c_i
;
159 static int hf_lap_c_s_u
;
161 static int hf_snrm_saddr
;
162 static int hf_snrm_daddr
;
163 static int hf_snrm_ca
;
164 static int hf_ua_saddr
;
165 static int hf_ua_daddr
;
166 static int hf_negotiation_param
;
167 static int hf_param_pi
;
168 static int hf_param_pl
;
169 static int hf_param_pv
;
170 static int hf_xid_ident
;
171 static int hf_xid_saddr
;
172 static int hf_xid_daddr
;
173 static int hf_xid_flags
;
175 static int hf_xid_conflict
;
176 static int hf_xid_slotnr
;
177 static int hf_xid_version
;
179 static int proto_irlmp
;
180 static int hf_lmp_xid_hints
;
181 static int hf_lmp_xid_charset
;
182 static int hf_lmp_xid_name
;
183 static int hf_lmp_xid_name_no_encoding
;
184 static int hf_lmp_dst
;
185 static int hf_lmp_dst_control
;
186 static int hf_lmp_dst_lsap
;
187 static int hf_lmp_src
;
188 static int hf_lmp_src_r
;
189 static int hf_lmp_src_lsap
;
190 static int hf_lmp_opcode
;
191 static int hf_lmp_rsvd
;
192 static int hf_lmp_reason
;
193 static int hf_lmp_mode
;
194 static int hf_lmp_status
;
196 static int proto_iap
;
197 static int hf_iap_ctl
;
198 static int hf_iap_ctl_lst
;
199 static int hf_iap_ctl_ack
;
200 static int hf_iap_ctl_opcode
;
201 static int hf_iap_class_name
;
202 static int hf_iap_attr_name
;
203 static int hf_iap_return
;
204 static int hf_iap_list_len
;
205 static int hf_iap_list_entry
;
206 static int hf_iap_obj_id
;
207 static int hf_iap_attr_type
;
208 static int hf_iap_int
;
209 static int hf_iap_seq_len
;
210 static int hf_iap_oct_seq
;
211 static int hf_iap_char_set
;
212 static int hf_iap_string
;
213 static int hf_iap_invaloctet
;
214 static int hf_iap_invallsap
;
216 static int proto_ttp
;
218 static int hf_ttp_icredit
;
220 static int hf_ttp_dcredit
;
222 static int proto_log
;
223 static int hf_log_msg
;
224 static int hf_log_missed
;
226 /* Initialize the subtree pointers */
227 static int ett_irlap
;
228 static int ett_lap_a
;
229 static int ett_lap_c
;
230 static int ett_lap_i
;
231 static int ett_xid_flags
;
233 static int ett_irlmp
;
234 static int ett_lmp_dst
;
235 static int ett_lmp_src
;
237 static int ett_iap_ctl
;
240 #define MAX_PARAMETERS 32
241 static int ett_param
[MAX_PARAMETERS
];
243 static int ett_iap_entry
[MAX_IAP_ENTRIES
];
245 static int irda_address_type
= -1;
247 static dissector_handle_t irda_handle
;
249 static const xdlc_cf_items irlap_cf_items
= {
261 /* IAP conversation type */
262 typedef struct iap_conversation
{
263 struct iap_conversation
* pnext
;
264 uint32_t iap_query_frame
;
265 ias_attr_dissector_t
* pattr_dissector
;
266 } iap_conversation_t
;
268 /* IrLMP conversation type */
269 typedef struct lmp_conversation
{
270 struct lmp_conversation
* pnext
;
271 uint32_t iap_result_frame
;
273 dissector_handle_t dissector
;
274 } lmp_conversation_t
;
276 static const true_false_string lap_cr_vals
= {
281 static const true_false_string set_notset
= {
286 static const value_string lap_c_ftype_vals
[] = {
287 { XDLC_I
, "Information frame" },
288 { XDLC_S
, "Supervisory frame" },
289 { XDLC_U
, "Unnumbered frame" },
293 static const value_string lap_c_u_cmd_abbr_vals
[] = {
294 { XDLC_SNRM
, "SNRM" },
295 { XDLC_DISC
, "DISC" },
297 { IRDA_XID_CMD
, "XID" },
298 { XDLC_TEST
, "TEST" },
302 static const value_string lap_c_u_rsp_abbr_vals
[] = {
303 { XDLC_SNRM
, "RNRM" },
305 { XDLC_FRMR
, "FRMR" },
310 { XDLC_TEST
, "TEST" },
314 static const value_string lap_c_u_cmd_vals
[] = {
315 { XDLC_SNRM
>>2, "Set Normal Response Mode" },
316 { XDLC_DISC
>>2, "Disconnect" },
317 { XDLC_UI
>>2, "Unnumbered Information" },
318 { IRDA_XID_CMD
>>2, "Exchange Station Identification" },
319 { XDLC_TEST
>>2, "Test" },
323 static const value_string lap_c_u_rsp_vals
[] = {
324 { XDLC_SNRM
>>2, "Request Normal Response Mode" },
325 { XDLC_UA
>>2, "Unnumbered Acknowledge" },
326 { XDLC_FRMR
>>2, "Frame Reject" },
327 { XDLC_DM
>>2, "Disconnect Mode" },
328 { XDLC_RD
>>2, "Request Disconnect" },
329 { XDLC_UI
>>2, "Unnumbered Information" },
330 { XDLC_XID
>>2, "Exchange Station Identification" },
331 { XDLC_TEST
>>2, "Test" },
335 static const value_string lap_c_s_vals
[] = {
336 { XDLC_RR
>>2, "Receiver ready" },
337 { XDLC_RNR
>>2, "Receiver not ready" },
338 { XDLC_REJ
>>2, "Reject" },
339 { XDLC_SREJ
>>2, "Selective reject" },
343 static const value_string xid_slot_numbers
[] = {
344 /* Number of XID slots */
352 static const value_string lmp_opcode_vals
[] = {
353 /* IrLMP frame opcodes */
354 { CONNECT_CMD
, "Connect Command" },
355 { CONNECT_CNF
, "Connect Confirm" },
356 { DISCONNECT
, "Disconnect" },
357 { ACCESSMODE_CMD
, "Access Mode Command" },
358 { ACCESSMODE_CNF
, "Access Mode Confirm" },
362 static const value_string lmp_reason_vals
[] = {
363 /* IrLMP disconnect reasons */
364 { 0x01, "User Request" },
365 { 0x02, "Unexpected IrLAP Disconnect" },
366 { 0x03, "Failed to establish IrLAP connection" },
367 { 0x04, "IrLAP Reset" },
368 { 0x05, "Link Management Initiated Disconnect" },
369 { 0x06, "Data delivered on disconnected LSAP-Connection"},
370 { 0x07, "Non Responsive LM-MUX Client" },
371 { 0x08, "No available LM-MUX Client" },
372 { 0x09, "Connection Half Open" },
373 { 0x0A, "Illegal Source Address" },
374 { 0xFF, "Unspecified Disconnect Reason" },
378 static const value_string lmp_mode_vals
[] = {
380 { 0x00, "Multiplexed" },
381 { 0x01, "Exclusive" },
385 static const value_string lmp_status_vals
[] = {
389 { 0xFF, "Unsupported" },
393 #define LMP_CHARSET_ASCII 0
394 #define LMP_CHARSET_ISO_8859_1 1
395 #define LMP_CHARSET_ISO_8859_2 2
396 #define LMP_CHARSET_ISO_8859_3 3
397 #define LMP_CHARSET_ISO_8859_4 4
398 #define LMP_CHARSET_ISO_8859_5 5
399 #define LMP_CHARSET_ISO_8859_6 6
400 #define LMP_CHARSET_ISO_8859_7 7
401 #define LMP_CHARSET_ISO_8859_8 8
402 #define LMP_CHARSET_ISO_8859_9 9
403 #define LMP_CHARSET_UNICODE 0xFF /* UCS-2 (byte order?) */
405 static const value_string lmp_charset_vals
[] = {
406 /* IrLMP character set */
407 { LMP_CHARSET_ASCII
, "ASCII" },
408 { LMP_CHARSET_ISO_8859_1
, "ISO 8859-1" },
409 { LMP_CHARSET_ISO_8859_2
, "ISO 8859-2" },
410 { LMP_CHARSET_ISO_8859_3
, "ISO 8859-3" },
411 { LMP_CHARSET_ISO_8859_4
, "ISO 8859-4" },
412 { LMP_CHARSET_ISO_8859_5
, "ISO 8859-5" },
413 { LMP_CHARSET_ISO_8859_6
, "ISO 8859-6" },
414 { LMP_CHARSET_ISO_8859_7
, "ISO 8859-7" },
415 { LMP_CHARSET_ISO_8859_8
, "ISO 8859-8" },
416 { LMP_CHARSET_ISO_8859_9
, "ISO 8859-9" },
417 { LMP_CHARSET_UNICODE
, "Unicode" },
421 static const value_string iap_opcode_vals
[] = {
423 { GET_INFO_BASE
, "GetInfoBase" },
424 { GET_OBJECTS
, "GetObjects" },
425 { GET_VALUE
, "GetValue" },
426 { GET_VALUE_BY_CLASS
, "GetValueByClass" },
427 { GET_OBJECT_INFO
, "GetObjectInfo" },
428 { GET_ATTRIB_NAMES
, "GetAttributeNames" },
432 static const value_string iap_return_vals
[] = {
433 /* IrIAP Return-codes */
434 { IAS_SUCCESS
, "Success" },
435 { IAS_CLASS_UNKNOWN
, "Class/Object Unknown" },
436 { IAS_ATTRIB_UNKNOWN
, "Attribute Unknown" },
437 { IAS_ATTR_TOO_LONG
, "Attribute List Too Long" },
438 { IAS_DISCONNECT
, "Disconnect (Linux-IrDA only)" },
439 { IAS_UNSUPPORTED
, "Unsupported Optional Operation" },
443 static const value_string iap_attr_type_vals
[] = {
444 /* LM-IAS Attribute types */
445 { IAS_MISSING
, "Missing" },
446 { IAS_INTEGER
, "Integer" },
447 { IAS_OCT_SEQ
, "Octet Sequence" },
448 { IAS_STRING
, "String" },
452 static ias_attr_dissector_t device_attr_dissector
[] = {
453 /* Device attribute dissectors */
454 /* { "IrLMPSupport", xxx }, not implemented yet... */
458 /* IAS class dissectors */
459 static ias_class_dissector_t class_dissector
[] = { CLASS_DISSECTORS
};
463 * Dissect parameter tuple
465 unsigned dissect_param_tuple(tvbuff_t
* tvb
, proto_tree
* tree
, unsigned offset
)
467 uint8_t len
= tvb_get_uint8(tvb
, offset
+ 1);
470 proto_tree_add_item(tree
, hf_param_pi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
474 proto_tree_add_item(tree
, hf_param_pl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
480 proto_tree_add_item(tree
, hf_param_pv
, tvb
, offset
, len
, ENC_NA
);
491 static unsigned dissect_ttp(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, bool data
)
497 if (tvb_reported_length(tvb
) == 0)
500 /* Make entries in Protocol column on summary display */
501 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TTP");
503 head
= tvb_get_uint8(tvb
, offset
);
505 snprintf(buf
, 128, ", Credit=%d", head
& ~TTP_PARAMETERS
);
506 col_append_str(pinfo
->cinfo
, COL_INFO
, buf
);
510 /* create display subtree for the protocol */
511 proto_item
* ti
= proto_tree_add_item(root
, proto_ttp
, tvb
, 0, -1, ENC_NA
);
512 proto_tree
* tree
= proto_item_add_subtree(ti
, ett_ttp
);
516 proto_tree_add_item(tree
, hf_ttp_m
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
517 proto_tree_add_item(tree
, hf_ttp_dcredit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
522 proto_tree_add_item(tree
, hf_ttp_p
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
523 proto_tree_add_item(tree
, hf_ttp_icredit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
526 proto_item_set_len(tree
, offset
);
536 * Dissect IAP request
538 static void dissect_iap_request(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, uint8_t circuit_id
)
547 conversation_t
* conv
;
548 iap_conversation_t
* iap_conv
;
550 if (tvb_reported_length(tvb
) == 0)
553 /* Make entries in Protocol column on summary display */
554 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IAP");
556 op
= tvb_get_uint8(tvb
, offset
) & IAP_OP
;
560 case GET_VALUE_BY_CLASS
:
561 clen
= MIN(tvb_get_uint8(tvb
, offset
+ 1), 60);
562 alen
= MIN(tvb_get_uint8(tvb
, offset
+ 1 + 1 + clen
), 60);
564 /* create conversation entry */
565 src
= circuit_id
^ CMD_FRAME
;
566 set_address(&srcaddr
, irda_address_type
, 1, &src
);
568 set_address(&destaddr
, irda_address_type
, 1, &circuit_id
);
570 conv
= find_conversation(pinfo
->num
, &srcaddr
, &destaddr
, CONVERSATION_NONE
, pinfo
->srcport
, pinfo
->destport
, 0);
573 iap_conv
= (iap_conversation_t
*)conversation_get_proto_data(conv
, proto_iap
);
576 if (iap_conv
->iap_query_frame
== pinfo
->num
)
581 if (iap_conv
->pnext
== NULL
)
583 iap_conv
->pnext
= wmem_new(wmem_file_scope(), iap_conversation_t
);
584 iap_conv
= iap_conv
->pnext
;
587 iap_conv
= iap_conv
->pnext
;
592 conv
= conversation_new(pinfo
->num
, &srcaddr
, &destaddr
, CONVERSATION_NONE
, pinfo
->srcport
, pinfo
->destport
, 0);
593 iap_conv
= wmem_new(wmem_file_scope(), iap_conversation_t
);
594 conversation_add_proto_data(conv
, proto_iap
, (void*)iap_conv
);
598 iap_conv
->pnext
= NULL
;
599 iap_conv
->iap_query_frame
= pinfo
->num
;
600 iap_conv
->pattr_dissector
= NULL
;
603 char *class_name
= (char *) tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ 1 + 1, clen
, ENC_ASCII
|ENC_NA
);
604 char *attr_name
= (char *) tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ 1 + 1 + clen
+ 1, alen
, ENC_ASCII
|ENC_NA
);
606 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "GetValueByClass: \"%s\" \"%s\"",
607 format_text(pinfo
->pool
, (unsigned char *) class_name
, strlen(class_name
)),
608 format_text(pinfo
->pool
, (unsigned char *) attr_name
, strlen(attr_name
)));
610 /* Dissect IAP query if it is new */
615 /* Find the attribute dissector */
616 for (i
= 0; class_dissector
[i
].class_name
!= NULL
; i
++)
617 if (strcmp(class_name
, class_dissector
[i
].class_name
) == 0)
619 for (j
= 0; class_dissector
[i
].pattr_dissector
[j
].attr_name
!= NULL
; j
++)
620 if (strcmp(attr_name
, class_dissector
[i
].pattr_dissector
[j
].attr_name
) == 0)
622 iap_conv
->pattr_dissector
= &class_dissector
[i
].pattr_dissector
[j
];
632 /* create display subtree for the protocol */
633 proto_item
* ti
= proto_tree_add_item(root
, proto_iap
, tvb
, 0, -1, ENC_NA
);
634 proto_tree
* tree
= proto_item_add_subtree(ti
, ett_iap
);
636 proto_tree
* ctl_tree
;
639 ti
= proto_tree_add_item(tree
, hf_iap_ctl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
640 ctl_tree
= proto_item_add_subtree(ti
, ett_iap_ctl
);
641 proto_tree_add_item(ctl_tree
, hf_iap_ctl_lst
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
642 proto_tree_add_item(ctl_tree
, hf_iap_ctl_ack
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
643 proto_tree_add_item(ctl_tree
, hf_iap_ctl_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
648 case GET_VALUE_BY_CLASS
:
649 proto_tree_add_item(tree
, hf_iap_class_name
, tvb
, offset
, 1, ENC_ASCII
|ENC_BIG_ENDIAN
);
652 proto_tree_add_item(tree
, hf_iap_attr_name
, tvb
, offset
, 1, ENC_ASCII
|ENC_BIG_ENDIAN
);
662 case GET_VALUE_BY_CLASS
:
663 offset
+= 1 + clen
+ 1 + alen
;
668 /* If any bytes remain, send it to the generic data dissector */
669 tvb
= tvb_new_subset_remaining(tvb
, offset
);
670 call_data_dissector(tvb
, pinfo
, root
);
677 static void dissect_iap_result(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, uint8_t circuit_id
)
680 unsigned len
= tvb_reported_length(tvb
);
691 conversation_t
* conv
;
692 iap_conversation_t
* cur_iap_conv
;
693 iap_conversation_t
* iap_conv
= NULL
;
700 /* Make entries in Protocol column on summary display */
701 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IAP");
703 op
= tvb_get_uint8(tvb
, offset
) & IAP_OP
;
704 retcode
= tvb_get_uint8(tvb
, offset
+ 1);
706 src
= circuit_id
^ CMD_FRAME
;
707 set_address(&srcaddr
, irda_address_type
, 1, &src
);
709 set_address(&destaddr
, irda_address_type
, 1, &circuit_id
);
711 /* Find result value dissector */
712 conv
= find_conversation(pinfo
->num
, &srcaddr
, &destaddr
, CONVERSATION_NONE
, pinfo
->srcport
, pinfo
->destport
, 0);
717 iap_conv
= (iap_conversation_t
*)conversation_get_proto_data(conv
, proto_iap
);
718 while (iap_conv
&& (iap_conv
->iap_query_frame
>= num
))
719 iap_conv
= iap_conv
->pnext
;
723 cur_iap_conv
= iap_conv
->pnext
;
726 if ((cur_iap_conv
->iap_query_frame
< num
) &&
727 (cur_iap_conv
->iap_query_frame
> iap_conv
->iap_query_frame
))
729 iap_conv
= cur_iap_conv
;
732 cur_iap_conv
= cur_iap_conv
->pnext
;
737 col_set_str(pinfo
->cinfo
, COL_INFO
, "Result: ");
738 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(retcode
, iap_return_vals
, "0x%02X"));
742 case GET_VALUE_BY_CLASS
:
745 switch (tvb_get_uint8(tvb
, offset
+ 6))
748 col_append_str(pinfo
->cinfo
, COL_INFO
, ", Missing");
752 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Integer: %d", tvb_get_ntohl(tvb
, offset
+ 7));
756 snprintf(buf
, 300, ", %d Octets", tvb_get_ntohs(tvb
, offset
+ 7));
760 n
= tvb_get_uint8(tvb
, offset
+ 8);
761 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", \"%s\"", tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ 9, n
, ENC_ASCII
));
766 if (tvb_get_ntohs(tvb
, offset
+ 2) > 1)
767 col_append_str(pinfo
->cinfo
, COL_INFO
, ", ...");
774 /* create display subtree for the protocol */
775 proto_item
* ti
= proto_tree_add_item(root
, proto_iap
, tvb
, 0, -1, ENC_NA
);
776 proto_tree
* tree
= proto_item_add_subtree(ti
, ett_iap
);
778 proto_tree
* ctl_tree
;
779 proto_tree
* entry_tree
;
782 ti
= proto_tree_add_item(tree
, hf_iap_ctl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
783 ctl_tree
= proto_item_add_subtree(ti
, ett_iap_ctl
);
784 proto_tree_add_item(ctl_tree
, hf_iap_ctl_lst
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
785 proto_tree_add_item(ctl_tree
, hf_iap_ctl_ack
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
786 proto_tree_add_item(ctl_tree
, hf_iap_ctl_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
789 proto_tree_add_item(tree
, hf_iap_return
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
794 case GET_VALUE_BY_CLASS
:
797 list_len
= tvb_get_ntohs(tvb
, offset
);
799 proto_tree_add_item(tree
, hf_iap_list_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
802 while ((offset
< len
) && (n
< list_len
))
804 type
= tvb_get_uint8(tvb
, offset
+ 2);
812 attr_len
= tvb_get_ntohs(tvb
, offset
+ 2 + 1) + 2;
816 attr_len
= tvb_get_uint8(tvb
, offset
+ 2 + 1 + 1) + 2;
823 ti
= proto_tree_add_item(tree
, hf_iap_list_entry
, tvb
, offset
, 2 + 1 + attr_len
, ENC_NA
);
824 proto_item_append_text(ti
, "%d", n
+ 1);
825 entry_tree
= proto_item_add_subtree(ti
, ett_iap_entry
[n
]);
827 proto_tree_add_item(entry_tree
, hf_iap_obj_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
830 proto_tree_add_item(entry_tree
, hf_iap_attr_type
, 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
, circuit_id
))
839 proto_tree_add_item(entry_tree
, hf_iap_int
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
843 proto_tree_add_item(entry_tree
, hf_iap_seq_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
844 if (!iap_conv
|| !iap_conv
->pattr_dissector
||
845 !iap_conv
->pattr_dissector
->value_dissector(tvb
, offset
, pinfo
, entry_tree
,
846 n
, type
, circuit_id
))
847 proto_tree_add_item(entry_tree
, hf_iap_oct_seq
, tvb
, offset
+ 2,
848 attr_len
- 2, ENC_NA
);
852 proto_tree_add_item(entry_tree
, hf_iap_char_set
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
853 if (!iap_conv
|| !iap_conv
->pattr_dissector
||
854 !iap_conv
->pattr_dissector
->value_dissector(tvb
, offset
, pinfo
, entry_tree
,
855 n
, type
, circuit_id
))
856 proto_tree_add_item(entry_tree
, hf_iap_string
, tvb
, offset
+ 1, 1, ENC_ASCII
|ENC_BIG_ENDIAN
);
872 case GET_VALUE_BY_CLASS
:
880 type
= tvb_get_uint8(tvb
, offset
);
887 if (iap_conv
&& iap_conv
->pattr_dissector
)
888 iap_conv
->pattr_dissector
->value_dissector(tvb
, offset
, pinfo
, 0,
889 n
, type
, circuit_id
);
893 attr_len
= tvb_get_ntohs(tvb
, offset
) + 2;
894 if (iap_conv
&& iap_conv
->pattr_dissector
)
895 iap_conv
->pattr_dissector
->value_dissector(tvb
, offset
, pinfo
, 0,
896 n
, type
, circuit_id
);
900 attr_len
= tvb_get_uint8(tvb
, offset
+ 1) + 2;
901 if (iap_conv
&& iap_conv
->pattr_dissector
)
902 iap_conv
->pattr_dissector
->value_dissector(tvb
, offset
, pinfo
, 0,
903 n
, type
, circuit_id
);
918 /* If any bytes remain, send it to the generic data dissector */
919 tvb
= tvb_new_subset_remaining(tvb
, offset
);
920 call_data_dissector(tvb
, pinfo
, root
);
925 * Check if IAP result is octet sequence
927 bool check_iap_octet_result(tvbuff_t
* tvb
, proto_tree
* tree
, unsigned offset
,
928 const char* attr_name
, uint8_t attr_type
)
930 if (attr_type
!= IAS_OCT_SEQ
)
934 proto_item
* ti
= proto_tree_add_item(tree
, hf_iap_invaloctet
, tvb
, offset
, 0, ENC_NA
);
935 proto_item_append_text(ti
, "%s", attr_name
);
936 proto_item_append_text(ti
, "\" attribute must be octet sequence!");
947 * Check if IAP result is correct LsapSel
949 uint8_t check_iap_lsap_result(tvbuff_t
* tvb
, proto_tree
* tree
, unsigned offset
,
950 const char* attr_name
, uint8_t attr_type
)
955 if ((attr_type
!= IAS_INTEGER
) || ((lsap
= tvb_get_ntohl(tvb
, offset
)) < 0x01) ||
960 proto_item
* ti
= proto_tree_add_item(tree
, hf_iap_invallsap
, tvb
, offset
, 0, ENC_NA
);
961 proto_item_append_text(ti
, "%s", attr_name
);
962 proto_item_append_text(ti
, "\" attribute must be integer value between 0x01 and 0x6F!");
973 * Dissect IrDA application protocol
975 static void dissect_appl_proto(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, pdu_type_t pdu_type
, uint8_t circuit_id
)
981 conversation_t
* conv
;
982 lmp_conversation_t
* cur_lmp_conv
;
983 lmp_conversation_t
* lmp_conv
= NULL
;
987 src
= circuit_id
^ CMD_FRAME
;
988 set_address(&srcaddr
, irda_address_type
, 1, &src
);
990 set_address(&destaddr
, irda_address_type
, 1, &circuit_id
);
992 /* Find result value dissector */
993 conv
= find_conversation(pinfo
->num
, &srcaddr
, &destaddr
, CONVERSATION_NONE
, pinfo
->srcport
, pinfo
->destport
, 0);
998 lmp_conv
= (lmp_conversation_t
*)conversation_get_proto_data(conv
, proto_irlmp
);
999 while (lmp_conv
&& (lmp_conv
->iap_result_frame
>= num
))
1000 lmp_conv
= lmp_conv
->pnext
;
1004 cur_lmp_conv
= lmp_conv
->pnext
;
1005 while (cur_lmp_conv
)
1007 if ((cur_lmp_conv
->iap_result_frame
< num
) &&
1008 (cur_lmp_conv
->iap_result_frame
> lmp_conv
->iap_result_frame
))
1010 lmp_conv
= cur_lmp_conv
;
1013 cur_lmp_conv
= cur_lmp_conv
->pnext
;
1020 /*ws_message("%x:%d->%x:%d = %p\n", src, pinfo->srcport, circuit_id, pinfo->destport, lmp_conv); */
1021 /*ws_message("->%d: %d %d %p\n", pinfo->num, lmp_conv->iap_result_frame, lmp_conv->ttp, lmp_conv->proto_dissector); */
1022 if ((lmp_conv
->ttp
) && (pdu_type
!= DISCONNECT_PDU
))
1024 offset
+= dissect_ttp(tvb
, pinfo
, root
, (pdu_type
== DATA_PDU
));
1026 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1029 call_dissector_with_data(lmp_conv
->dissector
, tvb
, pinfo
, root
, GUINT_TO_POINTER(pdu_type
));
1032 call_data_dissector(tvb
, pinfo
, root
);
1039 static void dissect_irlmp(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, uint8_t circuit_id
)
1041 unsigned offset
= 0;
1048 /* Make entries in Protocol column on summary display */
1049 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IrLMP");
1051 dlsap
= tvb_get_uint8(tvb
, offset
);
1052 cbit
= dlsap
& CONTROL_BIT
;
1053 dlsap
&= ~CONTROL_BIT
;
1055 slsap
= tvb_get_uint8(tvb
, offset
+1) & ~CONTROL_BIT
;
1057 /* save Lsaps in pinfo */
1058 pinfo
->srcport
= slsap
;
1059 pinfo
->destport
= dlsap
;
1063 opcode
= tvb_get_uint8(tvb
, offset
+2);
1065 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%d > %d, ", slsap
, dlsap
);
1066 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(opcode
, lmp_opcode_vals
, "0x%02X"));
1067 if ((opcode
== ACCESSMODE_CMD
) || (opcode
== ACCESSMODE_CNF
))
1069 col_append_str(pinfo
->cinfo
, COL_INFO
, " (");
1070 col_append_str(pinfo
->cinfo
, COL_INFO
,
1071 val_to_str(tvb_get_uint8(tvb
, offset
+4), lmp_mode_vals
, "0x%02X"));
1072 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
1076 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%d > %d, Len=%d", slsap
, dlsap
,
1077 tvb_reported_length(tvb
) - 2);
1081 /* create display subtree for the protocol */
1082 proto_item
* ti
= proto_tree_add_item(root
, proto_irlmp
, tvb
, 0, -1, ENC_NA
);
1083 proto_tree
* tree
= proto_item_add_subtree(ti
, ett_irlmp
);
1085 proto_tree
* dst_tree
;
1086 proto_tree
* src_tree
;
1089 ti
= proto_tree_add_item(tree
, hf_lmp_dst
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1090 dst_tree
= proto_item_add_subtree(ti
, ett_lmp_dst
);
1091 proto_tree_add_item(dst_tree
, hf_lmp_dst_control
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1092 proto_tree_add_item(dst_tree
, hf_lmp_dst_lsap
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1095 ti
= proto_tree_add_item(tree
, hf_lmp_src
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1096 src_tree
= proto_item_add_subtree(ti
, ett_lmp_src
);
1097 proto_tree_add_item(src_tree
, hf_lmp_src_r
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1098 proto_tree_add_item(src_tree
, hf_lmp_src_lsap
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1103 proto_tree_add_item(tree
, hf_lmp_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1110 if (offset
< tvb_reported_length(tvb
))
1112 proto_tree_add_item(tree
, hf_lmp_rsvd
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1118 proto_tree_add_item(tree
, hf_lmp_reason
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1122 case ACCESSMODE_CMD
:
1123 proto_tree_add_item(tree
, hf_lmp_rsvd
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1126 proto_tree_add_item(tree
, hf_lmp_mode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1130 case ACCESSMODE_CNF
:
1131 proto_tree_add_item( tree
, hf_lmp_status
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1134 proto_tree_add_item(tree
, hf_lmp_mode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1140 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1141 proto_item_set_len(tree
, offset
);
1154 if (offset
< tvb_reported_length(tvb
))
1162 case ACCESSMODE_CMD
:
1163 case ACCESSMODE_CNF
:
1169 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1174 if (dlsap
== LSAP_IAS
)
1175 dissect_iap_request(tvb
, pinfo
, root
, circuit_id
);
1176 else if (slsap
== LSAP_IAS
)
1177 dissect_iap_result(tvb
, pinfo
, root
, circuit_id
);
1179 dissect_appl_proto(tvb
, pinfo
, root
, DATA_PDU
, circuit_id
);
1183 if ((dlsap
== LSAP_IAS
) || (slsap
== LSAP_IAS
))
1184 call_data_dissector(tvb
, pinfo
, root
);
1190 dissect_appl_proto(tvb
, pinfo
, root
, CONNECT_PDU
, circuit_id
);
1194 dissect_appl_proto(tvb
, pinfo
, root
, DISCONNECT_PDU
, circuit_id
);
1198 call_data_dissector(tvb
, pinfo
, root
);
1205 * Add LMP conversation
1207 void add_lmp_conversation(packet_info
* pinfo
, uint8_t dlsap
, bool ttp
, dissector_handle_t dissector
, uint8_t circuit_id
)
1212 conversation_t
* conv
;
1213 lmp_conversation_t
* lmp_conv
= NULL
;
1216 /*ws_message("%d: add_lmp_conversation(%p, %d, %d, %p) = ", pinfo->num, pinfo, dlsap, ttp, proto_dissector); */
1217 set_address(&srcaddr
, irda_address_type
, 1, &circuit_id
);
1218 dest
= circuit_id
^ CMD_FRAME
;
1219 set_address(&destaddr
, irda_address_type
, 1, &dest
);
1221 conv
= find_conversation(pinfo
->num
, &destaddr
, &srcaddr
, CONVERSATION_NONE
, dlsap
, 0, NO_PORT_B
);
1224 lmp_conv
= (lmp_conversation_t
*)conversation_get_proto_data(conv
, proto_irlmp
);
1227 /* Does entry already exist? */
1228 if (lmp_conv
->iap_result_frame
== pinfo
->num
)
1231 if (lmp_conv
->pnext
== NULL
)
1233 lmp_conv
->pnext
= wmem_new(wmem_file_scope(), lmp_conversation_t
);
1234 lmp_conv
= lmp_conv
->pnext
;
1237 lmp_conv
= lmp_conv
->pnext
;
1242 conv
= conversation_new(pinfo
->num
, &destaddr
, &srcaddr
, CONVERSATION_NONE
, dlsap
, 0, NO_PORT2
);
1243 lmp_conv
= wmem_new(wmem_file_scope(), lmp_conversation_t
);
1244 conversation_add_proto_data(conv
, proto_irlmp
, (void*)lmp_conv
);
1247 lmp_conv
->pnext
= NULL
;
1248 lmp_conv
->iap_result_frame
= pinfo
->num
;
1249 lmp_conv
->ttp
= ttp
;
1250 lmp_conv
->dissector
= dissector
;
1252 /*ws_message("%p\n", lmp_conv); */
1257 * Dissect Negotiation Parameters
1259 static unsigned dissect_negotiation(tvbuff_t
* tvb
, proto_tree
* tree
, unsigned offset
)
1267 while (tvb_reported_length_remaining(tvb
, offset
) > 0)
1269 uint8_t p_len
= tvb_get_uint8(tvb
, offset
+ 1);
1273 ti
= proto_tree_add_item(tree
, hf_negotiation_param
, tvb
, offset
, p_len
+ 2, ENC_NA
);
1274 p_tree
= proto_item_add_subtree(ti
, ett_param
[n
]);
1276 pv
= tvb_get_uint8(tvb
, offset
+2);
1279 switch (tvb_get_uint8(tvb
, offset
))
1282 proto_item_append_text(ti
, ": Baud Rate (");
1285 (void) g_strlcat(buf
, ", 2400", 256);
1287 (void) g_strlcat(buf
, ", 9600", 256);
1289 (void) g_strlcat(buf
, ", 19200", 256);
1291 (void) g_strlcat(buf
, ", 38400", 256);
1293 (void) g_strlcat(buf
, ", 57600", 256);
1295 (void) g_strlcat(buf
, ", 115200", 256);
1297 (void) g_strlcat(buf
, ", 576000", 256);
1299 (void) g_strlcat(buf
, ", 1152000", 256);
1300 if ((p_len
> 1) && (tvb_get_uint8(tvb
, offset
+3) & 0x01))
1301 (void) g_strlcat(buf
, ", 4000000", 256);
1303 (void) g_strlcat(buf
, " bps)", 256);
1305 proto_item_append_text(ti
, "%s", buf
+2);
1309 case PI_MAX_TURN_TIME
:
1310 proto_item_append_text(ti
, ": Maximum Turn Time (");
1313 (void) g_strlcat(buf
, ", 500", 256);
1315 (void) g_strlcat(buf
, ", 250", 256);
1317 (void) g_strlcat(buf
, ", 100", 256);
1319 (void) g_strlcat(buf
, ", 50", 256);
1321 (void) g_strlcat(buf
, " ms)", 256);
1323 proto_item_append_text(ti
, "%s", buf
+2);
1328 proto_item_append_text(ti
, ": Data Size (");
1331 (void) g_strlcat(buf
, ", 64", 256);
1333 (void) g_strlcat(buf
, ", 128", 256);
1335 (void) g_strlcat(buf
, ", 256", 256);
1337 (void) g_strlcat(buf
, ", 512", 256);
1339 (void) g_strlcat(buf
, ", 1024", 256);
1341 (void) g_strlcat(buf
, ", 2048", 256);
1343 (void) g_strlcat(buf
, " bytes)", 256);
1345 proto_item_append_text(ti
, "%s", buf
+2);
1349 case PI_WINDOW_SIZE
:
1350 proto_item_append_text(ti
, ": Window Size (");
1353 (void) g_strlcat(buf
, ", 1", 256);
1355 (void) g_strlcat(buf
, ", 2", 256);
1357 (void) g_strlcat(buf
, ", 3", 256);
1359 (void) g_strlcat(buf
, ", 4", 256);
1361 (void) g_strlcat(buf
, ", 5", 256);
1363 (void) g_strlcat(buf
, ", 6", 256);
1365 (void) g_strlcat(buf
, ", 7", 256);
1367 (void) g_strlcat(buf
, " frame window)", 256);
1369 proto_item_append_text(ti
, "%s", buf
+2);
1374 proto_item_append_text(ti
, ": Additional BOFs (");
1377 (void) g_strlcat(buf
, ", 48", 256);
1379 (void) g_strlcat(buf
, ", 24", 256);
1381 (void) g_strlcat(buf
, ", 12", 256);
1383 (void) g_strlcat(buf
, ", 5", 256);
1385 (void) g_strlcat(buf
, ", 3", 256);
1387 (void) g_strlcat(buf
, ", 2", 256);
1389 (void) g_strlcat(buf
, ", 1", 256);
1391 (void) g_strlcat(buf
, ", 0", 256);
1393 (void) g_strlcat(buf
, " additional BOFs at 115200)", 256);
1395 proto_item_append_text(ti
, "%s", buf
+2);
1399 case PI_MIN_TURN_TIME
:
1400 proto_item_append_text(ti
, ": Minimum Turn Time (");
1403 (void) g_strlcat(buf
, ", 10", 256);
1405 (void) g_strlcat(buf
, ", 5", 256);
1407 (void) g_strlcat(buf
, ", 1", 256);
1409 (void) g_strlcat(buf
, ", 0.5", 256);
1411 (void) g_strlcat(buf
, ", 0.1", 256);
1413 (void) g_strlcat(buf
, ", 0.05", 256);
1415 (void) g_strlcat(buf
, ", 0.01", 256);
1417 (void) g_strlcat(buf
, ", 0", 256);
1419 (void) g_strlcat(buf
, " ms)", 256);
1421 proto_item_append_text(ti
, "%s", buf
+2);
1426 proto_item_append_text(ti
, ": Link Disconnect/Threshold Time (");
1429 (void) g_strlcat(buf
, ", 3/0", 256);
1431 (void) g_strlcat(buf
, ", 8/3", 256);
1433 (void) g_strlcat(buf
, ", 12/3", 256);
1435 (void) g_strlcat(buf
, ", 16/3", 256);
1437 (void) g_strlcat(buf
, ", 20/3", 256);
1439 (void) g_strlcat(buf
, ", 25/3", 256);
1441 (void) g_strlcat(buf
, ", 30/3", 256);
1443 (void) g_strlcat(buf
, ", 40/3", 256);
1445 (void) g_strlcat(buf
, " s)", 256);
1447 proto_item_append_text(ti
, "%s", buf
+2);
1452 proto_item_append_text(ti
, ": unknown");
1457 offset
= dissect_param_tuple(tvb
, p_tree
, offset
);
1466 * Dissect XID packet
1468 static void dissect_xid(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, proto_tree
* lap_tree
, bool is_command
)
1471 proto_item
* ti
= NULL
;
1472 proto_tree
* i_tree
= NULL
;
1473 proto_tree
* flags_tree
;
1474 uint32_t saddr
, daddr
;
1476 proto_tree
* lmp_tree
= NULL
;
1480 ti
= proto_tree_add_item(lap_tree
, hf_lap_i
, tvb
, offset
, -1, ENC_NA
);
1481 i_tree
= proto_item_add_subtree(ti
, ett_lap_i
);
1483 proto_tree_add_item(i_tree
, hf_xid_ident
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1487 saddr
= tvb_get_letohl(tvb
, offset
);
1488 col_add_fstr(pinfo
->cinfo
, COL_DEF_SRC
, "0x%08X", saddr
);
1490 proto_tree_add_uint(i_tree
, hf_xid_saddr
, tvb
, offset
, 4, saddr
);
1493 daddr
= tvb_get_letohl(tvb
, offset
);
1494 col_add_fstr(pinfo
->cinfo
, COL_DEF_DST
, "0x%08X", daddr
);
1496 proto_tree_add_uint(i_tree
, hf_xid_daddr
, tvb
, offset
, 4, daddr
);
1501 /* Discovery flags */
1502 ti
= proto_tree_add_item(i_tree
, hf_xid_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1503 flags_tree
= proto_item_add_subtree(ti
, ett_xid_flags
);
1504 proto_tree_add_item(flags_tree
, hf_xid_s
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1505 proto_tree_add_item(flags_tree
, hf_xid_conflict
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1511 s
= tvb_get_uint8(tvb
, offset
);
1513 col_append_str(pinfo
->cinfo
, COL_INFO
, ", s=final");
1515 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", s=%u", s
);
1518 ti
= proto_tree_add_uint(i_tree
, hf_xid_slotnr
, tvb
, offset
, 1, s
);
1520 proto_item_append_text(ti
, " (final)");
1523 /* Skip (empty?) byte even if no command.. Have seen non-zero values in a capture */
1527 proto_tree_add_item(i_tree
, hf_xid_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1532 proto_item_set_end(lap_tree
, tvb
, offset
);
1533 proto_item_set_end(i_tree
, tvb
, offset
);
1536 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
1544 ti
= proto_tree_add_item(root
, proto_irlmp
, tvb
, offset
, -1, ENC_NA
);
1545 lmp_tree
= proto_item_add_subtree(ti
, ett_irlmp
);
1548 for (hints_len
= 0;;)
1550 uint8_t hint
= tvb_get_uint8(tvb
, offset
+ hints_len
++);
1554 else if (hints_len
== 2)
1557 if ((hint
& 0x80) == 0)
1563 ti
= proto_tree_add_item(lmp_tree
, hf_lmp_xid_hints
, tvb
, offset
, hints_len
, ENC_NA
);
1564 if ((hint1
| hint2
) != 0)
1566 char service_hints
[256];
1568 service_hints
[0] = 0;
1571 (void) g_strlcat(service_hints
, ", PnP Compatible", 256);
1573 (void) g_strlcat(service_hints
, ", PDA/Palmtop", 256);
1575 (void) g_strlcat(service_hints
, ", Computer", 256);
1577 (void) g_strlcat(service_hints
, ", Printer", 256);
1579 (void) g_strlcat(service_hints
, ", Modem", 256);
1581 (void) g_strlcat(service_hints
, ", Fax", 256);
1583 (void) g_strlcat(service_hints
, ", LAN Access", 256);
1585 (void) g_strlcat(service_hints
, ", Telephony", 256);
1587 (void) g_strlcat(service_hints
, ", File Server", 256);
1589 (void) g_strlcat(service_hints
, ", IrCOMM", 256);
1591 (void) g_strlcat(service_hints
, ", OBEX", 256);
1593 (void) g_strlcat(service_hints
, ")", 256);
1594 service_hints
[0] = ' ';
1595 service_hints
[1] = '(';
1597 proto_item_append_text(ti
, "%s", service_hints
);
1600 offset
+= hints_len
;
1602 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
1610 cset
= tvb_get_uint8(tvb
, offset
);
1612 proto_tree_add_uint(lmp_tree
, hf_lmp_xid_charset
, tvb
, offset
, 1, cset
);
1614 name_len
= tvb_reported_length_remaining(tvb
, offset
);
1619 case LMP_CHARSET_ASCII
:
1620 encoding
= ENC_ASCII
|ENC_NA
;
1621 have_encoding
= true;
1624 case LMP_CHARSET_ISO_8859_1
:
1625 encoding
= ENC_ISO_8859_1
|ENC_NA
;
1626 have_encoding
= true;
1629 case LMP_CHARSET_ISO_8859_2
:
1630 encoding
= ENC_ISO_8859_2
|ENC_NA
;
1631 have_encoding
= true;
1634 case LMP_CHARSET_ISO_8859_3
:
1635 encoding
= ENC_ISO_8859_3
|ENC_NA
;
1636 have_encoding
= true;
1639 case LMP_CHARSET_ISO_8859_4
:
1640 encoding
= ENC_ISO_8859_4
|ENC_NA
;
1641 have_encoding
= true;
1644 case LMP_CHARSET_ISO_8859_5
:
1645 encoding
= ENC_ISO_8859_5
|ENC_NA
;
1646 have_encoding
= true;
1649 case LMP_CHARSET_ISO_8859_6
:
1650 encoding
= ENC_ISO_8859_6
|ENC_NA
;
1651 have_encoding
= true;
1654 case LMP_CHARSET_ISO_8859_7
:
1655 encoding
= ENC_ISO_8859_7
|ENC_NA
;
1656 have_encoding
= true;
1659 case LMP_CHARSET_ISO_8859_8
:
1660 encoding
= ENC_ISO_8859_8
|ENC_NA
;
1661 have_encoding
= true;
1664 case LMP_CHARSET_ISO_8859_9
:
1665 encoding
= ENC_ISO_8859_9
|ENC_NA
;
1666 have_encoding
= true;
1669 case LMP_CHARSET_UNICODE
:
1670 /* Presumably big-endian; assume just UCS-2 for now */
1671 encoding
= ENC_UCS_2
|ENC_BIG_ENDIAN
;
1672 have_encoding
= true;
1677 have_encoding
= false;
1683 name
= (char *) tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, name_len
, encoding
);
1684 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", \"%s\"", format_text(pinfo
->pool
, (unsigned char *) name
, strlen(name
)));
1686 proto_tree_add_item(lmp_tree
, hf_lmp_xid_name
, tvb
, offset
,
1692 proto_tree_add_item(lmp_tree
, hf_lmp_xid_name_no_encoding
, tvb
, offset
,
1702 * Dissect Log Messages
1704 static void dissect_log(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
)
1706 /* Make entries in Protocol column on summary display */
1707 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "Log");
1709 /* missed messages? */
1710 if (pinfo
->pseudo_header
->irda
.pkttype
== IRDA_MISSED_MSG
)
1712 col_set_str(pinfo
->cinfo
, COL_INFO
, "WARNING: Missed one or more messages while capturing!");
1719 length
= tvb_captured_length(tvb
);
1720 buf
= (char *) tvb_get_string_enc(pinfo
->pool
, tvb
, 0, length
, ENC_ASCII
|ENC_NA
);
1721 if (length
> 0 && buf
[length
-1] == '\n')
1723 else if (length
> 1 && buf
[length
-2] == '\n')
1726 col_add_str(pinfo
->cinfo
, COL_INFO
, format_text(pinfo
->pool
, (unsigned char *) buf
, strlen(buf
)));
1731 proto_item
* ti
= proto_tree_add_item(root
, proto_log
, tvb
, 0, -1, ENC_NA
);
1732 proto_tree
* tree
= proto_item_add_subtree(ti
, ett_log
);
1734 if (pinfo
->pseudo_header
->irda
.pkttype
== IRDA_MISSED_MSG
)
1735 proto_tree_add_item(tree
, hf_log_missed
, tvb
, 0, 0, ENC_NA
);
1737 proto_tree_add_item(tree
, hf_log_msg
, tvb
, 0, -1, ENC_ASCII
|ENC_NA
);
1745 static void dissect_irlap(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
)
1748 uint8_t circuit_id
, c
;
1751 proto_item
* ti
= NULL
;
1752 proto_tree
* tree
= NULL
;
1753 proto_tree
* i_tree
= NULL
;
1754 uint32_t saddr
, daddr
;
1757 /* Make entries in Protocol column on summary display */
1758 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IrLAP");
1760 /* Clear Info column */
1761 col_clear(pinfo
->cinfo
, COL_INFO
);
1763 /* set direction column */
1764 switch (pinfo
->pseudo_header
->irda
.pkttype
)
1767 col_set_str(pinfo
->cinfo
, COL_IF_DIR
, "Out");
1771 col_set_str(pinfo
->cinfo
, COL_IF_DIR
, "In");
1775 /* decode values used for demuxing */
1776 circuit_id
= tvb_get_uint8(tvb
, 0);
1778 /* initially set address columns to connection address */
1779 snprintf(addr
, sizeof(addr
)-1, "0x%02X", circuit_id
>> 1);
1780 col_add_str(pinfo
->cinfo
, COL_DEF_SRC
, addr
);
1781 col_add_str(pinfo
->cinfo
, COL_DEF_DST
, addr
);
1786 proto_item
* addr_item
;
1788 /* create display subtree for the protocol */
1789 ti
= proto_tree_add_item(root
, proto_irlap
, tvb
, 0, -1, ENC_NA
);
1790 tree
= proto_item_add_subtree(ti
, ett_irlap
);
1792 /* create subtree for the address field */
1793 ti
= proto_tree_add_item(tree
, hf_lap_a
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1794 a_tree
= proto_item_add_subtree(ti
, ett_lap_a
);
1795 proto_tree_add_item(a_tree
, hf_lap_a_cr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1796 addr_item
= proto_tree_add_item(a_tree
, hf_lap_a_address
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1797 switch (circuit_id
& ~CMD_FRAME
)
1800 proto_item_append_text(addr_item
, " (NULL Address)");
1803 proto_item_append_text(addr_item
, " (Broadcast)");
1807 is_response
= ((circuit_id
& CMD_FRAME
) == 0);
1810 /* process the control field */
1811 c
= dissect_xdlc_control(tvb
, offset
, pinfo
, tree
, hf_lap_c
,
1812 ett_lap_c
, &irlap_cf_items
, NULL
, lap_c_u_cmd_abbr_vals
,
1813 lap_c_u_rsp_abbr_vals
, is_response
, false, false);
1816 if ((c
& XDLC_I_MASK
) == XDLC_I
) {
1818 proto_item_set_len(tree
, offset
);
1819 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1820 dissect_irlmp(tvb
, pinfo
, root
, circuit_id
);
1824 if ((c
& XDLC_S_U_MASK
) == XDLC_U
) {
1826 switch (c
& XDLC_U_MODIFIER_MASK
)
1831 ti
= proto_tree_add_item(tree
, hf_lap_i
, tvb
, offset
, -1, ENC_NA
);
1832 i_tree
= proto_item_add_subtree(ti
, ett_lap_i
);
1835 saddr
= tvb_get_letohl(tvb
, offset
);
1838 col_add_fstr(pinfo
->cinfo
, COL_DEF_SRC
, "0x%08X", saddr
);
1841 proto_tree_add_uint(i_tree
, hf_snrm_saddr
, tvb
, offset
, 4, saddr
);
1844 daddr
= tvb_get_letohl(tvb
, offset
);
1847 col_add_fstr(pinfo
->cinfo
, COL_DEF_DST
, "0x%08X", daddr
);
1850 proto_tree_add_uint(i_tree
, hf_snrm_daddr
, tvb
, offset
, 4, daddr
);
1853 ca
= tvb_get_uint8(tvb
, offset
);
1856 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", ca=0x%02X",
1860 proto_tree_add_uint(i_tree
, hf_snrm_ca
, tvb
, offset
, 1, ca
>> 1);
1863 offset
= dissect_negotiation(tvb
, i_tree
, offset
);
1865 proto_item_set_end(ti
, tvb
, offset
);
1869 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1870 dissect_xid(tvb
, pinfo
, root
, tree
, true);
1874 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
1878 ti
= proto_tree_add_item(tree
, hf_lap_i
, tvb
, offset
, -1, ENC_NA
);
1879 i_tree
= proto_item_add_subtree(ti
, ett_lap_i
);
1882 saddr
= tvb_get_letohl(tvb
, offset
);
1883 col_add_fstr(pinfo
->cinfo
, COL_DEF_SRC
, "0x%08X", saddr
);
1885 proto_tree_add_uint(i_tree
, hf_ua_saddr
, tvb
, offset
, 4, saddr
);
1888 daddr
= tvb_get_letohl(tvb
, offset
);
1889 col_add_fstr(pinfo
->cinfo
, COL_DEF_DST
, "0x%08X", daddr
);
1891 proto_tree_add_uint(i_tree
, hf_ua_daddr
, tvb
, offset
, 4, daddr
);
1894 offset
= dissect_negotiation(tvb
, i_tree
, offset
);
1896 proto_item_set_end(ti
, tvb
, offset
);
1901 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1902 dissect_xid(tvb
, pinfo
, root
, tree
, false);
1907 /* If any bytes remain, send it to the generic data dissector */
1908 if (tvb_reported_length_remaining(tvb
, offset
) > 0)
1910 tvb
= tvb_new_subset_remaining(tvb
, offset
);
1911 call_data_dissector(tvb
, pinfo
, root
);
1917 * Dissect IrDA protocol
1919 static int dissect_irda(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* root
, void* data _U_
)
1921 /* check if log message */
1922 if ((pinfo
->pseudo_header
->irda
.pkttype
& IRDA_CLASS_MASK
) == IRDA_CLASS_LOG
)
1924 dissect_log(tvb
, pinfo
, root
);
1925 return tvb_captured_length(tvb
);
1929 dissect_irlap(tvb
, pinfo
, root
);
1930 return tvb_captured_length(tvb
);
1933 static int irda_addr_to_str(const address
* addr
, char *buf
, int buf_len _U_
)
1935 const uint8_t *addrdata
= (const uint8_t *)addr
->data
;
1937 uint32_to_str_buf(*addrdata
, buf
, buf_len
);
1938 return (int)strlen(buf
);
1941 static int irda_addr_str_len(const address
* addr _U_
)
1943 return 11; /* Leaves required space (10 bytes) for uint_to_str_back() */
1946 static const char* irda_col_filter_str(const address
* addr _U_
, bool is_src _U_
)
1951 static int irda_addr_len(void)
1957 * Register the protocol with Wireshark
1958 * This format is required because a script is used to build the C function
1959 * that calls all the protocol registrations.
1961 void proto_register_irda(void)
1965 /* Setup list of header fields */
1966 static hf_register_info hf_lap
[] = {
1968 { "Address Field", "irlap.a",
1969 FT_UINT8
, BASE_HEX
, NULL
, 0,
1972 { "C/R", "irlap.a.cr",
1973 FT_BOOLEAN
, 8, TFS(&lap_cr_vals
), CMD_FRAME
,
1975 { &hf_lap_a_address
,
1976 { "Address", "irlap.a.address",
1977 FT_UINT8
, BASE_HEX
, NULL
, ~CMD_FRAME
,
1980 { "Control Field", "irlap.c",
1981 FT_UINT8
, BASE_HEX
, NULL
, 0,
1984 { "N(R)", "irlap.c.n_r",
1985 FT_UINT8
, BASE_DEC
, NULL
, XDLC_N_R_MASK
,
1988 { "N(S)", "irlap.c.n_s",
1989 FT_UINT8
, BASE_DEC
, NULL
, XDLC_N_S_MASK
,
1992 { "Poll", "irlap.c.p",
1993 FT_BOOLEAN
, 8, TFS(&set_notset
), XDLC_P_F
,
1996 { "Final", "irlap.c.f",
1997 FT_BOOLEAN
, 8, TFS(&set_notset
), XDLC_P_F
,
2000 { "Supervisory frame type", "irlap.c.s_ftype",
2001 FT_UINT8
, BASE_HEX
, VALS(lap_c_s_vals
), XDLC_S_FTYPE_MASK
,
2004 { "Command", "irlap.c.u_modifier_cmd",
2005 FT_UINT8
, BASE_HEX
, VALS(lap_c_u_cmd_vals
), XDLC_U_MODIFIER_MASK
,
2008 { "Response", "irlap.c.u_modifier_resp",
2009 FT_UINT8
, BASE_HEX
, VALS(lap_c_u_rsp_vals
), XDLC_U_MODIFIER_MASK
,
2012 { "Frame Type", "irlap.c.ftype",
2013 FT_UINT8
, BASE_HEX
, VALS(lap_c_ftype_vals
), XDLC_I_MASK
,
2016 { "Frame Type", "irlap.c.ftype",
2017 FT_UINT8
, BASE_HEX
, VALS(lap_c_ftype_vals
), XDLC_S_U_MASK
,
2020 { "Information Field", "irlap.i",
2021 FT_NONE
, BASE_NONE
, NULL
, 0,
2024 { "Source Device Address", "irlap.snrm.saddr",
2025 FT_UINT32
, BASE_HEX
, NULL
, 0,
2028 { "Destination Device Address", "irlap.snrm.daddr",
2029 FT_UINT32
, BASE_HEX
, NULL
, 0,
2032 { "Connection Address", "irlap.snrm.ca",
2033 FT_UINT8
, BASE_HEX
, NULL
, 0,
2035 { &hf_negotiation_param
,
2036 { "Negotiation Parameter", "irlap.negotiation",
2037 FT_NONE
, BASE_NONE
, NULL
, 0,
2040 { "Parameter Identifier", "irlap.pi",
2041 FT_UINT8
, BASE_HEX
, NULL
, 0,
2044 { "Parameter Length", "irlap.pl",
2045 FT_UINT8
, BASE_HEX
, NULL
, 0,
2048 { "Parameter Value", "irlap.pv",
2049 FT_BYTES
, BASE_NONE
, NULL
, 0,
2052 { "Source Device Address", "irlap.ua.saddr",
2053 FT_UINT32
, BASE_HEX
, NULL
, 0,
2056 { "Destination Device Address", "irlap.ua.daddr",
2057 FT_UINT32
, BASE_HEX
, NULL
, 0,
2060 { "Format Identifier", "irlap.xid.fi",
2061 FT_UINT8
, BASE_HEX
, NULL
, 0,
2064 { "Source Device Address", "irlap.xid.saddr",
2065 FT_UINT32
, BASE_HEX
, NULL
, 0,
2068 { "Destination Device Address", "irlap.xid.daddr",
2069 FT_UINT32
, BASE_HEX
, NULL
, 0,
2072 { "Discovery Flags", "irlap.xid.flags",
2073 FT_UINT8
, BASE_HEX
, NULL
, 0,
2076 { "Number of Slots", "irlap.xid.s",
2077 FT_UINT8
, BASE_DEC
, VALS(xid_slot_numbers
), S_MASK
,
2080 { "Conflict", "irlap.xid.conflict",
2081 FT_BOOLEAN
, 8, TFS(&set_notset
), CONFLICT
,
2084 { "Slot Number", "irlap.xid.slotnr",
2085 FT_UINT8
, BASE_DEC
, NULL
, 0,
2088 { "Version Number", "irlap.xid.version",
2089 FT_UINT8
, BASE_HEX
, NULL
, 0,
2093 static hf_register_info hf_log
[] = {
2095 { "Message", "log.msg",
2096 FT_STRING
, BASE_NONE
, NULL
, 0,
2099 { "WARNING: Missed one or more messages while capturing!", "log.missed",
2100 FT_NONE
, BASE_NONE
, NULL
, 0,
2104 static hf_register_info hf_lmp
[] = {
2105 { &hf_lmp_xid_hints
,
2106 { "Service Hints", "irlmp.xid.hints",
2107 FT_BYTES
, BASE_NONE
, NULL
, 0,
2109 { &hf_lmp_xid_charset
,
2110 { "Character Set", "irlmp.xid.charset",
2111 FT_UINT8
, BASE_HEX
, VALS(lmp_charset_vals
), 0,
2114 { "Device Nickname", "irlmp.xid.name",
2115 FT_STRING
, BASE_NONE
, NULL
, 0,
2117 { &hf_lmp_xid_name_no_encoding
,
2118 { "Device Nickname (unsupported character set)", "irlmp.xid.name.no_encoding",
2119 FT_BYTES
, BASE_NONE
, NULL
, 0,
2122 { "Destination", "irlmp.dst",
2123 FT_UINT8
, BASE_HEX
, NULL
, 0,
2125 { &hf_lmp_dst_control
,
2126 { "Control Bit", "irlmp.dst.c",
2127 FT_BOOLEAN
, 8, TFS(&set_notset
), CONTROL_BIT
,
2130 { "Destination LSAP", "irlmp.dst.lsap",
2131 FT_UINT8
, BASE_DEC
, NULL
, ~CONTROL_BIT
,
2134 { "Source", "irlmp.src",
2135 FT_UINT8
, BASE_HEX
, NULL
, 0,
2138 { "reserved", "irlmp.src.r",
2139 FT_UINT8
, BASE_DEC
, NULL
, RESERVED_BIT
,
2142 { "Source LSAP", "irlmp.src.lsap",
2143 FT_UINT8
, BASE_DEC
, NULL
, ~RESERVED_BIT
,
2146 { "Opcode", "irlmp.opcode",
2147 FT_UINT8
, BASE_HEX
, VALS(lmp_opcode_vals
), 0x0,
2150 { "Reserved", "irlmp.rsvd",
2151 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2154 { "Reason", "irlmp.reason",
2155 FT_UINT8
, BASE_HEX
, VALS(lmp_reason_vals
), 0x0,
2158 { "Mode", "irlmp.mode",
2159 FT_UINT8
, BASE_HEX
, VALS(lmp_mode_vals
), 0x0,
2162 { "Status", "irlmp.status",
2163 FT_UINT8
, BASE_HEX
, VALS(lmp_status_vals
), 0x0,
2167 static hf_register_info hf_iap
[] = {
2169 { "Control Field", "iap.ctl",
2170 FT_UINT8
, BASE_HEX
, NULL
, 0,
2173 { "Last Frame", "iap.ctl.lst",
2174 FT_BOOLEAN
, 8, TFS(&set_notset
), IAP_LST
,
2177 { "Acknowledge", "iap.ctl.ack",
2178 FT_BOOLEAN
, 8, TFS(&set_notset
), IAP_ACK
,
2180 { &hf_iap_ctl_opcode
,
2181 { "Opcode", "iap.ctl.opcode",
2182 FT_UINT8
, BASE_HEX
, VALS(iap_opcode_vals
), IAP_OP
,
2184 { &hf_iap_class_name
,
2185 { "Class Name", "iap.classname",
2186 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x0,
2188 { &hf_iap_attr_name
,
2189 { "Attribute Name", "iap.attrname",
2190 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x0,
2193 { "Return", "iap.return",
2194 FT_UINT8
, BASE_HEX
, VALS(iap_return_vals
), 0x0,
2197 { "List Length", "iap.listlen",
2198 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2200 { &hf_iap_list_entry
,
2201 { "List Entry", "iap.listentry",
2202 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2205 { "Object Identifier", "iap.objectid",
2206 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2208 { &hf_iap_attr_type
,
2209 { "Type", "iap.attrtype",
2210 FT_UINT8
, BASE_DEC
, VALS(iap_attr_type_vals
), 0x0,
2213 { "Value", "iap.int",
2214 FT_INT32
, BASE_DEC
, NULL
, 0x0,
2217 { "Sequence Length", "iap.seqlen",
2218 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2221 { "Sequence", "iap.octseq",
2222 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2225 { "Character Set", "iap.charset",
2226 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2229 { "String", "iap.string",
2230 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x0,
2232 { &hf_iap_invaloctet
,
2233 { "Malformed IAP result: \"", "iap.invaloctet",
2234 FT_NONE
, BASE_NONE
, NULL
, 0,
2236 { &hf_iap_invallsap
,
2237 { "Malformed IAP result: \"", "iap.invallsap",
2238 FT_NONE
, BASE_NONE
, NULL
, 0,
2242 static hf_register_info hf_ttp
[] = {
2244 { "Parameter Bit", "ttp.p",
2245 FT_BOOLEAN
, 8, TFS(&set_notset
), TTP_PARAMETERS
,
2248 { "Initial Credit", "ttp.icredit",
2249 FT_UINT8
, BASE_DEC
, NULL
, ~TTP_PARAMETERS
,
2252 { "More Bit", "ttp.m",
2253 FT_BOOLEAN
, 8, TFS(&set_notset
), TTP_MORE
,
2256 { "Delta Credit", "ttp.dcredit",
2257 FT_UINT8
, BASE_DEC
, NULL
, ~TTP_MORE
,
2261 /* Setup protocol subtree arrays */
2262 static int* ett
[] = {
2277 int* ett_p
[MAX_PARAMETERS
];
2278 int* ett_iap_e
[MAX_IAP_ENTRIES
];
2281 /* Register protocol names and descriptions */
2282 proto_irlap
= proto_register_protocol("IrDA Link Access Protocol", "IrLAP", "irlap");
2283 proto_log
= proto_register_protocol("Log Message", "Log", "log");
2284 proto_irlmp
= proto_register_protocol("IrDA Link Management Protocol", "IrLMP", "irlmp");
2285 proto_iap
= proto_register_protocol("Information Access Protocol", "IAP", "iap");
2286 proto_ttp
= proto_register_protocol("Tiny Transport Protocol", "TTP", "ttp");
2288 /* Register the dissector */
2289 irda_handle
= register_dissector("irda", dissect_irda
, proto_irlap
);
2291 /* Required function calls to register the header fields */
2292 proto_register_field_array(proto_irlap
, hf_lap
, array_length(hf_lap
));
2293 proto_register_field_array(proto_log
, hf_log
, array_length(hf_log
));
2294 proto_register_field_array(proto_irlmp
, hf_lmp
, array_length(hf_lmp
));
2295 proto_register_field_array(proto_iap
, hf_iap
, array_length(hf_iap
));
2296 proto_register_field_array(proto_ttp
, hf_ttp
, array_length(hf_ttp
));
2298 /* Register subtrees */
2299 proto_register_subtree_array(ett
, array_length(ett
));
2300 for (i
= 0; i
< MAX_PARAMETERS
; i
++)
2302 ett_p
[i
] = &ett_param
[i
];
2304 proto_register_subtree_array(ett_p
, MAX_PARAMETERS
);
2305 for (i
= 0; i
< MAX_IAP_ENTRIES
; i
++)
2307 ett_iap_e
[i
] = &ett_iap_entry
[i
];
2309 proto_register_subtree_array(ett_iap_e
, MAX_IAP_ENTRIES
);
2311 irda_address_type
= address_type_dissector_register("AT_IRDA", "IRDA Address", irda_addr_to_str
, irda_addr_str_len
, NULL
, irda_col_filter_str
, irda_addr_len
, NULL
, NULL
);
2315 /* If this dissector uses sub-dissector registration add a registration routine.
2316 This format is required because a script is used to find these routines and
2317 create the code that calls these routines.
2320 void proto_reg_handoff_irda(void)
2322 dissector_add_uint("wtap_encap", WTAP_ENCAP_IRDA
, irda_handle
);
2323 dissector_add_uint("sll.ltype", LINUX_SLL_P_IRDA_LAP
, irda_handle
);
2327 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2332 * indent-tabs-mode: nil
2335 * vi: set shiftwidth=4 tabstop=8 expandtab:
2336 * :indentSize=4:tabSize=8:noTabs=true: