From 3f786003464fe0ff32eea263cb8b8cb4c3e981ea Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 13 Mar 2013 15:29:27 +0100 Subject: 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. --- openbsc/configure.ac | 2 +- openbsc/src/libmsc/gsm_04_11.c | 5 ++- openbsc/src/libmsc/smpp_openbsc.c | 85 +++++++++++++++++++++++++++++++++++++-- openbsc/src/libmsc/smpp_smsc.h | 1 + openbsc/src/libmsc/smpp_vty.c | 26 ++++++++++++ 5 files changed, 112 insertions(+), 7 deletions(-) diff --git a/openbsc/configure.ac b/openbsc/configure.ac index 7004f96bd..cdefcaf04 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -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) diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index 9e00bdac7..2fc250bc8 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -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); diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c index 585f93976..2f410e915 100644 --- a/openbsc/src/libmsc/smpp_openbsc.c +++ b/openbsc/src/libmsc/smpp_openbsc.c @@ -1,6 +1,6 @@ /* OpenBSC SMPP 3.4 interface, SMSC-side implementation */ -/* (C) 2012 by Harald Welte +/* (C) 2012-2013 by Harald Welte * * 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 #include #include +#include #include #include @@ -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) diff --git a/openbsc/src/libmsc/smpp_smsc.h b/openbsc/src/libmsc/smpp_smsc.h index be72a0c7c..e72f81fef 100644 --- a/openbsc/src/libmsc/smpp_smsc.h +++ b/openbsc/src/libmsc/smpp_smsc.h @@ -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; }; diff --git a/openbsc/src/libmsc/smpp_vty.c b/openbsc/src/libmsc/smpp_vty.c index 96447bf37..4c64a3cf1 100644 --- a/openbsc/src/libmsc/smpp_vty.c +++ b/openbsc/src/libmsc/smpp_vty.c @@ -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); -- cgit v1.2.3