mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-01 20:43:47 +00:00
Merge branch 'zecke/features/sgsn-hlr-number'
Store the hlr-Number for purgeMS and CDR handling
This commit is contained in:
@@ -120,6 +120,7 @@ Network peer -> SGSN
|
|||||||
Message type 4.2.1 M V 1
|
Message type 4.2.1 M V 1
|
||||||
01 IMSI 4.2.9 M TLV 2-10
|
01 IMSI 4.2.9 M TLV 2-10
|
||||||
08 MSISDN 4.2.10 O TLV 0-9
|
08 MSISDN 4.2.10 O TLV 0-9
|
||||||
|
09 HLR Number 4.2.12 O TLV 0-9
|
||||||
04 PDP info complete 4.2.8 O TLV 2
|
04 PDP info complete 4.2.8 O TLV 2
|
||||||
05 PDP info 4.2.3 1-10 TLV
|
05 PDP info 4.2.3 1-10 TLV
|
||||||
|
|
||||||
@@ -149,6 +150,7 @@ SGSN -> Network peer
|
|||||||
IEI Info Element Type Pres. Format Length
|
IEI Info Element Type Pres. Format Length
|
||||||
Message type 4.2.1 M V 1
|
Message type 4.2.1 M V 1
|
||||||
01 IMSI 4.2.9 M TLV 2-10
|
01 IMSI 4.2.9 M TLV 2-10
|
||||||
|
09 HLR Number 4.2.12 M TLV 0-9
|
||||||
|
|
||||||
3.2.10. Purge MS Error
|
3.2.10. Purge MS Error
|
||||||
|
|
||||||
@@ -357,6 +359,7 @@ IEI that shall be used for the encoding.
|
|||||||
| 0x06 Cancel type 4.2.6 |
|
| 0x06 Cancel type 4.2.6 |
|
||||||
| 0x07 Freeze P-TMSI 4.2.8 |
|
| 0x07 Freeze P-TMSI 4.2.8 |
|
||||||
| 0x08 MSISDN ISDN-AddressString/octet, 4.2.10 |
|
| 0x08 MSISDN ISDN-AddressString/octet, 4.2.10 |
|
||||||
|
| 0x09 HLR Number 4.2.12 |
|
||||||
| 0x10 PDP context id big endian int |
|
| 0x10 PDP context id big endian int |
|
||||||
| 0x11 PDP type 4.2.4 |
|
| 0x11 PDP type 4.2.4 |
|
||||||
| 0x12 APN 04.08, 10.5.6.1 |
|
| 0x12 APN 04.08, 10.5.6.1 |
|
||||||
@@ -442,3 +445,24 @@ Priority and the reset are encoded as octets 3-N of 24.008.
|
|||||||
+-----------------------------------------------------+
|
+-----------------------------------------------------+
|
||||||
: : :
|
: : :
|
||||||
+-----------------------------------------------------+
|
+-----------------------------------------------------+
|
||||||
|
|
||||||
|
4.2.12. HLR Number encoded as GSM 09.02 ISDN-AddressString
|
||||||
|
|
||||||
|
The HLR Number is encoded as an ISDN-AddressString in GSM 09.02. It
|
||||||
|
will be stored by the SGSN can be used by the CDR module to keep a
|
||||||
|
record.
|
||||||
|
|
||||||
|
8 7 6 5 4 3 2 1
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
| | IEI | octet 1
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
| Length of IE contents | octet 2
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
| ext | Type of num | Numbering plan | octet 2
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
| Number digit 2 | Number digit 1 | octet 3
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
| Number digit 4 | Number digit 3 | octet 4
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
: : :
|
||||||
|
+-----------------------------------------------------+
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ enum gprs_gsup_iei {
|
|||||||
GPRS_GSUP_CANCEL_TYPE_IE = 0x06,
|
GPRS_GSUP_CANCEL_TYPE_IE = 0x06,
|
||||||
GPRS_GSUP_FREEZE_PTMSI_IE = 0x07,
|
GPRS_GSUP_FREEZE_PTMSI_IE = 0x07,
|
||||||
GPRS_GSUP_MSISDN_IE = 0x08,
|
GPRS_GSUP_MSISDN_IE = 0x08,
|
||||||
|
GPRS_GSUP_HLR_NUMBER_IE = 0x09,
|
||||||
GPRS_GSUP_PDP_CONTEXT_ID_IE = 0x10,
|
GPRS_GSUP_PDP_CONTEXT_ID_IE = 0x10,
|
||||||
GPRS_GSUP_PDP_TYPE_IE = 0x11,
|
GPRS_GSUP_PDP_TYPE_IE = 0x11,
|
||||||
GPRS_GSUP_ACCESS_POINT_NAME_IE = 0x12,
|
GPRS_GSUP_ACCESS_POINT_NAME_IE = 0x12,
|
||||||
@@ -109,6 +110,8 @@ struct gprs_gsup_message {
|
|||||||
size_t num_pdp_infos;
|
size_t num_pdp_infos;
|
||||||
const uint8_t *msisdn_enc;
|
const uint8_t *msisdn_enc;
|
||||||
size_t msisdn_enc_len;
|
size_t msisdn_enc_len;
|
||||||
|
const uint8_t *hlr_enc;
|
||||||
|
size_t hlr_enc_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
int gprs_gsup_decode(const uint8_t *data, size_t data_len,
|
int gprs_gsup_decode(const uint8_t *data, size_t data_len,
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ struct sgsn_mm_ctx {
|
|||||||
enum sgsn_auth_state auth_state;
|
enum sgsn_auth_state auth_state;
|
||||||
int is_authenticated;
|
int is_authenticated;
|
||||||
|
|
||||||
|
/* the string representation of the current hlr */
|
||||||
|
char hlr[GSM_EXTENSION_LENGTH];
|
||||||
|
|
||||||
struct gsm_subscriber *subscr;
|
struct gsm_subscriber *subscr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -312,6 +315,9 @@ struct sgsn_subscriber_data {
|
|||||||
|
|
||||||
uint8_t msisdn[9];
|
uint8_t msisdn[9];
|
||||||
size_t msisdn_len;
|
size_t msisdn_len;
|
||||||
|
|
||||||
|
uint8_t hlr[9];
|
||||||
|
size_t hlr_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SGSN_ERROR_CAUSE_NONE (-1)
|
#define SGSN_ERROR_CAUSE_NONE (-1)
|
||||||
|
|||||||
@@ -578,6 +578,43 @@ static void extract_subscr_msisdn(struct sgsn_mm_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void extract_subscr_hlr(struct sgsn_mm_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct gsm_mncc_number called;
|
||||||
|
uint8_t hlr_number[sizeof(ctx->subscr->sgsn_data->hlr) + 1];
|
||||||
|
|
||||||
|
if (!ctx->subscr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctx->subscr->sgsn_data->hlr_len < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* prepare the data for the decoder */
|
||||||
|
memset(&called, 0, sizeof(called));
|
||||||
|
hlr_number[0] = ctx->subscr->sgsn_data->hlr_len;
|
||||||
|
memcpy(&hlr_number[1], ctx->subscr->sgsn_data->hlr,
|
||||||
|
ctx->subscr->sgsn_data->hlr_len);
|
||||||
|
|
||||||
|
/* decode the string now */
|
||||||
|
gsm48_decode_called(&called, hlr_number);
|
||||||
|
|
||||||
|
if (called.plan != 1) {
|
||||||
|
LOGMMCTXP(LOGL_ERROR, ctx,
|
||||||
|
"Numbering plan(%d) not allowed\n",
|
||||||
|
called.plan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (called.type != 1) {
|
||||||
|
LOGMMCTXP(LOGL_ERROR, ctx,
|
||||||
|
"Numbering type(%d) not allowed\n",
|
||||||
|
called.type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(&ctx->hlr[0], called.number, sizeof(ctx->hlr) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if we can already authorize a subscriber */
|
/* Check if we can already authorize a subscriber */
|
||||||
static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
|
static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
|
||||||
{
|
{
|
||||||
@@ -643,6 +680,7 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
|
|||||||
case GSM48_MT_GMM_ATTACH_REQ:
|
case GSM48_MT_GMM_ATTACH_REQ:
|
||||||
|
|
||||||
extract_subscr_msisdn(ctx);
|
extract_subscr_msisdn(ctx);
|
||||||
|
extract_subscr_hlr(ctx);
|
||||||
#ifdef PTMSI_ALLOC
|
#ifdef PTMSI_ALLOC
|
||||||
/* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
|
/* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
|
||||||
mmctx_timer_start(ctx, 3350, GSM0408_T3350_SECS);
|
mmctx_timer_start(ctx, 3350, GSM0408_T3350_SECS);
|
||||||
|
|||||||
@@ -303,6 +303,11 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len,
|
|||||||
gsup_msg->msisdn_enc_len = value_len;
|
gsup_msg->msisdn_enc_len = value_len;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GPRS_GSUP_HLR_NUMBER_IE:
|
||||||
|
gsup_msg->hlr_enc = value;
|
||||||
|
gsup_msg->hlr_enc_len = value_len;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOGP(DGPRS, LOGL_NOTICE,
|
LOGP(DGPRS, LOGL_NOTICE,
|
||||||
"GSUP IE type %d unknown\n", iei);
|
"GSUP IE type %d unknown\n", iei);
|
||||||
@@ -394,6 +399,9 @@ void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg
|
|||||||
if (gsup_msg->msisdn_enc)
|
if (gsup_msg->msisdn_enc)
|
||||||
msgb_tlv_put(msg, GPRS_GSUP_MSISDN_IE,
|
msgb_tlv_put(msg, GPRS_GSUP_MSISDN_IE,
|
||||||
gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc);
|
gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc);
|
||||||
|
if (gsup_msg->hlr_enc)
|
||||||
|
msgb_tlv_put(msg, GPRS_GSUP_HLR_NUMBER_IE,
|
||||||
|
gsup_msg->hlr_enc_len, gsup_msg->hlr_enc);
|
||||||
|
|
||||||
if ((u8 = gsup_msg->cause))
|
if ((u8 = gsup_msg->cause))
|
||||||
msgb_tlv_put(msg, GPRS_GSUP_CAUSE_IE, sizeof(u8), &u8);
|
msgb_tlv_put(msg, GPRS_GSUP_CAUSE_IE, sizeof(u8), &u8);
|
||||||
|
|||||||
@@ -276,6 +276,18 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gsup_msg->hlr_enc) {
|
||||||
|
if (gsup_msg->hlr_enc_len > sizeof(sdata->hlr)) {
|
||||||
|
LOGP(DGPRS, LOGL_ERROR, "HLR-Number too long (%zu)\n",
|
||||||
|
gsup_msg->hlr_enc_len);
|
||||||
|
sdata->hlr_len = 0;
|
||||||
|
} else {
|
||||||
|
memcpy(sdata->hlr, gsup_msg->hlr_enc,
|
||||||
|
gsup_msg->hlr_enc_len);
|
||||||
|
sdata->hlr_len = gsup_msg->hlr_enc_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (gsup_msg->pdp_info_compl) {
|
if (gsup_msg->pdp_info_compl) {
|
||||||
rc = gprs_subscr_pdp_data_clear(subscr);
|
rc = gprs_subscr_pdp_data_clear(subscr);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
@@ -666,11 +678,17 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
|
|||||||
|
|
||||||
int gprs_subscr_purge(struct gsm_subscriber *subscr)
|
int gprs_subscr_purge(struct gsm_subscriber *subscr)
|
||||||
{
|
{
|
||||||
|
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
|
||||||
struct gprs_gsup_message gsup_msg = {0};
|
struct gprs_gsup_message gsup_msg = {0};
|
||||||
|
|
||||||
LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
|
LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
|
||||||
|
|
||||||
gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST;
|
gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST;
|
||||||
|
|
||||||
|
/* Provide the HLR number in case it is known */
|
||||||
|
gsup_msg.hlr_enc_len = sdata->hlr_len;
|
||||||
|
gsup_msg.hlr_enc = sdata->hlr;
|
||||||
|
|
||||||
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
|
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ static void maybe_print_header(FILE *cdr_file)
|
|||||||
if (ftell(cdr_file) != 0)
|
if (ftell(cdr_file) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(cdr_file, "timestamp,imsi,imei,msisdn,cell_id,lac,event,pdp_duration,ggsn_addr,sgsn_addr,apni,eua_addr,vol_in,vol_out,charging_id\n");
|
fprintf(cdr_file, "timestamp,imsi,imei,msisdn,cell_id,lac,hlr,event,pdp_duration,ggsn_addr,sgsn_addr,apni,eua_addr,vol_in,vol_out,charging_id\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cdr_log_mm(struct sgsn_instance *inst, const char *ev,
|
static void cdr_log_mm(struct sgsn_instance *inst, const char *ev,
|
||||||
@@ -87,7 +87,7 @@ static void cdr_log_mm(struct sgsn_instance *inst, const char *ev,
|
|||||||
maybe_print_header(cdr_file);
|
maybe_print_header(cdr_file);
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
gmtime_r(&tv.tv_sec, &tm);
|
gmtime_r(&tv.tv_sec, &tm);
|
||||||
fprintf(cdr_file, "%04d%02d%02d%02d%02d%02d%03d,%s,%s,%s,%d,%d,%s\n",
|
fprintf(cdr_file, "%04d%02d%02d%02d%02d%02d%03d,%s,%s,%s,%d,%d,%s,%s\n",
|
||||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||||
(int)(tv.tv_usec / 1000),
|
(int)(tv.tv_usec / 1000),
|
||||||
@@ -96,6 +96,7 @@ static void cdr_log_mm(struct sgsn_instance *inst, const char *ev,
|
|||||||
mmctx->msisdn,
|
mmctx->msisdn,
|
||||||
mmctx->cell_id,
|
mmctx->cell_id,
|
||||||
mmctx->ra.lac,
|
mmctx->ra.lac,
|
||||||
|
mmctx->hlr,
|
||||||
ev);
|
ev);
|
||||||
|
|
||||||
fclose(cdr_file);
|
fclose(cdr_file);
|
||||||
@@ -171,7 +172,7 @@ static void cdr_log_pdp(struct sgsn_instance *inst, const char *ev,
|
|||||||
duration = tp.tv_sec - pdp->cdr_start.tv_sec;
|
duration = tp.tv_sec - pdp->cdr_start.tv_sec;
|
||||||
|
|
||||||
fprintf(cdr_file,
|
fprintf(cdr_file,
|
||||||
"%04d%02d%02d%02d%02d%02d%03d,%s,%s,%s,%d,%d,%s,%ld,%s,%s,%s,%s,%" PRIu64 ",%" PRIu64 ",%u\n",
|
"%04d%02d%02d%02d%02d%02d%03d,%s,%s,%s,%d,%d,%s,%s,%ld,%s,%s,%s,%s,%" PRIu64 ",%" PRIu64 ",%u\n",
|
||||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||||
(int)(tv.tv_usec / 1000),
|
(int)(tv.tv_usec / 1000),
|
||||||
@@ -180,6 +181,7 @@ static void cdr_log_pdp(struct sgsn_instance *inst, const char *ev,
|
|||||||
pdp->mm ? pdp->mm->msisdn : "N/A",
|
pdp->mm ? pdp->mm->msisdn : "N/A",
|
||||||
pdp->mm ? pdp->mm->cell_id : -1,
|
pdp->mm ? pdp->mm->cell_id : -1,
|
||||||
pdp->mm ? pdp->mm->ra.lac : -1,
|
pdp->mm ? pdp->mm->ra.lac : -1,
|
||||||
|
pdp->mm ? pdp->mm->hlr : "N/A",
|
||||||
ev,
|
ev,
|
||||||
(unsigned long ) duration,
|
(unsigned long ) duration,
|
||||||
ggsn_addr,
|
ggsn_addr,
|
||||||
|
|||||||
@@ -315,8 +315,8 @@ static void vty_dump_mmctx(struct vty *vty, const char *pfx,
|
|||||||
{
|
{
|
||||||
vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
|
vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
|
||||||
pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
|
pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
|
||||||
vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s", pfx, mm->msisdn,
|
vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
|
||||||
mm->tlli, VTY_NEWLINE);
|
pfx, mm->msisdn, mm->tlli, mm->hlr, VTY_NEWLINE);
|
||||||
vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
|
vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
|
||||||
"Cell ID: %u%s", pfx,
|
"Cell ID: %u%s", pfx,
|
||||||
get_value_string(gprs_mm_st_strs, mm->mm_state),
|
get_value_string(gprs_mm_st_strs, mm->mm_state),
|
||||||
|
|||||||
@@ -445,6 +445,8 @@ static void test_gsup_messages_dec_enc(void)
|
|||||||
TEST_IMSI_IE,
|
TEST_IMSI_IE,
|
||||||
0x08, 0x07, /* MSISDN of the subscriber */
|
0x08, 0x07, /* MSISDN of the subscriber */
|
||||||
0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43,
|
0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43,
|
||||||
|
0x09, 0x07, /* HLR-Number of the subscriber */
|
||||||
|
0x91, 0x83, 0x52, 0x38, 0x48, 0x83, 0x93,
|
||||||
0x04, 0x00, /* PDP info complete */
|
0x04, 0x00, /* PDP info complete */
|
||||||
0x05, 0x15,
|
0x05, 0x15,
|
||||||
0x10, 0x01, 0x01,
|
0x10, 0x01, 0x01,
|
||||||
|
|||||||
@@ -1155,6 +1155,8 @@ int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
|
|||||||
0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
|
0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
|
||||||
0x08, 0x07, /* MSISDN 49166213323 encoded */
|
0x08, 0x07, /* MSISDN 49166213323 encoded */
|
||||||
0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
|
0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
|
||||||
|
0x09, 0x07, /* MSISDN 38166213323 encoded */
|
||||||
|
0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
|
||||||
};
|
};
|
||||||
|
|
||||||
OSMO_ASSERT(!mmctx || mmctx->subscr);
|
OSMO_ASSERT(!mmctx || mmctx->subscr);
|
||||||
|
|||||||
Reference in New Issue
Block a user