aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmsc/smpp_openbsc.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-11-23 19:02:37 +0100
committerHarald Welte <laforge@gnumonks.org>2012-11-24 11:07:30 +0100
commite07b6a77e51f19b45d3ca0a7b3b4014ffeb40859 (patch)
treea1d5d5d35d5f7f11d7e029d569fa4059459a82fe /openbsc/src/libmsc/smpp_openbsc.c
parent338e3b3b4bf4947db817a57e0bf1838400e690ca (diff)
SMPP: Implement support for MO SMS
Each ESME can have a number of prefix-matching routes, or it can be a 'default route' to whcih all otherwise unknown SMS destinations are routed.
Diffstat (limited to 'openbsc/src/libmsc/smpp_openbsc.c')
-rw-r--r--openbsc/src/libmsc/smpp_openbsc.c93
1 files changed, 91 insertions, 2 deletions
diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c
index d8dde2993..b3b8d3697 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -66,7 +66,7 @@ static struct gsm_subscriber *subscr_by_dst(struct gsm_network *net,
}
/*! \brief find a TLV with given tag in list of libsmpp34 TLVs */
-struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag)
+static struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag)
{
struct tlv_t *t;
@@ -217,7 +217,6 @@ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
static int smpp_sms_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
- struct gsm_network *network = handler_data;
struct sms_signal_data *sig_sms = signal_data;
struct gsm_sms *sms = sig_sms->sms;
int rc = 0;
@@ -288,8 +287,98 @@ static int smpp_subscr_cb(unsigned int subsys, unsigned int signal,
return 0;
}
+static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms)
+{
+ struct deliver_sm_t deliver;
+ uint8_t dcs;
+
+ memset(&deliver, 0, sizeof(deliver));
+ deliver.command_length = 0;
+ deliver.command_id = DELIVER_SM;
+ deliver.command_status = ESME_ROK;
+
+ strcpy((char *)deliver.service_type, "CMT");
+ if (esme->acl && esme->acl->deliver_src_imsi) {
+ deliver.source_addr_ton = TON_Subscriber_Number;
+ deliver.source_addr_npi = NPI_Land_Mobile_E212;
+ snprintf((char *)deliver.source_addr,
+ sizeof(deliver.source_addr), "%s",
+ sms->sender->imsi);
+ } else {
+ deliver.source_addr_ton = TON_Network_Specific;
+ deliver.source_addr_npi = NPI_ISDN_E163_E164;
+ snprintf((char *)deliver.source_addr,
+ sizeof(deliver.source_addr), "%s",
+ sms->sender->extension);
+ }
+
+ deliver.dest_addr_ton = sms->destination.ton;
+ deliver.dest_addr_npi = sms->destination.npi;
+ memcpy(deliver.destination_addr, sms->destination.addr,
+ sizeof(deliver.destination_addr));
+
+ deliver.esm_class = 1; /* datagram mode */
+ if (sms->ud_hdr_ind)
+ deliver.esm_class |= 0x40;
+ if (sms->reply_path_req)
+ deliver.esm_class |= 0x80;
+
+ deliver.protocol_id = sms->protocol_id;
+ deliver.priority_flag = 0;
+ deliver.registered_delivery = 0;
+
+ dcs = sms->data_coding_scheme;
+ if (dcs == GSM338_DCS_1111_7BIT ||
+ ((dcs & 0xE0000000) == 0 && (dcs & 0xC) == 0)) {
+ uint8_t *src = sms->user_data;
+ uint8_t *dst = deliver.short_message;
+ uint8_t src_byte_len = sms->user_data_len;
+
+ /* SMPP has this strange notion of putting 7bit SMS in
+ * an octet-aligned mode */
+ deliver.data_coding = 0x01;
+ if (sms->ud_hdr_ind) {
+ uint8_t udh_len = sms->user_data[0];
+ src += udh_len + 1;
+ dst += udh_len + 1;
+ src_byte_len -= udh_len + 1;
+ memcpy(dst, sms->user_data, udh_len + 1);
+ deliver.sm_length = udh_len + 1;
+ }
+ deliver.sm_length += gsm_7bit_decode((char *)dst, src, src_byte_len);
+ } else if (dcs == GSM338_DCS_1111_8BIT_DATA ||
+ ((dcs & 0xE0000000) == 0 && (dcs & 0xC) == 4)) {
+ deliver.data_coding = 0x02;
+ deliver.sm_length = sms->user_data_len;
+ memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
+ } else if ((dcs & 0xE0000000) == 0 && (dcs & 0xC) == 8) {
+ deliver.data_coding = 0x08; /* UCS-2 */
+ deliver.sm_length = sms->user_data_len;
+ memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
+ }
+
+ return smpp_tx_deliver(esme, &deliver);
+}
+
static struct smsc *g_smsc;
+int smpp_try_deliver(struct gsm_sms *sms)
+{
+ struct osmo_esme *esme;
+ struct osmo_smpp_addr dst;
+
+ memset(&dst, 0, sizeof(dst));
+ dst.ton = sms->destination.ton;
+ dst.npi = sms->destination.npi;
+ memcpy(dst.addr, sms->destination.addr, sizeof(dst.addr));
+
+ esme = smpp_route(g_smsc, &dst);
+ if (!esme)
+ return 1; /* unknown subscriber */
+
+ return deliver_to_esme(esme, sms);
+}
+
struct smsc *smsc_from_vty(struct vty *v)
{
/* FIXME: this is ugly */