diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2009-11-04 09:43:12 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2009-11-04 09:43:12 +0000 |
commit | e9c829b4e1c51318cb40adbd0b53553f1a830e8f (patch) | |
tree | 0ed444d5d814d9fa4d08b4668b693e2ea3e10a85 /usr.sbin/tcpdump | |
parent | 8f05f74155ac584d7b2bfadbd35625184a2f91dd (diff) |
Add support to tcpdump for decoding the GPRS Tunnelling Protocol (GTP),
used to carry GPRS data over IP for GSM and UMTS networks. The decoder
understands GTPv0, GTPv0', GTPv1-C, GTPv1-U and GTPv1' traffic, however
at this stage not all TLV fields are fully decoded.
This work has been kindly sponsored by SystemNet AS (www.systemnet.no).
"commit" deraadt@
Diffstat (limited to 'usr.sbin/tcpdump')
-rw-r--r-- | usr.sbin/tcpdump/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/tcpdump/gtp.h | 437 | ||||
-rw-r--r-- | usr.sbin/tcpdump/interface.h | 5 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-gtp.c | 1800 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-udp.c | 9 |
5 files changed, 2250 insertions, 5 deletions
diff --git a/usr.sbin/tcpdump/Makefile b/usr.sbin/tcpdump/Makefile index 859711cbfb1..e04594d7fa4 100644 --- a/usr.sbin/tcpdump/Makefile +++ b/usr.sbin/tcpdump/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.52 2008/10/16 12:57:01 mpf Exp $ +# $OpenBSD: Makefile,v 1.53 2009/11/04 09:43:11 jsing Exp $ # # Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 # The Regents of the University of California. All rights reserved. @@ -34,7 +34,7 @@ SRCS= tcpdump.c addrtoname.c privsep.c privsep_fdpass.c privsep_pcap.c \ print-ether.c print-ip.c print-arp.c print-tcp.c print-udp.c \ print-atalk.c print-domain.c print-tftp.c print-bootp.c print-nfs.c \ print-icmp.c print-sl.c print-ppp.c print-rip.c print-timed.c \ - print-snmp.c print-ntp.c print-null.c print-ospf.c \ + print-snmp.c print-ntp.c print-null.c print-ospf.c print-gtp.c \ print-fddi.c print-llc.c print-sunrpc.c print-hsrp.c print-vqp.c \ print-vrrp.c print-wb.c print-decnet.c print-isoclns.c print-ipx.c \ print-atm.c print-dvmrp.c print-krb.c print-pim.c print-netbios.c \ diff --git a/usr.sbin/tcpdump/gtp.h b/usr.sbin/tcpdump/gtp.h new file mode 100644 index 00000000000..629a61ccc65 --- /dev/null +++ b/usr.sbin/tcpdump/gtp.h @@ -0,0 +1,437 @@ +/* $OpenBSD: gtp.h,v 1.1 2009/11/04 09:43:11 jsing Exp $ */ +/* + * Copyright (c) 2009 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __GTP_H_DEFINED +#define __GTP_H_DEFINED + +#define GTP_VERSION_0 0 +#define GTP_VERSION_1 1 +#define GTP_VERSION_2 2 + +#define GTP_VERSION_MASK 0x07 << 5 +#define GTP_VERSION_SHIFT 5 + +#define GTP_V0_PROTO 0 +#define GTP_V0_PRIME_PROTO 1 +#define GTP_V1_CTRL_PROTO 2 +#define GTP_V1_USER_PROTO 3 +#define GTP_V1_PRIME_PROTO 4 + +#define GTPV0_PORT 3386 + +#define GTPV1_C_PORT 2123 +#define GTPV1_U_PORT 2152 +#define GTPV1_PRIME_PORT 3386 + +#define GTPV0_HDR_PROTO_TYPE 1 << 4 +#define GTPV0_HDR_SNN 1 << 0 + +#define GTPV0_IE_TYPE_MASK 1 << 7 +#define GTPV0_IE_VALUE_MASK ~GTPV1_IE_TYPE_MASK + +/* + * GTPv0 Message Types. + */ +#define GTPV0_ECHO_REQUEST 1 +#define GTPV0_ECHO_RESPONSE 2 +#define GTPV0_VERSION_NOT_SUPPORTED 3 +#define GTPV0_NODE_ALIVE_REQUEST 4 +#define GTPV0_NODE_ALIVE_RESPONSE 5 +#define GTPV0_REDIRECTION_REQUEST 6 +#define GTPV0_REDIRECTION_RESPONSE 7 +#define GTPV0_CREATE_PDP_CONTEXT_REQUEST 16 +#define GTPV0_CREATE_PDP_CONTEXT_RESPONSE 17 +#define GTPV0_UPDATE_PDP_CONTEXT_REQUEST 18 +#define GTPV0_UPDATE_PDP_CONTEXT_RESPONSE 19 +#define GTPV0_DELETE_PDP_CONTEXT_REQUEST 20 +#define GTPV0_DELETE_PDP_CONTEXT_RESPONSE 21 +#define GTPV0_CREATE_AA_PDP_CONTEXT_REQUEST 22 +#define GTPV0_CREATE_AA_PDP_CONTEXT_RESPONSE 23 +#define GTPV0_DELETE_AA_PDP_CONTEXT_REQUEST 24 +#define GTPV0_DELETE_AA_PDP_CONTEXT_RESPONSE 25 +#define GTPV0_ERROR_INDICATION 26 +#define GTPV0_PDU_NOTIFICATION_REQUEST 27 +#define GTPV0_PDU_NOTIFICATION_RESPONSE 28 +#define GTPV0_PDU_NOTIFICATION_REJECT_REQUEST 29 +#define GTPV0_PDU_NOTIFICATION_REJECT_RESPONSE 30 +#define GTPV0_SEND_ROUTEING_INFO_REQUEST 32 +#define GTPV0_SEND_ROUTEING_INFO_RESPONSE 33 +#define GTPV0_FAILURE_REPORT_REQUEST 34 +#define GTPV0_FAILURE_REPORT_RESPONSE 35 +#define GTPV0_MS_GPRS_PRESENT_REQUEST 36 +#define GTPV0_MS_GPRS_PRESENT_RESPONSE 37 +#define GTPV0_IDENTIFICATION_REQUEST 48 +#define GTPV0_IDENTIFICATION_RESPONSE 49 +#define GTPV0_SGSN_CONTEXT_REQUEST 50 +#define GTPV0_SGSN_CONTEXT_RESPONSE 51 +#define GTPV0_SGSN_CONTEXT_ACKNOWLEDGE 52 +#define GTPV0_DATA_RECORD_TRANSFER_REQUEST 240 +#define GTPV0_DATA_RECORD_TRANSFER_RESPONSE 241 +#define GTPV0_T_PDU 255 + +/* + * GTPv0 Information Elements. + */ +#define GTPV0_TV_CAUSE 1 +#define GTPV0_TV_CAUSE_LENGTH 2 +#define GTPV0_TV_IMSI 2 +#define GTPV0_TV_IMSI_LENGTH 9 +#define GTPV0_TV_RAI 3 +#define GTPV0_TV_RAI_LENGTH 7 +#define GTPV0_TV_TLLI 4 +#define GTPV0_TV_TLLI_LENGTH 5 +#define GTPV0_TV_PTMSI 5 +#define GTPV0_TV_PTMSI_LENGTH 5 +#define GTPV0_TV_QOS 6 +#define GTPV0_TV_QOS_LENGTH 4 +#define GTPV0_TV_REORDER 8 +#define GTPV0_TV_REORDER_LENGTH 2 +#define GTPV0_TV_AUTH_TRIPLET 9 +#define GTPV0_TV_AUTH_TRIPLET_LENGTH 29 +#define GTPV0_TV_MAP_CAUSE 11 +#define GTPV0_TV_MAP_CAUSE_LENGTH 2 +#define GTPV0_TV_PTMSI_SIGNATURE 12 +#define GTPV0_TV_PTMSI_SIGNATURE_LENGTH 4 +#define GTPV0_TV_MS_VALIDATED 13 +#define GTPV0_TV_MS_VALIDATED_LENGTH 2 +#define GTPV0_TV_RECOVERY 14 +#define GTPV0_TV_RECOVERY_LENGTH 2 +#define GTPV0_TV_SELECTION_MODE 15 +#define GTPV0_TV_SELECTION_MODE_LENGTH 2 +#define GTPV0_TV_FLOW_LABEL_DATA_I 16 +#define GTPV0_TV_FLOW_LABEL_DATA_I_LENGTH 3 +#define GTPV0_TV_FLOW_LABEL_SIGNALLING 17 +#define GTPV0_TV_FLOW_LABEL_SIGNALLING_LENGTH 3 +#define GTPV0_TV_FLOW_LABEL_DATA_II 18 +#define GTPV0_TV_FLOW_LABEL_DATA_II_LENGTH 4 +#define GTPV0_TV_PACKET_XFER_CMD 126 +#define GTPV0_TV_PACKET_XFER_CMD_LENGTH 2 +#define GTPV0_TV_CHARGING_ID 127 +#define GTPV0_TV_CHARGING_ID_LENGTH 5 + +#define GTPV0_TLV_END_USER_ADDRESS 128 +#define GTPV0_TLV_MM_CONTEXT 129 +#define GTPV0_TLV_PDP_CONTEXT 130 +#define GTPV0_TLV_ACCESS_POINT_NAME 131 +#define GTPV0_TLV_PROTOCOL_CONFIG_OPTIONS 132 +#define GTPV0_TLV_GSN_ADDRESS 133 +#define GTPV0_TLV_MS_ISDN 134 +#define GTPV0_TLV_RELEASED_PACKETS 249 +#define GTPV0_TLV_CANCELLED_PACKETS 250 +#define GTPV0_TLV_CHARGING_GATEWAY_ADDRESS 251 +#define GTPV0_TLV_DATA_RECORD_PACKET 252 +#define GTPV0_TLV_REQUESTS_RESPONDED 253 +#define GTPV0_TLV_RECOMMENDED_NODE 254 +#define GTPV0_TLV_PRIVATE_EXTENSION 255 + +/* + * GTP Version 1. + */ + +#define GTPV1_HDR_PROTO_TYPE 1 << 4 +#define GTPV1_HDR_RSVD 1 << 3 +#define GTPV1_HDR_EH_FLAG 1 << 2 +#define GTPV1_HDR_SN_FLAG 1 << 1 +#define GTPV1_HDR_NPDU_FLAG 1 << 0 + +/* + * GTPv1 Extended Headers. + */ +#define GTPV1_HDR_EXT (GTPV1_HDR_EH_FLAG | \ + GTPV1_HDR_SN_FLAG | \ + GTPV1_HDR_NPDU_FLAG) + +#define GTPV1_EH_NONE 0x00 +#define GTPV1_EH_MBMS_SUPPORT 0x01 +#define GTPV1_EH_MSI_CHANGE_RPT 0x02 +#define GTPV1_EH_PDCP_PDU_NO 0xc0 +#define GTPV1_EH_SUSPEND_REQUEST 0xc1 +#define GTPV1_EH_SUSPEND_RESPONSE 0xc2 + +#define GTPV1_IE_TYPE_MASK 1 << 7 +#define GTPV1_IE_VALUE_MASK ~GTPV1_IE_TYPE_MASK + +#define GTPV1_CAUSE_VALUE_MASK 3 << 6 +#define GTPV1_CAUSE_REQUEST 0x00 +#define GTPV1_CAUSE_ACCEPTANCE 0x80 +#define GTPV1_CAUSE_REJECTION 0xc0 + +/* + * GTPv1 Message Types. + */ +#define GTPV1_ECHO_REQUEST 1 +#define GTPV1_ECHO_RESPONSE 2 +#define GTPV1_VERSION_NOT_SUPPORTED 3 +#define GTPV1_NODE_ALIVE_REQUEST 4 +#define GTPV1_NODE_ALIVE_RESPONSE 5 +#define GTPV1_REDIRECTION_REQUEST 6 +#define GTPV1_REDIRECTION_RESPONSE 7 +#define GTPV1_CREATE_PDP_REQUEST 16 +#define GTPV1_CREATE_PDP_RESPONSE 17 +#define GTPV1_UPDATE_PDP_REQUEST 18 +#define GTPV1_UPDATE_PDP_RESPONSE 19 +#define GTPV1_DELETE_PDP_REQUEST 20 +#define GTPV1_DELETE_PDP_RESPONSE 21 +#define GTPV1_INIT_PDP_ACTIVATE_REQUEST 22 +#define GTPV1_INIT_PDP_ACTIVATE_RESPONSE 23 +#define GTPV1_ERROR_INDICATION 26 +#define GTPV1_PDU_NOTIFICATION_REQUEST 27 +#define GTPV1_PDU_NOTIFICATION_RESPONSE 28 +#define GTPV1_PDU_NOTIFICATION_REJECT_REQUEST 29 +#define GTPV1_PDU_NOTIFICATION_REJECT_RESPONSE 30 +#define GTPV1_SUPPORT_EXT_HEADER_NOTIFICATION 31 +#define GTPV1_SEND_ROUTEING_INFO_REQUEST 32 +#define GTPV1_SEND_ROUTEING_INFO_RESPONSE 33 +#define GTPV1_FAILURE_REPORT_REQUEST 34 +#define GTPV1_FAILURE_REPORT_RESPONSE 35 +#define GTPV1_NOTE_MS_GPRS_PRESENT_REQUEST 36 +#define GTPV1_NOTE_MS_GPRS_PRESENT_RESPONSE 37 +#define GTPV1_IDENTIFICATION_REQUEST 48 +#define GTPV1_IDENTIFICATION_RESPONSE 49 +#define GTPV1_SGSN_CONTEXT_REQUEST 50 +#define GTPV1_SGSN_CONTEXT_RESPONSE 51 +#define GTPV1_SGSN_CONTEXT_ACKNOWLEDGE 52 +#define GTPV1_FORWARD_RELOCATION_REQUEST 53 +#define GTPV1_FORWARD_RELOCATION_RESPONSE 54 +#define GTPV1_FORWARD_RELOCATION_COMPLETE 55 +#define GTPV1_RELOCATION_CANCEL_REQUEST 56 +#define GTPV1_RELOCATION_CANCEL_RESPONSE 57 +#define GTPV1_FORWARD_SRNS_CONTEXT 58 +#define GTPV1_FORWARD_RELOCATION_COMPLETE_ACK 59 +#define GTPV1_FORWARD_SRNS_CONTEXT_ACK 60 +#define GTPV1_RAN_INFORMATION_RELAY 70 +#define GTPV1_MBMS_NOTIFICATION_REQUEST 96 +#define GTPV1_MBMS_NOTIFICATION_RESPONSE 97 +#define GTPV1_MBMS_NOTIFICATION_REJECT_REQUEST 98 +#define GTPV1_MBMS_NOTIFICATION_REJECT_RESPONSE 99 +#define GTPV1_CREATE_MBMS_CONTEXT_REQUEST 100 +#define GTPV1_CREATE_MBMS_CONTEXT_RESPONSE 101 +#define GTPV1_UPDATE_MBMS_CONTEXT_REQUEST 102 +#define GTPV1_UPDATE_MBMS_CONTEXT_RESPONSE 103 +#define GTPV1_DELETE_MBMS_CONTEXT_REQUEST 104 +#define GTPV1_DELETE_MBMS_CONTEXT_RESPONSE 105 +#define GTPV1_MBMS_REGISTRATION_REQUEST 112 +#define GTPV1_MBMS_REGISTRATION_RESPONSE 113 +#define GTPV1_MBMS_DEREGISTRATION_REQUEST 114 +#define GTPV1_MBMS_DEREGISTRATION_RESPONSE 115 +#define GTPV1_MBMS_SESSION_START_REQUEST 116 +#define GTPV1_MBMS_SESSION_START_RESPONSE 117 +#define GTPV1_MBMS_SESSION_STOP_REQUEST 118 +#define GTPV1_MBMS_SESSION_STOP_RESPONSE 119 +#define GTPV1_MBMS_SESSION_UPDATE_REQUEST 120 +#define GTPV1_MBMS_SESSION_UPDATE_RESPONSE 121 +#define GTPV1_MS_INFO_CHANGE_REQUEST 128 +#define GTPV1_MS_INFO_CHANGE_RESPONSE 129 +#define GTPV1_DATA_RECORD_XFER_REQUEST 240 +#define GTPV1_DATA_RECORD_XFER_RESPONSE 241 +#define GTPV1_G_PDU 255 + +/* + * GTPv1 Information Elements. + */ +#define GTPV1_TV_CAUSE 1 +#define GTPV1_TV_CAUSE_LENGTH 2 +#define GTPV1_TV_IMSI 2 +#define GTPV1_TV_IMSI_LENGTH 9 +#define GTPV1_TV_RAI 3 +#define GTPV1_TV_RAI_LENGTH 7 +#define GTPV1_TV_TLLI 4 +#define GTPV1_TV_TLLI_LENGTH 5 +#define GTPV1_TV_PTMSI 5 +#define GTPV1_TV_PTMSI_LENGTH 6 +#define GTPV1_TV_REORDER 8 +#define GTPV1_TV_REORDER_LENGTH 2 +#define GTPV1_TV_AUTH 9 +#define GTPV1_TV_AUTH_LENGTH 29 +#define GTPV1_TV_MAP_CAUSE 11 +#define GTPV1_TV_MAP_CAUSE_LENGTH 2 +#define GTPV1_TV_PTMSI_SIGNATURE 12 +#define GTPV1_TV_PTMSI_SIGNATURE_LENGTH 4 +#define GTPV1_TV_MS_VALIDATED 13 +#define GTPV1_TV_MS_VALIDATED_LENGTH 2 +#define GTPV1_TV_RECOVERY 14 +#define GTPV1_TV_RECOVERY_LENGTH 2 +#define GTPV1_TV_SELECTION_MODE 15 +#define GTPV1_TV_SELECTION_MODE_LENGTH 2 +#define GTPV1_TV_TEID_DATA_I 16 +#define GTPV1_TV_TEID_DATA_I_LENGTH 5 +#define GTPV1_TV_TEID_CTRL 17 +#define GTPV1_TV_TEID_CTRL_LENGTH 5 +#define GTPV1_TV_TEID_DATA_II 18 +#define GTPV1_TV_TEID_DATA_II_LENGTH 6 +#define GTPV1_TV_TEARDOWN 19 +#define GTPV1_TV_TEARDOWN_LENGTH 2 +#define GTPV1_TV_NSAPI 20 +#define GTPV1_TV_NSAPI_LENGTH 2 +#define GTPV1_TV_RANAP 21 +#define GTPV1_TV_RANAP_LENGTH 2 +#define GTPV1_TV_RAB_CONTEXT 22 +#define GTPV1_TV_RAB_CONTEXT_LENGTH 10 +#define GTPV1_TV_RADIO_PRIORITY_SMS 23 +#define GTPV1_TV_RADIO_PRI_SMS_LENGTH 2 +#define GTPV1_TV_RADIO_PRIORITY 24 +#define GTPV1_TV_RADIO_PRI_LENGTH 2 +#define GTPV1_TV_PACKET_FLOW_ID 25 +#define GTPV1_TV_PACKET_FLOW_ID_LENGTH 3 +#define GTPV1_TV_CHARGING 26 +#define GTPV1_TV_CHARGING_LENGTH 3 +#define GTPV1_TV_TRACE_REFERENCE 27 +#define GTPV1_TV_TRACE_REFERENCE_LENGTH 3 +#define GTPV1_TV_TRACE_TYPE 28 +#define GTPV1_TV_TRACE_TYPE_LENGTH 3 +#define GTPV1_TV_MSNRR 29 +#define GTPV1_TV_MSNRR_LENGTH 2 +#define GTPV1_TV_PACKET_XFER_CMD 126 +#define GTPV1_TV_PACKET_XFER_CMD_LENGTH 2 +#define GTPV1_TV_CHARGING_ID 127 +#define GTPV1_TV_CHARGING_ID_LENGTH 5 + +#define GTPV1_TLV_END_USER_ADDRESS 128 +#define GTPV1_TLV_MM_CONTEXT 129 +#define GTPV1_TLV_PDP_CONTEXT 130 +#define GTPV1_TLV_ACCESS_POINT_NAME 131 +#define GTPV1_TLV_PROTOCOL_CONFIG_OPTIONS 132 +#define GTPV1_TLV_GSN_ADDRESS 133 +#define GTPV1_TLV_MSISDN 134 +#define GTPV1_TLV_QOS_PROFILE 135 +#define GTPV1_TLV_AUTHENTICATION 136 +#define GTPV1_TLV_TRAFFIC_FLOW 137 +#define GTPV1_TLV_TARGET_IDENTIFICATION 138 +#define GTPV1_TLV_UTRAN_CONTAINER 139 +#define GTPV1_TLV_RAB_SETUP_INFORMATION 140 +#define GTPV1_TLV_EXT_HEADER_TYPE_LIST 141 +#define GTPV1_TLV_TRIGGER_ID 142 +#define GTPV1_TLV_OMC_IDENTITY 143 +#define GTPV1_TLV_RAN_CONTAINER 144 +#define GTPV1_TLV_PDP_CONTEXT_PRIORITIZATION 145 +#define GTPV1_TLV_ADDITIONAL_RAB_SETUP_INFO 146 +#define GTPV1_TLV_SGSN_NUMBER 147 +#define GTPV1_TLV_COMMON_FLAGS 148 +#define GTPV1_TLV_APN_RESTRICTION 149 +#define GTPV1_TLV_RADIO_PRIORITY_LCS 150 +#define GTPV1_TLV_RAT_TYPE 151 +#define GTPV1_TLV_USER_LOCATION_INFO 152 +#define GTPV1_TLV_MS_TIME_ZONE 153 +#define GTPV1_TLV_IMEI_SV 154 +#define GTPV1_TLV_CAMEL_CHARGING_CONTAINER 155 +#define GTPV1_TLV_MBMS_UE_CONTEXT 156 +#define GTPV1_TLV_TMGI 157 +#define GTPV1_TLV_RIM_ROUTING_ADDRESS 158 +#define GTPV1_TLV_MBMS_PROTOCOL_CONFIG_OPTIONS 159 +#define GTPV1_TLV_MBMS_SERVICE_AREA 160 +#define GTPV1_TLV_SOURCE_RNC_PDCP_CONTEXT_INFO 161 +#define GTPV1_TLV_ADDITIONAL_TRACE_INFO 162 +#define GTPV1_TLV_HOP_COUNTER 163 +#define GTPV1_TLV_SELECTED_PLMN_ID 164 +#define GTPV1_TLV_MBMS_SESSION_IDENTIFIER 165 +#define GTPV1_TLV_MBMS_2G_3G_INDICATOR 166 +#define GTPV1_TLV_ENHANCED_NSAPI 167 +#define GTPV1_TLV_MBMS_SESSION_DURATION 168 +#define GTPV1_TLV_ADDITIONAL_MBMS_TRACE_INFO 169 +#define GTPV1_TLV_MBMS_SESSION_REPITITION_NO 170 +#define GTPV1_TLV_MBMS_TIME_TO_DATA_TRANSFER 171 +#define GTPV1_TLV_PS_HANDOVER_REQUEST_CONTEXT 172 +#define GTPV1_TLV_BSS_CONTAINER 173 +#define GTPV1_TLV_CELL_IDENTIFICATION 174 +#define GTPV1_TLV_PDU_NUMBERS 175 +#define GTPV1_TLV_BSSGP_CAUSE 176 +#define GTPV1_TLV_REQUIRED_MBMS_BEARER_CAP 177 +#define GTPV1_TLV_RIM_ROUTING_ADDRESS_DISC 178 +#define GTPV1_TLV_LIST_OF_SETUP_PFCS 179 +#define GTPV1_TLV_PS_HANDOVER_XID_PARAMETERS 180 +#define GTPV1_TLV_MS_INFO_CHANGE_REPORTING 181 +#define GTPV1_TLV_DIRECT_TUNNEL_FLAGS 182 +#define GTPV1_TLV_CORRELATION_ID 183 +#define GTPV1_TLV_BEARER_CONTROL_MODE 184 +#define GTPV1_TLV_MBMS_FLOW_IDENTIFIER 185 + +#define GTPV1_TLV_RELEASED_PACKETS 249 +#define GTPV1_TLV_CANCELLED_PACKETS 250 +#define GTPV1_TLV_CHARGING_GATEWAY_ADDRESS 251 +#define GTPV1_TLV_DATA_RECORD_PACKET 252 +#define GTPV1_TLV_REQUESTS_RESPONDED 253 +#define GTPV1_TLV_ADDRESS_OF_RECOMMENDED_NODE 254 + +#define GTPV1_TLV_PRIVATE_EXTENSION 255 + +struct gtp_v0_hdr { + u_int8_t flags; + u_int8_t msgtype; + u_int16_t length; + u_int16_t seqno; + u_int16_t flow; + u_int8_t npduno; + u_int8_t spare1; + u_int8_t spare2; + u_int8_t spare3; + u_int64_t tid; +} __packed; + +struct gtp_v0_prime_hdr { + u_int8_t flags; + u_int8_t msgtype; + u_int16_t length; + u_int16_t seqno; +} __packed; + +struct gtp_v1_hdr { + u_int8_t flags; + u_int8_t msgtype; + u_int16_t length; + u_int32_t teid; +} __packed; + +struct gtp_v1_hdr_ext { + struct gtp_v1_hdr gh; + u_int16_t seqno; + u_int8_t npduno; + u_int8_t nexthdr; +} __packed; + +struct gtp_v1_prime_hdr { + u_int8_t flags; + u_int8_t msgtype; + u_int16_t length; + u_int16_t seqno; +} __packed; + +static struct tok gtp_type[] = { + { 0, "GTPv0" }, + { 1, "GTPv0'" }, + { 2, "GTPv1-C" }, + { 3, "GTPv1-U" }, + { 4, "GTPv1'" } +}; + +static const char *gtp_rat_type[] = { + NULL, "UTRAN", "GERAN", "WLAN", "GAN", "HSPA Evolution" +}; + +static const char *gtp_packet_xfer_cmd[] = { + NULL, "Send Data Record", "Send Duplicated Record", + "Cancel Data Record", "Release Data Record" +}; + +static const char *mbms_2g3g_indicator[] = { + "2G Only", "3G Only", "2G and 3G" +}; + +static const char *ms_info_change_rpt[] = { + "Stop Reporting", "Start Reporting CGI/SAI", "Start Reporting RAI" +}; + +#endif diff --git a/usr.sbin/tcpdump/interface.h b/usr.sbin/tcpdump/interface.h index da7efdfdb50..c6aee4b2c65 100644 --- a/usr.sbin/tcpdump/interface.h +++ b/usr.sbin/tcpdump/interface.h @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.h,v 1.58 2009/02/14 11:18:56 sthen Exp $ */ +/* $OpenBSD: interface.h,v 1.59 2009/11/04 09:43:11 jsing Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -20,7 +20,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Id: interface.h,v 1.58 2009/02/14 11:18:56 sthen Exp $ (LBL) + * @(#) $Id: interface.h,v 1.59 2009/11/04 09:43:11 jsing Exp $ (LBL) */ #ifndef tcpdump_interface_h @@ -273,6 +273,7 @@ extern void ipcomp_print(const u_char *, u_int, const u_char *); extern void mpls_print(const u_char *, u_int); extern void lldp_print(const u_char *, u_int); extern void slow_print(const u_char *, u_int); +extern void gtp_print(const u_char *, u_int, u_short, u_short); #ifdef INET6 extern void ip6_print(const u_char *, int); diff --git a/usr.sbin/tcpdump/print-gtp.c b/usr.sbin/tcpdump/print-gtp.c new file mode 100644 index 00000000000..703e52c7339 --- /dev/null +++ b/usr.sbin/tcpdump/print-gtp.c @@ -0,0 +1,1800 @@ +/* $OpenBSD: print-gtp.c,v 1.1 2009/11/04 09:43:11 jsing Exp $ */ +/* + * Copyright (c) 2009 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Decoder for the GPRS Trunking Protocol (GTP). + * + * This work has been kindly sponsored by SystemNet (www.systemnet.no). + * + * GTPv0 standards are available from the ETSI website: + * + * http://pda.etsi.org/pda/ + * + * GTPv1 standards are available from the 3GPP website: + * + * http://www.3gpp.org/specifications + * + * The following standards have been referenced to create this decoder: + * + * ETSI GSM 09.60 - GPRS Tunnelling Protocol (GTPv0) + * ETSI GSM 12.15 - GPRS Charging (GTPv0') + * + * 3GPP TS 23.003 - Numbering, addressing and identification + * 3GPP TS 29.002 - Mobile Application Part (MAP) specification + * 3GPP TS 29.060 - GPRS Tunnelling Protocol (GTPv1-C/GTPv1-U) + * 3GPP TS 32.295 - Charging Data Record (CDR) transfer (GTPv1') + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "addrtoname.h" +#include "interface.h" +#include "gtp.h" + +void gtp_print(register const u_char *, u_int, u_short, u_short); +void gtp_decode_ie(register const u_char *, u_short, int); +void gtp_print_tbcd(register const u_char *, u_int); +void gtp_print_user_address(register const u_char *, u_int); +void gtp_print_str(const char **, u_int); + +void gtp_v0_print(const u_char *, u_int, u_short, u_short); +void gtp_v0_print_prime(register const u_char *); +int gtp_v0_print_tv(register const u_char *, u_int); +int gtp_v0_print_tlv(register const u_char *, u_int); + +void gtp_v1_print(const u_char *, u_int, u_short, u_short); +void gtp_v1_print_ctrl(register const u_char *, u_int, struct gtp_v1_hdr *); +void gtp_v1_print_user(register const u_char *, u_int, struct gtp_v1_hdr *); +void gtp_v1_print_prime(register const u_char *, struct gtp_v1_prime_hdr *); +int gtp_v1_print_tv(register const u_char *, u_int); +int gtp_v1_print_tlv(register const u_char *, u_int); + +/* GTPv0 message types. */ +static struct tok gtp_v0_msgtype[] = { + + { 1, "Echo Request" }, + { 2, "Echo Response" }, + { 3, "Version Not Supported" }, + { 4, "Node Alive Request" }, + { 5, "Node Alive Response" }, + { 6, "Redirection Request" }, + { 7, "Redirection Response" }, + { 16, "Create PDP Context Request" }, + { 17, "Create PDP Context Response" }, + { 18, "Update PDP Context Request" }, + { 19, "Update PDP Context Response" }, + { 20, "Delete PDP Context Request" }, + { 21, "Delete PDP Context Response" }, + { 22, "Create AA PDP Context Request" }, + { 23, "Create AA PDP Context Response" }, + { 24, "Delete AA PDP Context Request" }, + { 25, "Delete AA PDP Context Response" }, + { 26, "Error Indication" }, + { 27, "PDU Notification Request" }, + { 28, "PDU Notification Response" }, + { 29, "PDU Notification Reject Request" }, + { 30, "PDU Notification Reject Response" }, + { 32, "Send Routeing Information Request" }, + { 33, "Send Routeing Information Response" }, + { 34, "Failure Report Request" }, + { 35, "Failure Report Response" }, + { 36, "MS GPRS Present Request" }, + { 37, "MS GPRS Present Response" }, + { 48, "Identification Request" }, + { 49, "Identification Response" }, + { 50, "SGSN Context Request" }, + { 51, "SGSN Context Response" }, + { 52, "SGSN Context Acknowledge" }, + { 240, "Data Record Transfer Request" }, + { 241, "Data Record Transfer Response" }, + { 255, "T-PDU" }, + + { 0, NULL } +}; + +/* GTPv0 causes. */ +static struct tok gtp_v0_cause[] = { + + { 0, "Request IMSI" }, + { 1, "Request IMEI" }, + { 2, "Request IMSI and IMEI" }, + { 3, "No identity needed" }, + { 4, "MS refuses" }, + { 5, "MS is not GPRS responding" }, + { 128, "Request accepted" }, + { 192, "Non-existent" }, + { 193, "Invalid message format" }, + { 194, "IMSI not known" }, + { 195, "MS is GPRS detached" }, + { 196, "MS is not GPRS responding" }, + { 197, "MS refuses" }, + { 198, "Version not supported" }, + { 199, "No resources available" }, + { 200, "Service not supported" }, + { 201, "Mandatory IE incorrect" }, + { 202, "Mandatory IE missing" }, + { 203, "Optional IE incorrect" }, + { 204, "System failure" }, + { 205, "Roaming restriction" }, + { 206, "P-TMSI signature mismatch" }, + { 207, "GPRS connection suspended" }, + { 208, "Authentication failure" }, + { 209, "User authentication failed" }, + + { 0, NULL } +}; + +/* GTPv1 message types. */ +static struct tok gtp_v1_msgtype[] = { + + { 1, "Echo Request" }, + { 2, "Echo Response" }, + { 3, "Version Not Supported" }, + { 4, "Node Alive Request" }, + { 5, "Node Alive Response" }, + { 6, "Redirection Request" }, + { 7, "Redirection Response" }, + { 16, "Create PDP Context Request" }, + { 17, "Create PDP Context Response" }, + { 18, "Update PDP Context Request" }, + { 19, "Update PDP Context Response" }, + { 20, "Delete PDP Context Request" }, + { 21, "Delete PDP Context Response" }, + { 22, "Initiate PDP Context Activiation Request" }, + { 23, "Initiate PDP Context Activiation Response" }, + { 26, "Error Indication" }, + { 27, "PDU Notification Request" }, + { 28, "PDU Notification Response" }, + { 29, "PDU Notification Reject Request" }, + { 30, "PDU Notification Reject Response" }, + { 31, "Supported Extension Headers Notification" }, + { 32, "Send Routeing Information for GPRS Request" }, + { 33, "Send Routeing Information for GPRS Response" }, + { 34, "Failure Report Request" }, + { 35, "Failure Report Response" }, + { 36, "Note MS GPRS Present Request" }, + { 37, "Note MS GPRS Present Response" }, + { 48, "Identification Request" }, + { 49, "Identification Response" }, + { 50, "SGSN Context Request" }, + { 51, "SGSN Context Response" }, + { 52, "SGSN Context Acknowledge" }, + { 53, "Forward Relocation Request" }, + { 54, "Forward Relocation Response" }, + { 55, "Forward Relocation Complete" }, + { 56, "Relocation Cancel Request" }, + { 57, "Relocation Cancel Response" }, + { 58, "Forward SRNS Context" }, + { 59, "Forward Relocation Complete Acknowledge" }, + { 60, "Forward SRNS Context Acknowledge" }, + { 70, "RAN Information Relay" }, + { 96, "MBMS Notification Request" }, + { 97, "MBMS Notification Response" }, + { 98, "MBMS Notification Reject Request" }, + { 99, "MBMS Notification Reject Response" }, + { 100, "Create MBMS Context Request" }, + { 101, "Create MBMS Context Response" }, + { 102, "Update MBMS Context Request" }, + { 103, "Update MBMS Context Response" }, + { 104, "Delete MBMS Context Request" }, + { 105, "Delete MBMS Context Response" }, + { 112, "MBMS Registration Request" }, + { 113, "MBMS Registration Response" }, + { 114, "MBMS De-Registration Request" }, + { 115, "MBMS De-Registration Response" }, + { 116, "MBMS Session Start Request" }, + { 117, "MBMS Session Start Response" }, + { 118, "MBMS Session Stop Request" }, + { 119, "MBMS Session Stop Response" }, + { 120, "MBMS Session Update Request" }, + { 121, "MBMS Session Update Response" }, + { 128, "MBMS Info Change Notification Request" }, + { 129, "MBMS Info Change Notification Response" }, + { 240, "Data Record Transfer Request" }, + { 241, "Data Record Transfer Response" }, + { 255, "G-PDU" }, + + { 0, NULL } +}; + +/* GTPv1 Causes. */ +static struct tok gtp_v1_cause[] = { + + /* GTPv1-C. */ + { 0, "Request IMSI" }, + { 1, "Request IMEI" }, + { 2, "Request IMSI and IMEI" }, + { 3, "No identity needed" }, + { 4, "MS refuses" }, + { 5, "MS is not GPRS responding" }, + { 128, "Request accepted" }, + { 192, "Non-existent" }, + { 193, "Invalid message format" }, + { 194, "IMSI not known" }, + { 195, "MS is GPRS detached" }, + { 196, "MS is not GPRS responding" }, + { 197, "MS refuses" }, + { 198, "Version not supported" }, + { 199, "No resources available" }, + { 200, "Service not supported" }, + { 201, "Mandatory IE incorrect" }, + { 202, "Mandatory IE missing" }, + { 203, "Optional IE incorrect" }, + { 204, "System failure" }, + { 205, "Roaming restriction" }, + { 206, "P-TMSI signature mismatch" }, + { 207, "GPRS connection suspended" }, + { 208, "Authentication failure" }, + { 209, "User authentication failed" }, + { 210, "Context not found" }, + { 211, "All dynamic PDP addresses are occupied" }, + { 212, "No memory is available" }, + { 213, "Relocation failure" }, + { 214, "Unknown mandatory extension header" }, + { 215, "Semantic error in the TFT operation" }, + { 216, "Syntactic error in the TFT operation" }, + { 217, "Semantic errors in packet filter(s)" }, + { 218, "Syntactic errors in packet filter(s)" }, + { 219, "Missing or unknown APN" }, + { 220, "Unknown PDP address or PDP type" }, + { 221, "PDP context without TFT already activated" }, + { 222, "APN access denied - no subscription" }, + { 223, "APN restriction type incompatibility with currently " + "active PDP contexts" }, + { 224, "MS MBMS capabilities insufficient" }, + { 225, "Invalid correlation-ID" }, + { 226, "MBMS bearer context superseded" }, + + /* GTP'v1. */ + { 59, "System failure" }, + { 60, "The transmit buffers are becoming full" }, + { 61, "The receive buffers are becoming full" }, + { 62, "Another node is about to go down" }, + { 63, "This node is about to go down" }, + { 177, "CDR decoding error" }, + { 252, "Request related to possibly duplicated packets already " + "fulfilled" }, + { 253, "Request already fulfilled" }, + { 254, "Sequence numbers of released/cancelled packets IE incorrect" }, + { 255, "Request not fulfilled" }, + + { 0, NULL } +}; + +static int gtp_proto = -1; + +void +gtp_print(register const u_char *cp, u_int length, u_short sport, u_short dport) +{ + int version; + + /* Decode GTP version. */ + TCHECK(cp[0]); + version = cp[0] >> GTP_VERSION_SHIFT; + + if (version == GTP_VERSION_0) + gtp_v0_print(cp, length, sport, dport); + else if (version == GTP_VERSION_1) + gtp_v1_print(cp, length, sport, dport); + else + printf(" GTP (version %i)", version); + + return; + +trunc: + printf(" [|GTP]"); +} + +/* + * Decode and print information elements from message. The actual work is + * handled in the appropriate Tag/Value (TV) or Tag/Length/Value (TLV) + * decoding routine. + */ +void +gtp_decode_ie(register const u_char *cp, u_short version, int len) +{ + int val, ielen, iecount = 0; + + if (len <= 0) + return; + + printf(" {"); + + while (len > 0) { + + iecount++; + if (iecount > 1) + printf(" "); + + TCHECK(cp[0]); + val = (u_int)cp[0]; + cp++; + + printf("["); + + switch (version) { + case GTP_VERSION_0: + if ((val & GTPV0_IE_TYPE_MASK) == 0) + ielen = gtp_v0_print_tv(cp, val); + else + ielen = gtp_v0_print_tlv(cp, val); + break; + + case GTP_VERSION_1: + if ((val & GTPV1_IE_TYPE_MASK) == 0) + ielen = gtp_v1_print_tv(cp, val); + else + ielen = gtp_v1_print_tlv(cp, val); + break; + + default: + /* Version not supported... */ + ielen = -1; + break; + } + + printf("]"); + + if (ielen < 0) + goto trunc; + + len -= ielen; + cp += ielen - 1; + } + + if (iecount > 0) + printf("}"); + + return; + +trunc: + printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); +} + +/* + * Decode and print telephony binary coded decimal. + */ +void +gtp_print_tbcd(register const u_char *cp, u_int len) +{ + u_int8_t *data, bcd; + int i; + + data = (u_int8_t *)cp; + for (i = 0; i < len; i++) { + bcd = *data & 0xf; + if (bcd != 0xf) + printf("%u", bcd); + bcd = *data >> 4; + if (bcd != 0xf) + printf("%u", bcd); + data++; + } +} + +/* + * Decode and print an end user address. Format is detailed in + * GSM 09.60 section 7.9.18 and 3GPP 29.060 section 7.7.27. + */ +void +gtp_print_user_address(register const u_char *cp, u_int len) +{ + u_int8_t org, type; + + if (len < 2) + return; + + org = (u_int8_t)cp[0] & 0xf; + type = (u_int8_t)cp[1]; + + cp += 2; + + if (org == 0x0 && type == 0x1) + printf(": PPP"); + else if (org == 0x1 && type == 0x21) { + if (len == 6) + printf(": %s", ipaddr_string(cp)); + else + printf(": IPv4"); +#ifdef INET6 + } else if (org == 0x1 && type == 0x57) { + if (len == 18) + printf(": %s", ip6addr_string(cp)); + else + printf(": IPv6"); +#endif + } else + printf(" (org 0x%x, type 0x%x)", org, type); +} + +/* Print string from array. */ +void +gtp_print_str(const char **strs, u_int index) +{ + + if (index >= (sizeof(*strs) / sizeof(*strs[0]))) + printf(": %u", index); + else if (strs[index] != NULL) + printf(": %s", strs[index]); +} + +/* + * Decoding routines for GTP version 0. + */ +void +gtp_v0_print(const u_char *cp, u_int length, u_short sport, u_short dport) +{ + struct gtp_v0_hdr *gh = (struct gtp_v0_hdr *)cp; + int len, version; + + gtp_proto = GTP_V0_PROTO; + + /* Check if this is GTP prime. */ + TCHECK(gh->flags); + if ((gh->flags & GTPV0_HDR_PROTO_TYPE) == 0) { + gtp_proto = GTP_V0_PRIME_PROTO; + gtp_v0_print_prime(cp); + return; + } + + /* Print GTP header. */ + TCHECK(*gh); + cp += sizeof(struct gtp_v0_hdr); + len = ntohs(gh->length); + printf(" GTPv0 (len %u, seqno %u, flow %u, N-PDU %u, tid 0x%llx) ", + ntohs(gh->length), ntohs(gh->seqno), ntohs(gh->flow), + ntohs(gh->npduno), betoh64(gh->tid)); + + /* Decode GTP message. */ + printf("%s", tok2str(gtp_v0_msgtype, "Message Type %u", gh->msgtype)); + + if (!vflag) + return; + + if (gh->msgtype == GTPV0_T_PDU) { + + TCHECK(cp[0]); + version = cp[0] >> 4; + + printf(" { "); + + if (version == 4) + ip_print(cp, len); +#ifdef INET6 + else if (version == 6) + ip6_print(cp, len); +#endif + else + printf("Unknown IP version %u", version); + + printf(" }"); + } else + gtp_decode_ie(cp, GTP_VERSION_0, len); + + return; + +trunc: + printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); +} + +void +gtp_v0_print_prime(register const u_char *cp) +{ + struct gtp_v0_prime_hdr *gph = (struct gtp_v0_prime_hdr *)cp; + int len; + + /* Decode GTP prime header. */ + TCHECK(*gph); + cp += sizeof(*gph); + + len = ntohs(gph->length); + printf(" GTPv0' (len %u, seq %u) ", len, ntohs(gph->seqno)); + + /* Decode GTP message. */ + printf("%s", tok2str(gtp_v0_msgtype, "Message Type %u", gph->msgtype)); + + if (vflag) + gtp_decode_ie(cp, GTP_VERSION_0, len); + + return; + +trunc: + printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); +} + +int +gtp_v0_print_tv(register const u_char *cp, u_int value) +{ + u_int32_t *dpl; + u_int16_t *dps; + u_int8_t data; + int ielen = -1; + + switch (value) { + case GTPV0_TV_CAUSE: + + /* 09.60 7.9.1 - Cause. */ + TCHECK(cp[0]); + data = (u_int8_t)cp[0]; + ielen = GTPV0_TV_CAUSE_LENGTH; + printf("Cause: %s", tok2str(gtp_v0_cause, "#%u", data)); + break; + + case GTPV0_TV_IMSI: + + /* 09.60 7.9.2 - International Mobile Subscriber Identity. */ + TCHECK2(cp[0], GTPV0_TV_IMSI_LENGTH - 1); + printf("IMSI "); + gtp_print_tbcd(cp, GTPV0_TV_IMSI_LENGTH - 1); + ielen = GTPV0_TV_IMSI_LENGTH; + break; + + case GTPV0_TV_RAI: + + /* 09.60 7.9.3 - Routing Area Identity (RAI). */ + TCHECK2(cp[0], GTPV0_TV_RAI_LENGTH - 1); + printf("RAI: MCC "); + data = cp[1] | 0xf0; + gtp_print_tbcd(cp, 1); + gtp_print_tbcd(&data, 1); + printf(", MNC "); + data = (cp[1] >> 4) | 0xf0; + gtp_print_tbcd(cp + 2, 1); + gtp_print_tbcd(&data, 1); + printf(", LAC 0x%x%x", cp[3], cp[4]); + printf(", RAC 0x%x", cp[5]); + ielen = GTPV0_TV_RAI_LENGTH; + break; + + case GTPV0_TV_TLLI: + + /* 09.60 7.9.4 - Temporary Logical Link Identity (TLLI). */ + TCHECK2(cp[0], GTPV0_TV_TLLI_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("TLLI 0x%x", ntohl(*dpl)); + ielen = GTPV0_TV_TLLI_LENGTH; + break; + + case GTPV0_TV_PTMSI: + + /* 09.60 7.9.5 - Packet TMSI (P-TMSI). */ + TCHECK2(cp[0], GTPV0_TV_PTMSI_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("P-TMSI 0x%x", ntohl(*dpl)); + ielen = GTPV0_TV_PTMSI_LENGTH; + break; + + case GTPV0_TV_QOS: + + /* 09.60 7.9.6 - Quality of Service (QoS) Profile. */ + TCHECK2(cp[0], GTPV0_TV_QOS_LENGTH - 1); + printf("QoS Profile"); /* XXX */ + ielen = GTPV0_TV_QOS_LENGTH; + break; + + case GTPV0_TV_REORDER: + + /* 09.60 7.9.7 - Reordering Required. */ + TCHECK2(cp[0], GTPV0_TV_REORDER_LENGTH - 1); + printf("Reordering Required: "); + if (cp[0] & 0x1) + printf("yes"); + else + printf("no"); + ielen = GTPV0_TV_REORDER_LENGTH; + break; + + case GTPV0_TV_AUTH_TRIPLET: + + /* 09.60 7.9.8 - Authentication Triplet. */ + TCHECK2(cp[0], GTPV0_TV_AUTH_TRIPLET_LENGTH - 1); + printf("Authentication"); /* XXX */ + ielen = GTPV0_TV_AUTH_TRIPLET_LENGTH; + break; + + case GTPV0_TV_MAP_CAUSE: + + /* 09.60 7.9.9 - MAP Cause. */ + TCHECK2(cp[0], GTPV0_TV_MAP_CAUSE_LENGTH - 1); + printf("MAP Cause: %u", cp[0]); + ielen = GTPV0_TV_MAP_CAUSE_LENGTH; + break; + + case GTPV0_TV_PTMSI_SIGNATURE: + + /* 09.60 7.9.10 - P-TMSI Signature. */ + /* Signature defined in GSM 04.08. */ + TCHECK2(cp[0], GTPV0_TV_PTMSI_SIGNATURE_LENGTH - 1); + printf("PTMSI Signature: 0x%x%x%x", cp[0], cp[1], cp[2]); + ielen = GTPV0_TV_PTMSI_SIGNATURE_LENGTH; + break; + + case GTPV0_TV_MS_VALIDATED: + + /* 09.60 7.9.11 - MS Validated. */ + TCHECK2(cp[0], GTPV0_TV_MS_VALIDATED_LENGTH - 1); + printf("MS Validated"); + if (cp[0] & 0x1) + printf("yes"); + else + printf("no"); + ielen = GTPV0_TV_MS_VALIDATED_LENGTH; + break; + + case GTPV0_TV_RECOVERY: + + /* 09.60 7.9.12 - Recovery. */ + TCHECK2(cp[0], GTPV0_TV_RECOVERY_LENGTH - 1); + printf("Recovery: Restart counter %u", cp[0]); + ielen = GTPV0_TV_RECOVERY_LENGTH; + break; + + case GTPV0_TV_SELECTION_MODE: + + /* 09.60 7.9.13 - Selection Mode. */ + TCHECK2(cp[0], GTPV0_TV_SELECTION_MODE_LENGTH - 1); + printf("Selection Mode"); /* XXX */ + ielen = GTPV0_TV_SELECTION_MODE_LENGTH; + break; + + case GTPV0_TV_FLOW_LABEL_DATA_I: + + /* 09.60 7.9.14 - Flow Label Data I. */ + TCHECK2(cp[0], GTPV0_TV_FLOW_LABEL_DATA_I_LENGTH - 1); + dps = (u_int16_t *)cp; + printf("Flow Label Data I: %u", ntohs(*dps)); + ielen = GTPV0_TV_FLOW_LABEL_DATA_I_LENGTH; + break; + + case GTPV0_TV_FLOW_LABEL_SIGNALLING: + + /* 09.60 7.9.15 - Flow Label Signalling. */ + TCHECK2(cp[0], GTPV0_TV_FLOW_LABEL_SIGNALLING_LENGTH - 1); + dps = (u_int16_t *)cp; + printf("Flow Label Signalling: %u", ntohs(*dps)); + ielen = GTPV0_TV_FLOW_LABEL_SIGNALLING_LENGTH; + break; + + case GTPV0_TV_FLOW_LABEL_DATA_II: + + /* 09.60 7.9.16 - Flow Label Data II. */ + TCHECK2(cp[0], GTPV0_TV_FLOW_LABEL_DATA_II_LENGTH - 1); + data = cp[0] & 0xf; + dps = (u_int16_t *)(cp + 1); + printf("Flow Label Data II: %u, NSAPI %u", ntohs(*dps), data); + ielen = GTPV0_TV_FLOW_LABEL_DATA_II_LENGTH; + break; + + case GTPV0_TV_PACKET_XFER_CMD: + + /* 12.15 7.3.4.5.3 - Packet Transfer Command. */ + TCHECK2(cp[0], GTPV0_TV_PACKET_XFER_CMD_LENGTH - 1); + printf("Packet Transfer Command"); + gtp_print_str(gtp_packet_xfer_cmd, cp[0]); + ielen = GTPV0_TV_PACKET_XFER_CMD_LENGTH; + break; + + case GTPV0_TV_CHARGING_ID: + + /* 09.60 7.9.17 - Charging ID. */ + TCHECK2(cp[0], GTPV0_TV_CHARGING_ID_LENGTH - 1); + dps = (u_int16_t *)cp; + printf("Charging ID: %u", ntohs(*dps)); + ielen = GTPV0_TV_CHARGING_ID_LENGTH; + break; + + default: + printf("TV %u", value); + } + +trunc: + return ielen; +} + +int +gtp_v0_print_tlv(register const u_char *cp, u_int value) +{ + u_int8_t data; + u_int16_t *lenp, *seqno, len; + u_char *buf; + int ielen = -1; + + /* Get length of IE. */ + TCHECK2(cp[0], 2); + lenp = (u_int16_t *)cp; + cp += 2; + len = ntohs(*lenp); + TCHECK2(cp[0], len); + ielen = sizeof(data) + sizeof(len) + len; + + switch (value) { + + case GTPV0_TLV_END_USER_ADDRESS: + + /* 09.60 7.9.18 - End User Address. */ + printf("End User Address"); + gtp_print_user_address(cp, len); + break; + + case GTPV0_TLV_MM_CONTEXT: + + /* 09.60 7.9.19 - MM Context. */ + printf("MM Context"); /* XXX */ + break; + + case GTPV0_TLV_PDP_CONTEXT: + + /* 09.60 7.9.20 - PDP Context. */ + printf("PDP Context"); /* XXX */ + break; + + case GTPV0_TLV_ACCESS_POINT_NAME: + + /* 09.60 7.9.21 - Access Point Name. */ + printf("AP Name:"); + len = (u_int8_t)cp[0]; + if ((buf = malloc(len + 1)) != NULL) { + bcopy(cp + 1, buf, len); + buf[len] = '\0'; + printf(": %s", buf); + free(buf); + } + break; + + case GTPV0_TLV_PROTOCOL_CONFIG_OPTIONS: + + /* 09.60 7.9.22 - Protocol Configuration Options. */ + printf("Protocol Configuration Options"); /* XXX */ + break; + + case GTPV0_TLV_GSN_ADDRESS: + + /* 09.60 7.9.23 - GSN Address. */ + printf("GSN Address"); + if (len == 4) + printf(": %s", ipaddr_string(cp)); +#ifdef INET6 + else if (len == 16) + printf(": %s", ip6addr_string(cp)); +#endif + break; + + case GTPV0_TLV_MS_ISDN: + + /* 09.60 7.9.24 - MS International PSTN/ISDN Number. */ + printf("MSISDN "); + data = (u_int8_t)cp[0]; /* XXX - Number type. */ + gtp_print_tbcd(cp + 1, len - 1); + break; + + case GTPV0_TLV_CHARGING_GATEWAY_ADDRESS: + + /* 09.60 7.9.25 - Charging Gateway Address. */ + printf("Charging Gateway"); + if (len == 4) + printf(": %s", ipaddr_string(cp)); + break; + + case GTPV0_TLV_DATA_RECORD_PACKET: + + /* 12.15 7.3.4.5.4 - Data Record Packet. */ + printf("Data Record: Records %u, Format %u, Format Version %u", + cp[0], cp[1], ntohs(*(u_int16_t *)(cp + 2))); + break; + + case GTPV0_TLV_REQUESTS_RESPONDED: + + /* 12.15 7.3.4.6 - Requests Responded. */ + printf("Requests Responded:"); + seqno = (u_int16_t *)cp; + while (len > 0) { + printf(" %u", ntohs(*seqno)); + seqno++; + len -= sizeof(*seqno); + } + break; + + case GTPV0_TLV_RECOMMENDED_NODE: + + /* 12.15 7.3.4.3 - Address of Recommended Node. */ + printf("Recommended Node"); + if (len == 4) + printf(": %s", ipaddr_string(cp)); +#ifdef INET6 + else if (len == 16) + printf(": %s", ip6addr_string(cp)); +#endif + break; + + case GTPV0_TLV_PRIVATE_EXTENSION: + + printf("Private Extension"); + break; + + default: + printf("TLV %u (len %u)", value, len); + } + + return ielen; + +trunc: + return -1; +} + +/* + * Decoding for GTP version 1, which consists of GTPv1-C, GTPv1-U and GTPv1'. + */ +void +gtp_v1_print(const u_char *cp, u_int length, u_short sport, u_short dport) +{ + struct gtp_v1_hdr *gh = (struct gtp_v1_hdr *)cp; + struct gtp_v1_hdr_ext *ghe = 0; + int nexthdr, hlen; + u_char *p = (u_char *)cp; + + TCHECK(gh->flags); + if ((gh->flags && GTPV1_HDR_PROTO_TYPE) == 0) { + printf(" GTPv1'"); + gtp_proto = GTP_V1_PRIME_PROTO; + gtp_v1_print_prime(p, (struct gtp_v1_prime_hdr *)gh); + return; + } + + if (dport == GTPV1_C_PORT || sport == GTPV1_C_PORT) { + gtp_proto = GTP_V1_CTRL_PROTO; + printf(" GTPv1-C"); + } else if (dport == GTPV1_U_PORT || sport == GTPV1_U_PORT) { + gtp_proto = GTP_V1_USER_PROTO; + printf(" GTPv1-U"); + } else if (dport == GTPV1_PRIME_PORT || sport == GTPV1_PRIME_PORT) { + gtp_proto = GTP_V1_PRIME_PROTO; + printf(" GTPv1'"); + } + + /* Decode GTP header. */ + TCHECK(*gh); + p += sizeof(struct gtp_v1_hdr); + + printf(" (teid %u, len %u)", ntohl(gh->teid), ntohs(gh->length)); + + if (gh->flags & GTPV1_HDR_EXT) { + ghe = (struct gtp_v1_hdr_ext *)cp; + TCHECK(*ghe); + p += sizeof(struct gtp_v1_hdr_ext) - sizeof(struct gtp_v1_hdr); + } + + if (gh->flags & GTPV1_HDR_SN_FLAG) + printf(" [seq %u]", ntohs(ghe->seqno)); + + if (gh->flags & GTPV1_HDR_NPDU_FLAG) + printf(" [N-PDU %u]", ghe->npduno); + + if (gh->flags & GTPV1_HDR_EH_FLAG) { + + /* Process next header... */ + nexthdr = ghe->nexthdr; + while (nexthdr != GTPV1_EH_NONE) { + + /* Header length is a 4 octet multiplier. */ + hlen = (int)p[0] * 4; + TCHECK2(p[0], hlen); + + switch (nexthdr) { + case GTPV1_EH_MBMS_SUPPORT: + printf(" [MBMS Support]"); + break; + + case GTPV1_EH_MSI_CHANGE_RPT: + printf(" [MS Info Change Reporting]"); + break; + + case GTPV1_EH_PDCP_PDU_NO: + printf(" [PDCP PDU %u]", + ntohs(*(u_int16_t *)(p + 1))); + break; + + case GTPV1_EH_SUSPEND_REQUEST: + printf(" [Suspend Request]"); + break; + + case GTPV1_EH_SUSPEND_RESPONSE: + printf(" [Suspend Response]"); + break; + + default: + printf(" [Unknown Header %u]", nexthdr); + } + + p += hlen - 1; + nexthdr = (int)p[0]; + p++; + } + + } + + hlen = p - cp; + + if (dport == GTPV1_C_PORT || sport == GTPV1_C_PORT) + gtp_v1_print_ctrl(p, hlen, gh); + else if (dport == GTPV1_U_PORT || sport == GTPV1_U_PORT) + gtp_v1_print_user(p, hlen, gh); + + return; + +trunc: + printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); +} + +void +gtp_v1_print_ctrl(register const u_char *cp, u_int hlen, struct gtp_v1_hdr *gh) +{ + int len; + + /* Decode GTP control message. */ + printf(" %s", tok2str(gtp_v1_msgtype, "Message Type %u", gh->msgtype)); + + len = ntohs(gh->length) - hlen + sizeof(*gh); + if (vflag) + gtp_decode_ie(cp, GTP_VERSION_1, len); +} + +void +gtp_v1_print_user(register const u_char *cp, u_int hlen, struct gtp_v1_hdr *gh) +{ + int len, version; + + /* Decode GTP user message. */ + printf(" %s", tok2str(gtp_v1_msgtype, "Message Type %u", gh->msgtype)); + + if (!vflag) + return; + + len = ntohs(gh->length) - hlen + sizeof(*gh); + + if (gh->msgtype == GTPV1_G_PDU) { + + TCHECK(cp[0]); + version = cp[0] >> 4; + + printf(" { "); + + if (version == 4) + ip_print(cp, len); +#ifdef INET6 + else if (version == 6) + ip6_print(cp, len); +#endif + else + printf("Unknown IP version %u", version); + + printf(" }"); + + } else + gtp_decode_ie(cp, GTP_VERSION_1, len); + + return; + +trunc: + printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); +} + +void +gtp_v1_print_prime(register const u_char *cp, struct gtp_v1_prime_hdr *gph) +{ + int len; + + /* Decode GTP prime header. */ + TCHECK(*gph); + cp += sizeof(struct gtp_v1_prime_hdr); + + len = ntohs(gph->length); + printf(" (len %u, seq %u) ", len, ntohs(gph->seqno)); + + /* Decode GTP message. */ + printf("%s", tok2str(gtp_v1_msgtype, "Message Type %u", gph->msgtype)); + + if (vflag) + gtp_decode_ie(cp, GTP_VERSION_1, len); + + return; + +trunc: + printf(" [|%s]", tok2str(gtp_type, "GTP", gtp_proto)); +} + +int +gtp_v1_print_tv(register const u_char *cp, u_int value) +{ + u_int32_t *dpl; + u_int16_t *dps; + u_int8_t data; + int ielen = -1; + + switch (value) { + case GTPV1_TV_CAUSE: + + /* 29.060 - 7.7.1 Cause. */ + TCHECK(cp[0]); + data = (u_int8_t)cp[0]; + ielen = GTPV1_TV_CAUSE_LENGTH; + printf("Cause: %s", tok2str(gtp_v1_cause, "#%u", data)); + break; + + case GTPV1_TV_IMSI: + + /* 29.060 7.7.2 - International Mobile Subscriber Identity. */ + TCHECK2(cp[0], GTPV1_TV_IMSI_LENGTH - 1); + printf("IMSI "); + gtp_print_tbcd(cp, GTPV1_TV_IMSI_LENGTH - 1); + ielen = GTPV1_TV_IMSI_LENGTH; + break; + + case GTPV1_TV_RAI: + + /* 29.060 7.7.3 - Routing Area Identity (RAI). */ + TCHECK2(cp[0], GTPV1_TV_RAI_LENGTH - 1); + printf("RAI: MCC "); + data = cp[1] | 0xf0; + gtp_print_tbcd(cp, 1); + gtp_print_tbcd(&data, 1); + printf(", MNC "); + data = (cp[1] >> 4) | 0xf0; + gtp_print_tbcd(cp + 2, 1); + gtp_print_tbcd(&data, 1); + printf(", LAC 0x%x%x", cp[3], cp[4]); + printf(", RAC 0x%x", cp[5]); + ielen = GTPV1_TV_RAI_LENGTH; + break; + + case GTPV1_TV_TLLI: + + /* 29.060 7.7.4 - Temporary Logical Link Identity (TLLI). */ + TCHECK2(cp[0], GTPV1_TV_TLLI_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("TLLI 0x%x", ntohl(*dpl)); + ielen = GTPV1_TV_TLLI_LENGTH; + break; + + case GTPV1_TV_PTMSI: + + /* 29.060 7.7.5 - Packet TMSI (P-TMSI). */ + TCHECK2(cp[0], GTPV1_TV_PTMSI_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("P-TMSI 0x%x", ntohl(*dpl)); + ielen = GTPV1_TV_PTMSI_LENGTH; + break; + + case GTPV1_TV_REORDER: + + /* 29.060 7.7.6 - Reordering Required. */ + TCHECK2(cp[0], GTPV1_TV_REORDER_LENGTH - 1); + printf("Reordering Required: "); + if (cp[0] & 0x1) + printf("yes"); + else + printf("no"); + ielen = GTPV1_TV_REORDER_LENGTH; + break; + + case GTPV1_TV_AUTH: + + /* 29.060 7.7.7 - Authentication Triplet. */ + TCHECK2(cp[0], GTPV1_TV_AUTH_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("Auth: RAND 0x%x%x%x%x, SRES 0x%x, Kc 0x%x%x", + ntohl(dpl[0]), ntohl(dpl[1]), ntohl(dpl[2]), ntohl(dpl[3]), + ntohl(dpl[4]), ntohl(dpl[5]), ntohl(dpl[6])); + ielen = GTPV1_TV_AUTH_LENGTH; + break; + + case GTPV1_TV_MAP_CAUSE: + + /* 29.060 7.7.8 - MAP Cause. */ + /* Cause defined in 3GPP TS 29.002. */ + TCHECK2(cp[0], GTPV1_TV_MAP_CAUSE_LENGTH - 1); + printf("Map Cause: %u", cp[0]); + ielen = GTPV1_TV_MAP_CAUSE_LENGTH; + break; + + case GTPV1_TV_PTMSI_SIGNATURE: + + /* 29.060 7.7.9 - P-TMSI Signature. */ + /* Signature defined in 3GPP TS 24.008. */ + TCHECK2(cp[0], GTPV1_TV_PTMSI_SIGNATURE_LENGTH - 1); + printf("PTMSI Signature: 0x%x%x%x", cp[0], cp[1], cp[2]); + ielen = GTPV1_TV_PTMSI_SIGNATURE_LENGTH; + break; + + case GTPV1_TV_MS_VALIDATED: + + /* 29.060 7.7.10 - MS Validated. */ + TCHECK2(cp[0], GTPV1_TV_MS_VALIDATED_LENGTH - 1); + printf("MS Validated: "); + if (cp[0] & 0x1) + printf("yes"); + else + printf("no"); + ielen = GTPV1_TV_MS_VALIDATED_LENGTH; + break; + + case GTPV1_TV_RECOVERY: + + /* 29.060 7.7.11 - Recovery. */ + TCHECK2(cp[0], GTPV1_TV_RECOVERY_LENGTH - 1); + printf("Recovery: Restart counter %u", cp[0]); + ielen = GTPV1_TV_RECOVERY_LENGTH; + break; + + case GTPV1_TV_SELECTION_MODE: + + /* 29.060 7.7.12 - Selection Mode. */ + TCHECK2(cp[0], GTPV1_TV_SELECTION_MODE_LENGTH - 1); + data = (u_int8_t)cp[0]; + printf("Selection Mode: %u", data & 0x2); + ielen = GTPV1_TV_SELECTION_MODE_LENGTH; + break; + + case GTPV1_TV_TEID_DATA_I: + + /* 29.060 7.7.13 - Tunnel Endpoint Identifier Data I. */ + TCHECK2(cp[0], GTPV1_TV_TEID_DATA_I_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("TEI Data I: %u", ntohl(*dpl)); + ielen = GTPV1_TV_TEID_DATA_I_LENGTH; + break; + + case GTPV1_TV_TEID_CTRL: + + /* 29.060 7.7.14 - Tunnel Endpoint Identifier Control Plane. */ + TCHECK2(cp[0], GTPV1_TV_TEID_CTRL_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("TEI Control Plane: %u", ntohl(*dpl)); + ielen = GTPV1_TV_TEID_CTRL_LENGTH; + break; + + case GTPV1_TV_TEID_DATA_II: + + /* 29.060 7.7.15 - Tunnel Endpoint Identifier Data II. */ + TCHECK2(cp[0], GTPV1_TV_TEID_DATA_II_LENGTH - 1); + data = cp[0] & 0xf; + dpl = (u_int32_t *)(cp + 1); + printf("TEI Data II: %u, NSAPI %u", ntohl(*dpl), data); + ielen = GTPV1_TV_TEID_DATA_II_LENGTH; + break; + + case GTPV1_TV_TEARDOWN: + + /* 29.060 7.7.16 - Teardown Indicator. */ + TCHECK2(cp[0], GTPV1_TV_TEARDOWN_LENGTH - 1); + printf("Teardown: "); + if (cp[0] & 0x1) + printf("yes"); + else + printf("no"); + ielen = GTPV1_TV_TEARDOWN_LENGTH; + break; + + case GTPV1_TV_NSAPI: + + /* 29.060 7.7.17 - NSAPI. */ + TCHECK2(cp[0], GTPV1_TV_NSAPI_LENGTH - 1); + data = (u_int8_t)cp[0]; + printf("NSAPI %u", data & 0xf); + ielen = GTPV1_TV_NSAPI_LENGTH; + break; + + case GTPV1_TV_RANAP: + + /* 29.060 7.7.18 - RANAP Cause. */ + TCHECK2(cp[0], GTPV1_TV_RANAP_LENGTH - 1); + printf("RANAP Cause: %u", cp[0]); + ielen = GTPV1_TV_RANAP_LENGTH; + break; + + case GTPV1_TV_RAB_CONTEXT: + + /* 29.060 7.7.19 - RAB Context. */ + TCHECK2(cp[0], GTPV1_TV_RAB_CONTEXT_LENGTH - 1); + data = cp[0] & 0xf; + dps = (u_int16_t *)(cp + 1); + printf("RAB Context: NSAPI %u, DL GTP-U Seq No %u," + "UL GTP-U Seq No %u, DL PDCP Seq No %u, UL PDCP Seq No %u", + data, ntohs(dps[0]), ntohs(dps[1]), ntohs(dps[2]), + ntohs(dps[3])); + ielen = GTPV1_TV_RAB_CONTEXT_LENGTH; + break; + + case GTPV1_TV_RADIO_PRIORITY_SMS: + + /* 29.060 7.7.20 - Radio Priority SMS. */ + TCHECK2(cp[0], GTPV1_TV_RADIO_PRI_SMS_LENGTH - 1); + printf("Radio Priority SMS: %u", cp[0] & 0x7); + ielen = GTPV1_TV_RADIO_PRI_SMS_LENGTH; + break; + + case GTPV1_TV_RADIO_PRIORITY: + + /* 29.060 7.7.21 - Radio Priority. */ + TCHECK2(cp[0], GTPV1_TV_RADIO_PRI_LENGTH - 1); + data = cp[0] >> 4; + printf("Radio Priority: %u, NSAPI %u", cp[0] & 0x7, data); + ielen = GTPV1_TV_RADIO_PRI_LENGTH; + break; + + case GTPV1_TV_PACKET_FLOW_ID: + + /* 29.060 7.7.22 - Packet Flow ID. */ + TCHECK2(cp[0], GTPV1_TV_PACKET_FLOW_ID_LENGTH - 1); + printf("Packet Flow ID: %u, NSAPI %u", cp[1], cp[0] & 0xf); + ielen = GTPV1_TV_PACKET_FLOW_ID_LENGTH; + break; + + case GTPV1_TV_CHARGING: + + /* 29.060 7.7.23 - Charging Characteristics. */ + /* Charging defined in 3GPP TS 32.298. */ + TCHECK2(cp[0], GTPV1_TV_CHARGING_LENGTH - 1); + printf("Charging Characteristics"); /* XXX */ + ielen = GTPV1_TV_CHARGING_LENGTH; + break; + + case GTPV1_TV_TRACE_REFERENCE: + + /* 29.060 7.7.24 - Trace Reference. */ + TCHECK2(cp[0], GTPV1_TV_TRACE_REFERENCE_LENGTH - 1); + dps = (u_int16_t *)cp; + printf("Trace Reference: %u", ntohs(*dps)); + ielen = GTPV1_TV_TRACE_REFERENCE_LENGTH; + break; + + case GTPV1_TV_TRACE_TYPE: + + /* 29.060 7.7.25 - Trace Type. */ + /* Trace type defined in GSM 12.08. */ + TCHECK2(cp[0], GTPV1_TV_TRACE_TYPE_LENGTH - 1); + dps = (u_int16_t *)cp; + printf("Trace Type: %u", ntohs(*dps)); + ielen = GTPV1_TV_TRACE_TYPE_LENGTH; + break; + + case GTPV1_TV_MSNRR: + + /* 29.060 7.7.26 - MS Not Reachable Reason. */ + /* Reason defined in 3GPP TS 23.040. */ + TCHECK2(cp[0], GTPV1_TV_MSNRR_LENGTH - 1); + printf("MS NRR: %u", cp[0]); + ielen = GTPV1_TV_MSNRR_LENGTH; + break; + + case GTPV1_TV_PACKET_XFER_CMD: + + /* 32.295 6.2.4.5.2 - Packet Transfer Command. */ + TCHECK2(cp[0], GTPV1_TV_PACKET_XFER_CMD_LENGTH - 1); + printf("Packet Transfer Command"); + gtp_print_str(gtp_packet_xfer_cmd, cp[0]); + ielen = GTPV1_TV_PACKET_XFER_CMD_LENGTH; + break; + + case GTPV1_TV_CHARGING_ID: + + /* 29.060 7.7.26 - Charging ID. */ + TCHECK2(cp[0], GTPV1_TV_CHARGING_ID_LENGTH - 1); + dpl = (u_int32_t *)cp; + printf("Charging ID: %u", ntohl(*dpl)); + ielen = GTPV1_TV_CHARGING_ID_LENGTH; + break; + + default: + printf("TV %u", value); + } + +trunc: + return ielen; +} + +int +gtp_v1_print_tlv(register const u_char *cp, u_int value) +{ + u_int8_t data; + u_int16_t *lenp, *seqno, len; + u_char *buf; + int ielen = -1; + + /* Get length of IE. */ + TCHECK2(cp[0], 2); + lenp = (u_int16_t *)cp; + cp += 2; + len = ntohs(*lenp); + TCHECK2(cp[0], len); + ielen = sizeof(data) + sizeof(len) + len; + + switch (value) { + case GTPV1_TLV_END_USER_ADDRESS: + + /* 3GPP 29.060 - 7.7.27 End User Address. */ + printf("End User Address"); + gtp_print_user_address(cp, len); + break; + + case GTPV1_TLV_MM_CONTEXT: + + /* 29.060 7.7.28 - MM Context. */ + printf("MM Context"); /* XXX */ + break; + + case GTPV1_TLV_PDP_CONTEXT: + + /* 29.260 7.7.29 - PDP Context. */ + printf("PDP Context"); /* XXX */ + break; + + case GTPV1_TLV_ACCESS_POINT_NAME: + + /* 29.060 7.7.30 - Access Point Name. */ + printf("AP Name"); + len = (u_int8_t)cp[0]; + if ((buf = malloc(len + 1)) != NULL) { + bcopy(cp + 1, buf, len); + buf[len] = '\0'; + printf(": %s", buf); + free(buf); + } + break; + + case GTPV1_TLV_PROTOCOL_CONFIG_OPTIONS: + + /* 29.060 7.7.31 - Protocol Configuration Options. */ + /* Defined in 3GPP TS 24.008. */ + printf("Config Options"); /* XXX */ + break; + + case GTPV1_TLV_GSN_ADDRESS: + + /* 29.060 7.7.32 - GSN Address. */ + /* Defined in 3GPP TS 23.003. */ + printf("GSN Address"); + if (len == 4) + printf(": %s", ipaddr_string(cp)); +#ifdef INET6 + else if (len == 16) + printf(": %s", ip6addr_string(cp)); +#endif + break; + + case GTPV1_TLV_MSISDN: + + /* 29.060 7.7.33 - MS International PSTN/ISDN Number. */ + printf("MSISDN "); + data = (u_int8_t)cp[0]; /* XXX - Number type. */ + gtp_print_tbcd(cp + 1, len - 1); + break; + + case GTPV1_TLV_QOS_PROFILE: + + /* 29.060 7.7.34 - QoS Profile. */ + /* QoS profile defined in 3GPP TS 24.008 10.5.6.5. */ + printf("QoS Profile: "); + data = (u_int8_t)cp[0]; + printf("Delay Class %u, ", (data >> 3) & 0x7); + printf("Reliability Class %u", data & 0x7); + if (vflag > 1) { + printf(", "); + data = (u_int8_t)cp[1]; + printf("Precedence Class %u", data & 0x7); + /* XXX - Decode more QoS fields. */ + } + break; + + case GTPV1_TLV_AUTHENTICATION: + + /* 29.060 7.7.35 - Authentication. */ + printf("Authentication"); /* XXX */ + break; + + case GTPV1_TLV_TRAFFIC_FLOW: + + /* 29.060 7.7.36 - Traffic Flow Template. */ + printf("Traffic Flow Template"); /* XXX */ + break; + + case GTPV1_TLV_TARGET_IDENTIFICATION: + + /* 29.060 7.7.37 - Target Identification. */ + printf("Target ID"); /* XXX */ + break; + + case GTPV1_TLV_UTRAN_CONTAINER: + + /* 29.060 7.7.38 - UTRAN Transparent Container. */ + printf("UTRAN Container"); /* XXX */ + break; + + case GTPV1_TLV_RAB_SETUP_INFORMATION: + + /* 29.060 7.7.39 - RAB Setup Information. */ + printf("RAB Setup"); /* XXX */ + break; + + case GTPV1_TLV_EXT_HEADER_TYPE_LIST: + + /* 29.060 7.7.40 - Extension Header Type List. */ + printf("Extension Header List"); /* XXX */ + break; + + case GTPV1_TLV_TRIGGER_ID: + + /* 29.060 7.7.41 - Trigger ID. */ + printf("Trigger ID"); /* XXX */ + break; + + case GTPV1_TLV_OMC_IDENTITY: + + /* 29.060 7.7.42 - OMC Identity. */ + printf("OMC Identity"); /* XXX */ + break; + + case GTPV1_TLV_RAN_CONTAINER: + + /* 29.060 7.7.43 - RAN Transparent Container. */ + printf("RAN Container"); /* XXX */ + break; + + case GTPV1_TLV_PDP_CONTEXT_PRIORITIZATION: + + /* 29.060 7.7.45 - PDP Context Prioritization. */ + printf("PDP Context Prioritization"); /* XXX */ + break; + + case GTPV1_TLV_ADDITIONAL_RAB_SETUP_INFO: + + /* 29.060 7.7.45A - Additional RAB Setup Information. */ + printf("Additional RAB Setup"); /* XXX */ + break; + + case GTPV1_TLV_SGSN_NUMBER: + + /* 29.060 7.7.47 - SGSN Number. */ + printf("SGSN Number"); /* XXX */ + break; + + case GTPV1_TLV_COMMON_FLAGS: + + /* 29.060 7.7.48 - Common Flags. */ + printf("Common Flags"); /* XXX */ + break; + + case GTPV1_TLV_APN_RESTRICTION: + + /* 29.060 7.7.49 - APN Restriction. */ + data = (u_int8_t)cp[0]; + printf("APN Restriction: %u", data); + break; + + case GTPV1_TLV_RADIO_PRIORITY_LCS: + + /* 29.060 7.7.25B - Radio Priority LCS. */ + printf("Radio Priority LCS: %u", cp[0] & 0x7); + break; + + case GTPV1_TLV_RAT_TYPE: + + /* 29.060 7.7.50 - RAT Type. */ + printf("RAT"); + gtp_print_str(gtp_rat_type, cp[0]); + break; + + case GTPV1_TLV_USER_LOCATION_INFO: + + /* 29.060 7.7.51 - User Location Information. */ + printf("ULI"); /* XXX */ + break; + + case GTPV1_TLV_MS_TIME_ZONE: + + /* 29.060 7.7.52 - MS Time Zone. */ + printf("MSTZ"); /* XXX */ + break; + + case GTPV1_TLV_IMEI_SV: + + /* 29.060 7.7.53 - IMEI(SV). */ + printf("IMEI(SV) "); + gtp_print_tbcd(cp, len); + break; + + case GTPV1_TLV_CAMEL_CHARGING_CONTAINER: + + /* 29.060 7.7.54 - CAMEL Charging Information Container. */ + printf("CAMEL Charging"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_UE_CONTEXT: + + /* 29.060 7.7.55 - MBMS UE Context. */ + printf("MBMS UE Context"); /* XXX */ + break; + + case GTPV1_TLV_TMGI: + + /* 29.060 7.7.56 - Temporary Mobile Group Identity. */ + printf("TMGI"); /* XXX */ + break; + + case GTPV1_TLV_RIM_ROUTING_ADDRESS: + + /* 29.060 7.7.57 - RIM Routing Address. */ + printf("RIM Routing Address"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_PROTOCOL_CONFIG_OPTIONS: + + /* 29.060 7.7.58 - MBMS Protocol Configuration Options. */ + printf("MBMS Protocol Config Options"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_SERVICE_AREA: + + /* 29.060 7.7.60 - MBMS Service Area. */ + printf("MBMS Service Area"); /* XXX */ + break; + + case GTPV1_TLV_SOURCE_RNC_PDCP_CONTEXT_INFO: + + /* 29.060 7.7.61 - Source RNC PDCP Context Information. */ + printf("Source RNC PDCP Context"); /* XXX */ + break; + + case GTPV1_TLV_ADDITIONAL_TRACE_INFO: + + /* 29.060 7.7.62 - Additional Trace Information. */ + printf("Additional Trace Info"); /* XXX */ + break; + + case GTPV1_TLV_HOP_COUNTER: + + /* 29.060 7.7.63 - Hop Counter. */ + printf("Hop Counter: %u", cp[0]); + break; + + case GTPV1_TLV_SELECTED_PLMN_ID: + + /* 29.060 7.7.64 - Selected PLMN ID. */ + printf("Selected PLMN ID"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_SESSION_IDENTIFIER: + + /* 29.060 7.7.65 - MBMS Session Identifier. */ + printf("MBMS Session ID: %u", cp[0]); + break; + + case GTPV1_TLV_MBMS_2G_3G_INDICATOR: + + /* 29.060 7.7.66 - MBMS 2G/3G Indicator. */ + printf("MBMS 2G/3G Indicator"); + gtp_print_str(mbms_2g3g_indicator, cp[0]); + break; + + case GTPV1_TLV_ENHANCED_NSAPI: + + /* 29.060 7.7.67 - Enhanced NSAPI. */ + printf("Enhanced NSAPI"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_SESSION_DURATION: + + /* 29.060 7.7.59 - MBMS Session Duration. */ + printf("MBMS Session Duration"); /* XXX */ + break; + + case GTPV1_TLV_ADDITIONAL_MBMS_TRACE_INFO: + + /* 29.060 7.7.68 - Additional MBMS Trace Info. */ + printf("Additional MBMS Trace Info"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_SESSION_REPITITION_NO: + + /* 29.060 7.7.69 - MBMS Session Repetition Number. */ + printf("MBMS Session Repetition No: %u", cp[0]); + break; + + case GTPV1_TLV_MBMS_TIME_TO_DATA_TRANSFER: + + /* 29.060 7.7.70 - MBMS Time to Data Transfer. */ + printf("MBMS Time to Data Transfer: %u", cp[0]); + break; + + case GTPV1_TLV_PS_HANDOVER_REQUEST_CONTEXT: + + /* 29.060 7.7.71 - PS Handover Request Context (Void). */ + break; + + case GTPV1_TLV_BSS_CONTAINER: + + /* 29.060 7.7.72 - BSS Container. */ + printf("BSS Container"); /* XXX */ + break; + + case GTPV1_TLV_CELL_IDENTIFICATION: + + /* 29.060 7.7.73 - Cell Identification. */ + printf("Cell Identification"); /* XXX */ + break; + + case GTPV1_TLV_PDU_NUMBERS: + + /* 29.060 7.7.74 - PDU Numbers. */ + printf("PDU Numbers"); /* XXX */ + break; + + case GTPV1_TLV_BSSGP_CAUSE: + + /* 29.060 7.7.75 - BSSGP Cause. */ + printf("BSSGP Cause: %u", cp[0]); + break; + + case GTPV1_TLV_REQUIRED_MBMS_BEARER_CAP: + + /* 29.060 7.7.76 - Required MBMS Bearer Cap. */ + printf("Required MBMS Bearer Cap"); /* XXX */ + break; + + case GTPV1_TLV_RIM_ROUTING_ADDRESS_DISC: + + /* 29.060 7.7.77 - RIM Routing Address Discriminator. */ + printf("RIM Routing Address Discriminator: %u", cp[0] & 0xf); + break; + + case GTPV1_TLV_LIST_OF_SETUP_PFCS: + + /* 29.060 7.7.78 - List of Setup PFCs. */ + printf("List of Setup PFCs"); /* XXX */ + break; + + case GTPV1_TLV_PS_HANDOVER_XID_PARAMETERS: + + /* 29.060 7.7.79 - PS Handover XID Parameters. */ + printf("PS Handover XID Parameters"); /* XXX */ + break; + + case GTPV1_TLV_MS_INFO_CHANGE_REPORTING: + + /* 29.060 7.7.80 - MS Info Change Reporting. */ + printf("MS Info Change Reporting"); + gtp_print_str(ms_info_change_rpt, cp[0]); + break; + + case GTPV1_TLV_DIRECT_TUNNEL_FLAGS: + + /* 29.060 7.7.81 - Direct Tunnel Flags. */ + printf("Direct Tunnel Flags"); /* XXX */ + break; + + case GTPV1_TLV_CORRELATION_ID: + + /* 29.060 7.7.82 - Correlation ID. */ + printf("Correlation ID"); /* XXX */ + break; + + case GTPV1_TLV_BEARER_CONTROL_MODE: + + /* 29.060 7.7.83 - Bearer Control Mode. */ + printf("Bearer Control Mode"); /* XXX */ + break; + + case GTPV1_TLV_MBMS_FLOW_IDENTIFIER: + + /* 29.060 7.7.84 - MBMS Flow Identifier. */ + printf("MBMS Flow Identifier"); /* XXX */ + break; + + case GTPV1_TLV_RELEASED_PACKETS: + + /* 32.295 6.2.4.5.4 - Sequence Numbers of Released Packets. */ + printf("Released Packets:"); + seqno = (u_int16_t *)cp; + while (len > 0) { + printf(" %u", ntohs(*seqno)); + seqno++; + len -= sizeof(*seqno); + } + break; + + case GTPV1_TLV_CANCELLED_PACKETS: + + /* 32.295 6.2.4.5.5 - Sequence Numbers of Cancelled Packets. */ + printf("Cancelled Packets:"); + seqno = (u_int16_t *)cp; + while (len > 0) { + printf(" %u", ntohs(*seqno)); + seqno++; + len -= sizeof(*seqno); + } + break; + + case GTPV1_TLV_CHARGING_GATEWAY_ADDRESS: + + /* 29.060 7.7.44 - Charging Gateway Address. */ + printf("Charging Gateway"); + if (len == 4) + printf(": %s", ipaddr_string(cp)); +#ifdef INET6 + else if (len == 16) + printf(": %s", ip6addr_string(cp)); +#endif + break; + + case GTPV1_TLV_DATA_RECORD_PACKET: + + /* 32.295 6.2.4.5.3 - Data Record Packet. */ + printf("Data Record: Records %u, Format %u, Format Version %u", + cp[0], cp[1], ntohs(*(u_int16_t *)(cp + 2))); + break; + + case GTPV1_TLV_REQUESTS_RESPONDED: + + /* 32.295 6.2.4.6 - Requests Responded. */ + printf("Requests Responded:"); + seqno = (u_int16_t *)cp; + while (len > 0) { + printf(" %u", ntohs(*seqno)); + seqno++; + len -= sizeof(*seqno); + } + break; + + case GTPV1_TLV_ADDRESS_OF_RECOMMENDED_NODE: + + /* 32.295 6.2.4.3 - Address of Recommended Node. */ + printf("Address of Recommended Node"); + if (len == 4) + printf(": %s", ipaddr_string(cp)); +#ifdef INET6 + else if (len == 16) + printf(": %s", ip6addr_string(cp)); +#endif + break; + + case GTPV1_TLV_PRIVATE_EXTENSION: + + /* 29.060 7.7.46 - Private Extension. */ + printf("Private Extension"); + break; + + default: + printf("TLV %u (len %u)", value, len); + } + + return ielen; + +trunc: + return -1; +} diff --git a/usr.sbin/tcpdump/print-udp.c b/usr.sbin/tcpdump/print-udp.c index 48c599c3315..3661d308d0e 100644 --- a/usr.sbin/tcpdump/print-udp.c +++ b/usr.sbin/tcpdump/print-udp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print-udp.c,v 1.32 2009/11/04 07:37:55 jsing Exp $ */ +/* $OpenBSD: print-udp.c,v 1.33 2009/11/04 09:43:11 jsing Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -357,6 +357,9 @@ static int udp_cksum(register const struct ip *ip, #define RADIUS_AUTH_PORT 1812 #define RADIUS_ACCT_PORT 1813 #define HSRP_PORT 1985 /*XXX*/ +#define GTP_C_PORT 2123 +#define GTP_U_PORT 2152 +#define GTP_PRIME_PORT 3386 #define UDPENCAP_PORT 4500 /*XXX*/ #define MULTICASTDNS_PORT 5353 @@ -615,6 +618,10 @@ udp_print(register const u_char *bp, u_int length, register const u_char *bp2) sport, dport); } #endif /*INET6*/ + else if (ISPORT(GTP_C_PORT) || ISPORT(GTP_U_PORT) || + ISPORT(GTP_PRIME_PORT)) + gtp_print((const u_char *)(up + 1), length, + sport, dport); /* * Kludge in test for whiteboard packets. */ |