2 * Routines for Mobile IP dissection
3 * Copyright 2000, Stefan Raab <sraab@cisco.com>
5 * $Id: packet-mip.c,v 1.17 2001/04/20 20:34:29 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
45 #ifdef NEED_SNPRINTF_H
46 # include "snprintf.h"
51 /* Initialize the protocol and registered fields */
52 static int proto_mip = -1;
53 static int hf_mip_type = -1;
54 static int hf_mip_s = -1;
55 static int hf_mip_b = -1;
56 static int hf_mip_d = -1;
57 static int hf_mip_m = -1;
58 static int hf_mip_g = -1;
59 static int hf_mip_v = -1;
60 static int hf_mip_t = -1;
61 static int hf_mip_code = -1;
62 static int hf_mip_life = -1;
63 static int hf_mip_homeaddr = -1;
64 static int hf_mip_haaddr = -1;
65 static int hf_mip_coa = -1;
66 static int hf_mip_ident = -1;
67 static int hf_mip_ext_type = -1;
68 static int hf_mip_ext_len = -1;
69 static int hf_mip_aext_spi = -1;
70 static int hf_mip_aext_auth = -1;
71 static int hf_mip_next_nai = -1;
73 /* Initialize the subtree pointers */
74 static gint ett_mip = -1;
75 static gint ett_mip_ext = -1;
77 /* Port used for Mobile IP */
78 #define UDP_PORT_MIP 434
79 #define NTP_BASETIME 2208988800ul
81 static const value_string mip_types[] = {
82 {1, "Registration Request"},
83 {3, "Registration Reply"},
87 static const value_string mip_reply_codes[]= {
89 {1, "Reg Accepted, but Simultaneous Bindings Unsupported."},
90 {64, "Reg Deny (FA)- Unspecified Reason"},
91 {65, "Reg Deny (FA)- Administratively Prohibited"},
92 {66, "Reg Deny (FA)- Insufficient Resources"},
93 {67, "Reg Deny (FA)- MN failed Authentication"},
94 {68, "Reg Deny (FA)- HA failed Authentication"},
95 {69, "Reg Deny (FA)- Requested Lifetime too Long"},
96 {70, "Reg Deny (FA)- Poorly Formed Request"},
97 {71, "Reg Deny (FA)- Poorly Formed Reply"},
98 {72, "Reg Deny (FA)- Requested Encapsulation Unavailable"},
99 {73, "Reg Deny (FA)- VJ Compression Unavailable"},
100 {74, "Reg Deny (FA)- Requested Reverse Tunnel Unavailable"},
101 {75, "Reg Deny (FA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
102 {76, "Reg Deny (FA)- Mobile Node Too Distant"},
103 {79, "Reg Deny (FA)- Delivery Style Not Supported"},
104 {80, "Reg Deny (FA)- Home Network Unreachable"},
105 {81, "Reg Deny (FA)- HA Host Unreachable"},
106 {82, "Reg Deny (FA)- HA Port Unreachable"},
107 {88, "Reg Deny (FA)- HA Unreachable"},
108 {96, "Reg Deny (FA)(NAI) - Non Zero Home Address Required"},
109 {97, "Reg Deny (FA)(NAI) - Missing NAI"},
110 {98, "Reg Deny (FA)(NAI) - Missing Home Agent"},
111 {99, "Reg Deny (FA)(NAI) - Missing Home Address"},
112 {128, "Reg Deny (HA)- Unspecified"},
113 {129, "Reg Deny (HA)- Administratively Prohibited"},
114 {130, "Reg Deny (HA)- Insufficient Resources"},
115 {131, "Reg Deny (HA)- MN Failed Authentication"},
116 {132, "Reg Deny (HA)- FA Failed Authentication"},
117 {133, "Reg Deny (HA)- Registration ID Mismatch"},
118 {134, "Reg Deny (HA)- Poorly Formed Request"},
119 {135, "Reg Deny (HA)- Too Many Simultaneous Bindings"},
120 {136, "Reg Deny (HA)- Unknown HA Address"},
121 {137, "Reg Deny (HA)- Requested Reverse Tunnel Unavailable"},
122 {138, "Reg Deny (HA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
123 {139, "Reg Deny (HA)- Requested Encapsulation Unavailable"},
127 static const value_string mip_ext_types[]= {
128 {32, "Mobile-Home Authentication Extension"},
129 {33, "Mobile-Foreign Authentication Extension"},
130 {34, "Foreign-Home Authentication Extension"},
131 {131, "Mobile Node NAI Extension"},
135 /* Code to actually dissect the packets */
137 dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
140 /* Set up structures we will need to add the protocol subtree and manage it */
142 proto_tree *mip_tree=NULL, *ext_tree=NULL;
144 struct timeval ident_time;
147 /* Make entries in Protocol column and Info column on summary display */
149 if (check_col(pinfo->fd, COL_PROTOCOL))
150 col_set_str(pinfo->fd, COL_PROTOCOL, "MobileIP");
151 if (check_col(pinfo->fd, COL_INFO))
152 col_clear(pinfo->fd, COL_INFO);
154 type = tvb_get_guint8(tvb, 0);
158 if (check_col(pinfo->fd, COL_INFO))
159 col_add_fstr(pinfo->fd, COL_INFO, "Reg Request: HAddr=%s COA=%s",
160 ip_to_str(tvb_get_ptr(tvb, 4, 4)), ip_to_str(tvb_get_ptr(tvb,12,4)));
163 ti = proto_tree_add_item(tree, proto_mip, tvb, 0, tvb_length(tvb), FALSE);
164 mip_tree = proto_item_add_subtree(ti, ett_mip);
165 proto_tree_add_int(mip_tree, hf_mip_type, tvb, 0, 1, type);
167 code = tvb_get_guint8(tvb, 1);
168 proto_tree_add_boolean(mip_tree, hf_mip_s, tvb, 1, 1, code);
169 proto_tree_add_boolean(mip_tree, hf_mip_b, tvb, 1, 1, code);
170 proto_tree_add_boolean(mip_tree, hf_mip_d, tvb, 1, 1, code);
171 proto_tree_add_boolean(mip_tree, hf_mip_m, tvb, 1, 1, code);
172 proto_tree_add_boolean(mip_tree, hf_mip_g, tvb, 1, 1, code);
173 proto_tree_add_boolean(mip_tree, hf_mip_v, tvb, 1, 1, code);
174 proto_tree_add_boolean(mip_tree, hf_mip_t, tvb, 1, 1, code);
176 proto_tree_add_item(mip_tree, hf_mip_life, tvb, 2, 2, FALSE);
177 proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, 4, 4, FALSE);
178 proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, 8, 4, FALSE);
179 proto_tree_add_item(mip_tree, hf_mip_coa, tvb, 12, 4, FALSE);
180 ident_time.tv_sec = tvb_get_ntohl(tvb,16)-(guint32) NTP_BASETIME;
181 ident_time.tv_usec = tvb_get_ntohl(tvb,20);
182 proto_tree_add_time(mip_tree, hf_mip_ident, tvb, 16, 8, &ident_time);
185 while (eoffset < tvb_length(tvb)) { /* Registration Extensions */
187 ti = proto_tree_add_text(mip_tree, tvb, 24, tvb_length(tvb)-24, "Extensions");
188 ext_tree = proto_item_add_subtree(ti, ett_mip_ext);
191 proto_tree_add_item(ext_tree, hf_mip_ext_type, tvb, eoffset, 1, FALSE);
192 elen = tvb_get_guint8(tvb, eoffset+1);
193 proto_tree_add_int(ext_tree, hf_mip_ext_len, tvb, eoffset+1, 1, elen);
195 switch (tvb_get_guint8(tvb, eoffset)) {
199 proto_tree_add_item(ext_tree, hf_mip_aext_spi, tvb, eoffset+2, 4, FALSE);
200 proto_tree_add_item(ext_tree, hf_mip_aext_auth, tvb, eoffset+6, elen-4, FALSE);
203 proto_tree_add_string(ext_tree, hf_mip_next_nai, tvb, eoffset+2,
204 tvb_get_guint8(tvb, eoffset+1),
205 tvb_get_ptr(tvb, eoffset+2,tvb_get_guint8(tvb, eoffset+1)));
208 proto_tree_add_text(ext_tree, tvb, eoffset + 2, tvb_get_guint8(tvb, eoffset+1),
209 "Unknown Extension");
213 eoffset += tvb_get_guint8(tvb, eoffset+1) + 2;
220 if (check_col(pinfo->fd, COL_INFO))
221 col_add_fstr(pinfo->fd, COL_INFO, "Reg Reply: HAddr=%s, Code=%u",
222 ip_to_str(tvb_get_ptr(tvb,4,4)), tvb_get_guint8(tvb,1));
225 ti = proto_tree_add_item(tree, proto_mip, tvb, 0, tvb_length(tvb), FALSE);
226 mip_tree = proto_item_add_subtree(ti, ett_mip);
227 proto_tree_add_int(mip_tree, hf_mip_type, tvb, 0, 1, type);
229 /* code = tvb_get_guint8(tvb, 1);
230 proto_tree_add_uint(mip_tree, hf_mip_code, tvb, 1, 1, code);*/
231 proto_tree_add_item(mip_tree, hf_mip_code, tvb, 1, 1, FALSE);
232 proto_tree_add_item(mip_tree, hf_mip_life, tvb, 2, 2, FALSE);
233 proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, 4, 4, FALSE);
234 proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, 8, 4, FALSE);
235 ident_time.tv_sec = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
236 ident_time.tv_usec = tvb_get_ntohl(tvb,16);
237 proto_tree_add_time(mip_tree, hf_mip_ident, tvb, 12, 8, &ident_time);
240 while (eoffset < tvb_length(tvb)) { /* Registration Extensions */
242 ti = proto_tree_add_text(mip_tree, tvb, 20, tvb_length(tvb)-20, "Extensions");
243 ext_tree = proto_item_add_subtree(ti, ett_mip_ext);
246 proto_tree_add_int(ext_tree, hf_mip_ext_type, tvb, eoffset, 1,
247 tvb_get_guint8(tvb, eoffset));
248 elen = tvb_get_guint8(tvb, eoffset+1);
249 proto_tree_add_int(ext_tree, hf_mip_ext_len, tvb, eoffset+1, 1, elen);
251 switch (tvb_get_guint8(tvb, eoffset)) {
255 proto_tree_add_item(ext_tree, hf_mip_aext_spi, tvb, eoffset+2, 4, FALSE);
256 proto_tree_add_item(ext_tree, hf_mip_aext_auth, tvb, eoffset+6, elen-4, FALSE);
259 proto_tree_add_item(ext_tree, hf_mip_next_nai, tvb, eoffset+2,
260 tvb_get_guint8(tvb, eoffset+1), FALSE);
263 proto_tree_add_text(ext_tree, tvb, eoffset + 2, tvb_get_guint8(tvb, eoffset+1),
264 "Unknown Extension");
267 eoffset += tvb_get_guint8(tvb, eoffset+1) + 2;
273 /* Register the protocol with Ethereal */
274 void proto_register_mip(void)
277 /* Setup list of header fields */
278 static hf_register_info hf[] = {
280 { "Message Type", "mip.type",
281 FT_INT8, BASE_DEC, VALS(mip_types), 0,
282 "Mobile IP Message type." }
285 {"Simultaneous Bindings", "mip.s",
287 FT_BOOLEAN, 8, NULL, 128,
288 "Simultaneous Bindings Allowed" }
291 {"Broadcast Datagrams", "mip.b",
292 FT_BOOLEAN, 8, NULL, 64,
293 "Broadcast Datagrams requested" }
296 { "Co-lcated Care-of Address", "mip.d",
297 FT_BOOLEAN, 8, NULL, 32,
298 "MN using Co-located Care-of address" }
301 {"Minimal Encapsulation", "mip.m",
302 FT_BOOLEAN, 8, NULL, 16,
303 "MN wants Minimal encapsulation" }
307 FT_BOOLEAN, 8, NULL, 8,
308 "MN wants GRE encapsulation" }
311 { "Van Jacobson", "mip.v",
312 FT_BOOLEAN, 8, NULL, 4,
316 { "Reverse Tunneling", "mip.t",
317 FT_BOOLEAN, 8, NULL, 2,
318 "Reverse tunneling requested" }
321 { "Reply Code", "mip.code",
322 FT_UINT8, BASE_DEC, VALS(mip_reply_codes), 0,
323 "Mobile IP Reply code." }
326 { "Lifetime", "mip.life",
327 FT_UINT16, BASE_DEC, NULL, 0,
328 "Mobile IP Lifetime." }
331 { "Home Address", "mip.homeaddr",
332 FT_IPv4, BASE_NONE, NULL, 0,
333 "Mobile Node's home address." }
337 { "Home Agent", "mip.haaddr",
338 FT_IPv4, BASE_NONE, NULL, 0,
339 "Home agent IP Address." }
342 { "Care of Address", "mip.coa",
343 FT_IPv4, BASE_NONE, NULL, 0,
347 { "Identification", "mip.ident",
348 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
349 "MN Identification." }
352 { "Extension Type", "mip.ext.type",
353 FT_INT8, BASE_DEC, VALS(mip_ext_types), 0,
354 "Mobile IP Extension Type." }
357 { "Extension Length", "mip.ext.len",
358 FT_INT8, BASE_DEC, NULL, 0,
359 "Mobile IP Extension Length."}
362 { "SPI", "mip.auth.spi",
363 FT_INT32, BASE_HEX, NULL, 0,
364 "Authentication Header Security Parameter Index."}
367 { "Authenticator", "mip.auth.auth",
368 FT_BYTES, BASE_NONE, NULL, 0,
373 FT_STRING, BASE_NONE, NULL, 0,
378 /* Setup protocol subtree array */
379 static gint *ett[] = {
384 /* Register the protocol name and description */
385 proto_mip = proto_register_protocol("Mobile IP", "Mobile IP", "mip");
387 /* Required function calls to register the header fields and subtrees used */
388 proto_register_field_array(proto_mip, hf, array_length(hf));
389 proto_register_subtree_array(ett, array_length(ett));
393 proto_reg_handoff_mip(void)
395 dissector_add("udp.port", UDP_PORT_MIP, dissect_mip, proto_mip);