mirror of https://gerrit.osmocom.org/osmo-tetra
move add sds parsing to tetra_sds.c
This commit is contained in:
parent
b547d72863
commit
6733e6c6ed
385
src/tetra_sds.c
385
src/tetra_sds.c
|
@ -21,21 +21,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdio.h>
|
||||||
#include "tetra_sds.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <osmocom/core/utils.h>
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
|
||||||
#include "tetra_common.h"
|
#include "tetra_common.h"
|
||||||
|
#include "tetra_prim.h"
|
||||||
|
#include "tetra_upper_mac.h"
|
||||||
#include "tetra_mac_pdu.h"
|
#include "tetra_mac_pdu.h"
|
||||||
|
#include "tetra_llc_pdu.h"
|
||||||
|
#include "tetra_mm_pdu.h"
|
||||||
|
#include "tetra_cmce_pdu.h"
|
||||||
|
#include "tetra_sndcp_pdu.h"
|
||||||
|
#include "tetra_mle_pdu.h"
|
||||||
|
#include "tetra_gsmtap.h"
|
||||||
|
#include "tetra_sds.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
const char oth_reserved[]="Other Reserved";
|
const char oth_reserved[]="Other Reserved";
|
||||||
|
|
||||||
int decode_pdu(char *dec,unsigned char *enc,int len)
|
int decode_pdu(char *dec,unsigned char *enc,int len)
|
||||||
|
@ -77,6 +85,371 @@ char *get_sds_type(uint8_t type) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: move this into tetra_sds.c and break into multiple functions */
|
||||||
|
unsigned int parse_d_sds_data(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
|
||||||
|
{
|
||||||
|
/* strona 269, 297, 1072, 1075 */
|
||||||
|
uint8_t *bits = msg->l3h+3;
|
||||||
|
|
||||||
|
int n=0;
|
||||||
|
int l,a;
|
||||||
|
int m=5;
|
||||||
|
|
||||||
|
uint8_t pdu_type;
|
||||||
|
uint8_t cpti;
|
||||||
|
uint32_t calling_ssi;
|
||||||
|
uint32_t calling_ext=0;
|
||||||
|
uint8_t sdti;
|
||||||
|
uint8_t udata[512];
|
||||||
|
uint16_t datalen=0;
|
||||||
|
uint8_t protoid;
|
||||||
|
uint8_t reserved1;
|
||||||
|
uint8_t coding_scheme;
|
||||||
|
char descr[4096];
|
||||||
|
char tmpstr[128];
|
||||||
|
char tmpstr2[1024];
|
||||||
|
int is_sdstl=0;
|
||||||
|
uint8_t message_type;
|
||||||
|
struct tetra_resrc_decoded rsd;
|
||||||
|
int tmpdu_offset;
|
||||||
|
uint8_t sdstl_delivery_report_request;
|
||||||
|
uint8_t sdstl_service_selection;
|
||||||
|
uint8_t sdstl_storage_control;
|
||||||
|
uint8_t sdstl_message_reference;
|
||||||
|
uint8_t sdstl_validity_period;
|
||||||
|
uint8_t sdstl_forw_address_type;
|
||||||
|
uint32_t sdstl_forw_address;
|
||||||
|
uint32_t sdstl_forw_address_ext;
|
||||||
|
uint8_t sdstl_extnum_digits;
|
||||||
|
uint8_t sdstl_extnum_digit;
|
||||||
|
int decode_sds=1;
|
||||||
|
|
||||||
|
|
||||||
|
memset(&rsd, 0, sizeof(rsd));
|
||||||
|
tmpdu_offset = macpdu_decode_resource(&rsd, msg->l1h);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m=5; pdu_type=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
m=2; cpti=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
switch(cpti) {
|
||||||
|
case 0: /* SNA */
|
||||||
|
m=8; calling_ssi=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
break;
|
||||||
|
case 1: /* SSI */
|
||||||
|
m=24; calling_ssi=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
break;
|
||||||
|
case 2: /* TETRA Subscriber Identity (TSI) */
|
||||||
|
m=24; calling_ssi=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
m=24; calling_ext=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* hgw co to jest */
|
||||||
|
printf("\nparse_d_sds_data: BAD CPTI %i\n",cpti);
|
||||||
|
return(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(descr,"CPTI:%i CalledSSI:%i CallingSSI:%i CallingEXT:%i ",cpti,rsd.addr.ssi,calling_ssi,calling_ext);
|
||||||
|
|
||||||
|
m=2; sdti=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
|
||||||
|
switch(sdti) {
|
||||||
|
case 0: /* user defined data-1 16 bit */
|
||||||
|
datalen=2;
|
||||||
|
m=8;
|
||||||
|
for(l=0;l<datalen;l++) {
|
||||||
|
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
}
|
||||||
|
sprintf(tmpstr," UserData1: 0x%2.2X 0x%2.2X",udata[0],udata[1]);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1: /* user defined data-2 32 bit */
|
||||||
|
datalen=4;
|
||||||
|
m=8;
|
||||||
|
for(l=0;l<datalen;l++) {
|
||||||
|
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
}
|
||||||
|
sprintf(tmpstr,"UserData2: 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X",udata[0],udata[1],udata[2],udata[3]);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
case 2: /* user defined data-3 64 bit */
|
||||||
|
datalen=8;
|
||||||
|
m=8;
|
||||||
|
for(l=0;l<datalen;l++) {
|
||||||
|
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
|
||||||
|
}
|
||||||
|
sprintf(tmpstr," UserData3: 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X",udata[0],udata[1],udata[2],udata[3],udata[4],udata[5],udata[6],udata[7]);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
case 3: /* length indicator + user defined data-4 bit */
|
||||||
|
m=11; datalen=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
m=8; protoid=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
sprintf(tmpstr," UserData4: len:%i protoid:%2.2X(%s) ",datalen,protoid,get_sds_type(protoid));
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
/* SDS-TL header */
|
||||||
|
if (protoid&0x80) {
|
||||||
|
is_sdstl=1;
|
||||||
|
m=4; message_type=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
strcat(descr,"SDS-TL:[ MsgType:");
|
||||||
|
|
||||||
|
switch(message_type) {
|
||||||
|
case 0: /* SDS-TRANSFER page 1182 */
|
||||||
|
strcat(descr,"SDS-TRANSFER");
|
||||||
|
m=2; sdstl_delivery_report_request=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m; /* page 1186 */
|
||||||
|
m=1; sdstl_service_selection=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m; /* page 1189 1:to group*/
|
||||||
|
m=1; sdstl_storage_control=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m; /* page 1189 */
|
||||||
|
m=8; sdstl_message_reference=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
|
||||||
|
sprintf(tmpstr," MSG_REF:%i TO_GROUP:%i",sdstl_message_reference,sdstl_service_selection);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
if (sdstl_storage_control) {
|
||||||
|
/* Storage/forward control information is available */
|
||||||
|
m=5; sdstl_validity_period=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
m=3; sdstl_forw_address_type=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
|
||||||
|
sprintf(tmpstr," Validity_period:%i",sdstl_validity_period);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
switch(sdstl_forw_address_type) {
|
||||||
|
case 0: /* SNA */
|
||||||
|
m=8; sdstl_forw_address=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
sprintf(tmpstr," Forward_addr_SNA:%i",sdstl_forw_address);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
case 1: /* SSI */
|
||||||
|
m=24; sdstl_forw_address=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
sprintf(tmpstr," Forward_addr_SSI:%i",sdstl_forw_address);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
case 2: /* TETRA Subscriber Identity (TSI) */
|
||||||
|
m=24; sdstl_forw_address=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
m=24; sdstl_forw_address_ext=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
sprintf(tmpstr," Forward_addr_SSI:%i:EXT:%i",sdstl_forw_address,sdstl_forw_address_ext);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
case 3: /* External subscriber number */
|
||||||
|
m=8; sdstl_extnum_digits=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
strcat(descr," Forward_addr_EXT:");
|
||||||
|
l=sdstl_extnum_digits;
|
||||||
|
while(l) {
|
||||||
|
m=4; sdstl_extnum_digit=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
sprintf(tmpstr,"%c",'0'+sdstl_extnum_digit);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
l--;
|
||||||
|
}
|
||||||
|
if (sdstl_extnum_digits&0x1) {
|
||||||
|
/* odd number, eat dummy digit */
|
||||||
|
n=n+4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7: /* no forward address */
|
||||||
|
strcat(descr," Forward_addr_none");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* hgw co to jest */
|
||||||
|
sprintf(tmpstr," Forward_addr_BAD:%i",sdstl_forw_address_type);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
return(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1: /* SDS-REPORT */
|
||||||
|
strcat(descr,"SDS-REPORT");
|
||||||
|
n=n+12;
|
||||||
|
decode_sds=0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* SDS-ACK */
|
||||||
|
strcat(descr,"SDS-ACK ");
|
||||||
|
decode_sds=0;
|
||||||
|
|
||||||
|
n=n+12;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
decode_sds=0;
|
||||||
|
if (message_type&0x8) {
|
||||||
|
sprintf(tmpstr,"Defined_by_application_%i ",message_type);
|
||||||
|
} else {
|
||||||
|
sprintf(tmpstr,"Reserved_for_add_msg_types_%i ",message_type);
|
||||||
|
}
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
n=n+12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(descr,"] ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datalen>2047) {
|
||||||
|
strcat(descr,"ERROR: SDS too short");
|
||||||
|
decode_sds=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t c;
|
||||||
|
if (decode_sds) {
|
||||||
|
switch (protoid) {
|
||||||
|
case TETRA_SDS_PROTO_SIMPLE_LOC:
|
||||||
|
sprintf(tmpstr,"SIMPLE_LOCATION_SYSTEM:[");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
decode_simplelocsystem(tmpstr2, sizeof(tmpstr2),bits+n,datalen);
|
||||||
|
strcat(descr,tmpstr2);
|
||||||
|
sprintf(tmpstr,"]\n");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TETRA_SDS_PROTO_LOCSYSTEM:
|
||||||
|
sprintf(tmpstr,"LOCATION_SYSTEM:[");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
decode_locsystem(tmpstr2, sizeof(tmpstr2),bits+n,datalen);
|
||||||
|
strcat(descr,tmpstr2);
|
||||||
|
sprintf(tmpstr,"]\n");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TETRA_SDS_PROTO_LIP:
|
||||||
|
sprintf(tmpstr,"LIP:[");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
decode_lip(tmpstr2, sizeof(tmpstr2),bits+n,datalen);
|
||||||
|
strcat(descr,tmpstr2);
|
||||||
|
sprintf(tmpstr,"]");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TETRA_SDS_PROTO_TXTMSG:
|
||||||
|
case TETRA_SDS_PROTO_SIMPLE_TXTMSG:
|
||||||
|
case TETRA_SDS_PROTO_SIMPLE_ITXTMSG:
|
||||||
|
case TETRA_SDS_PROTO_ITXTMSG:
|
||||||
|
m=1; reserved1=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
m=7; coding_scheme=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
||||||
|
sprintf(tmpstr," coding_scheme:%2.2x ",coding_scheme);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
sprintf(tmpstr,"DATA:[");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
/* dump text message */
|
||||||
|
switch(coding_scheme) {
|
||||||
|
case 0: /* 7-bit gsm encoding */
|
||||||
|
sprintf(tmpstr," *7bit* ");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
m=8;
|
||||||
|
l=0;
|
||||||
|
while((datalen>=m)&&(n<=len)) {
|
||||||
|
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
l++;
|
||||||
|
datalen=datalen-m;
|
||||||
|
}
|
||||||
|
/* TODO: maybe skip the first two bytes? i've never seen a 7-bit SDS in the wild --sq5bpf */
|
||||||
|
datalen=decode_pdu(tmpstr2,udata,l);
|
||||||
|
/* dump */
|
||||||
|
for(a=0;a<datalen;a++) {
|
||||||
|
if (isprint(tmpstr2[a])) {
|
||||||
|
sprintf(tmpstr,"%c",tmpstr2[a]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sprintf(tmpstr,"\\x%2.2X",tmpstr2[a]);
|
||||||
|
}
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
strcat(descr,"]");
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x1A: /* SO/IEC 10646-1 [22] UCS-2/UTF-16BE (16-bit) alphabet */
|
||||||
|
/* TODO: use iconv or whatever else
|
||||||
|
* for now we'll just use the 8-bit decoding function,
|
||||||
|
* every other bit will be written as \x00. ugly but readable --sq5bpf
|
||||||
|
*/
|
||||||
|
|
||||||
|
sprintf(tmpstr," *UTF16* ");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
default: /* 8-bit */
|
||||||
|
m=8;
|
||||||
|
l=0;
|
||||||
|
while((datalen>=m)&&(n<=len)) {
|
||||||
|
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
l++;
|
||||||
|
datalen=datalen-m;
|
||||||
|
}
|
||||||
|
/* TODO: the first two bytes are often garbage. either parse it or skip it
|
||||||
|
* i guess i'll have to read the etsi specifications better --sq5bpf */
|
||||||
|
|
||||||
|
for(a=0;a<l;a++) {
|
||||||
|
if (isprint(udata[a])) {
|
||||||
|
sprintf(tmpstr,"%c",udata[a]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sprintf(tmpstr,"\\x%2.2X",udata[a]);
|
||||||
|
}
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
strcat(descr,"]");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(tmpstr,"DATA:[");
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
/* other message */
|
||||||
|
/* hexdump */
|
||||||
|
m=8;
|
||||||
|
l=0;
|
||||||
|
while((datalen>=m)&&(n<=len)) {
|
||||||
|
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
||||||
|
l++;
|
||||||
|
datalen=datalen-m;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* dump */
|
||||||
|
for(a=0;a<l;a++) {
|
||||||
|
sprintf(tmpstr,"0x%2.2X ",udata[a]);
|
||||||
|
strcat(descr,tmpstr);
|
||||||
|
}
|
||||||
|
strcat(descr,"]");
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
printf("%s\n",descr);
|
||||||
|
sprintf(tmpstr2,"TETMON_begin FUNC:SDSDEC [%s] RX:%i TETMON_end",descr,tetra_hack_rxid);
|
||||||
|
sendto(tetra_hack_live_socket, (char *)&tmpstr2, strlen((char *)&tmpstr2)+1, 0, (struct sockaddr *)&tetra_hack_live_sockaddr, tetra_hack_socklen);
|
||||||
|
/* We'll just ignore these for now :)
|
||||||
|
* External subscriber number
|
||||||
|
* DM-MS address
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *get_lip_dirtravel_type(uint8_t type) {
|
char *get_lip_dirtravel_type(uint8_t type) {
|
||||||
struct lip_dirtravel_type* a= (struct lip_dirtravel_type *)&lip_dirtravel_types;
|
struct lip_dirtravel_type* a= (struct lip_dirtravel_type *)&lip_dirtravel_types;
|
||||||
while (a->description)
|
while (a->description)
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
//#include <osmocom/core/utils.h>
|
||||||
|
//#include <osmocom/core/msgb.h>
|
||||||
|
//#include <osmocom/core/talloc.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_TETRA_SDS_H
|
#ifndef HAVE_TETRA_SDS_H
|
||||||
#define HAVE_TETRA_SDS_H
|
#define HAVE_TETRA_SDS_H
|
||||||
|
@ -198,6 +202,10 @@ enum tetra_lip_velocitytypes {
|
||||||
TETRA_LIP_VELOCITY_HORIZ_VELOCITY_VERT_DIRTRAVEL_UNC = 7
|
TETRA_LIP_VELOCITY_HORIZ_VELOCITY_VERT_DIRTRAVEL_UNC = 7
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
unsigned int parse_d_sds_data(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len);
|
||||||
|
|
||||||
|
|
||||||
int decode_lip(char *out, int outlen,uint8_t *bits,int datalen);
|
int decode_lip(char *out, int outlen,uint8_t *bits,int datalen);
|
||||||
|
|
||||||
/************** Location System **************/
|
/************** Location System **************/
|
||||||
|
|
|
@ -200,369 +200,6 @@ uint parse_d_setup(struct tetra_mac_state *tms, struct msgb *msg, unsigned int l
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: move this into tetra_sds.c and break into multiple functions */
|
|
||||||
uint parse_d_sds_data(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
|
|
||||||
{
|
|
||||||
/* strona 269, 297, 1072, 1075 */
|
|
||||||
uint8_t *bits = msg->l3h+3;
|
|
||||||
|
|
||||||
int n=0;
|
|
||||||
int l,a;
|
|
||||||
int m=5;
|
|
||||||
|
|
||||||
uint8_t pdu_type;
|
|
||||||
uint8_t cpti;
|
|
||||||
uint32_t calling_ssi;
|
|
||||||
uint32_t calling_ext=0;
|
|
||||||
uint8_t sdti;
|
|
||||||
uint8_t udata[512];
|
|
||||||
uint16_t datalen=0;
|
|
||||||
uint8_t protoid;
|
|
||||||
uint8_t reserved1;
|
|
||||||
uint8_t coding_scheme;
|
|
||||||
char descr[4096];
|
|
||||||
char tmpstr[128];
|
|
||||||
char tmpstr2[1024];
|
|
||||||
int is_sdstl=0;
|
|
||||||
uint8_t message_type;
|
|
||||||
struct tetra_resrc_decoded rsd;
|
|
||||||
int tmpdu_offset;
|
|
||||||
uint8_t sdstl_delivery_report_request;
|
|
||||||
uint8_t sdstl_service_selection;
|
|
||||||
uint8_t sdstl_storage_control;
|
|
||||||
uint8_t sdstl_message_reference;
|
|
||||||
uint8_t sdstl_validity_period;
|
|
||||||
uint8_t sdstl_forw_address_type;
|
|
||||||
uint32_t sdstl_forw_address;
|
|
||||||
uint32_t sdstl_forw_address_ext;
|
|
||||||
uint8_t sdstl_extnum_digits;
|
|
||||||
uint8_t sdstl_extnum_digit;
|
|
||||||
int decode_sds=1;
|
|
||||||
|
|
||||||
|
|
||||||
memset(&rsd, 0, sizeof(rsd));
|
|
||||||
tmpdu_offset = macpdu_decode_resource(&rsd, msg->l1h);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m=5; pdu_type=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
m=2; cpti=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
switch(cpti) {
|
|
||||||
case 0: /* SNA */
|
|
||||||
m=8; calling_ssi=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
break;
|
|
||||||
case 1: /* SSI */
|
|
||||||
m=24; calling_ssi=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
break;
|
|
||||||
case 2: /* TETRA Subscriber Identity (TSI) */
|
|
||||||
m=24; calling_ssi=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
m=24; calling_ext=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* hgw co to jest */
|
|
||||||
printf("\nparse_d_sds_data: BAD CPTI %i\n",cpti);
|
|
||||||
return(1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(descr,"CPTI:%i CalledSSI:%i CallingSSI:%i CallingEXT:%i ",cpti,rsd.addr.ssi,calling_ssi,calling_ext);
|
|
||||||
|
|
||||||
m=2; sdti=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
|
|
||||||
switch(sdti) {
|
|
||||||
case 0: /* user defined data-1 16 bit */
|
|
||||||
datalen=2;
|
|
||||||
m=8;
|
|
||||||
for(l=0;l<datalen;l++) {
|
|
||||||
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
}
|
|
||||||
sprintf(tmpstr," UserData1: 0x%2.2X 0x%2.2X",udata[0],udata[1]);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1: /* user defined data-2 32 bit */
|
|
||||||
datalen=4;
|
|
||||||
m=8;
|
|
||||||
for(l=0;l<datalen;l++) {
|
|
||||||
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
}
|
|
||||||
sprintf(tmpstr,"UserData2: 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X",udata[0],udata[1],udata[2],udata[3]);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
case 2: /* user defined data-3 64 bit */
|
|
||||||
datalen=8;
|
|
||||||
m=8;
|
|
||||||
for(l=0;l<datalen;l++) {
|
|
||||||
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
|
|
||||||
}
|
|
||||||
sprintf(tmpstr," UserData3: 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X",udata[0],udata[1],udata[2],udata[3],udata[4],udata[5],udata[6],udata[7]);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
case 3: /* length indicator + user defined data-4 bit */
|
|
||||||
m=11; datalen=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
m=8; protoid=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
sprintf(tmpstr," UserData4: len:%i protoid:%2.2X(%s) ",datalen,protoid,get_sds_type(protoid));
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
/* SDS-TL header */
|
|
||||||
if (protoid&0x80) {
|
|
||||||
is_sdstl=1;
|
|
||||||
m=4; message_type=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
strcat(descr,"SDS-TL:[ MsgType:");
|
|
||||||
|
|
||||||
switch(message_type) {
|
|
||||||
case 0: /* SDS-TRANSFER page 1182 */
|
|
||||||
strcat(descr,"SDS-TRANSFER");
|
|
||||||
m=2; sdstl_delivery_report_request=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m; /* page 1186 */
|
|
||||||
m=1; sdstl_service_selection=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m; /* page 1189 1:to group*/
|
|
||||||
m=1; sdstl_storage_control=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m; /* page 1189 */
|
|
||||||
m=8; sdstl_message_reference=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
|
|
||||||
sprintf(tmpstr," MSG_REF:%i TO_GROUP:%i",sdstl_message_reference,sdstl_service_selection);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
if (sdstl_storage_control) {
|
|
||||||
/* Storage/forward control information is available */
|
|
||||||
m=5; sdstl_validity_period=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
m=3; sdstl_forw_address_type=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
|
|
||||||
sprintf(tmpstr," Validity_period:%i",sdstl_validity_period);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
switch(sdstl_forw_address_type) {
|
|
||||||
case 0: /* SNA */
|
|
||||||
m=8; sdstl_forw_address=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
sprintf(tmpstr," Forward_addr_SNA:%i",sdstl_forw_address);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
case 1: /* SSI */
|
|
||||||
m=24; sdstl_forw_address=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
sprintf(tmpstr," Forward_addr_SSI:%i",sdstl_forw_address);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
case 2: /* TETRA Subscriber Identity (TSI) */
|
|
||||||
m=24; sdstl_forw_address=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
m=24; sdstl_forw_address_ext=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
sprintf(tmpstr," Forward_addr_SSI:%i:EXT:%i",sdstl_forw_address,sdstl_forw_address_ext);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
case 3: /* External subscriber number */
|
|
||||||
m=8; sdstl_extnum_digits=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
strcat(descr," Forward_addr_EXT:");
|
|
||||||
l=sdstl_extnum_digits;
|
|
||||||
while(l) {
|
|
||||||
m=4; sdstl_extnum_digit=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
sprintf(tmpstr,"%c",'0'+sdstl_extnum_digit);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
l--;
|
|
||||||
}
|
|
||||||
if (sdstl_extnum_digits&0x1) {
|
|
||||||
/* odd number, eat dummy digit */
|
|
||||||
n=n+4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 7: /* no forward address */
|
|
||||||
strcat(descr," Forward_addr_none");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* hgw co to jest */
|
|
||||||
sprintf(tmpstr," Forward_addr_BAD:%i",sdstl_forw_address_type);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
return(1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1: /* SDS-REPORT */
|
|
||||||
strcat(descr,"SDS-REPORT");
|
|
||||||
n=n+12;
|
|
||||||
decode_sds=0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: /* SDS-ACK */
|
|
||||||
strcat(descr,"SDS-ACK ");
|
|
||||||
decode_sds=0;
|
|
||||||
|
|
||||||
n=n+12;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
decode_sds=0;
|
|
||||||
if (message_type&0x8) {
|
|
||||||
sprintf(tmpstr,"Defined_by_application_%i ",message_type);
|
|
||||||
} else {
|
|
||||||
sprintf(tmpstr,"Reserved_for_add_msg_types_%i ",message_type);
|
|
||||||
}
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
n=n+12;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(descr,"] ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datalen>2047) {
|
|
||||||
strcat(descr,"ERROR: SDS too short");
|
|
||||||
decode_sds=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t c;
|
|
||||||
if (decode_sds) {
|
|
||||||
switch (protoid) {
|
|
||||||
case TETRA_SDS_PROTO_SIMPLE_LOC:
|
|
||||||
sprintf(tmpstr,"SIMPLE_LOCATION_SYSTEM:[");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
decode_simplelocsystem(tmpstr2, sizeof(tmpstr2),bits+n,datalen);
|
|
||||||
strcat(descr,tmpstr2);
|
|
||||||
sprintf(tmpstr,"]\n");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TETRA_SDS_PROTO_LOCSYSTEM:
|
|
||||||
sprintf(tmpstr,"LOCATION_SYSTEM:[");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
decode_locsystem(tmpstr2, sizeof(tmpstr2),bits+n,datalen);
|
|
||||||
strcat(descr,tmpstr2);
|
|
||||||
sprintf(tmpstr,"]\n");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TETRA_SDS_PROTO_LIP:
|
|
||||||
sprintf(tmpstr,"LIP:[");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
decode_lip(tmpstr2, sizeof(tmpstr2),bits+n,datalen);
|
|
||||||
strcat(descr,tmpstr2);
|
|
||||||
sprintf(tmpstr,"]");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TETRA_SDS_PROTO_TXTMSG:
|
|
||||||
case TETRA_SDS_PROTO_SIMPLE_TXTMSG:
|
|
||||||
case TETRA_SDS_PROTO_SIMPLE_ITXTMSG:
|
|
||||||
case TETRA_SDS_PROTO_ITXTMSG:
|
|
||||||
m=1; reserved1=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
m=7; coding_scheme=bits_to_uint(bits+n, m); n=n+m; datalen=datalen-m;
|
|
||||||
sprintf(tmpstr," coding_scheme:%2.2x ",coding_scheme);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
sprintf(tmpstr,"DATA:[");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
/* dump text message */
|
|
||||||
switch(coding_scheme) {
|
|
||||||
case 0: /* 7-bit gsm encoding */
|
|
||||||
sprintf(tmpstr," *7bit* ");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
m=8;
|
|
||||||
l=0;
|
|
||||||
while((datalen>=m)&&(n<=len)) {
|
|
||||||
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
l++;
|
|
||||||
datalen=datalen-m;
|
|
||||||
}
|
|
||||||
/* TODO: maybe skip the first two bytes? i've never seen a 7-bit SDS in the wild --sq5bpf */
|
|
||||||
datalen=decode_pdu(tmpstr2,udata,l);
|
|
||||||
/* dump */
|
|
||||||
for(a=0;a<datalen;a++) {
|
|
||||||
if (isprint(tmpstr2[a])) {
|
|
||||||
sprintf(tmpstr,"%c",tmpstr2[a]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sprintf(tmpstr,"\\x%2.2X",tmpstr2[a]);
|
|
||||||
}
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
strcat(descr,"]");
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 0x1A: /* SO/IEC 10646-1 [22] UCS-2/UTF-16BE (16-bit) alphabet */
|
|
||||||
/* TODO: use iconv or whatever else
|
|
||||||
* for now we'll just use the 8-bit decoding function,
|
|
||||||
* every other bit will be written as \x00. ugly but readable --sq5bpf
|
|
||||||
*/
|
|
||||||
|
|
||||||
sprintf(tmpstr," *UTF16* ");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
default: /* 8-bit */
|
|
||||||
m=8;
|
|
||||||
l=0;
|
|
||||||
while((datalen>=m)&&(n<=len)) {
|
|
||||||
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
l++;
|
|
||||||
datalen=datalen-m;
|
|
||||||
}
|
|
||||||
/* TODO: the first two bytes are often garbage. either parse it or skip it
|
|
||||||
* i guess i'll have to read the etsi specifications better --sq5bpf */
|
|
||||||
|
|
||||||
for(a=0;a<l;a++) {
|
|
||||||
if (isprint(udata[a])) {
|
|
||||||
sprintf(tmpstr,"%c",udata[a]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sprintf(tmpstr,"\\x%2.2X",udata[a]);
|
|
||||||
}
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
strcat(descr,"]");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
sprintf(tmpstr,"DATA:[");
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
/* other message */
|
|
||||||
/* hexdump */
|
|
||||||
m=8;
|
|
||||||
l=0;
|
|
||||||
while((datalen>=m)&&(n<=len)) {
|
|
||||||
udata[l]=bits_to_uint(bits+n, m); n=n+m;
|
|
||||||
l++;
|
|
||||||
datalen=datalen-m;
|
|
||||||
|
|
||||||
}
|
|
||||||
/* dump */
|
|
||||||
for(a=0;a<l;a++) {
|
|
||||||
sprintf(tmpstr,"0x%2.2X ",udata[a]);
|
|
||||||
strcat(descr,tmpstr);
|
|
||||||
}
|
|
||||||
strcat(descr,"]");
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
printf("%s\n",descr);
|
|
||||||
sprintf(tmpstr2,"TETMON_begin FUNC:SDSDEC [%s] RX:%i TETMON_end",descr,tetra_hack_rxid);
|
|
||||||
sendto(tetra_hack_live_socket, (char *)&tmpstr2, strlen((char *)&tmpstr2)+1, 0, (struct sockaddr *)&tetra_hack_live_sockaddr, tetra_hack_socklen);
|
|
||||||
/* We'll just ignore these for now :)
|
|
||||||
* External subscriber number
|
|
||||||
* DM-MS address
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decode 18.5.17 Neighbour cell information for CA */
|
/* decode 18.5.17 Neighbour cell information for CA */
|
||||||
/* str 535, przyklad str 1294 */
|
/* str 535, przyklad str 1294 */
|
||||||
int parse_nci_ca( uint8_t *bits)
|
int parse_nci_ca( uint8_t *bits)
|
||||||
|
|
Loading…
Reference in New Issue