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