From Didier Gautheron:
[obnox/wireshark/wip.git] / epan / dissectors / packet-mip.c
1 /* packet-mip.c
2  * Routines for Mobile IP dissection
3  * Copyright 2000, Stefan Raab <sraab@cisco.com>
4  * Copyright 2007, Ville Nuorvala <Ville.Nuorvala@secgo.com>
5  * Copyright 2009, Ohuchi Munenori <ohuchi_at_iij.ad.jp>
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include <string.h>
36 #include <glib.h>
37 #include <time.h>
38
39 #include <epan/packet.h>
40 #include "packet-ntp.h"
41
42 /* Initialize the protocol and registered fields */
43 static int proto_mip = -1;
44 static int hf_mip_type = -1;
45 static int hf_mip_flags = -1;
46 static int hf_mip_s = -1;
47 static int hf_mip_b = -1;
48 static int hf_mip_d = -1;
49 static int hf_mip_m = -1;
50 static int hf_mip_g = -1;
51 static int hf_mip_v = -1;
52 static int hf_mip_t = -1;
53 static int hf_mip_x = -1;
54 static int hf_mip_code = -1;
55 static int hf_mip_life = -1;
56 static int hf_mip_homeaddr = -1;
57 static int hf_mip_haaddr = -1;
58 static int hf_mip_coa = -1;
59 static int hf_mip_ident = -1;
60 static int hf_mip_ext_type = -1;
61 static int hf_mip_gaext_stype = -1;
62 static int hf_mip_ext_len = -1;
63 static int hf_mip_ext = -1;
64 static int hf_mip_aext_spi = -1;
65 static int hf_mip_aext_auth = -1;
66 static int hf_mip_next_nai = -1;
67 static int hf_mip_rext_flags = -1;
68 static int hf_mip_rext_i = -1;
69 static int hf_mip_rext_reserved = -1;
70 static int hf_mip_rext_tstamp = -1;
71 static int hf_mip_rev_reserved = -1;
72 static int hf_mip_rev_a = -1;
73 static int hf_mip_rev_i = -1;
74 static int hf_mip_rev_reserved2 = -1;
75 static int hf_mip_ack_reserved = -1;
76 static int hf_mip_ack_i = -1;
77 static int hf_mip_ack_reserved2 = -1;
78 static int hf_mip_hda = -1;
79 static int hf_mip_fda = -1;
80 static int hf_mip_revid = -1;
81 static int hf_mip_dhaext_stype = -1;
82 static int hf_mip_dhaext_addr = -1;
83 static int hf_mip_mstrext_stype = -1;
84 static int hf_mip_mstrext_text = -1;
85 static int hf_mip_nattt_nexthdr = -1;
86 static int hf_mip_nattt_reserved = -1;
87 static int hf_mip_utrqext_stype = -1;
88 static int hf_mip_utrqext_reserved1 = -1;
89 static int hf_mip_utrqext_flags = -1;
90 static int hf_mip_utrqext_f = -1;
91 static int hf_mip_utrqext_r = -1;
92 static int hf_mip_utrqext_reserved2 = -1;
93 static int hf_mip_utrqext_encap_type = -1;
94 static int hf_mip_utrqext_reserved3 = -1;
95 static int hf_mip_utrpext_stype = -1;
96 static int hf_mip_utrpext_code = -1;
97 static int hf_mip_utrpext_flags = -1;
98 static int hf_mip_utrpext_f = -1;
99 static int hf_mip_utrpext_reserved = -1;
100 static int hf_mip_utrpext_keepalive = -1;
101 static int hf_mip_pmipv4nonskipext_stype = -1;
102 static int hf_mip_pmipv4nonskipext_pernodeauthmethod = -1;
103 static int hf_mip_pmipv4skipext_stype = -1;
104 static int hf_mip_pmipv4skipext_interfaceid = -1;
105 static int hf_mip_pmipv4skipext_deviceid_type = -1;
106 static int hf_mip_pmipv4skipext_deviceid_id = -1;
107 static int hf_mip_pmipv4skipext_subscriberid_type = -1;
108 static int hf_mip_pmipv4skipext_subscriberid_id = -1;
109 static int hf_mip_pmipv4skipext_accesstechnology_type = -1;
110
111 /* Initialize the subtree pointers */
112 static gint ett_mip = -1;
113 static gint ett_mip_flags = -1;
114 static gint ett_mip_ext = -1;
115 static gint ett_mip_exts = -1;
116 static gint ett_mip_pmipv4_ext = -1;
117
118 /* Port used for Mobile IP */
119 #define UDP_PORT_MIP    434
120
121 typedef enum {
122     REGISTRATION_REQUEST = 1,
123     REGISTRATION_REPLY = 3,
124     NATT_TUNNEL_DATA = 4,
125     REGISTRATION_REVOCATION = 7,
126     REGISTRATION_REVOCATION_ACKNOWLEDGEMENT = 15,
127     EXPERIMENTAL_MESSAGE = 255
128 } mipMessageTypes;
129
130 static const value_string mip_types[] = {
131   {REGISTRATION_REQUEST, "Registration Request"},
132   {REGISTRATION_REPLY,   "Registration Reply"},
133   {NATT_TUNNEL_DATA,   "NAT Traversal Tunnel Data"},
134   {REGISTRATION_REVOCATION, "Registration Revocation"},
135   {REGISTRATION_REVOCATION_ACKNOWLEDGEMENT, "Registration Revocation Acknowledgement"},
136   {EXPERIMENTAL_MESSAGE, "Message for Experimental Use"},
137   {0, NULL}
138 };
139
140 static const value_string mip_reply_codes[]= {
141   {0, "Reg Accepted"},
142   {1, "Reg Accepted, but Simultaneous Bindings Unsupported"},
143   {64, "Reg Deny (FA)- Unspecified Reason"},
144   {65, "Reg Deny (FA)- Administratively Prohibited"},
145   {66, "Reg Deny (FA)- Insufficient Resources"},
146   {67, "Reg Deny (FA)- MN Failed Authentication"},
147   {68, "Reg Deny (FA)- HA Failed Authentication"},
148   {69, "Reg Deny (FA)- Requested Lifetime too Long"},
149   {70, "Reg Deny (FA)- Poorly Formed Request"},
150   {71, "Reg Deny (FA)- Poorly Formed Reply"},
151   {72, "Reg Deny (FA)- Requested Encapsulation Unavailable"},
152   {73, "Reg Deny (FA)- VJ Compression Unavailable"},
153   {74, "Reg Deny (FA)- Requested Reverse Tunnel Unavailable"},
154   {75, "Reg Deny (FA)- Reverse Tunnel Is Mandatory and 'T' Bit Not Set"},
155   {76, "Reg Deny (FA)- Mobile Node Too Distant"},
156   {77, "Reg Deny (FA)- Invalid Care-of Address"},
157   {78, "Reg Deny (FA)- Registration Timeout"},
158   {79, "Reg Deny (FA)- Delivery Style Not Supported"},
159   {80, "Reg Deny (FA)- Home Network Unreachable"},
160   {81, "Reg Deny (FA)- HA Host Unreachable"},
161   {82, "Reg Deny (FA)- HA Port Unreachable"},
162   {88, "Reg Deny (FA)- HA Unreachable"},
163   {89, "Reg Deny (FA)- Vendor-specific Reason"},
164   {90, "Reg Deny (FA)- Non-zero HA Address Required"},
165   {96, "Reg Deny (FA)(NAI) - Non-zero Home Address Required"},
166   {97, "Reg Deny (FA)(NAI) - Missing NAI"},
167   {98, "Reg Deny (FA)(NAI) - Missing Home Agent"},
168   {99, "Reg Deny (FA)(NAI) - Missing Home Address"},
169   {100, "Reg Deny (FA)- Unable to Interpret CVSE Sent by MN"},
170   {101, "Reg Deny (FA)- Unable to Interpret CVSE Sent by HA"},
171   {104, "Reg Deny (FA)- Unknown Challenge"},
172   {105, "Reg Deny (FA)- Missing Challenge"},
173   {106, "Reg Deny (FA)- Stale Challenge"},
174   {107, "Reg Deny (FA)- Missing MN-FA Key Generation Nonce Reply Extension"},
175   {108, "Reg Deny (FA)- MN Failed AAA Authentication"},
176   {109, "Reg Deny (FA)- HA Sent Wrong Challenge in Reply"},
177   {127, "Reg Deny (FA)- Error Code for Experimental Use"},
178   {128, "Reg Deny (HA)- Unspecified"},
179   {129, "Reg Deny (HA)- Administratively Prohibited"},
180   {130, "Reg Deny (HA)- Insufficient Resources"},
181   {131, "Reg Deny (HA)- MN Failed Authentication"},
182   {132, "Reg Deny (HA)- FA Failed Authentication"},
183   {133, "Reg Deny (HA)- Registration ID Mismatch"},
184   {134, "Reg Deny (HA)- Poorly Formed Request"},
185   {135, "Reg Deny (HA)- Too Many Simultaneous Bindings"},
186   {136, "Reg Deny (HA)- Unknown HA Address"},
187   {137, "Reg Deny (HA)- Requested Reverse Tunnel Unavailable"},
188   {138, "Reg Deny (HA)- Reverse Tunnel Is Mandatory and 'T' Bit Not Set"},
189   {139, "Reg Deny (HA)- Requested Encapsulation Unavailable"},
190   {140, "Reg Deny (HA)- Unable to Interpret CVSE Sent by MN"},
191   {141, "Reg Deny (HA)- Unable to Interpret CVSE Sent by FA"},
192   {142, "Reg Deny (HA)- UDP Encapsulation Unavailable"},
193   {143, "Reg Deny (HA)- Register with Redirected HA"},
194   {144, "Reg Deny (HA)- MN Failed AAA Authentication"},
195   {149, "Reg Deny (HA)- PMIP_UNSUPPORTED"},               /* draft-leung-mip4-proxy-mode */
196   {150, "Reg Deny (HA)- PMIP_DISALLOWED"},                /* draft-leung-mip4-proxy-mode */
197   {192, "Reg Deny (HA)- Error Code for Experimental Use"},
198   {0, NULL}
199 };
200
201 static const value_string mip_nattt_nexthdr[]= {
202   {4, "IP Header"},
203   {47, "GRE Header"},
204   {55, "Minimal IP Encapsulation Header"},
205   {0, NULL}
206 };
207
208 typedef enum {
209   MH_AUTH_EXT = 32,
210   MF_AUTH_EXT = 33,
211   FH_AUTH_EXT = 34,
212   GEN_AUTH_EXT = 36,      /* RFC 3012 */
213   OLD_CVSE_EXT = 37,      /* RFC 3115 */
214   CVSE_EXT = 38,          /* RFC 3115 */
215   UDP_TUN_REP_EXT = 44,   /* RFC 3519 */
216   PMIPv4_NON_SKIP_EXT = 47,  /* draft-leung-mip4-proxy-mode */
217   MN_NAI_EXT = 131,       /* RFC 2794 */
218   MF_CHALLENGE_EXT = 132, /* RFC 3012 */
219   OLD_NVSE_EXT = 133,     /* RFC 3115 */
220   NVSE_EXT = 134,         /* RFC 3115 */
221   REV_SUPP_EXT = 137,     /* RFC 3543 */
222   DYN_HA_EXT = 139,       /* RFC 4433 */
223   UDP_TUN_REQ_EXT = 144,  /* RFC 3519 */
224   MSG_STR_EXT = 145,
225   PMIPv4_SKIP_EXT = 147,  /* draft-leung-mip4-proxy-mode */
226   SKIP_EXP_EXT = 255      /* RFC 4064 */
227 } MIP_EXTS;
228
229 static const value_string mip_ext_types[]= {
230   {MH_AUTH_EXT, "Mobile-Home Authentication Extension"},
231   {MF_AUTH_EXT, "Mobile-Foreign Authentication Extension"},
232   {FH_AUTH_EXT, "Foreign-Home Authentication Extension"},
233   {GEN_AUTH_EXT, "Generalized Mobile-IP Authentication Extension"},
234   {OLD_CVSE_EXT, "Critical Vendor/Organization Specific Extension"},
235   {CVSE_EXT, "Critical Vendor/Organization Specific Extension"},
236   {UDP_TUN_REP_EXT, "UDP Tunnel Reply Extension"},
237   {PMIPv4_NON_SKIP_EXT, "Proxy Mobile IPv4 Non-skippable Extension"},
238   {MN_NAI_EXT,  "Mobile Node NAI Extension"},
239   {MF_CHALLENGE_EXT, "MN-FA Challenge Extension"},
240   {OLD_NVSE_EXT, "Normal Vendor/Organization Specific Extension"},
241   {NVSE_EXT, "Normal Vendor/Organization Specific Extension"},
242   {REV_SUPP_EXT, "Revocation Support Extension"},
243   {DYN_HA_EXT, "Dynamic HA Extension"},
244   {UDP_TUN_REQ_EXT, "UDP Tunnel Request Extension"},
245   {MSG_STR_EXT, "Message String Extension"},
246   {PMIPv4_SKIP_EXT, "Proxy Mobile IPv4 Skippable Extension"},
247   {SKIP_EXP_EXT, "Skippable Extension for Experimental use"},
248   {0, NULL}
249 };
250
251 static const value_string mip_gaext_stypes[]= {
252   {1, "MN AAA Extension"},
253   {0, NULL}
254 };
255
256 static const value_string mip_dhaext_stypes[]= {
257   {1, "Requested HA Extension"},
258   {2, "Redirected HA Extension"},
259   {0, NULL}
260 };
261
262 static const value_string mip_mstrext_stypes[]= {
263   {1, "HA Extension"},
264   {2, "FA Extension"},
265   {0, NULL}
266 };
267
268 static const value_string mip_utrqext_stypes[]= {
269   {0, ""},
270   {0, NULL}
271 };
272
273 static const value_string mip_utrqext_encap_types[]= {
274   {4, "IP Header"},
275   {47, "GRE Header"},
276   {55, "Minimal IP Encapsulation Header"},
277   {0, NULL}
278 };
279
280 static const value_string mip_utrpext_stypes[]= {
281   {0, ""},
282   {0, NULL}
283 };
284
285 static const value_string mip_utrpext_codes[]= {
286   {0, "Will do Tunneling"},
287   {64, "Tunneling Declined, Reason Unspecified"},
288   {0, NULL}
289 };
290
291 static const value_string mip_pmipv4nonskipext_stypes[]= {
292   {0, "Unknown"},
293   {1, "Per-Node Authentication Method"},
294   {0, NULL}
295 };
296
297 static const value_string mip_pmipv4nonskipext_pernodeauthmethod_types[]= {
298   {0, "Reserved"},
299   {1, "FA-HA Authentication"},
300   {2, "IPSec Authentication"},
301   {0, NULL}
302 };
303
304 #define PMIPv4_SKIPEXT_STYPE_INTERFACE_ID       (1)
305 #define PMIPv4_SKIPEXT_STYPE_DEVICE_ID          (2)
306 #define PMIPv4_SKIPEXT_STYPE_SUBSCRIBER_ID      (3)
307 #define PMIPv4_SKIPEXT_STYPE_ACCESS_TECHNOLOGY  (4)
308 static const value_string mip_pmipv4skipext_stypes[]= {
309   {0, "Unknown"},
310   {PMIPv4_SKIPEXT_STYPE_INTERFACE_ID, "Interface ID"},
311   {PMIPv4_SKIPEXT_STYPE_DEVICE_ID, "Device ID"},
312   {PMIPv4_SKIPEXT_STYPE_SUBSCRIBER_ID, "Subscriber ID"},
313   {PMIPv4_SKIPEXT_STYPE_ACCESS_TECHNOLOGY, "Access Technology Type"},
314   {0, NULL}
315 };
316
317 static const value_string mip_pmipv4skipext_deviceid_types[]= {
318   {0, "Reserved"},
319   {1, "Ethernet MAC address"},
320   {2, "Mobile Equipment Identifier (MEID)"},
321   {3, "International Mobile Equipment Identity (IMEI)"},
322   {4, "Electronic Serial Number (ESN)"},
323   {0, NULL}
324 };
325
326 static const value_string mip_pmipv4skipext_subscriberid_types[]= {
327   {0, "Reserved"},
328   {1, "International Mobile Subscriber Identity (IMSI)"},
329   {0, NULL}
330 };
331
332 static const value_string mip_pmipv4skipext_accesstechnology_types[]= {
333   {0, "Reserved"},
334   {1, "802.3"},
335   {2, "802.11a/b/g"},
336   {3, "802.16e"},
337   {4, "802.16m"},
338   {5, "3GPP EUTRAN/LTE"},
339   {6, "3GPP UTRAN/GERAN"},
340   {7, "3GPP2 1xRTT/HRPD"},
341   {8, "3GPP2 UMB"},
342   {0, NULL}
343 };
344
345 static dissector_handle_t ip_handle;
346
347 /* Code to dissect extensions */
348 static void
349 dissect_mip_extensions( tvbuff_t *tvb, int offset, proto_tree *tree)
350 {
351   proto_item   *ti;
352   proto_tree   *exts_tree=NULL;
353   proto_tree   *ext_tree;
354   proto_tree   *tf;
355   proto_tree   *ext_flags_tree;
356   proto_tree   *tp;
357   proto_tree   *pmipv4_tree;
358   gint          ext_len;
359   guint8        ext_type;
360   guint8        ext_subtype=0;
361   guint8        pmipv4skipext_type;
362   guint16       flags;
363   gint          hdrLen;
364
365   /* None of this really matters if we don't have a tree */
366   if (!tree) return;
367
368   /* Add our tree, if we have extensions */
369   ti = proto_tree_add_text(tree, tvb, offset, -1, "Extensions");
370   exts_tree = proto_item_add_subtree(ti, ett_mip_exts);
371
372   /* And, handle each extension */
373   while (tvb_reported_length_remaining(tvb, offset) > 0) {
374
375         /* Get our extension info */
376         ext_type = tvb_get_guint8(tvb, offset);
377         if (ext_type == GEN_AUTH_EXT || ext_type == PMIPv4_NON_SKIP_EXT) {
378           /*
379            * Very nasty . . breaks normal extensions, since the length is
380            * in the wrong place :(
381            */
382           ext_subtype = tvb_get_guint8(tvb, offset + 1);
383           ext_len = tvb_get_ntohs(tvb, offset + 2);
384           hdrLen = 4;
385         } else {
386           ext_len = tvb_get_guint8(tvb, offset + 1);
387           hdrLen = 2;
388         }
389
390         ti = proto_tree_add_text(exts_tree, tvb, offset, ext_len + hdrLen,
391                                  "Extension: %s",
392                                  val_to_str(ext_type, mip_ext_types,
393                                             "Unknown Extension %u"));
394         ext_tree = proto_item_add_subtree(ti, ett_mip_ext);
395
396         proto_tree_add_item(ext_tree, hf_mip_ext_type, tvb, offset, 1, ext_type);
397         offset++;
398 #if 0 /* FIXME: This test doesn't make sense: t != a1 || t != a2 is true if a1 != a2 */
399         if (ext_type != GEN_AUTH_EXT || ext_type != PMIPv4_NON_SKIP_EXT) {
400 #endif
401           /* Another nasty hack since GEN_AUTH_EXT and PMIPv4_NON_SKIP_EXT broke everything */
402           proto_tree_add_uint(ext_tree, hf_mip_ext_len, tvb, offset, 1, ext_len);
403           offset++;
404 #if 0
405         }
406 #endif
407
408         switch (ext_type) {
409         case MH_AUTH_EXT:
410         case MF_AUTH_EXT:
411         case FH_AUTH_EXT:
412           /* All these extensions look the same.  4 byte SPI followed by a key */
413           proto_tree_add_item(ext_tree, hf_mip_aext_spi, tvb, offset, 4, FALSE);
414           proto_tree_add_item(ext_tree, hf_mip_aext_auth, tvb, offset+4, ext_len-4,
415                                                   FALSE);
416           break;
417         case MN_NAI_EXT:
418           proto_tree_add_item(ext_tree, hf_mip_next_nai, tvb, offset,
419                                                   ext_len, FALSE);
420           break;
421
422         case GEN_AUTH_EXT:      /* RFC 3012 */
423           /*
424            * Very nasty . . breaks normal extensions, since the length is
425            * in the wrong place :(
426            */
427           proto_tree_add_uint(ext_tree, hf_mip_gaext_stype, tvb, offset, 1, ext_subtype);
428           offset++;
429           proto_tree_add_uint(ext_tree, hf_mip_ext_len, tvb, offset, 2, ext_len);
430           offset+=2;
431           /* SPI */
432           proto_tree_add_item(ext_tree, hf_mip_aext_spi, tvb, offset, 4, FALSE);
433           /* Key */
434           proto_tree_add_item(ext_tree, hf_mip_aext_auth, tvb, offset + 4,
435                                                   ext_len - 4, FALSE);
436
437           break;
438         case REV_SUPP_EXT:      /* RFC 3543 */
439           /* flags */
440           flags = tvb_get_ntohs(tvb, offset);
441           tf = proto_tree_add_uint(ext_tree, hf_mip_rext_flags, tvb, offset, 2, flags);
442           ext_flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
443           proto_tree_add_boolean(ext_flags_tree, hf_mip_rext_i, tvb, offset, 2, flags);
444           
445           /* reserved */
446           proto_tree_add_uint(ext_flags_tree, hf_mip_rext_reserved, tvb, offset, 2, flags);
447           /* registration revocation timestamp */
448           proto_tree_add_item(ext_tree, hf_mip_rext_tstamp, tvb, offset + 2, 4, FALSE);
449           break;
450         case DYN_HA_EXT:      /* RFC 4433 */
451           /* subtype */
452           proto_tree_add_item(ext_tree, hf_mip_dhaext_stype, tvb, offset, 1, FALSE);
453           /* Home Agent */
454           proto_tree_add_item(ext_tree, hf_mip_dhaext_addr, tvb, offset + 1, 4, FALSE);
455           break;
456         case MSG_STR_EXT:
457           /* sub-type */
458           proto_tree_add_item(ext_tree, hf_mip_mstrext_stype, tvb, offset, 1, FALSE);
459
460           /* text */
461           proto_tree_add_item(ext_tree, hf_mip_mstrext_text, tvb, offset + 1, ext_len-1, FALSE);
462           break;
463         case UDP_TUN_REQ_EXT:   /* RFC 3519 */
464           /* sub-type */
465           proto_tree_add_item(ext_tree, hf_mip_utrqext_stype, tvb, offset, 1, FALSE);
466
467           /* reserved 1 */
468           proto_tree_add_item(ext_tree, hf_mip_utrqext_reserved1, tvb, offset + 1, 1, FALSE);     
469
470           /* flags */
471           flags = tvb_get_guint8(tvb, offset + 2);
472           tf = proto_tree_add_uint(ext_tree, hf_mip_utrqext_flags, tvb, offset + 2, 1, flags);
473           ext_flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
474           proto_tree_add_boolean(ext_flags_tree, hf_mip_utrqext_f, tvb, offset + 2, 1, flags);
475           proto_tree_add_boolean(ext_flags_tree, hf_mip_utrqext_r, tvb, offset + 2, 1, flags);
476
477           /* reserved 2 */
478           proto_tree_add_uint(ext_flags_tree, hf_mip_utrqext_reserved2, tvb, offset + 2, 1, flags);       
479           /* encapsulation */
480           proto_tree_add_item(ext_tree, hf_mip_utrqext_encap_type, tvb, offset + 3, 1, FALSE);
481
482           /* reserved 3 */
483           proto_tree_add_item(ext_tree, hf_mip_utrqext_reserved3, tvb, offset + 4, 2, FALSE);     
484           break;
485         case UDP_TUN_REP_EXT:   /* RFC 3519 */
486           /* sub-type */
487           proto_tree_add_item(ext_tree, hf_mip_utrpext_stype, tvb, offset, 1, FALSE);
488
489           /* code */
490           proto_tree_add_item(ext_tree, hf_mip_utrpext_code, tvb, offset + 1, 1, FALSE);          
491
492           /* flags */
493           flags = tvb_get_ntohs(tvb, offset+2);
494           tf = proto_tree_add_uint(ext_tree, hf_mip_utrpext_flags, tvb, offset + 2, 2, flags);
495           ext_flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
496           proto_tree_add_boolean(ext_flags_tree, hf_mip_utrpext_f, tvb, offset + 2, 2, flags);
497
498           /* reserved */
499           proto_tree_add_uint(ext_flags_tree, hf_mip_utrpext_reserved, tvb, offset + 2, 2, flags);        
500
501           /* keepalive interval */
502           proto_tree_add_item(ext_tree, hf_mip_utrpext_keepalive, tvb, offset + 4, 2, FALSE);
503           break;
504         case PMIPv4_NON_SKIP_EXT:   /* draft-leung-mip4-proxy-mode */
505           /* sub-type */
506           proto_tree_add_item(ext_tree, hf_mip_pmipv4nonskipext_stype, tvb, offset, 1, ext_subtype);
507           offset++;
508           /* len */
509           proto_tree_add_item(ext_tree, hf_mip_ext_len, tvb, offset, 2, ext_len);         
510           offset+=2;
511           if(ext_subtype == 1){     
512             /* Sub-type == 1 : PMIPv4 Per-Node Authentication Method */
513             proto_tree_add_item(ext_tree, hf_mip_pmipv4nonskipext_pernodeauthmethod, tvb, offset, 1, FALSE);
514           }
515           break;
516         case PMIPv4_SKIP_EXT:   /* draft-leung-mip4-proxy-mode */
517           /* sub-type */
518           ext_subtype = tvb_get_guint8(tvb, offset);
519           tp = proto_tree_add_text(ext_tree, tvb, offset, ext_len, 
520                                    "PMIPv4 Sub-Type: %s",
521                                    val_to_str(ext_subtype, mip_pmipv4skipext_stypes, "Unknown Sub-Type %u"));
522           pmipv4_tree = proto_item_add_subtree(tp, ett_mip_pmipv4_ext);
523           proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_stype, tvb, offset, 1, ext_subtype);
524           
525           if (ext_subtype == PMIPv4_SKIPEXT_STYPE_INTERFACE_ID) {
526             proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_interfaceid, tvb, offset + 1, ext_len-1, FALSE);
527           } else if (ext_subtype == PMIPv4_SKIPEXT_STYPE_DEVICE_ID) {
528             pmipv4skipext_type = tvb_get_guint8(tvb, offset + 1);
529             proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_deviceid_type, tvb, offset + 1, 1, pmipv4skipext_type);
530             proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_deviceid_id, tvb, offset + 2, ext_len - 2, FALSE);
531           } else if (ext_subtype == PMIPv4_SKIPEXT_STYPE_SUBSCRIBER_ID) {
532             pmipv4skipext_type = tvb_get_guint8(tvb, offset + 1);           
533             proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_subscriberid_type, tvb, offset + 1, 1, pmipv4skipext_type);
534             if (pmipv4skipext_type == 1) {     
535               proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_subscriberid_id, tvb, offset + 2, ext_len - 2, FALSE);
536             }
537           } else if (ext_subtype == PMIPv4_SKIPEXT_STYPE_ACCESS_TECHNOLOGY) {
538             pmipv4skipext_type = tvb_get_guint8(tvb, offset + 1);           
539             proto_tree_add_item(pmipv4_tree, hf_mip_pmipv4skipext_accesstechnology_type, tvb, offset + 1, 1, pmipv4skipext_type);
540           }
541           break;
542         case OLD_CVSE_EXT:      /* RFC 3115 */
543         case CVSE_EXT:          /* RFC 3115 */
544         case OLD_NVSE_EXT:      /* RFC 3115 */
545         case NVSE_EXT:          /* RFC 3115 */
546         case MF_CHALLENGE_EXT:  /* RFC 3012 */
547           /* The default dissector is good here.  The challenge is all hex anyway. */
548         default:
549           proto_tree_add_item(ext_tree, hf_mip_ext, tvb, offset, ext_len, FALSE);
550           break;
551         } /* ext type */
552
553         offset += ext_len;
554   } /* while data remaining */
555
556 } /* dissect_mip_extensions */
557
558 /* Code to actually dissect the packets */
559 static void
560 dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
561 {
562   /* Set up structures we will need to add the protocol subtree and manage it */
563   proto_item    *ti;
564   proto_tree    *mip_tree=NULL;
565   proto_item    *tf;
566   proto_tree    *flags_tree;
567   guint8         type;
568   guint16        flags;
569   gint           offset=0;
570   const guint8  *reftime;
571   tvbuff_t      *next_tvb;
572
573   /* Make entries in Protocol column and Info column on summary display */
574
575   col_set_str(pinfo->cinfo, COL_PROTOCOL, "MobileIP");
576   col_clear(pinfo->cinfo, COL_INFO);
577
578   type = tvb_get_guint8(tvb, offset);
579   switch (type) {
580   case REGISTRATION_REQUEST:
581         if (check_col(pinfo->cinfo, COL_INFO))
582           col_add_fstr(pinfo->cinfo, COL_INFO,
583                        "Reg Request: HoA=%s HA=%s CoA=%s",
584                        ip_to_str(tvb_get_ptr(tvb,4,4)),
585                        ip_to_str(tvb_get_ptr(tvb,8,4)),
586                        ip_to_str(tvb_get_ptr(tvb,12,4)));
587
588         if (tree) {
589           ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
590           mip_tree = proto_item_add_subtree(ti, ett_mip);
591
592           /* type */
593           proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
594           offset++;
595
596           /* flags */
597           flags = tvb_get_guint8(tvb, offset);
598           tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 1, flags);
599           flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
600           proto_tree_add_boolean(flags_tree, hf_mip_s, tvb, offset, 1, flags);
601           proto_tree_add_boolean(flags_tree, hf_mip_b, tvb, offset, 1, flags);
602           proto_tree_add_boolean(flags_tree, hf_mip_d, tvb, offset, 1, flags);
603           proto_tree_add_boolean(flags_tree, hf_mip_m, tvb, offset, 1, flags);
604           proto_tree_add_boolean(flags_tree, hf_mip_g, tvb, offset, 1, flags);
605           proto_tree_add_boolean(flags_tree, hf_mip_v, tvb, offset, 1, flags);
606           proto_tree_add_boolean(flags_tree, hf_mip_t, tvb, offset, 1, flags);
607           proto_tree_add_boolean(flags_tree, hf_mip_x, tvb, offset, 1, flags);
608           offset++;
609
610           /* lifetime */
611           proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
612           offset += 2;
613
614           /* home address */
615           proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
616           offset += 4;
617
618           /* home agent address */
619           proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
620           offset += 4;
621
622           /* Care of Address */
623           proto_tree_add_item(mip_tree, hf_mip_coa, tvb, offset, 4, FALSE);
624           offset += 4;
625
626           /* Identifier - assumed to be an NTP time here */
627           reftime = tvb_get_ptr(tvb, offset, 8);
628           proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8,
629                                       reftime,
630                                       "Identification: %s",
631                                       ntp_fmt_ts(reftime));
632           offset += 8;
633
634         } /* if tree */
635         break;
636   case REGISTRATION_REPLY:
637         if (check_col(pinfo->cinfo, COL_INFO))
638           col_add_fstr(pinfo->cinfo, COL_INFO,
639                        "Reg Reply: HoA=%s HA=%s, Code=%u",
640                        ip_to_str(tvb_get_ptr(tvb,4,4)), 
641                        ip_to_str(tvb_get_ptr(tvb,8,4)), 
642                        tvb_get_guint8(tvb,1));
643
644         if (tree) {
645           /* Add Subtree */
646           ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
647           mip_tree = proto_item_add_subtree(ti, ett_mip);
648
649           /* Type */
650           proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
651           offset++;
652
653           /* Reply Code */
654           proto_tree_add_item(mip_tree, hf_mip_code, tvb, offset, 1, FALSE);
655           offset++;
656
657           /* Registration Lifetime */
658           proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
659           offset += 2;
660
661           /* Home address */
662           proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
663           offset += 4;
664
665           /* Home Agent Address */
666           proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
667           offset += 4;
668
669           /* Identifier - assumed to be an NTP time here */
670           reftime = tvb_get_ptr(tvb, offset, 8);
671           proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8,
672                                       reftime,
673                                       "Identification: %s",
674                                       ntp_fmt_ts(reftime));
675           offset += 8;
676         } /* if tree */
677         break;
678   case NATT_TUNNEL_DATA:
679         if (check_col(pinfo->cinfo, COL_INFO))
680           col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel Data: Next Header=%u",
681                        tvb_get_guint8(tvb,1));
682
683         if (tree) {
684           /* Add Subtree */
685           ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
686           mip_tree = proto_item_add_subtree(ti, ett_mip);
687
688           /* Type */
689           proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
690           offset++;
691
692           /* Next Header */
693           proto_tree_add_item(mip_tree, hf_mip_nattt_nexthdr, tvb, offset, 1, FALSE);
694           offset++;
695
696           /* reserved */
697           proto_tree_add_item(mip_tree, hf_mip_nattt_reserved, tvb, offset, 2, FALSE);
698           offset += 2;
699         } /* if tree */
700         else {
701           offset += 4;
702         }
703         /* encapsulated payload */
704         next_tvb = tvb_new_subset_remaining(tvb, 4);
705         call_dissector(ip_handle, next_tvb, pinfo, mip_tree);
706         offset += tvb_reported_length_remaining(tvb, offset);
707         break;
708   case REGISTRATION_REVOCATION:
709         if (check_col(pinfo->cinfo, COL_INFO))
710           col_add_fstr(pinfo->cinfo, COL_INFO,
711                        "Reg Revocation: HoA=%s HDA=%s FDA=%s",
712                        ip_to_str(tvb_get_ptr(tvb,4,4)),
713                        ip_to_str(tvb_get_ptr(tvb,8,4)),
714                        ip_to_str(tvb_get_ptr(tvb,12,4)));
715
716         if (tree) {
717           ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
718           mip_tree = proto_item_add_subtree(ti, ett_mip);
719
720           /* type */
721           proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
722           offset++;
723
724           /* reserved */
725           proto_tree_add_item(mip_tree, hf_mip_rev_reserved, tvb, offset, 1, FALSE);
726           offset++;
727
728           /* flags */
729           flags = tvb_get_ntohs(tvb, offset);
730           tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags);
731           flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
732           proto_tree_add_boolean(flags_tree, hf_mip_rev_a, tvb, offset, 2, flags);
733           proto_tree_add_boolean(flags_tree, hf_mip_rev_i, tvb, offset, 2, flags);
734
735           /* reserved */
736           proto_tree_add_uint(flags_tree, hf_mip_rev_reserved, tvb, offset, 2, flags);
737           offset += 2;
738
739           /* home address */
740           proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
741           offset += 4;
742
743           /* home domain address */
744           proto_tree_add_item(mip_tree, hf_mip_hda, tvb, offset, 4, FALSE);
745           offset += 4;
746
747           /* foreign domain address */
748           proto_tree_add_item(mip_tree, hf_mip_fda, tvb, offset, 4, FALSE);
749           offset += 4;
750
751           /* revocation identifier */
752           proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE);
753           offset += 4;
754         } /* if tree */
755         break;
756   case REGISTRATION_REVOCATION_ACKNOWLEDGEMENT:
757         if (check_col(pinfo->cinfo, COL_INFO))
758           col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation Ack: HoA=%s",
759                        ip_to_str(tvb_get_ptr(tvb,4,4)));
760
761         if (tree) {
762           ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
763           mip_tree = proto_item_add_subtree(ti, ett_mip);
764
765           /* type */
766           proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
767           offset++;
768
769           /* reserved */
770           proto_tree_add_item(mip_tree, hf_mip_ack_reserved, tvb, offset, 1, FALSE);
771           offset++;
772
773           /* flags */
774           flags = tvb_get_ntohs(tvb, offset);
775           tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags);
776           flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
777           proto_tree_add_boolean(flags_tree, hf_mip_ack_i, tvb, offset, 2, flags);
778
779           /* reserved */
780           proto_tree_add_uint(flags_tree, hf_mip_ack_reserved, tvb, offset, 2, flags);
781           offset += 2;
782
783           /* home address */
784           proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
785           offset += 4;
786
787           /* revocation identifier */
788           proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE);
789           offset += 4;
790         } /* if tree */
791         break;
792   } /* End switch */
793
794   if (tree) {
795         if (tvb_reported_length_remaining(tvb, offset) > 0)
796           dissect_mip_extensions(tvb, offset, mip_tree);
797   }
798 } /* dissect_mip */
799
800 /* Register the protocol with Wireshark */
801 void proto_register_mip(void)
802 {
803
804 /* Setup list of header fields */
805         static hf_register_info hf[] = {
806           { &hf_mip_type,
807                  { "Message Type",           "mip.type",
808                         FT_UINT8, BASE_DEC, VALS(mip_types), 0,
809                         "Mobile IP Message type.", HFILL }
810           },
811           { &hf_mip_flags,
812                 {"Flags", "mip.flags",
813                  FT_UINT8, BASE_HEX, NULL, 0x0,
814                  NULL, HFILL}
815           },
816           { &hf_mip_s,
817                  {"Simultaneous Bindings",           "mip.s",
818
819                    FT_BOOLEAN, 8, NULL, 128,
820                    "Simultaneous Bindings Allowed", HFILL }
821           },
822           { &hf_mip_b,
823                  {"Broadcast Datagrams",           "mip.b",
824                    FT_BOOLEAN, 8, NULL, 64,
825                    "Broadcast Datagrams requested", HFILL }
826           },
827           { &hf_mip_d,
828                  { "Co-located Care-of Address",           "mip.d",
829                    FT_BOOLEAN, 8, NULL, 32,
830                    "MN using Co-located Care-of address", HFILL }
831           },
832           { &hf_mip_m,
833                  {"Minimal Encapsulation",           "mip.m",
834                    FT_BOOLEAN, 8, NULL, 16,
835                    "MN wants Minimal encapsulation", HFILL }
836           },
837           { &hf_mip_g,
838                  {"GRE",           "mip.g",
839                    FT_BOOLEAN, 8, NULL, 8,
840                    "MN wants GRE encapsulation", HFILL }
841           },
842           { &hf_mip_v,
843                  { "Van Jacobson",           "mip.v",
844                    FT_BOOLEAN, 8, NULL, 4,
845                    NULL, HFILL }
846           },
847           { &hf_mip_t,
848                  { "Reverse Tunneling",           "mip.t",
849                    FT_BOOLEAN, 8, NULL, 2,
850                    "Reverse tunneling requested", HFILL }
851           },
852           { &hf_mip_x,
853                  { "Reserved",           "mip.x",
854                    FT_BOOLEAN, 8, NULL, 1,
855                    NULL, HFILL }
856           },
857           { &hf_mip_code,
858                  { "Reply Code",           "mip.code",
859                         FT_UINT8, BASE_DEC, VALS(mip_reply_codes), 0,
860                         "Mobile IP Reply code.", HFILL }
861           },
862           { &hf_mip_life,
863                  { "Lifetime",           "mip.life",
864                         FT_UINT16, BASE_DEC, NULL, 0,
865                         "Mobile IP Lifetime.", HFILL }
866           },
867           { &hf_mip_homeaddr,
868                  { "Home Address",           "mip.homeaddr",
869                         FT_IPv4, BASE_NONE, NULL, 0,
870                         "Mobile Node's home address.", HFILL }
871           },
872
873           { &hf_mip_haaddr,
874                  { "Home Agent",           "mip.haaddr",
875                         FT_IPv4, BASE_NONE, NULL, 0,
876                         "Home agent IP Address.", HFILL }
877           },
878           { &hf_mip_coa,
879                  { "Care of Address",           "mip.coa",
880                         FT_IPv4, BASE_NONE, NULL, 0,
881                         "Care of Address.", HFILL }
882           },
883           { &hf_mip_ident,
884                  { "Identification",           "mip.ident",
885                         FT_BYTES, BASE_NONE, NULL, 0,
886                         "MN Identification.", HFILL }
887           },
888           { &hf_mip_ext_type,
889                  { "Extension Type",           "mip.ext.type",
890                         FT_UINT8, BASE_DEC, VALS(mip_ext_types), 0,
891                         "Mobile IP Extension Type.", HFILL }
892           },
893           { &hf_mip_gaext_stype,
894                  { "Gen Auth Ext SubType",           "mip.ext.auth.subtype",
895                         FT_UINT8, BASE_DEC, VALS(mip_gaext_stypes), 0,
896                         "Mobile IP Auth Extension Sub Type.", HFILL }
897           },
898           { &hf_mip_ext_len,
899                  { "Extension Length",         "mip.ext.len",
900                         FT_UINT16, BASE_DEC, NULL, 0,
901                         "Mobile IP Extension Length.", HFILL }
902           },
903           { &hf_mip_ext,
904                  { "Extension",                      "mip.extension",
905                         FT_BYTES, BASE_NONE, NULL, 0,
906                         NULL, HFILL }
907           },
908           { &hf_mip_aext_spi,
909                  { "SPI",                      "mip.auth.spi",
910                         FT_UINT32, BASE_HEX, NULL, 0,
911                         "Authentication Header Security Parameter Index.", HFILL }
912           },
913           { &hf_mip_aext_auth,
914                  { "Authenticator",            "mip.auth.auth",
915                         FT_BYTES, BASE_NONE, NULL, 0,
916                         "Authenticator.", HFILL }
917           },
918           { &hf_mip_next_nai,
919                  { "NAI",                      "mip.nai",
920                         FT_STRING, BASE_NONE, NULL, 0,
921                         NULL, HFILL }
922           },
923           { &hf_mip_rext_flags,
924                  {"Rev Ext Flags",             "mip.ext.rev.flags",
925                         FT_UINT16, BASE_HEX, NULL, 0x0,
926                         "Revocation Support Extension Flags", HFILL}
927           },
928           { &hf_mip_rext_i,
929                  { "'I' bit Support",          "mip.ext.rev.i",
930                         FT_BOOLEAN, 16, NULL, 32768,
931                         "Agent supports Inform bit in Revocation", HFILL }
932           },
933           { &hf_mip_rext_reserved,
934                  { "Reserved",                 "mip.ext.rev.reserved",
935                         FT_UINT16, BASE_HEX, NULL, 0x7fff,
936                         NULL, HFILL }
937           },
938           { &hf_mip_rext_tstamp,
939                  { "Timestamp",                "mip.ext.rev.tstamp",
940                         FT_UINT32, BASE_DEC, NULL, 0,
941                         "Revocation Timestamp of Sending Agent", HFILL }
942           },
943           { &hf_mip_rev_reserved,
944                  { "Reserved",                 "mip.rev.reserved", 
945                         FT_UINT8, BASE_HEX, NULL, 0x0,
946                         NULL, HFILL}
947           },
948           { &hf_mip_rev_a,
949                  { "Home Agent",               "mip.rev.a",
950                         FT_BOOLEAN, 16, NULL, 32768,
951                         "Revocation sent by Home Agent", HFILL }
952           },
953           { &hf_mip_rev_i,
954                  { "Inform",                   "mip.rev.i",
955                         FT_BOOLEAN, 16, NULL, 16384,
956                         "Inform Mobile Node", HFILL }
957           },
958           { &hf_mip_rev_reserved2,
959                  { "Reserved",                 "mip.rev.reserved2", 
960                         FT_UINT16, BASE_HEX, NULL, 0x3fff,
961                         NULL, HFILL}},
962           { &hf_mip_hda,
963                  { "Home Domain Address",      "mip.rev.hda",
964                         FT_IPv4, BASE_NONE, NULL, 0,
965                         "Revocation Home Domain IP Address", HFILL }
966           },
967           { &hf_mip_fda,
968                  { "Foreign Domain Address",   "mip.rev.fda",
969                         FT_IPv4, BASE_NONE, NULL, 0,
970                         "Revocation Foreign Domain IP Address", HFILL }
971           },
972           { &hf_mip_revid,
973                  { "Revocation Identifier",    "mip.revid",
974                         FT_UINT32, BASE_DEC, NULL, 0,
975                         "Revocation Identifier of Initiating Agent", HFILL }
976           },
977           { &hf_mip_ack_reserved,
978                  { "Reserved",                 "mip.ack.reserved", 
979                         FT_UINT8, BASE_HEX, NULL, 0x0,
980                         NULL, HFILL}
981           },
982           { &hf_mip_ack_i,
983                  { "Inform",                   "mip.ack.i",
984                         FT_BOOLEAN, 16, NULL, 32768,
985                         "Inform Mobile Node", HFILL }
986           },
987           { &hf_mip_ack_reserved2,
988                  { "Reserved",                 "mip.ack.reserved2", 
989                         FT_UINT16, BASE_HEX, NULL, 0x7fff,
990                         NULL, HFILL}},
991           { &hf_mip_dhaext_stype,
992                  { "DynHA Ext SubType",        "mip.ext.dynha.subtype",
993                         FT_UINT8, BASE_DEC, VALS(mip_dhaext_stypes), 0,
994                         "Dynamic HA Extension Sub-type", HFILL }
995           },
996           { &hf_mip_dhaext_addr,
997                  { "DynHA Home Agent",         "mip.ext.dynha.ha",
998                         FT_IPv4, BASE_NONE, NULL, 0,
999                         "Dynamic Home Agent IP Address", HFILL }
1000           },
1001           { &hf_mip_mstrext_stype,
1002                  { "MsgStr Ext SubType",       "mip.ext.msgstr.subtype",
1003                         FT_UINT8, BASE_DEC, VALS(mip_mstrext_stypes), 0,
1004                         "Message String Extension Sub-type", HFILL }
1005           },
1006           { &hf_mip_mstrext_text,
1007                  { "MsgStr Text",              "mip.ext.msgstr.text",
1008                         FT_STRING, BASE_NONE, NULL, 0,
1009                         "Message String Extension Text", HFILL }
1010           },
1011           { &hf_mip_nattt_nexthdr,
1012                  { "NATTT NextHeader",         "mip.nattt.nexthdr",
1013                         FT_UINT8, BASE_DEC, VALS(mip_nattt_nexthdr), 0,
1014                         "NAT Traversal Tunnel Next Header.", HFILL }
1015           },
1016           { &hf_mip_nattt_reserved,
1017                  { "Reserved",                 "mip.nattt.reserved",
1018                         FT_UINT16, BASE_HEX, NULL , 0x0,
1019                         NULL, HFILL }
1020           },
1021           { &hf_mip_utrqext_stype,
1022                  { "UDP TunReq Ext SubType",   "mip.ext.utrq.subtype",
1023                         FT_UINT8, BASE_DEC, VALS(mip_utrqext_stypes), 0,
1024                         "UDP Tunnel Request Extension Sub-type", HFILL }
1025           },
1026           { &hf_mip_utrqext_reserved1,
1027                  { "Reserved 1",                "mip.ext.utrq.reserved1",
1028                         FT_UINT8, BASE_HEX, NULL, 0x0,
1029                         NULL, HFILL }
1030           },
1031           { &hf_mip_utrqext_flags,
1032                  { "UDP TunReq Ext Flags",     "mip.ext.utrq.flags",
1033                         FT_UINT8, BASE_HEX, NULL, 0x0,
1034                         "UDP Tunnel Request Extension Flags", HFILL }
1035           },
1036           { &hf_mip_utrqext_f,
1037                  { "Req Forced",               "mip.ext.utrq.f",
1038                         FT_BOOLEAN, 8, NULL, 128,
1039                         "MN wants to Force UDP Tunneling", HFILL }
1040           },
1041           { &hf_mip_utrqext_r,
1042                  { "FA Registration Required", "mip.ext.utrq.r",
1043                         FT_BOOLEAN, 8, NULL, 64,
1044                         "Registration through FA Required", HFILL }
1045           },
1046           { &hf_mip_utrqext_reserved2,
1047                  { "Reserved 2",                "mip.ext.utrq.reserved2",
1048                         FT_UINT8, BASE_HEX, NULL, 0x3f,
1049                         NULL, HFILL }
1050           },
1051           { &hf_mip_utrqext_encap_type,
1052                  { "UDP Encap Type",           "mip.ext.utrq.encaptype",
1053                         FT_UINT8, BASE_DEC, VALS(mip_utrqext_encap_types), 0,
1054                         "UDP Encapsulation Type", HFILL }
1055           },
1056           { &hf_mip_utrqext_reserved3,
1057                  { "Reserved 3",                "mip.ext.utrq.reserved3",
1058                         FT_UINT16, BASE_HEX, NULL, 0x0,
1059                         NULL, HFILL }
1060           },
1061           { &hf_mip_utrpext_stype,
1062                  { "UDP TunRep Ext SubType",   "mip.ext.utrp.subtype",
1063                         FT_UINT8, BASE_DEC, VALS(mip_utrpext_stypes), 0,
1064                         "UDP Tunnel Reply Extension Sub-type", HFILL }
1065           },
1066           { &hf_mip_utrpext_code,
1067                  { "UDP TunRep Code",           "mip.ext.utrp.code",
1068                         FT_UINT8, BASE_DEC, VALS(mip_utrpext_codes), 0,
1069                         "UDP Tunnel Reply Code", HFILL }
1070           },
1071           { &hf_mip_utrpext_flags,
1072                  { "UDP TunRep Ext Flags",           "mip.ext.utrp.flags",
1073                         FT_UINT16, BASE_HEX, NULL, 0x0,
1074                         "UDP Tunnel Request Extension Flags", HFILL }
1075           },
1076           { &hf_mip_utrpext_f,
1077                  { "Rep Forced",                    "mip.ext.utrp.f",
1078                         FT_BOOLEAN, 16, NULL, 32768,
1079                         "HA wants to Force UDP Tunneling", HFILL }
1080           },
1081           { &hf_mip_utrpext_reserved,
1082                  { "Reserved",           "mip.ext.utrp.reserved",
1083                         FT_UINT16, BASE_HEX, NULL, 0x7fff,
1084                         NULL, HFILL }
1085           },
1086           { &hf_mip_utrpext_keepalive,
1087                  { "Keepalive Interval",            "mip.ext.utrp.keepalive",
1088                         FT_UINT16, BASE_DEC, NULL, 0,
1089                         "NAT Keepalive Interval", HFILL }
1090           },
1091           { &hf_mip_pmipv4nonskipext_stype,
1092                  { "Sub-type",  "mip.ext.pmipv4nonskipext.subtype",
1093                         FT_UINT8, BASE_DEC, VALS(mip_pmipv4nonskipext_stypes), 0,
1094                         "PMIPv4 Skippable Extension Sub-type", HFILL }
1095           },
1096           { &hf_mip_pmipv4nonskipext_pernodeauthmethod,
1097                  { "Per-Node Authentication Method",            "mip.ext.pmipv4nonskipext.pernodeauthmethod",
1098                         FT_UINT8, BASE_DEC, VALS(mip_pmipv4nonskipext_pernodeauthmethod_types), 0,
1099                         NULL, HFILL }
1100           },
1101           { &hf_mip_pmipv4skipext_stype,
1102                  { "Sub-type",  "mip.ext.pmipv4skipext.subtype",
1103                         FT_UINT8, BASE_DEC, VALS(mip_pmipv4skipext_stypes), 0,
1104                         "PMIPv4 Non-skippable Extension Sub-type", HFILL }
1105           },
1106           { &hf_mip_pmipv4skipext_interfaceid,
1107                  { "Interface ID",              "mip.ext.pmipv4skipext.interfaceid",
1108                         FT_BYTES, BASE_NONE, NULL, 0,
1109                         NULL, HFILL }
1110           },
1111           { &hf_mip_pmipv4skipext_deviceid_type,
1112                  { "ID-Type",           "mip.ext.pmipv4skipext.deviceid_type",
1113                         FT_UINT8, BASE_DEC, VALS(mip_pmipv4skipext_deviceid_types), 0,
1114                         "Device ID-Type", HFILL }
1115           },
1116           { &hf_mip_pmipv4skipext_deviceid_id,
1117                  { "Identifier",        "mip.ext.pmipv4skipext.deviceid_id",
1118                         FT_BYTES, BASE_NONE, NULL, 0,
1119                         "Device ID Identifier", HFILL }
1120           },
1121           { &hf_mip_pmipv4skipext_subscriberid_type,
1122                  { "ID-Type",   "mip.ext.pmipv4skipext.subscriberid_type",
1123                         FT_UINT8, BASE_DEC, VALS(mip_pmipv4skipext_subscriberid_types), 0,
1124                         "Subscriber ID-Type", HFILL }
1125           },
1126           { &hf_mip_pmipv4skipext_subscriberid_id,
1127                  { "Identifier",        "mip.ext.pmipv4skipext.subscriberid_id",
1128                         FT_BYTES, BASE_NONE, NULL, 0,
1129                         "Subscriber ID Identifier", HFILL }
1130           },
1131           { &hf_mip_pmipv4skipext_accesstechnology_type,
1132                  { "Access Technology Type",    "mip.ext.pmipv4skipext.accesstechnology_type",
1133                         FT_UINT8, BASE_DEC, VALS(mip_pmipv4skipext_accesstechnology_types), 0,
1134                         NULL, HFILL }
1135           },
1136         };
1137
1138         /* Setup protocol subtree array */
1139         static gint *ett[] = {
1140                 &ett_mip,
1141                 &ett_mip_flags,
1142                 &ett_mip_ext,
1143                 &ett_mip_exts,
1144                 &ett_mip_pmipv4_ext,
1145         };
1146
1147         /* Register the protocol name and description */
1148         proto_mip = proto_register_protocol("Mobile IP", "Mobile IP", "mip");
1149
1150         /* Register the dissector by name */
1151         register_dissector("mip", dissect_mip, proto_mip);
1152
1153         /* Required function calls to register the header fields and subtrees used */
1154         proto_register_field_array(proto_mip, hf, array_length(hf));
1155         proto_register_subtree_array(ett, array_length(ett));
1156 }
1157
1158 void
1159 proto_reg_handoff_mip(void)
1160 {
1161         dissector_handle_t mip_handle;
1162
1163         mip_handle = find_dissector("mip");
1164         ip_handle = find_dissector("ip");
1165         dissector_add("udp.port", UDP_PORT_MIP, mip_handle);
1166 }