nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* packet-irda.c |
2 | * Routines for IrDA dissection |
||
3 | * By Shaun Jackman <sjackman@pathwayconnect.com> |
||
4 | * Copyright 2000 Shaun Jackman |
||
5 | * |
||
6 | * Extended by Jan Kiszka <jan.kiszka@web.de> |
||
7 | * Copyright 2003 Jan Kiszka |
||
8 | * |
||
9 | * Wireshark - Network traffic analyzer |
||
10 | * By Gerald Combs <gerald@wireshark.org> |
||
11 | * Copyright 1998 Gerald Combs |
||
12 | * |
||
13 | * This program is free software; you can redistribute it and/or |
||
14 | * modify it under the terms of the GNU General Public License |
||
15 | * as published by the Free Software Foundation; either version 2 |
||
16 | * of the License, or (at your option) any later version. |
||
17 | * |
||
18 | * This program is distributed in the hope that it will be useful, |
||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
21 | * GNU General Public License for more details. |
||
22 | * |
||
23 | * You should have received a copy of the GNU General Public License |
||
24 | * along with this program; if not, write to the Free Software |
||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
26 | */ |
||
27 | |||
28 | #include "config.h" |
||
29 | |||
30 | #include <string.h> |
||
31 | |||
32 | #include <epan/packet.h> |
||
33 | #include <epan/address_types.h> |
||
34 | #include <epan/to_str.h> |
||
35 | #include <epan/conversation.h> |
||
36 | #include <epan/xdlc.h> |
||
37 | #include <wiretap/wtap.h> |
||
38 | |||
39 | #include <epan/dissectors/packet-sll.h> |
||
40 | #include "irda-appl.h" |
||
41 | |||
42 | /* |
||
43 | * This plugin dissects infrared data transmissions as defined by the IrDA |
||
44 | * specification (www.irda.org). See |
||
45 | * |
||
46 | * http://www.irda.org/standards/specifications.asp |
||
47 | * |
||
48 | * for various IrDA specifications. |
||
49 | * |
||
50 | * The plugin operates both offline with libpcap files and online on supported |
||
51 | * platforms. Live dissection is currently available for Linux-IrDA |
||
52 | * (irda.sourceforge.net) and for Windows if the Linux-IrDA port IrCOMM2k |
||
53 | * (www.ircomm2k.de) is installed. |
||
54 | */ |
||
55 | |||
56 | /* |
||
57 | * LAP |
||
58 | */ |
||
59 | |||
60 | /* Frame types and templates */ |
||
61 | #define INVALID 0xff |
||
62 | |||
63 | /* |
||
64 | * XXX - the IrDA spec gives XID as 0x2c; HDLC (and other HDLC-derived |
||
65 | * protocolc) use 0xAC. |
||
66 | */ |
||
67 | #define IRDA_XID_CMD 0x2c /* Exchange Station Identification */ |
||
68 | |||
69 | #define CMD_FRAME 0x01 |
||
70 | #define RSP_FRAME 0x00 |
||
71 | |||
72 | /* Discovery Flags */ |
||
73 | #define S_MASK 0x03 |
||
74 | #define CONFLICT 0x04 |
||
75 | |||
76 | /* Negotiation Parameters */ |
||
77 | #define PI_BAUD_RATE 0x01 |
||
78 | #define PI_MAX_TURN_TIME 0x82 |
||
79 | #define PI_DATA_SIZE 0x83 |
||
80 | #define PI_WINDOW_SIZE 0x84 |
||
81 | #define PI_ADD_BOFS 0x85 |
||
82 | #define PI_MIN_TURN_TIME 0x86 |
||
83 | #define PI_LINK_DISC 0x08 |
||
84 | |||
85 | |||
86 | /* |
||
87 | * LMP |
||
88 | */ |
||
89 | |||
90 | /* IrLMP frame opcodes */ |
||
91 | #define CONNECT_CMD 0x01 |
||
92 | #define CONNECT_CNF 0x81 |
||
93 | #define DISCONNECT 0x02 |
||
94 | #define ACCESSMODE_CMD 0x03 |
||
95 | #define ACCESSMODE_CNF 0x83 |
||
96 | |||
97 | #define CONTROL_BIT 0x80 |
||
98 | #define RESERVED_BIT 0x80 |
||
99 | |||
100 | /* LSAP-SEL's */ |
||
101 | #define LSAP_MASK 0x7f |
||
102 | #define LSAP_IAS 0x00 |
||
103 | #define LSAP_ANY 0xff |
||
104 | #define LSAP_MAX 0x6f /* 0x70-0x7f are reserved */ |
||
105 | #define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */ |
||
106 | |||
107 | |||
108 | /* |
||
109 | * IAP |
||
110 | */ |
||
111 | |||
112 | /* IrIAP Op-codes */ |
||
113 | #define GET_INFO_BASE 0x01 |
||
114 | #define GET_OBJECTS 0x02 |
||
115 | #define GET_VALUE 0x03 |
||
116 | #define GET_VALUE_BY_CLASS 0x04 |
||
117 | #define GET_OBJECT_INFO 0x05 |
||
118 | #define GET_ATTRIB_NAMES 0x06 |
||
119 | |||
120 | #define IAP_LST 0x80 |
||
121 | #define IAP_ACK 0x40 |
||
122 | #define IAP_OP 0x3F |
||
123 | |||
124 | #define IAS_SUCCESS 0 |
||
125 | #define IAS_CLASS_UNKNOWN 1 |
||
126 | #define IAS_ATTRIB_UNKNOWN 2 |
||
127 | #define IAS_ATTR_TOO_LONG 3 |
||
128 | #define IAS_DISCONNECT 10 |
||
129 | #define IAS_UNSUPPORTED 0xFF |
||
130 | |||
131 | |||
132 | /* |
||
133 | * TTP |
||
134 | */ |
||
135 | |||
136 | #define TTP_PARAMETERS 0x80 |
||
137 | #define TTP_MORE 0x80 |
||
138 | |||
139 | void proto_reg_handoff_irda(void); |
||
140 | void proto_register_irda(void); |
||
141 | |||
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; |
||
175 | |||
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; |
||
192 | |||
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; |
||
212 | |||
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; |
||
218 | |||
219 | static int proto_log = -1; |
||
220 | static int hf_log_msg = -1; |
||
221 | static int hf_log_missed = -1; |
||
222 | |||
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; |
||
236 | |||
237 | #define MAX_PARAMETERS 32 |
||
238 | static gint ett_param[MAX_PARAMETERS]; |
||
239 | |||
240 | static gint ett_iap_entry[MAX_IAP_ENTRIES]; |
||
241 | |||
242 | static int irda_address_type = -1; |
||
243 | |||
244 | static const xdlc_cf_items irlap_cf_items = { |
||
245 | &hf_lap_c_nr, |
||
246 | &hf_lap_c_ns, |
||
247 | &hf_lap_c_p, |
||
248 | &hf_lap_c_f, |
||
249 | &hf_lap_c_s, |
||
250 | &hf_lap_c_u_cmd, |
||
251 | &hf_lap_c_u_rsp, |
||
252 | &hf_lap_c_i, |
||
253 | &hf_lap_c_s_u |
||
254 | }; |
||
255 | |||
256 | /* IAP conversation type */ |
||
257 | typedef struct iap_conversation { |
||
258 | struct iap_conversation* pnext; |
||
259 | guint32 iap_query_frame; |
||
260 | ias_attr_dissector_t* pattr_dissector; |
||
261 | } iap_conversation_t; |
||
262 | |||
263 | /* IrLMP conversation type */ |
||
264 | typedef struct lmp_conversation { |
||
265 | struct lmp_conversation* pnext; |
||
266 | guint32 iap_result_frame; |
||
267 | gboolean ttp; |
||
268 | dissector_handle_t dissector; |
||
269 | } lmp_conversation_t; |
||
270 | |||
271 | static const true_false_string lap_cr_vals = { |
||
272 | "Command", |
||
273 | "Response" |
||
274 | }; |
||
275 | |||
276 | static const true_false_string set_notset = { |
||
277 | "Set", |
||
278 | "Not set" |
||
279 | }; |
||
280 | |||
281 | static const value_string lap_c_ftype_vals[] = { |
||
282 | { XDLC_I, "Information frame" }, |
||
283 | { XDLC_S, "Supervisory frame" }, |
||
284 | { XDLC_U, "Unnumbered frame" }, |
||
285 | { 0, NULL } |
||
286 | }; |
||
287 | |||
288 | static const value_string lap_c_u_cmd_abbr_vals[] = { |
||
289 | { XDLC_SNRM, "SNRM" }, |
||
290 | { XDLC_DISC, "DISC" }, |
||
291 | { XDLC_UI, "UI" }, |
||
292 | { IRDA_XID_CMD, "XID" }, |
||
293 | { XDLC_TEST, "TEST" }, |
||
294 | { 0, NULL } |
||
295 | }; |
||
296 | |||
297 | static const value_string lap_c_u_rsp_abbr_vals[] = { |
||
298 | { XDLC_SNRM, "RNRM" }, |
||
299 | { XDLC_UA, "UA" }, |
||
300 | { XDLC_FRMR, "FRMR" }, |
||
301 | { XDLC_DM, "DM" }, |
||
302 | { XDLC_RD, "RD" }, |
||
303 | { XDLC_UI, "UI" }, |
||
304 | { XDLC_XID, "XID" }, |
||
305 | { XDLC_TEST, "TEST" }, |
||
306 | { 0, NULL } |
||
307 | }; |
||
308 | |||
309 | static const value_string lap_c_u_cmd_vals[] = { |
||
310 | { XDLC_SNRM>>2, "Set Normal Response Mode" }, |
||
311 | { XDLC_DISC>>2, "Disconnect" }, |
||
312 | { XDLC_UI>>2, "Unnumbered Information" }, |
||
313 | { IRDA_XID_CMD>>2, "Exchange Station Identification" }, |
||
314 | { XDLC_TEST>>2, "Test" }, |
||
315 | { 0, NULL } |
||
316 | }; |
||
317 | |||
318 | static const value_string lap_c_u_rsp_vals[] = { |
||
319 | { XDLC_SNRM>>2, "Request Normal Response Mode" }, |
||
320 | { XDLC_UA>>2, "Unnumbered Acknowledge" }, |
||
321 | { XDLC_FRMR>>2, "Frame Reject" }, |
||
322 | { XDLC_DM>>2, "Disconnect Mode" }, |
||
323 | { XDLC_RD>>2, "Request Disconnect" }, |
||
324 | { XDLC_UI>>2, "Unnumbered Information" }, |
||
325 | { XDLC_XID>>2, "Exchange Station Identification" }, |
||
326 | { XDLC_TEST>>2, "Test" }, |
||
327 | { 0, NULL } |
||
328 | }; |
||
329 | |||
330 | static const value_string lap_c_s_vals[] = { |
||
331 | { XDLC_RR>>2, "Receiver ready" }, |
||
332 | { XDLC_RNR>>2, "Receiver not ready" }, |
||
333 | { XDLC_REJ>>2, "Reject" }, |
||
334 | { XDLC_SREJ>>2, "Selective reject" }, |
||
335 | { 0, NULL } |
||
336 | }; |
||
337 | |||
338 | static const value_string xid_slot_numbers[] = { |
||
339 | /* Number of XID slots */ |
||
340 | { 0, "1" }, |
||
341 | { 1, "6" }, |
||
342 | { 2, "8" }, |
||
343 | { 3, "16" }, |
||
344 | { 0, NULL } |
||
345 | }; |
||
346 | |||
347 | static const value_string lmp_opcode_vals[] = { |
||
348 | /* IrLMP frame opcodes */ |
||
349 | { CONNECT_CMD, "Connect Command" }, |
||
350 | { CONNECT_CNF, "Connect Confirm" }, |
||
351 | { DISCONNECT, "Disconnect" }, |
||
352 | { ACCESSMODE_CMD, "Access Mode Command" }, |
||
353 | { ACCESSMODE_CNF, "Access Mode Confirm" }, |
||
354 | { 0, NULL } |
||
355 | }; |
||
356 | |||
357 | static const value_string lmp_reason_vals[] = { |
||
358 | /* IrLMP disconnect reasons */ |
||
359 | { 0x01, "User Request" }, |
||
360 | { 0x02, "Unexpected IrLAP Disconnect" }, |
||
361 | { 0x03, "Failed to establish IrLAP connection" }, |
||
362 | { 0x04, "IrLAP Reset" }, |
||
363 | { 0x05, "Link Management Initiated Disconnect" }, |
||
364 | { 0x06, "Data delivered on disconnected LSAP-Connection"}, |
||
365 | { 0x07, "Non Responsive LM-MUX Client" }, |
||
366 | { 0x08, "No available LM-MUX Client" }, |
||
367 | { 0x09, "Connection Half Open" }, |
||
368 | { 0x0A, "Illegal Source Address" }, |
||
369 | { 0xFF, "Unspecified Disconnect Reason" }, |
||
370 | { 0, NULL } |
||
371 | }; |
||
372 | |||
373 | static const value_string lmp_mode_vals[] = { |
||
374 | /* IrLMP modes */ |
||
375 | { 0x00, "Multiplexed" }, |
||
376 | { 0x01, "Exclusive" }, |
||
377 | { 0, NULL } |
||
378 | }; |
||
379 | |||
380 | static const value_string lmp_status_vals[] = { |
||
381 | /* IrLMP status */ |
||
382 | { 0x00, "Success" }, |
||
383 | { 0x01, "Failure" }, |
||
384 | { 0xFF, "Unsupported" }, |
||
385 | { 0, NULL } |
||
386 | }; |
||
387 | |||
388 | static const value_string iap_opcode_vals[] = { |
||
389 | /* IrIAP Op-codes */ |
||
390 | { GET_INFO_BASE, "GetInfoBase" }, |
||
391 | { GET_OBJECTS, "GetObjects" }, |
||
392 | { GET_VALUE, "GetValue" }, |
||
393 | { GET_VALUE_BY_CLASS, "GetValueByClass" }, |
||
394 | { GET_OBJECT_INFO, "GetObjectInfo" }, |
||
395 | { GET_ATTRIB_NAMES, "GetAttributeNames" }, |
||
396 | { 0, NULL } |
||
397 | }; |
||
398 | |||
399 | static const value_string iap_return_vals[] = { |
||
400 | /* IrIAP Return-codes */ |
||
401 | { IAS_SUCCESS, "Success" }, |
||
402 | { IAS_CLASS_UNKNOWN, "Class/Object Unknown" }, |
||
403 | { IAS_ATTRIB_UNKNOWN, "Attribute Unknown" }, |
||
404 | { IAS_ATTR_TOO_LONG, "Attribute List Too Long" }, |
||
405 | { IAS_DISCONNECT, "Disconnect (Linux-IrDA only)" }, |
||
406 | { IAS_UNSUPPORTED, "Unsupported Optional Operation" }, |
||
407 | { 0, NULL } |
||
408 | }; |
||
409 | |||
410 | static const value_string iap_attr_type_vals[] = { |
||
411 | /* LM-IAS Attribute types */ |
||
412 | { IAS_MISSING, "Missing" }, |
||
413 | { IAS_INTEGER, "Integer" }, |
||
414 | { IAS_OCT_SEQ, "Octet Sequence" }, |
||
415 | { IAS_STRING, "String" }, |
||
416 | { 0, NULL } |
||
417 | }; |
||
418 | |||
419 | static ias_attr_dissector_t device_attr_dissector[] = { |
||
420 | /* Device attribute dissectors */ |
||
421 | /* { "IrLMPSupport", xxx }, not implemented yet... */ |
||
422 | { NULL, NULL } |
||
423 | }; |
||
424 | |||
425 | /* IAS class dissectors */ |
||
426 | static ias_class_dissector_t class_dissector[] = { CLASS_DISSECTORS }; |
||
427 | |||
428 | |||
429 | /* |
||
430 | * Dissect parameter tuple |
||
431 | */ |
||
432 | guint dissect_param_tuple(tvbuff_t* tvb, proto_tree* tree, guint offset) |
||
433 | { |
||
434 | guint8 len = tvb_get_guint8(tvb, offset + 1); |
||
435 | |||
436 | if (tree) |
||
437 | proto_tree_add_item(tree, hf_param_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
438 | offset++; |
||
439 | |||
440 | if (tree) |
||
441 | proto_tree_add_item(tree, hf_param_pl, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
442 | offset++; |
||
443 | |||
444 | if (len > 0) |
||
445 | { |
||
446 | if (tree) |
||
447 | proto_tree_add_item(tree, hf_param_pv, tvb, offset, len, ENC_NA); |
||
448 | offset += len; |
||
449 | } |
||
450 | |||
451 | return offset; |
||
452 | } |
||
453 | |||
454 | |||
455 | /* |
||
456 | * Dissect TTP |
||
457 | */ |
||
458 | static guint dissect_ttp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, gboolean data) |
||
459 | { |
||
460 | guint offset = 0; |
||
461 | guint8 head; |
||
462 | char buf[128]; |
||
463 | |||
464 | if (tvb_reported_length(tvb) == 0) |
||
465 | return 0; |
||
466 | |||
467 | /* Make entries in Protocol column on summary display */ |
||
468 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TTP"); |
||
469 | |||
470 | head = tvb_get_guint8(tvb, offset); |
||
471 | |||
472 | g_snprintf(buf, 128, ", Credit=%d", head & ~TTP_PARAMETERS); |
||
473 | col_append_str(pinfo->cinfo, COL_INFO, buf); |
||
474 | |||
475 | if (root) |
||
476 | { |
||
477 | /* create display subtree for the protocol */ |
||
478 | proto_item* ti = proto_tree_add_item(root, proto_ttp, tvb, 0, -1, ENC_NA); |
||
479 | proto_tree* tree = proto_item_add_subtree(ti, ett_ttp); |
||
480 | |||
481 | if (data) |
||
482 | { |
||
483 | proto_tree_add_item(tree, hf_ttp_m, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
484 | proto_tree_add_item(tree, hf_ttp_dcredit, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
485 | offset++; |
||
486 | } |
||
487 | else |
||
488 | { |
||
489 | proto_tree_add_item(tree, hf_ttp_p, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
490 | proto_tree_add_item(tree, hf_ttp_icredit, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
491 | offset++; |
||
492 | } |
||
493 | proto_item_set_len(tree, offset); |
||
494 | } |
||
495 | else |
||
496 | offset++; |
||
497 | |||
498 | return offset; |
||
499 | } |
||
500 | |||
501 | |||
502 | /* |
||
503 | * Dissect IAP request |
||
504 | */ |
||
505 | static void dissect_iap_request(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, guint8 circuit_id) |
||
506 | { |
||
507 | guint offset = 0; |
||
508 | guint8 op; |
||
509 | guint8 clen = 0; |
||
510 | guint8 alen = 0; |
||
511 | guint8 src; |
||
512 | address srcaddr; |
||
513 | address destaddr; |
||
514 | conversation_t* conv; |
||
515 | iap_conversation_t* iap_conv; |
||
516 | char buf[128]; |
||
517 | |||
518 | if (tvb_reported_length(tvb) == 0) |
||
519 | return; |
||
520 | |||
521 | /* Make entries in Protocol column on summary display */ |
||
522 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAP"); |
||
523 | |||
524 | op = tvb_get_guint8(tvb, offset) & IAP_OP; |
||
525 | |||
526 | switch (op) |
||
527 | { |
||
528 | case GET_VALUE_BY_CLASS: |
||
529 | clen = MIN(tvb_get_guint8(tvb, offset + 1), 60); |
||
530 | alen = MIN(tvb_get_guint8(tvb, offset + 1 + 1 + clen), 60); |
||
531 | |||
532 | /* create conversation entry */ |
||
533 | src = circuit_id ^ CMD_FRAME; |
||
534 | set_address(&srcaddr, irda_address_type, 1, &src); |
||
535 | |||
536 | set_address(&destaddr, irda_address_type, 1, &circuit_id); |
||
537 | |||
538 | conv = find_conversation(pinfo->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0); |
||
539 | if (conv) |
||
540 | { |
||
541 | iap_conv = (iap_conversation_t*)conversation_get_proto_data(conv, proto_iap); |
||
542 | while (1) |
||
543 | { |
||
544 | if (iap_conv->iap_query_frame == pinfo->num) |
||
545 | { |
||
546 | iap_conv = NULL; |
||
547 | break; |
||
548 | } |
||
549 | if (iap_conv->pnext == NULL) |
||
550 | { |
||
551 | iap_conv->pnext = wmem_new(wmem_file_scope(), iap_conversation_t); |
||
552 | iap_conv = iap_conv->pnext; |
||
553 | break; |
||
554 | } |
||
555 | iap_conv = iap_conv->pnext; |
||
556 | } |
||
557 | } |
||
558 | else |
||
559 | { |
||
560 | conv = conversation_new(pinfo->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0); |
||
561 | iap_conv = wmem_new(wmem_file_scope(), iap_conversation_t); |
||
562 | conversation_add_proto_data(conv, proto_iap, (void*)iap_conv); |
||
563 | } |
||
564 | |||
565 | /* Dissect IAP query if it is new */ |
||
566 | if (iap_conv) |
||
567 | { |
||
568 | int i, j; |
||
569 | char class_name[256]; |
||
570 | char attr_name[256]; |
||
571 | |||
572 | |||
573 | iap_conv->pnext = NULL; |
||
574 | iap_conv->iap_query_frame = pinfo->num; |
||
575 | iap_conv->pattr_dissector = NULL; |
||
576 | |||
577 | tvb_memcpy(tvb, class_name, offset + 1 + 1, clen); |
||
578 | class_name[clen] = 0; |
||
579 | tvb_memcpy(tvb, attr_name, offset + 1 + 1 + clen + 1, alen); |
||
580 | attr_name[alen] = 0; |
||
581 | |||
582 | /* Find the attribute dissector */ |
||
583 | for (i = 0; class_dissector[i].class_name != NULL; i++) |
||
584 | if (strcmp(class_name, class_dissector[i].class_name) == 0) |
||
585 | { |
||
586 | for (j = 0; class_dissector[i].pattr_dissector[j].attr_name != NULL; j++) |
||
587 | if (strcmp(attr_name, class_dissector[i].pattr_dissector[j].attr_name) == 0) |
||
588 | { |
||
589 | iap_conv->pattr_dissector = &class_dissector[i].pattr_dissector[j]; |
||
590 | break; |
||
591 | } |
||
592 | break; |
||
593 | } |
||
594 | } |
||
595 | |||
596 | col_set_str(pinfo->cinfo, COL_INFO, "GetValueByClass: \""); |
||
597 | |||
598 | tvb_memcpy(tvb, buf, offset + 1 + 1, clen); |
||
599 | memcpy(&buf[clen], "\" \"", 3); |
||
600 | tvb_memcpy(tvb, buf + clen + 3, offset + 1 + 1 + clen + 1, alen); |
||
601 | buf[clen + 3 + alen] = '\"'; |
||
602 | buf[clen + 3 + alen + 1] = 0; |
||
603 | col_append_str(pinfo->cinfo, COL_INFO, buf); |
||
604 | } |
||
605 | |||
606 | if (root) |
||
607 | { |
||
608 | /* create display subtree for the protocol */ |
||
609 | proto_item* ti = proto_tree_add_item(root, proto_iap, tvb, 0, -1, ENC_NA); |
||
610 | proto_tree* tree = proto_item_add_subtree(ti, ett_iap); |
||
611 | |||
612 | proto_tree* ctl_tree; |
||
613 | |||
614 | |||
615 | ti = proto_tree_add_item(tree, hf_iap_ctl, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
616 | ctl_tree = proto_item_add_subtree(ti, ett_iap_ctl); |
||
617 | proto_tree_add_item(ctl_tree, hf_iap_ctl_lst, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
618 | proto_tree_add_item(ctl_tree, hf_iap_ctl_ack, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
619 | proto_tree_add_item(ctl_tree, hf_iap_ctl_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
620 | offset++; |
||
621 | |||
622 | switch (op) |
||
623 | { |
||
624 | case GET_VALUE_BY_CLASS: |
||
625 | proto_tree_add_item(tree, hf_iap_class_name, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN); |
||
626 | offset += 1 + clen; |
||
627 | |||
628 | proto_tree_add_item(tree, hf_iap_attr_name, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN); |
||
629 | offset += 1 + alen; |
||
630 | break; |
||
631 | } |
||
632 | } |
||
633 | else |
||
634 | { |
||
635 | offset++; |
||
636 | switch (op) |
||
637 | { |
||
638 | case GET_VALUE_BY_CLASS: |
||
639 | offset += 1 + clen + 1 + alen; |
||
640 | break; |
||
641 | } |
||
642 | } |
||
643 | |||
644 | /* If any bytes remain, send it to the generic data dissector */ |
||
645 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
646 | call_data_dissector(tvb, pinfo, root); |
||
647 | } |
||
648 | |||
649 | |||
650 | /* |
||
651 | * Dissect IAP result |
||
652 | */ |
||
653 | static void dissect_iap_result(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, guint8 circuit_id) |
||
654 | { |
||
655 | guint offset = 0; |
||
656 | guint len = tvb_reported_length(tvb); |
||
657 | guint n = 0; |
||
658 | guint list_len; |
||
659 | guint8 op; |
||
660 | guint8 retcode; |
||
661 | guint8 type; |
||
662 | guint16 attr_len; |
||
663 | char buf[300]; |
||
664 | guint8 src; |
||
665 | address srcaddr; |
||
666 | address destaddr; |
||
667 | conversation_t* conv; |
||
668 | iap_conversation_t* cur_iap_conv; |
||
669 | iap_conversation_t* iap_conv = NULL; |
||
670 | guint32 num; |
||
671 | |||
672 | |||
673 | if (len == 0) |
||
674 | return; |
||
675 | |||
676 | /* Make entries in Protocol column on summary display */ |
||
677 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAP"); |
||
678 | |||
679 | op = tvb_get_guint8(tvb, offset) & IAP_OP; |
||
680 | retcode = tvb_get_guint8(tvb, offset + 1); |
||
681 | |||
682 | src = circuit_id ^ CMD_FRAME; |
||
683 | set_address(&srcaddr, irda_address_type, 1, &src); |
||
684 | |||
685 | set_address(&destaddr, irda_address_type, 1, &circuit_id); |
||
686 | |||
687 | /* Find result value dissector */ |
||
688 | conv = find_conversation(pinfo->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0); |
||
689 | if (conv) |
||
690 | { |
||
691 | num = pinfo->num; |
||
692 | |||
693 | iap_conv = (iap_conversation_t*)conversation_get_proto_data(conv, proto_iap); |
||
694 | while (iap_conv && (iap_conv->iap_query_frame >= num)) |
||
695 | iap_conv = iap_conv->pnext; |
||
696 | |||
697 | if (iap_conv) |
||
698 | { |
||
699 | cur_iap_conv = iap_conv->pnext; |
||
700 | while (cur_iap_conv) |
||
701 | { |
||
702 | if ((cur_iap_conv->iap_query_frame < num) && |
||
703 | (cur_iap_conv->iap_query_frame > iap_conv->iap_query_frame)) |
||
704 | { |
||
705 | iap_conv = cur_iap_conv; |
||
706 | } |
||
707 | |||
708 | cur_iap_conv = cur_iap_conv->pnext; |
||
709 | } |
||
710 | } |
||
711 | } |
||
712 | |||
713 | col_set_str(pinfo->cinfo, COL_INFO, "Result: "); |
||
714 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str(retcode, iap_return_vals, "0x%02X")); |
||
715 | |||
716 | switch (op) |
||
717 | { |
||
718 | case GET_VALUE_BY_CLASS: |
||
719 | if (retcode == 0) |
||
720 | { |
||
721 | switch (tvb_get_guint8(tvb, offset + 6)) |
||
722 | { |
||
723 | case IAS_MISSING: |
||
724 | col_append_str(pinfo->cinfo, COL_INFO, ", Missing"); |
||
725 | break; |
||
726 | |||
727 | case IAS_INTEGER: |
||
728 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Integer: %d", tvb_get_ntohl(tvb, offset + 7)); |
||
729 | break; |
||
730 | |||
731 | case IAS_OCT_SEQ: |
||
732 | g_snprintf(buf, 300, ", %d Octets", tvb_get_ntohs(tvb, offset + 7)); |
||
733 | break; |
||
734 | |||
735 | case IAS_STRING: |
||
736 | n = tvb_get_guint8(tvb, offset + 8); |
||
737 | col_append_fstr(pinfo->cinfo, COL_INFO, ", \"%s\"", tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 9, n, ENC_ASCII)); |
||
738 | break; |
||
739 | default: |
||
740 | break; |
||
741 | } |
||
742 | if (tvb_get_ntohs(tvb, offset + 2) > 1) |
||
743 | col_append_str(pinfo->cinfo, COL_INFO, ", ..."); |
||
744 | } |
||
745 | break; |
||
746 | } |
||
747 | |||
748 | if (root) |
||
749 | { |
||
750 | /* create display subtree for the protocol */ |
||
751 | proto_item* ti = proto_tree_add_item(root, proto_iap, tvb, 0, -1, ENC_NA); |
||
752 | proto_tree* tree = proto_item_add_subtree(ti, ett_iap); |
||
753 | |||
754 | proto_tree* ctl_tree; |
||
755 | proto_tree* entry_tree; |
||
756 | |||
757 | |||
758 | ti = proto_tree_add_item(tree, hf_iap_ctl, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
759 | ctl_tree = proto_item_add_subtree(ti, ett_iap_ctl); |
||
760 | proto_tree_add_item(ctl_tree, hf_iap_ctl_lst, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
761 | proto_tree_add_item(ctl_tree, hf_iap_ctl_ack, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
762 | proto_tree_add_item(ctl_tree, hf_iap_ctl_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
763 | offset++; |
||
764 | |||
765 | proto_tree_add_item(tree, hf_iap_return, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
766 | offset++; |
||
767 | |||
768 | switch (op) |
||
769 | { |
||
770 | case GET_VALUE_BY_CLASS: |
||
771 | if (retcode == 0) |
||
772 | { |
||
773 | list_len = tvb_get_ntohs(tvb, offset); |
||
774 | |||
775 | proto_tree_add_item(tree, hf_iap_list_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
||
776 | offset += 2; |
||
777 | |||
778 | while ((offset < len) && (n < list_len)) |
||
779 | { |
||
780 | type = tvb_get_guint8(tvb, offset + 2); |
||
781 | switch (type) |
||
782 | { |
||
783 | case IAS_INTEGER: |
||
784 | attr_len = 4; |
||
785 | break; |
||
786 | |||
787 | case IAS_OCT_SEQ: |
||
788 | attr_len = tvb_get_ntohs(tvb, offset + 2 + 1) + 2; |
||
789 | break; |
||
790 | |||
791 | case IAS_STRING: |
||
792 | attr_len = tvb_get_guint8(tvb, offset + 2 + 1 + 1) + 2; |
||
793 | break; |
||
794 | |||
795 | default: |
||
796 | attr_len = 0; |
||
797 | } |
||
798 | |||
799 | ti = proto_tree_add_item(tree, hf_iap_list_entry, tvb, offset, 2 + 1 + attr_len, ENC_NA); |
||
800 | proto_item_append_text(ti, "%d", n + 1); |
||
801 | entry_tree = proto_item_add_subtree(ti, ett_iap_entry[n]); |
||
802 | |||
803 | proto_tree_add_item(entry_tree, hf_iap_obj_id, tvb, offset, 2, ENC_BIG_ENDIAN); |
||
804 | offset += 2; |
||
805 | |||
806 | proto_tree_add_item(entry_tree, hf_iap_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
807 | offset++; |
||
808 | |||
809 | switch (type) |
||
810 | { |
||
811 | case IAS_INTEGER: |
||
812 | if (!iap_conv || !iap_conv->pattr_dissector || |
||
813 | !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree, |
||
814 | n, type, circuit_id)) |
||
815 | proto_tree_add_item(entry_tree, hf_iap_int, tvb, offset, 4, ENC_BIG_ENDIAN); |
||
816 | break; |
||
817 | |||
818 | case IAS_OCT_SEQ: |
||
819 | proto_tree_add_item(entry_tree, hf_iap_seq_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
||
820 | if (!iap_conv || !iap_conv->pattr_dissector || |
||
821 | !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree, |
||
822 | n, type, circuit_id)) |
||
823 | proto_tree_add_item(entry_tree, hf_iap_oct_seq, tvb, offset + 2, |
||
824 | attr_len - 2, ENC_NA); |
||
825 | break; |
||
826 | |||
827 | case IAS_STRING: |
||
828 | proto_tree_add_item(entry_tree, hf_iap_char_set, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
829 | if (!iap_conv || !iap_conv->pattr_dissector || |
||
830 | !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree, |
||
831 | n, type, circuit_id)) |
||
832 | proto_tree_add_item(entry_tree, hf_iap_string, tvb, offset + 1, 1, ENC_ASCII|ENC_BIG_ENDIAN); |
||
833 | break; |
||
834 | } |
||
835 | offset += attr_len; |
||
836 | |||
837 | n++; |
||
838 | } |
||
839 | } |
||
840 | break; |
||
841 | } |
||
842 | } |
||
843 | else |
||
844 | { |
||
845 | offset += 2; |
||
846 | switch (op) |
||
847 | { |
||
848 | case GET_VALUE_BY_CLASS: |
||
849 | if (retcode == 0) |
||
850 | { |
||
851 | offset += 2; |
||
852 | |||
853 | while (offset < len) |
||
854 | { |
||
855 | offset += 2; |
||
856 | type = tvb_get_guint8(tvb, offset); |
||
857 | offset++; |
||
858 | |||
859 | switch (type) |
||
860 | { |
||
861 | case IAS_INTEGER: |
||
862 | attr_len = 4; |
||
863 | if (iap_conv && iap_conv->pattr_dissector) |
||
864 | iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0, |
||
865 | n, type, circuit_id); |
||
866 | break; |
||
867 | |||
868 | case IAS_OCT_SEQ: |
||
869 | attr_len = tvb_get_ntohs(tvb, offset) + 2; |
||
870 | if (iap_conv && iap_conv->pattr_dissector) |
||
871 | iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0, |
||
872 | n, type, circuit_id); |
||
873 | break; |
||
874 | |||
875 | case IAS_STRING: |
||
876 | attr_len = tvb_get_guint8(tvb, offset + 1) + 2; |
||
877 | if (iap_conv && iap_conv->pattr_dissector) |
||
878 | iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0, |
||
879 | n, type, circuit_id); |
||
880 | break; |
||
881 | |||
882 | default: |
||
883 | attr_len = 0; |
||
884 | } |
||
885 | offset += attr_len; |
||
886 | |||
887 | n++; |
||
888 | } |
||
889 | } |
||
890 | break; |
||
891 | } |
||
892 | } |
||
893 | |||
894 | /* If any bytes remain, send it to the generic data dissector */ |
||
895 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
896 | call_data_dissector(tvb, pinfo, root); |
||
897 | } |
||
898 | |||
899 | |||
900 | /* |
||
901 | * Check if IAP result is octet sequence |
||
902 | */ |
||
903 | gboolean check_iap_octet_result(tvbuff_t* tvb, proto_tree* tree, guint offset, |
||
904 | const char* attr_name, guint8 attr_type) |
||
905 | { |
||
906 | if (attr_type != IAS_OCT_SEQ) |
||
907 | { |
||
908 | if (tree) |
||
909 | { |
||
910 | proto_item* ti = proto_tree_add_item(tree, hf_iap_invaloctet, tvb, offset, 0, ENC_NA); |
||
911 | proto_item_append_text(ti, "%s", attr_name); |
||
912 | proto_item_append_text(ti, "\" attribute must be octet sequence!"); |
||
913 | } |
||
914 | |||
915 | return FALSE; |
||
916 | } |
||
917 | else |
||
918 | return TRUE; |
||
919 | } |
||
920 | |||
921 | |||
922 | /* |
||
923 | * Check if IAP result is correct LsapSel |
||
924 | */ |
||
925 | guint8 check_iap_lsap_result(tvbuff_t* tvb, proto_tree* tree, guint offset, |
||
926 | const char* attr_name, guint8 attr_type) |
||
927 | { |
||
928 | guint32 lsap; |
||
929 | |||
930 | |||
931 | if ((attr_type != IAS_INTEGER) || ((lsap = tvb_get_ntohl(tvb, offset)) < 0x01) || |
||
932 | (lsap > 0x6F)) |
||
933 | { |
||
934 | if (tree) |
||
935 | { |
||
936 | proto_item* ti = proto_tree_add_item(tree, hf_iap_invallsap, tvb, offset, 0, ENC_NA); |
||
937 | proto_item_append_text(ti, "%s", attr_name); |
||
938 | proto_item_append_text(ti, "\" attribute must be integer value between 0x01 and 0x6F!"); |
||
939 | } |
||
940 | |||
941 | return 0; |
||
942 | } |
||
943 | else |
||
944 | return lsap; |
||
945 | } |
||
946 | |||
947 | |||
948 | /* |
||
949 | * Dissect IrDA application protocol |
||
950 | */ |
||
951 | static void dissect_appl_proto(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, pdu_type_t pdu_type, guint8 circuit_id) |
||
952 | { |
||
953 | guint offset = 0; |
||
954 | guint8 src; |
||
955 | address srcaddr; |
||
956 | address destaddr; |
||
957 | conversation_t* conv; |
||
958 | lmp_conversation_t* cur_lmp_conv; |
||
959 | lmp_conversation_t* lmp_conv = NULL; |
||
960 | guint32 num; |
||
961 | |||
962 | |||
963 | src = circuit_id ^ CMD_FRAME; |
||
964 | set_address(&srcaddr, irda_address_type, 1, &src); |
||
965 | |||
966 | set_address(&destaddr, irda_address_type, 1, &circuit_id); |
||
967 | |||
968 | /* Find result value dissector */ |
||
969 | conv = find_conversation(pinfo->num, &srcaddr, &destaddr, PT_NONE, pinfo->srcport, pinfo->destport, 0); |
||
970 | if (conv) |
||
971 | { |
||
972 | num = pinfo->num; |
||
973 | |||
974 | lmp_conv = (lmp_conversation_t*)conversation_get_proto_data(conv, proto_irlmp); |
||
975 | while (lmp_conv && (lmp_conv->iap_result_frame >= num)) |
||
976 | lmp_conv = lmp_conv->pnext; |
||
977 | |||
978 | if (lmp_conv) |
||
979 | { |
||
980 | cur_lmp_conv = lmp_conv->pnext; |
||
981 | while (cur_lmp_conv) |
||
982 | { |
||
983 | if ((cur_lmp_conv->iap_result_frame < num) && |
||
984 | (cur_lmp_conv->iap_result_frame > lmp_conv->iap_result_frame)) |
||
985 | { |
||
986 | lmp_conv = cur_lmp_conv; |
||
987 | } |
||
988 | |||
989 | cur_lmp_conv = cur_lmp_conv->pnext; |
||
990 | } |
||
991 | } |
||
992 | } |
||
993 | |||
994 | if (lmp_conv) |
||
995 | { |
||
996 | /*g_message("%x:%d->%x:%d = %p\n", src, pinfo->srcport, circuit_id, pinfo->destport, lmp_conv); */ |
||
997 | /*g_message("->%d: %d %d %p\n", pinfo->num, lmp_conv->iap_result_frame, lmp_conv->ttp, lmp_conv->proto_dissector); */ |
||
998 | if ((lmp_conv->ttp) && (pdu_type != DISCONNECT_PDU)) |
||
999 | { |
||
1000 | offset += dissect_ttp(tvb, pinfo, root, (pdu_type == DATA_PDU)); |
||
1001 | |||
1002 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1003 | } |
||
1004 | |||
1005 | call_dissector_with_data(lmp_conv->dissector, tvb, pinfo, root, GUINT_TO_POINTER(pdu_type)); |
||
1006 | } |
||
1007 | else |
||
1008 | call_data_dissector(tvb, pinfo, root); |
||
1009 | } |
||
1010 | |||
1011 | |||
1012 | /* |
||
1013 | * Dissect LMP |
||
1014 | */ |
||
1015 | static void dissect_irlmp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, guint8 circuit_id) |
||
1016 | { |
||
1017 | guint offset = 0; |
||
1018 | guint8 dlsap; |
||
1019 | guint8 slsap; |
||
1020 | guint8 cbit; |
||
1021 | guint8 opcode = 0; |
||
1022 | |||
1023 | |||
1024 | /* Make entries in Protocol column on summary display */ |
||
1025 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrLMP"); |
||
1026 | |||
1027 | dlsap = tvb_get_guint8(tvb, offset); |
||
1028 | cbit = dlsap & CONTROL_BIT; |
||
1029 | dlsap &= ~CONTROL_BIT; |
||
1030 | |||
1031 | slsap = tvb_get_guint8(tvb, offset+1) & ~CONTROL_BIT; |
||
1032 | |||
1033 | /* save Lsaps in pinfo */ |
||
1034 | pinfo->srcport = slsap; |
||
1035 | pinfo->destport = dlsap; |
||
1036 | |||
1037 | if (cbit != 0) |
||
1038 | { |
||
1039 | opcode = tvb_get_guint8(tvb, offset+2); |
||
1040 | |||
1041 | col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d, ", slsap, dlsap); |
||
1042 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, lmp_opcode_vals, "0x%02X")); |
||
1043 | if ((opcode == ACCESSMODE_CMD) || (opcode == ACCESSMODE_CNF)) |
||
1044 | { |
||
1045 | col_append_str(pinfo->cinfo, COL_INFO, " ("); |
||
1046 | col_append_str(pinfo->cinfo, COL_INFO, |
||
1047 | val_to_str(tvb_get_guint8(tvb, offset+4), lmp_mode_vals, "0x%02X")); |
||
1048 | col_append_str(pinfo->cinfo, COL_INFO, ")"); |
||
1049 | } |
||
1050 | } |
||
1051 | else |
||
1052 | col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d, Len=%d", slsap, dlsap, |
||
1053 | tvb_reported_length(tvb) - 2); |
||
1054 | |||
1055 | if (root) |
||
1056 | { |
||
1057 | /* create display subtree for the protocol */ |
||
1058 | proto_item* ti = proto_tree_add_item(root, proto_irlmp, tvb, 0, -1, ENC_NA); |
||
1059 | proto_tree* tree = proto_item_add_subtree(ti, ett_irlmp); |
||
1060 | |||
1061 | proto_tree* dst_tree; |
||
1062 | proto_tree* src_tree; |
||
1063 | |||
1064 | |||
1065 | ti = proto_tree_add_item(tree, hf_lmp_dst, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1066 | dst_tree = proto_item_add_subtree(ti, ett_lmp_dst); |
||
1067 | proto_tree_add_item(dst_tree, hf_lmp_dst_control, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1068 | proto_tree_add_item(dst_tree, hf_lmp_dst_lsap, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1069 | offset++; |
||
1070 | |||
1071 | ti = proto_tree_add_item(tree, hf_lmp_src, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1072 | src_tree = proto_item_add_subtree(ti, ett_lmp_src); |
||
1073 | proto_tree_add_item(src_tree, hf_lmp_src_r, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1074 | proto_tree_add_item(src_tree, hf_lmp_src_lsap, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1075 | offset++; |
||
1076 | |||
1077 | if (cbit != 0) |
||
1078 | { |
||
1079 | proto_tree_add_item(tree, hf_lmp_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1080 | offset++; |
||
1081 | |||
1082 | switch (opcode) |
||
1083 | { |
||
1084 | case CONNECT_CMD: |
||
1085 | case CONNECT_CNF: |
||
1086 | if (offset < tvb_reported_length(tvb)) |
||
1087 | { |
||
1088 | proto_tree_add_item(tree, hf_lmp_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1089 | offset++; |
||
1090 | } |
||
1091 | break; |
||
1092 | |||
1093 | case DISCONNECT: |
||
1094 | proto_tree_add_item(tree, hf_lmp_reason, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1095 | offset++; |
||
1096 | break; |
||
1097 | |||
1098 | case ACCESSMODE_CMD: |
||
1099 | proto_tree_add_item(tree, hf_lmp_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1100 | offset++; |
||
1101 | |||
1102 | proto_tree_add_item(tree, hf_lmp_mode, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1103 | offset++; |
||
1104 | break; |
||
1105 | |||
1106 | case ACCESSMODE_CNF: |
||
1107 | proto_tree_add_item( tree, hf_lmp_status, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1108 | offset++; |
||
1109 | |||
1110 | proto_tree_add_item(tree, hf_lmp_mode, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1111 | offset++; |
||
1112 | break; |
||
1113 | } |
||
1114 | } |
||
1115 | |||
1116 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1117 | proto_item_set_len(tree, offset); |
||
1118 | } |
||
1119 | else |
||
1120 | { |
||
1121 | offset += 2; |
||
1122 | if (cbit != 0) |
||
1123 | { |
||
1124 | offset += 1; |
||
1125 | |||
1126 | switch (opcode) |
||
1127 | { |
||
1128 | case CONNECT_CMD: |
||
1129 | case CONNECT_CNF: |
||
1130 | if (offset < tvb_reported_length(tvb)) |
||
1131 | offset++; |
||
1132 | break; |
||
1133 | |||
1134 | case DISCONNECT: |
||
1135 | offset++; |
||
1136 | break; |
||
1137 | |||
1138 | case ACCESSMODE_CMD: |
||
1139 | case ACCESSMODE_CNF: |
||
1140 | offset += 2; |
||
1141 | break; |
||
1142 | } |
||
1143 | } |
||
1144 | |||
1145 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1146 | } |
||
1147 | |||
1148 | if (cbit == 0) |
||
1149 | { |
||
1150 | if (dlsap == LSAP_IAS) |
||
1151 | dissect_iap_request(tvb, pinfo, root, circuit_id); |
||
1152 | else if (slsap == LSAP_IAS) |
||
1153 | dissect_iap_result(tvb, pinfo, root, circuit_id); |
||
1154 | else |
||
1155 | dissect_appl_proto(tvb, pinfo, root, DATA_PDU, circuit_id); |
||
1156 | } |
||
1157 | else |
||
1158 | { |
||
1159 | if ((dlsap == LSAP_IAS) || (slsap == LSAP_IAS)) |
||
1160 | call_data_dissector(tvb, pinfo, root); |
||
1161 | else |
||
1162 | switch (opcode) |
||
1163 | { |
||
1164 | case CONNECT_CMD: |
||
1165 | case CONNECT_CNF: |
||
1166 | dissect_appl_proto(tvb, pinfo, root, CONNECT_PDU, circuit_id); |
||
1167 | break; |
||
1168 | |||
1169 | case DISCONNECT: |
||
1170 | dissect_appl_proto(tvb, pinfo, root, DISCONNECT_PDU, circuit_id); |
||
1171 | break; |
||
1172 | |||
1173 | default: |
||
1174 | call_data_dissector(tvb, pinfo, root); |
||
1175 | } |
||
1176 | } |
||
1177 | } |
||
1178 | |||
1179 | |||
1180 | /* |
||
1181 | * Add LMP conversation |
||
1182 | */ |
||
1183 | void add_lmp_conversation(packet_info* pinfo, guint8 dlsap, gboolean ttp, dissector_handle_t dissector, guint8 circuit_id) |
||
1184 | { |
||
1185 | guint8 dest; |
||
1186 | address srcaddr; |
||
1187 | address destaddr; |
||
1188 | conversation_t* conv; |
||
1189 | lmp_conversation_t* lmp_conv = NULL; |
||
1190 | |||
1191 | |||
1192 | /*g_message("%d: add_lmp_conversation(%p, %d, %d, %p) = ", pinfo->num, pinfo, dlsap, ttp, proto_dissector); */ |
||
1193 | set_address(&srcaddr, irda_address_type, 1, &circuit_id); |
||
1194 | dest = circuit_id ^ CMD_FRAME; |
||
1195 | set_address(&destaddr, irda_address_type, 1, &dest); |
||
1196 | |||
1197 | conv = find_conversation(pinfo->num, &destaddr, &srcaddr, PT_NONE, dlsap, 0, NO_PORT_B); |
||
1198 | if (conv) |
||
1199 | { |
||
1200 | lmp_conv = (lmp_conversation_t*)conversation_get_proto_data(conv, proto_irlmp); |
||
1201 | while (1) |
||
1202 | { |
||
1203 | /* Does entry already exist? */ |
||
1204 | if (lmp_conv->iap_result_frame == pinfo->num) |
||
1205 | return; |
||
1206 | |||
1207 | if (lmp_conv->pnext == NULL) |
||
1208 | { |
||
1209 | lmp_conv->pnext = wmem_new(wmem_file_scope(), lmp_conversation_t); |
||
1210 | lmp_conv = lmp_conv->pnext; |
||
1211 | break; |
||
1212 | } |
||
1213 | lmp_conv = lmp_conv->pnext; |
||
1214 | } |
||
1215 | } |
||
1216 | else |
||
1217 | { |
||
1218 | conv = conversation_new(pinfo->num, &destaddr, &srcaddr, PT_NONE, dlsap, 0, NO_PORT_B); |
||
1219 | lmp_conv = wmem_new(wmem_file_scope(), lmp_conversation_t); |
||
1220 | conversation_add_proto_data(conv, proto_irlmp, (void*)lmp_conv); |
||
1221 | } |
||
1222 | |||
1223 | lmp_conv->pnext = NULL; |
||
1224 | lmp_conv->iap_result_frame = pinfo->num; |
||
1225 | lmp_conv->ttp = ttp; |
||
1226 | lmp_conv->dissector = dissector; |
||
1227 | |||
1228 | /*g_message("%p\n", lmp_conv); */ |
||
1229 | } |
||
1230 | |||
1231 | |||
1232 | /* |
||
1233 | * Dissect Negotiation Parameters |
||
1234 | */ |
||
1235 | static guint dissect_negotiation(tvbuff_t* tvb, proto_tree* tree, guint offset) |
||
1236 | { |
||
1237 | guint n = 0; |
||
1238 | proto_item* ti; |
||
1239 | proto_tree* p_tree; |
||
1240 | char buf[256]; |
||
1241 | guint8 pv; |
||
1242 | |||
1243 | while (tvb_reported_length_remaining(tvb, offset) > 0) |
||
1244 | { |
||
1245 | guint8 p_len = tvb_get_guint8(tvb, offset + 1); |
||
1246 | |||
1247 | if (tree) |
||
1248 | { |
||
1249 | ti = proto_tree_add_item(tree, hf_negotiation_param, tvb, offset, p_len + 2, ENC_NA); |
||
1250 | p_tree = proto_item_add_subtree(ti, ett_param[n]); |
||
1251 | |||
1252 | pv = tvb_get_guint8(tvb, offset+2); |
||
1253 | buf[0] = 0; |
||
1254 | |||
1255 | switch (tvb_get_guint8(tvb, offset)) |
||
1256 | { |
||
1257 | case PI_BAUD_RATE: |
||
1258 | proto_item_append_text(ti, ": Baud Rate ("); |
||
1259 | |||
1260 | if (pv & 0x01) |
||
1261 | g_strlcat(buf, ", 2400", 256); |
||
1262 | if (pv & 0x02) |
||
1263 | g_strlcat(buf, ", 9600", 256); |
||
1264 | if (pv & 0x04) |
||
1265 | g_strlcat(buf, ", 19200", 256); |
||
1266 | if (pv & 0x08) |
||
1267 | g_strlcat(buf, ", 38400", 256); |
||
1268 | if (pv & 0x10) |
||
1269 | g_strlcat(buf, ", 57600", 256); |
||
1270 | if (pv & 0x20) |
||
1271 | g_strlcat(buf, ", 115200", 256); |
||
1272 | if (pv & 0x40) |
||
1273 | g_strlcat(buf, ", 576000", 256); |
||
1274 | if (pv & 0x80) |
||
1275 | g_strlcat(buf, ", 1152000", 256); |
||
1276 | if ((p_len > 1) && (tvb_get_guint8(tvb, offset+3) & 0x01)) |
||
1277 | g_strlcat(buf, ", 4000000", 256); |
||
1278 | |||
1279 | g_strlcat(buf, " bps)", 256); |
||
1280 | |||
1281 | proto_item_append_text(ti, "%s", buf+2); |
||
1282 | |||
1283 | break; |
||
1284 | |||
1285 | case PI_MAX_TURN_TIME: |
||
1286 | proto_item_append_text(ti, ": Maximum Turn Time ("); |
||
1287 | |||
1288 | if (pv & 0x01) |
||
1289 | g_strlcat(buf, ", 500", 256); |
||
1290 | if (pv & 0x02) |
||
1291 | g_strlcat(buf, ", 250", 256); |
||
1292 | if (pv & 0x04) |
||
1293 | g_strlcat(buf, ", 100", 256); |
||
1294 | if (pv & 0x08) |
||
1295 | g_strlcat(buf, ", 50", 256); |
||
1296 | |||
1297 | g_strlcat(buf, " ms)", 256); |
||
1298 | |||
1299 | proto_item_append_text(ti, "%s", buf+2); |
||
1300 | |||
1301 | break; |
||
1302 | |||
1303 | case PI_DATA_SIZE: |
||
1304 | proto_item_append_text(ti, ": Data Size ("); |
||
1305 | |||
1306 | if (pv & 0x01) |
||
1307 | g_strlcat(buf, ", 64", 256); |
||
1308 | if (pv & 0x02) |
||
1309 | g_strlcat(buf, ", 128", 256); |
||
1310 | if (pv & 0x04) |
||
1311 | g_strlcat(buf, ", 256", 256); |
||
1312 | if (pv & 0x08) |
||
1313 | g_strlcat(buf, ", 512", 256); |
||
1314 | if (pv & 0x10) |
||
1315 | g_strlcat(buf, ", 1024", 256); |
||
1316 | if (pv & 0x20) |
||
1317 | g_strlcat(buf, ", 2048", 256); |
||
1318 | |||
1319 | g_strlcat(buf, " bytes)", 256); |
||
1320 | |||
1321 | proto_item_append_text(ti, "%s", buf+2); |
||
1322 | |||
1323 | break; |
||
1324 | |||
1325 | case PI_WINDOW_SIZE: |
||
1326 | proto_item_append_text(ti, ": Window Size ("); |
||
1327 | |||
1328 | if (pv & 0x01) |
||
1329 | g_strlcat(buf, ", 1", 256); |
||
1330 | if (pv & 0x02) |
||
1331 | g_strlcat(buf, ", 2", 256); |
||
1332 | if (pv & 0x04) |
||
1333 | g_strlcat(buf, ", 3", 256); |
||
1334 | if (pv & 0x08) |
||
1335 | g_strlcat(buf, ", 4", 256); |
||
1336 | if (pv & 0x10) |
||
1337 | g_strlcat(buf, ", 5", 256); |
||
1338 | if (pv & 0x20) |
||
1339 | g_strlcat(buf, ", 6", 256); |
||
1340 | if (pv & 0x40) |
||
1341 | g_strlcat(buf, ", 7", 256); |
||
1342 | |||
1343 | g_strlcat(buf, " frame window)", 256); |
||
1344 | |||
1345 | proto_item_append_text(ti, "%s", buf+2); |
||
1346 | |||
1347 | break; |
||
1348 | |||
1349 | case PI_ADD_BOFS: |
||
1350 | proto_item_append_text(ti, ": Additional BOFs ("); |
||
1351 | |||
1352 | if (pv & 0x01) |
||
1353 | g_strlcat(buf, ", 48", 256); |
||
1354 | if (pv & 0x02) |
||
1355 | g_strlcat(buf, ", 24", 256); |
||
1356 | if (pv & 0x04) |
||
1357 | g_strlcat(buf, ", 12", 256); |
||
1358 | if (pv & 0x08) |
||
1359 | g_strlcat(buf, ", 5", 256); |
||
1360 | if (pv & 0x10) |
||
1361 | g_strlcat(buf, ", 3", 256); |
||
1362 | if (pv & 0x20) |
||
1363 | g_strlcat(buf, ", 2", 256); |
||
1364 | if (pv & 0x40) |
||
1365 | g_strlcat(buf, ", 1", 256); |
||
1366 | if (pv & 0x80) |
||
1367 | g_strlcat(buf, ", 0", 256); |
||
1368 | |||
1369 | g_strlcat(buf, " additional BOFs at 115200)", 256); |
||
1370 | |||
1371 | proto_item_append_text(ti, "%s", buf+2); |
||
1372 | |||
1373 | break; |
||
1374 | |||
1375 | case PI_MIN_TURN_TIME: |
||
1376 | proto_item_append_text(ti, ": Minimum Turn Time ("); |
||
1377 | |||
1378 | if (pv & 0x01) |
||
1379 | g_strlcat(buf, ", 10", 256); |
||
1380 | if (pv & 0x02) |
||
1381 | g_strlcat(buf, ", 5", 256); |
||
1382 | if (pv & 0x04) |
||
1383 | g_strlcat(buf, ", 1", 256); |
||
1384 | if (pv & 0x08) |
||
1385 | g_strlcat(buf, ", 0.5", 256); |
||
1386 | if (pv & 0x10) |
||
1387 | g_strlcat(buf, ", 0.1", 256); |
||
1388 | if (pv & 0x20) |
||
1389 | g_strlcat(buf, ", 0.05", 256); |
||
1390 | if (pv & 0x40) |
||
1391 | g_strlcat(buf, ", 0.01", 256); |
||
1392 | if (pv & 0x80) |
||
1393 | g_strlcat(buf, ", 0", 256); |
||
1394 | |||
1395 | g_strlcat(buf, " ms)", 256); |
||
1396 | |||
1397 | proto_item_append_text(ti, "%s", buf+2); |
||
1398 | |||
1399 | break; |
||
1400 | |||
1401 | case PI_LINK_DISC: |
||
1402 | proto_item_append_text(ti, ": Link Disconnect/Threshold Time ("); |
||
1403 | |||
1404 | if (pv & 0x01) |
||
1405 | g_strlcat(buf, ", 3/0", 256); |
||
1406 | if (pv & 0x02) |
||
1407 | g_strlcat(buf, ", 8/3", 256); |
||
1408 | if (pv & 0x04) |
||
1409 | g_strlcat(buf, ", 12/3", 256); |
||
1410 | if (pv & 0x08) |
||
1411 | g_strlcat(buf, ", 16/3", 256); |
||
1412 | if (pv & 0x10) |
||
1413 | g_strlcat(buf, ", 20/3", 256); |
||
1414 | if (pv & 0x20) |
||
1415 | g_strlcat(buf, ", 25/3", 256); |
||
1416 | if (pv & 0x40) |
||
1417 | g_strlcat(buf, ", 30/3", 256); |
||
1418 | if (pv & 0x80) |
||
1419 | g_strlcat(buf, ", 40/3", 256); |
||
1420 | |||
1421 | g_strlcat(buf, " s)", 256); |
||
1422 | |||
1423 | proto_item_append_text(ti, "%s", buf+2); |
||
1424 | |||
1425 | break; |
||
1426 | |||
1427 | default: |
||
1428 | proto_item_append_text(ti, ": unknown"); |
||
1429 | } |
||
1430 | } else |
||
1431 | p_tree = NULL; |
||
1432 | |||
1433 | offset = dissect_param_tuple(tvb, p_tree, offset); |
||
1434 | n++; |
||
1435 | } |
||
1436 | |||
1437 | return offset; |
||
1438 | } |
||
1439 | |||
1440 | |||
1441 | /* |
||
1442 | * Dissect XID packet |
||
1443 | */ |
||
1444 | static void dissect_xid(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, proto_tree* lap_tree, gboolean is_command) |
||
1445 | { |
||
1446 | int offset = 0; |
||
1447 | proto_item* ti = NULL; |
||
1448 | proto_tree* i_tree = NULL; |
||
1449 | proto_tree* flags_tree; |
||
1450 | guint32 saddr, daddr; |
||
1451 | guint8 s; |
||
1452 | proto_tree* lmp_tree = NULL; |
||
1453 | |||
1454 | if (lap_tree) |
||
1455 | { |
||
1456 | ti = proto_tree_add_item(lap_tree, hf_lap_i, tvb, offset, -1, ENC_NA); |
||
1457 | i_tree = proto_item_add_subtree(ti, ett_lap_i); |
||
1458 | |||
1459 | proto_tree_add_item(i_tree, hf_xid_ident, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1460 | } |
||
1461 | offset++; |
||
1462 | |||
1463 | saddr = tvb_get_letohl(tvb, offset); |
||
1464 | col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr); |
||
1465 | if (lap_tree) |
||
1466 | proto_tree_add_uint(i_tree, hf_xid_saddr, tvb, offset, 4, saddr); |
||
1467 | offset += 4; |
||
1468 | |||
1469 | daddr = tvb_get_letohl(tvb, offset); |
||
1470 | col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr); |
||
1471 | if (lap_tree) |
||
1472 | proto_tree_add_uint(i_tree, hf_xid_daddr, tvb, offset, 4, daddr); |
||
1473 | offset += 4; |
||
1474 | |||
1475 | if (lap_tree) |
||
1476 | { |
||
1477 | ti = proto_tree_add_item(i_tree, hf_xid_flags, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1478 | flags_tree = proto_item_add_subtree(ti, ett_xid_flags); |
||
1479 | proto_tree_add_item(flags_tree, hf_xid_s, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1480 | proto_tree_add_item(flags_tree, hf_xid_conflict, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1481 | } |
||
1482 | offset++; |
||
1483 | |||
1484 | if (is_command) |
||
1485 | { |
||
1486 | s = tvb_get_guint8(tvb, offset); |
||
1487 | if (s == 0xFF) |
||
1488 | col_append_str(pinfo->cinfo, COL_INFO, ", s=final"); |
||
1489 | else |
||
1490 | col_append_fstr(pinfo->cinfo, COL_INFO, ", s=%u", s); |
||
1491 | if (lap_tree) |
||
1492 | { |
||
1493 | ti = proto_tree_add_uint(i_tree, hf_xid_slotnr, tvb, offset, 1, s); |
||
1494 | if (s == 0xFF) |
||
1495 | proto_item_append_text(ti, " (final)"); |
||
1496 | } |
||
1497 | } |
||
1498 | offset++; |
||
1499 | |||
1500 | if (lap_tree) |
||
1501 | proto_tree_add_item(i_tree, hf_xid_version, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1502 | offset++; |
||
1503 | |||
1504 | if (lap_tree) |
||
1505 | { |
||
1506 | proto_item_set_end(lap_tree, tvb, offset); |
||
1507 | proto_item_set_end(i_tree, tvb, offset); |
||
1508 | } |
||
1509 | |||
1510 | if (tvb_reported_length_remaining(tvb, offset) > 0) |
||
1511 | { |
||
1512 | guint hints_len; |
||
1513 | guint8 hint1 = 0; |
||
1514 | guint8 hint2 = 0; |
||
1515 | char buf[23]; |
||
1516 | |||
1517 | if (root) |
||
1518 | { |
||
1519 | ti = proto_tree_add_item(root, proto_irlmp, tvb, offset, -1, ENC_NA); |
||
1520 | lmp_tree = proto_item_add_subtree(ti, ett_irlmp); |
||
1521 | } |
||
1522 | |||
1523 | for (hints_len = 0;;) |
||
1524 | { |
||
1525 | guint8 hint = tvb_get_guint8(tvb, offset + hints_len++); |
||
1526 | |||
1527 | if (hints_len == 1) |
||
1528 | hint1 = hint; |
||
1529 | else if (hints_len == 2) |
||
1530 | hint2 = hint; |
||
1531 | |||
1532 | if ((hint & 0x80) == 0) |
||
1533 | break; |
||
1534 | } |
||
1535 | |||
1536 | if (root) |
||
1537 | { |
||
1538 | ti = proto_tree_add_item(lmp_tree, hf_lmp_xid_hints, tvb, offset, hints_len, ENC_NA); |
||
1539 | if ((hint1 | hint2) != 0) |
||
1540 | { |
||
1541 | char service_hints[256]; |
||
1542 | |||
1543 | service_hints[0] = 0; |
||
1544 | |||
1545 | if (hint1 & 0x01) |
||
1546 | g_strlcat(service_hints, ", PnP Compatible", 256); |
||
1547 | if (hint1 & 0x02) |
||
1548 | g_strlcat(service_hints, ", PDA/Palmtop", 256); |
||
1549 | if (hint1 & 0x04) |
||
1550 | g_strlcat(service_hints, ", Computer", 256); |
||
1551 | if (hint1 & 0x08) |
||
1552 | g_strlcat(service_hints, ", Printer", 256); |
||
1553 | if (hint1 & 0x10) |
||
1554 | g_strlcat(service_hints, ", Modem", 256); |
||
1555 | if (hint1 & 0x20) |
||
1556 | g_strlcat(service_hints, ", Fax", 256); |
||
1557 | if (hint1 & 0x40) |
||
1558 | g_strlcat(service_hints, ", LAN Access", 256); |
||
1559 | if (hint2 & 0x01) |
||
1560 | g_strlcat(service_hints, ", Telephony", 256); |
||
1561 | if (hint2 & 0x02) |
||
1562 | g_strlcat(service_hints, ", File Server", 256); |
||
1563 | if (hint2 & 0x04) |
||
1564 | g_strlcat(service_hints, ", IrCOMM", 256); |
||
1565 | if (hint2 & 0x20) |
||
1566 | g_strlcat(service_hints, ", OBEX", 256); |
||
1567 | |||
1568 | g_strlcat(service_hints, ")", 256); |
||
1569 | service_hints[0] = ' '; |
||
1570 | service_hints[1] = '('; |
||
1571 | |||
1572 | proto_item_append_text(ti, "%s", service_hints); |
||
1573 | } |
||
1574 | } |
||
1575 | offset += hints_len; |
||
1576 | |||
1577 | if (tvb_reported_length_remaining(tvb, offset) > 0) |
||
1578 | { |
||
1579 | guint8 cset; |
||
1580 | gint name_len; |
||
1581 | |||
1582 | cset = tvb_get_guint8(tvb, offset); |
||
1583 | if (root) |
||
1584 | proto_tree_add_uint(lmp_tree, hf_lmp_xid_charset, tvb, offset, 1, cset); |
||
1585 | offset++; |
||
1586 | name_len = tvb_reported_length_remaining(tvb, offset); |
||
1587 | if (name_len > 0) |
||
1588 | { |
||
1589 | if (cset == 0x00) |
||
1590 | { |
||
1591 | |||
1592 | if (name_len > 22) |
||
1593 | name_len = 22; |
||
1594 | tvb_memcpy(tvb, buf, offset, name_len); |
||
1595 | buf[name_len] = 0; |
||
1596 | col_append_str(pinfo->cinfo, COL_INFO, ", \""); |
||
1597 | col_append_str(pinfo->cinfo, COL_INFO, buf); |
||
1598 | col_append_str(pinfo->cinfo, COL_INFO, "\""); |
||
1599 | if (root) |
||
1600 | proto_tree_add_item(lmp_tree, hf_lmp_xid_name, tvb, offset, |
||
1601 | -1, ENC_ASCII|ENC_NA); |
||
1602 | } |
||
1603 | else |
||
1604 | { |
||
1605 | if (root) |
||
1606 | proto_tree_add_item(lmp_tree, hf_lmp_xid_name_no_ascii, tvb, offset, |
||
1607 | -1, ENC_NA); |
||
1608 | } |
||
1609 | } |
||
1610 | } |
||
1611 | } |
||
1612 | } |
||
1613 | |||
1614 | |||
1615 | /* |
||
1616 | * Dissect Log Messages |
||
1617 | */ |
||
1618 | static void dissect_log(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root) |
||
1619 | { |
||
1620 | /* Make entries in Protocol column on summary display */ |
||
1621 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Log"); |
||
1622 | |||
1623 | /* missed messages? */ |
||
1624 | if (pinfo->pseudo_header->irda.pkttype == IRDA_MISSED_MSG) |
||
1625 | { |
||
1626 | col_set_str(pinfo->cinfo, COL_INFO, "WARNING: Missed one or more messages while capturing!"); |
||
1627 | } |
||
1628 | else |
||
1629 | { |
||
1630 | guint length; |
||
1631 | char buf[256]; |
||
1632 | |||
1633 | |||
1634 | length = tvb_captured_length(tvb); |
||
1635 | if (length > sizeof(buf)-1) |
||
1636 | length = sizeof(buf)-1; |
||
1637 | tvb_memcpy(tvb, buf, 0, length); |
||
1638 | buf[length] = 0; |
||
1639 | if (length > 0 && buf[length-1] == '\n') |
||
1640 | buf[length-1] = 0; |
||
1641 | else if (length > 1 && buf[length-2] == '\n') |
||
1642 | buf[length-2] = 0; |
||
1643 | |||
1644 | col_add_str(pinfo->cinfo, COL_INFO, buf); |
||
1645 | } |
||
1646 | |||
1647 | if (root) |
||
1648 | { |
||
1649 | proto_item* ti = proto_tree_add_item(root, proto_log, tvb, 0, -1, ENC_NA); |
||
1650 | proto_tree* tree = proto_item_add_subtree(ti, ett_log); |
||
1651 | |||
1652 | if (pinfo->pseudo_header->irda.pkttype == IRDA_MISSED_MSG) |
||
1653 | proto_tree_add_item(tree, hf_log_missed, tvb, 0, 0, ENC_NA); |
||
1654 | else |
||
1655 | proto_tree_add_item(tree, hf_log_msg, tvb, 0, -1, ENC_ASCII|ENC_NA); |
||
1656 | } |
||
1657 | } |
||
1658 | |||
1659 | |||
1660 | /* |
||
1661 | * Dissect IrLAP |
||
1662 | */ |
||
1663 | static void dissect_irlap(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root) |
||
1664 | { |
||
1665 | int offset = 0; |
||
1666 | guint8 circuit_id, c; |
||
1667 | gboolean is_response; |
||
1668 | char addr[9]; |
||
1669 | proto_item* ti = NULL; |
||
1670 | proto_tree* tree = NULL; |
||
1671 | proto_tree* i_tree = NULL; |
||
1672 | guint32 saddr, daddr; |
||
1673 | guint8 ca; |
||
1674 | |||
1675 | /* Make entries in Protocol column on summary display */ |
||
1676 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrLAP"); |
||
1677 | |||
1678 | /* Clear Info column */ |
||
1679 | col_clear(pinfo->cinfo, COL_INFO); |
||
1680 | |||
1681 | /* set direction column */ |
||
1682 | switch (pinfo->pseudo_header->irda.pkttype) |
||
1683 | { |
||
1684 | case IRDA_OUTGOING: |
||
1685 | col_set_str(pinfo->cinfo, COL_IF_DIR, "Out"); |
||
1686 | break; |
||
1687 | |||
1688 | case IRDA_INCOMING: |
||
1689 | col_set_str(pinfo->cinfo, COL_IF_DIR, "In"); |
||
1690 | break; |
||
1691 | } |
||
1692 | |||
1693 | /* decode values used for demuxing */ |
||
1694 | circuit_id = tvb_get_guint8(tvb, 0); |
||
1695 | |||
1696 | /* initially set address columns to connection address */ |
||
1697 | g_snprintf(addr, sizeof(addr)-1, "0x%02X", circuit_id >> 1); |
||
1698 | col_add_str(pinfo->cinfo, COL_DEF_SRC, addr); |
||
1699 | col_add_str(pinfo->cinfo, COL_DEF_DST, addr); |
||
1700 | |||
1701 | if (root) |
||
1702 | { |
||
1703 | proto_tree* a_tree; |
||
1704 | proto_item* addr_item; |
||
1705 | |||
1706 | /* create display subtree for the protocol */ |
||
1707 | ti = proto_tree_add_item(root, proto_irlap, tvb, 0, -1, ENC_NA); |
||
1708 | tree = proto_item_add_subtree(ti, ett_irlap); |
||
1709 | |||
1710 | /* create subtree for the address field */ |
||
1711 | ti = proto_tree_add_item(tree, hf_lap_a, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1712 | a_tree = proto_item_add_subtree(ti, ett_lap_a); |
||
1713 | proto_tree_add_item(a_tree, hf_lap_a_cr, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1714 | addr_item = proto_tree_add_item(a_tree, hf_lap_a_address, tvb, offset, 1, ENC_BIG_ENDIAN); |
||
1715 | switch (circuit_id & ~CMD_FRAME) |
||
1716 | { |
||
1717 | case 0: |
||
1718 | proto_item_append_text(addr_item, " (NULL Address)"); |
||
1719 | break; |
||
1720 | case 0xFE: |
||
1721 | proto_item_append_text(addr_item, " (Broadcast)"); |
||
1722 | break; |
||
1723 | } |
||
1724 | } |
||
1725 | is_response = ((circuit_id & CMD_FRAME) == 0); |
||
1726 | offset++; |
||
1727 | |||
1728 | /* process the control field */ |
||
1729 | c = dissect_xdlc_control(tvb, 1, pinfo, tree, hf_lap_c, |
||
1730 | ett_lap_c, &irlap_cf_items, NULL, lap_c_u_cmd_abbr_vals, |
||
1731 | lap_c_u_rsp_abbr_vals, is_response, FALSE, FALSE); |
||
1732 | offset++; |
||
1733 | |||
1734 | if ((c & XDLC_I_MASK) == XDLC_I) { |
||
1735 | /* I frame */ |
||
1736 | proto_item_set_len(tree, offset); |
||
1737 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1738 | dissect_irlmp(tvb, pinfo, root, circuit_id); |
||
1739 | return; |
||
1740 | } |
||
1741 | |||
1742 | if ((c & 0x03) == XDLC_U) { |
||
1743 | /* U frame */ |
||
1744 | switch (c & XDLC_U_MODIFIER_MASK) |
||
1745 | { |
||
1746 | case XDLC_SNRM: |
||
1747 | if (root) |
||
1748 | { |
||
1749 | ti = proto_tree_add_item(tree, hf_lap_i, tvb, offset, -1, ENC_NA); |
||
1750 | i_tree = proto_item_add_subtree(ti, ett_lap_i); |
||
1751 | } |
||
1752 | |||
1753 | saddr = tvb_get_letohl(tvb, offset); |
||
1754 | if (!is_response) |
||
1755 | { |
||
1756 | col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr); |
||
1757 | } |
||
1758 | if (root) |
||
1759 | proto_tree_add_uint(i_tree, hf_snrm_saddr, tvb, offset, 4, saddr); |
||
1760 | offset += 4; |
||
1761 | |||
1762 | daddr = tvb_get_letohl(tvb, offset); |
||
1763 | if (!is_response) |
||
1764 | { |
||
1765 | col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr); |
||
1766 | } |
||
1767 | if (root) |
||
1768 | proto_tree_add_uint(i_tree, hf_snrm_daddr, tvb, offset, 4, daddr); |
||
1769 | offset += 4; |
||
1770 | |||
1771 | ca = tvb_get_guint8(tvb, offset); |
||
1772 | if (!is_response) |
||
1773 | { |
||
1774 | col_append_fstr(pinfo->cinfo, COL_INFO, ", ca=0x%02X", |
||
1775 | ca >> 1); |
||
1776 | } |
||
1777 | if (root) |
||
1778 | proto_tree_add_uint(i_tree, hf_snrm_ca, tvb, offset, 1, ca >> 1); |
||
1779 | offset++; |
||
1780 | |||
1781 | offset = dissect_negotiation(tvb, i_tree, offset); |
||
1782 | if (root) |
||
1783 | proto_item_set_end(ti, tvb, offset); |
||
1784 | break; |
||
1785 | |||
1786 | case IRDA_XID_CMD: |
||
1787 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1788 | dissect_xid(tvb, pinfo, root, tree, TRUE); |
||
1789 | return; |
||
1790 | |||
1791 | case XDLC_UA: |
||
1792 | if (tvb_reported_length_remaining(tvb, offset) > 0) |
||
1793 | { |
||
1794 | if (root) |
||
1795 | { |
||
1796 | ti = proto_tree_add_item(tree, hf_lap_i, tvb, offset, -1, ENC_NA); |
||
1797 | i_tree = proto_item_add_subtree(ti, ett_lap_i); |
||
1798 | } |
||
1799 | |||
1800 | saddr = tvb_get_letohl(tvb, offset); |
||
1801 | col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr); |
||
1802 | if (root) |
||
1803 | proto_tree_add_uint(i_tree, hf_ua_saddr, tvb, offset, 4, saddr); |
||
1804 | offset += 4; |
||
1805 | |||
1806 | daddr = tvb_get_letohl(tvb, offset); |
||
1807 | col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr); |
||
1808 | if (root) |
||
1809 | proto_tree_add_uint(i_tree, hf_ua_daddr, tvb, offset, 4, daddr); |
||
1810 | offset += 4; |
||
1811 | |||
1812 | offset = dissect_negotiation(tvb, i_tree, offset); |
||
1813 | if (root) |
||
1814 | proto_item_set_end(ti, tvb, offset); |
||
1815 | } |
||
1816 | break; |
||
1817 | |||
1818 | case XDLC_XID: |
||
1819 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1820 | dissect_xid(tvb, pinfo, root, tree, FALSE); |
||
1821 | return; |
||
1822 | } |
||
1823 | } |
||
1824 | |||
1825 | /* If any bytes remain, send it to the generic data dissector */ |
||
1826 | if (tvb_reported_length_remaining(tvb, offset) > 0) |
||
1827 | { |
||
1828 | tvb = tvb_new_subset_remaining(tvb, offset); |
||
1829 | call_data_dissector(tvb, pinfo, root); |
||
1830 | } |
||
1831 | } |
||
1832 | |||
1833 | |||
1834 | /* |
||
1835 | * Dissect IrDA protocol |
||
1836 | */ |
||
1837 | static int dissect_irda(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, void* data _U_) |
||
1838 | { |
||
1839 | /* check if log message */ |
||
1840 | if ((pinfo->pseudo_header->irda.pkttype & IRDA_CLASS_MASK) == IRDA_CLASS_LOG) |
||
1841 | { |
||
1842 | dissect_log(tvb, pinfo, root); |
||
1843 | return tvb_captured_length(tvb); |
||
1844 | } |
||
1845 | |||
1846 | |||
1847 | dissect_irlap(tvb, pinfo, root); |
||
1848 | return tvb_captured_length(tvb); |
||
1849 | } |
||
1850 | |||
1851 | static int irda_addr_to_str(const address* addr, gchar *buf, int buf_len _U_) |
||
1852 | { |
||
1853 | const guint8 *addrdata = (const guint8 *)addr->data; |
||
1854 | gchar *start_buf = buf; |
||
1855 | |||
1856 | buf = uint_to_str_back(buf, *addrdata); |
||
1857 | *buf = '\0'; |
||
1858 | return (int)(buf-start_buf+1); |
||
1859 | } |
||
1860 | |||
1861 | static int irda_addr_str_len(const address* addr _U_) |
||
1862 | { |
||
1863 | return 11; /* Leaves required space (10 bytes) for uint_to_str_back() */ |
||
1864 | } |
||
1865 | |||
1866 | static const char* irda_col_filter_str(const address* addr _U_, gboolean is_src _U_) |
||
1867 | { |
||
1868 | return "irlap.a"; |
||
1869 | } |
||
1870 | |||
1871 | static int irda_addr_len(void) |
||
1872 | { |
||
1873 | return 1; |
||
1874 | } |
||
1875 | |||
1876 | /* |
||
1877 | * Register the protocol with Wireshark |
||
1878 | * This format is required because a script is used to build the C function |
||
1879 | * that calls all the protocol registrations. |
||
1880 | */ |
||
1881 | void proto_register_irda(void) |
||
1882 | { |
||
1883 | guint i; |
||
1884 | |||
1885 | /* Setup list of header fields */ |
||
1886 | static hf_register_info hf_lap[] = { |
||
1887 | { &hf_lap_a, |
||
1888 | { "Address Field", "irlap.a", |
||
1889 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1890 | NULL, HFILL }}, |
||
1891 | { &hf_lap_a_cr, |
||
1892 | { "C/R", "irlap.a.cr", |
||
1893 | FT_BOOLEAN, 8, TFS(&lap_cr_vals), CMD_FRAME, |
||
1894 | NULL, HFILL }}, |
||
1895 | { &hf_lap_a_address, |
||
1896 | { "Address", "irlap.a.address", |
||
1897 | FT_UINT8, BASE_HEX, NULL, ~CMD_FRAME, |
||
1898 | NULL, HFILL }}, |
||
1899 | { &hf_lap_c, |
||
1900 | { "Control Field", "irlap.c", |
||
1901 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1902 | NULL, HFILL }}, |
||
1903 | { &hf_lap_c_nr, |
||
1904 | { "N(R)", "irlap.c.n_r", |
||
1905 | FT_UINT8, BASE_DEC, NULL, XDLC_N_R_MASK, |
||
1906 | NULL, HFILL }}, |
||
1907 | { &hf_lap_c_ns, |
||
1908 | { "N(S)", "irlap.c.n_s", |
||
1909 | FT_UINT8, BASE_DEC, NULL, XDLC_N_S_MASK, |
||
1910 | NULL, HFILL }}, |
||
1911 | { &hf_lap_c_p, |
||
1912 | { "Poll", "irlap.c.p", |
||
1913 | FT_BOOLEAN, 8, TFS(&set_notset), XDLC_P_F, |
||
1914 | NULL, HFILL }}, |
||
1915 | { &hf_lap_c_f, |
||
1916 | { "Final", "irlap.c.f", |
||
1917 | FT_BOOLEAN, 8, TFS(&set_notset), XDLC_P_F, |
||
1918 | NULL, HFILL }}, |
||
1919 | { &hf_lap_c_s, |
||
1920 | { "Supervisory frame type", "irlap.c.s_ftype", |
||
1921 | FT_UINT8, BASE_HEX, VALS(lap_c_s_vals), XDLC_S_FTYPE_MASK, |
||
1922 | NULL, HFILL }}, |
||
1923 | { &hf_lap_c_u_cmd, |
||
1924 | { "Command", "irlap.c.u_modifier_cmd", |
||
1925 | FT_UINT8, BASE_HEX, VALS(lap_c_u_cmd_vals), XDLC_U_MODIFIER_MASK, |
||
1926 | NULL, HFILL }}, |
||
1927 | { &hf_lap_c_u_rsp, |
||
1928 | { "Response", "irlap.c.u_modifier_resp", |
||
1929 | FT_UINT8, BASE_HEX, VALS(lap_c_u_rsp_vals), XDLC_U_MODIFIER_MASK, |
||
1930 | NULL, HFILL }}, |
||
1931 | { &hf_lap_c_i, |
||
1932 | { "Frame Type", "irlap.c.ftype", |
||
1933 | FT_UINT8, BASE_HEX, VALS(lap_c_ftype_vals), XDLC_I_MASK, |
||
1934 | NULL, HFILL }}, |
||
1935 | { &hf_lap_c_s_u, |
||
1936 | { "Frame Type", "irlap.c.ftype", |
||
1937 | FT_UINT8, BASE_HEX, VALS(lap_c_ftype_vals), XDLC_S_U_MASK, |
||
1938 | NULL, HFILL }}, |
||
1939 | { &hf_lap_i, |
||
1940 | { "Information Field", "irlap.i", |
||
1941 | FT_NONE, BASE_NONE, NULL, 0, |
||
1942 | NULL, HFILL }}, |
||
1943 | { &hf_snrm_saddr, |
||
1944 | { "Source Device Address", "irlap.snrm.saddr", |
||
1945 | FT_UINT32, BASE_HEX, NULL, 0, |
||
1946 | NULL, HFILL }}, |
||
1947 | { &hf_snrm_daddr, |
||
1948 | { "Destination Device Address", "irlap.snrm.daddr", |
||
1949 | FT_UINT32, BASE_HEX, NULL, 0, |
||
1950 | NULL, HFILL }}, |
||
1951 | { &hf_snrm_ca, |
||
1952 | { "Connection Address", "irlap.snrm.ca", |
||
1953 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1954 | NULL, HFILL }}, |
||
1955 | { &hf_negotiation_param, |
||
1956 | { "Negotiation Parameter", "irlap.negotiation", |
||
1957 | FT_NONE, BASE_NONE, NULL, 0, |
||
1958 | NULL, HFILL }}, |
||
1959 | { &hf_param_pi, |
||
1960 | { "Parameter Identifier", "irlap.pi", |
||
1961 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1962 | NULL, HFILL }}, |
||
1963 | { &hf_param_pl, |
||
1964 | { "Parameter Length", "irlap.pl", |
||
1965 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1966 | NULL, HFILL }}, |
||
1967 | { &hf_param_pv, |
||
1968 | { "Parameter Value", "irlap.pv", |
||
1969 | FT_BYTES, BASE_NONE, NULL, 0, |
||
1970 | NULL, HFILL }}, |
||
1971 | { &hf_ua_saddr, |
||
1972 | { "Source Device Address", "irlap.ua.saddr", |
||
1973 | FT_UINT32, BASE_HEX, NULL, 0, |
||
1974 | NULL, HFILL }}, |
||
1975 | { &hf_ua_daddr, |
||
1976 | { "Destination Device Address", "irlap.ua.daddr", |
||
1977 | FT_UINT32, BASE_HEX, NULL, 0, |
||
1978 | NULL, HFILL }}, |
||
1979 | { &hf_xid_ident, |
||
1980 | { "Format Identifier", "irlap.xid.fi", |
||
1981 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1982 | NULL, HFILL }}, |
||
1983 | { &hf_xid_saddr, |
||
1984 | { "Source Device Address", "irlap.xid.saddr", |
||
1985 | FT_UINT32, BASE_HEX, NULL, 0, |
||
1986 | NULL, HFILL }}, |
||
1987 | { &hf_xid_daddr, |
||
1988 | { "Destination Device Address", "irlap.xid.daddr", |
||
1989 | FT_UINT32, BASE_HEX, NULL, 0, |
||
1990 | NULL, HFILL }}, |
||
1991 | { &hf_xid_flags, |
||
1992 | { "Discovery Flags", "irlap.xid.flags", |
||
1993 | FT_UINT8, BASE_HEX, NULL, 0, |
||
1994 | NULL, HFILL }}, |
||
1995 | { &hf_xid_s, |
||
1996 | { "Number of Slots", "irlap.xid.s", |
||
1997 | FT_UINT8, BASE_DEC, VALS(xid_slot_numbers), S_MASK, |
||
1998 | NULL, HFILL }}, |
||
1999 | { &hf_xid_conflict, |
||
2000 | { "Conflict", "irlap.xid.conflict", |
||
2001 | FT_BOOLEAN, 8, TFS(&set_notset), CONFLICT, |
||
2002 | NULL, HFILL }}, |
||
2003 | { &hf_xid_slotnr, |
||
2004 | { "Slot Number", "irlap.xid.slotnr", |
||
2005 | FT_UINT8, BASE_DEC, NULL, 0, |
||
2006 | NULL, HFILL }}, |
||
2007 | { &hf_xid_version, |
||
2008 | { "Version Number", "irlap.xid.version", |
||
2009 | FT_UINT8, BASE_HEX, NULL, 0, |
||
2010 | NULL, HFILL }} |
||
2011 | }; |
||
2012 | |||
2013 | static hf_register_info hf_log[] = { |
||
2014 | { &hf_log_msg, |
||
2015 | { "Message", "log.msg", |
||
2016 | FT_STRING, BASE_NONE, NULL, 0, |
||
2017 | NULL, HFILL }}, |
||
2018 | { &hf_log_missed, |
||
2019 | { "WARNING: Missed one or more messages while capturing!", "log.missed", |
||
2020 | FT_NONE, BASE_NONE, NULL, 0, |
||
2021 | NULL, HFILL }} |
||
2022 | }; |
||
2023 | |||
2024 | static hf_register_info hf_lmp[] = { |
||
2025 | { &hf_lmp_xid_hints, |
||
2026 | { "Service Hints", "irlmp.xid.hints", |
||
2027 | FT_BYTES, BASE_NONE, NULL, 0, |
||
2028 | NULL, HFILL }}, |
||
2029 | { &hf_lmp_xid_charset, |
||
2030 | { "Character Set", "irlmp.xid.charset", |
||
2031 | FT_UINT8, BASE_HEX, NULL, 0, |
||
2032 | NULL, HFILL }}, |
||
2033 | { &hf_lmp_xid_name, |
||
2034 | { "Device Nickname", "irlmp.xid.name", |
||
2035 | FT_STRING, BASE_NONE, NULL, 0, |
||
2036 | NULL, HFILL }}, |
||
2037 | { &hf_lmp_xid_name_no_ascii, |
||
2038 | { "Device Nickname (unsupported character set)", "irlmp.xid.name.no_ascii", |
||
2039 | FT_BYTES, BASE_NONE, NULL, 0, |
||
2040 | NULL, HFILL }}, |
||
2041 | { &hf_lmp_dst, |
||
2042 | { "Destination", "irlmp.dst", |
||
2043 | FT_UINT8, BASE_HEX, NULL, 0, |
||
2044 | NULL, HFILL }}, |
||
2045 | { &hf_lmp_dst_control, |
||
2046 | { "Control Bit", "irlmp.dst.c", |
||
2047 | FT_BOOLEAN, 8, TFS(&set_notset), CONTROL_BIT, |
||
2048 | NULL, HFILL }}, |
||
2049 | { &hf_lmp_dst_lsap, |
||
2050 | { "Destination LSAP", "irlmp.dst.lsap", |
||
2051 | FT_UINT8, BASE_DEC, NULL, ~CONTROL_BIT, |
||
2052 | NULL, HFILL }}, |
||
2053 | { &hf_lmp_src, |
||
2054 | { "Source", "irlmp.src", |
||
2055 | FT_UINT8, BASE_HEX, NULL, 0, |
||
2056 | NULL, HFILL }}, |
||
2057 | { &hf_lmp_src_r, |
||
2058 | { "reserved", "irlmp.src.r", |
||
2059 | FT_UINT8, BASE_DEC, NULL, RESERVED_BIT, |
||
2060 | NULL, HFILL }}, |
||
2061 | { &hf_lmp_src_lsap, |
||
2062 | { "Source LSAP", "irlmp.src.lsap", |
||
2063 | FT_UINT8, BASE_DEC, NULL, ~RESERVED_BIT, |
||
2064 | NULL, HFILL }}, |
||
2065 | { &hf_lmp_opcode, |
||
2066 | { "Opcode", "irlmp.opcode", |
||
2067 | FT_UINT8, BASE_HEX, VALS(lmp_opcode_vals), 0x0, |
||
2068 | NULL, HFILL }}, |
||
2069 | { &hf_lmp_rsvd, |
||
2070 | { "Reserved", "irlmp.rsvd", |
||
2071 | FT_UINT8, BASE_HEX, NULL, 0x0, |
||
2072 | NULL, HFILL }}, |
||
2073 | { &hf_lmp_reason, |
||
2074 | { "Reason", "irlmp.reason", |
||
2075 | FT_UINT8, BASE_HEX, VALS(lmp_reason_vals), 0x0, |
||
2076 | NULL, HFILL }}, |
||
2077 | { &hf_lmp_mode, |
||
2078 | { "Mode", "irlmp.mode", |
||
2079 | FT_UINT8, BASE_HEX, VALS(lmp_mode_vals), 0x0, |
||
2080 | NULL, HFILL }}, |
||
2081 | { &hf_lmp_status, |
||
2082 | { "Status", "irlmp.status", |
||
2083 | FT_UINT8, BASE_HEX, VALS(lmp_status_vals), 0x0, |
||
2084 | NULL, HFILL }} |
||
2085 | }; |
||
2086 | |||
2087 | static hf_register_info hf_iap[] = { |
||
2088 | { &hf_iap_ctl, |
||
2089 | { "Control Field", "iap.ctl", |
||
2090 | FT_UINT8, BASE_HEX, NULL, 0, |
||
2091 | NULL, HFILL }}, |
||
2092 | { &hf_iap_ctl_lst, |
||
2093 | { "Last Frame", "iap.ctl.lst", |
||
2094 | FT_BOOLEAN, 8, TFS(&set_notset), IAP_LST, |
||
2095 | NULL, HFILL }}, |
||
2096 | { &hf_iap_ctl_ack, |
||
2097 | { "Acknowledge", "iap.ctl.ack", |
||
2098 | FT_BOOLEAN, 8, TFS(&set_notset), IAP_ACK, |
||
2099 | NULL, HFILL }}, |
||
2100 | { &hf_iap_ctl_opcode, |
||
2101 | { "Opcode", "iap.ctl.opcode", |
||
2102 | FT_UINT8, BASE_HEX, VALS(iap_opcode_vals), IAP_OP, |
||
2103 | NULL, HFILL }}, |
||
2104 | { &hf_iap_class_name, |
||
2105 | { "Class Name", "iap.classname", |
||
2106 | FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
||
2107 | NULL, HFILL }}, |
||
2108 | { &hf_iap_attr_name, |
||
2109 | { "Attribute Name", "iap.attrname", |
||
2110 | FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
||
2111 | NULL, HFILL }}, |
||
2112 | { &hf_iap_return, |
||
2113 | { "Return", "iap.return", |
||
2114 | FT_UINT8, BASE_HEX, VALS(iap_return_vals), 0x0, |
||
2115 | NULL, HFILL }}, |
||
2116 | { &hf_iap_list_len, |
||
2117 | { "List Length", "iap.listlen", |
||
2118 | FT_UINT16, BASE_DEC, NULL, 0x0, |
||
2119 | NULL, HFILL }}, |
||
2120 | { &hf_iap_list_entry, |
||
2121 | { "List Entry", "iap.listentry", |
||
2122 | FT_NONE, BASE_NONE, NULL, 0x0, |
||
2123 | NULL, HFILL }}, |
||
2124 | { &hf_iap_obj_id, |
||
2125 | { "Object Identifier", "iap.objectid", |
||
2126 | FT_UINT16, BASE_HEX, NULL, 0x0, |
||
2127 | NULL, HFILL }}, |
||
2128 | { &hf_iap_attr_type, |
||
2129 | { "Type", "iap.attrtype", |
||
2130 | FT_UINT8, BASE_DEC, VALS(iap_attr_type_vals), 0x0, |
||
2131 | NULL, HFILL }}, |
||
2132 | { &hf_iap_int, |
||
2133 | { "Value", "iap.int", |
||
2134 | FT_INT32, BASE_DEC, NULL, 0x0, |
||
2135 | NULL, HFILL }}, |
||
2136 | { &hf_iap_seq_len, |
||
2137 | { "Sequence Length", "iap.seqlen", |
||
2138 | FT_UINT16, BASE_DEC, NULL, 0x0, |
||
2139 | NULL, HFILL }}, |
||
2140 | { &hf_iap_oct_seq, |
||
2141 | { "Sequence", "iap.octseq", |
||
2142 | FT_BYTES, BASE_NONE, NULL, 0x0, |
||
2143 | NULL, HFILL }}, |
||
2144 | { &hf_iap_char_set, |
||
2145 | { "Character Set", "iap.charset", |
||
2146 | FT_UINT8, BASE_HEX, NULL, 0x0, |
||
2147 | NULL, HFILL }}, |
||
2148 | { &hf_iap_string, |
||
2149 | { "String", "iap.string", |
||
2150 | FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
||
2151 | NULL, HFILL }}, |
||
2152 | { &hf_iap_invaloctet, |
||
2153 | { "Malformed IAP result: \"", "iap.invaloctet", |
||
2154 | FT_NONE, BASE_NONE, NULL, 0, |
||
2155 | NULL, HFILL }}, |
||
2156 | { &hf_iap_invallsap, |
||
2157 | { "Malformed IAP result: \"", "iap.invallsap", |
||
2158 | FT_NONE, BASE_NONE, NULL, 0, |
||
2159 | NULL, HFILL }} |
||
2160 | }; |
||
2161 | |||
2162 | static hf_register_info hf_ttp[] = { |
||
2163 | { &hf_ttp_p, |
||
2164 | { "Parameter Bit", "ttp.p", |
||
2165 | FT_BOOLEAN, 8, TFS(&set_notset), TTP_PARAMETERS, |
||
2166 | NULL, HFILL }}, |
||
2167 | { &hf_ttp_icredit, |
||
2168 | { "Initial Credit", "ttp.icredit", |
||
2169 | FT_UINT8, BASE_DEC, NULL, ~TTP_PARAMETERS, |
||
2170 | NULL, HFILL }}, |
||
2171 | { &hf_ttp_m, |
||
2172 | { "More Bit", "ttp.m", |
||
2173 | FT_BOOLEAN, 8, TFS(&set_notset), TTP_MORE, |
||
2174 | NULL, HFILL }}, |
||
2175 | { &hf_ttp_dcredit, |
||
2176 | { "Delta Credit", "ttp.dcredit", |
||
2177 | FT_UINT8, BASE_DEC, NULL, ~TTP_MORE, |
||
2178 | NULL, HFILL }} |
||
2179 | }; |
||
2180 | |||
2181 | /* Setup protocol subtree arrays */ |
||
2182 | static gint* ett[] = { |
||
2183 | &ett_irlap, |
||
2184 | &ett_lap_a, |
||
2185 | &ett_lap_c, |
||
2186 | &ett_lap_i, |
||
2187 | &ett_xid_flags, |
||
2188 | &ett_log, |
||
2189 | &ett_irlmp, |
||
2190 | &ett_lmp_dst, |
||
2191 | &ett_lmp_src, |
||
2192 | &ett_iap, |
||
2193 | &ett_iap_ctl, |
||
2194 | &ett_ttp |
||
2195 | }; |
||
2196 | |||
2197 | gint* ett_p[MAX_PARAMETERS]; |
||
2198 | gint* ett_iap_e[MAX_IAP_ENTRIES]; |
||
2199 | |||
2200 | |||
2201 | /* Register protocol names and descriptions */ |
||
2202 | proto_irlap = proto_register_protocol("IrDA Link Access Protocol", "IrLAP", "irlap"); |
||
2203 | proto_log = proto_register_protocol("Log Message", "Log", "log"); |
||
2204 | proto_irlmp = proto_register_protocol("IrDA Link Management Protocol", "IrLMP", "irlmp"); |
||
2205 | proto_iap = proto_register_protocol("Information Access Protocol", "IAP", "iap"); |
||
2206 | proto_ttp = proto_register_protocol("Tiny Transport Protocol", "TTP", "ttp"); |
||
2207 | |||
2208 | /* Register the dissector */ |
||
2209 | register_dissector("irda", dissect_irda, proto_irlap); |
||
2210 | |||
2211 | /* Required function calls to register the header fields */ |
||
2212 | proto_register_field_array(proto_irlap, hf_lap, array_length(hf_lap)); |
||
2213 | proto_register_field_array(proto_log, hf_log, array_length(hf_log)); |
||
2214 | proto_register_field_array(proto_irlmp, hf_lmp, array_length(hf_lmp)); |
||
2215 | proto_register_field_array(proto_iap, hf_iap, array_length(hf_iap)); |
||
2216 | proto_register_field_array(proto_ttp, hf_ttp, array_length(hf_ttp)); |
||
2217 | |||
2218 | /* Register subtrees */ |
||
2219 | proto_register_subtree_array(ett, array_length(ett)); |
||
2220 | for (i = 0; i < MAX_PARAMETERS; i++) |
||
2221 | { |
||
2222 | ett_param[i] = -1; |
||
2223 | ett_p[i] = &ett_param[i]; |
||
2224 | } |
||
2225 | proto_register_subtree_array(ett_p, MAX_PARAMETERS); |
||
2226 | for (i = 0; i < MAX_IAP_ENTRIES; i++) |
||
2227 | { |
||
2228 | ett_iap_entry[i] = -1; |
||
2229 | ett_iap_e[i] = &ett_iap_entry[i]; |
||
2230 | } |
||
2231 | proto_register_subtree_array(ett_iap_e, MAX_IAP_ENTRIES); |
||
2232 | |||
2233 | 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); |
||
2234 | } |
||
2235 | |||
2236 | |||
2237 | /* If this dissector uses sub-dissector registration add a registration routine. |
||
2238 | This format is required because a script is used to find these routines and |
||
2239 | create the code that calls these routines. |
||
2240 | */ |
||
2241 | |||
2242 | void proto_reg_handoff_irda(void) |
||
2243 | { |
||
2244 | dissector_handle_t irda_handle; |
||
2245 | |||
2246 | irda_handle = find_dissector("irda"); |
||
2247 | dissector_add_uint("wtap_encap", WTAP_ENCAP_IRDA, irda_handle); |
||
2248 | dissector_add_uint("sll.ltype", LINUX_SLL_P_IRDA_LAP, irda_handle); |
||
2249 | } |
||
2250 | |||
2251 | /* |
||
2252 | * Editor modelines - http://www.wireshark.org/tools/modelines.html |
||
2253 | * |
||
2254 | * Local variables: |
||
2255 | * c-basic-offset: 4 |
||
2256 | * tab-width: 8 |
||
2257 | * indent-tabs-mode: nil |
||
2258 | * End: |
||
2259 | * |
||
2260 | * vi: set shiftwidth=4 tabstop=8 expandtab: |
||
2261 | * :indentSize=4:tabSize=8:noTabs=true: |
||
2262 | */ |