SMPP: Implement SMPP Osmocom Estensions on MO-SMS
An ESME can now be configured in the VTY to enable osmocom-extensions, which will add vendor-specific SMPP TLVs for RxLev/RxQual/ARFCN/IMEI and transmit power to the SMPP DELIVER-SM message type.
This commit is contained in:
parent
76afa16d04
commit
3f78600346
|
@ -21,7 +21,7 @@ AC_SEARCH_LIBS(crypt, crypt,
|
|||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.5.3.60)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.5.2)
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
|
||||
#ifdef BUILD_SMPP
|
||||
#include "smpp_smsc.h"
|
||||
extern int smpp_try_deliver(struct gsm_sms *sms);
|
||||
extern int smpp_try_deliver(struct gsm_sms *sms,
|
||||
struct gsm_subscriber_connection *conn);
|
||||
#endif
|
||||
|
||||
void *tall_gsms_ctx;
|
||||
|
@ -395,7 +396,7 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
|
|||
gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dst.addr);
|
||||
if (!gsms->receiver) {
|
||||
#ifdef BUILD_SMPP
|
||||
rc = smpp_try_deliver(gsms);
|
||||
rc = smpp_try_deliver(gsms, conn);
|
||||
if (rc == 1) {
|
||||
rc = 1; /* cause 1: unknown subscriber */
|
||||
osmo_counter_inc(conn->bts->network->stats.sms.no_receiver);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* OpenBSC SMPP 3.4 interface, SMSC-side implementation */
|
||||
|
||||
/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -33,6 +33,7 @@
|
|||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_11.h>
|
||||
#include <osmocom/gsm/protocol/smpp34_osmocom.h>
|
||||
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
@ -335,7 +336,80 @@ static int gsm_7bit_expand(char *text, const uint8_t *user_data, uint8_t septet_
|
|||
}
|
||||
|
||||
|
||||
static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms)
|
||||
/* FIXME: libsmpp34 helpers, they should be part of libsmpp34! */
|
||||
void append_tlv(tlv_t **req_tlv, uint16_t tag,
|
||||
const uint8_t *data, uint16_t len)
|
||||
{
|
||||
tlv_t tlv;
|
||||
|
||||
memset(&tlv, 0, sizeof(tlv));
|
||||
tlv.tag = tag;
|
||||
tlv.length = len;
|
||||
memcpy(tlv.value.octet, data, tlv.length);
|
||||
build_tlv(req_tlv, &tlv);
|
||||
}
|
||||
void append_tlv_u8(tlv_t **req_tlv, uint16_t tag, uint8_t val)
|
||||
{
|
||||
tlv_t tlv;
|
||||
|
||||
memset(&tlv, 0, sizeof(tlv));
|
||||
tlv.tag = tag;
|
||||
tlv.length = 1;
|
||||
tlv.value.val08 = val;
|
||||
build_tlv(req_tlv, &tlv);
|
||||
}
|
||||
void append_tlv_u16(tlv_t **req_tlv, uint16_t tag, uint16_t val)
|
||||
{
|
||||
tlv_t tlv;
|
||||
|
||||
memset(&tlv, 0, sizeof(tlv));
|
||||
tlv.tag = tag;
|
||||
tlv.length = 2;
|
||||
tlv.value.val16 = htons(val);
|
||||
build_tlv(req_tlv, &tlv);
|
||||
}
|
||||
|
||||
/* Append the Osmocom vendor-specific additional TLVs to a SMPP msg */
|
||||
static void append_osmo_tlvs(tlv_t **req_tlv, const struct gsm_lchan *lchan)
|
||||
{
|
||||
int idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
|
||||
lchan->meas_rep_idx, 1);
|
||||
const struct gsm_meas_rep *mr = &lchan->meas_rep[idx];
|
||||
const struct gsm_meas_rep_unidir *ul_meas = &mr->ul;
|
||||
const struct gsm_meas_rep_unidir *dl_meas = &mr->dl;
|
||||
|
||||
/* Osmocom vendor-specific SMPP34 extensions */
|
||||
append_tlv_u16(req_tlv, TLVID_osmo_arfcn, lchan->ts->trx->arfcn);
|
||||
if (mr->flags & MEAS_REP_F_MS_L1) {
|
||||
uint8_t ms_dbm;
|
||||
append_tlv_u8(req_tlv, TLVID_osmo_ta, mr->ms_l1.ta);
|
||||
ms_dbm = ms_pwr_dbm(lchan->ts->trx->bts->band, mr->ms_l1.pwr);
|
||||
append_tlv_u8(req_tlv, TLVID_osmo_ms_l1_txpwr, ms_dbm);
|
||||
} else if (mr->flags & MEAS_REP_F_MS_TO)
|
||||
append_tlv_u8(req_tlv, TLVID_osmo_ta, mr->ms_timing_offset);
|
||||
|
||||
append_tlv_u16(req_tlv, TLVID_osmo_rxlev_ul,
|
||||
rxlev2dbm(ul_meas->full.rx_lev));
|
||||
append_tlv_u8(req_tlv, TLVID_osmo_rxqual_ul, ul_meas->full.rx_qual);
|
||||
|
||||
if (mr->flags & MEAS_REP_F_DL_VALID) {
|
||||
append_tlv_u16(req_tlv, TLVID_osmo_rxlev_dl,
|
||||
rxlev2dbm(dl_meas->full.rx_lev));
|
||||
append_tlv_u8(req_tlv, TLVID_osmo_rxqual_dl,
|
||||
dl_meas->full.rx_qual);
|
||||
}
|
||||
|
||||
if (lchan->conn && lchan->conn->subscr) {
|
||||
struct gsm_subscriber *subscr = lchan->conn->subscr;
|
||||
size_t imei_len = strlen(subscr->equipment.imei);
|
||||
if (imei_len)
|
||||
append_tlv(req_tlv, TLVID_osmo_imei,
|
||||
(uint8_t *)subscr->equipment.imei, imei_len+1);
|
||||
}
|
||||
}
|
||||
|
||||
static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
|
||||
struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
struct deliver_sm_t deliver;
|
||||
uint8_t dcs;
|
||||
|
@ -405,12 +479,15 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms)
|
|||
memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
|
||||
}
|
||||
|
||||
if (esme->acl->osmocom_ext && conn && conn->lchan)
|
||||
append_osmo_tlvs(&deliver.tlv, conn->lchan);
|
||||
|
||||
return smpp_tx_deliver(esme, &deliver);
|
||||
}
|
||||
|
||||
static struct smsc *g_smsc;
|
||||
|
||||
int smpp_try_deliver(struct gsm_sms *sms)
|
||||
int smpp_try_deliver(struct gsm_sms *sms, struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
struct osmo_esme *esme;
|
||||
struct osmo_smpp_addr dst;
|
||||
|
@ -424,7 +501,7 @@ int smpp_try_deliver(struct gsm_sms *sms)
|
|||
if (!esme)
|
||||
return 1; /* unknown subscriber */
|
||||
|
||||
return deliver_to_esme(esme, sms);
|
||||
return deliver_to_esme(esme, sms, conn);
|
||||
}
|
||||
|
||||
struct smsc *smsc_from_vty(struct vty *v)
|
||||
|
|
|
@ -60,6 +60,7 @@ struct osmo_smpp_acl {
|
|||
char passwd[SMPP_PASSWD_LEN+1];
|
||||
int default_route;
|
||||
int deliver_src_imsi;
|
||||
int osmocom_ext;
|
||||
struct llist_head route_list;
|
||||
};
|
||||
|
||||
|
|
|
@ -339,6 +339,28 @@ DEFUN(cfg_no_esme_defaultroute, cfg_esme_no_defaultroute_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_esme_osmo_ext, cfg_esme_osmo_ext_cmd,
|
||||
"osmocom-extensions",
|
||||
"Enable the use of Osmocom SMPP Extensions for this ESME")
|
||||
{
|
||||
struct osmo_smpp_acl *acl = vty->index;
|
||||
|
||||
acl->osmocom_ext = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_esme_no_osmo_ext, cfg_esme_no_osmo_ext_cmd,
|
||||
"no osmocom-extensions", NO_STR
|
||||
"Disable the use of Osmocom SMPP Extensions for this ESME")
|
||||
{
|
||||
struct osmo_smpp_acl *acl = vty->index;
|
||||
|
||||
acl->osmocom_ext = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void dump_one_esme(struct vty *vty, struct osmo_esme *esme)
|
||||
{
|
||||
char host[128], serv[128];
|
||||
|
@ -395,6 +417,8 @@ static void config_write_esme_single(struct vty *vty, struct osmo_smpp_acl *acl)
|
|||
vty_out(vty, " default-route%s", VTY_NEWLINE);
|
||||
if (acl->deliver_src_imsi)
|
||||
vty_out(vty, " deliver-src-imsi%s", VTY_NEWLINE);
|
||||
if (acl->osmocom_ext)
|
||||
vty_out(vty, " osmocom-extensions%s", VTY_NEWLINE);
|
||||
|
||||
llist_for_each_entry(r, &acl->route_list, list)
|
||||
write_esme_route_single(vty, r);
|
||||
|
@ -431,6 +455,8 @@ int smpp_vty_init(void)
|
|||
install_element(SMPP_ESME_NODE, &cfg_esme_no_route_pfx_cmd);
|
||||
install_element(SMPP_ESME_NODE, &cfg_esme_defaultroute_cmd);
|
||||
install_element(SMPP_ESME_NODE, &cfg_esme_no_defaultroute_cmd);
|
||||
install_element(SMPP_ESME_NODE, &cfg_esme_osmo_ext_cmd);
|
||||
install_element(SMPP_ESME_NODE, &cfg_esme_no_osmo_ext_cmd);
|
||||
install_element(SMPP_ESME_NODE, &ournode_exit_cmd);
|
||||
|
||||
install_element_ve(&show_esme_cmd);
|
||||
|
|
Loading…
Reference in New Issue