/** * * \section COPYRIGHT * * Copyright 2013-2015 Software Radio Systems Limited * * \section LICENSE * * This file is part of the srsUE library. * * srsUE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsUE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #ifndef UEPCAP_H #define UEPCAP_H #include #include #include #include #define MAC_LTE_DLT 147 #define RRC_LTE_DLT 148 #define NAS_LTE_DLT 149 /* This structure gets written to the start of the file */ typedef struct pcap_hdr_s { unsigned int magic_number; /* magic number */ unsigned short version_major; /* major version number */ unsigned short version_minor; /* minor version number */ unsigned int thiszone; /* GMT to local correction */ unsigned int sigfigs; /* accuracy of timestamps */ unsigned int snaplen; /* max length of captured packets, in octets */ unsigned int network; /* data link type */ } pcap_hdr_t; /* This structure precedes each packet */ typedef struct pcaprec_hdr_s { unsigned int ts_sec; /* timestamp seconds */ unsigned int ts_usec; /* timestamp microseconds */ unsigned int incl_len; /* number of octets of packet saved in file */ unsigned int orig_len; /* actual length of packet */ } pcaprec_hdr_t; /* radioType */ #define FDD_RADIO 1 #define TDD_RADIO 2 /* Direction */ #define DIRECTION_UPLINK 0 #define DIRECTION_DOWNLINK 1 /* rntiType */ #define NO_RNTI 0 /* Used for BCH-BCH */ #define P_RNTI 1 #define RA_RNTI 2 #define C_RNTI 3 #define SI_RNTI 4 #define SPS_RNTI 5 #define M_RNTI 6 #define MAC_LTE_START_STRING "mac-lte" #define MAC_LTE_RNTI_TAG 0x02 /* 2 bytes, network order */ #define MAC_LTE_UEID_TAG 0x03 /* 2 bytes, network order */ #define MAC_LTE_FRAME_SUBFRAME_TAG 0x04 /* 2 bytes, network order */ /* SFN is stored in 12 MSB and SF in 4 LSB */ #define MAC_LTE_PREDFINED_DATA_TAG 0x05 /* 1 byte */ #define MAC_LTE_RETX_TAG 0x06 /* 1 byte */ #define MAC_LTE_CRC_STATUS_TAG 0x07 /* 1 byte */ /* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU continues until the end of the frame) */ #define MAC_LTE_PAYLOAD_TAG 0x01 /* Context information for every MAC PDU that will be logged */ typedef struct MAC_Context_Info_t { unsigned short radioType; unsigned char direction; unsigned char rntiType; unsigned short rnti; unsigned short ueid; unsigned char isRetx; unsigned char crcStatusOK; unsigned short sysFrameNumber; unsigned short subFrameNumber; } MAC_Context_Info_t; /* Context information for every NAS PDU that will be logged */ typedef struct NAS_Context_Info_s { // No Context yet } NAS_Context_Info_t; /**************************************************************************/ /* API functions for opening/writing/closing MAC-LTE PCAP files */ /* Open the file and write file header */ inline FILE *MAC_LTE_PCAP_Open(const char *fileName) { pcap_hdr_t file_header = { 0xa1b2c3d4, /* magic number */ 2, 4, /* version number is 2.4 */ 0, /* timezone */ 0, /* sigfigs - apparently all tools do this */ 65535, /* snaplen - this should be long enough */ MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */ }; FILE *fd = fopen(fileName, "w"); if (fd == NULL) { printf("Failed to open file \"%s\" for writing\n", fileName); return NULL; } /* Write the file header */ fwrite(&file_header, sizeof(pcap_hdr_t), 1, fd); return fd; } /* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, const unsigned char *PDU, unsigned int length) { pcaprec_hdr_t packet_header; char context_header[256]; int offset = 0; uint16_t tmp16; /* Can't write if file wasn't successfully opened */ if (fd == NULL) { printf("Error: Can't write to empty file handle\n"); return 0; } /*****************************************************************/ /* Context information (same as written by UDP heuristic clients */ context_header[offset++] = context->radioType; context_header[offset++] = context->direction; context_header[offset++] = context->rntiType; /* RNTI */ context_header[offset++] = MAC_LTE_RNTI_TAG; tmp16 = htons(context->rnti); memcpy(context_header+offset, &tmp16, 2); offset += 2; /* UEId */ context_header[offset++] = MAC_LTE_UEID_TAG; tmp16 = htons(context->ueid); memcpy(context_header+offset, &tmp16, 2); offset += 2; /* Subframe Number and System Frame Number */ /* SFN is stored in 12 MSB and SF in 4 LSB */ context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG; tmp16 = (context->sysFrameNumber << 4) | context->subFrameNumber; tmp16 = htons(tmp16); memcpy(context_header+offset, &tmp16, 2); offset += 2; /* CRC Status */ context_header[offset++] = MAC_LTE_CRC_STATUS_TAG; context_header[offset++] = context->crcStatusOK; /* Data tag immediately preceding PDU */ context_header[offset++] = MAC_LTE_PAYLOAD_TAG; /****************************************************************/ /* PCAP Header */ struct timeval t; gettimeofday(&t, NULL); packet_header.ts_sec = t.tv_sec; packet_header.ts_usec = t.tv_usec; packet_header.incl_len = offset + length; packet_header.orig_len = offset + length; /***************************************************************/ /* Now write everything to the file */ fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd); fwrite(context_header, 1, offset, fd); fwrite(PDU, 1, length, fd); return 1; } /* Close the PCAP file */ inline void MAC_LTE_PCAP_Close(FILE *fd) { if(fd) fclose(fd); } /**************************************************************************/ /* API functions for opening/writing/closing NAS-LTE PCAP files */ /* Open the file and write file header */ inline FILE *NAS_LTE_PCAP_Open(const char *fileName) { pcap_hdr_t file_header = { 0xa1b2c3d4, /* magic number */ 2, 4, /* version number is 2.4 */ 0, /* timezone */ 0, /* sigfigs - apparently all tools do this */ 65535, /* snaplen - this should be long enough */ NAS_LTE_DLT /* Data Link Type (DLT). Set as unused value 149 for now */ }; FILE *fd = fopen(fileName, "w"); if (fd == NULL) { printf("Failed to open file \"%s\" for writing\n", fileName); return NULL; } /* Write the file header */ fwrite(&file_header, sizeof(pcap_hdr_t), 1, fd); return fd; } /* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ inline int NAS_LTE_PCAP_WritePDU(FILE *fd, NAS_Context_Info_t *context, const unsigned char *PDU, unsigned int length) { pcaprec_hdr_t packet_header; /* Can't write if file wasn't successfully opened */ if (fd == NULL) { printf("Error: Can't write to empty file handle\n"); return 0; } /****************************************************************/ /* PCAP Header */ struct timeval t; gettimeofday(&t, NULL); packet_header.ts_sec = t.tv_sec; packet_header.ts_usec = t.tv_usec; packet_header.incl_len = length; packet_header.orig_len = length; /***************************************************************/ /* Now write everything to the file */ fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd); fwrite(PDU, 1, length, fd); return 1; } /* Close the PCAP file */ inline void NAS_LTE_PCAP_Close(FILE *fd) { if(fd) fclose(fd); } #endif /* UEPCAP_H */