1 |
|
|
/* $OpenBSD: print-gtp.c,v 1.9 2015/12/22 21:01:07 mmcc Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org> |
4 |
|
|
* |
5 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
6 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
7 |
|
|
* copyright notice and this permission notice appear in all copies. |
8 |
|
|
* |
9 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 |
|
|
*/ |
17 |
|
|
|
18 |
|
|
/* |
19 |
|
|
* Decoder for the GPRS Trunking Protocol (GTP). |
20 |
|
|
* |
21 |
|
|
* This work has been kindly sponsored by SystemNet (www.systemnet.no). |
22 |
|
|
* |
23 |
|
|
* GTPv0 standards are available from the ETSI website: |
24 |
|
|
* |
25 |
|
|
* http://pda.etsi.org/pda/ |
26 |
|
|
* |
27 |
|
|
* GTPv1 standards are available from the 3GPP website: |
28 |
|
|
* |
29 |
|
|
* http://www.3gpp.org/specifications |
30 |
|
|
* |
31 |
|
|
* The following standards have been referenced to create this decoder: |
32 |
|
|
* |
33 |
|
|
* ETSI GSM 09.60 - GPRS Tunnelling Protocol (GTPv0) |
34 |
|
|
* ETSI GSM 12.15 - GPRS Charging (GTPv0') |
35 |
|
|
* |
36 |
|
|
* 3GPP TS 23.003 - Numbering, addressing and identification |
37 |
|
|
* 3GPP TS 24.008 - Core network protocols |
38 |
|
|
* 3GPP TS 29.002 - Mobile Application Part (MAP) specification |
39 |
|
|
* 3GPP TS 29.060 - GPRS Tunnelling Protocol (GTPv1-C/GTPv1-U) |
40 |
|
|
* 3GPP TS 32.295 - Charging Data Record (CDR) transfer (GTPv1') |
41 |
|
|
*/ |
42 |
|
|
|
43 |
|
|
#include <sys/time.h> |
44 |
|
|
#include <sys/socket.h> |
45 |
|
|
#include <sys/types.h> |
46 |
|
|
|
47 |
|
|
#include <netinet/in.h> |
48 |
|
|
#include <netinet/ip.h> |
49 |
|
|
#include <netinet/ip_var.h> |
50 |
|
|
|
51 |
|
|
#include <ctype.h> |
52 |
|
|
#include <stdio.h> |
53 |
|
|
#include <stdlib.h> |
54 |
|
|
#include <string.h> |
55 |
|
|
|
56 |
|
|
#include "addrtoname.h" |
57 |
|
|
#include "interface.h" |
58 |
|
|
#include "gtp.h" |
59 |
|
|
|
60 |
|
|
void gtp_print(const u_char *, u_int, u_short, u_short); |
61 |
|
|
void gtp_decode_ie(const u_char *, u_short, int); |
62 |
|
|
void gtp_print_tbcd(const u_char *, u_int); |
63 |
|
|
void gtp_print_user_address(const u_char *, u_int); |
64 |
|
|
void gtp_print_apn(const u_char *, u_int); |
65 |
|
|
void gtp_print_str(const char **, u_int); |
66 |
|
|
|
67 |
|
|
void gtp_v0_print(const u_char *, u_int, u_short, u_short); |
68 |
|
|
void gtp_v0_print_prime(const u_char *); |
69 |
|
|
int gtp_v0_print_tv(const u_char *, u_int); |
70 |
|
|
int gtp_v0_print_tlv(const u_char *, u_int); |
71 |
|
|
|
72 |
|
|
void gtp_v1_print(const u_char *, u_int, u_short, u_short); |
73 |
|
|
void gtp_v1_print_ctrl(const u_char *, u_int, struct gtp_v1_hdr *); |
74 |
|
|
void gtp_v1_print_user(const u_char *, u_int, struct gtp_v1_hdr *); |
75 |
|
|
void gtp_v1_print_prime(const u_char *, struct gtp_v1_prime_hdr *); |
76 |
|
|
int gtp_v1_print_tv(const u_char *, u_int); |
77 |
|
|
int gtp_v1_print_tlv(const u_char *, u_int); |
78 |
|
|
|
79 |
|
|
/* GTPv0 message types. */ |
80 |
|
|
static struct tok gtp_v0_msgtype[] = { |
81 |
|
|
|
82 |
|
|
{ 1, "Echo Request" }, |
83 |
|
|
{ 2, "Echo Response" }, |
84 |
|
|
{ 3, "Version Not Supported" }, |
85 |
|
|
{ 4, "Node Alive Request" }, |
86 |
|
|
{ 5, "Node Alive Response" }, |
87 |
|
|
{ 6, "Redirection Request" }, |
88 |
|
|
{ 7, "Redirection Response" }, |
89 |
|
|
{ 16, "Create PDP Context Request" }, |
90 |
|
|
{ 17, "Create PDP Context Response" }, |
91 |
|
|
{ 18, "Update PDP Context Request" }, |
92 |
|
|
{ 19, "Update PDP Context Response" }, |
93 |
|
|
{ 20, "Delete PDP Context Request" }, |
94 |
|
|
{ 21, "Delete PDP Context Response" }, |
95 |
|
|
{ 22, "Create AA PDP Context Request" }, |
96 |
|
|
{ 23, "Create AA PDP Context Response" }, |
97 |
|
|
{ 24, "Delete AA PDP Context Request" }, |
98 |
|
|
{ 25, "Delete AA PDP Context Response" }, |
99 |
|
|
{ 26, "Error Indication" }, |
100 |
|
|
{ 27, "PDU Notification Request" }, |
101 |
|
|
{ 28, "PDU Notification Response" }, |
102 |
|
|
{ 29, "PDU Notification Reject Request" }, |
103 |
|
|
{ 30, "PDU Notification Reject Response" }, |
104 |
|
|
{ 32, "Send Routeing Information Request" }, |
105 |
|
|
{ 33, "Send Routeing Information Response" }, |
106 |
|
|
{ 34, "Failure Report Request" }, |
107 |
|
|
{ 35, "Failure Report Response" }, |
108 |
|
|
{ 36, "MS GPRS Present Request" }, |
109 |
|
|
{ 37, "MS GPRS Present Response" }, |
110 |
|
|
{ 48, "Identification Request" }, |
111 |
|
|
{ 49, "Identification Response" }, |
112 |
|
|
{ 50, "SGSN Context Request" }, |
113 |
|
|
{ 51, "SGSN Context Response" }, |
114 |
|
|
{ 52, "SGSN Context Acknowledge" }, |
115 |
|
|
{ 240, "Data Record Transfer Request" }, |
116 |
|
|
{ 241, "Data Record Transfer Response" }, |
117 |
|
|
{ 255, "T-PDU" }, |
118 |
|
|
|
119 |
|
|
{ 0, NULL } |
120 |
|
|
}; |
121 |
|
|
|
122 |
|
|
/* GTPv0 causes. */ |
123 |
|
|
static struct tok gtp_v0_cause[] = { |
124 |
|
|
|
125 |
|
|
{ 0, "Request IMSI" }, |
126 |
|
|
{ 1, "Request IMEI" }, |
127 |
|
|
{ 2, "Request IMSI and IMEI" }, |
128 |
|
|
{ 3, "No identity needed" }, |
129 |
|
|
{ 4, "MS refuses" }, |
130 |
|
|
{ 5, "MS is not GPRS responding" }, |
131 |
|
|
{ 128, "Request accepted" }, |
132 |
|
|
{ 192, "Non-existent" }, |
133 |
|
|
{ 193, "Invalid message format" }, |
134 |
|
|
{ 194, "IMSI not known" }, |
135 |
|
|
{ 195, "MS is GPRS detached" }, |
136 |
|
|
{ 196, "MS is not GPRS responding" }, |
137 |
|
|
{ 197, "MS refuses" }, |
138 |
|
|
{ 198, "Version not supported" }, |
139 |
|
|
{ 199, "No resources available" }, |
140 |
|
|
{ 200, "Service not supported" }, |
141 |
|
|
{ 201, "Mandatory IE incorrect" }, |
142 |
|
|
{ 202, "Mandatory IE missing" }, |
143 |
|
|
{ 203, "Optional IE incorrect" }, |
144 |
|
|
{ 204, "System failure" }, |
145 |
|
|
{ 205, "Roaming restriction" }, |
146 |
|
|
{ 206, "P-TMSI signature mismatch" }, |
147 |
|
|
{ 207, "GPRS connection suspended" }, |
148 |
|
|
{ 208, "Authentication failure" }, |
149 |
|
|
{ 209, "User authentication failed" }, |
150 |
|
|
|
151 |
|
|
{ 0, NULL } |
152 |
|
|
}; |
153 |
|
|
|
154 |
|
|
/* GTPv1 message types. */ |
155 |
|
|
static struct tok gtp_v1_msgtype[] = { |
156 |
|
|
|
157 |
|
|
{ 1, "Echo Request" }, |
158 |
|
|
{ 2, "Echo Response" }, |
159 |
|
|
{ 3, "Version Not Supported" }, |
160 |
|
|
{ 4, "Node Alive Request" }, |
161 |
|
|
{ 5, "Node Alive Response" }, |
162 |
|
|
{ 6, "Redirection Request" }, |
163 |
|
|
{ 7, "Redirection Response" }, |
164 |
|
|
{ 16, "Create PDP Context Request" }, |
165 |
|
|
{ 17, "Create PDP Context Response" }, |
166 |
|
|
{ 18, "Update PDP Context Request" }, |
167 |
|
|
{ 19, "Update PDP Context Response" }, |
168 |
|
|
{ 20, "Delete PDP Context Request" }, |
169 |
|
|
{ 21, "Delete PDP Context Response" }, |
170 |
|
|
{ 22, "Initiate PDP Context Activiation Request" }, |
171 |
|
|
{ 23, "Initiate PDP Context Activiation Response" }, |
172 |
|
|
{ 26, "Error Indication" }, |
173 |
|
|
{ 27, "PDU Notification Request" }, |
174 |
|
|
{ 28, "PDU Notification Response" }, |
175 |
|
|
{ 29, "PDU Notification Reject Request" }, |
176 |
|
|
{ 30, "PDU Notification Reject Response" }, |
177 |
|
|
{ 31, "Supported Extension Headers Notification" }, |
178 |
|
|
{ 32, "Send Routeing Information for GPRS Request" }, |
179 |
|
|
{ 33, "Send Routeing Information for GPRS Response" }, |
180 |
|
|
{ 34, "Failure Report Request" }, |
181 |
|
|
{ 35, "Failure Report Response" }, |
182 |
|
|
{ 36, "Note MS GPRS Present Request" }, |
183 |
|
|
{ 37, "Note MS GPRS Present Response" }, |
184 |
|
|
{ 48, "Identification Request" }, |
185 |
|
|
{ 49, "Identification Response" }, |
186 |
|
|
{ 50, "SGSN Context Request" }, |
187 |
|
|
{ 51, "SGSN Context Response" }, |
188 |
|
|
{ 52, "SGSN Context Acknowledge" }, |
189 |
|
|
{ 53, "Forward Relocation Request" }, |
190 |
|
|
{ 54, "Forward Relocation Response" }, |
191 |
|
|
{ 55, "Forward Relocation Complete" }, |
192 |
|
|
{ 56, "Relocation Cancel Request" }, |
193 |
|
|
{ 57, "Relocation Cancel Response" }, |
194 |
|
|
{ 58, "Forward SRNS Context" }, |
195 |
|
|
{ 59, "Forward Relocation Complete Acknowledge" }, |
196 |
|
|
{ 60, "Forward SRNS Context Acknowledge" }, |
197 |
|
|
{ 70, "RAN Information Relay" }, |
198 |
|
|
{ 96, "MBMS Notification Request" }, |
199 |
|
|
{ 97, "MBMS Notification Response" }, |
200 |
|
|
{ 98, "MBMS Notification Reject Request" }, |
201 |
|
|
{ 99, "MBMS Notification Reject Response" }, |
202 |
|
|
{ 100, "Create MBMS Context Request" }, |
203 |
|
|
{ 101, "Create MBMS Context Response" }, |
204 |
|
|
{ 102, "Update MBMS Context Request" }, |
205 |
|
|
{ 103, "Update MBMS Context Response" }, |
206 |
|
|
{ 104, "Delete MBMS Context Request" }, |
207 |
|
|
{ 105, "Delete MBMS Context Response" }, |
208 |
|
|
{ 112, "MBMS Registration Request" }, |
209 |
|
|
{ 113, "MBMS Registration Response" }, |
210 |
|
|
{ 114, "MBMS De-Registration Request" }, |
211 |
|
|
{ 115, "MBMS De-Registration Response" }, |
212 |
|
|
{ 116, "MBMS Session Start Request" }, |
213 |
|
|
{ 117, "MBMS Session Start Response" }, |
214 |
|
|
{ 118, "MBMS Session Stop Request" }, |
215 |
|
|
{ 119, "MBMS Session Stop Response" }, |
216 |
|
|
{ 120, "MBMS Session Update Request" }, |
217 |
|
|
{ 121, "MBMS Session Update Response" }, |
218 |
|
|
{ 128, "MBMS Info Change Notification Request" }, |
219 |
|
|
{ 129, "MBMS Info Change Notification Response" }, |
220 |
|
|
{ 240, "Data Record Transfer Request" }, |
221 |
|
|
{ 241, "Data Record Transfer Response" }, |
222 |
|
|
{ 255, "G-PDU" }, |
223 |
|
|
|
224 |
|
|
{ 0, NULL } |
225 |
|
|
}; |
226 |
|
|
|
227 |
|
|
/* GTPv1 Causes. */ |
228 |
|
|
static struct tok gtp_v1_cause[] = { |
229 |
|
|
|
230 |
|
|
/* GTPv1-C. */ |
231 |
|
|
{ 0, "Request IMSI" }, |
232 |
|
|
{ 1, "Request IMEI" }, |
233 |
|
|
{ 2, "Request IMSI and IMEI" }, |
234 |
|
|
{ 3, "No identity needed" }, |
235 |
|
|
{ 4, "MS refuses" }, |
236 |
|
|
{ 5, "MS is not GPRS responding" }, |
237 |
|
|
{ 128, "Request accepted" }, |
238 |
|
|
{ 192, "Non-existent" }, |
239 |
|
|
{ 193, "Invalid message format" }, |
240 |
|
|
{ 194, "IMSI not known" }, |
241 |
|
|
{ 195, "MS is GPRS detached" }, |
242 |
|
|
{ 196, "MS is not GPRS responding" }, |
243 |
|
|
{ 197, "MS refuses" }, |
244 |
|
|
{ 198, "Version not supported" }, |
245 |
|
|
{ 199, "No resources available" }, |
246 |
|
|
{ 200, "Service not supported" }, |
247 |
|
|
{ 201, "Mandatory IE incorrect" }, |
248 |
|
|
{ 202, "Mandatory IE missing" }, |
249 |
|
|
{ 203, "Optional IE incorrect" }, |
250 |
|
|
{ 204, "System failure" }, |
251 |
|
|
{ 205, "Roaming restriction" }, |
252 |
|
|
{ 206, "P-TMSI signature mismatch" }, |
253 |
|
|
{ 207, "GPRS connection suspended" }, |
254 |
|
|
{ 208, "Authentication failure" }, |
255 |
|
|
{ 209, "User authentication failed" }, |
256 |
|
|
{ 210, "Context not found" }, |
257 |
|
|
{ 211, "All dynamic PDP addresses are occupied" }, |
258 |
|
|
{ 212, "No memory is available" }, |
259 |
|
|
{ 213, "Relocation failure" }, |
260 |
|
|
{ 214, "Unknown mandatory extension header" }, |
261 |
|
|
{ 215, "Semantic error in the TFT operation" }, |
262 |
|
|
{ 216, "Syntactic error in the TFT operation" }, |
263 |
|
|
{ 217, "Semantic errors in packet filter(s)" }, |
264 |
|
|
{ 218, "Syntactic errors in packet filter(s)" }, |
265 |
|
|
{ 219, "Missing or unknown APN" }, |
266 |
|
|
{ 220, "Unknown PDP address or PDP type" }, |
267 |
|
|
{ 221, "PDP context without TFT already activated" }, |
268 |
|
|
{ 222, "APN access denied - no subscription" }, |
269 |
|
|
{ 223, "APN restriction type incompatibility with currently " |
270 |
|
|
"active PDP contexts" }, |
271 |
|
|
{ 224, "MS MBMS capabilities insufficient" }, |
272 |
|
|
{ 225, "Invalid correlation-ID" }, |
273 |
|
|
{ 226, "MBMS bearer context superseded" }, |
274 |
|
|
|
275 |
|
|
/* GTP'v1. */ |
276 |
|
|
{ 59, "System failure" }, |
277 |
|
|
{ 60, "The transmit buffers are becoming full" }, |
278 |
|
|
{ 61, "The receive buffers are becoming full" }, |
279 |
|
|
{ 62, "Another node is about to go down" }, |
280 |
|
|
{ 63, "This node is about to go down" }, |
281 |
|
|
{ 177, "CDR decoding error" }, |
282 |
|
|
{ 252, "Request related to possibly duplicated packets already " |
283 |
|
|
"fulfilled" }, |
284 |
|
|
{ 253, "Request already fulfilled" }, |
285 |
|
|
{ 254, "Sequence numbers of released/cancelled packets IE incorrect" }, |
286 |
|
|
{ 255, "Request not fulfilled" }, |
287 |
|
|
|
288 |
|
|
{ 0, NULL } |
289 |
|
|
}; |
290 |
|
|
|
291 |
|
|
static int gtp_proto = -1; |
292 |
|
|
|
293 |
|
|
void |
294 |
|
|
gtp_print(const u_char *cp, u_int length, u_short sport, u_short dport) |
295 |
|
|
{ |
296 |
|
|
int version; |
297 |
|
|
|
298 |
|
|
/* Decode GTP version. */ |
299 |
|
|
TCHECK(cp[0]); |
300 |
|
|
version = cp[0] >> GTP_VERSION_SHIFT; |
301 |
|
|
|
302 |
|
|
if (version == GTP_VERSION_0) |
303 |
|
|
gtp_v0_print(cp, length, sport, dport); |
304 |
|
|
else if (version == GTP_VERSION_1) |
305 |
|
|
gtp_v1_print(cp, length, sport, dport); |
306 |
|
|
else |
307 |
|
|
printf(" GTP (version %i)", version); |
308 |
|
|
|
309 |
|
|
return; |
310 |
|
|
|
311 |
|
|
trunc: |
312 |
|
|
printf(" [|GTP]"); |
313 |
|
|
} |
314 |
|
|
|
315 |
|
|
/* |
316 |
|
|
* Decode and print information elements from message. The actual work is |
317 |
|
|
* handled in the appropriate Tag/Value (TV) or Tag/Length/Value (TLV) |
318 |
|
|
* decoding routine. |
319 |
|
|
*/ |
320 |
|
|
void |
321 |
|
|
gtp_decode_ie(const u_char *cp, u_short version, int len) |
322 |
|
|
{ |
323 |
|
|
int val, ielen, iecount = 0; |
324 |
|
|
|
325 |
|
|
if (len <= 0) |
326 |
|
|
return; |
327 |
|
|
|
328 |
|
|
printf(" {"); |
329 |
|
|
|
330 |
|
|
while (len > 0) { |
331 |
|
|
|
332 |
|
|
iecount++; |
333 |
|
|
if (iecount > 1) |
334 |
|
|
printf(" "); |
335 |
|
|
|
336 |
|
|
TCHECK(cp[0]); |
337 |
|
|
val = (u_int)cp[0]; |
338 |
|
|
cp++; |
339 |
|
|
|
340 |
|
|
printf("["); |
341 |
|
|
|
342 |
|
|
switch (version) { |
343 |
|
|
case GTP_VERSION_0: |
344 |
|
|
if ((val & GTPV0_IE_TYPE_MASK) == 0) |
345 |
|
|
ielen = gtp_v0_print_tv(cp, val); |
346 |
|
|
else |
347 |
|
|
ielen = gtp_v0_print_tlv(cp, val); |
348 |
|
|
break; |
349 |
|
|
|
350 |
|
|
case GTP_VERSION_1: |
351 |
|
|
if ((val & GTPV1_IE_TYPE_MASK) == 0) |
352 |
|
|
ielen = gtp_v1_print_tv(cp, val); |
353 |
|
|
else |
354 |
|
|
ielen = gtp_v1_print_tlv(cp, val); |
355 |
|
|
break; |
356 |
|
|
|
357 |
|
|
default: |
358 |
|
|
/* Version not supported... */ |
359 |
|
|
ielen = -1; |
360 |
|
|
break; |
361 |
|
|
} |
362 |
|
|
|
363 |
|
|
printf("]"); |
364 |
|
|
|
365 |
|
|
if (ielen < 0) |
366 |
|
|
goto trunc; |
367 |
|
|
|
368 |
|
|
len -= ielen; |
369 |
|
|
cp += ielen - 1; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
if (iecount > 0) |
373 |
|
|
printf("}"); |
374 |
|
|
|
375 |
|
|
return; |
376 |
|
|
|
377 |
|
|
trunc: |
378 |
|
|
printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); |
379 |
|
|
} |
380 |
|
|
|
381 |
|
|
/* |
382 |
|
|
* Decode and print telephony binary coded decimal. |
383 |
|
|
*/ |
384 |
|
|
void |
385 |
|
|
gtp_print_tbcd(const u_char *cp, u_int len) |
386 |
|
|
{ |
387 |
|
|
u_int8_t *data, bcd; |
388 |
|
|
int i; |
389 |
|
|
|
390 |
|
|
data = (u_int8_t *)cp; |
391 |
|
|
for (i = 0; i < len; i++) { |
392 |
|
|
bcd = *data & 0xf; |
393 |
|
|
if (bcd != 0xf) |
394 |
|
|
printf("%u", bcd); |
395 |
|
|
bcd = *data >> 4; |
396 |
|
|
if (bcd != 0xf) |
397 |
|
|
printf("%u", bcd); |
398 |
|
|
data++; |
399 |
|
|
} |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
/* |
403 |
|
|
* Decode and print an end user address. Format is detailed in |
404 |
|
|
* GSM 09.60 section 7.9.18 and 3GPP 29.060 section 7.7.27. |
405 |
|
|
*/ |
406 |
|
|
void |
407 |
|
|
gtp_print_user_address(const u_char *cp, u_int len) |
408 |
|
|
{ |
409 |
|
|
u_int8_t org, type; |
410 |
|
|
|
411 |
|
|
if (len < 2) |
412 |
|
|
return; |
413 |
|
|
|
414 |
|
|
org = (u_int8_t)cp[0] & 0xf; |
415 |
|
|
type = (u_int8_t)cp[1]; |
416 |
|
|
|
417 |
|
|
cp += 2; |
418 |
|
|
|
419 |
|
|
if (org == 0x0 && type == 0x1) |
420 |
|
|
printf(": PPP"); |
421 |
|
|
else if (org == 0x1 && type == 0x21) { |
422 |
|
|
if (len == 6) |
423 |
|
|
printf(": %s", ipaddr_string(cp)); |
424 |
|
|
else |
425 |
|
|
printf(": IPv4"); |
426 |
|
|
#ifdef INET6 |
427 |
|
|
} else if (org == 0x1 && type == 0x57) { |
428 |
|
|
if (len == 18) |
429 |
|
|
printf(": %s", ip6addr_string(cp)); |
430 |
|
|
else |
431 |
|
|
printf(": IPv6"); |
432 |
|
|
#endif |
433 |
|
|
} else |
434 |
|
|
printf(" (org 0x%x, type 0x%x)", org, type); |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
/* |
438 |
|
|
* Decode and print an Access Point Name. Format is detailed in |
439 |
|
|
* 3GPP 24.008 section 10.5.6.1 and 3GPP 23.003 section 9.1. |
440 |
|
|
*/ |
441 |
|
|
void |
442 |
|
|
gtp_print_apn(const u_char *cp, u_int len) |
443 |
|
|
{ |
444 |
|
|
u_char label[100]; |
445 |
|
|
u_int8_t llen; |
446 |
|
|
|
447 |
|
|
if (len < 1 || len > 100) |
448 |
|
|
return; |
449 |
|
|
|
450 |
|
|
while (len > 0) { |
451 |
|
|
|
452 |
|
|
llen = (u_int8_t)cp[0]; |
453 |
|
|
if (llen > 99) |
454 |
|
|
return; |
455 |
|
|
|
456 |
|
|
bcopy(cp + 1, label, llen); |
457 |
|
|
label[llen] = '\0'; |
458 |
|
|
printf("%s", label); |
459 |
|
|
|
460 |
|
|
cp += llen + 1; |
461 |
|
|
len -= llen + 1; |
462 |
|
|
|
463 |
|
|
if (len > 0) |
464 |
|
|
printf("."); |
465 |
|
|
|
466 |
|
|
} |
467 |
|
|
} |
468 |
|
|
|
469 |
|
|
/* Print string from array. */ |
470 |
|
|
void |
471 |
|
|
gtp_print_str(const char **strs, u_int index) |
472 |
|
|
{ |
473 |
|
|
|
474 |
|
|
if (index >= (sizeof(*strs) / sizeof(*strs[0]))) |
475 |
|
|
printf(": %u", index); |
476 |
|
|
else if (strs[index] != NULL) |
477 |
|
|
printf(": %s", strs[index]); |
478 |
|
|
} |
479 |
|
|
|
480 |
|
|
/* |
481 |
|
|
* Decoding routines for GTP version 0. |
482 |
|
|
*/ |
483 |
|
|
void |
484 |
|
|
gtp_v0_print(const u_char *cp, u_int length, u_short sport, u_short dport) |
485 |
|
|
{ |
486 |
|
|
struct gtp_v0_hdr *gh = (struct gtp_v0_hdr *)cp; |
487 |
|
|
int len, version; |
488 |
|
|
u_int64_t tid; |
489 |
|
|
|
490 |
|
|
gtp_proto = GTP_V0_PROTO; |
491 |
|
|
|
492 |
|
|
/* Check if this is GTP prime. */ |
493 |
|
|
TCHECK(gh->flags); |
494 |
|
|
if ((gh->flags & GTPV0_HDR_PROTO_TYPE) == 0) { |
495 |
|
|
gtp_proto = GTP_V0_PRIME_PROTO; |
496 |
|
|
gtp_v0_print_prime(cp); |
497 |
|
|
return; |
498 |
|
|
} |
499 |
|
|
|
500 |
|
|
/* Print GTP header. */ |
501 |
|
|
TCHECK(*gh); |
502 |
|
|
cp += sizeof(struct gtp_v0_hdr); |
503 |
|
|
len = ntohs(gh->length); |
504 |
|
|
bcopy(&gh->tid, &tid, sizeof(tid)); |
505 |
|
|
printf(" GTPv0 (len %u, seqno %u, flow %u, N-PDU %u, tid 0x%llx) ", |
506 |
|
|
ntohs(gh->length), ntohs(gh->seqno), ntohs(gh->flow), |
507 |
|
|
ntohs(gh->npduno), betoh64(tid)); |
508 |
|
|
|
509 |
|
|
/* Decode GTP message. */ |
510 |
|
|
printf("%s", tok2str(gtp_v0_msgtype, "Message Type %u", gh->msgtype)); |
511 |
|
|
|
512 |
|
|
if (!vflag) |
513 |
|
|
return; |
514 |
|
|
|
515 |
|
|
if (gh->msgtype == GTPV0_T_PDU) { |
516 |
|
|
|
517 |
|
|
TCHECK(cp[0]); |
518 |
|
|
version = cp[0] >> 4; |
519 |
|
|
|
520 |
|
|
printf(" { "); |
521 |
|
|
|
522 |
|
|
if (version == 4) |
523 |
|
|
ip_print(cp, len); |
524 |
|
|
#ifdef INET6 |
525 |
|
|
else if (version == 6) |
526 |
|
|
ip6_print(cp, len); |
527 |
|
|
#endif |
528 |
|
|
else |
529 |
|
|
printf("Unknown IP version %u", version); |
530 |
|
|
|
531 |
|
|
printf(" }"); |
532 |
|
|
} else |
533 |
|
|
gtp_decode_ie(cp, GTP_VERSION_0, len); |
534 |
|
|
|
535 |
|
|
return; |
536 |
|
|
|
537 |
|
|
trunc: |
538 |
|
|
printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); |
539 |
|
|
} |
540 |
|
|
|
541 |
|
|
void |
542 |
|
|
gtp_v0_print_prime(const u_char *cp) |
543 |
|
|
{ |
544 |
|
|
struct gtp_v0_prime_hdr *gph = (struct gtp_v0_prime_hdr *)cp; |
545 |
|
|
int len; |
546 |
|
|
|
547 |
|
|
/* Decode GTP prime header. */ |
548 |
|
|
TCHECK(*gph); |
549 |
|
|
cp += sizeof(*gph); |
550 |
|
|
|
551 |
|
|
len = ntohs(gph->length); |
552 |
|
|
printf(" GTPv0' (len %u, seq %u) ", len, ntohs(gph->seqno)); |
553 |
|
|
|
554 |
|
|
/* Decode GTP message. */ |
555 |
|
|
printf("%s", tok2str(gtp_v0_msgtype, "Message Type %u", gph->msgtype)); |
556 |
|
|
|
557 |
|
|
if (vflag) |
558 |
|
|
gtp_decode_ie(cp, GTP_VERSION_0, len); |
559 |
|
|
|
560 |
|
|
return; |
561 |
|
|
|
562 |
|
|
trunc: |
563 |
|
|
printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); |
564 |
|
|
} |
565 |
|
|
|
566 |
|
|
int |
567 |
|
|
gtp_v0_print_tv(const u_char *cp, u_int value) |
568 |
|
|
{ |
569 |
|
|
u_int32_t *dpl; |
570 |
|
|
u_int16_t *dps; |
571 |
|
|
u_int8_t data; |
572 |
|
|
int ielen = -1; |
573 |
|
|
|
574 |
|
|
switch (value) { |
575 |
|
|
case GTPV0_TV_CAUSE: |
576 |
|
|
|
577 |
|
|
/* 09.60 7.9.1 - Cause. */ |
578 |
|
|
TCHECK(cp[0]); |
579 |
|
|
data = (u_int8_t)cp[0]; |
580 |
|
|
ielen = GTPV0_TV_CAUSE_LENGTH; |
581 |
|
|
printf("Cause: %s", tok2str(gtp_v0_cause, "#%u", data)); |
582 |
|
|
break; |
583 |
|
|
|
584 |
|
|
case GTPV0_TV_IMSI: |
585 |
|
|
|
586 |
|
|
/* 09.60 7.9.2 - International Mobile Subscriber Identity. */ |
587 |
|
|
TCHECK2(cp[0], GTPV0_TV_IMSI_LENGTH - 1); |
588 |
|
|
printf("IMSI "); |
589 |
|
|
gtp_print_tbcd(cp, GTPV0_TV_IMSI_LENGTH - 1); |
590 |
|
|
ielen = GTPV0_TV_IMSI_LENGTH; |
591 |
|
|
break; |
592 |
|
|
|
593 |
|
|
case GTPV0_TV_RAI: |
594 |
|
|
|
595 |
|
|
/* 09.60 7.9.3 - Routing Area Identity (RAI). */ |
596 |
|
|
TCHECK2(cp[0], GTPV0_TV_RAI_LENGTH - 1); |
597 |
|
|
printf("RAI: MCC "); |
598 |
|
|
data = cp[1] | 0xf0; |
599 |
|
|
gtp_print_tbcd(cp, 1); |
600 |
|
|
gtp_print_tbcd(&data, 1); |
601 |
|
|
printf(", MNC "); |
602 |
|
|
data = (cp[1] >> 4) | 0xf0; |
603 |
|
|
gtp_print_tbcd(cp + 2, 1); |
604 |
|
|
gtp_print_tbcd(&data, 1); |
605 |
|
|
printf(", LAC 0x%x%x", cp[3], cp[4]); |
606 |
|
|
printf(", RAC 0x%x", cp[5]); |
607 |
|
|
ielen = GTPV0_TV_RAI_LENGTH; |
608 |
|
|
break; |
609 |
|
|
|
610 |
|
|
case GTPV0_TV_TLLI: |
611 |
|
|
|
612 |
|
|
/* 09.60 7.9.4 - Temporary Logical Link Identity (TLLI). */ |
613 |
|
|
TCHECK2(cp[0], GTPV0_TV_TLLI_LENGTH - 1); |
614 |
|
|
dpl = (u_int32_t *)cp; |
615 |
|
|
printf("TLLI 0x%x", ntohl(*dpl)); |
616 |
|
|
ielen = GTPV0_TV_TLLI_LENGTH; |
617 |
|
|
break; |
618 |
|
|
|
619 |
|
|
case GTPV0_TV_PTMSI: |
620 |
|
|
|
621 |
|
|
/* 09.60 7.9.5 - Packet TMSI (P-TMSI). */ |
622 |
|
|
TCHECK2(cp[0], GTPV0_TV_PTMSI_LENGTH - 1); |
623 |
|
|
dpl = (u_int32_t *)cp; |
624 |
|
|
printf("P-TMSI 0x%x", ntohl(*dpl)); |
625 |
|
|
ielen = GTPV0_TV_PTMSI_LENGTH; |
626 |
|
|
break; |
627 |
|
|
|
628 |
|
|
case GTPV0_TV_QOS: |
629 |
|
|
|
630 |
|
|
/* 09.60 7.9.6 - Quality of Service (QoS) Profile. */ |
631 |
|
|
TCHECK2(cp[0], GTPV0_TV_QOS_LENGTH - 1); |
632 |
|
|
printf("QoS Profile"); /* XXX */ |
633 |
|
|
ielen = GTPV0_TV_QOS_LENGTH; |
634 |
|
|
break; |
635 |
|
|
|
636 |
|
|
case GTPV0_TV_REORDER: |
637 |
|
|
|
638 |
|
|
/* 09.60 7.9.7 - Reordering Required. */ |
639 |
|
|
TCHECK2(cp[0], GTPV0_TV_REORDER_LENGTH - 1); |
640 |
|
|
printf("Reordering Required: "); |
641 |
|
|
if (cp[0] & 0x1) |
642 |
|
|
printf("yes"); |
643 |
|
|
else |
644 |
|
|
printf("no"); |
645 |
|
|
ielen = GTPV0_TV_REORDER_LENGTH; |
646 |
|
|
break; |
647 |
|
|
|
648 |
|
|
case GTPV0_TV_AUTH_TRIPLET: |
649 |
|
|
|
650 |
|
|
/* 09.60 7.9.8 - Authentication Triplet. */ |
651 |
|
|
TCHECK2(cp[0], GTPV0_TV_AUTH_TRIPLET_LENGTH - 1); |
652 |
|
|
printf("Authentication"); /* XXX */ |
653 |
|
|
ielen = GTPV0_TV_AUTH_TRIPLET_LENGTH; |
654 |
|
|
break; |
655 |
|
|
|
656 |
|
|
case GTPV0_TV_MAP_CAUSE: |
657 |
|
|
|
658 |
|
|
/* 09.60 7.9.9 - MAP Cause. */ |
659 |
|
|
TCHECK2(cp[0], GTPV0_TV_MAP_CAUSE_LENGTH - 1); |
660 |
|
|
printf("MAP Cause: %u", cp[0]); |
661 |
|
|
ielen = GTPV0_TV_MAP_CAUSE_LENGTH; |
662 |
|
|
break; |
663 |
|
|
|
664 |
|
|
case GTPV0_TV_PTMSI_SIGNATURE: |
665 |
|
|
|
666 |
|
|
/* 09.60 7.9.10 - P-TMSI Signature. */ |
667 |
|
|
/* Signature defined in GSM 04.08. */ |
668 |
|
|
TCHECK2(cp[0], GTPV0_TV_PTMSI_SIGNATURE_LENGTH - 1); |
669 |
|
|
printf("PTMSI Signature: 0x%x%x%x", cp[0], cp[1], cp[2]); |
670 |
|
|
ielen = GTPV0_TV_PTMSI_SIGNATURE_LENGTH; |
671 |
|
|
break; |
672 |
|
|
|
673 |
|
|
case GTPV0_TV_MS_VALIDATED: |
674 |
|
|
|
675 |
|
|
/* 09.60 7.9.11 - MS Validated. */ |
676 |
|
|
TCHECK2(cp[0], GTPV0_TV_MS_VALIDATED_LENGTH - 1); |
677 |
|
|
printf("MS Validated"); |
678 |
|
|
if (cp[0] & 0x1) |
679 |
|
|
printf("yes"); |
680 |
|
|
else |
681 |
|
|
printf("no"); |
682 |
|
|
ielen = GTPV0_TV_MS_VALIDATED_LENGTH; |
683 |
|
|
break; |
684 |
|
|
|
685 |
|
|
case GTPV0_TV_RECOVERY: |
686 |
|
|
|
687 |
|
|
/* 09.60 7.9.12 - Recovery. */ |
688 |
|
|
TCHECK2(cp[0], GTPV0_TV_RECOVERY_LENGTH - 1); |
689 |
|
|
printf("Recovery: Restart counter %u", cp[0]); |
690 |
|
|
ielen = GTPV0_TV_RECOVERY_LENGTH; |
691 |
|
|
break; |
692 |
|
|
|
693 |
|
|
case GTPV0_TV_SELECTION_MODE: |
694 |
|
|
|
695 |
|
|
/* 09.60 7.9.13 - Selection Mode. */ |
696 |
|
|
TCHECK2(cp[0], GTPV0_TV_SELECTION_MODE_LENGTH - 1); |
697 |
|
|
printf("Selection Mode"); /* XXX */ |
698 |
|
|
ielen = GTPV0_TV_SELECTION_MODE_LENGTH; |
699 |
|
|
break; |
700 |
|
|
|
701 |
|
|
case GTPV0_TV_FLOW_LABEL_DATA_I: |
702 |
|
|
|
703 |
|
|
/* 09.60 7.9.14 - Flow Label Data I. */ |
704 |
|
|
TCHECK2(cp[0], GTPV0_TV_FLOW_LABEL_DATA_I_LENGTH - 1); |
705 |
|
|
dps = (u_int16_t *)cp; |
706 |
|
|
printf("Flow Label Data I: %u", ntohs(*dps)); |
707 |
|
|
ielen = GTPV0_TV_FLOW_LABEL_DATA_I_LENGTH; |
708 |
|
|
break; |
709 |
|
|
|
710 |
|
|
case GTPV0_TV_FLOW_LABEL_SIGNALLING: |
711 |
|
|
|
712 |
|
|
/* 09.60 7.9.15 - Flow Label Signalling. */ |
713 |
|
|
TCHECK2(cp[0], GTPV0_TV_FLOW_LABEL_SIGNALLING_LENGTH - 1); |
714 |
|
|
dps = (u_int16_t *)cp; |
715 |
|
|
printf("Flow Label Signalling: %u", ntohs(*dps)); |
716 |
|
|
ielen = GTPV0_TV_FLOW_LABEL_SIGNALLING_LENGTH; |
717 |
|
|
break; |
718 |
|
|
|
719 |
|
|
case GTPV0_TV_FLOW_LABEL_DATA_II: |
720 |
|
|
|
721 |
|
|
/* 09.60 7.9.16 - Flow Label Data II. */ |
722 |
|
|
TCHECK2(cp[0], GTPV0_TV_FLOW_LABEL_DATA_II_LENGTH - 1); |
723 |
|
|
data = cp[0] & 0xf; |
724 |
|
|
dps = (u_int16_t *)(cp + 1); |
725 |
|
|
printf("Flow Label Data II: %u, NSAPI %u", ntohs(*dps), data); |
726 |
|
|
ielen = GTPV0_TV_FLOW_LABEL_DATA_II_LENGTH; |
727 |
|
|
break; |
728 |
|
|
|
729 |
|
|
case GTPV0_TV_PACKET_XFER_CMD: |
730 |
|
|
|
731 |
|
|
/* 12.15 7.3.4.5.3 - Packet Transfer Command. */ |
732 |
|
|
TCHECK2(cp[0], GTPV0_TV_PACKET_XFER_CMD_LENGTH - 1); |
733 |
|
|
printf("Packet Transfer Command"); |
734 |
|
|
gtp_print_str(gtp_packet_xfer_cmd, cp[0]); |
735 |
|
|
ielen = GTPV0_TV_PACKET_XFER_CMD_LENGTH; |
736 |
|
|
break; |
737 |
|
|
|
738 |
|
|
case GTPV0_TV_CHARGING_ID: |
739 |
|
|
|
740 |
|
|
/* 09.60 7.9.17 - Charging ID. */ |
741 |
|
|
TCHECK2(cp[0], GTPV0_TV_CHARGING_ID_LENGTH - 1); |
742 |
|
|
dps = (u_int16_t *)cp; |
743 |
|
|
printf("Charging ID: %u", ntohs(*dps)); |
744 |
|
|
ielen = GTPV0_TV_CHARGING_ID_LENGTH; |
745 |
|
|
break; |
746 |
|
|
|
747 |
|
|
default: |
748 |
|
|
printf("TV %u", value); |
749 |
|
|
} |
750 |
|
|
|
751 |
|
|
trunc: |
752 |
|
|
return ielen; |
753 |
|
|
} |
754 |
|
|
|
755 |
|
|
int |
756 |
|
|
gtp_v0_print_tlv(const u_char *cp, u_int value) |
757 |
|
|
{ |
758 |
|
|
u_int8_t data; |
759 |
|
|
u_int16_t *lenp, *seqno, len; |
760 |
|
|
int ielen = -1; |
761 |
|
|
|
762 |
|
|
/* Get length of IE. */ |
763 |
|
|
TCHECK2(cp[0], 2); |
764 |
|
|
lenp = (u_int16_t *)cp; |
765 |
|
|
cp += 2; |
766 |
|
|
len = ntohs(*lenp); |
767 |
|
|
TCHECK2(cp[0], len); |
768 |
|
|
ielen = sizeof(data) + sizeof(len) + len; |
769 |
|
|
|
770 |
|
|
switch (value) { |
771 |
|
|
|
772 |
|
|
case GTPV0_TLV_END_USER_ADDRESS: |
773 |
|
|
|
774 |
|
|
/* 09.60 7.9.18 - End User Address. */ |
775 |
|
|
printf("End User Address"); |
776 |
|
|
gtp_print_user_address(cp, len); |
777 |
|
|
break; |
778 |
|
|
|
779 |
|
|
case GTPV0_TLV_MM_CONTEXT: |
780 |
|
|
|
781 |
|
|
/* 09.60 7.9.19 - MM Context. */ |
782 |
|
|
printf("MM Context"); /* XXX */ |
783 |
|
|
break; |
784 |
|
|
|
785 |
|
|
case GTPV0_TLV_PDP_CONTEXT: |
786 |
|
|
|
787 |
|
|
/* 09.60 7.9.20 - PDP Context. */ |
788 |
|
|
printf("PDP Context"); /* XXX */ |
789 |
|
|
break; |
790 |
|
|
|
791 |
|
|
case GTPV0_TLV_ACCESS_POINT_NAME: |
792 |
|
|
|
793 |
|
|
/* 09.60 7.9.21 - Access Point Name. */ |
794 |
|
|
printf("AP Name: "); |
795 |
|
|
gtp_print_apn(cp, len); |
796 |
|
|
break; |
797 |
|
|
|
798 |
|
|
case GTPV0_TLV_PROTOCOL_CONFIG_OPTIONS: |
799 |
|
|
|
800 |
|
|
/* 09.60 7.9.22 - Protocol Configuration Options. */ |
801 |
|
|
printf("Protocol Configuration Options"); /* XXX */ |
802 |
|
|
break; |
803 |
|
|
|
804 |
|
|
case GTPV0_TLV_GSN_ADDRESS: |
805 |
|
|
|
806 |
|
|
/* 09.60 7.9.23 - GSN Address. */ |
807 |
|
|
printf("GSN Address"); |
808 |
|
|
if (len == 4) |
809 |
|
|
printf(": %s", ipaddr_string(cp)); |
810 |
|
|
#ifdef INET6 |
811 |
|
|
else if (len == 16) |
812 |
|
|
printf(": %s", ip6addr_string(cp)); |
813 |
|
|
#endif |
814 |
|
|
break; |
815 |
|
|
|
816 |
|
|
case GTPV0_TLV_MS_ISDN: |
817 |
|
|
|
818 |
|
|
/* 09.60 7.9.24 - MS International PSTN/ISDN Number. */ |
819 |
|
|
printf("MSISDN "); |
820 |
|
|
data = (u_int8_t)cp[0]; /* XXX - Number type. */ |
821 |
|
|
gtp_print_tbcd(cp + 1, len - 1); |
822 |
|
|
break; |
823 |
|
|
|
824 |
|
|
case GTPV0_TLV_CHARGING_GATEWAY_ADDRESS: |
825 |
|
|
|
826 |
|
|
/* 09.60 7.9.25 - Charging Gateway Address. */ |
827 |
|
|
printf("Charging Gateway"); |
828 |
|
|
if (len == 4) |
829 |
|
|
printf(": %s", ipaddr_string(cp)); |
830 |
|
|
break; |
831 |
|
|
|
832 |
|
|
case GTPV0_TLV_DATA_RECORD_PACKET: |
833 |
|
|
|
834 |
|
|
/* 12.15 7.3.4.5.4 - Data Record Packet. */ |
835 |
|
|
printf("Data Record: Records %u, Format %u, Format Version %u", |
836 |
|
|
cp[0], cp[1], ntohs(*(u_int16_t *)(cp + 2))); |
837 |
|
|
break; |
838 |
|
|
|
839 |
|
|
case GTPV0_TLV_REQUESTS_RESPONDED: |
840 |
|
|
|
841 |
|
|
/* 12.15 7.3.4.6 - Requests Responded. */ |
842 |
|
|
printf("Requests Responded:"); |
843 |
|
|
seqno = (u_int16_t *)cp; |
844 |
|
|
while (len > 0) { |
845 |
|
|
printf(" %u", ntohs(*seqno)); |
846 |
|
|
seqno++; |
847 |
|
|
len -= sizeof(*seqno); |
848 |
|
|
} |
849 |
|
|
break; |
850 |
|
|
|
851 |
|
|
case GTPV0_TLV_RECOMMENDED_NODE: |
852 |
|
|
|
853 |
|
|
/* 12.15 7.3.4.3 - Address of Recommended Node. */ |
854 |
|
|
printf("Recommended Node"); |
855 |
|
|
if (len == 4) |
856 |
|
|
printf(": %s", ipaddr_string(cp)); |
857 |
|
|
#ifdef INET6 |
858 |
|
|
else if (len == 16) |
859 |
|
|
printf(": %s", ip6addr_string(cp)); |
860 |
|
|
#endif |
861 |
|
|
break; |
862 |
|
|
|
863 |
|
|
case GTPV0_TLV_PRIVATE_EXTENSION: |
864 |
|
|
|
865 |
|
|
printf("Private Extension"); |
866 |
|
|
break; |
867 |
|
|
|
868 |
|
|
default: |
869 |
|
|
printf("TLV %u (len %u)", value, len); |
870 |
|
|
} |
871 |
|
|
|
872 |
|
|
return ielen; |
873 |
|
|
|
874 |
|
|
trunc: |
875 |
|
|
return -1; |
876 |
|
|
} |
877 |
|
|
|
878 |
|
|
/* |
879 |
|
|
* Decoding for GTP version 1, which consists of GTPv1-C, GTPv1-U and GTPv1'. |
880 |
|
|
*/ |
881 |
|
|
void |
882 |
|
|
gtp_v1_print(const u_char *cp, u_int length, u_short sport, u_short dport) |
883 |
|
|
{ |
884 |
|
|
struct gtp_v1_hdr *gh = (struct gtp_v1_hdr *)cp; |
885 |
|
|
struct gtp_v1_hdr_ext *ghe = NULL; |
886 |
|
|
int nexthdr, hlen; |
887 |
|
|
u_char *p = (u_char *)cp; |
888 |
|
|
|
889 |
|
|
TCHECK(gh->flags); |
890 |
|
|
if ((gh->flags & GTPV1_HDR_PROTO_TYPE) == 0) { |
891 |
|
|
gtp_proto = GTP_V1_PRIME_PROTO; |
892 |
|
|
printf(" GTPv1'"); |
893 |
|
|
gtp_v1_print_prime(p, (struct gtp_v1_prime_hdr *)gh); |
894 |
|
|
return; |
895 |
|
|
} |
896 |
|
|
|
897 |
|
|
if (dport == GTPV1_C_PORT || sport == GTPV1_C_PORT) { |
898 |
|
|
gtp_proto = GTP_V1_CTRL_PROTO; |
899 |
|
|
printf(" GTPv1-C"); |
900 |
|
|
} else if (dport == GTPV1_U_PORT || sport == GTPV1_U_PORT) { |
901 |
|
|
gtp_proto = GTP_V1_USER_PROTO; |
902 |
|
|
printf(" GTPv1-U"); |
903 |
|
|
} else if (dport == GTPV1_PRIME_PORT || sport == GTPV1_PRIME_PORT) { |
904 |
|
|
gtp_proto = GTP_V1_PRIME_PROTO; |
905 |
|
|
printf(" GTPv1'"); |
906 |
|
|
} |
907 |
|
|
|
908 |
|
|
/* Decode GTP header. */ |
909 |
|
|
TCHECK(*gh); |
910 |
|
|
p += sizeof(struct gtp_v1_hdr); |
911 |
|
|
|
912 |
|
|
printf(" (teid %u, len %u)", ntohl(gh->teid), ntohs(gh->length)); |
913 |
|
|
|
914 |
|
|
if (gh->flags & GTPV1_HDR_EXT) { |
915 |
|
|
ghe = (struct gtp_v1_hdr_ext *)cp; |
916 |
|
|
TCHECK(*ghe); |
917 |
|
|
p += sizeof(struct gtp_v1_hdr_ext) - sizeof(struct gtp_v1_hdr); |
918 |
|
|
} |
919 |
|
|
|
920 |
|
|
if (gh->flags & GTPV1_HDR_SN_FLAG) |
921 |
|
|
printf(" [seq %u]", ntohs(ghe->seqno)); |
922 |
|
|
|
923 |
|
|
if (gh->flags & GTPV1_HDR_NPDU_FLAG) |
924 |
|
|
printf(" [N-PDU %u]", ghe->npduno); |
925 |
|
|
|
926 |
|
|
if (gh->flags & GTPV1_HDR_EH_FLAG) { |
927 |
|
|
|
928 |
|
|
/* Process next header... */ |
929 |
|
|
nexthdr = ghe->nexthdr; |
930 |
|
|
while (nexthdr != GTPV1_EH_NONE) { |
931 |
|
|
|
932 |
|
|
/* Header length is a 4 octet multiplier. */ |
933 |
|
|
hlen = (int)p[0] * 4; |
934 |
|
|
TCHECK2(p[0], hlen); |
935 |
|
|
|
936 |
|
|
switch (nexthdr) { |
937 |
|
|
case GTPV1_EH_MBMS_SUPPORT: |
938 |
|
|
printf(" [MBMS Support]"); |
939 |
|
|
break; |
940 |
|
|
|
941 |
|
|
case GTPV1_EH_MSI_CHANGE_RPT: |
942 |
|
|
printf(" [MS Info Change Reporting]"); |
943 |
|
|
break; |
944 |
|
|
|
945 |
|
|
case GTPV1_EH_PDCP_PDU_NO: |
946 |
|
|
printf(" [PDCP PDU %u]", |
947 |
|
|
ntohs(*(u_int16_t *)(p + 1))); |
948 |
|
|
break; |
949 |
|
|
|
950 |
|
|
case GTPV1_EH_SUSPEND_REQUEST: |
951 |
|
|
printf(" [Suspend Request]"); |
952 |
|
|
break; |
953 |
|
|
|
954 |
|
|
case GTPV1_EH_SUSPEND_RESPONSE: |
955 |
|
|
printf(" [Suspend Response]"); |
956 |
|
|
break; |
957 |
|
|
|
958 |
|
|
default: |
959 |
|
|
printf(" [Unknown Header %u]", nexthdr); |
960 |
|
|
} |
961 |
|
|
|
962 |
|
|
p += hlen - 1; |
963 |
|
|
nexthdr = (int)p[0]; |
964 |
|
|
p++; |
965 |
|
|
} |
966 |
|
|
|
967 |
|
|
} |
968 |
|
|
|
969 |
|
|
hlen = p - cp; |
970 |
|
|
|
971 |
|
|
if (dport == GTPV1_C_PORT || sport == GTPV1_C_PORT) |
972 |
|
|
gtp_v1_print_ctrl(p, hlen, gh); |
973 |
|
|
else if (dport == GTPV1_U_PORT || sport == GTPV1_U_PORT) |
974 |
|
|
gtp_v1_print_user(p, hlen, gh); |
975 |
|
|
|
976 |
|
|
return; |
977 |
|
|
|
978 |
|
|
trunc: |
979 |
|
|
printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); |
980 |
|
|
} |
981 |
|
|
|
982 |
|
|
void |
983 |
|
|
gtp_v1_print_ctrl(const u_char *cp, u_int hlen, struct gtp_v1_hdr *gh) |
984 |
|
|
{ |
985 |
|
|
int len; |
986 |
|
|
|
987 |
|
|
/* Decode GTP control message. */ |
988 |
|
|
printf(" %s", tok2str(gtp_v1_msgtype, "Message Type %u", gh->msgtype)); |
989 |
|
|
|
990 |
|
|
len = ntohs(gh->length) - hlen + sizeof(*gh); |
991 |
|
|
if (vflag) |
992 |
|
|
gtp_decode_ie(cp, GTP_VERSION_1, len); |
993 |
|
|
} |
994 |
|
|
|
995 |
|
|
void |
996 |
|
|
gtp_v1_print_user(const u_char *cp, u_int hlen, struct gtp_v1_hdr *gh) |
997 |
|
|
{ |
998 |
|
|
int len, version; |
999 |
|
|
|
1000 |
|
|
/* Decode GTP user message. */ |
1001 |
|
|
printf(" %s", tok2str(gtp_v1_msgtype, "Message Type %u", gh->msgtype)); |
1002 |
|
|
|
1003 |
|
|
if (!vflag) |
1004 |
|
|
return; |
1005 |
|
|
|
1006 |
|
|
len = ntohs(gh->length) - hlen + sizeof(*gh); |
1007 |
|
|
|
1008 |
|
|
if (gh->msgtype == GTPV1_G_PDU) { |
1009 |
|
|
|
1010 |
|
|
TCHECK(cp[0]); |
1011 |
|
|
version = cp[0] >> 4; |
1012 |
|
|
|
1013 |
|
|
printf(" { "); |
1014 |
|
|
|
1015 |
|
|
if (version == 4) |
1016 |
|
|
ip_print(cp, len); |
1017 |
|
|
#ifdef INET6 |
1018 |
|
|
else if (version == 6) |
1019 |
|
|
ip6_print(cp, len); |
1020 |
|
|
#endif |
1021 |
|
|
else |
1022 |
|
|
printf("Unknown IP version %u", version); |
1023 |
|
|
|
1024 |
|
|
printf(" }"); |
1025 |
|
|
|
1026 |
|
|
} else |
1027 |
|
|
gtp_decode_ie(cp, GTP_VERSION_1, len); |
1028 |
|
|
|
1029 |
|
|
return; |
1030 |
|
|
|
1031 |
|
|
trunc: |
1032 |
|
|
printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); |
1033 |
|
|
} |
1034 |
|
|
|
1035 |
|
|
void |
1036 |
|
|
gtp_v1_print_prime(const u_char *cp, struct gtp_v1_prime_hdr *gph) |
1037 |
|
|
{ |
1038 |
|
|
int len; |
1039 |
|
|
|
1040 |
|
|
/* Decode GTP prime header. */ |
1041 |
|
|
TCHECK(*gph); |
1042 |
|
|
cp += sizeof(struct gtp_v1_prime_hdr); |
1043 |
|
|
|
1044 |
|
|
len = ntohs(gph->length); |
1045 |
|
|
printf(" (len %u, seq %u) ", len, ntohs(gph->seqno)); |
1046 |
|
|
|
1047 |
|
|
/* Decode GTP message. */ |
1048 |
|
|
printf("%s", tok2str(gtp_v1_msgtype, "Message Type %u", gph->msgtype)); |
1049 |
|
|
|
1050 |
|
|
if (vflag) |
1051 |
|
|
gtp_decode_ie(cp, GTP_VERSION_1, len); |
1052 |
|
|
|
1053 |
|
|
return; |
1054 |
|
|
|
1055 |
|
|
trunc: |
1056 |
|
|
printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); |
1057 |
|
|
} |
1058 |
|
|
|
1059 |
|
|
int |
1060 |
|
|
gtp_v1_print_tv(const u_char *cp, u_int value) |
1061 |
|
|
{ |
1062 |
|
|
u_int32_t *dpl; |
1063 |
|
|
u_int16_t *dps; |
1064 |
|
|
u_int8_t data; |
1065 |
|
|
int ielen = -1; |
1066 |
|
|
|
1067 |
|
|
switch (value) { |
1068 |
|
|
case GTPV1_TV_CAUSE: |
1069 |
|
|
|
1070 |
|
|
/* 29.060 - 7.7.1 Cause. */ |
1071 |
|
|
TCHECK(cp[0]); |
1072 |
|
|
data = (u_int8_t)cp[0]; |
1073 |
|
|
ielen = GTPV1_TV_CAUSE_LENGTH; |
1074 |
|
|
printf("Cause: %s", tok2str(gtp_v1_cause, "#%u", data)); |
1075 |
|
|
break; |
1076 |
|
|
|
1077 |
|
|
case GTPV1_TV_IMSI: |
1078 |
|
|
|
1079 |
|
|
/* 29.060 7.7.2 - International Mobile Subscriber Identity. */ |
1080 |
|
|
TCHECK2(cp[0], GTPV1_TV_IMSI_LENGTH - 1); |
1081 |
|
|
printf("IMSI "); |
1082 |
|
|
gtp_print_tbcd(cp, GTPV1_TV_IMSI_LENGTH - 1); |
1083 |
|
|
ielen = GTPV1_TV_IMSI_LENGTH; |
1084 |
|
|
break; |
1085 |
|
|
|
1086 |
|
|
case GTPV1_TV_RAI: |
1087 |
|
|
|
1088 |
|
|
/* 29.060 7.7.3 - Routing Area Identity (RAI). */ |
1089 |
|
|
TCHECK2(cp[0], GTPV1_TV_RAI_LENGTH - 1); |
1090 |
|
|
printf("RAI: MCC "); |
1091 |
|
|
data = cp[1] | 0xf0; |
1092 |
|
|
gtp_print_tbcd(cp, 1); |
1093 |
|
|
gtp_print_tbcd(&data, 1); |
1094 |
|
|
printf(", MNC "); |
1095 |
|
|
data = (cp[1] >> 4) | 0xf0; |
1096 |
|
|
gtp_print_tbcd(cp + 2, 1); |
1097 |
|
|
gtp_print_tbcd(&data, 1); |
1098 |
|
|
printf(", LAC 0x%x%x", cp[3], cp[4]); |
1099 |
|
|
printf(", RAC 0x%x", cp[5]); |
1100 |
|
|
ielen = GTPV1_TV_RAI_LENGTH; |
1101 |
|
|
break; |
1102 |
|
|
|
1103 |
|
|
case GTPV1_TV_TLLI: |
1104 |
|
|
|
1105 |
|
|
/* 29.060 7.7.4 - Temporary Logical Link Identity (TLLI). */ |
1106 |
|
|
TCHECK2(cp[0], GTPV1_TV_TLLI_LENGTH - 1); |
1107 |
|
|
dpl = (u_int32_t *)cp; |
1108 |
|
|
printf("TLLI 0x%x", ntohl(*dpl)); |
1109 |
|
|
ielen = GTPV1_TV_TLLI_LENGTH; |
1110 |
|
|
break; |
1111 |
|
|
|
1112 |
|
|
case GTPV1_TV_PTMSI: |
1113 |
|
|
|
1114 |
|
|
/* 29.060 7.7.5 - Packet TMSI (P-TMSI). */ |
1115 |
|
|
TCHECK2(cp[0], GTPV1_TV_PTMSI_LENGTH - 1); |
1116 |
|
|
dpl = (u_int32_t *)cp; |
1117 |
|
|
printf("P-TMSI 0x%x", ntohl(*dpl)); |
1118 |
|
|
ielen = GTPV1_TV_PTMSI_LENGTH; |
1119 |
|
|
break; |
1120 |
|
|
|
1121 |
|
|
case GTPV1_TV_REORDER: |
1122 |
|
|
|
1123 |
|
|
/* 29.060 7.7.6 - Reordering Required. */ |
1124 |
|
|
TCHECK2(cp[0], GTPV1_TV_REORDER_LENGTH - 1); |
1125 |
|
|
printf("Reordering Required: "); |
1126 |
|
|
if (cp[0] & 0x1) |
1127 |
|
|
printf("yes"); |
1128 |
|
|
else |
1129 |
|
|
printf("no"); |
1130 |
|
|
ielen = GTPV1_TV_REORDER_LENGTH; |
1131 |
|
|
break; |
1132 |
|
|
|
1133 |
|
|
case GTPV1_TV_AUTH: |
1134 |
|
|
|
1135 |
|
|
/* 29.060 7.7.7 - Authentication Triplet. */ |
1136 |
|
|
TCHECK2(cp[0], GTPV1_TV_AUTH_LENGTH - 1); |
1137 |
|
|
dpl = (u_int32_t *)cp; |
1138 |
|
|
printf("Auth: RAND 0x%x%x%x%x, SRES 0x%x, Kc 0x%x%x", |
1139 |
|
|
ntohl(dpl[0]), ntohl(dpl[1]), ntohl(dpl[2]), ntohl(dpl[3]), |
1140 |
|
|
ntohl(dpl[4]), ntohl(dpl[5]), ntohl(dpl[6])); |
1141 |
|
|
ielen = GTPV1_TV_AUTH_LENGTH; |
1142 |
|
|
break; |
1143 |
|
|
|
1144 |
|
|
case GTPV1_TV_MAP_CAUSE: |
1145 |
|
|
|
1146 |
|
|
/* 29.060 7.7.8 - MAP Cause. */ |
1147 |
|
|
/* Cause defined in 3GPP TS 29.002. */ |
1148 |
|
|
TCHECK2(cp[0], GTPV1_TV_MAP_CAUSE_LENGTH - 1); |
1149 |
|
|
printf("Map Cause: %u", cp[0]); |
1150 |
|
|
ielen = GTPV1_TV_MAP_CAUSE_LENGTH; |
1151 |
|
|
break; |
1152 |
|
|
|
1153 |
|
|
case GTPV1_TV_PTMSI_SIGNATURE: |
1154 |
|
|
|
1155 |
|
|
/* 29.060 7.7.9 - P-TMSI Signature. */ |
1156 |
|
|
/* Signature defined in 3GPP TS 24.008. */ |
1157 |
|
|
TCHECK2(cp[0], GTPV1_TV_PTMSI_SIGNATURE_LENGTH - 1); |
1158 |
|
|
printf("PTMSI Signature: 0x%x%x%x", cp[0], cp[1], cp[2]); |
1159 |
|
|
ielen = GTPV1_TV_PTMSI_SIGNATURE_LENGTH; |
1160 |
|
|
break; |
1161 |
|
|
|
1162 |
|
|
case GTPV1_TV_MS_VALIDATED: |
1163 |
|
|
|
1164 |
|
|
/* 29.060 7.7.10 - MS Validated. */ |
1165 |
|
|
TCHECK2(cp[0], GTPV1_TV_MS_VALIDATED_LENGTH - 1); |
1166 |
|
|
printf("MS Validated: "); |
1167 |
|
|
if (cp[0] & 0x1) |
1168 |
|
|
printf("yes"); |
1169 |
|
|
else |
1170 |
|
|
printf("no"); |
1171 |
|
|
ielen = GTPV1_TV_MS_VALIDATED_LENGTH; |
1172 |
|
|
break; |
1173 |
|
|
|
1174 |
|
|
case GTPV1_TV_RECOVERY: |
1175 |
|
|
|
1176 |
|
|
/* 29.060 7.7.11 - Recovery. */ |
1177 |
|
|
TCHECK2(cp[0], GTPV1_TV_RECOVERY_LENGTH - 1); |
1178 |
|
|
printf("Recovery: Restart counter %u", cp[0]); |
1179 |
|
|
ielen = GTPV1_TV_RECOVERY_LENGTH; |
1180 |
|
|
break; |
1181 |
|
|
|
1182 |
|
|
case GTPV1_TV_SELECTION_MODE: |
1183 |
|
|
|
1184 |
|
|
/* 29.060 7.7.12 - Selection Mode. */ |
1185 |
|
|
TCHECK2(cp[0], GTPV1_TV_SELECTION_MODE_LENGTH - 1); |
1186 |
|
|
data = (u_int8_t)cp[0]; |
1187 |
|
|
printf("Selection Mode: %u", data & 0x2); |
1188 |
|
|
ielen = GTPV1_TV_SELECTION_MODE_LENGTH; |
1189 |
|
|
break; |
1190 |
|
|
|
1191 |
|
|
case GTPV1_TV_TEID_DATA_I: |
1192 |
|
|
|
1193 |
|
|
/* 29.060 7.7.13 - Tunnel Endpoint Identifier Data I. */ |
1194 |
|
|
TCHECK2(cp[0], GTPV1_TV_TEID_DATA_I_LENGTH - 1); |
1195 |
|
|
dpl = (u_int32_t *)cp; |
1196 |
|
|
printf("TEI Data I: %u", ntohl(*dpl)); |
1197 |
|
|
ielen = GTPV1_TV_TEID_DATA_I_LENGTH; |
1198 |
|
|
break; |
1199 |
|
|
|
1200 |
|
|
case GTPV1_TV_TEID_CTRL: |
1201 |
|
|
|
1202 |
|
|
/* 29.060 7.7.14 - Tunnel Endpoint Identifier Control Plane. */ |
1203 |
|
|
TCHECK2(cp[0], GTPV1_TV_TEID_CTRL_LENGTH - 1); |
1204 |
|
|
dpl = (u_int32_t *)cp; |
1205 |
|
|
printf("TEI Control Plane: %u", ntohl(*dpl)); |
1206 |
|
|
ielen = GTPV1_TV_TEID_CTRL_LENGTH; |
1207 |
|
|
break; |
1208 |
|
|
|
1209 |
|
|
case GTPV1_TV_TEID_DATA_II: |
1210 |
|
|
|
1211 |
|
|
/* 29.060 7.7.15 - Tunnel Endpoint Identifier Data II. */ |
1212 |
|
|
TCHECK2(cp[0], GTPV1_TV_TEID_DATA_II_LENGTH - 1); |
1213 |
|
|
data = cp[0] & 0xf; |
1214 |
|
|
dpl = (u_int32_t *)(cp + 1); |
1215 |
|
|
printf("TEI Data II: %u, NSAPI %u", ntohl(*dpl), data); |
1216 |
|
|
ielen = GTPV1_TV_TEID_DATA_II_LENGTH; |
1217 |
|
|
break; |
1218 |
|
|
|
1219 |
|
|
case GTPV1_TV_TEARDOWN: |
1220 |
|
|
|
1221 |
|
|
/* 29.060 7.7.16 - Teardown Indicator. */ |
1222 |
|
|
TCHECK2(cp[0], GTPV1_TV_TEARDOWN_LENGTH - 1); |
1223 |
|
|
printf("Teardown: "); |
1224 |
|
|
if (cp[0] & 0x1) |
1225 |
|
|
printf("yes"); |
1226 |
|
|
else |
1227 |
|
|
printf("no"); |
1228 |
|
|
ielen = GTPV1_TV_TEARDOWN_LENGTH; |
1229 |
|
|
break; |
1230 |
|
|
|
1231 |
|
|
case GTPV1_TV_NSAPI: |
1232 |
|
|
|
1233 |
|
|
/* 29.060 7.7.17 - NSAPI. */ |
1234 |
|
|
TCHECK2(cp[0], GTPV1_TV_NSAPI_LENGTH - 1); |
1235 |
|
|
data = (u_int8_t)cp[0]; |
1236 |
|
|
printf("NSAPI %u", data & 0xf); |
1237 |
|
|
ielen = GTPV1_TV_NSAPI_LENGTH; |
1238 |
|
|
break; |
1239 |
|
|
|
1240 |
|
|
case GTPV1_TV_RANAP: |
1241 |
|
|
|
1242 |
|
|
/* 29.060 7.7.18 - RANAP Cause. */ |
1243 |
|
|
TCHECK2(cp[0], GTPV1_TV_RANAP_LENGTH - 1); |
1244 |
|
|
printf("RANAP Cause: %u", cp[0]); |
1245 |
|
|
ielen = GTPV1_TV_RANAP_LENGTH; |
1246 |
|
|
break; |
1247 |
|
|
|
1248 |
|
|
case GTPV1_TV_RAB_CONTEXT: |
1249 |
|
|
|
1250 |
|
|
/* 29.060 7.7.19 - RAB Context. */ |
1251 |
|
|
TCHECK2(cp[0], GTPV1_TV_RAB_CONTEXT_LENGTH - 1); |
1252 |
|
|
data = cp[0] & 0xf; |
1253 |
|
|
dps = (u_int16_t *)(cp + 1); |
1254 |
|
|
printf("RAB Context: NSAPI %u, DL GTP-U Seq No %u," |
1255 |
|
|
"UL GTP-U Seq No %u, DL PDCP Seq No %u, UL PDCP Seq No %u", |
1256 |
|
|
data, ntohs(dps[0]), ntohs(dps[1]), ntohs(dps[2]), |
1257 |
|
|
ntohs(dps[3])); |
1258 |
|
|
ielen = GTPV1_TV_RAB_CONTEXT_LENGTH; |
1259 |
|
|
break; |
1260 |
|
|
|
1261 |
|
|
case GTPV1_TV_RADIO_PRIORITY_SMS: |
1262 |
|
|
|
1263 |
|
|
/* 29.060 7.7.20 - Radio Priority SMS. */ |
1264 |
|
|
TCHECK2(cp[0], GTPV1_TV_RADIO_PRI_SMS_LENGTH - 1); |
1265 |
|
|
printf("Radio Priority SMS: %u", cp[0] & 0x7); |
1266 |
|
|
ielen = GTPV1_TV_RADIO_PRI_SMS_LENGTH; |
1267 |
|
|
break; |
1268 |
|
|
|
1269 |
|
|
case GTPV1_TV_RADIO_PRIORITY: |
1270 |
|
|
|
1271 |
|
|
/* 29.060 7.7.21 - Radio Priority. */ |
1272 |
|
|
TCHECK2(cp[0], GTPV1_TV_RADIO_PRI_LENGTH - 1); |
1273 |
|
|
data = cp[0] >> 4; |
1274 |
|
|
printf("Radio Priority: %u, NSAPI %u", cp[0] & 0x7, data); |
1275 |
|
|
ielen = GTPV1_TV_RADIO_PRI_LENGTH; |
1276 |
|
|
break; |
1277 |
|
|
|
1278 |
|
|
case GTPV1_TV_PACKET_FLOW_ID: |
1279 |
|
|
|
1280 |
|
|
/* 29.060 7.7.22 - Packet Flow ID. */ |
1281 |
|
|
TCHECK2(cp[0], GTPV1_TV_PACKET_FLOW_ID_LENGTH - 1); |
1282 |
|
|
printf("Packet Flow ID: %u, NSAPI %u", cp[1], cp[0] & 0xf); |
1283 |
|
|
ielen = GTPV1_TV_PACKET_FLOW_ID_LENGTH; |
1284 |
|
|
break; |
1285 |
|
|
|
1286 |
|
|
case GTPV1_TV_CHARGING: |
1287 |
|
|
|
1288 |
|
|
/* 29.060 7.7.23 - Charging Characteristics. */ |
1289 |
|
|
/* Charging defined in 3GPP TS 32.298. */ |
1290 |
|
|
TCHECK2(cp[0], GTPV1_TV_CHARGING_LENGTH - 1); |
1291 |
|
|
printf("Charging Characteristics"); /* XXX */ |
1292 |
|
|
ielen = GTPV1_TV_CHARGING_LENGTH; |
1293 |
|
|
break; |
1294 |
|
|
|
1295 |
|
|
case GTPV1_TV_TRACE_REFERENCE: |
1296 |
|
|
|
1297 |
|
|
/* 29.060 7.7.24 - Trace Reference. */ |
1298 |
|
|
TCHECK2(cp[0], GTPV1_TV_TRACE_REFERENCE_LENGTH - 1); |
1299 |
|
|
dps = (u_int16_t *)cp; |
1300 |
|
|
printf("Trace Reference: %u", ntohs(*dps)); |
1301 |
|
|
ielen = GTPV1_TV_TRACE_REFERENCE_LENGTH; |
1302 |
|
|
break; |
1303 |
|
|
|
1304 |
|
|
case GTPV1_TV_TRACE_TYPE: |
1305 |
|
|
|
1306 |
|
|
/* 29.060 7.7.25 - Trace Type. */ |
1307 |
|
|
/* Trace type defined in GSM 12.08. */ |
1308 |
|
|
TCHECK2(cp[0], GTPV1_TV_TRACE_TYPE_LENGTH - 1); |
1309 |
|
|
dps = (u_int16_t *)cp; |
1310 |
|
|
printf("Trace Type: %u", ntohs(*dps)); |
1311 |
|
|
ielen = GTPV1_TV_TRACE_TYPE_LENGTH; |
1312 |
|
|
break; |
1313 |
|
|
|
1314 |
|
|
case GTPV1_TV_MSNRR: |
1315 |
|
|
|
1316 |
|
|
/* 29.060 7.7.26 - MS Not Reachable Reason. */ |
1317 |
|
|
/* Reason defined in 3GPP TS 23.040. */ |
1318 |
|
|
TCHECK2(cp[0], GTPV1_TV_MSNRR_LENGTH - 1); |
1319 |
|
|
printf("MS NRR: %u", cp[0]); |
1320 |
|
|
ielen = GTPV1_TV_MSNRR_LENGTH; |
1321 |
|
|
break; |
1322 |
|
|
|
1323 |
|
|
case GTPV1_TV_PACKET_XFER_CMD: |
1324 |
|
|
|
1325 |
|
|
/* 32.295 6.2.4.5.2 - Packet Transfer Command. */ |
1326 |
|
|
TCHECK2(cp[0], GTPV1_TV_PACKET_XFER_CMD_LENGTH - 1); |
1327 |
|
|
printf("Packet Transfer Command"); |
1328 |
|
|
gtp_print_str(gtp_packet_xfer_cmd, cp[0]); |
1329 |
|
|
ielen = GTPV1_TV_PACKET_XFER_CMD_LENGTH; |
1330 |
|
|
break; |
1331 |
|
|
|
1332 |
|
|
case GTPV1_TV_CHARGING_ID: |
1333 |
|
|
|
1334 |
|
|
/* 29.060 7.7.26 - Charging ID. */ |
1335 |
|
|
TCHECK2(cp[0], GTPV1_TV_CHARGING_ID_LENGTH - 1); |
1336 |
|
|
dpl = (u_int32_t *)cp; |
1337 |
|
|
printf("Charging ID: %u", ntohl(*dpl)); |
1338 |
|
|
ielen = GTPV1_TV_CHARGING_ID_LENGTH; |
1339 |
|
|
break; |
1340 |
|
|
|
1341 |
|
|
default: |
1342 |
|
|
printf("TV %u", value); |
1343 |
|
|
} |
1344 |
|
|
|
1345 |
|
|
trunc: |
1346 |
|
|
return ielen; |
1347 |
|
|
} |
1348 |
|
|
|
1349 |
|
|
int |
1350 |
|
|
gtp_v1_print_tlv(const u_char *cp, u_int value) |
1351 |
|
|
{ |
1352 |
|
|
u_int8_t data; |
1353 |
|
|
u_int16_t *lenp, *seqno, len; |
1354 |
|
|
int ielen = -1; |
1355 |
|
|
|
1356 |
|
|
/* Get length of IE. */ |
1357 |
|
|
TCHECK2(cp[0], 2); |
1358 |
|
|
lenp = (u_int16_t *)cp; |
1359 |
|
|
cp += 2; |
1360 |
|
|
len = ntohs(*lenp); |
1361 |
|
|
TCHECK2(cp[0], len); |
1362 |
|
|
ielen = sizeof(data) + sizeof(len) + len; |
1363 |
|
|
|
1364 |
|
|
switch (value) { |
1365 |
|
|
case GTPV1_TLV_END_USER_ADDRESS: |
1366 |
|
|
|
1367 |
|
|
/* 3GPP 29.060 - 7.7.27 End User Address. */ |
1368 |
|
|
printf("End User Address"); |
1369 |
|
|
gtp_print_user_address(cp, len); |
1370 |
|
|
break; |
1371 |
|
|
|
1372 |
|
|
case GTPV1_TLV_MM_CONTEXT: |
1373 |
|
|
|
1374 |
|
|
/* 29.060 7.7.28 - MM Context. */ |
1375 |
|
|
printf("MM Context"); /* XXX */ |
1376 |
|
|
break; |
1377 |
|
|
|
1378 |
|
|
case GTPV1_TLV_PDP_CONTEXT: |
1379 |
|
|
|
1380 |
|
|
/* 29.260 7.7.29 - PDP Context. */ |
1381 |
|
|
printf("PDP Context"); /* XXX */ |
1382 |
|
|
break; |
1383 |
|
|
|
1384 |
|
|
case GTPV1_TLV_ACCESS_POINT_NAME: |
1385 |
|
|
|
1386 |
|
|
/* 29.060 7.7.30 - Access Point Name. */ |
1387 |
|
|
printf("AP Name: "); |
1388 |
|
|
gtp_print_apn(cp, len); |
1389 |
|
|
break; |
1390 |
|
|
|
1391 |
|
|
case GTPV1_TLV_PROTOCOL_CONFIG_OPTIONS: |
1392 |
|
|
|
1393 |
|
|
/* 29.060 7.7.31 - Protocol Configuration Options. */ |
1394 |
|
|
/* Defined in 3GPP TS 24.008. */ |
1395 |
|
|
printf("Config Options"); /* XXX */ |
1396 |
|
|
break; |
1397 |
|
|
|
1398 |
|
|
case GTPV1_TLV_GSN_ADDRESS: |
1399 |
|
|
|
1400 |
|
|
/* 29.060 7.7.32 - GSN Address. */ |
1401 |
|
|
/* Defined in 3GPP TS 23.003. */ |
1402 |
|
|
printf("GSN Address"); |
1403 |
|
|
if (len == 4) |
1404 |
|
|
printf(": %s", ipaddr_string(cp)); |
1405 |
|
|
#ifdef INET6 |
1406 |
|
|
else if (len == 16) |
1407 |
|
|
printf(": %s", ip6addr_string(cp)); |
1408 |
|
|
#endif |
1409 |
|
|
break; |
1410 |
|
|
|
1411 |
|
|
case GTPV1_TLV_MSISDN: |
1412 |
|
|
|
1413 |
|
|
/* 29.060 7.7.33 - MS International PSTN/ISDN Number. */ |
1414 |
|
|
printf("MSISDN "); |
1415 |
|
|
data = (u_int8_t)cp[0]; /* XXX - Number type. */ |
1416 |
|
|
gtp_print_tbcd(cp + 1, len - 1); |
1417 |
|
|
break; |
1418 |
|
|
|
1419 |
|
|
case GTPV1_TLV_QOS_PROFILE: |
1420 |
|
|
|
1421 |
|
|
/* 29.060 7.7.34 - QoS Profile. */ |
1422 |
|
|
/* QoS profile defined in 3GPP TS 24.008 10.5.6.5. */ |
1423 |
|
|
printf("QoS Profile: "); |
1424 |
|
|
data = (u_int8_t)cp[0]; |
1425 |
|
|
printf("Delay Class %u, ", (data >> 3) & 0x7); |
1426 |
|
|
printf("Reliability Class %u", data & 0x7); |
1427 |
|
|
if (vflag > 1) { |
1428 |
|
|
printf(", "); |
1429 |
|
|
data = (u_int8_t)cp[1]; |
1430 |
|
|
printf("Precedence Class %u", data & 0x7); |
1431 |
|
|
/* XXX - Decode more QoS fields. */ |
1432 |
|
|
} |
1433 |
|
|
break; |
1434 |
|
|
|
1435 |
|
|
case GTPV1_TLV_AUTHENTICATION: |
1436 |
|
|
|
1437 |
|
|
/* 29.060 7.7.35 - Authentication. */ |
1438 |
|
|
printf("Authentication"); /* XXX */ |
1439 |
|
|
break; |
1440 |
|
|
|
1441 |
|
|
case GTPV1_TLV_TRAFFIC_FLOW: |
1442 |
|
|
|
1443 |
|
|
/* 29.060 7.7.36 - Traffic Flow Template. */ |
1444 |
|
|
printf("Traffic Flow Template"); /* XXX */ |
1445 |
|
|
break; |
1446 |
|
|
|
1447 |
|
|
case GTPV1_TLV_TARGET_IDENTIFICATION: |
1448 |
|
|
|
1449 |
|
|
/* 29.060 7.7.37 - Target Identification. */ |
1450 |
|
|
printf("Target ID"); /* XXX */ |
1451 |
|
|
break; |
1452 |
|
|
|
1453 |
|
|
case GTPV1_TLV_UTRAN_CONTAINER: |
1454 |
|
|
|
1455 |
|
|
/* 29.060 7.7.38 - UTRAN Transparent Container. */ |
1456 |
|
|
printf("UTRAN Container"); /* XXX */ |
1457 |
|
|
break; |
1458 |
|
|
|
1459 |
|
|
case GTPV1_TLV_RAB_SETUP_INFORMATION: |
1460 |
|
|
|
1461 |
|
|
/* 29.060 7.7.39 - RAB Setup Information. */ |
1462 |
|
|
printf("RAB Setup"); /* XXX */ |
1463 |
|
|
break; |
1464 |
|
|
|
1465 |
|
|
case GTPV1_TLV_EXT_HEADER_TYPE_LIST: |
1466 |
|
|
|
1467 |
|
|
/* 29.060 7.7.40 - Extension Header Type List. */ |
1468 |
|
|
printf("Extension Header List"); /* XXX */ |
1469 |
|
|
break; |
1470 |
|
|
|
1471 |
|
|
case GTPV1_TLV_TRIGGER_ID: |
1472 |
|
|
|
1473 |
|
|
/* 29.060 7.7.41 - Trigger ID. */ |
1474 |
|
|
printf("Trigger ID"); /* XXX */ |
1475 |
|
|
break; |
1476 |
|
|
|
1477 |
|
|
case GTPV1_TLV_OMC_IDENTITY: |
1478 |
|
|
|
1479 |
|
|
/* 29.060 7.7.42 - OMC Identity. */ |
1480 |
|
|
printf("OMC Identity"); /* XXX */ |
1481 |
|
|
break; |
1482 |
|
|
|
1483 |
|
|
case GTPV1_TLV_RAN_CONTAINER: |
1484 |
|
|
|
1485 |
|
|
/* 29.060 7.7.43 - RAN Transparent Container. */ |
1486 |
|
|
printf("RAN Container"); /* XXX */ |
1487 |
|
|
break; |
1488 |
|
|
|
1489 |
|
|
case GTPV1_TLV_PDP_CONTEXT_PRIORITIZATION: |
1490 |
|
|
|
1491 |
|
|
/* 29.060 7.7.45 - PDP Context Prioritization. */ |
1492 |
|
|
printf("PDP Context Prioritization"); /* XXX */ |
1493 |
|
|
break; |
1494 |
|
|
|
1495 |
|
|
case GTPV1_TLV_ADDITIONAL_RAB_SETUP_INFO: |
1496 |
|
|
|
1497 |
|
|
/* 29.060 7.7.45A - Additional RAB Setup Information. */ |
1498 |
|
|
printf("Additional RAB Setup"); /* XXX */ |
1499 |
|
|
break; |
1500 |
|
|
|
1501 |
|
|
case GTPV1_TLV_SGSN_NUMBER: |
1502 |
|
|
|
1503 |
|
|
/* 29.060 7.7.47 - SGSN Number. */ |
1504 |
|
|
printf("SGSN Number"); /* XXX */ |
1505 |
|
|
break; |
1506 |
|
|
|
1507 |
|
|
case GTPV1_TLV_COMMON_FLAGS: |
1508 |
|
|
|
1509 |
|
|
/* 29.060 7.7.48 - Common Flags. */ |
1510 |
|
|
printf("Common Flags"); /* XXX */ |
1511 |
|
|
break; |
1512 |
|
|
|
1513 |
|
|
case GTPV1_TLV_APN_RESTRICTION: |
1514 |
|
|
|
1515 |
|
|
/* 29.060 7.7.49 - APN Restriction. */ |
1516 |
|
|
data = (u_int8_t)cp[0]; |
1517 |
|
|
printf("APN Restriction: %u", data); |
1518 |
|
|
break; |
1519 |
|
|
|
1520 |
|
|
case GTPV1_TLV_RADIO_PRIORITY_LCS: |
1521 |
|
|
|
1522 |
|
|
/* 29.060 7.7.25B - Radio Priority LCS. */ |
1523 |
|
|
printf("Radio Priority LCS: %u", cp[0] & 0x7); |
1524 |
|
|
break; |
1525 |
|
|
|
1526 |
|
|
case GTPV1_TLV_RAT_TYPE: |
1527 |
|
|
|
1528 |
|
|
/* 29.060 7.7.50 - RAT Type. */ |
1529 |
|
|
printf("RAT"); |
1530 |
|
|
gtp_print_str(gtp_rat_type, cp[0]); |
1531 |
|
|
break; |
1532 |
|
|
|
1533 |
|
|
case GTPV1_TLV_USER_LOCATION_INFO: |
1534 |
|
|
|
1535 |
|
|
/* 29.060 7.7.51 - User Location Information. */ |
1536 |
|
|
printf("ULI"); /* XXX */ |
1537 |
|
|
break; |
1538 |
|
|
|
1539 |
|
|
case GTPV1_TLV_MS_TIME_ZONE: |
1540 |
|
|
|
1541 |
|
|
/* 29.060 7.7.52 - MS Time Zone. */ |
1542 |
|
|
printf("MSTZ"); /* XXX */ |
1543 |
|
|
break; |
1544 |
|
|
|
1545 |
|
|
case GTPV1_TLV_IMEI_SV: |
1546 |
|
|
|
1547 |
|
|
/* 29.060 7.7.53 - IMEI(SV). */ |
1548 |
|
|
printf("IMEI(SV) "); |
1549 |
|
|
gtp_print_tbcd(cp, len); |
1550 |
|
|
break; |
1551 |
|
|
|
1552 |
|
|
case GTPV1_TLV_CAMEL_CHARGING_CONTAINER: |
1553 |
|
|
|
1554 |
|
|
/* 29.060 7.7.54 - CAMEL Charging Information Container. */ |
1555 |
|
|
printf("CAMEL Charging"); /* XXX */ |
1556 |
|
|
break; |
1557 |
|
|
|
1558 |
|
|
case GTPV1_TLV_MBMS_UE_CONTEXT: |
1559 |
|
|
|
1560 |
|
|
/* 29.060 7.7.55 - MBMS UE Context. */ |
1561 |
|
|
printf("MBMS UE Context"); /* XXX */ |
1562 |
|
|
break; |
1563 |
|
|
|
1564 |
|
|
case GTPV1_TLV_TMGI: |
1565 |
|
|
|
1566 |
|
|
/* 29.060 7.7.56 - Temporary Mobile Group Identity. */ |
1567 |
|
|
printf("TMGI"); /* XXX */ |
1568 |
|
|
break; |
1569 |
|
|
|
1570 |
|
|
case GTPV1_TLV_RIM_ROUTING_ADDRESS: |
1571 |
|
|
|
1572 |
|
|
/* 29.060 7.7.57 - RIM Routing Address. */ |
1573 |
|
|
printf("RIM Routing Address"); /* XXX */ |
1574 |
|
|
break; |
1575 |
|
|
|
1576 |
|
|
case GTPV1_TLV_MBMS_PROTOCOL_CONFIG_OPTIONS: |
1577 |
|
|
|
1578 |
|
|
/* 29.060 7.7.58 - MBMS Protocol Configuration Options. */ |
1579 |
|
|
printf("MBMS Protocol Config Options"); /* XXX */ |
1580 |
|
|
break; |
1581 |
|
|
|
1582 |
|
|
case GTPV1_TLV_MBMS_SERVICE_AREA: |
1583 |
|
|
|
1584 |
|
|
/* 29.060 7.7.60 - MBMS Service Area. */ |
1585 |
|
|
printf("MBMS Service Area"); /* XXX */ |
1586 |
|
|
break; |
1587 |
|
|
|
1588 |
|
|
case GTPV1_TLV_SOURCE_RNC_PDCP_CONTEXT_INFO: |
1589 |
|
|
|
1590 |
|
|
/* 29.060 7.7.61 - Source RNC PDCP Context Information. */ |
1591 |
|
|
printf("Source RNC PDCP Context"); /* XXX */ |
1592 |
|
|
break; |
1593 |
|
|
|
1594 |
|
|
case GTPV1_TLV_ADDITIONAL_TRACE_INFO: |
1595 |
|
|
|
1596 |
|
|
/* 29.060 7.7.62 - Additional Trace Information. */ |
1597 |
|
|
printf("Additional Trace Info"); /* XXX */ |
1598 |
|
|
break; |
1599 |
|
|
|
1600 |
|
|
case GTPV1_TLV_HOP_COUNTER: |
1601 |
|
|
|
1602 |
|
|
/* 29.060 7.7.63 - Hop Counter. */ |
1603 |
|
|
printf("Hop Counter: %u", cp[0]); |
1604 |
|
|
break; |
1605 |
|
|
|
1606 |
|
|
case GTPV1_TLV_SELECTED_PLMN_ID: |
1607 |
|
|
|
1608 |
|
|
/* 29.060 7.7.64 - Selected PLMN ID. */ |
1609 |
|
|
printf("Selected PLMN ID"); /* XXX */ |
1610 |
|
|
break; |
1611 |
|
|
|
1612 |
|
|
case GTPV1_TLV_MBMS_SESSION_IDENTIFIER: |
1613 |
|
|
|
1614 |
|
|
/* 29.060 7.7.65 - MBMS Session Identifier. */ |
1615 |
|
|
printf("MBMS Session ID: %u", cp[0]); |
1616 |
|
|
break; |
1617 |
|
|
|
1618 |
|
|
case GTPV1_TLV_MBMS_2G_3G_INDICATOR: |
1619 |
|
|
|
1620 |
|
|
/* 29.060 7.7.66 - MBMS 2G/3G Indicator. */ |
1621 |
|
|
printf("MBMS 2G/3G Indicator"); |
1622 |
|
|
gtp_print_str(mbms_2g3g_indicator, cp[0]); |
1623 |
|
|
break; |
1624 |
|
|
|
1625 |
|
|
case GTPV1_TLV_ENHANCED_NSAPI: |
1626 |
|
|
|
1627 |
|
|
/* 29.060 7.7.67 - Enhanced NSAPI. */ |
1628 |
|
|
printf("Enhanced NSAPI"); /* XXX */ |
1629 |
|
|
break; |
1630 |
|
|
|
1631 |
|
|
case GTPV1_TLV_MBMS_SESSION_DURATION: |
1632 |
|
|
|
1633 |
|
|
/* 29.060 7.7.59 - MBMS Session Duration. */ |
1634 |
|
|
printf("MBMS Session Duration"); /* XXX */ |
1635 |
|
|
break; |
1636 |
|
|
|
1637 |
|
|
case GTPV1_TLV_ADDITIONAL_MBMS_TRACE_INFO: |
1638 |
|
|
|
1639 |
|
|
/* 29.060 7.7.68 - Additional MBMS Trace Info. */ |
1640 |
|
|
printf("Additional MBMS Trace Info"); /* XXX */ |
1641 |
|
|
break; |
1642 |
|
|
|
1643 |
|
|
case GTPV1_TLV_MBMS_SESSION_REPITITION_NO: |
1644 |
|
|
|
1645 |
|
|
/* 29.060 7.7.69 - MBMS Session Repetition Number. */ |
1646 |
|
|
printf("MBMS Session Repetition No: %u", cp[0]); |
1647 |
|
|
break; |
1648 |
|
|
|
1649 |
|
|
case GTPV1_TLV_MBMS_TIME_TO_DATA_TRANSFER: |
1650 |
|
|
|
1651 |
|
|
/* 29.060 7.7.70 - MBMS Time to Data Transfer. */ |
1652 |
|
|
printf("MBMS Time to Data Transfer: %u", cp[0]); |
1653 |
|
|
break; |
1654 |
|
|
|
1655 |
|
|
case GTPV1_TLV_PS_HANDOVER_REQUEST_CONTEXT: |
1656 |
|
|
|
1657 |
|
|
/* 29.060 7.7.71 - PS Handover Request Context (Void). */ |
1658 |
|
|
break; |
1659 |
|
|
|
1660 |
|
|
case GTPV1_TLV_BSS_CONTAINER: |
1661 |
|
|
|
1662 |
|
|
/* 29.060 7.7.72 - BSS Container. */ |
1663 |
|
|
printf("BSS Container"); /* XXX */ |
1664 |
|
|
break; |
1665 |
|
|
|
1666 |
|
|
case GTPV1_TLV_CELL_IDENTIFICATION: |
1667 |
|
|
|
1668 |
|
|
/* 29.060 7.7.73 - Cell Identification. */ |
1669 |
|
|
printf("Cell Identification"); /* XXX */ |
1670 |
|
|
break; |
1671 |
|
|
|
1672 |
|
|
case GTPV1_TLV_PDU_NUMBERS: |
1673 |
|
|
|
1674 |
|
|
/* 29.060 7.7.74 - PDU Numbers. */ |
1675 |
|
|
printf("PDU Numbers"); /* XXX */ |
1676 |
|
|
break; |
1677 |
|
|
|
1678 |
|
|
case GTPV1_TLV_BSSGP_CAUSE: |
1679 |
|
|
|
1680 |
|
|
/* 29.060 7.7.75 - BSSGP Cause. */ |
1681 |
|
|
printf("BSSGP Cause: %u", cp[0]); |
1682 |
|
|
break; |
1683 |
|
|
|
1684 |
|
|
case GTPV1_TLV_REQUIRED_MBMS_BEARER_CAP: |
1685 |
|
|
|
1686 |
|
|
/* 29.060 7.7.76 - Required MBMS Bearer Cap. */ |
1687 |
|
|
printf("Required MBMS Bearer Cap"); /* XXX */ |
1688 |
|
|
break; |
1689 |
|
|
|
1690 |
|
|
case GTPV1_TLV_RIM_ROUTING_ADDRESS_DISC: |
1691 |
|
|
|
1692 |
|
|
/* 29.060 7.7.77 - RIM Routing Address Discriminator. */ |
1693 |
|
|
printf("RIM Routing Address Discriminator: %u", cp[0] & 0xf); |
1694 |
|
|
break; |
1695 |
|
|
|
1696 |
|
|
case GTPV1_TLV_LIST_OF_SETUP_PFCS: |
1697 |
|
|
|
1698 |
|
|
/* 29.060 7.7.78 - List of Setup PFCs. */ |
1699 |
|
|
printf("List of Setup PFCs"); /* XXX */ |
1700 |
|
|
break; |
1701 |
|
|
|
1702 |
|
|
case GTPV1_TLV_PS_HANDOVER_XID_PARAMETERS: |
1703 |
|
|
|
1704 |
|
|
/* 29.060 7.7.79 - PS Handover XID Parameters. */ |
1705 |
|
|
printf("PS Handover XID Parameters"); /* XXX */ |
1706 |
|
|
break; |
1707 |
|
|
|
1708 |
|
|
case GTPV1_TLV_MS_INFO_CHANGE_REPORTING: |
1709 |
|
|
|
1710 |
|
|
/* 29.060 7.7.80 - MS Info Change Reporting. */ |
1711 |
|
|
printf("MS Info Change Reporting"); |
1712 |
|
|
gtp_print_str(ms_info_change_rpt, cp[0]); |
1713 |
|
|
break; |
1714 |
|
|
|
1715 |
|
|
case GTPV1_TLV_DIRECT_TUNNEL_FLAGS: |
1716 |
|
|
|
1717 |
|
|
/* 29.060 7.7.81 - Direct Tunnel Flags. */ |
1718 |
|
|
printf("Direct Tunnel Flags"); /* XXX */ |
1719 |
|
|
break; |
1720 |
|
|
|
1721 |
|
|
case GTPV1_TLV_CORRELATION_ID: |
1722 |
|
|
|
1723 |
|
|
/* 29.060 7.7.82 - Correlation ID. */ |
1724 |
|
|
printf("Correlation ID"); /* XXX */ |
1725 |
|
|
break; |
1726 |
|
|
|
1727 |
|
|
case GTPV1_TLV_BEARER_CONTROL_MODE: |
1728 |
|
|
|
1729 |
|
|
/* 29.060 7.7.83 - Bearer Control Mode. */ |
1730 |
|
|
printf("Bearer Control Mode"); /* XXX */ |
1731 |
|
|
break; |
1732 |
|
|
|
1733 |
|
|
case GTPV1_TLV_MBMS_FLOW_IDENTIFIER: |
1734 |
|
|
|
1735 |
|
|
/* 29.060 7.7.84 - MBMS Flow Identifier. */ |
1736 |
|
|
printf("MBMS Flow Identifier"); /* XXX */ |
1737 |
|
|
break; |
1738 |
|
|
|
1739 |
|
|
case GTPV1_TLV_RELEASED_PACKETS: |
1740 |
|
|
|
1741 |
|
|
/* 32.295 6.2.4.5.4 - Sequence Numbers of Released Packets. */ |
1742 |
|
|
printf("Released Packets:"); |
1743 |
|
|
seqno = (u_int16_t *)cp; |
1744 |
|
|
while (len > 0) { |
1745 |
|
|
printf(" %u", ntohs(*seqno)); |
1746 |
|
|
seqno++; |
1747 |
|
|
len -= sizeof(*seqno); |
1748 |
|
|
} |
1749 |
|
|
break; |
1750 |
|
|
|
1751 |
|
|
case GTPV1_TLV_CANCELLED_PACKETS: |
1752 |
|
|
|
1753 |
|
|
/* 32.295 6.2.4.5.5 - Sequence Numbers of Cancelled Packets. */ |
1754 |
|
|
printf("Cancelled Packets:"); |
1755 |
|
|
seqno = (u_int16_t *)cp; |
1756 |
|
|
while (len > 0) { |
1757 |
|
|
printf(" %u", ntohs(*seqno)); |
1758 |
|
|
seqno++; |
1759 |
|
|
len -= sizeof(*seqno); |
1760 |
|
|
} |
1761 |
|
|
break; |
1762 |
|
|
|
1763 |
|
|
case GTPV1_TLV_CHARGING_GATEWAY_ADDRESS: |
1764 |
|
|
|
1765 |
|
|
/* 29.060 7.7.44 - Charging Gateway Address. */ |
1766 |
|
|
printf("Charging Gateway"); |
1767 |
|
|
if (len == 4) |
1768 |
|
|
printf(": %s", ipaddr_string(cp)); |
1769 |
|
|
#ifdef INET6 |
1770 |
|
|
else if (len == 16) |
1771 |
|
|
printf(": %s", ip6addr_string(cp)); |
1772 |
|
|
#endif |
1773 |
|
|
break; |
1774 |
|
|
|
1775 |
|
|
case GTPV1_TLV_DATA_RECORD_PACKET: |
1776 |
|
|
|
1777 |
|
|
/* 32.295 6.2.4.5.3 - Data Record Packet. */ |
1778 |
|
|
printf("Data Record: Records %u, Format %u, Format Version %u", |
1779 |
|
|
cp[0], cp[1], ntohs(*(u_int16_t *)(cp + 2))); |
1780 |
|
|
break; |
1781 |
|
|
|
1782 |
|
|
case GTPV1_TLV_REQUESTS_RESPONDED: |
1783 |
|
|
|
1784 |
|
|
/* 32.295 6.2.4.6 - Requests Responded. */ |
1785 |
|
|
printf("Requests Responded:"); |
1786 |
|
|
seqno = (u_int16_t *)cp; |
1787 |
|
|
while (len > 0) { |
1788 |
|
|
printf(" %u", ntohs(*seqno)); |
1789 |
|
|
seqno++; |
1790 |
|
|
len -= sizeof(*seqno); |
1791 |
|
|
} |
1792 |
|
|
break; |
1793 |
|
|
|
1794 |
|
|
case GTPV1_TLV_ADDRESS_OF_RECOMMENDED_NODE: |
1795 |
|
|
|
1796 |
|
|
/* 32.295 6.2.4.3 - Address of Recommended Node. */ |
1797 |
|
|
printf("Address of Recommended Node"); |
1798 |
|
|
if (len == 4) |
1799 |
|
|
printf(": %s", ipaddr_string(cp)); |
1800 |
|
|
#ifdef INET6 |
1801 |
|
|
else if (len == 16) |
1802 |
|
|
printf(": %s", ip6addr_string(cp)); |
1803 |
|
|
#endif |
1804 |
|
|
break; |
1805 |
|
|
|
1806 |
|
|
case GTPV1_TLV_PRIVATE_EXTENSION: |
1807 |
|
|
|
1808 |
|
|
/* 29.060 7.7.46 - Private Extension. */ |
1809 |
|
|
printf("Private Extension"); |
1810 |
|
|
break; |
1811 |
|
|
|
1812 |
|
|
default: |
1813 |
|
|
printf("TLV %u (len %u)", value, len); |
1814 |
|
|
} |
1815 |
|
|
|
1816 |
|
|
return ielen; |
1817 |
|
|
|
1818 |
|
|
trunc: |
1819 |
|
|
return -1; |
1820 |
|
|
} |