59544911bba786171c86a888702bc6b9eb09660f
[obnox/wireshark/wip.git] / packet-mip6.c
1 /* packet-mip6.c
2  *
3  * $Id: packet-mip6.c,v 1.5 2003/11/24 21:42:13 guy Exp $
4  *
5  * Routines for Mobile IPv6 dissection (draft-ietf-mobileip-ipv6-20.txt)
6  * Copyright 2003 Oy L M Ericsson Ab <teemu.rinta-aho@ericsson.fi>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <epan/packet.h>
32
33 #include "ipproto.h"
34 #include "ip_opts.h"
35 #include "packet-mip6.h"
36
37 /* Initialize the protocol and registered header fields */
38 static int proto_mip6 = -1;
39 static int hf_mip6_proto = -1;
40 static int hf_mip6_hlen = -1;
41 static int hf_mip6_mhtype = -1;
42 static int hf_mip6_reserved = -1;
43 static int hf_mip6_csum = -1;
44
45 static int hf_mip6_hoti_cookie = -1;
46
47 static int hf_mip6_coti_cookie = -1;
48
49 static int hf_mip6_hot_nindex = -1;
50 static int hf_mip6_hot_cookie = -1;
51 static int hf_mip6_hot_token = -1;
52
53 static int hf_mip6_cot_nindex = -1;
54 static int hf_mip6_cot_cookie = -1;
55 static int hf_mip6_cot_token = -1;
56
57 static int hf_mip6_bu_seqnr = -1;
58 static int hf_mip6_bu_a_flag = -1;
59 static int hf_mip6_bu_h_flag = -1;
60 static int hf_mip6_bu_l_flag = -1;
61 static int hf_mip6_bu_k_flag = -1;
62 static int hf_mip6_bu_lifetime = -1;
63
64 static int hf_mip6_ba_status = -1;
65 static int hf_mip6_ba_k_flag = -1;
66 static int hf_mip6_ba_seqnr = -1;
67 static int hf_mip6_ba_lifetime = -1;
68
69 static int hf_mip6_be_status = -1;
70 static int hf_mip6_be_haddr = -1;
71
72 static int hf_mip6_bra_interval = -1;
73
74 static int hf_mip6_acoa_acoa = -1;
75
76 static int hf_mip6_ni_hni = -1;
77 static int hf_mip6_ni_cni = -1;
78
79 static int hf_mip6_bad_auth = -1;
80
81 /* Initialize the subtree pointers */
82 static gint ett_mip6 = -1;
83 static gint ett_mip6_opt_padn = -1;
84 static gint ett_mip6_opt_bra = -1;
85 static gint ett_mip6_opt_acoa = -1;
86 static gint ett_mip6_opt_ni = -1;
87 static gint ett_mip6_opt_bad = -1;
88
89 /* Functions to dissect the mobility headers */
90
91 static int
92 dissect_mip6_brr(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
93 {
94     proto_tree *data_tree = NULL;
95     proto_item *ti;
96
97     if (check_col(pinfo->cinfo, COL_INFO))
98         col_set_str(pinfo->cinfo, COL_INFO, "Binding Refresh Request");
99
100     if (mip6_tree) {
101         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
102                                  MIP6_BRR_LEN, "Binding Refresh Request");
103         data_tree = proto_item_add_subtree(ti, ett_mip6);
104     }
105
106     return MIP6_DATA_OFF+MIP6_BRR_LEN;
107 }
108
109 static int
110 dissect_mip6_hoti(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
111 {
112     proto_tree *data_tree = NULL;
113     proto_item *ti;
114
115     if (check_col(pinfo->cinfo, COL_INFO))
116         col_set_str(pinfo->cinfo, COL_INFO, "Home Test Init");
117
118     if (mip6_tree) {
119         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
120                                  MIP6_HOTI_LEN, "Home Test Init");
121         data_tree = proto_item_add_subtree(ti, ett_mip6);
122
123         proto_tree_add_item(data_tree, hf_mip6_hoti_cookie, tvb,
124                             MIP6_HOTI_COOKIE_OFF, MIP6_HOTI_COOKIE_LEN, FALSE);
125     }
126
127     return MIP6_DATA_OFF+MIP6_HOTI_LEN;
128 }
129
130 static int
131 dissect_mip6_coti(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
132 {
133     proto_tree *data_tree = NULL;
134     proto_item *ti;
135
136     if (check_col(pinfo->cinfo, COL_INFO))
137         col_set_str(pinfo->cinfo, COL_INFO, "Care-of Test Init");
138
139     if (mip6_tree) {
140         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
141                                  MIP6_COTI_LEN, "Care-of Test Init");
142         data_tree = proto_item_add_subtree(ti, ett_mip6);
143
144         proto_tree_add_item(data_tree, hf_mip6_coti_cookie, tvb,
145                             MIP6_COTI_COOKIE_OFF, MIP6_COTI_COOKIE_LEN, FALSE);
146     }
147
148     return MIP6_DATA_OFF+MIP6_COTI_LEN;
149 }
150
151 static int
152 dissect_mip6_hot(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
153 {
154     proto_tree *data_tree = NULL;
155     proto_item *ti;
156
157     if (check_col(pinfo->cinfo, COL_INFO))
158         col_set_str(pinfo->cinfo, COL_INFO, "Home Test");
159
160     if (mip6_tree) {
161         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
162                                  MIP6_HOT_LEN, "Home Test");
163         data_tree = proto_item_add_subtree(ti, ett_mip6);
164
165         proto_tree_add_item(data_tree, hf_mip6_hot_nindex, tvb,
166                             MIP6_HOT_INDEX_OFF, MIP6_HOT_INDEX_LEN, FALSE);
167         proto_tree_add_item(data_tree, hf_mip6_hot_cookie, tvb,
168                             MIP6_HOT_COOKIE_OFF, MIP6_HOT_COOKIE_LEN, FALSE);
169         proto_tree_add_item(data_tree, hf_mip6_hot_token, tvb,
170                             MIP6_HOT_TOKEN_OFF, MIP6_HOT_TOKEN_LEN, FALSE);
171     }
172
173     return MIP6_DATA_OFF+MIP6_HOT_LEN;
174 }
175
176 static int
177 dissect_mip6_cot(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
178 {
179     proto_tree *data_tree = NULL;
180     proto_item *ti;
181
182     if (check_col(pinfo->cinfo, COL_INFO))
183         col_set_str(pinfo->cinfo, COL_INFO, "Care-of Test");
184
185     if (mip6_tree) {
186         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
187                                  MIP6_COT_LEN, "Care-of Test");
188         data_tree = proto_item_add_subtree(ti, ett_mip6);
189
190         proto_tree_add_item(data_tree, hf_mip6_cot_nindex, tvb,
191                             MIP6_COT_INDEX_OFF, MIP6_COT_INDEX_LEN, FALSE);
192         proto_tree_add_item(data_tree, hf_mip6_cot_cookie, tvb,
193                             MIP6_COT_COOKIE_OFF, MIP6_COT_COOKIE_LEN, FALSE);
194         proto_tree_add_item(data_tree, hf_mip6_hot_token, tvb,
195                             MIP6_COT_TOKEN_OFF, MIP6_COT_TOKEN_LEN, FALSE);
196     }
197
198     return MIP6_DATA_OFF+MIP6_COT_LEN;
199 }
200
201 static int
202 dissect_mip6_bu(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
203 {
204     proto_tree *data_tree = NULL;
205     proto_item *ti;
206     int lifetime;
207
208     if (check_col(pinfo->cinfo, COL_INFO))
209         col_set_str(pinfo->cinfo, COL_INFO, "Binding Update");
210
211     if (mip6_tree) {
212         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
213                                  MIP6_BU_LEN, "Binding Update");
214         data_tree = proto_item_add_subtree(ti, ett_mip6);
215
216         proto_tree_add_item(data_tree, hf_mip6_bu_seqnr, tvb,
217                             MIP6_BU_SEQNR_OFF, MIP6_BU_SEQNR_LEN, FALSE);
218
219         proto_tree_add_item(data_tree, hf_mip6_bu_a_flag, tvb, 
220                             MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
221         proto_tree_add_item(data_tree, hf_mip6_bu_h_flag, tvb, 
222                             MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
223         proto_tree_add_item(data_tree, hf_mip6_bu_l_flag, tvb, 
224                             MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
225         proto_tree_add_item(data_tree, hf_mip6_bu_k_flag, tvb, 
226                             MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
227
228         lifetime = tvb_get_ntohs(tvb, MIP6_BU_LIFETIME_OFF);
229         proto_tree_add_uint_format(data_tree, hf_mip6_bu_lifetime, tvb,
230                                    MIP6_BU_LIFETIME_OFF, 
231                                    MIP6_BU_LIFETIME_LEN, lifetime,
232                                    "Lifetime: %d (%ld seconds)",
233                                    lifetime, (long)lifetime * 4);
234     }
235
236     return MIP6_DATA_OFF+MIP6_BU_LEN;
237 }
238
239 static int
240 dissect_mip6_ba(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
241 {
242     proto_tree *data_tree = NULL;
243     proto_item *ti;
244     int lifetime;
245
246     if (check_col(pinfo->cinfo, COL_INFO))
247         col_set_str(pinfo->cinfo, COL_INFO, "Binding Acknowledgement");
248
249     if (mip6_tree) {
250         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
251                                  MIP6_BA_LEN, "Binding Acknowledgement");
252         data_tree = proto_item_add_subtree(ti, ett_mip6);
253
254         proto_tree_add_item(data_tree, hf_mip6_ba_status, tvb,
255                             MIP6_BA_STATUS_OFF, MIP6_BA_STATUS_LEN, FALSE);
256         proto_tree_add_item(data_tree, hf_mip6_ba_k_flag, tvb, 
257                             MIP6_BA_FLAGS_OFF, MIP6_BA_FLAGS_LEN, FALSE);
258         proto_tree_add_item(data_tree, hf_mip6_ba_seqnr, tvb,
259                             MIP6_BA_SEQNR_OFF, MIP6_BA_SEQNR_LEN, FALSE);
260         lifetime = tvb_get_ntohs(tvb, MIP6_BA_LIFETIME_OFF);
261         proto_tree_add_uint_format(data_tree, hf_mip6_ba_lifetime, tvb,
262                                    MIP6_BA_LIFETIME_OFF, 
263                                    MIP6_BA_LIFETIME_LEN, lifetime,
264                                    "Lifetime: %d (%ld seconds)",
265                                    lifetime, (long)lifetime * 4);
266     }
267
268     return MIP6_DATA_OFF+MIP6_BA_LEN;
269 }
270
271 static int
272 dissect_mip6_be(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
273 {
274     proto_tree *data_tree = NULL;
275     proto_item *ti;
276     
277     if (check_col(pinfo->cinfo, COL_INFO))
278         col_set_str(pinfo->cinfo, COL_INFO, "Binding Error");
279
280     if (mip6_tree) {
281         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
282                                  MIP6_BE_LEN, "Binding Error");
283         data_tree = proto_item_add_subtree(ti, ett_mip6);
284
285         proto_tree_add_item(data_tree, hf_mip6_be_status, tvb,
286                             MIP6_BE_STATUS_OFF, MIP6_BE_STATUS_LEN, FALSE);
287         proto_tree_add_item(data_tree, hf_mip6_be_haddr, tvb,
288                             MIP6_BE_HOA_OFF, MIP6_BE_HOA_LEN, FALSE);
289     }
290
291     return MIP6_DATA_OFF+MIP6_BE_LEN;
292 }
293
294 static int
295 dissect_mip6_unknown(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
296 {
297     proto_tree *data_tree = NULL;
298     proto_item *ti;
299
300     if (check_col(pinfo->cinfo, COL_INFO))
301         col_set_str(pinfo->cinfo, COL_INFO, "Unknown MH Type");
302
303     if (mip6_tree) {
304         ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
305                                  MIP6_DATA_OFF+1, "Unknown MH Type");
306         data_tree = proto_item_add_subtree(ti, ett_mip6);
307     }
308
309     return MIP6_DATA_OFF+1;
310 }
311
312 /* Functions to dissect the mobility options */
313
314 static void
315 dissect_mip6_opt_padn(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
316                       guint optlen, packet_info *pinfo _U_,
317                       proto_tree *opt_tree)
318 {
319     proto_tree_add_text(opt_tree, tvb, offset, optlen,
320                         "%s: %u bytes", optp->name, optlen);
321 }
322
323 static void
324 dissect_mip6_opt_bra(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
325                      guint optlen, packet_info *pinfo _U_,
326                      proto_tree *opt_tree)
327 {
328     int ri;
329
330     ri = tvb_get_ntohs(tvb, offset + MIP6_BRA_RI_OFF);
331     proto_tree_add_uint_format(opt_tree, hf_mip6_bra_interval, tvb,
332                                offset, optlen,
333                                ri, "Refresh interval: %d (%ld seconds)",
334                                ri, (long)ri * 4);
335 }
336
337 static void
338 dissect_mip6_opt_acoa(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
339                       guint optlen, packet_info *pinfo _U_,
340                       proto_tree *opt_tree)
341 {
342     proto_tree_add_ipv6(opt_tree, hf_mip6_acoa_acoa, tvb,
343                         offset, optlen,
344                         tvb_get_ptr(tvb, offset + MIP6_ACOA_ACOA_OFF, MIP6_ACOA_ACOA_LEN));
345 }
346
347 static void
348 dissect_mip6_opt_ni(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
349                     guint optlen, packet_info *pinfo _U_,
350                     proto_tree *opt_tree)
351 {
352     proto_tree *field_tree = NULL;
353     proto_item *tf;
354
355     tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s", optp->name);
356     field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
357
358     proto_tree_add_item(field_tree, hf_mip6_ni_hni, tvb,
359                         offset + MIP6_NI_HNI_OFF, MIP6_NI_HNI_LEN, FALSE);
360     proto_tree_add_item(field_tree, hf_mip6_ni_cni, tvb,
361                         offset + MIP6_NI_CNI_OFF, MIP6_NI_CNI_LEN, FALSE);
362 }
363
364 static void
365 dissect_mip6_opt_bad(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
366                      guint optlen, packet_info *pinfo _U_,
367                      proto_tree *opt_tree)
368 {
369     proto_tree *field_tree = NULL;
370     proto_item *tf;
371
372     tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s", optp->name);
373     field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
374
375     proto_tree_add_item(field_tree, hf_mip6_bad_auth, tvb,
376                         offset + MIP6_BAD_AUTH_OFF,
377                         optlen - MIP6_BAD_AUTH_OFF, FALSE);
378 }
379
380 static const ip_tcp_opt mip6_opts[] = {
381   {
382     PAD1,
383     "Pad1",
384     NULL,
385     NO_LENGTH,
386     0,
387     NULL,
388   },
389   {
390     PADN,
391     "PadN",
392     &ett_mip6_opt_padn,
393     VARIABLE_LENGTH,
394     0,
395     dissect_mip6_opt_padn
396   },
397   {
398     BRA,
399     "Binding Refresh Advice",
400     &ett_mip6_opt_bra,
401     FIXED_LENGTH,
402     MIP6_BRA_LEN,
403     dissect_mip6_opt_bra
404   },
405   {
406     ACOA,
407     "Alternate Care-of Address",
408     &ett_mip6_opt_acoa,
409     FIXED_LENGTH,
410     MIP6_ACOA_LEN,
411     dissect_mip6_opt_acoa
412   },
413   {
414     NI,
415     "Nonce Indices",
416     &ett_mip6_opt_ni,
417     FIXED_LENGTH,
418     MIP6_NI_LEN,
419     dissect_mip6_opt_ni
420   },
421   {
422     BAD,
423     "Binding Authorization Data",
424     &ett_mip6_opt_bad,
425     VARIABLE_LENGTH,
426     0,
427     dissect_mip6_opt_bad
428   },
429 };
430
431 #define N_MIP6_OPTS     (sizeof mip6_opts / sizeof mip6_opts[0])
432
433 /* Function to dissect mobility options */
434 static int
435 dissect_mip6_options(tvbuff_t *tvb, proto_tree *mip6_tree, int offset, int len,
436                      packet_info *pinfo)
437 {
438     proto_tree *opts_tree = NULL;
439     proto_item *ti;
440
441     if (!mip6_tree)
442         return len;
443
444     ti = proto_tree_add_text(mip6_tree, tvb, offset, len - offset, 
445                              "Mobility Options");
446     opts_tree = proto_item_add_subtree(ti, ett_mip6);
447
448     dissect_ipv6_options(tvb, offset, len,
449        mip6_opts, N_MIP6_OPTS, -1, pinfo, opts_tree);
450
451     return len;
452 }
453
454 /* Function that dissects the whole MIPv6 packet */
455 static void
456 dissect_mip6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
457 {
458     proto_tree *mip6_tree = NULL;
459     proto_item *ti;
460     guint8     type;
461     guint      len, offset = 0, start_offset = offset;
462
463     /* Make entries in Protocol column and Info column on summary display */
464     if (check_col(pinfo->cinfo, COL_PROTOCOL))
465         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MIPv6");
466     if (check_col(pinfo->cinfo, COL_INFO))
467         col_clear(pinfo->cinfo, COL_INFO);
468
469     len = (tvb_get_guint8(tvb, MIP6_HLEN_OFF) + 1) * 8;
470     if (tree) {
471         ti = proto_tree_add_item(tree, proto_mip6, tvb, 0, len, FALSE);
472         mip6_tree = proto_item_add_subtree(ti, ett_mip6);
473
474         /* Process header fields */
475         proto_tree_add_uint_format(mip6_tree, hf_mip6_proto, tvb,
476                                    MIP6_PROTO_OFF, 1,
477                                    tvb_get_guint8(tvb, MIP6_PROTO_OFF),
478                                    "Payload protocol: %s (0x%02x)",
479                                    ipprotostr(
480                                        tvb_get_guint8(tvb, MIP6_PROTO_OFF)), 
481                                    tvb_get_guint8(tvb, MIP6_PROTO_OFF));
482
483         proto_tree_add_uint_format(mip6_tree, hf_mip6_hlen, tvb,
484                                    MIP6_HLEN_OFF, 1,
485                                    tvb_get_guint8(tvb, MIP6_HLEN_OFF),
486                                    "Header length: %u (%u bytes)",
487                                    tvb_get_guint8(tvb, MIP6_HLEN_OFF),
488                                    len);
489
490         proto_tree_add_item(mip6_tree, hf_mip6_mhtype, tvb,
491                             MIP6_TYPE_OFF, 1, FALSE);
492
493         proto_tree_add_item(mip6_tree, hf_mip6_reserved, tvb,
494                             MIP6_RES_OFF, 1, FALSE);
495
496         proto_tree_add_item(mip6_tree, hf_mip6_csum, tvb,
497                             MIP6_CSUM_OFF, 2, FALSE);
498     }
499
500     /* Process mobility header */
501     type = tvb_get_guint8(tvb, MIP6_TYPE_OFF);
502     switch (type) {
503     case BRR:
504         offset = dissect_mip6_brr(tvb, mip6_tree, pinfo);
505         break;
506     case HOTI:
507         offset = dissect_mip6_hoti(tvb, mip6_tree, pinfo);
508         break;
509     case COTI:
510         offset = dissect_mip6_coti(tvb, mip6_tree, pinfo);
511         break;
512     case HOT:
513         offset = dissect_mip6_hot(tvb, mip6_tree, pinfo);
514         break;
515     case COT:
516         offset = dissect_mip6_cot(tvb, mip6_tree, pinfo);
517         break;
518     case BU:
519         offset = dissect_mip6_bu(tvb, mip6_tree, pinfo);
520         break;
521     case BA:
522         offset = dissect_mip6_ba(tvb, mip6_tree, pinfo);
523         break;
524     case BE:
525         offset = dissect_mip6_be(tvb, mip6_tree, pinfo);
526         break;
527     default:
528         dissect_mip6_unknown(tvb, mip6_tree, pinfo);
529         offset = len;
530         break;
531     }
532
533     /* Process mobility options */
534     if (offset < len) {
535         if (len < (offset - start_offset)) {
536             proto_tree_add_text(tree, tvb, 0, 0, "Bogus header length");
537             return;
538         }
539         len -= (offset - start_offset);
540         dissect_mip6_options(tvb, mip6_tree, offset, len, pinfo);
541     }
542 }
543
544 /* Register the protocol with Ethereal */
545 void 
546 proto_register_mip6(void)
547 {    
548     /* Setup list of header fields */
549     static hf_register_info hf[] = {
550
551         { &hf_mip6_proto,        { "Payload protocol", "mip6.proto",
552                                    FT_UINT8, BASE_DEC, NULL, 0,
553                                    "Payload protocol", HFILL }},
554         { &hf_mip6_hlen,         { "Header length", "mip6.hlen",
555                                    FT_UINT8, BASE_DEC, NULL, 0,
556                                    "Header length", HFILL }},
557         { &hf_mip6_mhtype,       { "Mobility Header Type", "mip6.mhtype",
558                                    FT_UINT8, BASE_DEC, VALS(mip6_mh_types), 0,
559                                    "Mobility Header Type", HFILL }},
560         { &hf_mip6_reserved,     { "Reserved", "mip6.reserved",
561                                    FT_UINT8, BASE_HEX, NULL, 0,
562                                    "Reserved", HFILL }},
563         { &hf_mip6_csum,         { "Checksum", "mip6.csum",
564                                    FT_UINT16, BASE_HEX, NULL, 0,
565                                    "Header Checksum", HFILL }},
566         
567         { &hf_mip6_hoti_cookie,  { "Home Init Cookie", "mip6.hoti.cookie",
568                                    FT_UINT64, BASE_HEX, NULL, 0,
569                                    "Home Init Cookie", HFILL }},
570         
571         { &hf_mip6_coti_cookie,  { "Care-of Init Cookie", "mip6.coti.cookie",
572                                    FT_UINT64, BASE_HEX, NULL, 0,
573                                    "Care-of Init Cookie", HFILL }},
574         
575         { &hf_mip6_hot_nindex,   { "Home Nonce Index", "mip6.hot.nindex",
576                                    FT_UINT16, BASE_DEC, NULL, 0,
577                                    "Home Nonce Index", HFILL }},
578         { &hf_mip6_hot_cookie,   { "Home Init Cookie", "mip6.hot.cookie",
579                                    FT_UINT64, BASE_HEX, NULL, 0,
580                                    "Home Init Cookie", HFILL }},
581         { &hf_mip6_hot_token,    { "Home Keygen Token", "mip6.hot.token",
582                                    FT_UINT64, BASE_HEX, NULL, 0,
583                                    "Home Keygen Token", HFILL }},
584         
585         { &hf_mip6_cot_nindex,   { "Care-of Nonce Index", "mip6.cot.nindex",
586                                    FT_UINT16, BASE_DEC, NULL, 0,
587                                    "Care-of Nonce Index", HFILL }},
588         { &hf_mip6_cot_cookie,   { "Care-of Init Cookie", "mip6.cot.cookie",
589                                    FT_UINT64, BASE_HEX, NULL, 0,
590                                    "Care-of Init Cookie", HFILL }},
591         { &hf_mip6_cot_token,    { "Care-of Keygen Token", "mip6.cot.token",
592                                    FT_UINT64, BASE_HEX, NULL, 0,
593                                    "Care-of Keygen Token", HFILL }},
594         
595         { &hf_mip6_bu_seqnr,     { "Sequence number", "mip6.bu.seqnr",
596                                    FT_UINT16, BASE_DEC, NULL, 0,
597                                    "Sequence number", HFILL }},
598         { &hf_mip6_bu_a_flag,    { "Acknowledge (A) flag", "mip6.bu.a_flag",
599                                    FT_BOOLEAN, 8, TFS(&mip6_bu_a_flag_value),
600                                    0x80, "Acknowledge (A) flag", HFILL }},
601         { &hf_mip6_bu_h_flag,    { "Home Registration (H) flag", 
602                                    "mip6.bu.h_flag",
603                                    FT_BOOLEAN, 8, TFS(&mip6_bu_h_flag_value),
604                                    0x40, "Home Registration (H) flag", HFILL }},
605         { &hf_mip6_bu_l_flag,    { "Link-Local Compatibility (L) flag", 
606                                    "mip6.bu.l_flag",
607                                    FT_BOOLEAN, 8, TFS(&mip6_bu_l_flag_value),
608                                    0x20, "Home Registration (H) flag", HFILL }},
609         { &hf_mip6_bu_k_flag,    { "Key Management Compatibility (K) flag", 
610                                    "mip6.bu.k_flag",
611                                    FT_BOOLEAN, 8, TFS(&mip6_bu_k_flag_value),
612                                    0x10, "Key Management Compatibility (K) flag", 
613                                    HFILL }},
614         { &hf_mip6_bu_lifetime,  { "Lifetime", "mip6.bu.lifetime",
615                                    FT_UINT16, BASE_DEC, NULL, 0,
616                                    "Lifetime", HFILL }},
617         
618         { &hf_mip6_ba_status,    { "Status", "mip6.ba.status",
619                                    FT_UINT8, BASE_DEC,
620                                    VALS(&mip6_ba_status_value), 0,
621                                    "Binding Acknowledgement status", HFILL }},
622         { &hf_mip6_ba_k_flag,    { "Key Management Compatibility (K) flag", 
623                                    "mip6.ba.k_flag",
624                                    FT_BOOLEAN, 8, TFS(&mip6_bu_k_flag_value),
625                                    0x80, "Key Management Compatibility (K) flag", 
626                                    HFILL }},
627         { &hf_mip6_ba_seqnr,     { "Sequence number", "mip6.ba.seqnr",
628                                    FT_UINT16, BASE_DEC, NULL, 0,
629                                    "Sequence number", HFILL }},
630         { &hf_mip6_ba_lifetime,  { "Lifetime", "mip6.ba.lifetime",
631                                    FT_UINT16, BASE_DEC, NULL, 0,
632                                    "Lifetime", HFILL }},
633         
634         { &hf_mip6_be_status,    { "Status", "mip6.be.status",
635                                    FT_UINT8, BASE_DEC,
636                                    VALS(&mip6_be_status_value), 0,
637                                    "Binding Error status", HFILL }},
638         { &hf_mip6_be_haddr,     { "Home Address", "mip6.be.haddr",
639                                    FT_IPv6, BASE_HEX, NULL, 0,
640                                    "Home Address", HFILL }},
641         
642         { &hf_mip6_bra_interval, { "Refresh interval", "mip6.bra.interval",
643                                    FT_UINT16, BASE_DEC, NULL, 0,
644                                    "Refresh interval", HFILL }},
645
646         { &hf_mip6_acoa_acoa,    { "Alternate care-of address", "mip6.acoa.acoa",
647                                    FT_IPv6, BASE_HEX, NULL, 0,
648                                    "Alternate Care-of address", HFILL }},
649         
650         { &hf_mip6_ni_hni,       { "Home nonce index", "mip6.ni.hni",
651                                    FT_UINT16, BASE_DEC, NULL, 0,
652                                    "Home nonce index", HFILL }},
653         { &hf_mip6_ni_cni,       { "Care-of nonce index", "mip6.ni.cni",
654                                    FT_UINT16, BASE_DEC, NULL, 0,
655                                    "Care-of nonce index", HFILL }},
656
657         { &hf_mip6_bad_auth,     { "Authenticator", "mip6.bad.auth",
658                                    FT_BYTES, BASE_HEX, NULL, 0,
659                                    "Care-of nonce index", HFILL }}
660     };
661
662     /* Setup protocol subtree array */
663     static gint *ett[] = {
664         &ett_mip6,
665         &ett_mip6_opt_padn,
666         &ett_mip6_opt_bra,
667         &ett_mip6_opt_acoa,
668         &ett_mip6_opt_ni,
669         &ett_mip6_opt_bad,
670     };
671     
672     /* Register the protocol name and description */
673     proto_mip6 = proto_register_protocol("Mobile IPv6", "MIPv6", "mipv6");
674     
675     /* Register the dissector by name */
676     /* register_dissector("mipv6", dissect_mip6, proto_mip6); */
677     
678     /* Required function calls to register the header fields and subtrees used */
679     proto_register_field_array(proto_mip6, hf, array_length(hf));
680     proto_register_subtree_array(ett, array_length(ett));
681 };
682
683 void
684 proto_reg_handoff_mip6(void)
685 {
686     dissector_handle_t mip6_handle;
687     
688     /* mip6_handle = find_dissector("mipv6"); */
689     mip6_handle = create_dissector_handle(dissect_mip6, proto_mip6);
690     dissector_add("ip.proto", IP_PROTO_MIPV6_OLD, mip6_handle);
691     dissector_add("ip.proto", IP_PROTO_MIPV6, mip6_handle);
692 }