Use MAC address documentation range in filter examples
[metze/wireshark/wip.git] / epan / dissectors / packet-xip.c
1 /* packet-xip.c
2  * Routines for XIP dissection
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * The eXpressive Internet Protocol (XIP) is the network layer protocol for
23  * the eXpressive Internet Architecture (XIA), a future Internet architecture
24  * project. The addresses in XIP are directed acyclic graphs, so some of the
25  * code in this file verifies the correctness of the DAGs and displays them
26  * in human-readable form.
27  *
28  * More information about XIA can be found here:
29  *  https://www.cs.cmu.edu/~xia/
30  *
31  * And here:
32  *  https://github.com/AltraMayor/XIA-for-Linux/wiki
33  *
34  * More information about the format of the DAG can be found here:
35  *  https://github.com/AltraMayor/XIA-for-Linux/wiki/Human-readable-XIP-address-format
36  */
37
38 #include "config.h"
39 #include <epan/packet.h>
40 #include <epan/expert.h>
41
42 void proto_register_xip(void);
43 void proto_reg_handoff_xip(void);
44
45 /* Next dissector handles. */
46 static dissector_handle_t data_handle;
47
48 static gint proto_xip                   = -1;
49
50 static gint hf_xip_version              = -1;
51 static gint hf_xip_next_hdr             = -1;
52 static gint hf_xip_payload_len          = -1;
53 static gint hf_xip_hop_limit            = -1;
54 static gint hf_xip_num_dst              = -1;
55 static gint hf_xip_num_src              = -1;
56 static gint hf_xip_last_node            = -1;
57 static gint hf_xip_dst_dag              = -1;
58 static gint hf_xip_dst_dag_entry        = -1;
59 static gint hf_xip_src_dag              = -1;
60 static gint hf_xip_src_dag_entry        = -1;
61
62 static gint ett_xip_tree                = -1;
63 static gint ett_xip_ddag                = -1;
64 static gint ett_xip_sdag                = -1;
65
66 static expert_field ei_xip_invalid_len = EI_INIT;
67 static expert_field ei_xip_next_header = EI_INIT;
68 static expert_field ei_xip_bad_num_dst = EI_INIT;
69 static expert_field ei_xip_bad_num_src = EI_INIT;
70
71 /* XIA principals. */
72 #define XIDTYPE_NAT             0x00
73 #define XIDTYPE_AD              0x10
74 #define XIDTYPE_HID             0x11
75 #define XIDTYPE_CID             0x12
76 #define XIDTYPE_SID             0x13
77 #define XIDTYPE_UNI4ID          0x14
78 #define XIDTYPE_I4ID            0x15
79 #define XIDTYPE_U4ID            0x16
80 #define XIDTYPE_XDP             0x17
81 #define XIDTYPE_SRVCID          0x18
82 #define XIDTYPE_FLOWID          0x19
83 #define XIDTYPE_ZF              0x20
84
85 /* Principal string values. */
86 static const value_string xidtype_vals[] = {
87         { XIDTYPE_AD,           "ad" },
88         { XIDTYPE_HID,          "hid" },
89         { XIDTYPE_CID,          "cid" },
90         { XIDTYPE_SID,          "sid" },
91         { XIDTYPE_UNI4ID,       "uni4id" },
92         { XIDTYPE_I4ID,         "i4id" },
93         { XIDTYPE_U4ID,         "u4id" },
94         { XIDTYPE_XDP,          "xdp" },
95         { XIDTYPE_SRVCID,       "serval" },
96         { XIDTYPE_FLOWID,       "flowid" },
97         { XIDTYPE_ZF,           "zf" },
98         { 0,                    NULL }
99 };
100
101 enum xia_addr_error {
102         /* There's a non-XIDTYPE_NAT node after an XIDTYPE_NAT node. */
103         XIAEADDR_NAT_MISPLACED = 1,
104         /* Edge-selected bit is only valid in packets. */
105         XIAEADDR_CHOSEN_EDGE,
106         /* There's a non-empty edge after an Empty Edge.
107          * This error can also occur if an empty edge is selected. */
108         XIAEADDR_EE_MISPLACED,
109         /* An edge of a node is out of range. */
110         XIAEADDR_EDGE_OUT_RANGE,
111         /* The nodes are not in topological order. Notice that being in
112          * topological guarantees that the graph is acyclic, and has a simple,
113          * cheap test. */
114         XIAEADDR_NOT_TOPOLOGICAL,
115         /* No single component. */
116         XIAEADDR_MULTI_COMPONENTS,
117         /* Entry node is not present. */
118         XIAEADDR_NO_ENTRY
119 };
120
121 /* Maximum number of nodes in a DAG. */
122 #define XIA_NODES_MAX           9
123
124 /* Number of outgoing edges for each node. */
125 #define XIA_OUTDEGREE_MAX       4
126
127 /* Sizes of an XIA node and its components. */
128 #define XIA_TYPE_SIZE           4
129 #define XIA_XID_SIZE            20
130 #define XIA_EDGES_SIZE          4
131 #define XIA_NODE_SIZE           (XIA_TYPE_SIZE + XIA_XID_SIZE + XIA_EDGES_SIZE)
132
133 /* Split XID up into 4 byte chunks. */
134 #define XIA_XID_CHUNK_SIZE      4
135
136 typedef guint32 xid_type_t;
137
138 struct xia_xid {
139         /* XID type. */
140         xid_type_t      xid_type;
141
142         /* XID, represented as 4 byte ints. */
143         guint32         xid_id[XIA_XID_SIZE / XIA_XID_CHUNK_SIZE];
144 };
145
146 struct xia_row {
147         struct xia_xid  s_xid;
148         /* Outgoing edges. */
149         union {
150                 guint8  a[XIA_OUTDEGREE_MAX];
151                 guint32 i;
152         } s_edge;
153 };
154
155 struct xia_addr {
156         struct xia_row s_row[XIA_NODES_MAX];
157 };
158
159 /* XIA_MAX_STRADDR_SIZE - The maximum size of an XIA address as a string
160  * in bytes. It's the recommended size to call xia_ntop with. It includes space
161  * for an invalid sign (i.e. '!'), the type and name of a nodes in
162  * hexadecimal, the out-edges, the two separators (i.e. '-') per node,
163  * the edge-chosen sign (i.e. '>') for each selected edge,
164  * the node separators (i.e. ':' or ":\n"), a string terminator (i.e. '\0'),
165  * and an extra '\n' at the end the caller may want to add.
166  */
167 #define MAX_PPAL_NAME_SIZE      32
168 #define XIA_MAX_STRID_SIZE      (XIA_XID_SIZE * 2 + 1)
169 #define XIA_MAX_STRXID_SIZE     (MAX_PPAL_NAME_SIZE + XIA_MAX_STRID_SIZE)
170 #define XIA_MAX_STRADDR_SIZE    (1 + XIA_NODES_MAX * \
171         (XIA_MAX_STRXID_SIZE + XIA_OUTDEGREE_MAX * 2 + 2) + 1)
172
173 /*
174  *      Validating addresses
175  */
176
177 #define XIA_CHOSEN_EDGE         0x80
178 #define XIA_EMPTY_EDGE          0x7f
179 #define XIA_ENTRY_NODE_INDEX    0x7e
180
181 #define XIA_EMPTY_EDGES (XIA_EMPTY_EDGE << 24 | XIA_EMPTY_EDGE << 16 |\
182                          XIA_EMPTY_EDGE <<  8 | XIA_EMPTY_EDGE)
183 #define XIA_CHOSEN_EDGES (XIA_CHOSEN_EDGE << 24 | XIA_CHOSEN_EDGE << 16 |\
184                          XIA_CHOSEN_EDGE <<  8 | XIA_CHOSEN_EDGE)
185
186 static inline gint
187 is_edge_chosen(guint8 e)
188 {
189         return e & XIA_CHOSEN_EDGE;
190 }
191
192 static inline gint
193 is_any_edge_chosen(const struct xia_row *row)
194 {
195         return row->s_edge.i & XIA_CHOSEN_EDGES;
196 }
197
198 static inline gint
199 is_empty_edge(guint8 e)
200 {
201         return (e & XIA_EMPTY_EDGE) == XIA_EMPTY_EDGE;
202 }
203
204 static inline gint
205 xia_is_nat(xid_type_t ty)
206 {
207         return ty == XIDTYPE_NAT;
208 }
209
210 static gint
211 xia_are_edges_valid(const struct xia_row *row,
212         guint8 node, guint8 num_node, guint32 *pvisited)
213 {
214         const guint8 *edge;
215         guint32 all_edges, bits;
216         gint i;
217
218         if (is_any_edge_chosen(row)) {
219                 /* Since at least an edge of last_node has already
220                  * been chosen, the address is corrupted.
221                  */
222                 return -XIAEADDR_CHOSEN_EDGE;
223         }
224
225         edge = row->s_edge.a;
226         all_edges = g_ntohl(row->s_edge.i);
227         bits = 0xffffffff;
228         for (i = 0; i < XIA_OUTDEGREE_MAX; i++, edge++) {
229                 guint8 e;
230                 e = *edge;
231                 if (e == XIA_EMPTY_EDGE) {
232                         if ((all_edges & bits) !=
233                                 (XIA_EMPTY_EDGES & bits))
234                                 return -XIAEADDR_EE_MISPLACED;
235                         else
236                                 break;
237                 } else if (e >= num_node) {
238                         return -XIAEADDR_EDGE_OUT_RANGE;
239                 } else if (node < (num_node - 1) && e <= node) {
240                         /* Notice that if (node == XIA_ENTRY_NODE_INDEX)
241                          * it still works fine because XIA_ENTRY_NODE_INDEX
242                          * is greater than (num_node - 1).
243                          */
244                         return -XIAEADDR_NOT_TOPOLOGICAL;
245                 }
246                 bits >>= 8;
247                 *pvisited |= 1 << e;
248         }
249         return 0;
250 }
251
252 static gint
253 xia_test_addr(const struct xia_addr *addr)
254 {
255         gint i, n;
256         gint saw_nat = 0;
257         guint32 visited = 0;
258
259         /* Test that XIDTYPE_NAT is present only on last rows. */
260         n = XIA_NODES_MAX;
261         for (i = 0; i < XIA_NODES_MAX; i++) {
262                 xid_type_t ty;
263                 ty = addr->s_row[i].s_xid.xid_type;
264                 if (saw_nat) {
265                         if (!xia_is_nat(ty))
266                                 return -XIAEADDR_NAT_MISPLACED;
267                 } else if (xia_is_nat(ty)) {
268                         n = i;
269                         saw_nat = 1;
270                 }
271         }
272         /* n = number of nodes from here. */
273
274         /* Test edges are well formed. */
275         for (i = 0; i < n; i++) {
276                 gint rc;
277                 rc = xia_are_edges_valid(&addr->s_row[i], i, n, &visited);
278                 if (rc)
279                         return rc;
280         }
281
282         if (n >= 1) {
283                 /* Test entry point is present. Notice that it's just a
284                  * friendlier error since it's also XIAEADDR_MULTI_COMPONENTS.
285                  */
286                 guint32 all_edges;
287                 all_edges = addr->s_row[n - 1].s_edge.i;
288                 if (all_edges == XIA_EMPTY_EDGES)
289                         return -XIAEADDR_NO_ENTRY;
290
291                 if (visited != ((1U << n) - 1))
292                         return -XIAEADDR_MULTI_COMPONENTS;
293         }
294
295         return n;
296 }
297
298 /*
299  *      Printing addresses out
300  */
301
302 #define INDEX_BASE 36
303
304 static inline gchar
305 edge_to_char(guint8 e)
306 {
307         const gchar *ch_edge = "0123456789abcdefghijklmnopqrstuvwxyz";
308         e &= ~XIA_CHOSEN_EDGE;
309         if (e < INDEX_BASE)
310                 return ch_edge[e];
311         else if (is_empty_edge(e))
312                 return '*';
313         else
314                 return '+';
315 }
316
317 static void
318 add_edges_to_buf(gint valid, wmem_strbuf_t *buf, const guint8 *edges)
319 {
320         gint i;
321         wmem_strbuf_append_c(buf, '-');
322         for (i = 0; i < XIA_OUTDEGREE_MAX; i++) {
323                 if (valid && edges[i] == XIA_EMPTY_EDGE)
324                         return;
325
326                 if (is_edge_chosen(edges[i]))
327                         wmem_strbuf_append_c(buf, '>');
328
329                 wmem_strbuf_append_c(buf, edge_to_char(edges[i]));
330         }
331 }
332
333 static void
334 add_type_to_buf(xid_type_t ty, wmem_strbuf_t *buf)
335 {
336         const gchar *xid_name;
337         gsize buflen = wmem_strbuf_get_len(buf);
338
339         if (XIA_MAX_STRADDR_SIZE - buflen - 1 < MAX_PPAL_NAME_SIZE)
340                 return;
341
342         xid_name = try_val_to_str(ty, xidtype_vals);
343         if (xid_name)
344                 wmem_strbuf_append_printf(buf, "%s-", xid_name);
345         else
346                 wmem_strbuf_append_printf(buf, "0x%x-", ty);
347 }
348
349 static inline void
350 add_id_to_buf(const struct xia_xid *src, wmem_strbuf_t *buf)
351 {
352         wmem_strbuf_append_printf(buf, "%08x%08x%08x%08x%08x",
353                 src->xid_id[0],
354                 src->xid_id[1],
355                 src->xid_id[2],
356                 src->xid_id[3],
357                 src->xid_id[4]);
358 }
359
360 /* xia_ntop - convert an XIA address to a string.
361  * @src can be ill-formed, but xia_ntop won't report an error and will return
362  * a string that approximates that ill-formed address.
363  */
364 static int
365 xia_ntop(const struct xia_addr *src, wmem_strbuf_t *buf)
366 {
367         gint valid, i;
368
369         valid = xia_test_addr(src) >= 1;
370         if (!valid)
371                 wmem_strbuf_append_c(buf, '!');
372
373         for (i = 0; i < XIA_NODES_MAX; i++) {
374                 const struct xia_row *row = &src->s_row[i];
375
376                 if (xia_is_nat(row->s_xid.xid_type))
377                         break;
378
379                 if (i > 0)
380                         wmem_strbuf_append(buf, ":\n");
381
382                 /* Add the type, ID, and edges for this node. */
383                 add_type_to_buf(row->s_xid.xid_type, buf);
384                 add_id_to_buf(&row->s_xid, buf);
385                 add_edges_to_buf(valid, buf, row->s_edge.a);
386         }
387
388         return 0;
389 }
390
391 /*
392  *      Dissection
393  */
394
395 #define XIPH_MIN_LEN            36
396 #define ETHERTYPE_XIP           0xC0DE
397 #define XIA_NEXT_HEADER_DATA    0
398
399 /* Offsets of XIP fields in bytes. */
400 #define XIPH_VERS               0
401 #define XIPH_NXTH               1
402 #define XIPH_PLEN               2
403 #define XIPH_HOPL               4
404 #define XIPH_NDST               5
405 #define XIPH_NSRC               6
406 #define XIPH_LSTN               7
407 #define XIPH_DSTD               8
408
409 static void
410 construct_dag(tvbuff_t *tvb, proto_tree *xip_tree,
411         const gint ett, const gint hf, const gint hf_entry,
412         const guint8 num_nodes, guint8 offset)
413 {
414         proto_tree *dag_tree;
415         proto_item *ti;
416         struct xia_addr dag;
417         wmem_strbuf_t *buf;
418         const gchar *dag_str;
419         guint i, j;
420         guint8 dag_offset = offset;
421
422         ti = proto_tree_add_item(xip_tree, hf, tvb, offset,
423                 num_nodes * XIA_NODE_SIZE, ENC_BIG_ENDIAN);
424
425         buf = wmem_strbuf_sized_new(wmem_packet_scope(),
426                 XIA_MAX_STRADDR_SIZE, XIA_MAX_STRADDR_SIZE);
427
428         dag_tree = proto_item_add_subtree(ti, ett);
429
430         memset(&dag, 0, sizeof(dag));
431         for (i = 0; i < num_nodes; i++) {
432                 struct xia_row *row = &dag.s_row[i];
433
434                 row->s_xid.xid_type = tvb_get_ntohl(tvb, offset);
435                 offset += XIA_TYPE_SIZE;
436
437                 /* Process the ID 32 bits at a time. */
438                 for (j = 0; j < XIA_XID_SIZE / XIA_XID_CHUNK_SIZE; j++) {
439                         row->s_xid.xid_id[j] = tvb_get_ntohl(tvb, offset);
440                         offset += XIA_XID_CHUNK_SIZE;
441                 }
442
443                 /* Need to process the edges byte-by-byte,
444                  * so keep the bytes in network order.
445                  */
446                 tvb_memcpy(tvb, row->s_edge.a, offset, XIA_EDGES_SIZE);
447                 offset += XIA_EDGES_SIZE;
448         }
449
450         xia_ntop(&dag, buf);
451         dag_str = wmem_strbuf_get_str(buf);
452         proto_tree_add_string_format(dag_tree, hf_entry, tvb, dag_offset,
453                 XIA_NODE_SIZE * num_nodes, dag_str, "%s", dag_str);
454 }
455
456 static void
457 display_xip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
458 {
459         proto_tree *xip_tree = NULL;
460
461         proto_item *ti = NULL;
462         proto_item *payload_ti = NULL;
463         proto_item *next_ti = NULL;
464         proto_item *num_ti = NULL;
465
466         tvbuff_t *next_tvb;
467
468         guint16 xiph_len, payload_len;
469         guint8 num_dst_nodes, num_src_nodes, last_node,
470                 next_header, next_header_offset;
471
472         num_dst_nodes = tvb_get_guint8(tvb, XIPH_NDST);
473         num_src_nodes = tvb_get_guint8(tvb, XIPH_NSRC);
474         xiph_len = 8 + (XIA_NODE_SIZE * num_dst_nodes) +
475                 (XIA_NODE_SIZE * num_src_nodes);
476
477         /* Construct protocol tree. */
478         ti = proto_tree_add_item(tree, proto_xip, tvb, 0, xiph_len, ENC_NA);
479         xip_tree = proto_item_add_subtree(ti, ett_xip_tree);
480
481         /* Add XIP version. */
482         proto_tree_add_item(xip_tree, hf_xip_version, tvb,
483                 XIPH_VERS, 1, ENC_BIG_ENDIAN);
484
485         /* Add XIP next header. */
486         next_ti = proto_tree_add_item(xip_tree, hf_xip_next_hdr, tvb,
487                 XIPH_NXTH, 1, ENC_BIG_ENDIAN);
488
489         /* Add XIP payload length. */
490         payload_len = tvb_get_ntohs(tvb, XIPH_PLEN);
491         payload_ti = proto_tree_add_uint_format(xip_tree, hf_xip_payload_len,
492                 tvb, XIPH_PLEN, 2, payload_len, "Payload Length: %u bytes",
493                 payload_len);
494         if (tvb_captured_length_remaining(tvb, xiph_len) != payload_len)
495                 expert_add_info_format(pinfo, payload_ti, &ei_xip_invalid_len,
496                 "Payload length field (%d bytes) does not match actual payload length (%d bytes)",
497                 payload_len, tvb_captured_length_remaining(tvb, xiph_len));
498
499         /* Add XIP hop limit. */
500         proto_tree_add_item(xip_tree, hf_xip_hop_limit, tvb,
501                 XIPH_HOPL, 1, ENC_BIG_ENDIAN);
502
503         /* Add XIP number of destination DAG nodes. */
504         num_ti = proto_tree_add_item(xip_tree, hf_xip_num_dst, tvb,
505                 XIPH_NDST, 1, ENC_BIG_ENDIAN);
506         if (num_dst_nodes > XIA_NODES_MAX) {
507                 expert_add_info_format(pinfo, num_ti, &ei_xip_bad_num_dst,
508                 "The number of destination DAG nodes (%d) must be less than XIA_NODES_MAX (%d)",
509                 num_dst_nodes, XIA_NODES_MAX);
510                 num_dst_nodes = XIA_NODES_MAX;
511         }
512
513         /* Add XIP number of source DAG nodes. */
514         num_ti = proto_tree_add_item(xip_tree, hf_xip_num_src, tvb,
515                 XIPH_NSRC, 1, ENC_BIG_ENDIAN);
516         if (num_src_nodes > XIA_NODES_MAX) {
517                 expert_add_info_format(pinfo, num_ti, &ei_xip_bad_num_src,
518                 "The number of source DAG nodes (%d) must be less than XIA_NODES_MAX (%d)",
519                 num_src_nodes, XIA_NODES_MAX);
520                 num_src_nodes = XIA_NODES_MAX;
521         }
522
523         /* Add XIP last node. */
524         last_node = tvb_get_guint8(tvb, XIPH_LSTN);
525         proto_tree_add_uint_format_value(xip_tree, hf_xip_last_node, tvb,
526                 XIPH_LSTN, 1, last_node, "%d%s", last_node,
527                 last_node == XIA_ENTRY_NODE_INDEX ? " (entry node)" : "");
528
529         /* Construct Destination DAG subtree. */
530         if (num_dst_nodes > 0)
531                 construct_dag(tvb, xip_tree, ett_xip_ddag,
532                         hf_xip_dst_dag, hf_xip_dst_dag_entry,
533                         num_dst_nodes, XIPH_DSTD);
534
535         /* Construct Source DAG subtree. */
536         if (num_src_nodes > 0)
537                 construct_dag(tvb, xip_tree, ett_xip_sdag,
538                         hf_xip_src_dag, hf_xip_src_dag_entry,
539                         num_src_nodes,
540                         XIPH_DSTD + num_dst_nodes * XIA_NODE_SIZE);
541
542         next_header_offset = XIPH_DSTD + XIA_NODE_SIZE *
543                 (num_dst_nodes + num_src_nodes);
544
545         next_header = tvb_get_guint8(tvb, XIPH_NXTH);
546         switch (next_header) {
547         case XIA_NEXT_HEADER_DATA:
548                 next_tvb = tvb_new_subset(tvb, next_header_offset, -1, -1);
549                 call_dissector(data_handle, next_tvb, pinfo, tree);
550                 break;
551         default:
552                 expert_add_info_format(pinfo, next_ti, &ei_xip_next_header,
553                  "Unrecognized next header type: 0x%02x", next_header);
554                 break;
555         }
556 }
557
558 static gint
559 dissect_xip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
560         void *data _U_)
561 {
562         /* Not large enough to be valid XIP packet. */
563         if (tvb_reported_length(tvb) < XIPH_MIN_LEN)
564                 return 0;
565
566         col_set_str(pinfo->cinfo, COL_PROTOCOL, "XIP");
567         col_set_str(pinfo->cinfo, COL_INFO, "XIP Packet");
568
569         display_xip(tvb, pinfo, tree);
570         return tvb_captured_length(tvb);
571 }
572
573 void
574 proto_register_xip(void)
575 {
576         static hf_register_info hf[] = {
577
578                 /* XIP Header. */
579
580                 { &hf_xip_version,
581                 { "Version", "xip.version", FT_UINT8,
582                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
583
584                 { &hf_xip_next_hdr,
585                 { "Next Header", "xip.next_hdr", FT_UINT8,
586                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
587
588                 { &hf_xip_payload_len,
589                 { "Payload Length", "xip.payload_len", FT_UINT16,
590                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
591
592                 { &hf_xip_hop_limit,
593                 { "Hop Limit", "xip.hop_limit", FT_UINT8,
594                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
595
596                 { &hf_xip_num_dst,
597                 { "Number of Destination Nodes", "xip.num_dst", FT_UINT8,
598                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
599
600                 { &hf_xip_num_src,
601                 { "Number of Source Nodes", "xip.num_src", FT_UINT8,
602                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
603
604                 { &hf_xip_last_node,
605                 { "Last Node", "xip.last_node", FT_UINT8,
606                    BASE_DEC, NULL, 0x0, NULL, HFILL }},
607
608                 { &hf_xip_dst_dag,
609                 { "Destination DAG", "xip.dst_dag", FT_NONE,
610                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
611
612                 { &hf_xip_dst_dag_entry,
613                 { "Destination DAG Entry", "xip.dst_dag_entry", FT_STRING,
614                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
615
616                 { &hf_xip_src_dag,
617                 { "Source DAG", "xip.src_dag", FT_NONE,
618                    BASE_NONE, NULL, 0x0, NULL, HFILL }},
619
620                 { &hf_xip_src_dag_entry,
621                 { "Source DAG Entry", "xip.src_dag_entry", FT_STRING,
622                    BASE_NONE, NULL, 0x0, NULL, HFILL }}
623         };
624
625         static gint *ett[] = {
626                 &ett_xip_tree,
627                 &ett_xip_ddag,
628                 &ett_xip_sdag
629         };
630
631         static ei_register_info ei[] = {
632                 { &ei_xip_invalid_len,
633                 { "xip.invalid.len", PI_MALFORMED, PI_ERROR,
634                   "Invalid length", EXPFILL }},
635
636                 { &ei_xip_next_header,
637                 { "xip.next.header", PI_MALFORMED, PI_ERROR,
638                   "Invalid next header", EXPFILL }},
639
640                 { &ei_xip_bad_num_dst,
641                 { "xip.bad_num_dst", PI_MALFORMED, PI_ERROR,
642                   "Invalid number of destination DAG nodes", EXPFILL }},
643
644                 { &ei_xip_bad_num_src,
645                 { "xip.bad_num_src", PI_MALFORMED, PI_ERROR,
646                   "Invalid number of source DAG nodes", EXPFILL }}
647         };
648
649         expert_module_t* expert_xip;
650
651         proto_xip = proto_register_protocol(
652                 "eXpressive Internet Protocol",
653                 "XIP",
654                 "xip");
655
656         new_register_dissector("xip", dissect_xip, proto_xip);
657         proto_register_field_array(proto_xip, hf, array_length(hf));
658         proto_register_subtree_array(ett, array_length(ett));
659
660         expert_xip = expert_register_protocol(proto_xip);
661         expert_register_field_array(expert_xip, ei, array_length(ei));
662 }
663
664 void
665 proto_reg_handoff_xip(void)
666 {
667         dissector_handle_t xip_handle;
668
669         xip_handle = new_create_dissector_handle(dissect_xip, proto_xip);
670         dissector_add_uint("ethertype", ETHERTYPE_XIP, xip_handle);
671
672         data_handle = find_dissector("data");
673 }
674
675 /*
676  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
677  *
678  * Local variables:
679  * c-basic-offset: 8
680  * tab-width: 8
681  * indent-tabs-mode: t
682  * End:
683  *
684  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
685  * :indentSize=8:tabSize=8:noTabs=false:
686  */