#include "decode_gtp.h" #define GTP_TPDU 255 #define GTP1U_PORT 2152 #define GTP1_F_MASK 0x07 #define GTP1_GET_TYPE(gtp1_hdr) ((gtp1_hdr)->type) #define GTP1_GET_FLAGS(gtp1_hdr) ((gtp1_hdr)->flags >> 5) #define GTP1_GET_HLEN(gtp1_hdr) (((gtp1_hdr)->flags & GTP1_F_MASK) > 0 ? 12 : 8) enum gtp_version_e { GTP_V0 = 0, GTP_V1, }; int decode_gtp(gtp_info_t *packet, const uint8_t *data, uint32_t len) { if (len < sizeof(gtp1_header_t)) { LOG_ERROR("Parser GTP Header: packet length too small %d", len); return -1; } packet->hdr = (gtp1_header_t *)data; if (GTP1_GET_FLAGS(packet->hdr) != GTP_V1) { LOG_ERROR("Parser GTP Header: invalid gtp flags %d", GTP1_GET_FLAGS(packet->hdr)); return -1; } if (GTP1_GET_TYPE(packet->hdr) != GTP_TPDU) { LOG_ERROR("Parser GTP Header: invalid gtp type %d", GTP1_GET_TYPE(packet->hdr)); return -1; } /* From 29.060: "This field shall be present if and only if any one or * more of the S, PN and E flags are set.". * * If any of the bit is set, then the remaining ones also have to be set. */ packet->hdr_len = GTP1_GET_HLEN(packet->hdr); packet->payload = (uint8_t *)data + packet->hdr_len; packet->payload_len = len - packet->hdr_len; return 0; } int dump_gtp_info(gtp_info_t *packet, char *buff, size_t size) { return snprintf(buff, size, "{\"hdr_len\":%u,\"data_len\":%u}", packet->hdr_len, packet->payload_len); }