From Jan Gerbecks via bug 4440:
[obnox/wireshark/wip.git] / epan / dissectors / packet-pnrp.c
1 /* packet-pnrp.h
2  * Routines for Peer Name Resolution Protocol (PNRP) dissection  
3  *
4  *  Copyright 2010, Jan Gerbecks <jan.gerbecks@stud.uni-due.de>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (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 along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 /* The official Dokumentation for the Peer Name Resolution Protocol can be found at
29  http://msdn.microsoft.com/en-us/library/cc239047(PROT.13).aspx
30  This dissector is based on Revision 6.1.2 
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <glib.h>
42
43 #include <epan/packet.h>
44 #include <epan/prefs.h>
45
46 #define PROTONAME "Peer Network Resolution Protocol"
47 #define PROTOSHORTNAME "PNRP"
48 #define PROTOABBREV "pnrp"
49
50 #define PNRP_PORT 3540
51
52 #define FIELDID_LENGTH = 2
53 #define LENGTH_FIELD = 2
54
55 /* Define all FieldIDs here, so we can use them later on in switch statement etc */
56 #define PNRP_HEADER                     0x0010
57 #define PNRP_HEADER_ACKED       0x0018
58 #define PNRP_ID                         0x0030
59 #define TARGET_PNRP_ID          0x0038
60 #define VALIDATE_PNRP_ID        0x0039
61 #define FLAGS_FIELD                     0x0040
62 #define FLOOD_CONTROLS          0x0043
63 #define SOLICIT_CONTROLS        0x0044
64 #define LOOKUP_CONTROLS         0x0045
65 #define EXTENDED_PAYLOAD        0x005A
66 #define PNRP_ID_ARRAY           0x0060
67 #define CERT_CHAIN                      0x0080
68 #define WCHAR                           0x0084
69 #define CLASSIFIER                      0x0085
70 #define HASHED_NONCE            0x0092
71 #define NONCE                           0x0093
72 #define SPLIT_CONTROLS          0x0098
73 #define ROUTING_ENTRY           0x009A
74 #define VALIDATE_CPA            0x009B
75 #define REVOKE_CPA                      0x009C
76 #define IPV6_ENDPOINT           0x009D
77 #define IPV6_ENDPOINT_ARRAY 0x009E
78
79 /* Define all message types */
80 #define SOLICIT                         0x01
81 #define ADVERTISE                       0x02
82 #define REQUEST                         0x03
83 #define FLOOD                           0x04
84 #define INQUIRE                         0x07
85 #define AUTHORITY                       0x08
86 #define ACK                                     0x09
87 #define LOOKUP                          0x0B
88
89 /* Define flags mask fields */
90 #define FLAGS_INQUIRE_RESERVED1 0xFFE0
91 #define FLAGS_INQUIRE_A 0x0010
92 #define FLAGS_INQUIRE_X 0x0008
93 #define FLAGS_INQUIRE_C 0x0004
94 #define FLAGS_INQUIRE_RESERVED2 0x0003
95
96 #define FLAGS_AUTHORITY_RESERVED1 0xFC00
97 #define FLAGS_AUTHORITY_L 0x0200
98 #define FLAGS_AUTHORITY_RESERVED2 0x01F0
99 #define FLAGS_AUTHORITY_B 0x0008
100 #define FLAGS_AUTHORITY_RESERVED3 0x0006
101 #define FLAGS_AUTHORITY_N 0x0001
102
103 #define FLAGS_LOOKUPCONTROLS_RESERVED 0xFFFC
104 #define FLAGS_LOOKUPCONTROLS_A 0x0002
105 #define FLAGS_LOOKUPCONTROLS_0 0x0001
106
107 #define FLAGS_ENCODED_CPA_RESERVED 0xC0
108 #define FLAGS_ENCODED_CPA_X 0x20
109 #define FLAGS_ENCODED_CPA_U 0x02
110 #define FLAGS_ENCODED_CPA_R 0x01
111 #define FLAGS_ENCODED_CPA_A 0x04
112 #define FLAGS_ENCODED_CPA_C 0x08
113 #define FLAGS_ENCODED_CPA_F 0x10
114
115 /* Define all helper methods  */
116 static void dissect_pnrp_ids(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
117 static void dissect_ipv6_address(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
118 static void dissect_route_entry(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
119 static void dissect_ipv6_endpoint_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
120 static void dissect_encodedCPA_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
121 static void dissect_payload_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
122 static void dissect_publicKey_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
123 static void dissect_signature_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree);
124
125 /* Define global variables 
126  ----------------------------*/
127 static int proto_pnrp = -1;
128
129 /* Define FieldIDs */
130 static const value_string fieldID[] = {
131         { PNRP_HEADER, "PNRP_HEADER" },
132         { PNRP_HEADER_ACKED, "PNRP_HEADER_ACKED" },
133         { PNRP_ID, "PNRP_ID" },
134         { TARGET_PNRP_ID, "TARGET_PNRP_ID" },
135         { VALIDATE_PNRP_ID, "VALIDATE_PNRP_ID" },
136         { FLAGS_FIELD, "FLAGS_FIELD" },
137         { FLOOD_CONTROLS, "FLOOD_CONTROLS" },
138         { SOLICIT_CONTROLS, "SOLICIT_CONTROLS" },
139         { LOOKUP_CONTROLS, "LOOKUP_CONTROLS" },
140         { EXTENDED_PAYLOAD, "EXTENDED_PAYLOAD" },
141         { PNRP_ID_ARRAY, "PNRP_ID_ARRAY" },
142         { CERT_CHAIN, "CERT_CHAIN" },
143         { WCHAR, "WCHAR" },
144         { CLASSIFIER, "CLASSIFIER" },
145         { HASHED_NONCE, "HASHED_NONCE" },
146         { NONCE, "NONCE" },
147         { SPLIT_CONTROLS, "SPLIT_CONTROLS" },
148         { ROUTING_ENTRY, "ROUTING_ENTRY" },
149         { VALIDATE_CPA, "VALIDATE_CPA" },
150         { REVOKE_CPA, "REVOKE_CPA" },
151         { IPV6_ENDPOINT, "IPV6_ENDPOINT" },
152         { IPV6_ENDPOINT_ARRAY, "IPV6_ENDPOINT_ARRAY" },
153         {0,                                             NULL}
154 };
155
156 /* Define Packetnames */
157 static const value_string messageType[] = {
158         { SOLICIT, "SOLICIT" },
159         { ADVERTISE, "ADVERTISE" },
160         { REQUEST, "REQUEST" },
161         { FLOOD, "FLOOD" },
162         { INQUIRE, "INQUIRE" },
163         { AUTHORITY, "AUTHORITY" },
164         { ACK, "ACK" },
165         { LOOKUP, "LOOKUP" },
166         {0,                                             NULL}
167 };
168 /* Define Solicit Type */
169 static const value_string solicitType[] = {
170         { 0x00, "SOLICIT_TYPE_ANY" },
171         { 0x01, "SOLICIT_TYPE_LOCAL" },
172         {0,                                             NULL}
173 };
174 /* Define Resolve Criteria for Lookup Controls */
175 static const value_string resolveCriteria[] = {
176         { 0x00, "SEARCH_OPCODE_NONE" },
177         { 0x01, "SEARCH_OPCODE_ANY_PEERNAME" },
178         { 0x02, "SEARCH_OPCODE_NEAREST_PEERNAME" },
179         { 0x04, "SEARCH_OPCODE_NEAREST64_PEERNAME" },
180         { 0x08, "SEARCH_OPCODE_UPPER_BITS" },
181         {0,                                             NULL}
182 };
183 /* Define Reason Code for Lookup Controls */
184 static const value_string reasonCode[] = {
185         { 0x00, "REASON_APP_REQUEST" },
186         { 0x01, "REASON_REGISTRATION" },
187         { 0x02, "REASON_CACHE_MAINTENANCE" },
188         { 0x03, "REASON_SPLIT_DETECTION" },
189         {0,                                             NULL}
190 };
191
192 /* Define IDs for subcomponents */
193 /* Message Header */
194 static gint hf_pnrp_header = -1;
195 static gint hf_pnrp_header_fieldID = -1;
196 static gint hf_pnrp_header_length = -1;
197 static gint hf_pnrp_header_ident = -1;
198 static gint hf_pnrp_header_versionMajor = -1;
199 static gint hf_pnrp_header_versionMinor = -1;
200 static gint hf_pnrp_header_messageType = -1;
201 static gint hf_pnrp_header_messageID = -1;
202 /* Message Body */
203 static gint hf_pnrp_message_type = -1;
204 static gint hf_pnrp_message_length = -1;
205 static gint hf_pnrp_message_headerack = -1;
206 static gint hf_pnrp_message_pnrpID = -1;        /* Generic variable to display pnrp ID in various situations */
207 /* Inquire Message Flags */
208 static gint hf_pnrp_message_inquire_flags = -1;
209 static gint hf_pnrp_message_inquire_flags_reserved1 = -1;
210 static gint hf_pnrp_message_inquire_flags_Abit = -1;
211 static gint hf_pnrp_message_inquire_flags_Xbit = -1;
212 static gint hf_pnrp_message_inquire_flags_Cbit = -1;
213 static gint hf_pnrp_message_inquire_flags_reserved2 = -1;
214
215 static const int *inquire_flags[] = {
216         &hf_pnrp_message_inquire_flags_reserved1,
217         &hf_pnrp_message_inquire_flags_Abit,
218         &hf_pnrp_message_inquire_flags_Xbit,
219         &hf_pnrp_message_inquire_flags_Cbit,
220         &hf_pnrp_message_inquire_flags_reserved2,
221         NULL
222 };
223
224 /* Classifier */
225 static gint hf_pnrp_message_classifier_unicodeCount = -1;
226 static gint hf_pnrp_message_classifier_arrayLength = -1;
227 static gint hf_pnrp_message_classifier_entryLength = -1;
228 /* ACK Message Flags */
229 static gint hf_pnrp_message_ack_flags_reserved = -1;
230 static gint hf_pnrp_message_ack_flags_Nbit = -1;
231 /* SplitControls */
232 static gint hf_pnrp_message_splitControls_authorityBuffer = -1;
233 /* IPv6 Endpoint Array */
234 static gint hf_pnrp_message_ipv6EndpointArray_NumberOfEntries = -1;
235 static gint hf_pnrp_message_ipv6EndpointArray_ArrayLength = -1;
236 static gint hf_pnrp_message_ipv6EndpointArray_EntryLength = -1;
237 /* AUTHORITY Message Flags */
238 static gint hf_pnrp_message_authority_flags = -1;
239 static gint hf_pnrp_message_authority_flags_reserved1 = -1;
240 static gint hf_pnrp_message_authority_flags_Lbit = -1;
241 static gint hf_pnrp_message_authority_flags_reserved2 = -1;
242 static gint hf_pnrp_message_authority_flags_Bbit = -1;
243 static gint hf_pnrp_message_authority_flags_reserved3= -1;
244 static gint hf_pnrp_message_authority_flags_Nbit = -1;
245
246 static const int *authority_flags[] = {
247         &hf_pnrp_message_authority_flags_reserved1,
248         &hf_pnrp_message_authority_flags_Lbit,
249         &hf_pnrp_message_authority_flags_reserved2,
250         &hf_pnrp_message_authority_flags_Bbit,
251         &hf_pnrp_message_authority_flags_reserved3,
252         &hf_pnrp_message_authority_flags_Nbit,
253         NULL
254 };
255
256 /* Flood Control Flags */
257 static gint hf_pnrp_message_flood_flags_reserved1 = -1;
258 static gint hf_pnrp_message_flood_flags_Dbit = -1;
259
260 /* PNRP ID Array */
261 static gint hf_pnrp_message_idArray_NumEntries = -1;
262 static gint hf_pnrp_message_idArray_Length = -1;
263 static gint hf_pnrp_message_ElementFieldType = -1;
264 static gint hf_pnrp_message_idarray_Entrylength = -1;
265
266 static gint hf_pnrp_message_solicitType = -1;
267 static gint hf_pnrp_message_certChain = -1;
268 static gint hf_pnrp_message_nonce = -1;
269 static gint hf_pnrp_message_hashednonce = -1;
270 static gint hf_pnrp_message_ipv6 = -1;
271
272 /* Encoded CPA */
273 static gint hf_pnrp_encodedCPA = -1;
274 static gint hf_pnrp_encodedCPA_length = -1;
275 static gint hf_pnrp_encodedCPA_minorVersion = -1;
276 static gint hf_pnrp_encodedCPA_majorVersion = -1;
277 static gint hf_pnrp_encodedCPA_flags = -1;
278 static gint hf_pnrp_encodedCPA_flags_reserved = -1;
279 static gint hf_pnrp_encodedCPA_flags_Xbit = -1;
280 static gint hf_pnrp_encodedCPA_flags_Fbit = -1;
281 static gint hf_pnrp_encodedCPA_flags_Cbit = -1;
282 static gint hf_pnrp_encodedCPA_flags_Abit = -1;
283 static gint hf_pnrp_encodedCPA_flags_Ubit = -1;
284 static gint hf_pnrp_encodedCPA_flags_Rbit = -1;
285 static const int *encodedCPA_flags[] = {
286         &hf_pnrp_encodedCPA_flags_reserved,
287         &hf_pnrp_encodedCPA_flags_Xbit,
288         &hf_pnrp_encodedCPA_flags_Fbit,
289         &hf_pnrp_encodedCPA_flags_Cbit,
290         &hf_pnrp_encodedCPA_flags_Abit,
291         &hf_pnrp_encodedCPA_flags_Ubit,
292         &hf_pnrp_encodedCPA_flags_Rbit,
293         NULL
294 };
295 static gint hf_pnrp_encodedCPA_notAfter = -1;
296 static gint hf_pnrp_encodedCPA_serviceLocation = -1;
297 static gint hf_pnrp_encodedCPA_binaryAuthority = -1;
298 static gint hf_pnrp_encodedCPA_classifiertHash = -1;
299 static gint hf_pnrp_encodedCPA_friendlyName = -1;
300
301 /* Lookup Controls */
302 static gint hf_pnrp_message_lookupControls_flags = -1;
303 static gint hf_pnrp_message_lookupControls_flags_reserved = -1;
304 static gint hf_pnrp_message_lookupControls_flags_Abit = -1;
305 static gint hf_pnrp_message_lookupControls_flags_0bit = -1;
306 static const int *lookupControls_flags[] = {
307         &hf_pnrp_message_lookupControls_flags_reserved,
308         &hf_pnrp_message_lookupControls_flags_Abit,
309         &hf_pnrp_message_lookupControls_flags_0bit,
310         NULL
311 };
312 static gint hf_pnrp_message_lookupControls_precision =-1;
313 static gint hf_pnrp_message_lookupControls_resolveCriteria =-1;
314 static gint hf_pnrp_message_lookupControls_reasonCode =-1;
315
316 /* Dissect Route Entry */
317 static gint hf_pnrp_message_routeEntry_portNumber = -1;
318 static gint hf_pnrp_message_routeEntry_flags = -1;
319 static gint hf_pnrp_message_routeEntry_addressCount = -1;
320
321 /* Public Key Structure */
322 static gint hf_pnrp_publicKey_objID = -1;
323 static gint hf_pnrp_publicKey_publicKeyData = -1;
324
325 /* Signature Structure */
326 static gint hf_pnrp_signature_signatureData = -1;
327
328 /* Define variables to reference subtrees */
329 static gint ett_pnrp = -1;
330 static gint ett_pnrp_message = -1;
331 static gint ett_pnrp_message_inquire_flags = -1;
332 static gint ett_pnrp_message_authority_flags = -1;
333 static gint ett_pnrp_message_encodedCPA = -1;
334 static gint ett_pnrp_message_encodedCPA_flags = -1;
335 static gint ett_pnrp_message_lookupControls_flags = -1;
336 static gint ett_pnrp_message_payloadStructure = -1;
337 static gint ett_pnrp_message_publicKeyStructure = -1;
338 static gint ett_pnrp_message_signatureStructure = -1;
339
340
341 /* Do actual dissection work */
342 static int dissect_pnrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
343 {
344         /* Variabel declaration */
345         gint offset;
346         gint padding_bytes;
347         guint8 message_type;
348         guint16 field_type;
349         guint16 data_length;
350
351         
352         /*----------------------------------------
353          * Validate if it is really a PNRP Packet
354          *----------------------------------------*/
355         /* Check that there's enough data */
356         data_length = tvb_reported_length(tvb);
357         
358         /* Shortest Message is ACK -> 12 Bytes for Header plus 8 Bytes for Data */
359         if (data_length <  12+8 )
360         {
361                 return 0;
362         }
363         
364         /* Check some values from the packet header */
365         /* First 2 bytes must be 0x0010 */
366         if (tvb_get_ntohs(tvb,0) != PNRP_HEADER )
367         {
368                 return 0;
369         }
370         /* Length of Header must be 0x000C = 12 */
371         if (tvb_get_ntohs(tvb,2) != 0x000C) {
372                 return 0;
373         }
374         /* Identifier must 0x51 */
375         if (tvb_get_guint8(tvb,4) != 0x51) {
376                 return 0;
377         }
378
379         
380         /* Assign Values to Variables */
381         /* Use to track data */
382         offset= 0;
383         padding_bytes = 0;
384         /* Get the message Information beforehand */
385         message_type = tvb_get_guint8(tvb,7);
386         
387         
388         /* Simply Display the Protcol Name in the INFO column */
389         col_set_str(pinfo->cinfo, COL_PROTOCOL, "pnrp"); 
390         /* Clear out stuff in the info column */ 
391         col_clear(pinfo->cinfo,COL_INFO);
392         col_add_fstr(pinfo->cinfo, COL_INFO, "PNRP %s Message ",
393                                  val_to_str(message_type, messageType, "Unknown (0x%02x)"));
394         
395         
396         /* If tree is NULL we are asked for summary, otherwise for details */
397         if(tree){ /* we are beeing asked for details */
398                 proto_item *ti = NULL;
399                 proto_tree *pnrp_tree = NULL;
400                 
401                 proto_item *pnrp_header_item = NULL;
402                 proto_tree *pnrp_header_tree = NULL;
403                 
404                 proto_item *pnrp_message_tree = NULL;
405                 proto_item *pnrp_message_item = NULL;
406                 
407                 
408                 /* Lets add a subtree to our dissection to display the info */
409                 ti = proto_tree_add_item(tree, proto_pnrp, tvb, 0, -1, FALSE);
410                 proto_item_append_text(ti, ", Message Type %s",
411                                                            val_to_str(message_type, messageType, "Unknown (0x%02x)"));
412                 /* Get a main tree for the whole protocol */
413                 pnrp_tree = proto_item_add_subtree(ti, ett_pnrp);
414                 /*-------------------------------
415                  *--Add all Header Fields
416                  *------------------------------*/
417                 /* Get a subtree for the Header */
418                 pnrp_header_tree = proto_item_add_subtree(ti, ett_pnrp);
419                 pnrp_header_item = proto_tree_add_item(pnrp_tree, hf_pnrp_header, tvb, offset,12,FALSE);
420                 pnrp_header_tree = proto_item_add_subtree(pnrp_header_item, ett_pnrp);
421                 
422                 /* Add Field ID should be 0c0010 */
423                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_fieldID,tvb,offset,2,FALSE);
424                 offset += 2;
425                 /* Add Length should be 0x000C */
426                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_length,tvb,offset,2,FALSE);
427                 offset += 2;
428                 /* Add Ident should be 0x51 */
429                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_ident,tvb,offset,1,FALSE);
430                 offset += 1;
431                 /* Add Major Version */
432                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_versionMajor,tvb,offset,1,FALSE);
433                 offset += 1;
434                 /* Add Minor Version */
435                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_versionMinor,tvb,offset,1,FALSE);
436                 offset += 1;
437                 /* Add Message Type */
438                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_messageType,tvb,offset,1,FALSE);
439                 offset += 1;
440                 /* Add Message ID */
441                 proto_tree_add_item(pnrp_header_tree,hf_pnrp_header_messageID,tvb,offset,4,FALSE);
442                 offset += 4;
443                 
444                 
445                 /*-------------------------------
446                  *--Add all Message Fields
447                  *------------------------------*/
448                 
449                 /* The following part has dynamic length depending on message type */
450                 while (tvb_reported_length_remaining(tvb, offset) != 0) {
451                         /* Determine the Field Type */
452                         field_type = tvb_get_ntohs(tvb,offset );
453                         /* Determine length of this message */
454                         data_length = tvb_get_ntohs(tvb,offset + 2);
455                         
456                         /* Length must be at least 4, because field_type and data_length are part of data_length information */
457                         if (data_length < 4) {
458                                 if (tree) {
459                                         pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 4, "Message with invalid length %u (< 4)", data_length);
460                                         pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
461                                         proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset, 2, FALSE);
462                                         proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
463                                 }
464                                 offset += 4;
465                                 /* Don't continue parsing this message segment */
466                                 break;
467                         }
468                         /* Actual Parsing of the message Type */
469                         switch (field_type) {
470                                 /* First Field in ACK Message */
471                                 case PNRP_HEADER_ACKED:
472                                         if (tree) {                                             
473                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
474                                                 data_length, "Message ACK ID: ");
475                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
476                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
477                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
478                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_headerack, tvb, offset + 4, data_length -4, FALSE);
479
480                                         }
481                                         offset += data_length;
482                                         break;
483                                 
484                                         /* A validate pnrp id follows as found in FLOOD */
485                                 case VALIDATE_PNRP_ID:
486                                         if (tree) {
487                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
488                                                                                                                                 data_length, "Validate PNRP ID: ");
489                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
490                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
491                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
492                                                 /* We can have a large number of pnrp IDs here */
493                                                 dissect_pnrp_ids(tvb,offset+4,data_length-4,pnrp_message_tree);
494                                                 
495                                         }
496                                         offset += data_length;
497                                         break;
498                                          
499                                         /* The Flags have different meaning, depending on the message */
500                                 case FLAGS_FIELD:
501                                         if (tree) {
502                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
503                                                                                                                                 data_length, "Flags Field: ");
504                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
505                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
506                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
507                                                 switch (message_type) {
508                                                         case INQUIRE:
509                                                                 proto_tree_add_bitmask(pnrp_message_tree, tvb, offset+4, hf_pnrp_message_inquire_flags, ett_pnrp_message_inquire_flags, inquire_flags, FALSE);
510                                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 6, 2, "Padding : %d - 2 Bytes",tvb_get_ntohs(tvb,offset+6));
511                                                                 offset += data_length+2;
512
513                                                                 break;
514                                                                 
515                                                         case ACK:
516                                                                 /* Reserved 0 - 14 bits */
517                                                                 proto_tree_add_bits_item(pnrp_message_tree, hf_pnrp_message_ack_flags_reserved, tvb, (offset + 4)*8, 15, FALSE);
518                                                                 /* N - Bit */
519                                                                 proto_tree_add_bits_item(pnrp_message_tree, hf_pnrp_message_ack_flags_Nbit, tvb,((offset + 4)*8)+15, 1, FALSE);
520                                                                 offset += data_length;
521                                                                 break;
522                                                         case AUTHORITY:
523                                                                 proto_tree_add_bitmask(pnrp_message_tree, tvb, offset+4, hf_pnrp_message_authority_flags, ett_pnrp_message_authority_flags, authority_flags, FALSE);
524                                                                 /* Check if the Flags Field is the last message part. If so, no padding of 2 bytes is added */
525                                                                 if(tvb_reported_length_remaining(tvb, offset+data_length)==0)
526                                                                 {
527                                                                         offset += data_length;
528                                                                 }
529                                                                 else {
530                                                                         padding_bytes = 2;
531                                                                         proto_tree_add_text(pnrp_message_tree, tvb, offset + 6, padding_bytes, "Padding: %d bytes", padding_bytes);
532                                                                         offset += data_length+2;
533                                                                 }
534                                                                 break;
535                                                                 
536
537                                                         default:
538                                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 4, data_length -4, "Flags");
539                                                                 offset += data_length;
540                                                                 break;
541                                                 }
542                                                 
543                                         }
544                                         
545                                         break;
546                                         
547                                         /* Flood controls found in FLOOD Message */
548                                 case FLOOD_CONTROLS:
549                                         if (tree) {
550                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
551                                                                                                                                 data_length, "Flood Control: ");
552                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
553                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
554                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
555                                                 /* Reserved 1 - 15 bits */
556                                                 proto_tree_add_bits_item(pnrp_message_tree, hf_pnrp_message_flood_flags_reserved1, tvb, (offset + 4)*8, 15, FALSE);
557                                                 /* D - Bit */
558                                                 proto_tree_add_bits_item(pnrp_message_tree, hf_pnrp_message_flood_flags_Dbit, tvb,((offset + 4)*8)+15, 1, FALSE);
559                                                 /* Reserved 2 */
560                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 6, 1, "Reserved 2: %d",tvb_get_guint8(tvb,offset+6));
561                                                 /* Padding 1 */
562                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 7, 1, "Padding: %d",tvb_get_guint8(tvb,offset+7));
563                                         }
564                                         
565                                         offset += data_length+1;
566                                         break;
567                                         
568                                         /* Solicit Controls found in SOLICIT Message */
569                                 case SOLICIT_CONTROLS:
570                                         if (tree) {
571                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
572                                                                                                                                 data_length, "Solicit Controls: ");
573                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
574                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
575                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
576                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 4, 1, "Reserved : %d",tvb_get_guint8(tvb,offset+4));
577                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_solicitType, tvb, offset + 5, 1, FALSE);
578                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 6, 2, "Reserved : %d",tvb_get_ntohs(tvb,offset+6));
579                                         }
580                                         offset += data_length +2;       /* Padding involved */
581                                         break;
582                                         /* Lookup controls found in LOOKUP Message */
583                                 case LOOKUP_CONTROLS:
584                                         if (tree) {
585                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
586                                                                                                                                 data_length, "Lookup Control: ");
587                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
588                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
589                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
590                                                 /* 2 Bytes of Flags */
591                                                 proto_tree_add_bitmask(pnrp_message_tree, tvb, offset+4, hf_pnrp_message_lookupControls_flags, ett_pnrp_message_lookupControls_flags, lookupControls_flags, FALSE);
592                                                 /* Precision Bytes */
593                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_lookupControls_precision, tvb, offset + 6, 2, FALSE);
594                                                 /* Resolve Criteria */
595                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_lookupControls_resolveCriteria, tvb, offset + 8, 1, FALSE);
596                                                 /* Reason Code */
597                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_lookupControls_reasonCode, tvb, offset + 9, 1, FALSE);
598                                                 /* Reserved */
599                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 10, 2, "Reserved : %d",tvb_get_ntohs(tvb,offset+10));
600                                                 
601                                         }
602                                         
603                                         offset += data_length;
604                                         break;
605                                         /* Target PNRP ID found in Lookup Message */
606                                 case TARGET_PNRP_ID:
607                                         if (tree) {
608                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
609                                                                                                                                 data_length, "Target PNRP ID: ");
610                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
611                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
612                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
613                                                 dissect_pnrp_ids(tvb, offset+4, data_length-4, pnrp_message_tree);
614                                         }
615                                         
616                                         offset += data_length;
617                                         break;
618
619                                         /* Extended Payload found in AUTHORITY Message */
620                                 case EXTENDED_PAYLOAD:
621                                         if (tree) {
622                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
623                                                                                                                                 data_length, "Extended Payload: ");
624                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
625                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
626                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
627                                                 /* TODO: Do actual parsing */
628                                         }
629                                         
630                                         offset += data_length;
631                                         break;
632                                         /* Pnrp id Array as found in REQUEST & ADVERTISE Message */
633                                 case PNRP_ID_ARRAY:
634                                         if (tree) {
635                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
636                                                                                                                                 data_length, "PNRP ID Array: ");
637                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
638                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
639                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
640                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_idArray_NumEntries, tvb, offset + 4, 2, FALSE);
641                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_idArray_Length, tvb, offset + 6, 2, FALSE);
642                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_ElementFieldType, tvb, offset + 8, 2, FALSE);
643                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_idarray_Entrylength, tvb, offset + 10, 2, FALSE);
644                                                 dissect_pnrp_ids(tvb,offset+12,data_length-12,pnrp_message_tree);
645                                         }
646                                         
647                                         offset += data_length;
648                                         break;
649                                         /* Cert Chain follows as found in AUTHORITY */
650                                 case CERT_CHAIN:
651                                         if (tree) {
652                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
653                                                                                                                                 data_length, "CERT Chain: ");
654                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
655                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
656                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
657                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_certChain, tvb, offset + 4, data_length-4, FALSE);
658                                         }
659                                         
660                                         /* There might be padding, so fill up to the next byte */
661                                         padding_bytes = 0;
662                                         while (data_length%4 != 0 &&tvb_reported_length_remaining(tvb, offset+data_length)!=0) {
663                                                 data_length++;
664                                                 padding_bytes++;
665                                         }
666                                         /* Check if we actually had some padding bytes */
667                                         if (0<padding_bytes) {
668                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + data_length-padding_bytes, padding_bytes, "Padding: %d bytes", padding_bytes);
669                                         }
670                                         offset += data_length;
671                                         break;
672                                         /* classifier: A classifier string follows as found in AUTHORITY */
673                                 case CLASSIFIER:
674                                         if (tree) {
675                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
676                                                                                                                                 data_length, "Classifier: ");
677                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
678                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
679                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
680                                                 /* NumEntries */
681                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_classifier_unicodeCount, tvb, offset + 4, 2, FALSE);
682                                                 /* Array Length: 8+(NumEntries*EntryLength */
683                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_classifier_arrayLength, tvb, offset + 6, 2, FALSE);
684                                                 /* Element Field Type: WCHAR */
685                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset+8 , 2, FALSE);
686                                                 /* Entry Length: Must be 0x0002 */
687                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_classifier_entryLength, tvb, offset + 10, 2, FALSE);
688                                                 /* The actual classifier String */
689                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 12, tvb_get_ntohs(tvb,offset+6)-8, "Classifier: %s",tvb_get_ephemeral_faked_unicode(tvb, offset + 12, (tvb_get_ntohs(tvb,offset+6)-8)/2, FALSE));
690                                         }
691                                         
692                                         /* There might be padding, so fill up to the next byte */
693                                         padding_bytes = 0;
694                                         while (data_length%4 != 0 &&tvb_reported_length_remaining(tvb, offset+data_length)!=0) {
695                                                 data_length++;
696                                                 padding_bytes++;
697                                         }
698                                         /* Check if we actually had some padding bytes */
699                                         if (0<padding_bytes) {
700                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + data_length-padding_bytes, padding_bytes, "Padding: %d bytes", padding_bytes);
701                                         }
702                                         offset += data_length;
703                                         break;
704                                         /* A hashed nonce follows as found in ADVERTISE & SOLICIT */
705                                 case HASHED_NONCE:
706                                         if (tree) {
707                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
708                                                                                                                                 data_length, "Hashed Nonce: ");
709                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
710                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
711                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
712                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_hashednonce, tvb, offset + 4, data_length-4, FALSE);
713                                                 
714                                         }
715                                         
716                                         offset += data_length;
717                                         break;
718                                         
719                                         /* A nonce follows as found in REQUEST & INQUIRE */
720                                 case NONCE:
721                                         if (tree) {
722                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
723                                                                                                                                 data_length, "Nonce: ");
724                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
725                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
726                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
727                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_nonce, tvb, offset + 4, data_length-4, FALSE);
728                                         }
729                                         
730                                         offset += data_length;
731                                         break;
732                                         
733                                         /* split controls as found in AUTHORITY */
734                                 case SPLIT_CONTROLS:
735                                         if (tree) {
736                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
737                                                                                                                                 data_length, "Split controls: ");
738                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
739                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
740                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
741                                                 /* Size of Authority Buffer */
742                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_splitControls_authorityBuffer, tvb, offset + 4, 2, FALSE);
743                                                 /* Byte offset */
744                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + 6, 2, "Offset : %d",tvb_get_ntohs(tvb,offset+6));
745                 
746                                         }
747                                         
748                                         /* There could be data offset */
749                                         offset += data_length+tvb_get_ntohs(tvb,offset+6);
750                                         break;
751                                         
752                                         /* routing entry: A route entry follows as found in ADVERTISE, INQUIRE, LOOKUP & AUTHORITY */
753                                 case ROUTING_ENTRY:
754                                         if (tree) {
755                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
756                                                                                                                                 data_length, "Routing Entry: ");
757                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
758                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
759                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
760                                                 dissect_route_entry(tvb,offset+4, tvb_get_ntohs(tvb,offset+2)-4, pnrp_message_tree);
761                                         }
762                                         
763                                         /* There might be padding, so fill up to the next byte */
764                                         padding_bytes = 0;
765                                         while (data_length%4 != 0 &&tvb_reported_length_remaining(tvb, offset+data_length)!=0) {
766                                                 data_length++;
767                                                 padding_bytes++;
768                                         }
769                                         /* Check if we actually had some padding bytes */
770                                         if (0<padding_bytes) {
771                                                 proto_tree_add_text(pnrp_message_tree, tvb, offset + data_length-padding_bytes, padding_bytes, "Padding: %d bytes", padding_bytes);
772                                         }
773                                         offset += data_length;
774                                         break;
775                                         
776                                         /* validate cpa: an encoded CPA structure follows as found in AUTHORITY */
777                                 case VALIDATE_CPA:
778                                         if (tree) {
779                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
780                                                                                                                                 data_length, "Validate CPA: ");
781                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
782                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
783                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
784                                                 /* Do the actual parsing in own method */
785                                                 dissect_encodedCPA_structure(tvb, offset+4, data_length-4, pnrp_message_tree);
786                                                 
787                                         }
788                                         
789                                         offset += data_length;
790                                         break;
791                                         
792                                         
793                                         /* IPV6 Endpoint: an ipv6 endpoint array structure follows as found in LOOKUP */
794                                 case IPV6_ENDPOINT_ARRAY:
795                                         if (tree) {
796                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
797                                                                                                                                 data_length, "IPv6 Endpoint Array: ");
798                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
799                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
800                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
801                                                 /* Number of route entries */
802                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_ipv6EndpointArray_NumberOfEntries, tvb, offset + 4, 2, FALSE);
803                                                 /* Array length */
804                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_ipv6EndpointArray_ArrayLength, tvb, offset + 6, 2, FALSE);
805                                                 /* Element Field Type */
806                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset+8 , 2, FALSE);
807                                                 /* Entry Length: must be 0x0012 (18 bytes) */
808                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_ipv6EndpointArray_EntryLength, tvb, offset + 10, 2, FALSE);
809                                                 /* Flagged Path */
810                                                 dissect_ipv6_endpoint_structure(tvb, offset+12, tvb_get_ntohs(tvb,offset+6)-8,pnrp_message_tree);
811                                         }
812                                         
813                                         offset += data_length;
814                                         break;
815                                         
816                                 default:
817                                         if (tree) {
818                                                 pnrp_message_item = proto_tree_add_text(pnrp_tree, tvb, offset, 
819                                                                                                                                 data_length, "Type: %s, length: %u",
820                                                                                                                                 val_to_str(field_type, fieldID, "Unknown (0x%04x)"), data_length);
821                                                 pnrp_message_tree = proto_item_add_subtree(pnrp_message_item, ett_pnrp_message);
822                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_type, tvb, offset , 2, FALSE);
823                                                 proto_tree_add_item(pnrp_message_tree, hf_pnrp_message_length, tvb, offset + 2, 2, FALSE);
824                                                 if(data_length > 4)
825                                                 {
826                                                         proto_tree_add_text(pnrp_message_tree, tvb, offset + 4, data_length -4, "Data");
827                                                 }
828                                                 else {
829                                                         return 0;
830                                                 }
831                                         }
832                                         offset += data_length;
833                                         break;
834                         }
835                 }
836         }
837         return offset;
838         
839 }
840
841 /*--------------------------------------------------------------*
842  * Dissecting helper methods                                    *
843  *--------------------------------------------------------------*/
844
845 static void dissect_pnrp_ids(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
846 {
847         while (32 <=length) {
848                 proto_tree_add_item(tree, hf_pnrp_message_pnrpID, tvb, offset, 32, FALSE);
849                 length -= 32;
850                 offset += 32;
851         }
852         
853 }
854
855 static void dissect_route_entry(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
856 {
857         gint tmp_offset;
858         /* Check if we don't run out of data */ 
859         if (0 <= tvb_reported_length_remaining(tvb, offset+length)) {
860                 tmp_offset = 0;
861                 /* First, we have a 32 Bit long PNRP ID */
862                 proto_tree_add_item(tree, hf_pnrp_message_pnrpID, tvb, offset+tmp_offset, 32, FALSE);
863                 tmp_offset +=32;
864                 /* Add PNRP Major Version */
865                 proto_tree_add_item(tree,hf_pnrp_header_versionMajor,tvb,offset+tmp_offset,1,FALSE);
866                 tmp_offset += 1;
867                 /* Add Minor Version */
868                 proto_tree_add_item(tree,hf_pnrp_header_versionMinor,tvb,offset+tmp_offset,1,FALSE);
869                 tmp_offset +=1;
870                 /* Port Number */
871                 proto_tree_add_item(tree,hf_pnrp_message_routeEntry_portNumber,tvb,offset+tmp_offset,2,FALSE);
872                 tmp_offset +=2;
873                 /* Flags */
874                 proto_tree_add_item(tree,hf_pnrp_message_routeEntry_flags,tvb,offset+tmp_offset,1,FALSE);
875                 tmp_offset +=1;
876                 /* Address count */
877                 proto_tree_add_item(tree,hf_pnrp_message_routeEntry_addressCount,tvb,offset+tmp_offset,1,FALSE);
878                 tmp_offset +=1;
879                 /* IPv6 Addresses */
880                 dissect_ipv6_address(tvb, offset+tmp_offset, length -tmp_offset, tree);
881         }
882 }
883
884 static void dissect_ipv6_endpoint_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
885 {
886         /* Check if we don't run out of data */ 
887         while (0 <= tvb_reported_length_remaining(tvb, offset+18) && 18 <=length) {
888                 /* Port Number */
889                 proto_tree_add_text(tree, tvb, offset, 2, "Port Number : %d",tvb_get_ntohs(tvb, offset));
890                 /* IPv6 Addresses */
891                 dissect_ipv6_address(tvb, offset+2,16,tree);
892                 offset += 18;
893                 length -= 18;
894         }
895 }
896
897 static void dissect_ipv6_address(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
898 {
899         while (0 <= tvb_reported_length_remaining(tvb, offset+16) && 16 <=length) {
900                 proto_tree_add_item(tree, hf_pnrp_message_ipv6, tvb, offset, 16, FALSE);
901                 offset += 16;
902                 length -= 16;
903         }
904 }
905
906 static void dissect_encodedCPA_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
907 {
908         /* Check if we don't run out of data */ 
909         if (0 <= tvb_reported_length_remaining(tvb, offset+length)) {
910                 guint8 flagsField;
911                 /* Add a new subtree */
912                 proto_item *pnrp_encodedCPA_tree = NULL;
913                 proto_item *pnrp_encodedCPA_item = NULL;
914                 pnrp_encodedCPA_item = proto_tree_add_item(tree, hf_pnrp_encodedCPA, tvb, offset,length,FALSE);
915                 pnrp_encodedCPA_tree = proto_item_add_subtree(pnrp_encodedCPA_item, ett_pnrp_message_encodedCPA);
916                 
917                 /* Length information */
918                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_length, tvb, offset, 2, FALSE);
919                 /* CPA Minor Version */
920                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_minorVersion, tvb, offset+2, 1, FALSE);
921                 /* CPA Major Version */
922                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_majorVersion, tvb, offset+3, 1, FALSE);
923                 /* PNRP Minor Version */
924                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_header_versionMinor, tvb, offset+4, 1, FALSE);
925                 /* PNRP Major Version */
926                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_header_versionMajor, tvb, offset+5, 1, FALSE);
927                 /* Flags Field */
928                 proto_tree_add_bitmask(pnrp_encodedCPA_tree, tvb, offset+6, hf_pnrp_encodedCPA_flags, ett_pnrp_message_encodedCPA_flags, encodedCPA_flags, FALSE);
929                 flagsField = tvb_get_guint8(tvb,offset+6);
930                 /* Reserved */
931                 proto_tree_add_text(pnrp_encodedCPA_tree, tvb, offset + 7, 1, "Reserved");
932                 /* Not After */
933                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_notAfter, tvb, offset+8, 8, FALSE);
934                 /* Service Location */
935                 proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_serviceLocation, tvb, offset+16, 16, FALSE);
936                 
937                 /* now, the structure is variable, so add bytes to offset */
938                 offset +=32;
939                 
940                 /* Check if R Flag is set */
941                 if ((flagsField & FLAGS_ENCODED_CPA_R)==0x00) {
942                         /* Nonce follows */
943                         proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_message_nonce, tvb, offset, 16, FALSE);
944                         offset +=16;
945                 }
946                 /* Check if A Flag is set */
947                 if (flagsField & FLAGS_ENCODED_CPA_A) {
948                         /* Binary authority */
949                         proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_binaryAuthority, tvb, offset, 20, FALSE);
950                         offset +=20;
951                 }
952                 /* Check if C Flag is set */
953                 if (flagsField & FLAGS_ENCODED_CPA_C) {
954                         /* Classifiert Hash */
955                         proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_classifiertHash, tvb, offset, 20, FALSE);
956                         offset +=20;
957                 }
958                 /* Check if F Flag is set */
959                 if (flagsField & FLAGS_ENCODED_CPA_F) {
960                         /* Friendly Name Length */
961                         proto_tree_add_text(pnrp_encodedCPA_tree, tvb, offset,2, "Length of Friendly name : %d",tvb_get_letohs(tvb,offset));
962                         /* Friendly Name */
963                         proto_tree_add_item(pnrp_encodedCPA_tree, hf_pnrp_encodedCPA_friendlyName, tvb, offset+2, tvb_get_letohs(tvb,offset), FALSE);
964                         offset +=tvb_get_letohs(tvb,offset)+2;
965                 }
966                 /* Service Address List */
967                 proto_tree_add_text(pnrp_encodedCPA_tree, tvb, offset,2, "Number of Service Addresses : %d",tvb_get_letohs(tvb,offset));
968                 offset += 2;
969                 proto_tree_add_text(pnrp_encodedCPA_tree, tvb, offset,2, "Service Address Length : %d",tvb_get_letohs(tvb,offset));
970                 offset += 2;
971                 /* A list of IPV6_Endpoint Structures follows */
972                 dissect_ipv6_endpoint_structure(tvb, offset,tvb_get_letohs(tvb,offset-4)*tvb_get_letohs(tvb,offset-2) , pnrp_encodedCPA_tree);
973                 offset += tvb_get_letohs(tvb,offset-4)*tvb_get_letohs(tvb,offset-2);
974                 /* A number of Payload Structures */
975                 proto_tree_add_text(pnrp_encodedCPA_tree, tvb, offset,2, "Number of Payload Structures : %d",tvb_get_letohs(tvb,offset));
976                 offset += 2;
977                 proto_tree_add_text(pnrp_encodedCPA_tree, tvb, offset,2, "Total Bytes of Payload : %d",tvb_get_letohs(tvb,offset));
978                 offset += 2;
979                 dissect_payload_structure(tvb,offset, tvb_get_letohs(tvb,offset-2)-4,pnrp_encodedCPA_tree);
980                 offset += tvb_get_letohs(tvb,offset-2)-4;
981                 /* Public Key */
982                 dissect_publicKey_structure(tvb, offset,tvb_get_letohs(tvb,offset),pnrp_encodedCPA_tree);
983                 offset += tvb_get_letohs(tvb,offset);
984                 /* Signature */
985                 dissect_signature_structure(tvb, offset,tvb_get_letohs(tvb,offset),pnrp_encodedCPA_tree);
986                 offset += tvb_get_letohs(tvb,offset);
987         }
988 }
989 static void dissect_payload_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
990 {
991         guint16 lengthOfData;
992         /* Add a new Subtree */
993         proto_item *pnrp_payload_tree = NULL;
994         proto_item *pnrp_payload_item = NULL;
995         /* Check if we actually should display something */
996         if (0<length ) {
997         pnrp_payload_item = proto_tree_add_text(tree, tvb, offset, length, "Payload Structure");
998         pnrp_payload_tree = proto_item_add_subtree(pnrp_payload_item, ett_pnrp_message_payloadStructure);
999         
1000         /* Dissect the Payload Structure */
1001         /* Payload Type */
1002         proto_tree_add_text(pnrp_payload_tree, tvb, offset,4, "Payload Type : %d",tvb_get_letohl(tvb,offset));
1003         offset += 4;
1004         /* Data Length */
1005         lengthOfData = tvb_get_letohs(tvb,offset);
1006         proto_tree_add_text(pnrp_payload_tree, tvb, offset,2, "Length of Data : %d",lengthOfData);
1007         offset += 2;
1008         /* IPV6_APP_ENDPOINT Structure */
1009         while (0 <= tvb_reported_length_remaining(tvb, offset+20)&& 20 <= lengthOfData) {
1010                 dissect_ipv6_address(tvb, offset, 16, pnrp_payload_tree);
1011                 offset += 16;
1012                 proto_tree_add_text(pnrp_payload_tree, tvb, offset,2, "Port Number : %d",tvb_get_letohs(tvb,offset));
1013                 /* proto_tree_add_item(pnrp_payload_tree, hf_pnrp_payload_port, tvb, offset, 2, FALSE); */
1014                 offset += 2;
1015                 proto_tree_add_text(pnrp_payload_tree, tvb, offset,2, "IANA Protocol Number : %d",tvb_get_letohs(tvb,offset));
1016                 offset += 2;
1017                 lengthOfData -=20;
1018         }
1019         }
1020 }
1021 static void dissect_publicKey_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
1022 {
1023         guint16 objIDLength;
1024         guint16 cbDataLength;
1025         /* Add a new Subtree */
1026         proto_item *pnrp_publicKey_tree = NULL;
1027         proto_item *pnrp_publicKey_item = NULL;
1028         /* Check if we can safely parse Data */
1029         if (0 < length && 0 <= tvb_reported_length_remaining(tvb, offset+length)) {
1030                 pnrp_publicKey_item = proto_tree_add_text(tree, tvb, offset, length, "CPA Public Key Structure");
1031                 pnrp_publicKey_tree = proto_item_add_subtree(pnrp_publicKey_item, ett_pnrp_message_publicKeyStructure);
1032                 /* Parsing of Data */
1033                 /* Field Length of Structure */
1034                 proto_tree_add_text(pnrp_publicKey_tree, tvb, offset,2, "Length of Structure : %d",tvb_get_letohs(tvb,offset));
1035                 offset += 2;
1036                 /* ObjID length */
1037                 objIDLength = tvb_get_letohs(tvb,offset);
1038                 proto_tree_add_text(pnrp_publicKey_tree, tvb, offset,2, "Size of Algorithm OID : %d",objIDLength);
1039                 offset += 2;
1040                 /* Reserved */
1041                 proto_tree_add_text(pnrp_publicKey_tree, tvb, offset,2, "Reserved : %d",tvb_get_ntohs(tvb,offset));
1042                 offset +=2;
1043                 /* Public Key cbData Length */
1044                 cbDataLength = tvb_get_letohs(tvb,offset);
1045                 proto_tree_add_text(pnrp_publicKey_tree, tvb, offset,2, "Size of cbData : %d",cbDataLength);
1046                 offset += 2;
1047                 /* Unused Bits, actually only 7... */
1048                 proto_tree_add_text(pnrp_publicKey_tree, tvb, offset,1, "Unused Bits : %d",7);
1049                 offset +=1;
1050                 /* Algorithm ObjID */
1051                 proto_tree_add_item(pnrp_publicKey_tree, hf_pnrp_publicKey_objID, tvb, offset, objIDLength, FALSE);
1052                 offset += objIDLength;
1053                 /*  Public Key Data */
1054                 proto_tree_add_item(pnrp_publicKey_tree, hf_pnrp_publicKey_publicKeyData, tvb, offset, cbDataLength, FALSE);
1055         }
1056 }
1057 static void dissect_signature_structure(tvbuff_t *tvb, gint offset, gint length, proto_tree *tree)
1058 {
1059         guint16 signatureLength;
1060         /* Add a new Subtree */
1061         proto_item *pnrp_signature_tree = NULL;
1062         proto_item *pnrp_signature_item = NULL;
1063         /* Check if we can safely parse Data */
1064         if (0 < length && 0 <= tvb_reported_length_remaining(tvb, offset+length)) {
1065                 pnrp_signature_item = proto_tree_add_text(tree, tvb, offset, length, "Signature Structure");
1066                 pnrp_signature_tree = proto_item_add_subtree(pnrp_signature_item, ett_pnrp_message_signatureStructure);
1067                 /* Parsing of Data */
1068                 /* Field Length of Structure */
1069                 proto_tree_add_text(pnrp_signature_tree, tvb, offset,2, "Length of Structure : %d",tvb_get_letohs(tvb,offset));
1070                 offset +=2;
1071                 /* Signature Length */
1072                 signatureLength = tvb_get_letohs(tvb,offset);
1073                 proto_tree_add_text(pnrp_signature_tree, tvb, offset,2, "Length of Signature : %d",signatureLength);
1074                 offset += 2;
1075                 /* Hash Algorithm Identifier */
1076                 proto_tree_add_text(pnrp_signature_tree, tvb, offset,4, "Hash Algorithm Identifier : %x",tvb_get_letohl(tvb,offset));
1077                 offset += 4;
1078                 /* Signature Data */
1079                 proto_tree_add_item(pnrp_signature_tree, hf_pnrp_signature_signatureData, tvb, offset, signatureLength, FALSE);
1080         }
1081 }
1082 /* Register the protocol */
1083 void proto_register_pnrp(void)
1084 {
1085         /* A header field is something you can search/filter on.
1086          * 
1087          * We create a structure to register our fields. It consists of an
1088          * array of hf_register_info structures, each of which are of the format
1089          * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
1090          */
1091         static hf_register_info hf[] = {
1092                 { &hf_pnrp_header,
1093                         { "Header", "pnrp.header", FT_NONE, BASE_NONE, NULL, 0x0,
1094                                 "PNRP Header", HFILL }},
1095                 { &hf_pnrp_header_fieldID,
1096                         { "Header FieldID", "pnrp.header.fieldID", FT_UINT16, BASE_HEX, VALS(fieldID), 0x0,
1097                                 NULL, HFILL }},
1098                 { &hf_pnrp_header_length,
1099                         { "Header length", "pnrp.header.lenght", FT_UINT16, BASE_DEC, NULL, 0x0,
1100                                 NULL, HFILL }},
1101                 { &hf_pnrp_header_ident,
1102                         { "Ident", "pnrp.ident", FT_UINT8, BASE_HEX, NULL, 0x0,
1103                                 NULL, HFILL }},
1104                 { &hf_pnrp_header_versionMajor,
1105                         { "Version Major", "pnrp.vMajor", FT_UINT8, BASE_DEC, NULL, 0x0,
1106                                 NULL, HFILL }},
1107                 { &hf_pnrp_header_versionMinor,
1108                         { "Version Minor", "pnrp.vMinor", FT_UINT8, BASE_DEC, NULL, 0x0,
1109                                 NULL, HFILL }},
1110                 { &hf_pnrp_header_messageType,
1111                         { "Message Type", "pnrp.messageType", FT_UINT8, BASE_DEC, VALS(messageType), 0x0,
1112                                 NULL, HFILL }},
1113                 { &hf_pnrp_header_messageID,
1114                         { "Message ID", "pnrp.header.messageID", FT_UINT32, BASE_HEX, NULL, 0x0,
1115                                 NULL, HFILL }},
1116                 { &hf_pnrp_message_type,
1117                         { "Segment Type", "pnrp.segment.type", FT_UINT16, BASE_HEX, VALS(fieldID), 0x0,
1118                                 NULL, HFILL }},
1119                 { &hf_pnrp_message_length,
1120                         { "Segment length", "pnrp.segment.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1121                                 "Message length", HFILL }},
1122                 { &hf_pnrp_message_headerack,
1123                         { "ACKed Header ID", "pnrp.segment.headerAck", FT_UINT32, BASE_HEX, NULL, 0x0,
1124                                 NULL, HFILL }},
1125                 { &hf_pnrp_message_pnrpID,
1126                         { "PNRP ID", "pnrp.segment.pnrpID", FT_BYTES, BASE_NONE, NULL, 0x0,
1127                                 NULL, HFILL }},
1128                 /* Inquire Flags */
1129                 { &hf_pnrp_message_inquire_flags,
1130                         { "Flags", "pnrp.segment.inquire.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1131                                 NULL, HFILL }},
1132                 { &hf_pnrp_message_inquire_flags_reserved1,
1133                         { "Reserved 1", "pnrp.segment.inquire.flags.reserved1", FT_UINT16, BASE_HEX, NULL, FLAGS_INQUIRE_RESERVED1,
1134                                 NULL, HFILL }},
1135                 { &hf_pnrp_message_inquire_flags_Abit,
1136                         { "CPA shoul (a)ppear in response", "pnrp.segment.inquire.flags.Abit", FT_UINT16, BASE_HEX, NULL, FLAGS_INQUIRE_A,
1137                                 NULL, HFILL }},
1138                 { &hf_pnrp_message_inquire_flags_Xbit,
1139                         { "E(X)tended Payload sent in Authority response", "pnrp.segment.inquire.flags.Xbit", FT_UINT16, BASE_HEX, NULL, FLAGS_INQUIRE_X,
1140                                 NULL, HFILL }},
1141                 { &hf_pnrp_message_inquire_flags_Cbit,
1142                         { "(C)ertificate Chain sent in Authority response", "pnrp.segment.inquire.flags.Cbit", FT_UINT16, BASE_HEX, NULL, FLAGS_INQUIRE_C,
1143                                 NULL, HFILL }},
1144                 { &hf_pnrp_message_inquire_flags_reserved2,
1145                         { "Reserved 2", "pnrp.segment.inquire.flags.reserved2", FT_UINT16, BASE_HEX, NULL, FLAGS_INQUIRE_RESERVED2,
1146                                 NULL, HFILL }},
1147                 /* Classifier */
1148                 { &hf_pnrp_message_classifier_unicodeCount,
1149                         { "Number of Unicode Characters", "pnrp.segment.classifier.unicodeCount", FT_UINT16, BASE_DEC, NULL, 0x0,
1150                                 NULL, HFILL }},
1151                 { &hf_pnrp_message_classifier_arrayLength,
1152                         { "Array Length", "pnrp.segment.classifier.arrayLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1153                                 NULL, HFILL }},
1154                 { &hf_pnrp_message_classifier_entryLength,
1155                         { "Entry Length", "pnrp.segment.classifier.entryLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1156                                 NULL, HFILL }},
1157                 /* Ack Flags */
1158                 { &hf_pnrp_message_ack_flags_reserved,
1159                         { "Reserved", "pnrp.segment.ack.flags.reserved", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1160                                 NULL, HFILL }},
1161                 { &hf_pnrp_message_ack_flags_Nbit,
1162                         { "(N)ot found Bit", "pnrp.segment.ack.flags.Nbit", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1163                                 NULL, HFILL }},
1164                 /* Authority Flags */
1165                 { &hf_pnrp_message_authority_flags,
1166                         { "Flags", "pnrp.segment.authority.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1167                                 NULL, HFILL }},
1168                 { &hf_pnrp_message_authority_flags_reserved1,
1169                         { "Reserved 1", "pnrp.segment.authority.flags.reserved1", FT_UINT16, BASE_HEX, NULL, FLAGS_AUTHORITY_RESERVED1,
1170                                 NULL, HFILL }},
1171                 { &hf_pnrp_message_authority_flags_Lbit,
1172                         { "(L)eaf Set", "pnrp.segment.authority.flags.Lbit", FT_UINT16, BASE_HEX, NULL, FLAGS_AUTHORITY_L,
1173                                 NULL, HFILL }},
1174                 { &hf_pnrp_message_authority_flags_reserved2,
1175                         { "Reserved 2", "pnrp.segment.authority.flags.reserved2", FT_UINT16, BASE_HEX, NULL, FLAGS_AUTHORITY_RESERVED2,
1176                                 NULL, HFILL }},
1177                 { &hf_pnrp_message_authority_flags_Bbit,
1178                         { "(B)usy", "pnrp.segment.authority.flags.Bbit", FT_UINT16, BASE_HEX, NULL, FLAGS_AUTHORITY_B,
1179                                 NULL, HFILL }},
1180                 { &hf_pnrp_message_authority_flags_reserved3,
1181                         { "Reserved 3", "pnrp.segment.authority.flags.reserved3", FT_UINT16, BASE_HEX, NULL, FLAGS_AUTHORITY_RESERVED3,
1182                                 NULL, HFILL }},
1183                 { &hf_pnrp_message_authority_flags_Nbit,
1184                         { "(N)ot found", "pnrp.segment.authority.flags.Nbit", FT_UINT16, BASE_HEX, NULL, FLAGS_AUTHORITY_N,
1185                                 NULL, HFILL }},
1186                 /* Flood Control Flags */
1187                 { &hf_pnrp_message_flood_flags_reserved1,
1188                         { "Reserved", "pnrp.segment.flood.flags.reserved", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1189                                 NULL, HFILL }},
1190                 { &hf_pnrp_message_flood_flags_Dbit,
1191                         { "(D)on't send ACK", "pnrp.segment.flood.flags.Dbit", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1192                                 NULL, HFILL }},
1193                 /* Split Controls */
1194                 { &hf_pnrp_message_splitControls_authorityBuffer,
1195                         { "Authority  Buffer Size:", "pnrp.segment.splitControls.authorityBuffer", FT_UINT16, BASE_DEC, NULL, 0x0,
1196                                 NULL, HFILL }},
1197                 /* IPv6 Endpoint Array */
1198                 { &hf_pnrp_message_ipv6EndpointArray_NumberOfEntries,
1199                         { "Number of Entries:", "pnrp.segment.ipv6EndpointArray.NumberOfEntries", FT_UINT16, BASE_DEC, NULL, 0x0,
1200                                 NULL, HFILL }},
1201                 { &hf_pnrp_message_ipv6EndpointArray_ArrayLength,
1202                         { "Array Length:", "pnrp.segment.ipv6EndpointArray.ArrayLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1203                                 NULL, HFILL }},
1204                 { &hf_pnrp_message_ipv6EndpointArray_EntryLength,
1205                         { "Entry Length", "pnrp.segment.ipv6EndpointArray.EntryLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1206                                 NULL, HFILL }},
1207                 /* Encoded CPA structrue */
1208                 { &hf_pnrp_encodedCPA,
1209                         { "Encoded CPA structure", "pnrp.encodedCPA", FT_NONE, BASE_NONE, NULL, 0x0,
1210                                 NULL, HFILL }},
1211                 { &hf_pnrp_encodedCPA_length,
1212                         { "Length", "pnrp.encodedCPA.lenght", FT_UINT16, BASE_DEC, NULL, 0x0,
1213                                 NULL, HFILL }},
1214                 { &hf_pnrp_encodedCPA_majorVersion,
1215                         { "CPA Major Version ", "pnrp.encodedCPA.vMajor", FT_UINT8, BASE_DEC, NULL, 0x0,
1216                                 NULL, HFILL }},
1217                 { &hf_pnrp_encodedCPA_minorVersion,
1218                         { "CPA Minor Version", "pnrp.encodedCPA.vMinor", FT_UINT8, BASE_DEC, NULL, 0x0,
1219                                 NULL, HFILL }},
1220                         /* Encoded CPA flags */
1221                 { &hf_pnrp_encodedCPA_flags,
1222                         { "Flags", "pnrp.encodedCPA.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1223                                 NULL, HFILL }},
1224                 { &hf_pnrp_encodedCPA_flags_reserved,
1225                         { "Reserved ", "pnrp.encodedCPA.flags.reserved", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_RESERVED,
1226                                 NULL, HFILL }},
1227                 { &hf_pnrp_encodedCPA_flags_Xbit,
1228                         { "CPA has E(X)tended Payload ", "pnrp.encodedCPA.flags.xbit", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_X,
1229                                 NULL, HFILL }},
1230                 { &hf_pnrp_encodedCPA_flags_Fbit,
1231                         { "CPA contains (F)riendly Name ", "pnrp.encodedCPA.flags.fbit", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_F,
1232                                 NULL, HFILL }},
1233                 { &hf_pnrp_encodedCPA_flags_Cbit,
1234                         { "CPA contains (C)lassifier Hash ", "pnrp.encodedCPA.flags.cbit", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_C,
1235                                 NULL, HFILL }},
1236                 { &hf_pnrp_encodedCPA_flags_Abit,
1237                         { "CPA contains Binary (A)uthority field ", "pnrp.encodedCPA.flags.abit", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_A,
1238                                 NULL, HFILL }},
1239                 { &hf_pnrp_encodedCPA_flags_Ubit,
1240                         { "Friendly Name in (U)TF-8 ", "pnrp.encodedCPA.flags.ubit", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_U,
1241                                 NULL, HFILL }},
1242                 { &hf_pnrp_encodedCPA_flags_Rbit,
1243                         { "This is a (r)evoke CPA", "pnrp.encodedCPA.flags.rbit", FT_UINT8, BASE_HEX, NULL, FLAGS_ENCODED_CPA_R,
1244                                 NULL, HFILL }},
1245                 /* TODO: Find correct way to Display Time */
1246                 { &hf_pnrp_encodedCPA_notAfter,
1247                         { "CPA expiration Date", "pnrp.encodedCPA.expirationDate", FT_UINT64,BASE_DEC, NULL, 0x0,
1248                                 "CPA expiration Date since January 1, 1601 UTC", HFILL }},
1249                 { &hf_pnrp_encodedCPA_serviceLocation,
1250                         { "Service Location", "pnrp.encodedCPA.serviceLocation", FT_BYTES,BASE_NONE, NULL, 0x0,
1251                                 NULL, HFILL }},
1252                 { &hf_pnrp_encodedCPA_binaryAuthority,
1253                         { "Binary Authoriy", "pnrp.encodedCPA.binaryAuthority", FT_BYTES,BASE_NONE, NULL, 0x0,
1254                                 "SHA-1 Hash of PublicKey Data field", HFILL }},
1255                 { &hf_pnrp_encodedCPA_classifiertHash,
1256                         { "Classifiert Hash", "pnrp.encodedCPA.classifierHash", FT_BYTES,BASE_NONE, NULL, 0x0,
1257                                 "SHA-1 Hash of the classifier text", HFILL }},
1258                 { &hf_pnrp_encodedCPA_friendlyName,
1259                         { "Friendly Name of PNRP ID", "pnrp.encodedCPA.friendlyName", FT_STRING,BASE_NONE, NULL, 0x0,
1260                                 "A human-readable label identifying the PNRP ID", HFILL }},
1261                 /* Lookup Controls */
1262                 { &hf_pnrp_message_lookupControls_flags,
1263                         { "Flags", "pnrp.lookupControls.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1264                                 NULL, HFILL }},
1265                 { &hf_pnrp_message_lookupControls_flags_reserved,
1266                         { "Reserved ", "pnrp.lookupControls.flags.reserved", FT_UINT16, BASE_HEX, NULL, FLAGS_LOOKUPCONTROLS_RESERVED,
1267                                 NULL, HFILL }},
1268                 { &hf_pnrp_message_lookupControls_flags_Abit,
1269                         { "A bit: ", "pnrp.lookupControls.flags.Abit", FT_UINT16, BASE_HEX, NULL, FLAGS_LOOKUPCONTROLS_A,
1270                                 "Sender is willing to accept returned nodes that are not closer to the target ID than the Validate PNRP ID", HFILL }},
1271                 { &hf_pnrp_message_lookupControls_flags_0bit,
1272                         { "0 bit - reserved: ", "pnrp.lookupControls.flags.0bit", FT_UINT16, BASE_HEX, NULL, FLAGS_LOOKUPCONTROLS_0,
1273                                 NULL, HFILL }},
1274                 { &hf_pnrp_message_lookupControls_precision,
1275                         { "Precision", "pnrp.lookupControls.precision", FT_UINT16, BASE_HEX, NULL, 0x0,
1276                                 "Precision - Number of significant bits to match", HFILL }},
1277                 { &hf_pnrp_message_lookupControls_resolveCriteria,
1278                         { "Resolve Criteria", "pnrp.lookupControls.resolveCriteria", FT_UINT8, BASE_HEX, VALS(resolveCriteria), 0x0,
1279                                 NULL, HFILL }},
1280                 { &hf_pnrp_message_lookupControls_reasonCode,
1281                         { "Reason Code", "pnrp.lookupControls.reasonCode", FT_UINT8, BASE_HEX, VALS(reasonCode), 0x0,
1282                                 NULL, HFILL }},
1283                 /* Public Key Structure */
1284                 { &hf_pnrp_publicKey_objID,
1285                         { "Public Key Object Identifiert", "pnrp.publicKey.objID", FT_STRING,BASE_NONE, NULL, 0x0,
1286                                 "An ASN.1-encoded object identifier (OID) indicating the public key format", HFILL }},
1287                 { &hf_pnrp_publicKey_publicKeyData,
1288                         { "Public Key Data", "pnrp.publicKey.publicKeyData", FT_STRING,BASE_NONE, NULL, 0x0,
1289                                 "An ASN.1-encoded 1024-bit RSA public key", HFILL }},
1290                 /* Signature Structure */
1291                 { &hf_pnrp_signature_signatureData,
1292                         { "Signature ", "pnrp.signature.data", FT_BYTES,BASE_NONE, NULL, 0x0,
1293                                 "Signature created when signing the CPA", HFILL }},
1294                 
1295                 /* Route Entry */
1296                 { &hf_pnrp_message_routeEntry_portNumber,
1297                         { "Port Number", "pnrp.segment.routeEntry.portNumber", FT_UINT16, BASE_DEC, NULL, 0x0,
1298                                 NULL, HFILL }},
1299                 { &hf_pnrp_message_routeEntry_flags,
1300                         { "Flags", "pnrp.segment.routeEntry.flags", FT_UINT8, BASE_DEC, NULL, 0x0,
1301                                 NULL, HFILL }},
1302                 { &hf_pnrp_message_routeEntry_addressCount,
1303                         { "Address Count", "pnrp.segment.routeEntry.addressCount", FT_UINT8, BASE_DEC, NULL, 0x0,
1304                                 NULL, HFILL }},
1305                 { &hf_pnrp_message_nonce,
1306                         { "Nonce", "pnrp.segment.nonce", FT_BYTES, BASE_NONE, NULL, 0x0,
1307                                 NULL, HFILL }},
1308                 { &hf_pnrp_message_hashednonce,
1309                         { "Hashed Nonce", "pnrp.segment.hashednonce", FT_BYTES, BASE_NONE, NULL, 0x0,
1310                                 NULL, HFILL }},
1311                 { &hf_pnrp_message_idArray_NumEntries,
1312                         { "Number of Entries", "pnrp.segment.idArray.NumEnries", FT_UINT16, BASE_DEC, NULL, 0x0,
1313                                 NULL, HFILL }},
1314                 { &hf_pnrp_message_idArray_Length,
1315                         { "Length of Array ", "pnrp.segment.idArray.Length", FT_UINT16, BASE_DEC, NULL, 0x0,
1316                                 NULL, HFILL }},
1317                 { &hf_pnrp_message_ElementFieldType,
1318                         { "Type of Array Entry ", "pnrp.segment.ElementFieldType", FT_UINT16, BASE_HEX, VALS(fieldID), 0x0,
1319                                 NULL, HFILL }},
1320                 { &hf_pnrp_message_idarray_Entrylength,
1321                         { "Length of each Array Entry ", "pnrp.segment.idArray.Entrylength", FT_UINT16, BASE_DEC, NULL, 0x0,
1322                                 NULL, HFILL }},
1323                 { &hf_pnrp_message_certChain,
1324                         { "Certificate Chain ", "pnrp.segment.certChain", FT_BYTES,BASE_NONE, NULL, 0x0,
1325                                 "A Certificate Chain, containing the public key used to sign the CPA and its Certificate Chain", HFILL }},
1326                 { &hf_pnrp_message_solicitType,
1327                         { "Solicit Type ", "pnrp.segment.solicitType", FT_UINT8, BASE_DEC, VALS(solicitType), 0x0,
1328                                 NULL, HFILL }},
1329                 { &hf_pnrp_message_ipv6,
1330                         { "IPv6 Address","pnrp.segment.ipv6Address",FT_IPv6, BASE_NONE, NULL, 0x0,"IPv6 Address",HFILL}}
1331         };
1332         
1333         /* Protocol subtree array */
1334         static gint *ett[] = {
1335         &ett_pnrp,
1336                 &ett_pnrp_message,
1337                 &ett_pnrp_message_inquire_flags,
1338                 &ett_pnrp_message_authority_flags,
1339                 &ett_pnrp_message_encodedCPA,
1340                 &ett_pnrp_message_encodedCPA_flags,
1341                 &ett_pnrp_message_payloadStructure,
1342                 &ett_pnrp_message_publicKeyStructure,
1343                 &ett_pnrp_message_signatureStructure,
1344                 &ett_pnrp_message_lookupControls_flags
1345         };
1346         /* Register the Dissector with Wireshark */
1347         proto_pnrp = proto_register_protocol(PROTONAME,PROTOSHORTNAME,PROTOABBREV);
1348         
1349         proto_register_field_array(proto_pnrp,hf,array_length(hf));
1350         proto_register_subtree_array (ett, array_length(ett));
1351 }
1352
1353 /* Initialise the dissector */
1354 void proto_reg_handoff_pnrp(void)
1355 {
1356         static gboolean initialized = FALSE;
1357         if(!initialized)
1358         {
1359                 static dissector_handle_t pnrp_handle;
1360                 pnrp_handle = new_create_dissector_handle(dissect_pnrp, proto_pnrp);
1361                 dissector_add("udp.port",PNRP_PORT,pnrp_handle);
1362         }
1363 }
1364