Move dissectors to epan/dissectors directory.
[obnox/wireshark/wip.git] / epan / dissectors / packet-3g-a11.c
1 /*
2  * packet-3g-a11.c
3  * Routines for CDMA2000 A11 packet trace
4  * Copyright 2002, Ryuji Somegawa <somegawa@wide.ad.jp>
5  * packet-3g-a11.c was written based on 'packet-mip.c'.
6  *
7  * packet-mip.c
8  * Routines for Mobile IP dissection
9  * Copyright 2000, Stefan Raab <sraab@cisco.com>
10  *
11  * $Id$
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  * 
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  * 
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #include <string.h>
40 #include <glib.h>
41 #include <time.h>
42
43 #include <epan/packet.h>
44
45 /* Initialize the protocol and registered fields */
46 static int proto_a11 = -1;
47 static int hf_a11_type = -1;
48 static int hf_a11_flags = -1;
49 static int hf_a11_s = -1;
50 static int hf_a11_b = -1;
51 static int hf_a11_d = -1;
52 static int hf_a11_m = -1;
53 static int hf_a11_g = -1;
54 static int hf_a11_v = -1;
55 static int hf_a11_t = -1;
56 static int hf_a11_code = -1;
57 static int hf_a11_status = -1;
58 static int hf_a11_life = -1;
59 static int hf_a11_homeaddr = -1;
60 static int hf_a11_haaddr = -1;
61 static int hf_a11_coa = -1;
62 static int hf_a11_ident = -1;
63 static int hf_a11_ext_type = -1;
64 static int hf_a11_ext_stype = -1;
65 static int hf_a11_ext_len = -1;
66 static int hf_a11_ext = -1;
67 static int hf_a11_aext_spi = -1;
68 static int hf_a11_aext_auth = -1;
69 static int hf_a11_next_nai = -1;
70
71 static int hf_a11_ses_key = -1;
72 static int hf_a11_ses_mnsrid = -1;
73 static int hf_a11_ses_sidver = -1;
74 static int hf_a11_ses_msid_type = -1;
75 static int hf_a11_ses_msid_len = -1;
76 static int hf_a11_ses_msid = -1;
77 static int hf_a11_ses_ptype = -1;
78
79 static int hf_a11_vse_vid = -1;
80 static int hf_a11_vse_apptype = -1;
81 static int hf_a11_vse_canid = -1;
82 static int hf_a11_vse_panid = -1;
83 static int hf_a11_vse_srvopt = -1;
84 static int hf_a11_vse_pdit = -1;
85 static int hf_a11_vse_code = -1;
86 static int hf_a11_vse_dormant = -1;
87 static int hf_a11_vse_ppaddr = -1;
88
89 /* Initialize the subtree pointers */
90 static gint ett_a11 = -1;
91 static gint ett_a11_flags = -1;
92 static gint ett_a11_ext = -1;
93 static gint ett_a11_exts = -1;
94 static gint ett_a11_radius = -1;
95 static gint ett_a11_radiuses = -1;
96
97 /* Port used for Mobile IP based Tunneling Protocol (A11) */
98 #define UDP_PORT_3GA11    699
99 #define NTP_BASETIME 2208988800ul
100 #define THE3GPP2_VENDOR_ID 0x159f
101
102 typedef enum {
103     REGISTRATION_REQUEST = 1,
104     REGISTRATION_REPLY = 3,
105     REGISTRATION_UPDATE = 20,
106     REGISTRATION_ACK =21,
107     SESSION_UPDATE = 22,
108     SESSION_ACK = 23
109 } a11MessageTypes;
110
111 static const value_string a11_types[] = {
112   {REGISTRATION_REQUEST, "Registration Request"},
113   {REGISTRATION_REPLY,   "Registration Reply"},
114   {REGISTRATION_UPDATE,   "Registration Update"},
115   {REGISTRATION_ACK,   "Registration Ack"},
116   {SESSION_UPDATE,   "Session Update"},
117   {SESSION_ACK,   "Session Update Ack"},
118   {0, NULL},
119 };
120
121 static const value_string a11_reply_codes[]= {
122   {0, "Reg Accepted"},
123   {9, "Connection Update"},
124 #if 0
125   {1, "Reg Accepted, but Simultaneous Bindings Unsupported."},
126   {64, "Reg Deny (FA)- Unspecified Reason"}, 
127   {65, "Reg Deny (FA)- Administratively Prohibited"},
128   {66, "Reg Deny (FA)- Insufficient Resources"},
129   {67, "Reg Deny (FA)- MN failed Authentication"},
130   {68, "Reg Deny (FA)- HA failed Authentication"},
131   {69, "Reg Deny (FA)- Requested Lifetime too Long"},
132   {70, "Reg Deny (FA)- Poorly Formed Request"},
133   {71, "Reg Deny (FA)- Poorly Formed Reply"},
134   {72, "Reg Deny (FA)- Requested Encapsulation Unavailable"},
135   {73, "Reg Deny (FA)- VJ Compression Unavailable"},
136   {74, "Reg Deny (FA)- Requested Reverse Tunnel Unavailable"},
137   {75, "Reg Deny (FA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
138   {76, "Reg Deny (FA)- Mobile Node Too Distant"},
139   {79, "Reg Deny (FA)- Delivery Style Not Supported"},
140   {80, "Reg Deny (FA)- Home Network Unreachable"},
141   {81, "Reg Deny (FA)- HA Host Unreachable"},
142   {82, "Reg Deny (FA)- HA Port Unreachable"},
143   {88, "Reg Deny (FA)- HA Unreachable"},
144   {96, "Reg Deny (FA)(NAI) - Non Zero Home Address Required"},
145   {97, "Reg Deny (FA)(NAI) - Missing NAI"},
146   {98, "Reg Deny (FA)(NAI) - Missing Home Agent"},
147   {99, "Reg Deny (FA)(NAI) - Missing Home Address"},
148 #endif
149   {128, "Reg Deny (HA)- Unspecified"},
150   {129, "Reg Deny (HA)- Administratively Prohibited"},
151   {130, "Reg Deny (HA)- Insufficient Resources"},
152   {131, "Reg Deny (HA)- PCF Failed Authentication"},
153   /* {132, "Reg Deny (HA)- FA Failed Authentication"}, */
154   {133, "Reg Deny (HA)- Identification Mismatch"},
155   {134, "Reg Deny (HA)- Poorly Formed Request"},
156   /* {135, "Reg Deny (HA)- Too Many Simultaneous Bindings"}, */
157   {136, "Reg Deny (HA)- Unknown PDSN Address"},
158   {137, "Reg Deny (HA)- Requested Reverse Tunnel Unavailable"},
159   {138, "Reg Deny (HA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
160   {139, "Reg Deny (HA)- Requested Encapsulation Unavailable"},
161   {141, "Reg Deny (HA)- unsupported Vendor ID / Application Type in CVSE"},
162 };
163
164
165 static const value_string a11_ack_status[]= {
166   {0, "Update Accepted"},
167   {128, "Update Deny - Unspecified"},
168   {131, "Update Deny - Sending Node Failed Authentication"},
169   {133, "Update Deny - Registration ID Mismatch"},
170   {134, "Update Deny - Poorly Formed Request"},
171   {201, "Update Deny - Session Parameter Not Updated"},
172 };
173
174 typedef enum {
175   MH_AUTH_EXT = 32,
176   MF_AUTH_EXT = 33,
177   FH_AUTH_EXT = 34,
178   GEN_AUTH_EXT = 36,      /* RFC 3012 */
179   OLD_CVSE_EXT = 37,      /* RFC 3115 */
180   CVSE_EXT = 38,          /* RFC 3115 */
181   SS_EXT = 39,            /* 3GPP2 IOS4.2 */
182   RU_AUTH_EXT = 40,       /* 3GPP2 IOS4.2 */
183   MN_NAI_EXT = 131,
184   MF_CHALLENGE_EXT = 132, /* RFC 3012 */
185   OLD_NVSE_EXT = 133,     /* RFC 3115 */
186   NVSE_EXT = 134          /* RFC 3115 */
187 } MIP_EXTS;
188
189
190 static const value_string a11_ext_types[]= {
191   {MH_AUTH_EXT, "Mobile-Home Authentication Extension"},
192   {MF_AUTH_EXT, "Mobile-Foreign Authentication Extension"},
193   {FH_AUTH_EXT, "Foreign-Home Authentication Extension"},
194   {MN_NAI_EXT,  "Mobile Node NAI Extension"},
195   {GEN_AUTH_EXT, "Generalized Mobile-IP Authentication Extension"},
196   {MF_CHALLENGE_EXT, "MN-FA Challenge Extension"},
197   {CVSE_EXT, "Critical Vendor/Organization Specific Extension"},
198   {SS_EXT, "Session Specific Extension"},
199   {RU_AUTH_EXT, "Registration Update Authentication Extension"},
200   {OLD_CVSE_EXT, "Critical Vendor/Organization Specific Extension (OLD)"},
201   {NVSE_EXT, "Normal Vendor/Organization Specific Extension"},
202   {OLD_NVSE_EXT, "Normal Vendor/Organization Specific Extension (OLD)"},
203   {0, NULL},
204 };
205
206 static const value_string a11_ext_stypes[]= {
207   {1, "MN AAA Extension"},
208   {0, NULL},
209 };
210
211 static const value_string a11_ext_nvose_srvopt[]= {
212   {0x0021, "3G High Speed Packet Data"},
213   {0x003C, "Link Layer Assisted Header Removal"},
214   {0x003D, "Link Layer Assisted Robust Header Compression"},
215   {0, NULL},
216 };
217
218 static const value_string a11_ext_nvose_pdsn_code[]= {
219   {0xc1, "Connection Release - reason unspecified"},
220   {0xc2, "Connection Release - PPP time-out"},
221   {0xc3, "Connection Release - registration time-out"},
222   {0xc4, "Connection Release - PDSN error"},
223   {0xc5, "Connection Release - inter-PCF handoff"},
224   {0xc6, "Connection Release - inter-PDSN handoff"},
225   {0xc7, "Connection Release - PDSN OAM&P intervention"},
226   {0xc8, "Connection Release - accounting error"},
227   {0xca, "Connection Release - user (NAI) failed authentication"},
228   {0x00, NULL},
229 };
230
231 static const value_string a11_ext_dormant[]= {
232   {0x0000, "all MS packet data service instances are dormant"},
233   {0, NULL},
234 };
235
236 static const value_string a11_ext_app[]= {
237   {0x0101, "Accounting (RADIUS)"},
238   {0x0102, "Accounting (DIAMETER)"},
239   {0x0201, "Mobility Event Indicator (Mobility)"},
240   {0x0301, "Data Available Indicator (Data Ready to Send)"},
241   {0x0401, "Access Network Identifiers (ANID)"},
242   {0x0501, "PDSN Identifiers (Anchor P-P Address)"},
243   {0x0601, "Indicators (All Dormant Indicator)"},
244   {0x0701, "PDSN Code (PDSN Code)"},
245   {0x0801, "Session Parameter (RN-PDIT:Radio Network Packet Data Inactivity Timer)"},
246   {0x0901, "Service Option (Service Option Value)"},
247   {0, NULL},
248 };
249
250 static const value_string a11_airlink_types[]= {
251   {1, "Session Setup (Y=1)"},
252   {2, "Active Start (Y=2)"},
253   {3, "Active Stop (Y=3)"},
254   {4, "Short Data Burst (Y=4)"},
255   {0, NULL},
256 };
257
258 #define ATTRIBUTE_NAME_LEN_MAX 128
259 #define ATTR_TYPE_NULL 0
260 #define ATTR_TYPE_INT 1 
261 #define ATTR_TYPE_STR 2 
262 #define ATTR_TYPE_IPV4 3
263 #define ATTR_TYPE_TYPE 4 
264 #define ATTR_TYPE_MSID 5 
265
266 struct radius_attribute {
267   char attrname[ATTRIBUTE_NAME_LEN_MAX];
268   int type;
269   int subtype;
270   int bytes;
271   int data_type;
272 };
273
274 static const struct radius_attribute attrs[]={
275   {"Airlink Record",          26, 40,  4, ATTR_TYPE_TYPE},
276   {"R-P Session ID",          26, 41,  4, ATTR_TYPE_INT},
277   {"Airlink Sequence Number", 26, 42,  4, ATTR_TYPE_INT},
278 #if 0
279   {"MSID",                    31, -1, 15, ATTR_TYPE_MSID},
280 #endif
281   {"Serving PCF",             26,  9,  4, ATTR_TYPE_IPV4},
282   {"BSID",                    26, 10, 12, ATTR_TYPE_STR},
283   {"ESN",                     26, 52, 15, ATTR_TYPE_STR},
284   {"User Zone",               26, 11,  4, ATTR_TYPE_INT},
285   {"Forward FCH Mux Option",  26, 12,  4, ATTR_TYPE_INT},
286   {"Reverse FCH Mux Option",  26, 13,  4, ATTR_TYPE_INT},
287   {"Forward Fundamental Rate (IOS 4.1)",26, 14,  4, ATTR_TYPE_INT},
288   {"Reverse Fundamental Rate (IOS 4.1)",26, 15,  4, ATTR_TYPE_INT},
289   {"Service Option",          26, 16,  4, ATTR_TYPE_INT},
290   {"Forward Traffic Type",    26, 17,  4, ATTR_TYPE_INT},
291   {"Reverse Traffic Type",    26, 18,  4, ATTR_TYPE_INT},
292   {"FCH Frame Size",          26, 19,  4, ATTR_TYPE_INT},
293   {"Forward FCH RC",          26, 20,  4, ATTR_TYPE_INT},
294   {"Reverse FCH RC",          26, 21,  4, ATTR_TYPE_INT},
295   {"DCCH Frame Size 0/5/20",  26, 50,  4, ATTR_TYPE_INT},
296   {"Forward DCCH Mux Option", 26, 84,  4, ATTR_TYPE_INT},
297   {"Reverse DCCH Mux Option", 26, 85,  4, ATTR_TYPE_INT},
298   {"Forward DCCH RC",         26, 86,  4, ATTR_TYPE_INT},
299   {"Reverse DCCH RC",         26, 87,  4, ATTR_TYPE_INT},
300   {"Airlink Priority",        26, 39,  4, ATTR_TYPE_INT},
301   {"Active Connection Time",  26, 49,  4, ATTR_TYPE_INT},
302   {"Mobile Orig/Term Ind.",   26, 45,  4, ATTR_TYPE_INT},
303   {"SDB Octet Count (Term.)", 26, 31,  4, ATTR_TYPE_INT},
304   {"SDB Octet Count (Orig.)", 26, 32,  4, ATTR_TYPE_INT},
305   {"Unknown",                 -1, -1, -1, ATTR_TYPE_NULL},
306 };
307 #define NUM_ATTR (sizeof(attrs)/sizeof(struct radius_attribute))
308
309 #define MAX_STRVAL 16
310
311 #define RADIUS_VENDOR_SPECIFIC 26
312 #define SKIP_HDR_LEN 6
313
314 static void dissect_a11_radius( tvbuff_t *, int, proto_tree *, int);
315
316 /* RADIUS attributed */
317 static void
318 dissect_a11_radius( tvbuff_t *tvb, int offset, proto_tree *tree, int app_len)
319 {
320   proto_item *ti;
321   proto_tree *radius_tree=NULL;
322   size_t     radius_len;
323   guint8     radius_type;
324   guint8     radius_subtype;
325   int        attribute_type;
326   guint      attribute_len;
327   guint      offset0;
328   guint      radius_offset;
329   guint      i;
330   guchar     str_val[MAX_STRVAL];
331   guint      radius_vendor_id = 0;
332
333   /* None of this really matters if we don't have a tree */
334   if (!tree) return;
335
336   offset0 = offset;
337
338   /* return if length of extension is not valid */
339   if (tvb_reported_length_remaining(tvb, offset)  < 12) {
340     return;
341   }
342
343   ti = proto_tree_add_text(tree, tvb, offset - 2, app_len, "Airlink Record");
344
345   radius_tree = proto_item_add_subtree(ti, ett_a11_radiuses);
346
347   /* And, handle each record */
348   while (tvb_reported_length_remaining(tvb, offset) > 0
349          && ((int)offset-(int)offset0) <app_len-2)
350   {
351
352     radius_type = tvb_get_guint8(tvb, offset);
353         radius_len = tvb_get_guint8(tvb, offset + 1);
354
355     if (radius_type == RADIUS_VENDOR_SPECIFIC)
356     {
357       radius_vendor_id = tvb_get_ntohl(tvb, offset +2); 
358
359       if(radius_vendor_id != THE3GPP2_VENDOR_ID)
360       {
361         ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
362                 "Unknown Vendor-specific Attribute (Vendor Id: %x)", radius_vendor_id);
363         offset += radius_len;
364         continue;
365       }
366     }
367     else
368     {
369
370       /**** ad-hoc ***/
371       if(radius_type == 31)
372       {
373         strncpy(str_val, tvb_get_ptr(tvb,offset+2,radius_len-2), 
374                 radius_len-2);
375         if(radius_len-2 < MAX_STRVAL) {
376           str_val[radius_len-2] = '\0';
377         }
378         else {
379           str_val[MAX_STRVAL-1] = '\0';
380         }
381         ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
382             "MSID: %s", str_val);
383       }
384       else if (radius_type == 46)
385       {
386         ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
387             "Acct Session Time: %d",tvb_get_ntohl(tvb,offset+2));
388       }
389       else
390       {
391         ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
392               "Unknown RADIUS Attributes (Type: %d)", radius_type);
393       }
394
395       offset += radius_len;
396       continue;
397     }
398     
399         radius_len = tvb_get_guint8(tvb, offset + 1);
400
401     offset += SKIP_HDR_LEN;
402     radius_offset = 0;
403
404         /* Detect Airlink Record Type */
405
406     while (radius_len - 6 > radius_offset)
407     {
408
409       radius_subtype = tvb_get_guint8(tvb, offset + radius_offset);     
410       attribute_len = tvb_get_guint8(tvb, offset + radius_offset + 1);  
411
412       attribute_type = -1;
413       for(i = 0; i < NUM_ATTR; i++) {
414         if (attrs[i].subtype == radius_subtype) {
415             attribute_type = i;
416             break;
417         }
418           }
419
420       if(attribute_type >= 0) {
421         switch(attrs[attribute_type].data_type) {
422         case ATTR_TYPE_INT:
423           ti = proto_tree_add_text(radius_tree, tvb, offset + radius_offset,
424             attribute_len, "3GPP2: %s (%04x)", attrs[attribute_type].attrname,
425             tvb_get_ntohl(tvb,offset + radius_offset + 2));
426           break;
427         case ATTR_TYPE_IPV4:
428           ti = proto_tree_add_text(radius_tree, tvb, offset + radius_offset,
429             attribute_len, "3GPP2: %s (%s)", attrs[attribute_type].attrname,
430             ip_to_str(tvb_get_ptr(tvb,offset + radius_offset + 2,4)));
431           break;
432         case ATTR_TYPE_TYPE:
433           ti = proto_tree_add_text(radius_tree, tvb, offset + radius_offset,
434             attribute_len, "3GPP2: %s (%s)", attrs[attribute_type].attrname,
435             val_to_str(tvb_get_ntohl(tvb,offset+radius_offset+2),
436             a11_airlink_types,"Unknown"));
437           break;
438         case ATTR_TYPE_STR:
439           strncpy(str_val, tvb_get_ptr(tvb,offset+radius_offset+2,attribute_len - 2),
440              attribute_len - 2);
441           if(attribute_len - 2 < MAX_STRVAL) {
442              str_val[attribute_len - 2] = '\0';
443           }
444           else {
445             str_val[MAX_STRVAL-1] = '\0';
446           }
447           ti = proto_tree_add_text(radius_tree, tvb, offset+radius_offset,
448              attribute_len,
449             "3GPP2: %s (%s)", attrs[attribute_type].attrname, str_val);
450           break;
451         case ATTR_TYPE_NULL:
452           break;
453         default:
454           ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
455             "RADIUS: %s", attrs[attribute_type].attrname);
456           break;
457         }
458       }
459       else {
460         ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
461           "RADIUS: Unknown 3GPP2 Attribute (Type:%d, SubType:%d)",
462           radius_type,radius_subtype);
463       }
464
465       radius_offset += attribute_len;
466     }
467     offset += radius_len - 6;
468
469   }
470
471 }
472
473 /* Code to dissect extensions */
474 static void
475 dissect_a11_extensions( tvbuff_t *tvb, int offset, proto_tree *tree)
476 {
477   proto_item   *ti;
478   proto_tree   *exts_tree=NULL;
479   proto_tree   *ext_tree;
480   size_t        ext_len;
481   guint8        ext_type;
482   guint8        ext_subtype=0;
483   size_t        hdrLen;
484
485   gint16       apptype = -1;
486
487   /* None of this really matters if we don't have a tree */
488   if (!tree) return;
489
490   /* Add our tree, if we have extensions */
491   ti = proto_tree_add_text(tree, tvb, offset, -1, "Extensions");
492   exts_tree = proto_item_add_subtree(ti, ett_a11_exts);
493
494   /* And, handle each extension */
495   while (tvb_reported_length_remaining(tvb, offset) > 0) {
496
497         /* Get our extension info */
498         ext_type = tvb_get_guint8(tvb, offset);
499         if (ext_type == GEN_AUTH_EXT) {
500           /*
501            * Very nasty . . breaks normal extensions, since the length is
502            * in the wrong place :(
503            */
504           ext_subtype = tvb_get_guint8(tvb, offset + 1);
505           ext_len = tvb_get_ntohs(tvb, offset + 2);
506           hdrLen = 4;
507     } else if (ext_type == CVSE_EXT || ext_type == OLD_CVSE_EXT) {
508           ext_len = tvb_get_ntohs(tvb, offset + 2);
509       ext_subtype = tvb_get_guint8(tvb, offset + 8);    
510       hdrLen = 4;
511         } else {
512           ext_len = tvb_get_guint8(tvb, offset + 1);
513           hdrLen = 2;
514         }
515         
516         ti = proto_tree_add_text(exts_tree, tvb, offset, ext_len + hdrLen,
517                                  "Extension: %s",
518                                  val_to_str(ext_type, a11_ext_types,
519                                             "Unknown Extension %u"));
520         ext_tree = proto_item_add_subtree(ti, ett_a11_ext);
521
522         proto_tree_add_item(ext_tree, hf_a11_ext_type, tvb, offset, 1, ext_type);
523         offset++;
524
525         if (ext_type == SS_EXT) {
526           proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len);
527           offset++;
528         }
529         else if(ext_type == CVSE_EXT || ext_type == OLD_CVSE_EXT) {
530           offset++;
531           proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len);
532           offset+=2;
533         }
534         else if (ext_type != GEN_AUTH_EXT) {
535           /* Another nasty hack since GEN_AUTH_EXT broke everything */
536           proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len);
537           offset++;
538         }
539
540         switch(ext_type) {
541         case SS_EXT:
542           proto_tree_add_item(ext_tree, hf_a11_ses_ptype, tvb, offset, 2, FALSE);
543           proto_tree_add_item(ext_tree, hf_a11_ses_key, tvb, offset+2, 4, FALSE);
544           proto_tree_add_item(ext_tree, hf_a11_ses_sidver, tvb, offset+7, 1, FALSE);
545           proto_tree_add_item(ext_tree, hf_a11_ses_mnsrid, tvb, offset+8, 2, FALSE);
546           proto_tree_add_item(ext_tree, hf_a11_ses_msid_type, tvb, offset+10, 2, FALSE);
547           proto_tree_add_item(ext_tree, hf_a11_ses_msid_len, tvb, offset+12, 1, FALSE);
548           proto_tree_add_item(ext_tree, hf_a11_ses_msid, tvb, offset+13, ext_len-13, FALSE);
549           break;
550         case MH_AUTH_EXT:
551         case MF_AUTH_EXT:
552         case FH_AUTH_EXT:
553           /* All these extensions look the same.  4 byte SPI followed by a key */
554           proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, FALSE);
555           proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset+4, ext_len-4,
556                                                   FALSE);
557           break;
558         case MN_NAI_EXT:
559           proto_tree_add_item(ext_tree, hf_a11_next_nai, tvb, offset, 
560                                                   ext_len, FALSE);
561           break;
562
563         case GEN_AUTH_EXT:      /* RFC 3012 */
564           /*
565            * Very nasty . . breaks normal extensions, since the length is
566            * in the wrong place :(
567            */
568           proto_tree_add_uint(ext_tree, hf_a11_ext_stype, tvb, offset, 1, ext_subtype);
569           offset++;
570           proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len);
571           offset+=2;
572           /* SPI */
573           proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, FALSE);
574           /* Key */
575           proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset + 4,
576                                                   ext_len - 4, FALSE);
577           
578           break;
579         case OLD_CVSE_EXT:      /* RFC 3115 */
580         case CVSE_EXT:          /* RFC 3115 */
581           proto_tree_add_item(ext_tree, hf_a11_vse_vid, tvb, offset, 4, FALSE);
582           proto_tree_add_item(ext_tree, hf_a11_vse_apptype, tvb, offset+4, 2, FALSE);
583           apptype = tvb_get_ntohs(tvb, offset+4);
584       if(apptype == 0x0101) {
585         if (tvb_reported_length_remaining(tvb, offset) > 0) {
586           dissect_a11_radius(tvb, offset+6, ext_tree, ext_len + hdrLen - 8);
587         }
588       }
589           break;
590         case OLD_NVSE_EXT:      /* RFC 3115 */
591         case NVSE_EXT:          /* RFC 3115 */
592           proto_tree_add_item(ext_tree, hf_a11_vse_vid, tvb, offset+2, 4, FALSE);
593           proto_tree_add_item(ext_tree, hf_a11_vse_apptype, tvb, offset+6, 2, FALSE);
594
595           apptype = tvb_get_ntohs(tvb, offset+6);
596       switch(apptype) {
597         case 0x0401:
598           proto_tree_add_item(ext_tree, hf_a11_vse_panid, tvb, offset+8, 5, FALSE);
599           proto_tree_add_item(ext_tree, hf_a11_vse_canid, tvb, offset+13, 5, FALSE);
600           break;
601         case 0x0501:
602           proto_tree_add_item(ext_tree, hf_a11_vse_ppaddr, tvb, offset+8, 4, FALSE);
603           break;
604         case 0x0601:
605           proto_tree_add_item(ext_tree, hf_a11_vse_dormant, tvb, offset+8, 2, FALSE);
606           break;
607         case 0x0701:
608           proto_tree_add_item(ext_tree, hf_a11_vse_code, tvb, offset+8, 1, FALSE);
609           break;
610         case 0x0801:
611           proto_tree_add_item(ext_tree, hf_a11_vse_pdit, tvb, offset+8, 1, FALSE);
612           break;
613         case 0x0802:
614           proto_tree_add_text(ext_tree, tvb, offset+8, -1, "Session Parameter - Always On");
615           break;
616         case 0x0901:
617           proto_tree_add_item(ext_tree, hf_a11_vse_srvopt, tvb, offset+8, 2, FALSE);
618           break;
619       }
620
621           break;
622         case MF_CHALLENGE_EXT:  /* RFC 3012 */
623           /* The default dissector is good here.  The challenge is all hex anyway. */
624         default:
625           proto_tree_add_item(ext_tree, hf_a11_ext, tvb, offset, ext_len, FALSE);
626           break;
627         } /* ext type */
628
629         offset += ext_len;
630   } /* while data remaining */
631
632 } /* dissect_a11_extensions */
633
634 /* Code to actually dissect the packets */
635 static int
636 dissect_a11( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
637 {
638   /* Set up structures we will need to add the protocol subtree and manage it */
639   proto_item    *ti;
640   proto_tree    *a11_tree=NULL;
641   proto_item    *tf;
642   proto_tree    *flags_tree;
643   guint8         type;
644   guint8         flags;
645   nstime_t       ident_time;
646   size_t         offset=0;
647   
648   if (!tvb_bytes_exist(tvb, offset, 1))
649         return 0;       /* not enough data to check message type */
650
651   type = tvb_get_guint8(tvb, offset);
652   if (match_strval(type, a11_types) == NULL)
653         return 0;       /* not a known message type */
654
655   /* Make entries in Protocol column and Info column on summary display */
656   
657   if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
658         col_set_str(pinfo->cinfo, COL_PROTOCOL, "3GPP2 A11");
659   if (check_col(pinfo->cinfo, COL_INFO)) 
660         col_clear(pinfo->cinfo, COL_INFO);
661
662   switch (type) {
663   case REGISTRATION_REQUEST:
664         if (check_col(pinfo->cinfo, COL_INFO)) 
665           col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Request: PDSN=%s PCF=%s", 
666                                    ip_to_str(tvb_get_ptr(tvb, 8, 4)),
667                                    ip_to_str(tvb_get_ptr(tvb,12,4)));
668         
669         if (tree) {
670           ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
671           a11_tree = proto_item_add_subtree(ti, ett_a11);
672           
673           /* type */
674           proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
675           offset++;
676           
677           /* flags */
678           flags = tvb_get_guint8(tvb, offset);
679           tf = proto_tree_add_uint(a11_tree, hf_a11_flags, tvb,
680                                                            offset, 1, flags);
681           flags_tree = proto_item_add_subtree(tf, ett_a11_flags);
682           proto_tree_add_boolean(flags_tree, hf_a11_s, tvb, offset, 1, flags);
683           proto_tree_add_boolean(flags_tree, hf_a11_b, tvb, offset, 1, flags);
684           proto_tree_add_boolean(flags_tree, hf_a11_d, tvb, offset, 1, flags);
685           proto_tree_add_boolean(flags_tree, hf_a11_m, tvb, offset, 1, flags);
686           proto_tree_add_boolean(flags_tree, hf_a11_g, tvb, offset, 1, flags);
687           proto_tree_add_boolean(flags_tree, hf_a11_v, tvb, offset, 1, flags);
688           proto_tree_add_boolean(flags_tree, hf_a11_t, tvb, offset, 1, flags);
689           offset++;
690
691           /* lifetime */
692           proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, FALSE);
693           offset +=2;
694           
695           /* home address */
696           proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
697           offset += 4;
698           
699           /* home agent address */
700           proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
701           offset += 4;
702           
703           /* Care of Address */
704           proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
705           offset += 4;
706
707           /* Identifier */
708           ident_time.secs =  tvb_get_ntohl(tvb,16)-(guint32) NTP_BASETIME;
709           ident_time.nsecs = tvb_get_ntohl(tvb,20)*1000;
710           proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
711           offset += 8;
712                 
713         } /* if tree */
714         break;
715   case REGISTRATION_REPLY:
716         if (check_col(pinfo->cinfo, COL_INFO)) 
717           col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Reply:   PDSN=%s, Code=%u", 
718                                    ip_to_str(tvb_get_ptr(tvb,8,4)), tvb_get_guint8(tvb,1));
719         
720         if (tree) {
721           /* Add Subtree */
722           ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
723           a11_tree = proto_item_add_subtree(ti, ett_a11);
724           
725           /* Type */
726           proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
727           offset++;
728           
729           /* Reply Code */
730           proto_tree_add_item(a11_tree, hf_a11_code, tvb, offset, 1, FALSE);
731           offset++;
732
733           /* Registration Lifetime */
734           proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, FALSE);
735           offset += 2;
736
737           /* Home address */
738           proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
739           offset += 4;
740
741           /* Home Agent Address */
742           proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
743           offset += 4;
744
745           /* Identifier */
746           ident_time.secs =  tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
747           ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
748           proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
749           offset += 8;
750         } /* if tree */
751         
752         break;
753   case REGISTRATION_UPDATE:
754         if (check_col(pinfo->cinfo, COL_INFO)) 
755           col_add_fstr(pinfo->cinfo, COL_INFO,"Reg Update:  PDSN=%s", 
756                                    ip_to_str(tvb_get_ptr(tvb,8,4)));
757         if (tree) {
758           /* Add Subtree */
759           ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
760           a11_tree = proto_item_add_subtree(ti, ett_a11);
761           
762           /* Type */
763           proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
764           offset++;
765
766           /* Reserved */
767           offset+=3;
768         
769           /* Home address */
770           proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
771           offset += 4;
772
773           /* Home Agent Address */
774           proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
775           offset += 4;
776
777           /* Identifier */
778           ident_time.secs =  tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
779           ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
780           proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
781           offset += 8;
782
783         } /* if tree */
784         break;
785   case REGISTRATION_ACK:
786         if (check_col(pinfo->cinfo, COL_INFO)) 
787           col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Ack:     PCF=%s Status=%u", 
788                                    ip_to_str(tvb_get_ptr(tvb, 8, 4)),
789                                    tvb_get_guint8(tvb,3));
790         if (tree) {
791           /* Add Subtree */
792           ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
793           a11_tree = proto_item_add_subtree(ti, ett_a11);
794           
795           /* Type */
796           proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
797           offset++;
798         
799           /* Reserved */
800           offset+=2;
801
802           /* Ack Status */
803           proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, FALSE);
804           offset++;
805
806           /* Home address */
807           proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
808           offset += 4;
809
810           /* Care of Address */
811           proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
812           offset += 4;
813
814           /* Identifier */
815           ident_time.secs =  tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
816           ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
817           proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
818           offset += 8;
819
820         } /* if tree */
821         break;
822   case SESSION_UPDATE: /* IOS4.3 */
823         if (check_col(pinfo->cinfo, COL_INFO)) 
824           col_add_fstr(pinfo->cinfo, COL_INFO,"Ses Update:  PDSN=%s", 
825                                    ip_to_str(tvb_get_ptr(tvb,8,4)));
826         if (tree) {
827           /* Add Subtree */
828           ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
829           a11_tree = proto_item_add_subtree(ti, ett_a11);
830           
831           /* Type */
832           proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
833           offset++;
834
835           /* Reserved */
836           offset+=3;
837         
838           /* Home address */
839           proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
840           offset += 4;
841
842           /* Home Agent Address */
843           proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
844           offset += 4;
845
846           /* Identifier */
847           ident_time.secs =  tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
848           ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
849           proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
850           offset += 8;
851
852         } /* if tree */
853         break;
854   case SESSION_ACK: /* IOS4.3 */
855         if (check_col(pinfo->cinfo, COL_INFO)) 
856           col_add_fstr(pinfo->cinfo, COL_INFO, "Ses Upd Ack: PCF=%s, Status=%u", 
857                                    ip_to_str(tvb_get_ptr(tvb, 8, 4)),
858                                    tvb_get_guint8(tvb,3));
859         if (tree) {
860           /* Add Subtree */
861           ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
862           a11_tree = proto_item_add_subtree(ti, ett_a11);
863           
864           /* Type */
865           proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
866           offset++;
867         
868           /* Reserved */
869           offset+=2;
870
871           /* Ack Status */
872           proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, FALSE);
873           offset++;
874
875           /* Home address */
876           proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
877           offset += 4;
878
879           /* Care of Address */
880           proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
881           offset += 4;
882
883           /* Identifier */
884           ident_time.secs =  tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
885           ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
886           proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
887           offset += 8;
888
889         } /* if tree */
890         break;
891   } /* End switch */
892
893   if (tree) {
894         if (tvb_reported_length_remaining(tvb, offset) > 0)
895           dissect_a11_extensions(tvb, offset, a11_tree);
896   }
897   return tvb_length(tvb);
898 } /* dissect_a11 */
899
900 /* Register the protocol with Ethereal */
901 void proto_register_a11(void)
902 {                 
903
904 /* Setup list of header fields */
905         static hf_register_info hf[] = {
906           { &hf_a11_type,
907                  { "Message Type",           "a11.type",
908                         FT_UINT8, BASE_DEC, VALS(a11_types), 0,          
909                         "A11 Message type.", HFILL }
910           },
911           { &hf_a11_flags,
912                 {"Flags", "a11.flags",
913                  FT_UINT8, BASE_HEX, NULL, 0x0,
914                  "", HFILL}
915           },
916           { &hf_a11_s,
917                  {"Simultaneous Bindings",           "a11.s",
918
919                    FT_BOOLEAN, 8, NULL, 128,          
920                    "Simultaneous Bindings Allowed", HFILL }
921           },
922           { &hf_a11_b,
923                  {"Broadcast Datagrams",           "a11.b",
924                    FT_BOOLEAN, 8, NULL, 64,          
925                    "Broadcast Datagrams requested", HFILL }
926           },
927           { &hf_a11_d,
928                  { "Co-lcated Care-of Address",           "a11.d",
929                    FT_BOOLEAN, 8, NULL, 32,          
930                    "MN using Co-located Care-of address", HFILL }
931           },
932           { &hf_a11_m,
933                  {"Minimal Encapsulation",           "a11.m",
934                    FT_BOOLEAN, 8, NULL, 16,          
935                    "MN wants Minimal encapsulation", HFILL }
936           },
937           { &hf_a11_g,
938                  {"GRE",           "a11.g",
939                    FT_BOOLEAN, 8, NULL, 8,          
940                    "MN wants GRE encapsulation", HFILL }
941           },
942           { &hf_a11_v,
943                  { "Van Jacobson",           "a11.v",
944                    FT_BOOLEAN, 8, NULL, 4,          
945                    "Van Jacobson", HFILL }
946           },
947           { &hf_a11_t,
948                  { "Reverse Tunneling",           "a11.t",
949                    FT_BOOLEAN, 8, NULL, 2,          
950                    "Reverse tunneling requested", HFILL }
951           },
952           { &hf_a11_code,
953                  { "Reply Code",           "a11.code",
954                         FT_UINT8, BASE_DEC, VALS(a11_reply_codes), 0,          
955                         "A11 Registration Reply code.", HFILL }
956           },
957           { &hf_a11_status,
958                  { "Reply Status",           "a11.ackstat",
959                         FT_UINT8, BASE_DEC, VALS(a11_ack_status), 0,          
960                         "A11 Registration Ack Status.", HFILL }
961           },
962           { &hf_a11_life,
963                  { "Lifetime",           "a11.life",
964                         FT_UINT16, BASE_DEC, NULL, 0,          
965                         "A11 Registration Lifetime.", HFILL }
966           },
967           { &hf_a11_homeaddr,
968                  { "Home Address",           "a11.homeaddr",
969                         FT_IPv4, BASE_NONE, NULL, 0,          
970                         "Mobile Node's home address.", HFILL }
971           },
972           
973           { &hf_a11_haaddr,
974                  { "Home Agent",           "a11.haaddr",
975                         FT_IPv4, BASE_NONE, NULL, 0,          
976                         "Home agent IP Address.", HFILL }
977           },
978           { &hf_a11_coa,
979                  { "Care of Address",           "a11.coa",
980                         FT_IPv4, BASE_NONE, NULL, 0,          
981                         "Care of Address.", HFILL }
982           },
983           { &hf_a11_ident,
984                  { "Identification",           "a11.ident",
985                         FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,          
986                         "MN Identification.", HFILL }
987           },
988           { &hf_a11_ext_type,
989                  { "Extension Type",           "a11.ext.type",
990                         FT_UINT8, BASE_DEC, VALS(a11_ext_types), 0,          
991                         "Mobile IP Extension Type.", HFILL }
992           },
993           { &hf_a11_ext_stype,
994                  { "Gen Auth Ext SubType",           "a11.ext.auth.subtype",
995                         FT_UINT8, BASE_DEC, VALS(a11_ext_stypes), 0,          
996                         "Mobile IP Auth Extension Sub Type.", HFILL }
997           },
998           { &hf_a11_ext_len,
999                  { "Extension Length",         "a11.ext.len",
1000                         FT_UINT16, BASE_DEC, NULL, 0,
1001                         "Mobile IP Extension Length.", HFILL }
1002           },
1003           { &hf_a11_ext,
1004                  { "Extension",                      "a11.extension",
1005                         FT_BYTES, BASE_HEX, NULL, 0,
1006                         "Extension", HFILL }
1007           },
1008           { &hf_a11_aext_spi,
1009                  { "SPI",                      "a11.auth.spi",
1010                         FT_UINT32, BASE_HEX, NULL, 0,
1011                         "Authentication Header Security Parameter Index.", HFILL }
1012           },
1013           { &hf_a11_aext_auth,
1014                  { "Authenticator",            "a11.auth.auth",
1015                         FT_BYTES, BASE_NONE, NULL, 0,
1016                         "Authenticator.", HFILL }
1017           },
1018           { &hf_a11_next_nai,
1019                  { "NAI",                      "a11.nai",
1020                         FT_STRING, BASE_NONE, NULL, 0,
1021                         "NAI", HFILL }
1022           },
1023           { &hf_a11_ses_key,
1024                  { "Key",                      "a11.ext.key",
1025                         FT_UINT32, BASE_HEX, NULL, 0,
1026                         "Session Key.", HFILL }
1027           },
1028           { &hf_a11_ses_sidver,
1029                 { "Session ID Version",         "a11.ext.sidver",
1030                         FT_UINT8, BASE_DEC, NULL, 3,
1031                         "Session ID Version", HFILL}
1032           },
1033           { &hf_a11_ses_mnsrid,
1034                  { "MNSR-ID",                      "a11.ext.mnsrid",
1035                         FT_UINT16, BASE_HEX, NULL, 0,
1036                         "MNSR-ID", HFILL }
1037           },
1038           { &hf_a11_ses_msid_type,
1039                  { "MSID Type",                      "a11.ext.msid_type",
1040                         FT_UINT16, BASE_DEC, NULL, 0,
1041                         "MSID Type.", HFILL }
1042           },
1043           { &hf_a11_ses_msid_len,
1044                  { "MSID Length",                      "a11.ext.msid_len",
1045                         FT_UINT8, BASE_DEC, NULL, 0,
1046                         "MSID Length.", HFILL }
1047           },
1048           { &hf_a11_ses_msid,
1049                  { "MSID(BCD)",                      "a11.ext.msid",
1050                         FT_BYTES, BASE_HEX, NULL, 0,
1051                         "MSID(BCD).", HFILL }
1052           },
1053           { &hf_a11_ses_ptype,
1054                  { "Protocol Type",                      "a11.ext.ptype",
1055                         FT_UINT16, BASE_HEX, NULL, 0,
1056                         "Protocol Type.", HFILL }
1057           },
1058           { &hf_a11_vse_vid,
1059                  { "Vendor ID",                      "a11.ext.vid",
1060                         FT_UINT32, BASE_HEX, NULL, 0,
1061                         "Vendor ID.", HFILL }
1062           },
1063           { &hf_a11_vse_apptype,
1064                  { "Application Type",                      "a11.ext.apptype",
1065                         FT_UINT8, BASE_HEX, VALS(a11_ext_app), 0,
1066                         "Application Type.", HFILL }
1067           },
1068           { &hf_a11_vse_ppaddr,
1069                  { "Anchor P-P Address",           "a11.ext.ppaddr",
1070                         FT_IPv4, BASE_NONE, NULL, 0,          
1071                         "Anchor P-P Address.", HFILL }
1072           },
1073           { &hf_a11_vse_dormant,
1074                  { "All Dormant Indicator",           "a11.ext.dormant",
1075                         FT_UINT16, BASE_HEX, VALS(a11_ext_dormant), 0,          
1076                         "All Dormant Indicator.", HFILL }
1077           },
1078           { &hf_a11_vse_code,
1079                  { "Reply Code",           "a11.ext.code",
1080                         FT_UINT8, BASE_DEC, VALS(a11_reply_codes), 0,          
1081                         "PDSN Code.", HFILL }
1082           },
1083           { &hf_a11_vse_pdit,
1084                  { "PDSN Code",                      "a11.ext.code",
1085                         FT_UINT8, BASE_HEX, VALS(a11_ext_nvose_pdsn_code), 0,
1086                         "PDSN Code.", HFILL }
1087           },
1088           { &hf_a11_vse_srvopt,
1089                  { "Service Option",                      "a11.ext.srvopt",
1090                         FT_UINT16, BASE_HEX, VALS(a11_ext_nvose_srvopt), 0,
1091                         "Service Option.", HFILL }
1092           },
1093           { &hf_a11_vse_panid,
1094                  { "PANID",                      "a11.ext.panid",
1095                         FT_BYTES, BASE_HEX, NULL, 0,
1096                         "PANID", HFILL }
1097           },
1098           { &hf_a11_vse_canid,
1099                  { "CANID",                      "a11.ext.canid",
1100                         FT_BYTES, BASE_HEX, NULL, 0,
1101                         "CANID", HFILL }
1102           },
1103      
1104         };
1105
1106         /* Setup protocol subtree array */
1107         static gint *ett[] = {
1108                 &ett_a11,
1109                 &ett_a11_flags,
1110                 &ett_a11_ext,
1111                 &ett_a11_exts,
1112                 &ett_a11_radius,
1113                 &ett_a11_radiuses,
1114         };
1115
1116         /* Register the protocol name and description */
1117         proto_a11 = proto_register_protocol("3GPP2 A11", "3GPP2 A11", "a11");
1118
1119         /* Register the dissector by name */
1120         new_register_dissector("a11", dissect_a11, proto_a11);
1121
1122         /* Required function calls to register the header fields and subtrees used */
1123         proto_register_field_array(proto_a11, hf, array_length(hf));
1124         proto_register_subtree_array(ett, array_length(ett));
1125 }
1126
1127 void
1128 proto_reg_handoff_a11(void)
1129 {
1130         dissector_handle_t a11_handle;
1131
1132         a11_handle = find_dissector("a11");
1133         dissector_add("udp.port", UDP_PORT_3GA11, a11_handle);
1134 }
1135