1 /* packet-atalk.c
2 * Routines for AppleTalk packet disassembly: LLAP, DDP, NBP, ATP, ASP,
3 * RTMP, PAP.
4 *
5 * Simon Wilkinson <sxw@dcs.ed.ac.uk>
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 */
13
14 #include "config.h"
15
16
17 #include <epan/packet.h>
18 #include <epan/etypes.h>
19 #include <epan/ppptypes.h>
20 #include <epan/aftypes.h>
21 #include <epan/arcnet_pids.h>
22 #include <epan/oui.h>
23 #include <epan/conversation.h>
24 #include <epan/prefs.h>
25 #include <epan/reassemble.h>
26 #include <epan/address_types.h>
27 #include <epan/to_str.h>
28 #include <epan/expert.h>
29 #include <epan/dissectors/packet-llc.h>
30 #include <wiretap/wtap.h>
31 #include <epan/capture_dissectors.h>
32 #include "packet-atalk.h"
33 #include "packet-afp.h"
34
35 void proto_register_atalk(void);
36 void proto_reg_handoff_atalk(void);
37
38 /* Tables for reassembly of fragments. */
39 static reassembly_table atp_reassembly_table;
40
41 /* desegmentation of ATP */
42 static gboolean atp_defragment = TRUE;
43
44 static dissector_handle_t afp_handle;
45 static dissector_handle_t afp_server_status_handle;
46
47 static int proto_llap = -1;
48 static int hf_llap_dst = -1;
49 static int hf_llap_src = -1;
50 static int hf_llap_type = -1;
51
52 static int hf_llc_apple_atalk_pid = -1;
53
54 /*
55 * See Inside AppleTalk.
56 */
57 #define APPLE_PID_ATALK 0x809B
58
59 static const value_string apple_atalk_pid_vals[] = {
60 {APPLE_PID_ATALK, "AppleTalk"},
61 {0, NULL}
62 };
63
64 static int proto_ddp = -1;
65 static int hf_ddp_hopcount = -1;
66 static int hf_ddp_len = -1;
67 static int hf_ddp_checksum = -1;
68 static int hf_ddp_dst = -1;
69 static int hf_ddp_dst_net = -1;
70 static int hf_ddp_src = -1;
71 static int hf_ddp_src_net = -1;
72 static int hf_ddp_dst_node = -1;
73 static int hf_ddp_src_node = -1;
74 static int hf_ddp_dst_socket = -1;
75 static int hf_ddp_src_socket = -1;
76 static int hf_ddp_type = -1;
77
78 static dissector_handle_t ddp_handle;
79 static dissector_handle_t ddp_short_handle;
80
81 /* --------------------------------------
82 * ATP protocol parameters
83 * from netatalk/include/atalk/atp.h
84 */
85 #define ATP_MAXDATA (578+4) /* maximum ATP data size */
86 #define ATP_BUFSIZ 587 /* maximum packet size */
87 #define ATP_HDRSIZE 5 /* includes DDP type field */
88
89 #define ATP_TRELMASK 0x07 /* mask all but TREL */
90 #define ATP_RELTIME 30 /* base release timer (in secs) */
91
92 #define ATP_TREL30 0x0 /* release time codes */
93 #define ATP_TREL1M 0x1 /* these are passed in flags of */
94 #define ATP_TREL2M 0x2 /* atp_sreq call, and set in the */
95 #define ATP_TREL4M 0x3 /* packet control info. */
96 #define ATP_TREL8M 0x4
97
98 /* flags for ATP options (and control byte)
99 */
100 #define ATP_XO 0x20 /* (1<<5) eXactly Once mode */
101 #define ATP_EOM 0x10 /* (1<<4) End Of Message */
102 #define ATP_STS 0x08 /* (1<<3) Transaction Status */
103
104 /* function codes
105 */
106 #define ATP_FUNCMASK (3<<6) /* mask all but function */
107
108 #define ATP_TREQ 1 /* (1<<6) Trans. REQuest */
109 #define ATP_TRESP 2 /* (2<<6) Trans. RESPonse */
110 #define ATP_TREL 3 /* (3<<6) Trans. RELease */
111
112 /* ------------------------- */
113 static dissector_handle_t asp_handle;
114 static dissector_handle_t pap_handle;
115
116 static int proto_atp = -1;
117 static int hf_atp_ctrlinfo = -1; /* guint8_t control information */
118 static int hf_atp_function = -1; /* bits 7,6 function */
119 static int hf_atp_xo = -1; /* bit 5 exactly-once */
120 static int hf_atp_eom = -1; /* bit 4 end-of-message */
121 static int hf_atp_sts = -1; /* bit 3 send transaction status */
122 static int hf_atp_treltimer = -1; /* bits 2,1,0 TRel timeout indicator */
123
124 static int hf_atp_bitmap = -1; /* guint8_t bitmap or sequence number */
125 static int hf_atp_tid = -1; /* guint16_t transaction id. */
126 static int hf_atp_user_bytes = -1;
127
128 static int hf_atp_segments = -1;
129 static int hf_atp_segment = -1;
130 static int hf_atp_segment_overlap = -1;
131 static int hf_atp_segment_overlap_conflict = -1;
132 static int hf_atp_segment_multiple_tails = -1;
133 static int hf_atp_segment_too_long_segment = -1;
134 static int hf_atp_segment_error = -1;
135 static int hf_atp_segment_count = -1;
136 static int hf_atp_reassembled_in = -1;
137 static int hf_atp_reassembled_length = -1;
138
139 /* ------------------------- */
140 static int proto_zip = -1;
141 static dissector_handle_t zip_atp_handle;
142
143 static int hf_zip_function = -1;
144 static int hf_zip_atp_function = -1;
145 static int hf_zip_start_index = -1;
146 static int hf_zip_count = -1;
147 static int hf_zip_zero_value = -1;
148
149 static int hf_zip_network_count = -1;
150 static int hf_zip_network = -1;
151 static int hf_zip_network_start = -1;
152 static int hf_zip_network_end = -1;
153
154 static int hf_zip_flags = -1;
155 static int hf_zip_flags_zone_invalid = -1;
156 static int hf_zip_flags_use_broadcast = -1;
157 static int hf_zip_flags_only_one_zone = -1;
158
159 static int hf_zip_last_flag = -1;
160
161 static int hf_zip_zone_name = -1;
162 static int hf_zip_default_zone = -1;
163
164 static int hf_zip_multicast_length = -1;
165 static int hf_zip_multicast_address = -1;
166
167 static const value_string zip_function_vals[] = {
168 {1, "Query"},
169 {2, "Reply"},
170 {5, "GetNetInfo request"},
171 {6, "GetNetInfo reply"},
172 {7, "notify"},
173 {8, "Extended reply"},
174 {0, NULL}
175 };
176 static value_string_ext zip_function_vals_ext = VALUE_STRING_EXT_INIT(zip_function_vals);
177
178 static const value_string zip_atp_function_vals[] = {
179 {7, "GetMyZone"},
180 {8, "GetZoneList"},
181 {9, "GetLocalZones"},
182 {0, NULL}
183 };
184
185 static gint ett_zip = -1;
186 static gint ett_zip_flags = -1;
187 static gint ett_zip_zones_list = -1;
188 static gint ett_zip_network_list = -1;
189
190 /* --------------------------------
191 * from netatalk/include/atalk/ats.h
192 */
193
194 #define ASPFUNC_CLOSE 1
195 #define ASPFUNC_CMD 2
196 #define ASPFUNC_STAT 3
197 #define ASPFUNC_OPEN 4
198 #define ASPFUNC_TICKLE 5
199 #define ASPFUNC_WRITE 6
200 #define ASPFUNC_WRTCONT 7
201 #define ASPFUNC_ATTN 8
202
203 #define ASP_HDRSIZ 4
204 #define ASPERR_OK 0
205 #define ASPERR_BADVERS (-1066)
206 #define ASPERR_BUFSMALL (-1067)
207 #define ASPERR_NOSESS (-1068)
208 #define ASPERR_NOSERV (-1069)
209 #define ASPERR_PARM (-1070)
210 #define ASPERR_SERVBUSY (-1071)
211 #define ASPERR_SESSCLOS (-1072)
212 #define ASPERR_SIZERR (-1073)
213 #define ASPERR_TOOMANY (-1074)
214 #define ASPERR_NOACK (-1075)
215
216 static int proto_asp = -1;
217 static int hf_asp_func = -1;
218 static int hf_asp_error = -1;
219 static int hf_asp_socket = -1;
220 static int hf_asp_version = -1;
221 static int hf_asp_session_id = -1;
222 static int hf_asp_zero_value = -1;
223 static int hf_asp_init_error = -1;
224 static int hf_asp_attn_code = -1;
225 static int hf_asp_seq = -1;
226 static int hf_asp_size = -1;
227
228 typedef struct {
229 guint32 conversation;
230 guint8 src[4];
231 guint16 seq;
232 } asp_request_key;
233
234 typedef struct {
235 guint8 value; /* command for asp, bitmap for atp */
236 } asp_request_val;
237
238 static wmem_map_t *asp_request_hash = NULL;
239
240 /* Hash Functions */
asp_equal(gconstpointer v,gconstpointer v2)241 static gint asp_equal (gconstpointer v, gconstpointer v2)
242 {
243 const asp_request_key *val1 = (const asp_request_key*)v;
244 const asp_request_key *val2 = (const asp_request_key*)v2;
245
246 if (val1->conversation == val2->conversation &&
247 val1->seq == val2->seq &&
248 !memcmp(val1->src, val2->src, 4)) {
249 return 1;
250 }
251 return 0;
252 }
253
asp_hash(gconstpointer v)254 static guint asp_hash (gconstpointer v)
255 {
256 const asp_request_key *asp_key = (const asp_request_key*)v;
257 return asp_key->seq;
258 }
259
260 /* ------------------------------------ */
261 static wmem_map_t *atp_request_hash = NULL;
262
263
264 /* ------------------------------------ */
265 static int proto_nbp = -1;
266 static int hf_nbp_op = -1;
267 static int hf_nbp_info = -1;
268 static int hf_nbp_count = -1;
269 static int hf_nbp_tid = -1;
270
271 static int hf_nbp_node_net = -1;
272 static int hf_nbp_node_port = -1;
273 static int hf_nbp_node_node = -1;
274 static int hf_nbp_node_enum = -1;
275 static int hf_nbp_node_object = -1;
276 static int hf_nbp_node_type = -1;
277 static int hf_nbp_node_zone = -1;
278
279 static int proto_rtmp = -1;
280 static int hf_rtmp_net = -1;
281 static int hf_rtmp_node_len = -1;
282 static int hf_rtmp_node = -1;
283 static int hf_rtmp_tuple_net = -1;
284 static int hf_rtmp_tuple_range_start = -1;
285 static int hf_rtmp_tuple_range_end = -1;
286 static int hf_rtmp_tuple_dist = -1;
287 static int hf_rtmp_version = -1;
288 static int hf_rtmp_function = -1;
289
290 static gint ett_atp = -1;
291
292 static gint ett_atp_segments = -1;
293 static gint ett_atp_segment = -1;
294 static gint ett_atp_info = -1;
295 static gint ett_asp = -1;
296 static gint ett_pap = -1;
297
298 static gint ett_nbp = -1;
299 static gint ett_nbp_info = -1;
300 static gint ett_nbp_node = -1;
301 static gint ett_rtmp = -1;
302 static gint ett_rtmp_tuple = -1;
303 static gint ett_ddp = -1;
304 static gint ett_llap = -1;
305 static gint ett_pstring = -1;
306
307 static expert_field ei_ddp_len_invalid = EI_INIT;
308
309 static const fragment_items atp_frag_items = {
310 &ett_atp_segment,
311 &ett_atp_segments,
312 &hf_atp_segments,
313 &hf_atp_segment,
314 &hf_atp_segment_overlap,
315 &hf_atp_segment_overlap_conflict,
316 &hf_atp_segment_multiple_tails,
317 &hf_atp_segment_too_long_segment,
318 &hf_atp_segment_error,
319 &hf_atp_segment_count,
320 &hf_atp_reassembled_in,
321 &hf_atp_reassembled_length,
322 /* Reassembled data field */
323 NULL,
324 "segments"
325 };
326
327 /* -------------------------------- */
328
329 #define PAPOpenConn 1
330 #define PAPOpenConnReply 2
331 #define PAPSendData 3
332 #define PAPData 4
333 #define PAPTickle 5
334 #define PAPCloseConn 6
335 #define PAPCloseConnReply 7
336 #define PAPSendStatus 8
337 #define PAPStatus 9
338
339 static int proto_pap = -1;
340
341 static int hf_pap_connid = -1;
342 static int hf_pap_function = -1;
343 static int hf_pap_socket = -1;
344 static int hf_pap_quantum = -1;
345 static int hf_pap_waittime = -1;
346 static int hf_pap_result = -1;
347 static int hf_pap_status = -1;
348 static int hf_pap_seq = -1;
349 static int hf_pap_eof = -1;
350
351 static int hf_pap_pad = -1;
352
353 static int atalk_address_type = -1;
354
355 static const value_string pap_function_vals[] = {
356 {PAPOpenConn , "Open Connection Query"},
357 {PAPOpenConnReply , "Open Connection Reply"},
358 {PAPSendData , "Send Data"},
359 {PAPData , "Data"},
360 {PAPTickle , "Tickle"},
361 {PAPCloseConn , "Close Connection Query"},
362 {PAPCloseConnReply , "Close Connection reply"},
363 {PAPSendStatus , "Send Status"},
364 {PAPStatus , "Status"},
365
366 {0, NULL}
367 };
368 static value_string_ext pap_function_vals_ext = VALUE_STRING_EXT_INIT(pap_function_vals);
369
370 /* -------------------------------- */
371
372 static dissector_table_t ddp_dissector_table;
373
374 #define DDP_SHORT_HEADER_SIZE 5
375
376 #define DDP_HEADER_SIZE 13
377
378
379 static const value_string op_vals[] = {
380 {DDP_RTMPDATA, "AppleTalk Routing Table response or data" },
381 {DDP_NBP, "AppleTalk Name Binding Protocol packet"},
382 {DDP_ATP, "AppleTalk Transaction Protocol packet"},
383 {DDP_AEP, "AppleTalk Echo Protocol packet"},
384 {DDP_RTMPREQ, "AppleTalk Routing Table request"},
385 {DDP_ZIP, "AppleTalk Zone Information Protocol packet"},
386 {DDP_ADSP, "AppleTalk Data Stream Protocol"},
387 {DDP_EIGRP, "Cisco EIGRP for AppleTalk"},
388 {0, NULL}
389 };
390 static value_string_ext op_vals_ext = VALUE_STRING_EXT_INIT(op_vals);
391
392 static const value_string rtmp_function_vals[] = {
393 {1, "Request"},
394 {2, "Route Data Request (split horizon processed)"},
395 {3, "Route Data Request (no split horizon processing)"},
396 {0, NULL}
397 };
398
399 #define NBP_BROADCAST 1
400 #define NBP_LOOKUP 2
401 #define NBP_FORWARD 4
402 #define NBP_REPLY 3
403
404 static const value_string nbp_op_vals[] = {
405 {NBP_BROADCAST, "broadcast request"},
406 {NBP_LOOKUP, "lookup"},
407 {NBP_FORWARD, "forward request"},
408 {NBP_REPLY, "reply"},
409 {0, NULL}
410 };
411
412 static const value_string atp_function_vals[] = {
413 {ATP_TREQ ,"REQuest"},
414 {ATP_TRESP ,"RESPonse"},
415 {ATP_TREL ,"RELease"},
416 {0, NULL}
417 };
418
419 static const value_string atp_trel_timer_vals[] = {
420 {0, "30 seconds"},
421 {1, "1 minute"},
422 {2, "2 minutes"},
423 {3, "4 minutes"},
424 {4, "8 minutes"},
425 {0, NULL}
426 };
427
428 /*
429 */
430 static const value_string asp_func_vals[] = {
431 {ASPFUNC_CLOSE, "CloseSession" },
432 {ASPFUNC_CMD, "Command" },
433 {ASPFUNC_STAT, "GetStatus" },
434 {ASPFUNC_OPEN, "OpenSession" },
435 {ASPFUNC_TICKLE, "Tickle" },
436 {ASPFUNC_WRITE, "Write" },
437 {ASPFUNC_WRTCONT, "Write Cont" },
438 {ASPFUNC_ATTN, "Attention" },
439 {0, NULL } };
440 static value_string_ext asp_func_vals_ext = VALUE_STRING_EXT_INIT(asp_func_vals);
441
442 /* XXX: Array sorted in ascending order (unsigned) to allow value_string_ext binary search */
443 static const value_string asp_error_vals[] = {
444 {AFP_OK , "success"},
445 {AFPERR_USRLOGIN , "user already logged on" },
446 {AFPERR_PWDPOLCY , "password fails policy check" },
447 {AFPERR_PWDCHNG , "password needs to be changed" },
448 {AFPERR_INTRASH , "shared folder in trash." },
449 {AFPERR_INSHRD , "folder being shared is inside a shared folder." },
450 {AFPERR_PWDEXPR , "password expired" },
451 {AFPERR_PWDSHORT , "password too short" },
452 {AFPERR_PWDSAME , "same password/can't change password" },
453 {AFPERR_BADID , "non-existent file id" },
454 {AFPERR_SAMEOBJ , "source file == destination file" },
455 {AFPERR_CATCHNG , "catalog has changed" },
456 {AFPERR_DIFFVOL , "different volume" },
457 {AFPERR_EXISTID , "file already has an id" },
458 {AFPERR_NOID , "file thread not found" },
459 {AFPERR_CTNSHRD , "share point contains a share point" },
460 {AFPERR_OLOCK , "object locked" },
461 {AFPERR_VLOCK , "volume locked" },
462 {AFPERR_ITYPE , "wrong icon type" },
463 {AFPERR_NODIR , "couldn't find directory" },
464 {AFPERR_NORENAME , "can't rename" },
465 {AFPERR_SHUTDOWN , "server is going down" },
466 {AFPERR_NFILE , "too many files open" },
467 {AFPERR_BADTYPE , "object is the wrong type" },
468 {AFPERR_NOOP , "command not supported" },
469 {AFPERR_NOTAUTH , "user not authenticated" },
470 {AFPERR_SESSCLOS , "session closed" },
471 {AFPERR_RANGEOVR , "range overlap" },
472 {AFPERR_NORANGE , "no range lock" },
473 {AFPERR_PARAM , "parameter error" },
474 {AFPERR_NOOBJ , "object not found" },
475 {AFPERR_EXIST , "object already exists" },
476 {AFPERR_NOSRVR , "no response by server at that address" },
477 {AFPERR_NLOCK , "no more locks" },
478 {AFPERR_MISC , "misc. err" },
479 {AFPERR_LOCK , "LockErr" },
480 {AFPERR_NOITEM , "ItemNotFound" },
481 {AFPERR_FLATVOL , "volume doesn't support directories" },
482 {AFPERR_BUSY , "FileBusy" },
483 {AFPERR_EOF , "end of file" },
484 {AFPERR_DFULL , "disk full" },
485 {AFPERR_DIRNEMPT , "directory not empty" },
486 {AFPERR_DENYCONF , "file synchronization locks conflict" },
487 {AFPERR_CANTMOVE , "can't move file" },
488 {AFPERR_BITMAP , "invalid bitmap" },
489 {AFPERR_BADVERS , "bad afp version number" },
490 {AFPERR_BADUAM , "uam doesn't exist" },
491 {AFPERR_AUTHCONT , "logincont" },
492 {AFPERR_ACCESS , "permission denied" },
493 {ASPERR_SESSCLOS , "session closed (ASP)" },
494 {ASPERR_NOSESS , "no more sessions available"},
495 {0, NULL } };
496 value_string_ext asp_error_vals_ext = VALUE_STRING_EXT_INIT(asp_error_vals);
497
498 /*
499 * hf_index must be a FT_UINT_STRING type
500 * Are these always in a Mac extended character set? Should we have a
501 * preference to allow different character sets to be selected?
502 */
dissect_pascal_string(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_index)503 static int dissect_pascal_string(tvbuff_t *tvb, int offset, proto_tree *tree,
504 int hf_index)
505 {
506 int len;
507
508 len = tvb_get_guint8(tvb, offset);
509 proto_tree_add_item(tree, hf_index, tvb, offset, 1, ENC_MAC_ROMAN|ENC_BIG_ENDIAN);
510
511 offset += (len+1);
512
513 return offset;
514 }
515
516 static int
dissect_rtmp_request(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)517 dissect_rtmp_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
518 proto_tree *rtmp_tree;
519 proto_item *ti;
520 guint8 function;
521
522 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
523 col_clear(pinfo->cinfo, COL_INFO);
524
525 function = tvb_get_guint8(tvb, 0);
526
527 col_add_str(pinfo->cinfo, COL_INFO,
528 val_to_str(function, rtmp_function_vals, "Unknown function (%02x)"));
529
530 if (tree) {
531 ti = proto_tree_add_item(tree, proto_rtmp, tvb, 0, 1, ENC_NA);
532 rtmp_tree = proto_item_add_subtree(ti, ett_rtmp);
533
534 proto_tree_add_uint(rtmp_tree, hf_rtmp_function, tvb, 0, 1, function);
535 }
536 return tvb_captured_length(tvb);
537 }
538
539 static int
dissect_rtmp_data(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)540 dissect_rtmp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
541 proto_tree *rtmp_tree;
542 proto_item *ti;
543 int offset = 0;
544 guint16 net;
545 guint8 nodelen,nodelen_bits;
546 guint16 node; /* might be more than 8 bits */
547 int i;
548
549 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
550 col_clear(pinfo->cinfo, COL_INFO);
551
552 net = tvb_get_ntohs(tvb, offset);
553 nodelen_bits = tvb_get_guint8(tvb, offset+2);
554 if ( nodelen_bits <= 8 ) {
555 node = tvb_get_guint8(tvb, offset+3);
556 nodelen = 1;
557 } else {
558 node = tvb_get_ntohs(tvb, offset+3);
559 nodelen = 2;
560 }
561
562 col_add_fstr(pinfo->cinfo, COL_INFO, "Net: %u Node Len: %u Node: %u",
563 net, nodelen_bits, node);
564
565 if (tree) {
566 ti = proto_tree_add_item(tree, proto_rtmp, tvb, offset, -1, ENC_NA);
567 rtmp_tree = proto_item_add_subtree(ti, ett_rtmp);
568
569 proto_tree_add_uint(rtmp_tree, hf_rtmp_net, tvb, offset, 2, net);
570 proto_tree_add_uint(rtmp_tree, hf_rtmp_node_len, tvb, offset+2, 1,
571 nodelen_bits);
572 proto_tree_add_uint(rtmp_tree, hf_rtmp_node, tvb, offset+3, nodelen,
573 node);
574 offset += 3 + nodelen;
575
576 /*
577 * Peek at what is purportedly the first tuple. If the net is 0,
578 * this is a version-number indicator for a non-extended network,
579 * not a tuple; the version number field may have the 0x80 bit set,
580 * but it's not a 6-octet tuple.
581 */
582 if (tvb_get_ntohs(tvb, offset) == 0) {
583 proto_tree_add_item(rtmp_tree, hf_rtmp_version, tvb, offset+2, 1, ENC_BIG_ENDIAN);
584 offset += 3;
585 }
586
587 i = 1;
588 while (tvb_offset_exists(tvb, offset)) {
589 proto_tree *tuple_tree;
590 guint16 tuple_net;
591 guint8 tuple_dist;
592 guint16 tuple_range_end;
593 guint8 version;
594
595 tuple_net = tvb_get_ntohs(tvb, offset);
596 tuple_dist = tvb_get_guint8(tvb, offset+2);
597
598 if (tuple_dist & 0x80) {
599 /*
600 * Extended network tuple.
601 */
602 tuple_range_end = tvb_get_ntohs(tvb, offset+3);
603 version = tvb_get_guint8(tvb, offset+5);
604 if (i == 1) {
605 /*
606 * For the first tuple, the last octet is a version number.
607 */
608 tuple_tree = proto_tree_add_subtree_format(rtmp_tree, tvb, offset, 6,
609 ett_rtmp_tuple, NULL,
610 "Tuple %d: Range Start: %u Dist: %u Range End: %u Version: 0x%02x",
611 i, tuple_net, tuple_dist&0x7F,
612 tuple_range_end, version);
613 } else {
614 tuple_tree = proto_tree_add_subtree_format(rtmp_tree, tvb, offset, 6,
615 ett_rtmp_tuple, NULL,
616 "Tuple %d: Range Start: %u Dist: %u Range End: %u",
617 i, tuple_net, tuple_dist&0x7F,
618 tuple_range_end);
619 }
620 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_range_start, tvb, offset, 2,
621 tuple_net);
622 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_dist, tvb, offset+2, 1,
623 tuple_dist & 0x7F);
624 proto_tree_add_item(tuple_tree, hf_rtmp_tuple_range_end, tvb, offset+3, 2,
625 ENC_BIG_ENDIAN);
626
627 if (i == 1)
628 proto_tree_add_uint(tuple_tree, hf_rtmp_version, tvb, offset+5, 1, version);
629 offset += 6;
630 } else {
631 /*
632 * Non-extended network tuple.
633 */
634 tuple_tree = proto_tree_add_subtree_format(rtmp_tree, tvb, offset, 3,
635 ett_rtmp_tuple, NULL,
636 "Tuple %d: Net: %u Dist: %u",
637 i, tuple_net, tuple_dist);
638 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_net, tvb, offset, 2,
639 tuple_net);
640 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_dist, tvb, offset+2, 1,
641 tuple_dist);
642 offset += 3;
643 }
644
645 i++;
646 }
647 }
648 return tvb_captured_length(tvb);
649 }
650
651 static int
dissect_nbp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)652 dissect_nbp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
653 proto_tree *nbp_tree;
654 proto_tree *nbp_info_tree;
655 proto_item *ti, *info_item;
656 int offset = 0;
657 guint8 info;
658 guint op, count;
659 guint i;
660
661 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBP");
662 col_clear(pinfo->cinfo, COL_INFO);
663
664 info = tvb_get_guint8(tvb, offset);
665 op = info >> 4;
666 count = info & 0x0F;
667
668 col_add_fstr(pinfo->cinfo, COL_INFO, "Op: %s Count: %u",
669 val_to_str(op, nbp_op_vals, "Unknown (0x%01x)"), count);
670
671 if (tree) {
672 ti = proto_tree_add_item(tree, proto_nbp, tvb, offset, -1, ENC_NA);
673 nbp_tree = proto_item_add_subtree(ti, ett_nbp);
674
675 info_item = proto_tree_add_uint_format(nbp_tree, hf_nbp_info, tvb, offset, 1,
676 info,
677 "Info: 0x%01X Operation: %s Count: %u", info,
678 val_to_str(op, nbp_op_vals, "Unknown (0x%01X)"),
679 count);
680 nbp_info_tree = proto_item_add_subtree(info_item, ett_nbp_info);
681 proto_tree_add_uint(nbp_info_tree, hf_nbp_op, tvb, offset, 1, info);
682 proto_tree_add_uint(nbp_info_tree, hf_nbp_count, tvb, offset, 1, info);
683 proto_tree_add_item(nbp_tree, hf_nbp_tid, tvb, offset+1, 1, ENC_BIG_ENDIAN);
684 offset += 2;
685
686 for (i = 0; i < count; i++) {
687 proto_tree *node_item,*node_tree;
688 int soffset = offset;
689
690 node_tree = proto_tree_add_subtree_format(nbp_tree, tvb, offset, -1,
691 ett_nbp_node, &node_item, "Node %u", i+1);
692
693 proto_tree_add_item(node_tree, hf_nbp_node_net, tvb, offset, 2, ENC_BIG_ENDIAN);
694 offset += 2;
695 proto_tree_add_item(node_tree, hf_nbp_node_node, tvb, offset, 1, ENC_BIG_ENDIAN);
696 offset++;
697 proto_tree_add_item(node_tree, hf_nbp_node_port, tvb, offset, 1, ENC_BIG_ENDIAN);
698 offset++;
699 proto_tree_add_item(node_tree, hf_nbp_node_enum, tvb, offset, 1, ENC_BIG_ENDIAN);
700 offset++;
701
702 offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_object);
703 offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_type);
704 offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_zone);
705
706 proto_item_set_len(node_item, offset-soffset);
707 }
708 }
709
710 return tvb_captured_length(tvb);
711 }
712
713 /* -----------------------------
714 ATP protocol cf. inside appletalk chap. 9
715 desegmentation from packet-ieee80211.c
716 */
717 static int
dissect_atp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)718 dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
719 proto_tree *atp_tree = NULL;
720 proto_item *ti;
721 proto_tree *atp_info_tree;
722 proto_item *info_item;
723 int offset = 0;
724 guint8 ctrlinfo;
725 guint8 frag_number = 0;
726 guint op;
727 guint16 tid;
728 guint8 query;
729 struct aspinfo aspinfo;
730 tvbuff_t *new_tvb = NULL;
731 gboolean save_fragmented;
732 gboolean more_fragment = FALSE;
733 int len;
734 guint8 bitmap;
735 guint8 nbe = 0;
736 guint8 t = 0;
737 conversation_t *conversation;
738 asp_request_val *request_val = NULL;
739
740 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATP");
741
742 ctrlinfo = tvb_get_guint8(tvb, offset);
743 bitmap = tvb_get_guint8(tvb, offset +1);
744 tid = tvb_get_ntohs(tvb, offset +2);
745
746 t = bitmap;
747 while(t) {
748 nbe++;
749 t >>= 1;
750 }
751
752 op = ctrlinfo >> 6;
753
754 aspinfo.reply = (0x80 == (ctrlinfo & ATP_FUNCMASK))?1:0;
755 aspinfo.release = (0xC0 == (ctrlinfo & ATP_FUNCMASK))?1:0;
756 aspinfo.seq = tid;
757 aspinfo.code = 0;
758 query = (!aspinfo.reply && !aspinfo.release);
759
760 conversation = find_or_create_conversation(pinfo);
761
762 if (atp_defragment) {
763 asp_request_key request_key;
764
765 request_key.conversation = conversation->conv_index;
766 memcpy(request_key.src, (!aspinfo.reply)?pinfo->src.data:pinfo->dst.data, 4);
767 request_key.seq = aspinfo.seq;
768
769 request_val = (asp_request_val *) wmem_map_lookup(atp_request_hash, &request_key);
770
771 if (!request_val && query && nbe > 1) {
772 asp_request_key *new_request_key;
773
774 /* only save nbe packets if more than 1 requested
775 save some memory and help the defragmentation if tid wraparound, ie
776 we have both a request for 1 packet and a request for n packets,
777 hopefully most of the time ATP_EOM will be set in the last packet.
778 */
779 new_request_key = wmem_new(wmem_file_scope(), asp_request_key);
780 *new_request_key = request_key;
781
782 request_val = wmem_new(wmem_file_scope(), asp_request_val);
783 request_val->value = nbe;
784
785 wmem_map_insert(atp_request_hash, new_request_key,request_val);
786 }
787 }
788
789 /*
790 ATP_EOM is not mandatory. Some implementations don't always set it
791 if the query is only one packet.
792
793 So it needs to keep the number of packets asked in request.
794 */
795
796 if (aspinfo.reply) {
797 more_fragment = !(ATP_EOM & ctrlinfo) && request_val;
798 frag_number = bitmap;
799 }
800
801 col_clear(pinfo->cinfo, COL_INFO);
802 col_add_fstr(pinfo->cinfo, COL_INFO, "%s transaction %u",
803 val_to_str(op, atp_function_vals, "Unknown (0x%01x)"),tid);
804 if (more_fragment)
805 col_append_str(pinfo->cinfo, COL_INFO, " [fragment]");
806
807 if (tree) {
808 ti = proto_tree_add_item(tree, proto_atp, tvb, offset, -1, ENC_NA);
809 atp_tree = proto_item_add_subtree(ti, ett_atp);
810 proto_item_set_len(atp_tree, aspinfo.release?8:ATP_HDRSIZE -1);
811
812 info_item = proto_tree_add_item(atp_tree, hf_atp_ctrlinfo, tvb, offset, 1, ENC_BIG_ENDIAN);
813 atp_info_tree = proto_item_add_subtree(info_item, ett_atp_info);
814
815 proto_tree_add_item(atp_info_tree, hf_atp_function, tvb, offset, 1, ENC_BIG_ENDIAN);
816 proto_tree_add_item(atp_info_tree, hf_atp_xo, tvb, offset, 1, ENC_BIG_ENDIAN);
817 proto_tree_add_item(atp_info_tree, hf_atp_eom, tvb, offset, 1, ENC_BIG_ENDIAN);
818 proto_tree_add_item(atp_info_tree, hf_atp_sts, tvb, offset, 1, ENC_BIG_ENDIAN);
819 if ((ctrlinfo & (ATP_FUNCMASK|ATP_XO)) == (0x40|ATP_XO)) {
820 /* TReq with XO set */
821 proto_tree_add_item(atp_info_tree, hf_atp_treltimer, tvb, offset, 1, ENC_BIG_ENDIAN);
822 }
823 if (query) {
824 proto_tree_add_uint_format_value(atp_tree, hf_atp_bitmap, tvb, offset +1, 1,
825 bitmap, "0x%02x %u packet(s) max", bitmap, nbe);
826 }
827 else {
828 proto_tree_add_item(atp_tree, hf_atp_bitmap, tvb, offset +1, 1, ENC_BIG_ENDIAN);
829 }
830 proto_tree_add_item(atp_tree, hf_atp_tid, tvb, offset +2, 2, ENC_BIG_ENDIAN);
831
832 if (aspinfo.release)
833 proto_tree_add_item(atp_tree, hf_atp_user_bytes, tvb, offset +4, 4, ENC_BIG_ENDIAN);
834
835 }
836
837 if (aspinfo.release)
838 return tvb_captured_length(tvb);
839
840 save_fragmented = pinfo->fragmented;
841
842 /* FIXME
843 asp doesn't fit very well here
844 move asp back in atp?
845 */
846 if (atp_defragment && aspinfo.reply && (more_fragment || frag_number != 0)) {
847 fragment_head *fd_head;
848 int hdr;
849
850 hdr = ATP_HDRSIZE -1;
851 if (frag_number != 0)
852 hdr += 4; /* asp header */
853 len = tvb_reported_length_remaining(tvb, hdr);
854 fd_head = fragment_add_seq_check(&atp_reassembly_table,
855 tvb, hdr, pinfo, tid, NULL,
856 frag_number,
857 len,
858 more_fragment);
859 new_tvb = process_reassembled_data(tvb, ATP_HDRSIZE -1, pinfo,
860 "Reassembled ATP", fd_head, &atp_frag_items,
861 NULL, atp_tree);
862 }
863 else {
864 /* full packet */
865 new_tvb = tvb_new_subset_remaining(tvb, ATP_HDRSIZE -1 );
866 }
867
868 if (new_tvb) {
869 /* if port == 6 it's not an ASP packet but a ZIP packet */
870 if (pinfo->srcport == 6 || pinfo->destport == 6 )
871 call_dissector_with_data(zip_atp_handle, new_tvb, pinfo, tree, &aspinfo);
872 else {
873 /* XXX need a conversation_get_dissector function ? */
874 if (!aspinfo.reply && !conversation_get_dissector(conversation, pinfo->num)) {
875 dissector_handle_t sub;
876
877 /* if it's a known ASP function call ASP dissector
878 else assume it's a PAP connection ID.
879 the test is wrong because PAP conn IDs overlapped with ASP fn
880 but I don't want to keep track of NBP msgs and open connection
881 port allocation.
882 */
883 guint8 fn = tvb_get_guint8(new_tvb, 0);
884
885 if (!fn || fn > ASPFUNC_ATTN) {
886 sub = pap_handle;
887 }
888 else {
889 sub = asp_handle;
890 }
891 call_dissector_with_data(sub, new_tvb, pinfo, tree, &aspinfo);
892 conversation_set_dissector(conversation, sub);
893 }
894 else if (!try_conversation_dissector(&pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
895 pinfo->srcport, pinfo->destport, new_tvb,pinfo, tree, &aspinfo, 0)) {
896 call_data_dissector(new_tvb, pinfo, tree);
897
898 }
899 }
900 }
901 else {
902 /* Just show this as a fragment. */
903 new_tvb = tvb_new_subset_remaining (tvb, ATP_HDRSIZE -1);
904 call_data_dissector(new_tvb, pinfo, tree);
905 }
906 pinfo->fragmented = save_fragmented;
907 return tvb_captured_length(tvb);
908 }
909
910 /* -----------------------------
911 PAP protocol cf. inside appletalk chap. 10
912 */
913 #define PAD(x) { proto_tree_add_item(pap_tree, hf_pap_pad, tvb, offset, x, ENC_NA); offset += x; }
914
915 static int
dissect_pap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)916 dissect_pap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
917 {
918 int offset = 0;
919 guint8 fn;
920 guint8 connID;
921 proto_tree *pap_tree = NULL;
922 proto_item *ti;
923
924 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAP");
925 col_clear(pinfo->cinfo, COL_INFO);
926
927 if (tree) {
928 ti = proto_tree_add_item(tree, proto_pap, tvb, offset, -1, ENC_NA);
929 pap_tree = proto_item_add_subtree(ti, ett_pap);
930 }
931
932 connID = tvb_get_guint8(tvb, offset);
933 proto_tree_add_item(pap_tree, hf_pap_connid, tvb, offset, 1, ENC_BIG_ENDIAN);
934 offset++;
935
936 fn = tvb_get_guint8(tvb, offset);
937 proto_tree_add_item(pap_tree, hf_pap_function, tvb, offset, 1, ENC_BIG_ENDIAN);
938 offset++;
939
940 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID: %d",
941 val_to_str_ext(fn, &pap_function_vals_ext, "Unknown (0x%01x)"), connID);
942
943 switch(fn) {
944 case PAPOpenConn:
945 PAD(2);
946 proto_tree_add_item(pap_tree, hf_pap_socket, tvb, offset, 1, ENC_BIG_ENDIAN);
947 offset++;
948 proto_tree_add_item(pap_tree, hf_pap_quantum, tvb, offset, 1, ENC_BIG_ENDIAN);
949 offset++;
950 proto_tree_add_item(pap_tree, hf_pap_waittime, tvb, offset, 2, ENC_BIG_ENDIAN);
951 offset += 2;
952 break;
953
954 case PAPOpenConnReply:
955 PAD(2);
956 proto_tree_add_item(pap_tree, hf_pap_socket, tvb, offset, 1, ENC_BIG_ENDIAN);
957 offset++;
958 proto_tree_add_item(pap_tree, hf_pap_quantum, tvb, offset, 1, ENC_BIG_ENDIAN);
959 offset++;
960 proto_tree_add_item(pap_tree, hf_pap_result, tvb, offset, 2, ENC_BIG_ENDIAN);
961 offset += 2;
962 offset = dissect_pascal_string(tvb, offset, pap_tree, hf_pap_status);
963 break;
964
965 case PAPSendData:
966 proto_tree_add_item(pap_tree, hf_pap_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
967 offset += 2;
968 break;
969
970 case PAPData:
971 proto_tree_add_item(pap_tree, hf_pap_eof, tvb, offset, 1, ENC_BIG_ENDIAN);
972 offset++;
973 PAD(1);
974 /* follow by data */
975 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
976 break;
977
978 case PAPTickle:
979 case PAPCloseConn:
980 case PAPCloseConnReply:
981 PAD(2);
982 break;
983
984 case PAPSendStatus:
985 PAD(2);
986 break;
987
988 case PAPStatus:
989 PAD(2);
990 PAD(4);
991 offset = dissect_pascal_string(tvb, offset, pap_tree, hf_pap_status);
992 break;
993
994 default: /* unknown */
995 break;
996 }
997 return offset;
998 }
999
1000 /* -----------------------------
1001 ASP protocol cf. inside appletalk chap. 11
1002 */
1003 static struct aspinfo *
get_transaction(tvbuff_t * tvb,packet_info * pinfo,struct aspinfo * aspinfo)1004 get_transaction(tvbuff_t *tvb, packet_info *pinfo, struct aspinfo *aspinfo)
1005 {
1006 conversation_t *conversation;
1007 asp_request_key request_key, *new_request_key;
1008 asp_request_val *request_val;
1009 guint8 fn;
1010
1011 conversation = find_or_create_conversation(pinfo);
1012
1013 request_key.conversation = conversation->conv_index;
1014 memcpy(request_key.src, (!aspinfo->reply)?pinfo->src.data:pinfo->dst.data, 4);
1015 request_key.seq = aspinfo->seq;
1016
1017 request_val = (asp_request_val *) wmem_map_lookup(asp_request_hash, &request_key);
1018 if (!request_val && !aspinfo->reply ) {
1019 fn = tvb_get_guint8(tvb, 0);
1020 new_request_key = wmem_new(wmem_file_scope(), asp_request_key);
1021 *new_request_key = request_key;
1022
1023 request_val = wmem_new(wmem_file_scope(), asp_request_val);
1024 request_val->value = fn;
1025
1026 wmem_map_insert(asp_request_hash, new_request_key, request_val);
1027 }
1028
1029 if (!request_val)
1030 return NULL;
1031
1032 aspinfo->command = request_val->value;
1033 return aspinfo;
1034 }
1035
1036
1037 static int
dissect_asp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1038 dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1039 {
1040 struct aspinfo *aspinfo;
1041 int offset = 0;
1042 proto_tree *asp_tree = NULL;
1043 proto_item *ti;
1044 guint8 fn;
1045
1046 /* Reject the packet if data is NULL */
1047 if (data == NULL)
1048 return 0;
1049
1050 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASP");
1051 col_clear(pinfo->cinfo, COL_INFO);
1052
1053 aspinfo = get_transaction(tvb, pinfo, (struct aspinfo *)data);
1054 if (!aspinfo)
1055 return 0;
1056
1057 fn = (guint8) aspinfo->command;
1058
1059 if (aspinfo->reply)
1060 col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %u",aspinfo->seq);
1061 else
1062 col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s tid %u",
1063 val_to_str_ext(fn, &asp_func_vals_ext, "Unknown (0x%01x)"), aspinfo->seq);
1064
1065 if (tree) {
1066 ti = proto_tree_add_item(tree, proto_asp, tvb, offset, -1, ENC_NA);
1067 asp_tree = proto_item_add_subtree(ti, ett_asp);
1068 }
1069 if (!aspinfo->reply) {
1070 tvbuff_t *new_tvb;
1071 /* let the called deal with asp_tree == NULL */
1072
1073 proto_tree_add_item(asp_tree, hf_asp_func, tvb, offset, 1, ENC_BIG_ENDIAN);
1074 offset++;
1075 switch(fn) {
1076 case ASPFUNC_OPEN:
1077 proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, ENC_BIG_ENDIAN);
1078 offset++;
1079 proto_tree_add_item(asp_tree, hf_asp_version, tvb, offset, 2, ENC_BIG_ENDIAN);
1080 offset += 2;
1081 break;
1082 case ASPFUNC_TICKLE:
1083 case ASPFUNC_CLOSE:
1084 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1085 offset++;
1086 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, ENC_NA);
1087 offset +=2;
1088 break;
1089 case ASPFUNC_STAT:
1090 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, ENC_NA);
1091 offset++;
1092 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, ENC_NA);
1093 offset += 2;
1094 break;
1095 case ASPFUNC_ATTN:
1096 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1097 offset++;
1098 proto_tree_add_item(asp_tree, hf_asp_attn_code, tvb, offset, 2, ENC_BIG_ENDIAN);
1099 offset +=2;
1100 break;
1101 case ASPFUNC_CMD:
1102 case ASPFUNC_WRITE:
1103 proto_item_set_len(asp_tree, 4);
1104 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1105 offset++;
1106 proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
1107 offset += 2;
1108 new_tvb = tvb_new_subset_remaining(tvb, offset);
1109 call_dissector_with_data(afp_handle, new_tvb, pinfo, tree, aspinfo);
1110 break;
1111 case ASPFUNC_WRTCONT:
1112 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1113 offset++;
1114 proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, ENC_BIG_ENDIAN);
1115 offset += 2;
1116 proto_tree_add_item(asp_tree, hf_asp_size, tvb, offset, 2, ENC_BIG_ENDIAN);
1117 offset += 2;
1118 break;
1119 default:
1120 proto_item_set_len(asp_tree, 4);
1121 offset += 3;
1122 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
1123 break;
1124 }
1125 }
1126 else {
1127 tvbuff_t *new_tvb;
1128
1129 proto_tree_add_uint(asp_tree, hf_asp_func, tvb, 0, 0, fn);
1130 switch(fn) {
1131 case ASPFUNC_OPEN:
1132 proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, ENC_BIG_ENDIAN);
1133 offset++;
1134 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1135 offset++;
1136 proto_tree_add_item(asp_tree, hf_asp_init_error, tvb, offset, 2, ENC_BIG_ENDIAN);
1137 offset += 2;
1138 break;
1139 case ASPFUNC_CLOSE:
1140 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, ENC_NA);
1141 offset++;
1142 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, ENC_NA);
1143 offset++;
1144 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, ENC_NA);
1145 offset += 2;
1146 break;
1147 case ASPFUNC_STAT:
1148 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, ENC_NA);
1149 offset += 4;
1150 /* XXX - what if something other than AFP is running atop ASP? */
1151 new_tvb = tvb_new_subset_remaining(tvb, offset);
1152 call_dissector(afp_server_status_handle, new_tvb, pinfo, asp_tree);
1153 break;
1154 case ASPFUNC_CMD:
1155 case ASPFUNC_WRITE:
1156 proto_item_set_len(asp_tree, 4);
1157 aspinfo->code = tvb_get_ntohl(tvb, offset);
1158 proto_tree_add_item(asp_tree, hf_asp_error, tvb, offset, 4, ENC_BIG_ENDIAN);
1159 offset += 4;
1160 new_tvb = tvb_new_subset_remaining(tvb, offset);
1161 call_dissector_with_data(afp_handle, new_tvb, pinfo, tree, aspinfo);
1162 break;
1163 case ASPFUNC_TICKLE:
1164 case ASPFUNC_WRTCONT:
1165 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, ENC_NA);
1166 /* FALL THROUGH */
1167 case ASPFUNC_ATTN: /* FIXME capture and spec disagree */
1168 default:
1169 proto_item_set_len(asp_tree, 4);
1170 offset += 4;
1171 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
1172 break;
1173 }
1174 }
1175 return offset;
1176 }
1177
1178 /* -----------------------------
1179 ZIP protocol cf. inside appletalk chap. 8
1180 */
1181 /*
1182 * Structure used to represent a DDP address; gives the layout of the
1183 * data pointed to by an Appletalk "address" structure.
1184 */
1185 struct atalk_ddp_addr {
1186 guint16 net;
1187 guint8 node;
1188 };
1189
1190
atalk_str_len(const address * addr _U_)1191 static int atalk_str_len(const address* addr _U_)
1192 {
1193 return 8;
1194 }
1195
atalk_to_str(const address * addr,gchar * buf,int buf_len _U_)1196 static int atalk_to_str(const address* addr, gchar *buf, int buf_len _U_)
1197 {
1198 struct atalk_ddp_addr atalk;
1199 memcpy(&atalk, addr->data, sizeof atalk);
1200
1201 buf = word_to_hex(buf, atalk.net);
1202 *buf++ = '.';
1203 buf = bytes_to_hexstr(buf, &atalk.node, 1);
1204 *buf++ = '\0'; /* NULL terminate */
1205
1206 return atalk_str_len(addr);
1207 }
1208
atalk_col_filter_str(const address * addr _U_,gboolean is_src)1209 static const char* atalk_col_filter_str(const address* addr _U_, gboolean is_src)
1210 {
1211 if (is_src)
1212 return "ddp.src";
1213
1214 return "ddp.dst";
1215 }
1216
atalk_len(void)1217 static int atalk_len(void)
1218 {
1219 return 3;
1220 }
1221
1222 static int
dissect_atp_zip(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1223 dissect_atp_zip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1224 {
1225 struct aspinfo *aspinfo;
1226 int offset = 0;
1227 proto_tree *zip_tree;
1228 proto_tree *sub_tree;
1229 proto_item *ti;
1230 guint8 fn;
1231 guint16 count;
1232 guint8 len;
1233
1234 /* Reject the packet if data is NULL */
1235 if (data == NULL)
1236 return 0;
1237
1238 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZIP");
1239 col_clear(pinfo->cinfo, COL_INFO);
1240
1241 aspinfo = get_transaction(tvb, pinfo, (struct aspinfo *)data);
1242 if (!aspinfo)
1243 return tvb_reported_length(tvb);
1244
1245 fn = (guint8) aspinfo->command;
1246
1247 if (aspinfo->reply)
1248 col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %u",aspinfo->seq);
1249 else
1250 col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s tid %u",
1251 val_to_str(fn, zip_atp_function_vals, "Unknown (0x%01x)"), aspinfo->seq);
1252
1253 if (!tree)
1254 return tvb_reported_length(tvb);
1255
1256 ti = proto_tree_add_item(tree, proto_zip, tvb, offset, -1, ENC_NA);
1257 zip_tree = proto_item_add_subtree(ti, ett_zip);
1258
1259 if (!aspinfo->reply) {
1260 proto_tree_add_item(zip_tree, hf_zip_atp_function, tvb, offset, 1, ENC_BIG_ENDIAN);
1261 offset++;
1262 switch(fn) {
1263 case 7: /* start_index = 0 */
1264 case 8:
1265 case 9:
1266 proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 1, ENC_NA);
1267 offset++;
1268 proto_tree_add_item(zip_tree, hf_zip_start_index, tvb, offset, 2, ENC_BIG_ENDIAN);
1269 break;
1270 }
1271 }
1272 else {
1273 guint i;
1274
1275 proto_tree_add_uint(zip_tree, hf_zip_atp_function, tvb, 0, 0, fn);
1276 switch(fn) {
1277 case 7:
1278 case 8:
1279 case 9:
1280 proto_tree_add_item(zip_tree, hf_zip_last_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1281 offset++;
1282
1283 proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 1, ENC_NA);
1284 offset++;
1285 count = tvb_get_ntohs(tvb, offset);
1286 ti = proto_tree_add_item(zip_tree, hf_zip_count, tvb, offset, 2, ENC_BIG_ENDIAN);
1287 offset += 2;
1288 sub_tree = proto_item_add_subtree(ti, ett_zip_zones_list);
1289 for (i = 0; i < count; i++) {
1290 len = tvb_get_guint8(tvb, offset);
1291 proto_tree_add_item(sub_tree, hf_zip_zone_name, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1292 offset += len +1;
1293 }
1294 break;
1295 }
1296 }
1297
1298 return tvb_reported_length(tvb);
1299 }
1300
1301 static int
dissect_ddp_zip(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1302 dissect_ddp_zip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1303 {
1304 proto_tree *zip_tree = NULL;
1305 proto_item *ti;
1306 guint8 fn;
1307 guint8 len;
1308 gint offset = 0;
1309 proto_tree *sub_tree;
1310 proto_tree *net_tree;
1311 guint8 flag;
1312 guint16 net;
1313 guint i;
1314 guint count;
1315
1316 static int * const zip_flags[] = {
1317 &hf_zip_flags_zone_invalid,
1318 &hf_zip_flags_use_broadcast,
1319 &hf_zip_flags_only_one_zone,
1320 NULL
1321 };
1322
1323 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZIP");
1324 col_clear(pinfo->cinfo, COL_INFO);
1325
1326 fn = tvb_get_guint8(tvb, 0);
1327 col_add_str(pinfo->cinfo, COL_INFO,
1328 val_to_str_ext(fn, &zip_function_vals_ext, "Unknown ZIP function (%02x)"));
1329
1330 if (!tree)
1331 return tvb_captured_length(tvb);
1332
1333 ti = proto_tree_add_item(tree, proto_zip, tvb, 0, -1, ENC_NA);
1334 zip_tree = proto_item_add_subtree(ti, ett_zip);
1335
1336 proto_tree_add_item(zip_tree, hf_zip_function, tvb, offset, 1,ENC_BIG_ENDIAN);
1337 offset++;
1338 /* fn 1,7,2,8 are not tested */
1339 switch (fn) {
1340 case 1: /* Query */
1341 count = tvb_get_guint8(tvb, offset);
1342 ti = proto_tree_add_item(zip_tree, hf_zip_network_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1343 offset++;
1344 sub_tree = proto_item_add_subtree(ti, ett_zip_network_list);
1345 for (i = 0; i < count; i++) {
1346 proto_tree_add_item(sub_tree, hf_zip_network, tvb, offset, 2, ENC_BIG_ENDIAN);
1347 offset += 2;
1348 }
1349 break;
1350 case 7: /* Notify */
1351 proto_tree_add_bitmask(zip_tree, tvb, offset, hf_zip_flags, ett_zip_flags, zip_flags, ENC_NA);
1352 offset++;
1353
1354 proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 4, ENC_NA);
1355 offset += 4;
1356
1357 len = tvb_get_guint8(tvb, offset);
1358 proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1359 offset += len +1;
1360
1361 len = tvb_get_guint8(tvb, offset);
1362 proto_tree_add_item(zip_tree, hf_zip_multicast_length,tvb, offset, 1,ENC_BIG_ENDIAN);
1363 offset++;
1364 proto_tree_add_item(zip_tree, hf_zip_multicast_address,tvb, offset, len,ENC_NA);
1365 offset += len;
1366
1367 proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1368 break;
1369
1370 case 2: /* Reply */
1371 case 8: /* Extended Reply */
1372 count = tvb_get_guint8(tvb, offset);
1373 ti = proto_tree_add_item(zip_tree, hf_zip_network_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1374 offset++;
1375 sub_tree = proto_item_add_subtree(ti, ett_zip_network_list);
1376 for (i = 0; i < count; i++) {
1377 net = tvb_get_ntohs(tvb, offset);
1378 net_tree = proto_tree_add_subtree_format(sub_tree, tvb, offset, 2, ett_zip_network_list, &ti, "Zone for network: %u", net);
1379 proto_tree_add_item(net_tree, hf_zip_network, tvb, offset, 2, ENC_BIG_ENDIAN);
1380 offset += 2;
1381 len = tvb_get_guint8(tvb, offset);
1382 proto_tree_add_item(net_tree, hf_zip_zone_name, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1383 offset += len +1;
1384 proto_item_set_len(ti, len+3);
1385 }
1386 break;
1387
1388 case 5 : /* GetNetInfo request */
1389 proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 1, ENC_NA);
1390 offset++;
1391 proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 4, ENC_NA);
1392 offset += 4;
1393 proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1394 break;
1395
1396 case 6 : /* GetNetInfo reply */
1397 flag = tvb_get_guint8(tvb, offset);
1398 proto_tree_add_bitmask(zip_tree, tvb, offset, hf_zip_flags, ett_zip_flags, zip_flags, ENC_NA);
1399 offset++;
1400
1401 proto_tree_add_item(zip_tree, hf_zip_network_start, tvb, offset, 2, ENC_BIG_ENDIAN);
1402 offset += 2;
1403
1404 proto_tree_add_item(zip_tree, hf_zip_network_end, tvb, offset, 2, ENC_BIG_ENDIAN);
1405 offset += 2;
1406
1407 len = tvb_get_guint8(tvb, offset);
1408 proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1409 offset += len +1;
1410
1411 len = tvb_get_guint8(tvb, offset);
1412 proto_tree_add_item(zip_tree, hf_zip_multicast_length,tvb, offset, 1,ENC_BIG_ENDIAN);
1413 offset++;
1414 proto_tree_add_item(zip_tree, hf_zip_multicast_address,tvb, offset, len,ENC_NA);
1415 offset += len;
1416 if ((flag & 0x80) != 0)
1417 proto_tree_add_item(zip_tree, hf_zip_default_zone, tvb, offset, 1,ENC_ASCII|ENC_BIG_ENDIAN);
1418 break;
1419
1420 default:
1421 break;
1422 }
1423 return tvb_captured_length(tvb);
1424 }
1425
1426 typedef struct ddp_nodes
1427 {
1428 guint8 dnode;
1429 guint8 snode;
1430
1431 } ddp_nodes_t;
1432
1433 static int
dissect_ddp_short(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)1434 dissect_ddp_short(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1435 {
1436 guint16 len;
1437 guint8 dport;
1438 guint8 sport;
1439 guint8 type;
1440 proto_tree *ddp_tree = NULL;
1441 proto_item *ti, *hidden_item, *len_item;
1442 struct atalk_ddp_addr *src = wmem_new0(pinfo->pool, struct atalk_ddp_addr),
1443 *dst = wmem_new0(pinfo->pool, struct atalk_ddp_addr);
1444 tvbuff_t *new_tvb;
1445 ddp_nodes_t *ddp_node = (ddp_nodes_t*)data;
1446
1447 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP");
1448 col_clear(pinfo->cinfo, COL_INFO);
1449
1450 if (tree) {
1451 ti = proto_tree_add_item(tree, proto_ddp, tvb, 0, DDP_SHORT_HEADER_SIZE,
1452 ENC_NA);
1453 ddp_tree = proto_item_add_subtree(ti, ett_ddp);
1454 }
1455 len = tvb_get_ntohs(tvb, 0);
1456 len_item = proto_tree_add_uint(ddp_tree, hf_ddp_len, tvb, 0, 2, len);
1457 if (len < DDP_SHORT_HEADER_SIZE) {
1458 expert_add_info_format(pinfo, len_item, &ei_ddp_len_invalid,
1459 "Length field is shorter than the DDP header size");
1460 len = DDP_SHORT_HEADER_SIZE;
1461 } else {
1462 /* Length of the payload following the DDP header */
1463 guint reported_length = tvb_reported_length(tvb);
1464 if (len > reported_length) {
1465 expert_add_info_format(pinfo, len_item, &ei_ddp_len_invalid,
1466 "Length field is larger than the remaining packet payload");
1467 len = reported_length;
1468 }
1469 }
1470 set_actual_length(tvb, len);
1471 dport = tvb_get_guint8(tvb, 2);
1472 if (tree)
1473 proto_tree_add_uint(ddp_tree, hf_ddp_dst_socket, tvb, 2, 1, dport);
1474 sport = tvb_get_guint8(tvb, 3);
1475 if (tree)
1476 proto_tree_add_uint(ddp_tree, hf_ddp_src_socket, tvb, 3, 1, sport);
1477 type = tvb_get_guint8(tvb, 4);
1478
1479 src->net = 0;
1480 src->node = ddp_node->snode;
1481 dst->net = 0;
1482 dst->node = ddp_node->dnode;
1483 set_address(&pinfo->net_src, atalk_address_type, sizeof(struct atalk_ddp_addr), src);
1484 copy_address_shallow(&pinfo->src, &pinfo->net_src);
1485 set_address(&pinfo->net_dst, atalk_address_type, sizeof(struct atalk_ddp_addr), dst);
1486 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
1487
1488 pinfo->ptype = PT_DDP;
1489 pinfo->destport = dport;
1490 pinfo->srcport = sport;
1491
1492 col_add_str(pinfo->cinfo, COL_INFO,
1493 val_to_str_ext(type, &op_vals_ext, "Unknown DDP protocol (%02x)"));
1494
1495 if (tree) {
1496 hidden_item = proto_tree_add_string(ddp_tree, hf_ddp_src, tvb,
1497 4, 3, address_to_str(pinfo->pool, &pinfo->src));
1498 proto_item_set_hidden(hidden_item);
1499 hidden_item = proto_tree_add_string(ddp_tree, hf_ddp_dst, tvb,
1500 6, 3, address_to_str(pinfo->pool, &pinfo->dst));
1501 proto_item_set_hidden(hidden_item);
1502
1503 proto_tree_add_uint(ddp_tree, hf_ddp_type, tvb, 4, 1, type);
1504 }
1505 new_tvb = tvb_new_subset_remaining(tvb, DDP_SHORT_HEADER_SIZE);
1506
1507 if (!dissector_try_uint(ddp_dissector_table, type, new_tvb, pinfo, tree))
1508 call_data_dissector(new_tvb, pinfo, tree);
1509
1510 return tvb_captured_length(tvb);
1511 }
1512
1513 static int
dissect_ddp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1514 dissect_ddp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1515 {
1516 proto_tree *ddp_tree;
1517 proto_item *ti, *hidden_item, *len_item;
1518 struct atalk_ddp_addr *src = wmem_new0(pinfo->pool, struct atalk_ddp_addr),
1519 *dst = wmem_new0(pinfo->pool, struct atalk_ddp_addr);
1520 tvbuff_t *new_tvb;
1521 guint type;
1522 guint32 len;
1523
1524 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP");
1525 col_clear(pinfo->cinfo, COL_INFO);
1526
1527 pinfo->ptype = PT_DDP;
1528
1529 ti = proto_tree_add_item(tree, proto_ddp, tvb, 0, DDP_HEADER_SIZE, ENC_NA);
1530 ddp_tree = proto_item_add_subtree(ti, ett_ddp);
1531
1532 hidden_item = proto_tree_add_string(ddp_tree, hf_ddp_src, tvb,
1533 4, 3, address_to_str(pinfo->pool, &pinfo->src));
1534 proto_item_set_hidden(hidden_item);
1535
1536 hidden_item = proto_tree_add_string(ddp_tree, hf_ddp_dst, tvb,
1537 6, 3, address_to_str(pinfo->pool, &pinfo->dst));
1538 proto_item_set_hidden(hidden_item);
1539
1540 proto_tree_add_item(ddp_tree, hf_ddp_hopcount, tvb, 0, 2, ENC_BIG_ENDIAN);
1541 len_item = proto_tree_add_item_ret_uint(ddp_tree, hf_ddp_len, tvb, 0, 2, ENC_BIG_ENDIAN, &len);
1542 if (len < DDP_HEADER_SIZE) {
1543 expert_add_info_format(pinfo, len_item, &ei_ddp_len_invalid,
1544 "Length field is shorter than the DDP header size");
1545 len = DDP_HEADER_SIZE;
1546 } else {
1547 /* Length of the payload following the DDP header */
1548 guint reported_length = tvb_reported_length(tvb);
1549 if (len > reported_length) {
1550 expert_add_info_format(pinfo, len_item, &ei_ddp_len_invalid,
1551 "Length field is larger than the remaining packet payload");
1552 len = reported_length;
1553 }
1554 }
1555 set_actual_length(tvb, len);
1556 proto_tree_add_checksum(ddp_tree, tvb, 2, hf_ddp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1557 dst->net = tvb_get_ntohs(tvb, 4);
1558 proto_tree_add_uint(ddp_tree, hf_ddp_dst_net, tvb, 4, 2, dst->net);
1559 src->net = tvb_get_ntohs(tvb, 6);
1560 proto_tree_add_uint(ddp_tree, hf_ddp_src_net, tvb, 6, 2, src->net);
1561 dst->node = tvb_get_guint8(tvb, 8);
1562 proto_tree_add_uint(ddp_tree, hf_ddp_dst_node, tvb, 8, 1, dst->node);
1563 src->node = tvb_get_guint8(tvb, 9);
1564 proto_tree_add_uint(ddp_tree, hf_ddp_src_node, tvb, 9, 1, src->node);
1565 proto_tree_add_item_ret_uint(ddp_tree, hf_ddp_dst_socket, tvb, 10, 1, ENC_NA, &pinfo->destport);
1566 proto_tree_add_item_ret_uint(ddp_tree, hf_ddp_src_socket, tvb, 11, 1, ENC_NA, &pinfo->srcport);
1567 proto_tree_add_item_ret_uint(ddp_tree, hf_ddp_type, tvb, 12, 1, ENC_NA, &type);
1568
1569 col_add_str(pinfo->cinfo, COL_INFO,
1570 val_to_str_ext(type, &op_vals_ext, "Unknown DDP protocol (%02x)"));
1571
1572 set_address(&pinfo->net_src, atalk_address_type, sizeof(struct atalk_ddp_addr), src);
1573 copy_address_shallow(&pinfo->src, &pinfo->net_src);
1574 set_address(&pinfo->net_dst, atalk_address_type, sizeof(struct atalk_ddp_addr), dst);
1575 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
1576
1577 new_tvb = tvb_new_subset_remaining(tvb, DDP_HEADER_SIZE);
1578
1579 if (!dissector_try_uint(ddp_dissector_table, type, new_tvb, pinfo, tree))
1580 {
1581 call_data_dissector(new_tvb, pinfo, tree);
1582 }
1583 return tvb_captured_length(tvb);
1584 }
1585
1586 static const value_string llap_type_vals[] = {
1587 {0x01, "Short DDP"},
1588 {0x02, "DDP" },
1589 {0x81, "Enquiry"},
1590 {0x82, "Acknowledgement"},
1591 {0x84, "RTS"},
1592 {0x85, "CTS"},
1593 {0, NULL}
1594 };
1595 static value_string_ext llap_type_vals_ext = VALUE_STRING_EXT_INIT(llap_type_vals);
1596
1597 static gboolean
capture_llap(const guchar * pd _U_,int offset _U_,int len _U_,capture_packet_info_t * cpinfo _U_,const union wtap_pseudo_header * pseudo_header _U_)1598 capture_llap(const guchar *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo _U_, const union wtap_pseudo_header *pseudo_header _U_)
1599 {
1600 /* XXX - get its own counter
1601 counts->other++; */
1602 return FALSE;
1603 }
1604
1605 static int
dissect_llap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1606 dissect_llap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1607 {
1608 ddp_nodes_t ddp_node;
1609 guint8 type;
1610 proto_tree *llap_tree;
1611 proto_item *ti;
1612 tvbuff_t *new_tvb;
1613 guint new_reported_length;
1614
1615 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLAP");
1616 col_clear(pinfo->cinfo, COL_INFO);
1617
1618 ti = proto_tree_add_item(tree, proto_llap, tvb, 0, 3, ENC_NA);
1619 llap_tree = proto_item_add_subtree(ti, ett_llap);
1620
1621 ddp_node.dnode = tvb_get_guint8(tvb, 0);
1622 proto_tree_add_uint(llap_tree, hf_llap_dst, tvb, 0, 1, ddp_node.dnode);
1623
1624 ddp_node.snode = tvb_get_guint8(tvb, 1);
1625 proto_tree_add_uint(llap_tree, hf_llap_src, tvb, 1, 1, ddp_node.snode);
1626
1627 type = tvb_get_guint8(tvb, 2);
1628 col_add_str(pinfo->cinfo, COL_INFO,
1629 val_to_str_ext(type, &llap_type_vals_ext, "Unknown LLAP type (%02x)"));
1630 proto_tree_add_uint(llap_tree, hf_llap_type, tvb, 2, 1, type);
1631
1632 new_tvb = tvb_new_subset_remaining(tvb, 3);
1633
1634 switch (type) {
1635 case 0x01:
1636 if (call_dissector_with_data(ddp_short_handle, new_tvb, pinfo, tree, &ddp_node)) {
1637 /*
1638 * Set our tvbuff's length based on the new tvbuff's length, so
1639 * that, if we're called from the Ethernet dissector, it can
1640 * report any trailer.
1641 *
1642 * Add 3 to that length, for the LLAP header.
1643 */
1644 new_reported_length = tvb_reported_length(new_tvb) + 3;
1645 set_actual_length(tvb, new_reported_length);
1646 return tvb_captured_length(tvb);
1647 }
1648 break;
1649 case 0x02:
1650 if (call_dissector(ddp_handle, new_tvb, pinfo, tree)) {
1651 /*
1652 * As above.
1653 */
1654 new_reported_length = tvb_reported_length(new_tvb) + 3;
1655 set_actual_length(tvb, new_reported_length);
1656 return tvb_captured_length(tvb);
1657 }
1658 break;
1659 }
1660 call_data_dissector(new_tvb, pinfo, tree);
1661 return tvb_captured_length(tvb);
1662 }
1663
1664 void
proto_register_atalk(void)1665 proto_register_atalk(void)
1666 {
1667 static hf_register_info hf_llap[] = {
1668 { &hf_llap_dst,
1669 { "Destination Node", "llap.dst", FT_UINT8, BASE_DEC, NULL, 0x0,
1670 NULL, HFILL }},
1671
1672 { &hf_llap_src,
1673 { "Source Node", "llap.src", FT_UINT8, BASE_DEC, NULL, 0x0,
1674 NULL, HFILL }},
1675
1676 { &hf_llap_type,
1677 { "Type", "llap.type", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &llap_type_vals_ext, 0x0,
1678 NULL, HFILL }},
1679 };
1680
1681 static hf_register_info hf_llc[] = {
1682 { &hf_llc_apple_atalk_pid,
1683 { "PID", "llc.apple_atalk_pid", FT_UINT16, BASE_HEX,
1684 VALS(apple_atalk_pid_vals), 0x0, "Protocol ID", HFILL }
1685 }
1686 };
1687
1688 static hf_register_info hf_ddp[] = {
1689 { &hf_ddp_hopcount,
1690 { "Hop count", "ddp.hopcount", FT_UINT16, BASE_DEC, NULL, 0x3C00,
1691 NULL, HFILL }},
1692
1693 { &hf_ddp_len,
1694 { "Datagram length", "ddp.len", FT_UINT16, BASE_DEC, NULL, 0x03FF,
1695 NULL, HFILL }},
1696
1697 { &hf_ddp_checksum,
1698 { "Checksum", "ddp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0,
1699 NULL, HFILL }},
1700
1701 { &hf_ddp_dst,
1702 { "Destination address", "ddp.dst", FT_STRING, BASE_NONE, NULL, 0x0,
1703 NULL, HFILL }},
1704
1705 { &hf_ddp_dst_net,
1706 { "Destination Net", "ddp.dst.net", FT_UINT16, BASE_DEC, NULL, 0x0,
1707 NULL, HFILL }},
1708
1709 { &hf_ddp_src,
1710 { "Source address", "ddp.src", FT_STRING, BASE_NONE, NULL, 0x0,
1711 NULL, HFILL }},
1712
1713 { &hf_ddp_src_net,
1714 { "Source Net", "ddp.src.net", FT_UINT16, BASE_DEC, NULL, 0x0,
1715 NULL, HFILL }},
1716
1717 { &hf_ddp_dst_node,
1718 { "Destination Node", "ddp.dst.node", FT_UINT8, BASE_DEC, NULL, 0x0,
1719 NULL, HFILL }},
1720
1721 { &hf_ddp_src_node,
1722 { "Source Node", "ddp.src.node", FT_UINT8, BASE_DEC, NULL, 0x0,
1723 NULL, HFILL }},
1724
1725 { &hf_ddp_dst_socket,
1726 { "Destination Socket", "ddp.dst_socket", FT_UINT8, BASE_DEC, NULL, 0x0,
1727 NULL, HFILL }},
1728
1729 { &hf_ddp_src_socket,
1730 { "Source Socket", "ddp.src_socket", FT_UINT8, BASE_DEC, NULL, 0x0,
1731 NULL, HFILL }},
1732
1733 { &hf_ddp_type,
1734 { "Protocol type", "ddp.type", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &op_vals_ext, 0x0,
1735 NULL, HFILL }},
1736 };
1737
1738 static hf_register_info hf_nbp[] = {
1739 { &hf_nbp_op,
1740 { "Operation", "nbp.op", FT_UINT8, BASE_DEC,
1741 VALS(nbp_op_vals), 0xF0, NULL, HFILL }},
1742 { &hf_nbp_info,
1743 { "Info", "nbp.info", FT_UINT8, BASE_HEX,
1744 NULL, 0x0, NULL, HFILL }},
1745 { &hf_nbp_count,
1746 { "Count", "nbp.count", FT_UINT8, BASE_DEC,
1747 NULL, 0x0F, NULL, HFILL }},
1748 { &hf_nbp_node_net,
1749 { "Network", "nbp.net", FT_UINT16, BASE_DEC,
1750 NULL, 0x0, NULL, HFILL }},
1751 { &hf_nbp_node_node,
1752 { "Node", "nbp.node", FT_UINT8, BASE_DEC,
1753 NULL, 0x0, NULL, HFILL }},
1754 { &hf_nbp_node_port,
1755 { "Port", "nbp.port", FT_UINT8, BASE_DEC,
1756 NULL, 0x0, NULL, HFILL }},
1757 { &hf_nbp_node_enum,
1758 { "Enumerator", "nbp.enum", FT_UINT8, BASE_DEC,
1759 NULL, 0x0, NULL, HFILL }},
1760 { &hf_nbp_node_object,
1761 { "Object", "nbp.object", FT_UINT_STRING, STR_UNICODE,
1762 NULL, 0x0, NULL, HFILL }},
1763 { &hf_nbp_node_type,
1764 { "Type", "nbp.type", FT_UINT_STRING, STR_UNICODE,
1765 NULL, 0x0, NULL, HFILL }},
1766 { &hf_nbp_node_zone,
1767 { "Zone", "nbp.zone", FT_UINT_STRING, STR_UNICODE,
1768 NULL, 0x0, NULL, HFILL }},
1769 { &hf_nbp_tid,
1770 { "Transaction ID", "nbp.tid", FT_UINT8, BASE_DEC,
1771 NULL, 0x0, NULL, HFILL }}
1772 };
1773
1774 static hf_register_info hf_rtmp[] = {
1775 { &hf_rtmp_net,
1776 { "Net", "rtmp.net", FT_UINT16, BASE_DEC,
1777 NULL, 0x0, NULL, HFILL }},
1778 { &hf_rtmp_node,
1779 { "Node", "nbp.nodeid", FT_UINT8, BASE_DEC,
1780 NULL, 0x0, NULL, HFILL }},
1781 { &hf_rtmp_node_len,
1782 { "Node Length", "nbp.nodeid.length", FT_UINT8, BASE_DEC,
1783 NULL, 0x0, NULL, HFILL }},
1784 { &hf_rtmp_tuple_net,
1785 { "Net", "rtmp.tuple.net", FT_UINT16, BASE_DEC,
1786 NULL, 0x0, NULL, HFILL }},
1787 { &hf_rtmp_tuple_range_start,
1788 { "Range Start", "rtmp.tuple.range_start", FT_UINT16, BASE_DEC,
1789 NULL, 0x0, NULL, HFILL }},
1790 { &hf_rtmp_tuple_range_end,
1791 { "Range End", "rtmp.tuple.range_end", FT_UINT16, BASE_DEC,
1792 NULL, 0x0, NULL, HFILL }},
1793 { &hf_rtmp_tuple_dist,
1794 { "Distance", "rtmp.tuple.dist", FT_UINT16, BASE_DEC,
1795 NULL, 0x0, NULL, HFILL }},
1796 { &hf_rtmp_version,
1797 { "Version", "rtmp.version", FT_UINT8, BASE_HEX,
1798 NULL, 0x0, NULL, HFILL }},
1799 { &hf_rtmp_function,
1800 { "Function", "rtmp.function", FT_UINT8, BASE_DEC,
1801 VALS(rtmp_function_vals), 0x0, "Request Function", HFILL }}
1802 };
1803
1804 static hf_register_info hf_atp[] = {
1805 { &hf_atp_ctrlinfo,
1806 { "Control info", "atp.ctrlinfo", FT_UINT8, BASE_HEX,
1807 NULL, 0, NULL, HFILL }},
1808
1809 { &hf_atp_function,
1810 { "Function", "atp.function", FT_UINT8, BASE_DEC,
1811 VALS(atp_function_vals), ATP_FUNCMASK, "function code", HFILL }},
1812
1813
1814 { &hf_atp_xo,
1815 { "XO", "atp.xo", FT_BOOLEAN, 8,
1816 NULL, ATP_XO, "Exactly-once flag", HFILL }},
1817
1818 { &hf_atp_eom,
1819 { "EOM", "atp.eom", FT_BOOLEAN, 8,
1820 NULL, ATP_EOM, "End-of-message", HFILL }},
1821
1822 { &hf_atp_sts,
1823 { "STS", "atp.sts", FT_BOOLEAN, 8,
1824 NULL, ATP_STS, "Send transaction status", HFILL }},
1825
1826 { &hf_atp_treltimer,
1827 { "TRel timer", "atp.treltimer", FT_UINT8, BASE_DEC,
1828 VALS(atp_trel_timer_vals), 0x07, NULL, HFILL }},
1829
1830 { &hf_atp_bitmap,
1831 { "Bitmap", "atp.bitmap", FT_UINT8, BASE_HEX,
1832 NULL, 0x0, "Bitmap or sequence number", HFILL }},
1833
1834 { &hf_atp_tid,
1835 { "TID", "atp.tid", FT_UINT16, BASE_DEC,
1836 NULL, 0x0, "Transaction id", HFILL }},
1837 { &hf_atp_user_bytes,
1838 { "User bytes", "atp.user_bytes", FT_UINT32, BASE_HEX,
1839 NULL, 0x0, NULL, HFILL }},
1840
1841 { &hf_atp_segment_overlap,
1842 { "Segment overlap", "atp.segment.overlap", FT_BOOLEAN, BASE_NONE,
1843 NULL, 0x0, "Segment overlaps with other segments", HFILL }},
1844
1845 { &hf_atp_segment_overlap_conflict,
1846 { "Conflicting data in segment overlap", "atp.segment.overlap.conflict",
1847 FT_BOOLEAN, BASE_NONE,
1848 NULL, 0x0, "Overlapping segments contained conflicting data", HFILL }},
1849
1850 { &hf_atp_segment_multiple_tails,
1851 { "Multiple tail segments found", "atp.segment.multipletails",
1852 FT_BOOLEAN, BASE_NONE,
1853 NULL, 0x0, "Several tails were found when desegmenting the packet", HFILL }},
1854
1855 { &hf_atp_segment_too_long_segment,
1856 { "Segment too long", "atp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE,
1857 NULL, 0x0, "Segment contained data past end of packet", HFILL }},
1858
1859 { &hf_atp_segment_error,
1860 {"Desegmentation error", "atp.segment.error", FT_FRAMENUM, BASE_NONE,
1861 NULL, 0x0, "Desegmentation error due to illegal segments", HFILL }},
1862
1863 { &hf_atp_segment_count,
1864 { "Segment count", "atp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
1865 NULL, HFILL }},
1866
1867 { &hf_atp_segment,
1868 { "ATP Fragment", "atp.fragment", FT_FRAMENUM, BASE_NONE,
1869 NULL, 0x0, NULL, HFILL }},
1870
1871 { &hf_atp_segments,
1872 { "ATP Fragments", "atp.fragments", FT_NONE, BASE_NONE,
1873 NULL, 0x0, NULL, HFILL }},
1874
1875 { &hf_atp_reassembled_in,
1876 { "Reassembled ATP in frame", "atp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1877 "This ATP packet is reassembled in this frame", HFILL }},
1878
1879 { &hf_atp_reassembled_length,
1880 { "Reassembled ATP length", "atp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1881 "The total length of the reassembled payload", HFILL }}
1882 };
1883
1884 static hf_register_info hf_asp[] = {
1885 { &hf_asp_func,
1886 { "asp function", "asp.function", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
1887 &asp_func_vals_ext, 0, NULL, HFILL }},
1888
1889 { &hf_asp_error,
1890 { "asp error", "asp.error", FT_INT32, BASE_DEC|BASE_EXT_STRING,
1891 &asp_error_vals_ext, 0, "return error code", HFILL }},
1892
1893 { &hf_asp_version,
1894 { "Version", "asp.version", FT_UINT16, BASE_HEX,
1895 NULL, 0, "asp version", HFILL }},
1896
1897 { &hf_asp_attn_code,
1898 { "Attn code", "asp.attn_code", FT_UINT16, BASE_HEX,
1899 NULL, 0, "asp attention code", HFILL }},
1900
1901 { &hf_asp_init_error,
1902 { "Error", "asp.init_error", FT_UINT16, BASE_DEC,
1903 NULL, 0, "asp init error", HFILL }},
1904
1905 { &hf_asp_session_id,
1906 { "Session ID", "asp.session_id", FT_UINT8, BASE_DEC,
1907 NULL, 0, "asp session id", HFILL }},
1908
1909 { &hf_asp_socket,
1910 { "Socket", "asp.socket", FT_UINT8, BASE_DEC,
1911 NULL, 0, "asp socket", HFILL }},
1912
1913 { &hf_asp_seq,
1914 { "Sequence", "asp.seq", FT_UINT16, BASE_DEC,
1915 NULL, 0, "asp sequence number", HFILL }},
1916
1917 { &hf_asp_size,
1918 { "size", "asp.size", FT_UINT16, BASE_DEC,
1919 NULL, 0, "asp available size for reply", HFILL }},
1920
1921 { &hf_asp_zero_value,
1922 { "Pad (0)", "asp.zero_value",
1923 FT_BYTES, BASE_NONE, NULL, 0x0,
1924 "Pad", HFILL }},
1925 };
1926
1927 static hf_register_info hf_zip[] = {
1928 { &hf_zip_function,
1929 { "Function", "zip.function", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &zip_function_vals_ext, 0x0,
1930 "ZIP function", HFILL }},
1931
1932 { &hf_zip_zero_value,
1933 { "Pad (0)", "zip.zero_value",FT_BYTES, BASE_NONE, NULL, 0x0,
1934 "Pad", HFILL }},
1935
1936 { &hf_zip_atp_function,
1937 { "Function", "zip.atp_function", FT_UINT8, BASE_DEC, VALS(zip_atp_function_vals), 0x0,
1938 NULL, HFILL }},
1939
1940 { &hf_zip_start_index,
1941 { "Start index", "zip.start_index", FT_UINT16, BASE_DEC, NULL, 0x0,
1942 NULL, HFILL }},
1943
1944 { &hf_zip_count,
1945 { "Count", "zip.count", FT_UINT16, BASE_DEC, NULL, 0x0,
1946 NULL, HFILL }},
1947
1948 { &hf_zip_network_count,
1949 { "Count", "zip.network_count", FT_UINT8, BASE_DEC, NULL, 0x0,
1950 NULL, HFILL }},
1951 { &hf_zip_network,
1952 { "Network","zip.network", FT_UINT16, BASE_DEC, NULL, 0x0,
1953 NULL, HFILL }},
1954 { &hf_zip_network_start,
1955 { "Network start","zip.network_start", FT_UINT16, BASE_DEC, NULL, 0x0,
1956 NULL, HFILL }},
1957 { &hf_zip_network_end,
1958 { "Network end", "zip.network_end", FT_UINT16, BASE_DEC, NULL, 0x0,
1959 NULL, HFILL }},
1960
1961 { &hf_zip_flags,
1962 { "Flags", "zip.flags", FT_UINT8, BASE_HEX, NULL, 0xC0,
1963 NULL, HFILL }},
1964 { &hf_zip_last_flag,
1965 { "Last Flag", "zip.last_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1966 "Non zero if contains last zone name in the zone list", HFILL }},
1967
1968 { &hf_zip_flags_zone_invalid,
1969 { "Zone invalid", "zip.flags.zone_invalid", FT_BOOLEAN, 8, NULL, 0x80,
1970 NULL, HFILL }},
1971
1972 { &hf_zip_flags_use_broadcast,
1973 { "Use broadcast","zip.flags.use_broadcast", FT_BOOLEAN, 8, NULL, 0x40,
1974 NULL, HFILL }},
1975
1976 { &hf_zip_flags_only_one_zone,
1977 { "Only one zone","zip.flags.only_one_zone", FT_BOOLEAN, 8, NULL, 0x20,
1978 NULL, HFILL }},
1979
1980 { &hf_zip_zone_name,
1981 { "Zone", "zip.zone_name", FT_UINT_STRING, STR_UNICODE, NULL, 0x0,
1982 NULL, HFILL }},
1983
1984 { &hf_zip_default_zone,
1985 { "Default zone", "zip.default_zone",FT_UINT_STRING, STR_UNICODE, NULL, 0x0,
1986 NULL, HFILL }},
1987
1988 { &hf_zip_multicast_length,
1989 { "Multicast length", "zip.multicast_length", FT_UINT8, BASE_DEC, NULL, 0x0,
1990 "Multicast address length", HFILL }},
1991
1992 { &hf_zip_multicast_address,
1993 { "Multicast address", "zip.multicast_address",FT_BYTES, BASE_NONE, NULL, 0x0,
1994 NULL, HFILL }},
1995
1996 };
1997
1998 static hf_register_info hf_pap[] = {
1999 { &hf_pap_connid,
2000 { "ConnID", "prap.connid", FT_UINT8, BASE_DEC, NULL, 0x0,
2001 "PAP connection ID", HFILL }},
2002
2003 { &hf_pap_function,
2004 { "Function", "prap.function", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &pap_function_vals_ext, 0x0,
2005 "PAP function", HFILL }},
2006
2007 { &hf_pap_socket,
2008 { "Socket", "prap.socket", FT_UINT8, BASE_DEC, NULL, 0x0,
2009 "ATP responding socket number", HFILL }},
2010
2011 { &hf_pap_quantum,
2012 { "Quantum", "prap.quantum", FT_UINT8, BASE_DEC, NULL, 0x0,
2013 "Flow quantum", HFILL }},
2014
2015 { &hf_pap_waittime,
2016 { "Wait time", "prap.waittime", FT_UINT16, BASE_DEC, NULL, 0x0,
2017 NULL, HFILL }},
2018
2019 { &hf_pap_result,
2020 { "Result", "prap.result", FT_UINT16, BASE_DEC, NULL, 0x0,
2021 NULL, HFILL }},
2022
2023 { &hf_pap_seq,
2024 { "Sequence", "prap.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
2025 "Sequence number", HFILL }},
2026
2027 { &hf_pap_status,
2028 { "Status", "prap.status", FT_UINT_STRING, STR_UNICODE, NULL, 0x0,
2029 "Printer status", HFILL }},
2030
2031 { &hf_pap_eof,
2032 { "EOF", "prap.eof", FT_BOOLEAN, BASE_NONE,
2033 NULL, 0x0, NULL, HFILL }},
2034
2035 { &hf_pap_pad,
2036 { "Pad", "prap.pad", FT_NONE, BASE_NONE, NULL, 0,
2037 "Pad Byte", HFILL }},
2038
2039 };
2040
2041 static ei_register_info ei_ddp[] = {
2042 { &ei_ddp_len_invalid, { "ddp.len_invalid", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
2043 };
2044
2045 static gint *ett[] = {
2046 &ett_llap,
2047 &ett_ddp,
2048 &ett_atp,
2049 &ett_atp_info,
2050 &ett_atp_segments,
2051 &ett_atp_segment,
2052 &ett_asp,
2053 &ett_pap,
2054
2055 &ett_nbp,
2056 &ett_nbp_info,
2057 &ett_nbp_node,
2058 &ett_pstring,
2059 &ett_rtmp,
2060 &ett_rtmp_tuple,
2061
2062 &ett_zip,
2063 &ett_zip_flags,
2064 &ett_zip_zones_list,
2065 &ett_zip_network_list,
2066 };
2067 module_t *atp_module;
2068 expert_module_t *expert_ddp;
2069
2070 /*
2071 * AppleTalk over LAN (EtherTalk, TokenTalk) uses LLC/SNAP headers with
2072 * an OUI of OUI_APPLE_ATALK and a PID of either ETHERTYPE_ATALK.
2073 */
2074 llc_add_oui(OUI_APPLE_ATALK, "llc.apple_atalk_pid", "LLC Apple AppleTalk OUI PID", hf_llc, -1);
2075
2076 proto_llap = proto_register_protocol("LocalTalk Link Access Protocol", "LLAP", "llap");
2077 proto_register_field_array(proto_llap, hf_llap, array_length(hf_llap));
2078
2079 proto_ddp = proto_register_protocol("Datagram Delivery Protocol", "DDP", "ddp");
2080 proto_register_field_array(proto_ddp, hf_ddp, array_length(hf_ddp));
2081 expert_ddp = expert_register_protocol(proto_ddp);
2082 expert_register_field_array(expert_ddp, ei_ddp, array_length(ei_ddp));
2083
2084 proto_nbp = proto_register_protocol("Name Binding Protocol", "NBP", "nbp");
2085 proto_register_field_array(proto_nbp, hf_nbp, array_length(hf_nbp));
2086
2087 proto_atp = proto_register_protocol("AppleTalk Transaction Protocol packet", "ATP", "atp");
2088 proto_register_field_array(proto_atp, hf_atp, array_length(hf_atp));
2089
2090 proto_asp = proto_register_protocol("AppleTalk Session Protocol", "ASP", "asp");
2091 proto_register_field_array(proto_asp, hf_asp, array_length(hf_asp));
2092
2093 proto_pap = proto_register_protocol("Printer Access Protocol", "PrAP", "prap");
2094 proto_register_field_array(proto_pap, hf_pap, array_length(hf_pap));
2095
2096 proto_zip = proto_register_protocol("Zone Information Protocol", "ZIP", "zip");
2097 proto_register_field_array(proto_zip, hf_zip, array_length(hf_zip));
2098
2099 atp_module = prefs_register_protocol(proto_atp, NULL);
2100 prefs_register_bool_preference(atp_module, "desegment",
2101 "Reassemble ATP messages spanning multiple DDP packets",
2102 "Whether the ATP dissector should reassemble messages spanning multiple DDP packets",
2103 &atp_defragment);
2104
2105 proto_rtmp = proto_register_protocol("Routing Table Maintenance Protocol",
2106 "RTMP", "rtmp");
2107 proto_register_field_array(proto_rtmp, hf_rtmp, array_length(hf_rtmp));
2108
2109 proto_register_subtree_array(ett, array_length(ett));
2110
2111 /* subdissector code */
2112 ddp_dissector_table = register_dissector_table("ddp.type", "DDP packet type", proto_ddp,
2113 FT_UINT8, BASE_HEX);
2114
2115 atalk_address_type = address_type_dissector_register("AT_ATALK", "Appletalk DDP", atalk_to_str, atalk_str_len, NULL, atalk_col_filter_str, atalk_len, NULL, NULL);
2116 }
2117
2118 void
proto_reg_handoff_atalk(void)2119 proto_reg_handoff_atalk(void)
2120 {
2121 dissector_handle_t nbp_handle, rtmp_request_handle;
2122 dissector_handle_t atp_handle;
2123 dissector_handle_t zip_ddp_handle;
2124 dissector_handle_t rtmp_data_handle, llap_handle;
2125 capture_dissector_handle_t llap_cap_handle;
2126
2127 ddp_short_handle = create_dissector_handle(dissect_ddp_short, proto_ddp);
2128 ddp_handle = create_dissector_handle(dissect_ddp, proto_ddp);
2129 dissector_add_uint("llc.apple_atalk_pid", APPLE_PID_ATALK, ddp_handle);
2130 dissector_add_uint("chdlc.protocol", ETHERTYPE_ATALK, ddp_handle);
2131 dissector_add_uint("ppp.protocol", PPP_AT, ddp_handle);
2132 dissector_add_uint("null.type", BSD_AF_APPLETALK, ddp_handle);
2133 dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_APPLETALK, ddp_handle);
2134
2135 nbp_handle = create_dissector_handle(dissect_nbp, proto_nbp);
2136 dissector_add_uint("ddp.type", DDP_NBP, nbp_handle);
2137 dissector_add_for_decode_as_with_preference("udp.port", nbp_handle);
2138
2139 atp_handle = create_dissector_handle(dissect_atp, proto_atp);
2140 dissector_add_uint("ddp.type", DDP_ATP, atp_handle);
2141
2142 asp_handle = create_dissector_handle(dissect_asp, proto_asp);
2143 pap_handle = create_dissector_handle(dissect_pap, proto_pap);
2144
2145 rtmp_request_handle = create_dissector_handle(dissect_rtmp_request, proto_rtmp);
2146 rtmp_data_handle = create_dissector_handle(dissect_rtmp_data, proto_rtmp);
2147 dissector_add_uint("ddp.type", DDP_RTMPREQ, rtmp_request_handle);
2148 dissector_add_uint("ddp.type", DDP_RTMPDATA, rtmp_data_handle);
2149
2150 zip_ddp_handle = create_dissector_handle(dissect_ddp_zip, proto_zip);
2151 dissector_add_uint("ddp.type", DDP_ZIP, zip_ddp_handle);
2152
2153 zip_atp_handle = create_dissector_handle(dissect_atp_zip, proto_zip);
2154
2155 llap_handle = create_dissector_handle(dissect_llap, proto_llap);
2156 dissector_add_uint("wtap_encap", WTAP_ENCAP_LOCALTALK, llap_handle);
2157 /*
2158 * This is for Ethernet packets with an Ethertype of ETHERTYPE_ATALK
2159 * and LLC/SNAP packets with an OUI of 00:00:00 and a PID of
2160 * ETHERTYPE_ATALK; those appear to be gatewayed LLAP packets,
2161 * complete with an LLAP header.
2162 */
2163 dissector_add_uint("ethertype", ETHERTYPE_ATALK, llap_handle);
2164 llap_cap_handle = create_capture_dissector_handle(capture_llap, proto_llap);
2165 capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_LOCALTALK, llap_cap_handle);
2166
2167 reassembly_table_register(&atp_reassembly_table,
2168 &addresses_reassembly_table_functions);
2169
2170 atp_request_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), asp_hash, asp_equal);
2171 asp_request_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), asp_hash, asp_equal);
2172
2173 afp_handle = find_dissector_add_dependency("afp", proto_asp);
2174 afp_server_status_handle = find_dissector_add_dependency("afp_server_status", proto_asp);
2175 }
2176
2177 /*
2178 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2179 *
2180 * Local variables:
2181 * c-basic-offset: 2
2182 * tab-width: 8
2183 * indent-tabs-mode: nil
2184 * End:
2185 *
2186 * vi: set shiftwidth=2 tabstop=8 expandtab:
2187 * :indentSize=4:tabSize=8:noTabs=true:
2188 */
2189