Free the string you "g_strdup()"ed, rather than handing "g_free()" the
[obnox/wireshark/wip.git] / packet-mip.c
1 /* packet-mip.c
2  * Routines for Mobile IP dissection
3  * Copyright 2000, Stefan Raab <sraab@cisco.com>
4  *
5  * $Id: packet-mip.c,v 1.17 2001/04/20 20:34:29 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  * 
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.
20  * 
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
39 #endif
40
41 #include <string.h>
42 #include <glib.h>
43 #include <time.h>
44
45 #ifdef NEED_SNPRINTF_H
46 # include "snprintf.h"
47 #endif
48
49 #include "packet.h"
50
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;
72
73 /* Initialize the subtree pointers */
74 static gint ett_mip = -1;
75 static gint ett_mip_ext = -1;
76
77 /* Port used for Mobile IP */
78 #define UDP_PORT_MIP    434
79 #define NTP_BASETIME 2208988800ul
80
81 static const value_string mip_types[] = {
82   {1, "Registration Request"},
83   {3, "Registration Reply"},
84   {0, NULL},
85 };
86
87 static const value_string mip_reply_codes[]= {
88   {0, "Reg Accepted"},
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"},
124   {0, NULL},
125 };
126
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"},
132   {0, NULL},
133 };
134
135 /* Code to actually dissect the packets */
136 static void
137 dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
138 {
139
140 /* Set up structures we will need to add the protocol subtree and manage it */
141         proto_item      *ti;
142         proto_tree      *mip_tree=NULL, *ext_tree=NULL;
143         guint8          type, code;
144         struct timeval      ident_time;
145         int eoffset, elen;
146         
147 /* Make entries in Protocol column and Info column on summary display */
148
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);
153     
154         type = tvb_get_guint8(tvb, 0);
155
156         if (type==1) {
157
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)));
161         
162           if (tree) {
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);
166
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);
175                  
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);
183                  
184                  eoffset = 24;
185                  while (eoffset < tvb_length(tvb)) {             /* Registration Extensions */
186                         if (eoffset ==24) {
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);
189                         }
190
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);
194
195                         switch (tvb_get_guint8(tvb, eoffset)) {
196                         case 32:
197                         case 33:
198                         case 34:
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);
201                           break;
202                         case 131:
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)));
206                           break;
207                         default:
208                           proto_tree_add_text(ext_tree, tvb, eoffset + 2,  tvb_get_guint8(tvb, eoffset+1), 
209                                                                                  "Unknown Extension");
210                           break;
211                           
212                         }
213                         eoffset += tvb_get_guint8(tvb, eoffset+1) + 2;
214                  }
215           }
216         }
217
218         
219         if (type==3){
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));
223           
224           if (tree) {
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);
228                  
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);
238                  
239                  eoffset = 20;
240                  while (eoffset < tvb_length(tvb)) {             /* Registration Extensions */
241                         if (eoffset==20) {
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);
244                         }
245                         
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);
250                         
251                         switch (tvb_get_guint8(tvb, eoffset)) {
252                         case 32:
253                         case 33:
254                         case 34:                             
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);
257                           break;
258                         case 131:
259                           proto_tree_add_item(ext_tree, hf_mip_next_nai, tvb, eoffset+2, 
260                                                                                         tvb_get_guint8(tvb, eoffset+1), FALSE);
261                           break;
262                         default:
263                           proto_tree_add_text(ext_tree, tvb, eoffset + 2,  tvb_get_guint8(tvb, eoffset+1), 
264                                                                                  "Unknown Extension");
265                           break;
266                         }
267                         eoffset += tvb_get_guint8(tvb, eoffset+1) + 2;
268                  }
269           }
270         }
271 }
272
273 /* Register the protocol with Ethereal */
274 void proto_register_mip(void)
275 {                 
276
277 /* Setup list of header fields */
278         static hf_register_info hf[] = {
279           { &hf_mip_type,
280                  { "Message Type",           "mip.type",
281                         FT_INT8, BASE_DEC, VALS(mip_types), 0,          
282                         "Mobile IP Message type." }
283           },
284           { &hf_mip_s,
285                  {"Simultaneous Bindings",           "mip.s",
286
287                    FT_BOOLEAN, 8, NULL, 128,          
288                    "Simultaneous Bindings Allowed" }
289           },
290           { &hf_mip_b,
291                  {"Broadcast Datagrams",           "mip.b",
292                    FT_BOOLEAN, 8, NULL, 64,          
293                    "Broadcast Datagrams requested" }
294           },
295           { &hf_mip_d,
296                  { "Co-lcated Care-of Address",           "mip.d",
297                    FT_BOOLEAN, 8, NULL, 32,          
298                    "MN using Co-located Care-of address" }
299           },
300           { &hf_mip_m,
301                  {"Minimal Encapsulation",           "mip.m",
302                    FT_BOOLEAN, 8, NULL, 16,          
303                    "MN wants Minimal encapsulation" }
304           },
305           { &hf_mip_g,
306                  {"GRE",           "mip.g",
307                    FT_BOOLEAN, 8, NULL, 8,          
308                    "MN wants GRE encapsulation" }
309           },
310           { &hf_mip_v,
311                  { "Van Jacobson",           "mip.v",
312                    FT_BOOLEAN, 8, NULL, 4,          
313                    "Van Jacobson" }
314           },
315           { &hf_mip_t,
316                  { "Reverse Tunneling",           "mip.t",
317                    FT_BOOLEAN, 8, NULL, 2,          
318                    "Reverse tunneling requested" }
319           },
320           { &hf_mip_code,
321                  { "Reply Code",           "mip.code",
322                         FT_UINT8, BASE_DEC, VALS(mip_reply_codes), 0,          
323                         "Mobile IP Reply code." }
324           },
325           { &hf_mip_life,
326                  { "Lifetime",           "mip.life",
327                         FT_UINT16, BASE_DEC, NULL, 0,          
328                         "Mobile IP Lifetime." }
329           },
330           { &hf_mip_homeaddr,
331                  { "Home Address",           "mip.homeaddr",
332                         FT_IPv4, BASE_NONE, NULL, 0,          
333                         "Mobile Node's home address." }
334           },
335           
336           { &hf_mip_haaddr,
337                  { "Home Agent",           "mip.haaddr",
338                         FT_IPv4, BASE_NONE, NULL, 0,          
339                         "Home agent IP Address." }
340           },
341           { &hf_mip_coa,
342                  { "Care of Address",           "mip.coa",
343                         FT_IPv4, BASE_NONE, NULL, 0,          
344                         "Care of Address." }
345           },
346           { &hf_mip_ident,
347                  { "Identification",           "mip.ident",
348                         FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,          
349                         "MN Identification." }
350           },
351           { &hf_mip_ext_type,
352                  { "Extension Type",           "mip.ext.type",
353                         FT_INT8, BASE_DEC, VALS(mip_ext_types), 0,          
354                         "Mobile IP Extension Type." }
355           },
356           { &hf_mip_ext_len,
357                  { "Extension Length",         "mip.ext.len",
358                         FT_INT8, BASE_DEC, NULL, 0,
359                         "Mobile IP Extension Length."}
360           },
361           { &hf_mip_aext_spi,
362                  { "SPI",                      "mip.auth.spi",
363                         FT_INT32, BASE_HEX, NULL, 0,
364                         "Authentication Header Security Parameter Index."}
365           },
366           { &hf_mip_aext_auth,
367                  { "Authenticator",            "mip.auth.auth",
368                         FT_BYTES, BASE_NONE, NULL, 0,
369                         "Authenticator."}
370           },
371           { &hf_mip_next_nai,
372                  { "NAI",                      "mip.nai",
373                         FT_STRING, BASE_NONE, NULL, 0,
374                         "NAI"}
375           },
376         };
377
378 /* Setup protocol subtree array */
379         static gint *ett[] = {
380                 &ett_mip,
381                 &ett_mip_ext,
382         };
383
384 /* Register the protocol name and description */
385         proto_mip = proto_register_protocol("Mobile IP", "Mobile IP", "mip");
386
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));
390 };
391
392 void
393 proto_reg_handoff_mip(void)
394 {
395         dissector_add("udp.port", UDP_PORT_MIP, dissect_mip, proto_mip);
396 }