2 * Routines for AppleTalk packet disassembly: LLAP, DDP, NBP, ATP, ASP,
5 * $Id: packet-atalk.c,v 1.76 2002/06/25 02:56:59 tpot Exp $
7 * Simon Wilkinson <sxw@dcs.ed.ac.uk>
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
41 #include <epan/packet.h>
47 #include <epan/atalk-utils.h>
48 #include <epan/conversation.h>
51 #include "reassemble.h"
53 #include "packet-afp.h"
55 /* Tables for reassembly of fragments. */
56 static GHashTable *atp_fragment_table = NULL;
57 static GHashTable *atp_reassembled_table = NULL;
59 /* desegmentation of ATP */
60 static gboolean atp_defragment = TRUE;
62 static dissector_handle_t afp_handle;
64 static int proto_llap = -1;
65 static int hf_llap_dst = -1;
66 static int hf_llap_src = -1;
67 static int hf_llap_type = -1;
69 static int proto_ddp = -1;
70 static int hf_ddp_hopcount = -1;
71 static int hf_ddp_len = -1;
72 static int hf_ddp_checksum = -1;
73 static int hf_ddp_dst_net = -1;
74 static int hf_ddp_src_net = -1;
75 static int hf_ddp_dst_node = -1;
76 static int hf_ddp_src_node = -1;
77 static int hf_ddp_dst_socket = -1;
78 static int hf_ddp_src_socket = -1;
79 static int hf_ddp_type = -1;
82 /* --------------------------------------
83 * ATP protocol parameters
84 * from netatalk/include/atalk/atp.h
86 #define ATP_MAXDATA (578+4) /* maximum ATP data size */
87 #define ATP_BUFSIZ 587 /* maximum packet size */
88 #define ATP_HDRSIZE 5 /* includes DDP type field */
90 #define ATP_TRELMASK 0x07 /* mask all but TREL */
91 #define ATP_RELTIME 30 /* base release timer (in secs) */
93 #define ATP_TREL30 0x0 /* release time codes */
94 #define ATP_TREL1M 0x1 /* these are passed in flags of */
95 #define ATP_TREL2M 0x2 /* atp_sreq call, and set in the */
96 #define ATP_TREL4M 0x3 /* packet control info. */
97 #define ATP_TREL8M 0x4
99 /* flags for ATP options (and control byte)
101 #define ATP_XO 0x20 /* (1<<5) eXactly Once mode */
102 #define ATP_EOM 0x10 /* (1<<4) End Of Message */
103 #define ATP_STS 0x08 /* (1<<3) Transaction Status */
107 #define ATP_FUNCMASK (3<<6) /* mask all but function */
109 #define ATP_TREQ 1 /* (1<<6) Trans. REQuest */
110 #define ATP_TRESP 2 /* (2<<6) Trans. RESPonse */
111 #define ATP_TREL 3 /* (3<<6) Trans. RELease */
113 /* ------------------------- */
114 static dissector_handle_t asp_handle;
116 static int proto_atp = -1;
117 static int hf_atp_ctrlinfo = -1; /* u_int8_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 */
124 static int hf_atp_bitmap = -1; /* u_int8_t bitmap or sequence number */
125 static int hf_atp_tid = -1; /* u_int16_t transaction id. */
126 static int hf_atp_user_bytes = -1;
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;
136 /* --------------------------------
137 * from netatalk/include/atalk/ats.h
140 #define ASPFUNC_CLOSE 1
141 #define ASPFUNC_CMD 2
142 #define ASPFUNC_STAT 3
143 #define ASPFUNC_OPEN 4
144 #define ASPFUNC_TICKLE 5
145 #define ASPFUNC_WRITE 6
146 #define ASPFUNC_WRTCONT 7
147 #define ASPFUNC_ATTN 8
150 #define ASPERR_OK 0x0000
151 #define ASPERR_BADVERS 0xfbd6
152 #define ASPERR_BUFSMALL 0xfbd5
153 #define ASPERR_NOSESS 0xfbd4
154 #define ASPERR_NOSERV 0xfbd3
155 #define ASPERR_PARM 0xfbd2
156 #define ASPERR_SERVBUSY 0xfbd1
157 #define ASPERR_SESSCLOS 0xfbd0
158 #define ASPERR_SIZERR 0xfbcf
159 #define ASPERR_TOOMANY 0xfbce
160 #define ASPERR_NOACK 0xfbcd
162 static int proto_asp = -1;
163 static int hf_asp_func = -1;
164 static int hf_asp_error = -1;
165 static int hf_asp_socket = -1;
166 static int hf_asp_version = -1;
167 static int hf_asp_session_id = -1;
168 static int hf_asp_zero_value = -1;
169 static int hf_asp_init_error = -1;
170 static int hf_asp_attn_code = -1;
171 static int hf_asp_seq = -1;
172 static int hf_asp_size = -1;
174 /* status stuff same for asp and afp */
175 static int hf_asp_server_name = -1;
176 static int hf_asp_server_type = -1;
177 static int hf_asp_server_vers = -1;
178 static int hf_asp_server_uams = -1;
179 static int hf_asp_server_icon = -1;
180 static int hf_asp_server_directory = -1;
182 static int hf_asp_server_flag = -1;
183 static int hf_asp_server_flag_copyfile = -1;
184 static int hf_asp_server_flag_passwd = -1;
185 static int hf_asp_server_flag_no_save_passwd = -1;
186 static int hf_asp_server_flag_srv_msg = -1;
187 static int hf_asp_server_flag_srv_sig = -1;
188 static int hf_asp_server_flag_tcpip = -1;
189 static int hf_asp_server_flag_notify = -1;
190 static int hf_asp_server_flag_reconnect = -1;
191 static int hf_asp_server_flag_directory = -1;
192 static int hf_asp_server_flag_fast_copy = -1;
193 static int hf_asp_server_signature = -1;
195 static int hf_asp_server_addr_len = -1;
196 static int hf_asp_server_addr_type = -1;
197 static int hf_asp_server_addr_value = -1;
199 static gint ett_asp_status = -1;
200 static gint ett_asp_uams = -1;
201 static gint ett_asp_vers = -1;
202 static gint ett_asp_addr = -1;
203 static gint ett_asp_addr_line = -1;
204 static gint ett_asp_directory = -1;
205 static gint ett_asp_status_server_flag = -1;
207 static guint asp_packet_init_count = 200;
210 guint32 conversation;
216 guint8 value; /* command for asp, bitmap for atp */
219 static GHashTable *asp_request_hash = NULL;
220 static GMemChunk *asp_request_keys = NULL;
221 static GMemChunk *asp_request_vals = NULL;
224 static gint asp_equal (gconstpointer v, gconstpointer v2)
226 asp_request_key *val1 = (asp_request_key*)v;
227 asp_request_key *val2 = (asp_request_key*)v2;
229 if (val1->conversation == val2->conversation &&
230 val1->seq == val2->seq &&
231 !memcmp(val1->src, val2->src, 4)) {
237 static guint asp_hash (gconstpointer v)
239 asp_request_key *asp_key = (asp_request_key*)v;
243 /* ------------------------------------ */
244 static GHashTable *atp_request_hash = NULL;
245 static GMemChunk *atp_request_keys = NULL;
246 static GMemChunk *atp_request_vals = NULL;
249 /* ------------------------------------ */
250 static int proto_nbp = -1;
251 static int hf_nbp_op = -1;
252 static int hf_nbp_info = -1;
253 static int hf_nbp_count = -1;
254 static int hf_nbp_tid = -1;
256 static int hf_nbp_node_net = -1;
257 static int hf_nbp_node_port = -1;
258 static int hf_nbp_node_node = -1;
259 static int hf_nbp_node_enum = -1;
260 static int hf_nbp_node_object = -1;
261 static int hf_nbp_node_type = -1;
262 static int hf_nbp_node_zone = -1;
264 static int proto_rtmp = -1;
265 static int hf_rtmp_net = -1;
266 static int hf_rtmp_node_len = -1;
267 static int hf_rtmp_node = -1;
268 static int hf_rtmp_tuple_net = -1;
269 static int hf_rtmp_tuple_range_start = -1;
270 static int hf_rtmp_tuple_range_end = -1;
271 static int hf_rtmp_tuple_dist = -1;
272 static int hf_rtmp_function = -1;
274 static gint ett_atp = -1;
276 static gint ett_atp_segments = -1;
277 static gint ett_atp_segment = -1;
278 static gint ett_atp_info = -1;
279 static gint ett_asp = -1;
281 static gint ett_nbp = -1;
282 static gint ett_nbp_info = -1;
283 static gint ett_nbp_node = -1;
284 static gint ett_rtmp = -1;
285 static gint ett_rtmp_tuple = -1;
286 static gint ett_ddp = -1;
287 static gint ett_llap = -1;
288 static gint ett_pstring = -1;
290 fragment_items atp_frag_items = {
295 &hf_atp_segment_overlap,
296 &hf_atp_segment_overlap_conflict,
297 &hf_atp_segment_multiple_tails,
298 &hf_atp_segment_too_long_segment,
299 &hf_atp_segment_error,
303 static dissector_table_t ddp_dissector_table;
305 static dissector_handle_t data_handle;
307 #define DDP_SHORT_HEADER_SIZE 5
310 * P = Padding, H = Hops, L = Len
314 * Assumes the argument is in host byte order.
316 #define ddp_hops(x) ( ( x >> 10) & 0x3C )
317 #define ddp_len(x) ( x & 0x03ff )
318 typedef struct _e_ddp {
319 guint16 hops_len; /* combines pad, hops, and len */
320 guint16 sum,dnet,snet;
326 #define DDP_HEADER_SIZE 13
329 static const value_string op_vals[] = {
330 {DDP_RTMPDATA, "AppleTalk Routing Table response or data" },
331 {DDP_NBP, "AppleTalk Name Binding Protocol packet"},
332 {DDP_ATP, "AppleTalk Transaction Protocol packet"},
333 {DDP_AEP, "AppleTalk Echo Protocol packet"},
334 {DDP_RTMPREQ, "AppleTalk Routing Table request"},
335 {DDP_ZIP, "AppleTalk Zone Information Protocol packet"},
336 {DDP_ADSP, "AppleTalk Data Stream Protocol"},
337 {DDP_EIGRP, "Cisco EIGRP for AppleTalk"},
341 static const value_string rtmp_function_vals[] = {
343 {2, "Route Data Request (split horizon processed)"},
344 {3, "Route Data Request (no split horizon processing)"},
348 #define NBP_BROADCAST 1
350 #define NBP_FORWARD 4
353 static const value_string nbp_op_vals[] = {
354 {NBP_BROADCAST, "broadcast request"},
355 {NBP_LOOKUP, "lookup"},
356 {NBP_FORWARD, "forward request"},
357 {NBP_REPLY, "reply"},
361 static const value_string atp_function_vals[] = {
362 {ATP_TREQ ,"REQuest"},
363 {ATP_TRESP ,"RESPonse"},
364 {ATP_TREL ,"RELease"},
368 static const value_string atp_trel_timer_vals[] = {
379 static const value_string asp_func_vals[] = {
380 {ASPFUNC_CLOSE, "CloseSession" },
381 {ASPFUNC_CMD, "Command" },
382 {ASPFUNC_STAT, "GetStatus" },
383 {ASPFUNC_OPEN, "OpenSession" },
384 {ASPFUNC_TICKLE, "Tickle" },
385 {ASPFUNC_WRITE, "Write" },
386 {ASPFUNC_WRTCONT, "Write Cont" },
387 {ASPFUNC_ATTN, "Attention" },
390 const value_string asp_error_vals[] = {
391 {AFP_OK , "success"},
392 {AFPERR_ACCESS , "permission denied" },
393 {AFPERR_AUTHCONT , "logincont" },
394 {AFPERR_BADUAM , "uam doesn't exist" },
395 {AFPERR_BADVERS , "bad afp version number" },
396 {AFPERR_BITMAP , "invalid bitmap" },
397 {AFPERR_CANTMOVE , "can't move file" },
398 {AFPERR_DENYCONF , "file synchronization locks conflict" },
399 {AFPERR_DIRNEMPT , "directory not empty" },
400 {AFPERR_DFULL , "disk full" },
401 {AFPERR_EOF , "end of file" },
402 {AFPERR_BUSY , "FileBusy" },
403 {AFPERR_FLATVOL , "volume doesn't support directories" },
404 {AFPERR_NOITEM , "ItemNotFound" },
405 {AFPERR_LOCK , "LockErr" },
406 {AFPERR_MISC , "misc. err" },
407 {AFPERR_NLOCK , "no more locks" },
408 {AFPERR_NOSRVR , "no response by server at that address" },
409 {AFPERR_EXIST , "object already exists" },
410 {AFPERR_NOOBJ , "object not found" },
411 {AFPERR_PARAM , "parameter error" },
412 {AFPERR_NORANGE , "no range lock" },
413 {AFPERR_RANGEOVR , "range overlap" },
414 {AFPERR_SESSCLOS , "session closed" },
415 {AFPERR_NOTAUTH , "user not authenticated" },
416 {AFPERR_NOOP , "command not supported" },
417 {AFPERR_BADTYPE , "object is the wrong type" },
418 {AFPERR_NFILE , "too many files open" },
419 {AFPERR_SHUTDOWN , "server is going down" },
420 {AFPERR_NORENAME , "can't rename" },
421 {AFPERR_NODIR , "couldn't find directory" },
422 {AFPERR_ITYPE , "wrong icon type" },
423 {AFPERR_VLOCK , "volume locked" },
424 {AFPERR_OLOCK , "object locked" },
425 {AFPERR_CTNSHRD , "share point contains a share point" },
426 {AFPERR_NOID , "file thread not found" },
427 {AFPERR_EXISTID , "file already has an id" },
428 {AFPERR_DIFFVOL , "different volume" },
429 {AFPERR_CATCHNG , "catalog has changed" },
430 {AFPERR_SAMEOBJ , "source file == destination file" },
431 {AFPERR_BADID , "non-existent file id" },
432 {AFPERR_PWDSAME , "same password/can't change password" },
433 {AFPERR_PWDSHORT , "password too short" },
434 {AFPERR_PWDEXPR , "password expired" },
435 {AFPERR_INSHRD , "folder being shared is inside a shared folder." },
436 {AFPERR_INTRASH , "shared folder in trash." },
437 {AFPERR_PWDCHNG , "password needs to be changed" },
438 {AFPERR_PWDPOLCY , "password fails policy check" },
439 {AFPERR_USRLOGIN , "user already logged on" },
443 * XXX - do this with an FT_UINT_STRING?
444 * Unfortunately, you can't extract from an FT_UINT_STRING the string,
445 * which we'd want to do in order to put it into the "Data:" portion.
447 * Are these always in the Mac extended character set?
449 static int dissect_pascal_string(tvbuff_t *tvb, int offset, proto_tree *tree,
454 len = tvb_get_guint8(tvb, offset);
464 * XXX - if we could do this inside the protocol tree
465 * code, we could perhaps avoid allocating and freeing
466 * this string buffer.
468 tmp = g_malloc( len+1 );
469 tvb_memcpy(tvb, tmp, offset, len);
471 item = proto_tree_add_string(tree, hf_index, tvb, offset-1, len+1, tmp);
473 subtree = proto_item_add_subtree(item, ett_pstring);
474 proto_tree_add_text(subtree, tvb, offset-1, 1, "Length: %d", len);
475 proto_tree_add_text(subtree, tvb, offset, len, "Data: %s", tmp);
485 dissect_rtmp_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
486 proto_tree *rtmp_tree;
490 if (check_col(pinfo->cinfo, COL_PROTOCOL))
491 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
492 if (check_col(pinfo->cinfo, COL_INFO))
493 col_clear(pinfo->cinfo, COL_INFO);
495 function = tvb_get_guint8(tvb, 0);
497 if (check_col(pinfo->cinfo, COL_INFO))
498 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
499 val_to_str(function, rtmp_function_vals, "Unknown function (%02x)"));
502 ti = proto_tree_add_item(tree, proto_rtmp, tvb, 0, 1, FALSE);
503 rtmp_tree = proto_item_add_subtree(ti, ett_rtmp);
505 proto_tree_add_uint(rtmp_tree, hf_rtmp_function, tvb, 0, 1, function);
510 dissect_rtmp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
511 proto_tree *rtmp_tree;
515 guint8 nodelen,nodelen_bits;
516 guint16 node; /* might be more than 8 bits */
519 if (check_col(pinfo->cinfo, COL_PROTOCOL))
520 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
521 if (check_col(pinfo->cinfo, COL_INFO))
522 col_clear(pinfo->cinfo, COL_INFO);
524 net = tvb_get_ntohs(tvb, offset);
525 nodelen_bits = tvb_get_guint8(tvb, offset+2);
526 if ( nodelen_bits <= 8 ) {
527 node = tvb_get_guint8(tvb, offset)+1;
530 node = tvb_get_ntohs(tvb, offset);
534 if (check_col(pinfo->cinfo, COL_INFO))
535 col_add_fstr(pinfo->cinfo, COL_INFO, "Net: %u Node Len: %u Node: %u",
536 net, nodelen_bits, node);
539 ti = proto_tree_add_item(tree, proto_rtmp, tvb, offset, -1, FALSE);
540 rtmp_tree = proto_item_add_subtree(ti, ett_rtmp);
542 proto_tree_add_uint(rtmp_tree, hf_rtmp_net, tvb, offset, 2, net);
543 proto_tree_add_uint(rtmp_tree, hf_rtmp_node_len, tvb, offset+2, 1,
545 proto_tree_add_uint(rtmp_tree, hf_rtmp_node, tvb, offset+3, nodelen,
547 offset += 3 + nodelen;
550 while (tvb_offset_exists(tvb, offset)) {
551 proto_tree *tuple_item, *tuple_tree;
554 guint16 tuple_range_end;
556 tuple_net = tvb_get_ntohs(tvb, offset);
557 tuple_dist = tvb_get_guint8(tvb, offset+2);
559 if (tuple_dist & 0x80) {
560 tuple_range_end = tvb_get_ntohs(tvb, offset+3);
561 tuple_item = proto_tree_add_text(rtmp_tree, tvb, offset, 6,
562 "Tuple %d: Range Start: %u Dist: %u Range End: %u",
563 i, tuple_net, tuple_dist&0x7F, tuple_range_end);
565 tuple_item = proto_tree_add_text(rtmp_tree, tvb, offset, 3,
566 "Tuple %d: Net: %u Dist: %u",
567 i, tuple_net, tuple_dist);
569 tuple_tree = proto_item_add_subtree(tuple_item, ett_rtmp_tuple);
571 if (tuple_dist & 0x80) {
572 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_range_start, tvb, offset, 2,
575 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_net, tvb, offset, 2,
578 proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_dist, tvb, offset+2, 1,
581 if (tuple_dist & 0x80) {
583 * Extended network tuple.
585 proto_tree_add_item(tuple_tree, hf_rtmp_tuple_range_end, tvb, offset+3, 2,
597 dissect_nbp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
598 proto_tree *nbp_tree;
599 proto_tree *nbp_info_tree;
600 proto_item *ti, *info_item;
606 if (check_col(pinfo->cinfo, COL_PROTOCOL))
607 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBP");
608 if (check_col(pinfo->cinfo, COL_INFO))
609 col_clear(pinfo->cinfo, COL_INFO);
611 info = tvb_get_guint8(tvb, offset);
615 if (check_col(pinfo->cinfo, COL_INFO))
616 col_add_fstr(pinfo->cinfo, COL_INFO, "Op: %s Count: %u",
617 val_to_str(op, nbp_op_vals, "Unknown (0x%01x)"), count);
620 ti = proto_tree_add_item(tree, proto_nbp, tvb, offset, -1, FALSE);
621 nbp_tree = proto_item_add_subtree(ti, ett_nbp);
623 info_item = proto_tree_add_uint_format(nbp_tree, hf_nbp_info, tvb, offset, 1,
625 "Info: 0x%01X Operation: %s Count: %u", info,
626 val_to_str(op, nbp_op_vals, "Unknown (0x%01X)"),
628 nbp_info_tree = proto_item_add_subtree(info_item, ett_nbp_info);
629 proto_tree_add_uint(nbp_info_tree, hf_nbp_op, tvb, offset, 1, info);
630 proto_tree_add_uint(nbp_info_tree, hf_nbp_count, tvb, offset, 1, info);
631 proto_tree_add_item(nbp_tree, hf_nbp_tid, tvb, offset+1, 1, FALSE);
634 for (i=0; i<count; i++) {
635 proto_tree *node_item,*node_tree;
636 int soffset = offset;
638 node_item = proto_tree_add_text(nbp_tree, tvb, offset, -1,
640 node_tree = proto_item_add_subtree(node_item, ett_nbp_node);
642 proto_tree_add_item(node_tree, hf_nbp_node_net, tvb, offset, 2, FALSE);
644 proto_tree_add_item(node_tree, hf_nbp_node_node, tvb, offset, 1, FALSE);
646 proto_tree_add_item(node_tree, hf_nbp_node_port, tvb, offset, 1, FALSE);
648 proto_tree_add_item(node_tree, hf_nbp_node_enum, tvb, offset, 1, FALSE);
651 offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_object);
652 offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_type);
653 offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_zone);
655 proto_item_set_len(node_item, offset-soffset);
662 /* -----------------------------
663 ATP protocol cf. inside appletalk chap. 9
664 desegmentation from packet-ieee80211.c
667 dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
668 proto_tree *atp_tree = NULL;
670 proto_tree *atp_info_tree;
671 proto_item *info_item;
674 guint8 frag_number = 0;
678 struct aspinfo aspinfo;
679 tvbuff_t *new_tvb = NULL;
680 gboolean save_fragmented;
681 gboolean more_fragment = FALSE;
686 conversation_t *conversation;
687 asp_request_key request_key, *new_request_key;
688 asp_request_val *request_val;
690 if (check_col(pinfo->cinfo, COL_PROTOCOL))
691 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATP");
693 ctrlinfo = tvb_get_guint8(tvb, offset);
694 bitmap = tvb_get_guint8(tvb, offset +1);
695 tid = tvb_get_ntohs(tvb, offset +2);
705 aspinfo.reply = (0x80 == (ctrlinfo & ATP_FUNCMASK))?1:0;
706 aspinfo.release = (0xC0 == (ctrlinfo & ATP_FUNCMASK))?1:0;
709 query = (!aspinfo.reply && !aspinfo.release);
711 conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
712 pinfo->srcport, pinfo->destport, 0);
714 if (conversation == NULL)
716 conversation = conversation_new(&pinfo->src, &pinfo->dst,
717 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
720 request_key.conversation = conversation->index;
721 memcpy(request_key.src, (!aspinfo.reply)?pinfo->src.data:pinfo->dst.data, 4);
722 request_key.seq = aspinfo.seq;
724 request_val = (asp_request_val *) g_hash_table_lookup(atp_request_hash, &request_key);
726 if (!request_val && query ) {
727 new_request_key = g_mem_chunk_alloc(atp_request_keys);
728 *new_request_key = request_key;
730 request_val = g_mem_chunk_alloc(atp_request_vals);
731 request_val->value = nbe;
733 g_hash_table_insert(atp_request_hash, new_request_key,request_val);
737 ATP_EOM is not mandatory. Some implementations don't always set it
738 if the query is only one packet.
740 So it needs to keep the number of packets asked in request.
744 more_fragment = !((ATP_EOM & ctrlinfo) || (request_val && 1 == request_val->value));
745 frag_number = bitmap;
748 if (check_col(pinfo->cinfo, COL_INFO)) {
749 col_clear(pinfo->cinfo, COL_INFO);
750 col_add_fstr(pinfo->cinfo, COL_INFO, "%s transaction %d",
751 val_to_str(op, atp_function_vals, "Unknown (0x%01x)"),tid);
753 col_append_fstr(pinfo->cinfo, COL_INFO, " [fragment]");
757 ti = proto_tree_add_item(tree, proto_atp, tvb, offset, -1, FALSE);
758 atp_tree = proto_item_add_subtree(ti, ett_atp);
759 proto_item_set_len(atp_tree, aspinfo.release?8:ATP_HDRSIZE -1);
761 info_item = proto_tree_add_item(atp_tree, hf_atp_ctrlinfo, tvb, offset, 1, FALSE);
762 atp_info_tree = proto_item_add_subtree(info_item, ett_atp_info);
764 proto_tree_add_item(atp_info_tree, hf_atp_function, tvb, offset, 1, FALSE);
765 proto_tree_add_item(atp_info_tree, hf_atp_xo, tvb, offset, 1, FALSE);
766 proto_tree_add_item(atp_info_tree, hf_atp_eom, tvb, offset, 1, FALSE);
767 proto_tree_add_item(atp_info_tree, hf_atp_sts, tvb, offset, 1, FALSE);
768 if ((ctrlinfo & (ATP_FUNCMASK|ATP_XO)) == (0x40|ATP_XO)) {
769 /* TReq with XO set */
770 proto_tree_add_item(atp_info_tree, hf_atp_treltimer, tvb, offset, 1, FALSE);
773 proto_tree_add_text(atp_tree, tvb, offset +1, 1,
774 "Bitmap: 0x%02x %d packet(s) max", bitmap, nbe);
777 proto_tree_add_item(atp_tree, hf_atp_bitmap, tvb, offset +1, 1, FALSE);
779 proto_tree_add_item(atp_tree, hf_atp_tid, tvb, offset +2, 2, FALSE);
782 proto_tree_add_item(atp_tree, hf_atp_user_bytes, tvb, offset +4, 4, FALSE);
789 save_fragmented = pinfo->fragmented;
792 asp doesn't fit very well here
793 move asp back in atp?
795 if (atp_defragment && aspinfo.reply && (more_fragment || frag_number != 0)) {
796 fragment_data *fd_head;
799 hdr = ATP_HDRSIZE -1;
800 if (frag_number != 0)
801 hdr += 4; /* asp header */
802 len = tvb_length_remaining(tvb, hdr);
803 fd_head = fragment_add_seq_check(tvb, hdr, pinfo, tid,
805 atp_reassembled_table,
809 if (fd_head != NULL) {
810 if (fd_head->next != NULL) {
811 new_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
812 tvb_set_child_real_data_tvbuff(tvb, new_tvb);
813 add_new_data_source(pinfo, new_tvb, "Reassembled ATP");
814 /* Show all fragments. */
816 show_fragment_seq_tree(fd_head, &atp_frag_items,
817 atp_tree, pinfo, new_tvb);
821 new_tvb = tvb_new_subset(tvb, ATP_HDRSIZE -1, -1, -1);
829 new_tvb = tvb_new_subset(tvb, ATP_HDRSIZE -1, -1,- 1);
833 pinfo->private_data = &aspinfo;
834 call_dissector(asp_handle, new_tvb, pinfo, tree);
837 /* Just show this as a fragment. */
838 new_tvb = tvb_new_subset (tvb, ATP_HDRSIZE -1, -1, -1);
839 call_dissector(data_handle, new_tvb, pinfo, tree);
841 pinfo->fragmented = save_fragmented;
846 copy and past from dsi
849 dissect_asp_reply_get_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
851 proto_tree *sub_tree;
856 guint16 sign_ofs = 0;
866 ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status");
867 tree = proto_item_add_subtree(ti, ett_asp_status);
869 ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
870 proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %d", ofs);
872 ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
873 proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %d", ofs);
875 ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
876 proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %d", ofs);
878 ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
879 proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %d", ofs);
881 ofs = offset +AFPSTATUS_FLAGOFF;
882 ti = proto_tree_add_item(tree, hf_asp_server_flag, tvb, ofs, 2, FALSE);
883 sub_tree = proto_item_add_subtree(ti, ett_asp_status_server_flag);
884 proto_tree_add_item(sub_tree, hf_asp_server_flag_copyfile , tvb, ofs, 2, FALSE);
885 proto_tree_add_item(sub_tree, hf_asp_server_flag_passwd , tvb, ofs, 2, FALSE);
886 proto_tree_add_item(sub_tree, hf_asp_server_flag_no_save_passwd, tvb, ofs, 2, FALSE);
887 proto_tree_add_item(sub_tree, hf_asp_server_flag_srv_msg , tvb, ofs, 2, FALSE);
888 proto_tree_add_item(sub_tree, hf_asp_server_flag_srv_sig , tvb, ofs, 2, FALSE);
889 proto_tree_add_item(sub_tree, hf_asp_server_flag_tcpip , tvb, ofs, 2, FALSE);
890 proto_tree_add_item(sub_tree, hf_asp_server_flag_notify , tvb, ofs, 2, FALSE);
891 proto_tree_add_item(sub_tree, hf_asp_server_flag_reconnect , tvb, ofs, 2, FALSE);
892 proto_tree_add_item(sub_tree, hf_asp_server_flag_directory , tvb, ofs, 2, FALSE);
893 proto_tree_add_item(sub_tree, hf_asp_server_flag_fast_copy , tvb, ofs, 2, FALSE);
895 proto_tree_add_item(tree, hf_asp_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, FALSE);
897 flag = tvb_get_ntohs(tvb, ofs);
898 if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
899 ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN);
903 sign_ofs = tvb_get_ntohs(tvb, ofs);
904 proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %d", sign_ofs);
907 if ((flag & AFPSRVRINFO_TCPIP)) {
909 adr_ofs = tvb_get_ntohs(tvb, ofs);
910 proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs);
914 if ((flag & AFPSRVRINFO_SRVDIRECTORY)) {
916 dir_ofs = tvb_get_ntohs(tvb, ofs);
917 proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs);
922 ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
924 proto_tree_add_item(tree, hf_asp_server_type, tvb, ofs, 1, FALSE);
926 ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
928 nbe = tvb_get_guint8(tvb, ofs);
929 ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %d", nbe);
931 sub_tree = proto_item_add_subtree(ti, ett_asp_vers);
932 for (i = 0; i < nbe; i++) {
933 len = tvb_get_guint8(tvb, ofs) +1;
934 proto_tree_add_item(sub_tree, hf_asp_server_vers, tvb, ofs, 1, FALSE);
939 ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
941 nbe = tvb_get_guint8(tvb, ofs);
942 ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %d", nbe);
944 sub_tree = proto_item_add_subtree(ti, ett_asp_uams);
945 for (i = 0; i < nbe; i++) {
946 len = tvb_get_guint8(tvb, ofs) +1;
947 proto_tree_add_item(sub_tree, hf_asp_server_uams, tvb, ofs, 1, FALSE);
952 ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
954 proto_tree_add_item(tree, hf_asp_server_icon, tvb, ofs, 256, FALSE);
957 proto_tree_add_item(tree, hf_asp_server_signature, tvb, sign_ofs, 16, FALSE);
961 proto_tree *adr_tree;
969 nbe = tvb_get_guint8(tvb, ofs);
970 ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %d", nbe);
972 adr_tree = proto_item_add_subtree(ti, ett_asp_addr);
973 for (i = 0; i < nbe; i++) {
976 len = tvb_get_guint8(tvb, ofs);
977 type = tvb_get_guint8(tvb, ofs +1);
980 ip = tvb_get_ptr(tvb, ofs+2, 4);
981 ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s", ip_to_str(ip));
983 case 2: /* IP + port */
984 ip = tvb_get_ptr(tvb, ofs+2, 4);
985 port = tvb_get_ntohs(tvb, ofs+6);
986 ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s:%d",ip_to_str(ip),port);
988 case 3: /* DDP, atalk_addr_to_str want host order not network */
989 net = tvb_get_ntohs(tvb, ofs+2);
990 node = tvb_get_guint8(tvb, ofs +4);
991 port = tvb_get_guint8(tvb, ofs +5);
992 ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ddp %u.%u:%u",
997 tmp = g_malloc( len -1);
998 tvb_memcpy(tvb, tmp, ofs +2, len -2);
1000 ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "dns %s", tmp);
1004 /* else fall to default malformed record */
1006 ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Unknow type : %d", type);
1010 sub_tree = proto_item_add_subtree(ti,ett_asp_addr_line);
1011 proto_tree_add_item(sub_tree, hf_asp_server_addr_len, tvb, ofs, 1, FALSE);
1013 proto_tree_add_item(sub_tree, hf_asp_server_addr_type, tvb, ofs, 1, FALSE);
1015 proto_tree_add_item(sub_tree, hf_asp_server_addr_value,tvb, ofs, len, FALSE);
1022 nbe = tvb_get_guint8(tvb, ofs);
1023 ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe);
1025 sub_tree = proto_item_add_subtree(ti, ett_asp_directory);
1026 for (i = 0; i < nbe; i++) {
1027 len = tvb_get_guint8(tvb, ofs) +1;
1028 proto_tree_add_item(sub_tree, hf_asp_server_directory, tvb, ofs, 1, FALSE);
1036 /* -----------------------------
1037 ASP protocol cf. inside appletalk chap. 11
1040 dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1042 struct aspinfo *aspinfo = pinfo->private_data;
1044 proto_tree *asp_tree = NULL;
1048 conversation_t *conversation;
1049 asp_request_key request_key, *new_request_key;
1050 asp_request_val *request_val;
1052 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1053 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASP");
1054 if (check_col(pinfo->cinfo, COL_INFO))
1055 col_clear(pinfo->cinfo, COL_INFO);
1057 conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
1058 pinfo->srcport, pinfo->destport, 0);
1060 if (conversation == NULL)
1062 conversation = conversation_new(&pinfo->src, &pinfo->dst,
1063 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1066 request_key.conversation = conversation->index;
1067 memcpy(request_key.src, (!aspinfo->reply)?pinfo->src.data:pinfo->dst.data, 4);
1068 request_key.seq = aspinfo->seq;
1070 request_val = (asp_request_val *) g_hash_table_lookup(
1071 asp_request_hash, &request_key);
1073 if (!request_val && !aspinfo->reply ) {
1074 fn = tvb_get_guint8(tvb, offset);
1075 new_request_key = g_mem_chunk_alloc(asp_request_keys);
1076 *new_request_key = request_key;
1078 request_val = g_mem_chunk_alloc(asp_request_vals);
1079 request_val->value = fn;
1081 g_hash_table_insert(asp_request_hash, new_request_key,
1089 fn = request_val->value;
1090 aspinfo->command = fn;
1092 if (check_col(pinfo->cinfo, COL_INFO)) {
1094 col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %d",aspinfo->seq);
1096 col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s tid %d",
1097 val_to_str(fn, asp_func_vals, "Unknown (0x%01x)"), aspinfo->seq);
1101 ti = proto_tree_add_item(tree, proto_asp, tvb, offset, -1, FALSE);
1102 asp_tree = proto_item_add_subtree(ti, ett_asp);
1104 if (!aspinfo->reply) {
1106 /* let the called deal with asp_tree == NULL */
1108 proto_tree_add_item(asp_tree, hf_asp_func, tvb, offset, 1, FALSE);
1112 proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, FALSE);
1114 proto_tree_add_item(asp_tree, hf_asp_version, tvb, offset, 2, FALSE);
1117 case ASPFUNC_TICKLE:
1119 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
1121 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
1125 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
1127 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
1131 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
1133 proto_tree_add_item(asp_tree, hf_asp_attn_code, tvb, offset, 2, FALSE);
1138 proto_item_set_len(asp_tree, 4);
1139 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
1141 proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, FALSE);
1143 len = tvb_reported_length_remaining(tvb,offset);
1144 new_tvb = tvb_new_subset(tvb, offset,-1,len);
1145 call_dissector(afp_handle, new_tvb, pinfo, tree);
1147 case ASPFUNC_WRTCONT:
1148 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
1150 proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, FALSE);
1152 proto_tree_add_item(asp_tree, hf_asp_size, tvb, offset, 2, FALSE);
1156 proto_item_set_len(asp_tree, 4);
1158 len = tvb_reported_length_remaining(tvb,offset);
1159 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree);
1166 proto_tree_add_uint(asp_tree, hf_asp_func, tvb, 0, 0, fn);
1169 proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, FALSE);
1171 proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
1173 proto_tree_add_item(asp_tree, hf_asp_init_error, tvb, offset, 2, FALSE);
1177 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
1179 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
1181 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
1185 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, FALSE);
1187 dissect_asp_reply_get_status(tvb, pinfo, asp_tree, offset);
1191 proto_item_set_len(asp_tree, 4);
1192 aspinfo->code = tvb_get_ntohl(tvb, offset);;
1193 proto_tree_add_item(asp_tree, hf_asp_error, tvb, offset, 4, FALSE);
1195 len = tvb_reported_length_remaining(tvb,offset);
1196 new_tvb = tvb_new_subset(tvb, offset,-1,len);
1197 call_dissector(afp_handle, new_tvb, pinfo, tree);
1199 case ASPFUNC_TICKLE:
1200 case ASPFUNC_WRTCONT:
1201 proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, FALSE);
1203 case ASPFUNC_ATTN: /* FIXME capture and spec disagree */
1205 proto_item_set_len(asp_tree, 4);
1207 len = tvb_reported_length_remaining(tvb,offset);
1208 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree);
1216 dissect_ddp_short(tvbuff_t *tvb, packet_info *pinfo, guint8 dnode,
1217 guint8 snode, proto_tree *tree)
1223 proto_tree *ddp_tree = NULL;
1225 static struct atalk_ddp_addr src, dst;
1228 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1229 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP");
1230 if (check_col(pinfo->cinfo, COL_INFO))
1231 col_clear(pinfo->cinfo, COL_INFO);
1234 ti = proto_tree_add_item(tree, proto_ddp, tvb, 0, DDP_SHORT_HEADER_SIZE,
1236 ddp_tree = proto_item_add_subtree(ti, ett_ddp);
1238 len = tvb_get_ntohs(tvb, 0);
1240 proto_tree_add_uint(ddp_tree, hf_ddp_len, tvb, 0, 2, len);
1241 dport = tvb_get_guint8(tvb, 2);
1243 proto_tree_add_uint(ddp_tree, hf_ddp_dst_socket, tvb, 2, 1, dport);
1244 sport = tvb_get_guint8(tvb, 3);
1246 proto_tree_add_uint(ddp_tree, hf_ddp_src_socket, tvb, 3, 1, sport);
1247 type = tvb_get_guint8(tvb, 4);
1255 SET_ADDRESS(&pinfo->net_src, AT_ATALK, sizeof src, (guint8 *)&src);
1256 SET_ADDRESS(&pinfo->src, AT_ATALK, sizeof src, (guint8 *)&src);
1257 SET_ADDRESS(&pinfo->net_dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
1258 SET_ADDRESS(&pinfo->dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
1260 if (check_col(pinfo->cinfo, COL_INFO)) {
1261 col_add_str(pinfo->cinfo, COL_INFO,
1262 val_to_str(type, op_vals, "Unknown DDP protocol (%02x)"));
1265 proto_tree_add_uint(ddp_tree, hf_ddp_type, tvb, 4, 1, type);
1267 new_tvb = tvb_new_subset(tvb, DDP_SHORT_HEADER_SIZE, -1, -1);
1269 if (!dissector_try_port(ddp_dissector_table, type, new_tvb, pinfo, tree))
1270 call_dissector(data_handle,new_tvb, pinfo, tree);
1274 dissect_ddp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1277 proto_tree *ddp_tree;
1279 static struct atalk_ddp_addr src, dst;
1282 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1283 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP");
1284 if (check_col(pinfo->cinfo, COL_INFO))
1285 col_clear(pinfo->cinfo, COL_INFO);
1287 tvb_memcpy(tvb, (guint8 *)&ddp, 0, sizeof(e_ddp));
1288 ddp.dnet=ntohs(ddp.dnet);
1289 ddp.snet=ntohs(ddp.snet);
1290 ddp.sum=ntohs(ddp.sum);
1291 ddp.hops_len=ntohs(ddp.hops_len);
1294 src.node = ddp.snode;
1295 src.port = ddp.sport;
1297 dst.node = ddp.dnode;
1298 dst.port = ddp.dport;
1299 SET_ADDRESS(&pinfo->net_src, AT_ATALK, sizeof src, (guint8 *)&src);
1300 SET_ADDRESS(&pinfo->src, AT_ATALK, sizeof src, (guint8 *)&src);
1301 SET_ADDRESS(&pinfo->net_dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
1302 SET_ADDRESS(&pinfo->dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
1304 if (check_col(pinfo->cinfo, COL_INFO))
1305 col_add_str(pinfo->cinfo, COL_INFO,
1306 val_to_str(ddp.type, op_vals, "Unknown DDP protocol (%02x)"));
1309 ti = proto_tree_add_item(tree, proto_ddp, tvb, 0, DDP_HEADER_SIZE,
1311 ddp_tree = proto_item_add_subtree(ti, ett_ddp);
1312 proto_tree_add_uint(ddp_tree, hf_ddp_hopcount, tvb, 0, 1,
1313 ddp_hops(ddp.hops_len));
1314 proto_tree_add_uint(ddp_tree, hf_ddp_len, tvb, 0, 2,
1315 ddp_len(ddp.hops_len));
1316 proto_tree_add_uint(ddp_tree, hf_ddp_checksum, tvb, 2, 2,
1318 proto_tree_add_uint(ddp_tree, hf_ddp_dst_net, tvb, 4, 2,
1320 proto_tree_add_uint(ddp_tree, hf_ddp_src_net, tvb, 6, 2,
1322 proto_tree_add_uint(ddp_tree, hf_ddp_dst_node, tvb, 8, 1,
1324 proto_tree_add_uint(ddp_tree, hf_ddp_src_node, tvb, 9, 1,
1326 proto_tree_add_uint(ddp_tree, hf_ddp_dst_socket, tvb, 10, 1,
1328 proto_tree_add_uint(ddp_tree, hf_ddp_src_socket, tvb, 11, 1,
1330 proto_tree_add_uint(ddp_tree, hf_ddp_type, tvb, 12, 1,
1334 new_tvb = tvb_new_subset(tvb, DDP_HEADER_SIZE, -1, -1);
1336 if (!dissector_try_port(ddp_dissector_table, ddp.type, new_tvb, pinfo, tree))
1337 call_dissector(data_handle,new_tvb, pinfo, tree);
1340 static const value_string llap_type_vals[] = {
1341 {0x01, "Short DDP"},
1344 {0x82, "Acknowledgement"},
1351 capture_llap(packet_counts *ld)
1357 dissect_llap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1362 proto_tree *llap_tree = NULL;
1366 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1367 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLAP");
1368 if (check_col(pinfo->cinfo, COL_INFO))
1369 col_clear(pinfo->cinfo, COL_INFO);
1372 ti = proto_tree_add_item(tree, proto_llap, tvb, 0, 3, FALSE);
1373 llap_tree = proto_item_add_subtree(ti, ett_llap);
1376 dnode = tvb_get_guint8(tvb, 0);
1378 proto_tree_add_uint(llap_tree, hf_llap_dst, tvb, 0, 1, dnode);
1379 snode = tvb_get_guint8(tvb, 1);
1381 proto_tree_add_uint(llap_tree, hf_llap_src, tvb, 1, 1, snode);
1382 type = tvb_get_guint8(tvb, 2);
1383 if (check_col(pinfo->cinfo, COL_INFO)) {
1384 col_add_str(pinfo->cinfo, COL_INFO,
1385 val_to_str(type, llap_type_vals, "Unknown LLAP type (%02x)"));
1388 proto_tree_add_uint(llap_tree, hf_llap_type, tvb, 2, 1, type);
1390 new_tvb = tvb_new_subset(tvb, 3, -1, -1);
1392 if (proto_is_protocol_enabled(proto_ddp)) {
1393 pinfo->current_proto = "DDP";
1397 dissect_ddp_short(new_tvb, pinfo, dnode, snode, tree);
1401 dissect_ddp(new_tvb, pinfo, tree);
1405 call_dissector(data_handle,new_tvb, pinfo, tree);
1412 fragment_table_init(&atp_fragment_table);
1413 reassembled_table_init(&atp_reassembled_table);
1415 if (atp_request_hash)
1416 g_hash_table_destroy(atp_request_hash);
1417 if (atp_request_keys)
1418 g_mem_chunk_destroy(atp_request_keys);
1419 if (atp_request_vals)
1420 g_mem_chunk_destroy(atp_request_vals);
1422 atp_request_hash = g_hash_table_new(asp_hash, asp_equal);
1424 atp_request_keys = g_mem_chunk_new("atp_request_keys",
1425 sizeof(asp_request_key),
1426 asp_packet_init_count * sizeof(asp_request_key),
1428 atp_request_vals = g_mem_chunk_new("atp_request_vals",
1429 sizeof(asp_request_val),
1430 asp_packet_init_count * sizeof(asp_request_val),
1438 if (asp_request_hash)
1439 g_hash_table_destroy(asp_request_hash);
1440 if (asp_request_keys)
1441 g_mem_chunk_destroy(asp_request_keys);
1442 if (asp_request_vals)
1443 g_mem_chunk_destroy(asp_request_vals);
1445 asp_request_hash = g_hash_table_new(asp_hash, asp_equal);
1447 asp_request_keys = g_mem_chunk_new("asp_request_keys",
1448 sizeof(asp_request_key),
1449 asp_packet_init_count * sizeof(asp_request_key),
1451 asp_request_vals = g_mem_chunk_new("asp_request_vals",
1452 sizeof(asp_request_val),
1453 asp_packet_init_count * sizeof(asp_request_val),
1459 proto_register_atalk(void)
1461 static hf_register_info hf_llap[] = {
1463 { "Destination Node", "llap.dst", FT_UINT8, BASE_DEC, NULL, 0x0,
1467 { "Source Node", "llap.src", FT_UINT8, BASE_DEC, NULL, 0x0,
1471 { "Type", "llap.type", FT_UINT8, BASE_HEX, VALS(llap_type_vals), 0x0,
1475 static hf_register_info hf_ddp[] = {
1477 { "Hop count", "ddp.hopcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1481 { "Datagram length", "ddp.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1485 { "Checksum", "ddp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0,
1489 { "Destination Net", "ddp.dst.net", FT_UINT16, BASE_DEC, NULL, 0x0,
1493 { "Source Net", "ddp.src.net", FT_UINT16, BASE_DEC, NULL, 0x0,
1497 { "Destination Node", "ddp.dst.node", FT_UINT8, BASE_DEC, NULL, 0x0,
1501 { "Source Node", "ddp.src.node", FT_UINT8, BASE_DEC, NULL, 0x0,
1504 { &hf_ddp_dst_socket,
1505 { "Destination Socket", "ddp.dst.socket", FT_UINT8, BASE_DEC, NULL, 0x0,
1508 { &hf_ddp_src_socket,
1509 { "Source Socket", "ddp.src.socket", FT_UINT8, BASE_DEC, NULL, 0x0,
1513 { "Protocol type", "ddp.type", FT_UINT8, BASE_DEC, VALS(op_vals), 0x0,
1517 static hf_register_info hf_nbp[] = {
1519 { "Operation", "nbp.op", FT_UINT8, BASE_DEC,
1520 VALS(nbp_op_vals), 0xF0, "Operation", HFILL }},
1522 { "Info", "nbp.info", FT_UINT8, BASE_HEX,
1523 NULL, 0x0, "Info", HFILL }},
1525 { "Count", "nbp.count", FT_UINT8, BASE_DEC,
1526 NULL, 0x0F, "Count", HFILL }},
1528 { "Network", "nbp.net", FT_UINT16, BASE_DEC,
1529 NULL, 0x0, "Network", HFILL }},
1530 { &hf_nbp_node_node,
1531 { "Node", "nbp.node", FT_UINT8, BASE_DEC,
1532 NULL, 0x0, "Node", HFILL }},
1533 { &hf_nbp_node_port,
1534 { "Port", "nbp.port", FT_UINT8, BASE_DEC,
1535 NULL, 0x0, "Port", HFILL }},
1536 { &hf_nbp_node_enum,
1537 { "Enumerator", "nbp.enum", FT_UINT8, BASE_DEC,
1538 NULL, 0x0, "Enumerator", HFILL }},
1539 { &hf_nbp_node_object,
1540 { "Object", "nbp.object", FT_STRING, BASE_DEC,
1541 NULL, 0x0, "Object", HFILL }},
1542 { &hf_nbp_node_type,
1543 { "Type", "nbp.type", FT_STRING, BASE_DEC,
1544 NULL, 0x0, "Type", HFILL }},
1545 { &hf_nbp_node_zone,
1546 { "Zone", "nbp.zone", FT_STRING, BASE_DEC,
1547 NULL, 0x0, "Zone", HFILL }},
1549 { "Transaction ID", "nbp.tid", FT_UINT8, BASE_DEC,
1550 NULL, 0x0, "Transaction ID", HFILL }}
1553 static hf_register_info hf_rtmp[] = {
1555 { "Net", "rtmp.net", FT_UINT16, BASE_DEC,
1556 NULL, 0x0, "Net", HFILL }},
1558 { "Node", "nbp.nodeid", FT_UINT8, BASE_DEC,
1559 NULL, 0x0, "Node", HFILL }},
1560 { &hf_rtmp_node_len,
1561 { "Node Length", "nbp.nodeid.length", FT_UINT8, BASE_DEC,
1562 NULL, 0x0, "Node Length", HFILL }},
1563 { &hf_rtmp_tuple_net,
1564 { "Net", "rtmp.tuple.net", FT_UINT16, BASE_DEC,
1565 NULL, 0x0, "Net", HFILL }},
1566 { &hf_rtmp_tuple_range_start,
1567 { "Range Start", "rtmp.tuple.range_start", FT_UINT16, BASE_DEC,
1568 NULL, 0x0, "Range Start", HFILL }},
1569 { &hf_rtmp_tuple_range_end,
1570 { "Range End", "rtmp.tuple.range_end", FT_UINT16, BASE_DEC,
1571 NULL, 0x0, "Range End", HFILL }},
1572 { &hf_rtmp_tuple_dist,
1573 { "Distance", "rtmp.tuple.dist", FT_UINT16, BASE_DEC,
1574 NULL, 0x0, "Distance", HFILL }},
1575 { &hf_rtmp_function,
1576 { "Function", "rtmp.function", FT_UINT8, BASE_DEC,
1577 VALS(rtmp_function_vals), 0x0, "Request Function", HFILL }}
1580 static hf_register_info hf_atp[] = {
1582 { "Control info", "atp.ctrlinfo", FT_UINT8, BASE_HEX,
1583 NULL, 0, "control info", HFILL }},
1586 { "Function", "atp.function", FT_UINT8, BASE_DEC,
1587 VALS(atp_function_vals), ATP_FUNCMASK, "function code", HFILL }},
1591 { "XO", "atp.xo", FT_BOOLEAN, 8,
1592 NULL, ATP_XO, "Exactly-once flag", HFILL }},
1595 { "EOM", "atp.eom", FT_BOOLEAN, 8,
1596 NULL, ATP_EOM, "End-of-message", HFILL }},
1599 { "STS", "atp.sts", FT_BOOLEAN, 8,
1600 NULL, ATP_STS, "Send transaction status", HFILL }},
1602 { &hf_atp_treltimer,
1603 { "TRel timer", "atp.treltimer", FT_UINT8, BASE_DEC,
1604 VALS(atp_trel_timer_vals), 0x07, "TRel timer", HFILL }},
1607 { "Bitmap", "atp.bitmap", FT_UINT8, BASE_HEX,
1608 NULL, 0x0, "Bitmap or sequence number", HFILL }},
1611 { "TID", "atp.tid", FT_UINT16, BASE_DEC,
1612 NULL, 0x0, "Transaction id", HFILL }},
1613 { &hf_atp_user_bytes,
1614 { "User bytes", "atp.user_bytes", FT_UINT32, BASE_HEX,
1615 NULL, 0x0, "User bytes", HFILL }},
1617 { &hf_atp_segment_overlap,
1618 { "Segment overlap", "atp.segment.overlap", FT_BOOLEAN, BASE_NONE,
1619 NULL, 0x0, "Segment overlaps with other segments", HFILL }},
1621 { &hf_atp_segment_overlap_conflict,
1622 { "Conflicting data in seagment overlap", "atp.segment.overlap.conflict",
1623 FT_BOOLEAN, BASE_NONE,
1624 NULL, 0x0, "Overlapping segments contained conflicting data", HFILL }},
1626 { &hf_atp_segment_multiple_tails,
1627 { "Multiple tail segments found", "atp.segment.multipletails",
1628 FT_BOOLEAN, BASE_NONE,
1629 NULL, 0x0, "Several tails were found when desegmenting the packet", HFILL }},
1631 { &hf_atp_segment_too_long_segment,
1632 { "Segment too long", "atp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE,
1633 NULL, 0x0, "Segment contained data past end of packet", HFILL }},
1635 { &hf_atp_segment_error,
1636 {" Desegmentation error", "atp.segment.error", FT_NONE, BASE_NONE,
1637 NULL, 0x0, "Desegmentation error due to illegal segments", HFILL }},
1640 { "ATP Fragment", "atp.fragment", FT_NONE, BASE_NONE,
1641 NULL, 0x0, "ATP Fragment", HFILL }},
1644 { "ATP Fragments", "atp.fragments", FT_NONE, BASE_NONE,
1645 NULL, 0x0, "ATP Fragments", HFILL }},
1648 static hf_register_info hf_asp[] = {
1650 { "asp function", "asp.function", FT_UINT8, BASE_DEC,
1651 VALS(asp_func_vals), 0, "asp function", HFILL }},
1654 { "asp error", "asp.error", FT_INT32, BASE_DEC,
1655 VALS(asp_error_vals), 0, "return error code", HFILL }},
1658 { "Version", "asp.version", FT_UINT16, BASE_HEX,
1659 NULL, 0, "asp version", HFILL }},
1661 { &hf_asp_attn_code,
1662 { "Attn code", "asp.attn_code", FT_UINT16, BASE_HEX,
1663 NULL, 0, "asp attention code", HFILL }},
1665 { &hf_asp_init_error,
1666 { "Error", "asp.init_error", FT_UINT16, BASE_DEC,
1667 NULL, 0, "asp init error", HFILL }},
1669 { &hf_asp_session_id,
1670 { "Session ID", "asp.session_id", FT_UINT8, BASE_DEC,
1671 NULL, 0, "asp session id", HFILL }},
1674 { "Socket", "asp.socket", FT_UINT8, BASE_DEC,
1675 NULL, 0, "asp socket", HFILL }},
1678 { "Sequence", "asp.seq", FT_UINT16, BASE_DEC,
1679 NULL, 0, "asp sequence number", HFILL }},
1682 { "size", "asp.size", FT_UINT16, BASE_DEC,
1683 NULL, 0, "asp available size for reply", HFILL }},
1685 { &hf_asp_zero_value,
1686 { "Pad (0)", "asp.zero_value",
1687 FT_BYTES, BASE_HEX, NULL, 0x0,
1691 { &hf_asp_server_name,
1692 { "Server name", "asp.server_name",
1693 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
1694 "Server name", HFILL }},
1696 { &hf_asp_server_type,
1697 { "Server type", "asp.server_type",
1698 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
1699 "Server type", HFILL }},
1701 { &hf_asp_server_vers,
1702 { "AFP version", "asp.server_vers",
1703 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
1704 "AFP version", HFILL }},
1706 { &hf_asp_server_uams,
1707 { "UAM", "asp.server_uams",
1708 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
1711 { &hf_asp_server_icon,
1712 { "Icon bitmap", "asp.server_icon",
1713 FT_BYTES, BASE_HEX, NULL, 0x0,
1714 "Server icon bitmap", HFILL }},
1716 { &hf_asp_server_directory,
1717 { "Directory service", "asp.server_directory",
1718 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
1719 "Server directory service", HFILL }},
1721 { &hf_asp_server_signature,
1722 { "Server signature", "asp.server_signature",
1723 FT_BYTES, BASE_HEX, NULL, 0x0,
1724 "Server signature", HFILL }},
1726 { &hf_asp_server_flag,
1727 { "Flag", "asp.server_flag",
1728 FT_UINT16, BASE_HEX, NULL, 0x0,
1729 "Server capabilities flag", HFILL }},
1730 { &hf_asp_server_flag_copyfile,
1731 { "Support copyfile", "asp.server_flag.copyfile",
1732 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_COPY,
1733 "Server support copyfile", HFILL }},
1734 { &hf_asp_server_flag_passwd,
1735 { "Support change password", "asp.server_flag.passwd",
1736 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_PASSWD,
1737 "Server support change password", HFILL }},
1738 { &hf_asp_server_flag_no_save_passwd,
1739 { "Don't allow save password", "asp.server_flag.no_save_passwd",
1740 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_NOSAVEPASSWD,
1741 "Don't allow save password", HFILL }},
1742 { &hf_asp_server_flag_srv_msg,
1743 { "Support server message", "asp.server_flag.srv_msg",
1744 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVMSGS,
1745 "Support server message", HFILL }},
1746 { &hf_asp_server_flag_srv_sig,
1747 { "Support server signature", "asp.server_flag.srv_sig",
1748 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVSIGNATURE,
1749 "Support server signature", HFILL }},
1750 { &hf_asp_server_flag_tcpip,
1751 { "Support TCP/IP", "asp.server_flag.tcpip",
1752 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_TCPIP,
1753 "Server support TCP/IP", HFILL }},
1754 { &hf_asp_server_flag_notify,
1755 { "Support server notifications", "asp.server_flag.notify",
1756 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVNOTIFY,
1757 "Server support notifications", HFILL }},
1758 { &hf_asp_server_flag_reconnect,
1759 { "Support server reconnect", "asp.server_flag.reconnect",
1760 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVRECONNECT,
1761 "Server support reconnect", HFILL }},
1762 { &hf_asp_server_flag_directory,
1763 { "Support directory services", "asp.server_flag.directory",
1764 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVDIRECTORY,
1765 "Server support directory services", HFILL }},
1766 { &hf_asp_server_flag_fast_copy,
1767 { "Support fast copy", "asp.server_flag.fast_copy",
1768 FT_BOOLEAN, 16, NULL, AFPSRVRINFO_FASTBOZO,
1769 "Server support fast copy", HFILL }},
1771 { &hf_asp_server_addr_len,
1772 { "Length", "asp.server_addr.len",
1773 FT_UINT8, BASE_DEC, NULL, 0x0,
1774 "Address length.", HFILL }},
1776 { &hf_asp_server_addr_type,
1777 { "Type", "asp.server_addr.type",
1778 FT_UINT8, BASE_DEC, VALS(afp_server_addr_type_vals), 0x0,
1779 "Address type.", HFILL }},
1781 { &hf_asp_server_addr_value,
1782 { "Value", "asp.server_addr.value",
1783 FT_BYTES, BASE_HEX, NULL, 0x0,
1784 "Address value", HFILL }},
1788 static gint *ett[] = {
1799 &ett_asp_status_server_flag,
1813 module_t *atp_module;
1815 proto_llap = proto_register_protocol("LocalTalk Link Access Protocol", "LLAP", "llap");
1816 proto_register_field_array(proto_llap, hf_llap, array_length(hf_llap));
1818 proto_ddp = proto_register_protocol("Datagram Delivery Protocol", "DDP", "ddp");
1819 proto_register_field_array(proto_ddp, hf_ddp, array_length(hf_ddp));
1821 proto_nbp = proto_register_protocol("Name Binding Protocol", "NBP", "nbp");
1822 proto_register_field_array(proto_nbp, hf_nbp, array_length(hf_nbp));
1824 proto_atp = proto_register_protocol("AppleTalk Transaction Protocol packet", "ATP", "atp");
1825 proto_register_field_array(proto_atp, hf_atp, array_length(hf_atp));
1827 proto_asp = proto_register_protocol("AppleTalk Session Protocol", "ASP", "asp");
1828 proto_register_field_array(proto_asp, hf_asp, array_length(hf_asp));
1830 atp_module = prefs_register_protocol(proto_atp, NULL);
1831 prefs_register_bool_preference(atp_module, "desegment",
1832 "Desegment all ATP messages spanning multiple DDP packets",
1833 "Whether the ATP dissector should desegment all messages spanning multiple DDP packets",
1836 proto_rtmp = proto_register_protocol("Routing Table Maintenance Protocol",
1838 proto_register_field_array(proto_rtmp, hf_rtmp, array_length(hf_rtmp));
1840 proto_register_subtree_array(ett, array_length(ett));
1842 /* subdissector code */
1843 ddp_dissector_table = register_dissector_table("ddp.type", "DDP packet type",
1844 FT_UINT8, BASE_HEX);
1848 proto_reg_handoff_atalk(void)
1850 dissector_handle_t ddp_handle, nbp_handle, rtmp_request_handle;
1851 dissector_handle_t atp_handle;
1852 dissector_handle_t rtmp_data_handle, llap_handle;
1854 ddp_handle = create_dissector_handle(dissect_ddp, proto_ddp);
1855 dissector_add("ethertype", ETHERTYPE_ATALK, ddp_handle);
1856 dissector_add("chdlctype", ETHERTYPE_ATALK, ddp_handle);
1857 dissector_add("ppp.protocol", PPP_AT, ddp_handle);
1858 dissector_add("null.type", BSD_AF_APPLETALK, ddp_handle);
1860 nbp_handle = create_dissector_handle(dissect_nbp, proto_nbp);
1861 dissector_add("ddp.type", DDP_NBP, nbp_handle);
1863 atp_handle = create_dissector_handle(dissect_atp, proto_atp);
1864 dissector_add("ddp.type", DDP_ATP, atp_handle);
1866 asp_handle = create_dissector_handle(dissect_asp, proto_asp);
1868 rtmp_request_handle = create_dissector_handle(dissect_rtmp_request, proto_rtmp);
1869 rtmp_data_handle = create_dissector_handle(dissect_rtmp_data, proto_rtmp);
1870 dissector_add("ddp.type", DDP_RTMPREQ, rtmp_request_handle);
1871 dissector_add("ddp.type", DDP_RTMPDATA, rtmp_data_handle);
1873 llap_handle = create_dissector_handle(dissect_llap, proto_llap);
1874 dissector_add("wtap_encap", WTAP_ENCAP_LOCALTALK, llap_handle);
1876 register_init_routine( atp_init);
1877 register_init_routine( &asp_reinit);
1879 afp_handle = find_dissector("afp");
1880 data_handle = find_dissector("data");