mirror of https://gerrit.osmocom.org/libosmocore
import gsm48 utility functions from OpenBSC
* gsm48_generate_lai() gsm48_generate_mid_from_tmsi() gsm48_generate_mid_from_imsi() * gsm48_cc_msg_names[]
This commit is contained in:
parent
a73e2f9acb
commit
61e2bfc5f4
|
@ -1,9 +1,16 @@
|
||||||
#ifndef _OSMOCORE_GSM48_H
|
#ifndef _OSMOCORE_GSM48_H
|
||||||
|
|
||||||
#include <osmocore/tlv.h>
|
#include <osmocore/tlv.h>
|
||||||
|
#include <osmocore/protocol/gsm_04_08.h>
|
||||||
|
|
||||||
extern const struct tlv_definition gsm48_att_tlvdef;
|
extern const struct tlv_definition gsm48_att_tlvdef;
|
||||||
extern const char *cc_state_names[];
|
extern const char *cc_state_names[32];
|
||||||
|
const char *gsm48_cc_msg_names[0x40];
|
||||||
const char *rr_cause_name(uint8_t cause);
|
const char *rr_cause_name(uint8_t cause);
|
||||||
|
|
||||||
|
void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
|
||||||
|
uint16_t mnc, uint16_t lac);
|
||||||
|
int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
|
||||||
|
int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
142
src/gsm48.c
142
src/gsm48.c
|
@ -26,6 +26,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <osmocore/utils.h>
|
#include <osmocore/utils.h>
|
||||||
#include <osmocore/tlv.h>
|
#include <osmocore/tlv.h>
|
||||||
#include <osmocore/gsm48.h>
|
#include <osmocore/gsm48.h>
|
||||||
|
@ -93,7 +95,7 @@ static const char *rr_cause_names[] = {
|
||||||
[GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
|
[GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *cc_state_names[] = {
|
const char *cc_state_names[32] = {
|
||||||
"NULL",
|
"NULL",
|
||||||
"INITIATED",
|
"INITIATED",
|
||||||
"illegal state 2",
|
"illegal state 2",
|
||||||
|
@ -128,6 +130,73 @@ const char *cc_state_names[] = {
|
||||||
"illegal state 31",
|
"illegal state 31",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *gsm48_cc_msg_names[0x40] = {
|
||||||
|
"unknown 0x00",
|
||||||
|
"ALERTING",
|
||||||
|
"CALL_PROC",
|
||||||
|
"PROGRESS",
|
||||||
|
"ESTAB",
|
||||||
|
"SETUP",
|
||||||
|
"ESTAB_CONF",
|
||||||
|
"CONNECT",
|
||||||
|
"CALL_CONF",
|
||||||
|
"START_CC",
|
||||||
|
"unknown 0x0a",
|
||||||
|
"RECALL",
|
||||||
|
"unknown 0x0c",
|
||||||
|
"unknown 0x0d",
|
||||||
|
"EMERG_SETUP",
|
||||||
|
"CONNECT_ACK",
|
||||||
|
"USER_INFO",
|
||||||
|
"unknown 0x11",
|
||||||
|
"unknown 0x12",
|
||||||
|
"MODIFY_REJECT",
|
||||||
|
"unknown 0x14",
|
||||||
|
"unknown 0x15",
|
||||||
|
"unknown 0x16",
|
||||||
|
"MODIFY",
|
||||||
|
"HOLD",
|
||||||
|
"HOLD_ACK",
|
||||||
|
"HOLD_REJ",
|
||||||
|
"unknown 0x1b",
|
||||||
|
"RETR",
|
||||||
|
"RETR_ACK",
|
||||||
|
"RETR_REJ",
|
||||||
|
"MODIFY_COMPL",
|
||||||
|
"unknown 0x20",
|
||||||
|
"unknown 0x21",
|
||||||
|
"unknown 0x22",
|
||||||
|
"unknown 0x23",
|
||||||
|
"unknown 0x24",
|
||||||
|
"DISCONNECT",
|
||||||
|
"unknown 0x26",
|
||||||
|
"unknown 0x27",
|
||||||
|
"unknown 0x28",
|
||||||
|
"unknown 0x29",
|
||||||
|
"RELEASE_COMPL",
|
||||||
|
"unknown 0x2b",
|
||||||
|
"unknown 0x2c",
|
||||||
|
"RELEASE",
|
||||||
|
"unknown 0x2e",
|
||||||
|
"unknown 0x2f",
|
||||||
|
"unknown 0x30",
|
||||||
|
"STOP_DTMF",
|
||||||
|
"STOP_DTMF_ACK",
|
||||||
|
"unknown 0x33",
|
||||||
|
"STATUS_ENQ",
|
||||||
|
"START_DTMF",
|
||||||
|
"START_DTMF_ACK",
|
||||||
|
"START_DTMF_REJ",
|
||||||
|
"unknown 0x38",
|
||||||
|
"CONG_CTRL",
|
||||||
|
"FACILITY",
|
||||||
|
"unknown 0x3b",
|
||||||
|
"STATUS",
|
||||||
|
"unknown 0x3d",
|
||||||
|
"NOTIFY",
|
||||||
|
"unknown 0x3f",
|
||||||
|
};
|
||||||
|
|
||||||
static char strbuf[64];
|
static char strbuf[64];
|
||||||
|
|
||||||
const char *rr_cause_name(uint8_t cause)
|
const char *rr_cause_name(uint8_t cause)
|
||||||
|
@ -140,4 +209,75 @@ const char *rr_cause_name(uint8_t cause)
|
||||||
return strbuf;
|
return strbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void to_bcd(uint8_t *bcd, uint16_t val)
|
||||||
|
{
|
||||||
|
bcd[2] = val % 10;
|
||||||
|
val = val / 10;
|
||||||
|
bcd[1] = val % 10;
|
||||||
|
val = val / 10;
|
||||||
|
bcd[0] = val % 10;
|
||||||
|
val = val / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
|
||||||
|
uint16_t mnc, uint16_t lac)
|
||||||
|
{
|
||||||
|
uint8_t bcd[3];
|
||||||
|
|
||||||
|
to_bcd(bcd, mcc);
|
||||||
|
lai48->digits[0] = bcd[0] | (bcd[1] << 4);
|
||||||
|
lai48->digits[1] = bcd[2];
|
||||||
|
|
||||||
|
to_bcd(bcd, mnc);
|
||||||
|
/* FIXME: do we need three-digit MNC? See Table 10.5.3 */
|
||||||
|
#if 0
|
||||||
|
lai48->digits[1] |= bcd[2] << 4;
|
||||||
|
lai48->digits[2] = bcd[0] | (bcd[1] << 4);
|
||||||
|
#else
|
||||||
|
lai48->digits[1] |= 0xf << 4;
|
||||||
|
lai48->digits[2] = bcd[1] | (bcd[2] << 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lai48->lac = htons(lac);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi)
|
||||||
|
{
|
||||||
|
uint32_t *tptr = (uint32_t *) &buf[3];
|
||||||
|
|
||||||
|
buf[0] = GSM48_IE_MOBILE_ID;
|
||||||
|
buf[1] = GSM48_TMSI_LEN;
|
||||||
|
buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
|
||||||
|
*tptr = htonl(tmsi);
|
||||||
|
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi)
|
||||||
|
{
|
||||||
|
unsigned int length = strlen(imsi), i, off = 0;
|
||||||
|
uint8_t odd = (length & 0x1) == 1;
|
||||||
|
|
||||||
|
buf[0] = GSM48_IE_MOBILE_ID;
|
||||||
|
buf[2] = char2bcd(imsi[0]) << 4 | GSM_MI_TYPE_IMSI | (odd << 3);
|
||||||
|
|
||||||
|
/* if the length is even we will fill half of the last octet */
|
||||||
|
if (odd)
|
||||||
|
buf[1] = (length + 1) >> 1;
|
||||||
|
else
|
||||||
|
buf[1] = (length + 2) >> 1;
|
||||||
|
|
||||||
|
for (i = 1; i < buf[1]; ++i) {
|
||||||
|
uint8_t lower, upper;
|
||||||
|
|
||||||
|
lower = char2bcd(imsi[++off]);
|
||||||
|
if (!odd && off + 1 == length)
|
||||||
|
upper = 0x0f;
|
||||||
|
else
|
||||||
|
upper = char2bcd(imsi[++off]) & 0x0f;
|
||||||
|
|
||||||
|
buf[2 + i] = (upper << 4) | lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2 + buf[1];
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue