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'.
8 * Routines for Mobile IP dissection
9 * Copyright 2000, Stefan Raab <sraab@cisco.com>
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
15 * Copyright 1998 Gerald Combs
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.
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.
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.
43 #include <epan/packet.h>
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;
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;
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;
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;
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
103 REGISTRATION_REQUEST = 1,
104 REGISTRATION_REPLY = 3,
105 REGISTRATION_UPDATE = 20,
106 REGISTRATION_ACK =21,
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"},
121 static const value_string a11_reply_codes[]= {
123 {9, "Connection Update"},
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"},
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"},
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"},
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 */
184 MF_CHALLENGE_EXT = 132, /* RFC 3012 */
185 OLD_NVSE_EXT = 133, /* RFC 3115 */
186 NVSE_EXT = 134 /* RFC 3115 */
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)"},
206 static const value_string a11_ext_stypes[]= {
207 {1, "MN AAA Extension"},
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"},
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"},
231 static const value_string a11_ext_dormant[]= {
232 {0x0000, "all MS packet data service instances are dormant"},
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)"},
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)"},
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
266 struct radius_attribute {
267 char attrname[ATTRIBUTE_NAME_LEN_MAX];
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},
279 {"MSID", 31, -1, 15, ATTR_TYPE_MSID},
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},
307 #define NUM_ATTR (sizeof(attrs)/sizeof(struct radius_attribute))
309 #define MAX_STRVAL 16
311 #define RADIUS_VENDOR_SPECIFIC 26
312 #define SKIP_HDR_LEN 6
314 static void dissect_a11_radius( tvbuff_t *, int, proto_tree *, int);
316 /* RADIUS attributed */
318 dissect_a11_radius( tvbuff_t *tvb, int offset, proto_tree *tree, int app_len)
321 proto_tree *radius_tree=NULL;
324 guint8 radius_subtype;
330 guchar str_val[MAX_STRVAL];
331 guint radius_vendor_id = 0;
333 /* None of this really matters if we don't have a tree */
338 /* return if length of extension is not valid */
339 if (tvb_reported_length_remaining(tvb, offset) < 12) {
343 ti = proto_tree_add_text(tree, tvb, offset - 2, app_len, "Airlink Record");
345 radius_tree = proto_item_add_subtree(ti, ett_a11_radiuses);
347 /* And, handle each record */
348 while (tvb_reported_length_remaining(tvb, offset) > 0
349 && ((int)offset-(int)offset0) <app_len-2)
352 radius_type = tvb_get_guint8(tvb, offset);
353 radius_len = tvb_get_guint8(tvb, offset + 1);
355 if (radius_type == RADIUS_VENDOR_SPECIFIC)
357 radius_vendor_id = tvb_get_ntohl(tvb, offset +2);
359 if(radius_vendor_id != THE3GPP2_VENDOR_ID)
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;
371 if(radius_type == 31)
373 strncpy(str_val, tvb_get_ptr(tvb,offset+2,radius_len-2),
375 if(radius_len-2 < MAX_STRVAL) {
376 str_val[radius_len-2] = '\0';
379 str_val[MAX_STRVAL-1] = '\0';
381 ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
382 "MSID: %s", str_val);
384 else if (radius_type == 46)
386 ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
387 "Acct Session Time: %d",tvb_get_ntohl(tvb,offset+2));
391 ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
392 "Unknown RADIUS Attributes (Type: %d)", radius_type);
395 offset += radius_len;
399 radius_len = tvb_get_guint8(tvb, offset + 1);
401 offset += SKIP_HDR_LEN;
404 /* Detect Airlink Record Type */
406 while (radius_len - 6 > radius_offset)
409 radius_subtype = tvb_get_guint8(tvb, offset + radius_offset);
410 attribute_len = tvb_get_guint8(tvb, offset + radius_offset + 1);
413 for(i = 0; i < NUM_ATTR; i++) {
414 if (attrs[i].subtype == radius_subtype) {
420 if(attribute_type >= 0) {
421 switch(attrs[attribute_type].data_type) {
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));
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)));
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"));
439 strncpy(str_val, tvb_get_ptr(tvb,offset+radius_offset+2,attribute_len - 2),
441 if(attribute_len - 2 < MAX_STRVAL) {
442 str_val[attribute_len - 2] = '\0';
445 str_val[MAX_STRVAL-1] = '\0';
447 ti = proto_tree_add_text(radius_tree, tvb, offset+radius_offset,
449 "3GPP2: %s (%s)", attrs[attribute_type].attrname, str_val);
454 ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
455 "RADIUS: %s", attrs[attribute_type].attrname);
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);
465 radius_offset += attribute_len;
467 offset += radius_len - 6;
473 /* Code to dissect extensions */
475 dissect_a11_extensions( tvbuff_t *tvb, int offset, proto_tree *tree)
478 proto_tree *exts_tree=NULL;
479 proto_tree *ext_tree;
482 guint8 ext_subtype=0;
487 /* None of this really matters if we don't have a tree */
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);
494 /* And, handle each extension */
495 while (tvb_reported_length_remaining(tvb, offset) > 0) {
497 /* Get our extension info */
498 ext_type = tvb_get_guint8(tvb, offset);
499 if (ext_type == GEN_AUTH_EXT) {
501 * Very nasty . . breaks normal extensions, since the length is
502 * in the wrong place :(
504 ext_subtype = tvb_get_guint8(tvb, offset + 1);
505 ext_len = tvb_get_ntohs(tvb, offset + 2);
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);
512 ext_len = tvb_get_guint8(tvb, offset + 1);
516 ti = proto_tree_add_text(exts_tree, tvb, offset, ext_len + hdrLen,
518 val_to_str(ext_type, a11_ext_types,
519 "Unknown Extension %u"));
520 ext_tree = proto_item_add_subtree(ti, ett_a11_ext);
522 proto_tree_add_item(ext_tree, hf_a11_ext_type, tvb, offset, 1, ext_type);
525 if (ext_type == SS_EXT) {
526 proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len);
529 else if(ext_type == CVSE_EXT || ext_type == OLD_CVSE_EXT) {
531 proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len);
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);
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);
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,
559 proto_tree_add_item(ext_tree, hf_a11_next_nai, tvb, offset,
563 case GEN_AUTH_EXT: /* RFC 3012 */
565 * Very nasty . . breaks normal extensions, since the length is
566 * in the wrong place :(
568 proto_tree_add_uint(ext_tree, hf_a11_ext_stype, tvb, offset, 1, ext_subtype);
570 proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len);
573 proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, FALSE);
575 proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset + 4,
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);
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);
595 apptype = tvb_get_ntohs(tvb, offset+6);
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);
602 proto_tree_add_item(ext_tree, hf_a11_vse_ppaddr, tvb, offset+8, 4, FALSE);
605 proto_tree_add_item(ext_tree, hf_a11_vse_dormant, tvb, offset+8, 2, FALSE);
608 proto_tree_add_item(ext_tree, hf_a11_vse_code, tvb, offset+8, 1, FALSE);
611 proto_tree_add_item(ext_tree, hf_a11_vse_pdit, tvb, offset+8, 1, FALSE);
614 proto_tree_add_text(ext_tree, tvb, offset+8, -1, "Session Parameter - Always On");
617 proto_tree_add_item(ext_tree, hf_a11_vse_srvopt, tvb, offset+8, 2, FALSE);
622 case MF_CHALLENGE_EXT: /* RFC 3012 */
623 /* The default dissector is good here. The challenge is all hex anyway. */
625 proto_tree_add_item(ext_tree, hf_a11_ext, tvb, offset, ext_len, FALSE);
630 } /* while data remaining */
632 } /* dissect_a11_extensions */
634 /* Code to actually dissect the packets */
636 dissect_a11( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
638 /* Set up structures we will need to add the protocol subtree and manage it */
640 proto_tree *a11_tree=NULL;
642 proto_tree *flags_tree;
648 if (!tvb_bytes_exist(tvb, offset, 1))
649 return 0; /* not enough data to check message type */
651 type = tvb_get_guint8(tvb, offset);
652 if (match_strval(type, a11_types) == NULL)
653 return 0; /* not a known message type */
655 /* Make entries in Protocol column and Info column on summary display */
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);
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)));
670 ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
671 a11_tree = proto_item_add_subtree(ti, ett_a11);
674 proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
678 flags = tvb_get_guint8(tvb, offset);
679 tf = proto_tree_add_uint(a11_tree, hf_a11_flags, tvb,
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);
692 proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, FALSE);
696 proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
699 /* home agent address */
700 proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
703 /* Care of Address */
704 proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
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);
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));
722 ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
723 a11_tree = proto_item_add_subtree(ti, ett_a11);
726 proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
730 proto_tree_add_item(a11_tree, hf_a11_code, tvb, offset, 1, FALSE);
733 /* Registration Lifetime */
734 proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, FALSE);
738 proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
741 /* Home Agent Address */
742 proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
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);
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)));
759 ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
760 a11_tree = proto_item_add_subtree(ti, ett_a11);
763 proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
770 proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
773 /* Home Agent Address */
774 proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
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);
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));
792 ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
793 a11_tree = proto_item_add_subtree(ti, ett_a11);
796 proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
803 proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, FALSE);
807 proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
810 /* Care of Address */
811 proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
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);
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)));
828 ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
829 a11_tree = proto_item_add_subtree(ti, ett_a11);
832 proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
839 proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
842 /* Home Agent Address */
843 proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
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);
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));
861 ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
862 a11_tree = proto_item_add_subtree(ti, ett_a11);
865 proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
872 proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, FALSE);
876 proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
879 /* Care of Address */
880 proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
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);
894 if (tvb_reported_length_remaining(tvb, offset) > 0)
895 dissect_a11_extensions(tvb, offset, a11_tree);
897 return tvb_length(tvb);
900 /* Register the protocol with Ethereal */
901 void proto_register_a11(void)
904 /* Setup list of header fields */
905 static hf_register_info hf[] = {
907 { "Message Type", "a11.type",
908 FT_UINT8, BASE_DEC, VALS(a11_types), 0,
909 "A11 Message type.", HFILL }
912 {"Flags", "a11.flags",
913 FT_UINT8, BASE_HEX, NULL, 0x0,
917 {"Simultaneous Bindings", "a11.s",
919 FT_BOOLEAN, 8, NULL, 128,
920 "Simultaneous Bindings Allowed", HFILL }
923 {"Broadcast Datagrams", "a11.b",
924 FT_BOOLEAN, 8, NULL, 64,
925 "Broadcast Datagrams requested", HFILL }
928 { "Co-lcated Care-of Address", "a11.d",
929 FT_BOOLEAN, 8, NULL, 32,
930 "MN using Co-located Care-of address", HFILL }
933 {"Minimal Encapsulation", "a11.m",
934 FT_BOOLEAN, 8, NULL, 16,
935 "MN wants Minimal encapsulation", HFILL }
939 FT_BOOLEAN, 8, NULL, 8,
940 "MN wants GRE encapsulation", HFILL }
943 { "Van Jacobson", "a11.v",
944 FT_BOOLEAN, 8, NULL, 4,
945 "Van Jacobson", HFILL }
948 { "Reverse Tunneling", "a11.t",
949 FT_BOOLEAN, 8, NULL, 2,
950 "Reverse tunneling requested", HFILL }
953 { "Reply Code", "a11.code",
954 FT_UINT8, BASE_DEC, VALS(a11_reply_codes), 0,
955 "A11 Registration Reply code.", HFILL }
958 { "Reply Status", "a11.ackstat",
959 FT_UINT8, BASE_DEC, VALS(a11_ack_status), 0,
960 "A11 Registration Ack Status.", HFILL }
963 { "Lifetime", "a11.life",
964 FT_UINT16, BASE_DEC, NULL, 0,
965 "A11 Registration Lifetime.", HFILL }
968 { "Home Address", "a11.homeaddr",
969 FT_IPv4, BASE_NONE, NULL, 0,
970 "Mobile Node's home address.", HFILL }
974 { "Home Agent", "a11.haaddr",
975 FT_IPv4, BASE_NONE, NULL, 0,
976 "Home agent IP Address.", HFILL }
979 { "Care of Address", "a11.coa",
980 FT_IPv4, BASE_NONE, NULL, 0,
981 "Care of Address.", HFILL }
984 { "Identification", "a11.ident",
985 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
986 "MN Identification.", HFILL }
989 { "Extension Type", "a11.ext.type",
990 FT_UINT8, BASE_DEC, VALS(a11_ext_types), 0,
991 "Mobile IP Extension Type.", HFILL }
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 }
999 { "Extension Length", "a11.ext.len",
1000 FT_UINT16, BASE_DEC, NULL, 0,
1001 "Mobile IP Extension Length.", HFILL }
1004 { "Extension", "a11.extension",
1005 FT_BYTES, BASE_HEX, NULL, 0,
1006 "Extension", HFILL }
1009 { "SPI", "a11.auth.spi",
1010 FT_UINT32, BASE_HEX, NULL, 0,
1011 "Authentication Header Security Parameter Index.", HFILL }
1013 { &hf_a11_aext_auth,
1014 { "Authenticator", "a11.auth.auth",
1015 FT_BYTES, BASE_NONE, NULL, 0,
1016 "Authenticator.", HFILL }
1020 FT_STRING, BASE_NONE, NULL, 0,
1024 { "Key", "a11.ext.key",
1025 FT_UINT32, BASE_HEX, NULL, 0,
1026 "Session Key.", HFILL }
1028 { &hf_a11_ses_sidver,
1029 { "Session ID Version", "a11.ext.sidver",
1030 FT_UINT8, BASE_DEC, NULL, 3,
1031 "Session ID Version", HFILL}
1033 { &hf_a11_ses_mnsrid,
1034 { "MNSR-ID", "a11.ext.mnsrid",
1035 FT_UINT16, BASE_HEX, NULL, 0,
1038 { &hf_a11_ses_msid_type,
1039 { "MSID Type", "a11.ext.msid_type",
1040 FT_UINT16, BASE_DEC, NULL, 0,
1041 "MSID Type.", HFILL }
1043 { &hf_a11_ses_msid_len,
1044 { "MSID Length", "a11.ext.msid_len",
1045 FT_UINT8, BASE_DEC, NULL, 0,
1046 "MSID Length.", HFILL }
1049 { "MSID(BCD)", "a11.ext.msid",
1050 FT_BYTES, BASE_HEX, NULL, 0,
1051 "MSID(BCD).", HFILL }
1053 { &hf_a11_ses_ptype,
1054 { "Protocol Type", "a11.ext.ptype",
1055 FT_UINT16, BASE_HEX, NULL, 0,
1056 "Protocol Type.", HFILL }
1059 { "Vendor ID", "a11.ext.vid",
1060 FT_UINT32, BASE_HEX, NULL, 0,
1061 "Vendor ID.", HFILL }
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 }
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 }
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 }
1079 { "Reply Code", "a11.ext.code",
1080 FT_UINT8, BASE_DEC, VALS(a11_reply_codes), 0,
1081 "PDSN Code.", HFILL }
1084 { "PDSN Code", "a11.ext.code",
1085 FT_UINT8, BASE_HEX, VALS(a11_ext_nvose_pdsn_code), 0,
1086 "PDSN Code.", HFILL }
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 }
1093 { &hf_a11_vse_panid,
1094 { "PANID", "a11.ext.panid",
1095 FT_BYTES, BASE_HEX, NULL, 0,
1098 { &hf_a11_vse_canid,
1099 { "CANID", "a11.ext.canid",
1100 FT_BYTES, BASE_HEX, NULL, 0,
1106 /* Setup protocol subtree array */
1107 static gint *ett[] = {
1116 /* Register the protocol name and description */
1117 proto_a11 = proto_register_protocol("3GPP2 A11", "3GPP2 A11", "a11");
1119 /* Register the dissector by name */
1120 new_register_dissector("a11", dissect_a11, proto_a11);
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));
1128 proto_reg_handoff_a11(void)
1130 dissector_handle_t a11_handle;
1132 a11_handle = find_dissector("a11");
1133 dissector_add("udp.port", UDP_PORT_3GA11, a11_handle);