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