2 * Code based on work of:
3 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
4 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
8 * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <osmocom/core/msgb.h>
35 #include <osmocom/bb/common/logging.h>
36 #include <osmocom/bb/common/osmocom_data.h>
37 #include <osmocom/bb/mobile/mncc.h>
38 #include <osmocom/bb/mobile/transaction.h>
39 #include <osmocom/bb/mobile/gsm411_sms.h>
40 #include <osmocom/gsm/gsm0411_utils.h>
41 #include <osmocom/core/talloc.h>
42 #include <osmocom/bb/mobile/vty.h>
43 #include <osmocom/bb/mobile/primitives.h>
48 static uint32_t new_callref
= 0x40000001;
50 static int gsm411_rl_recv(struct gsm411_smr_inst
*inst
, int msg_type
,
52 static int gsm411_mn_recv(struct gsm411_smc_inst
*inst
, int msg_type
,
54 static int gsm411_mm_send(struct gsm411_smc_inst
*inst
, int msg_type
,
55 struct msgb
*msg
, int cp_msg_type
);
56 static int gsm411_mn_send(struct gsm411_smr_inst
*inst
, int msg_type
,
62 int gsm411_sms_init(struct osmocom_ms
*ms
)
64 LOGP(DLSMS
, LOGL_INFO
, "init SMS\n");
69 int gsm411_sms_exit(struct osmocom_ms
*ms
)
71 struct gsm_trans
*trans
, *trans2
;
73 LOGP(DLSMS
, LOGL_INFO
, "exit SMS processes for %s\n", ms
->name
);
75 llist_for_each_entry_safe(trans
, trans2
, &ms
->trans_list
, entry
) {
76 if (trans
->protocol
== GSM48_PDISC_SMS
) {
77 LOGP(DLSMS
, LOGL_NOTICE
, "Free pendig "
78 "SMS-transaction.\n");
90 struct gsm_sms
*sms_alloc(void)
92 return talloc_zero(l23_ctx
, struct gsm_sms
);
95 void sms_free(struct gsm_sms
*sms
)
100 struct gsm_sms
*sms_from_text(const char *receiver
, int dcs
, const char *text
)
102 struct gsm_sms
*sms
= sms_alloc();
107 OSMO_STRLCPY_ARRAY(sms
->text
, text
);
109 /* FIXME: don't use ID 1 static */
110 sms
->reply_path_req
= 0;
111 sms
->status_rep_req
= 0;
113 sms
->protocol_id
= 0; /* implicit */
114 sms
->data_coding_scheme
= dcs
;
115 OSMO_STRLCPY_ARRAY(sms
->address
, receiver
);
116 /* Generate user_data */
117 sms
->user_data_len
= gsm_7bit_encode_n(sms
->user_data
,
118 sizeof(sms
->user_data
), sms
->text
, NULL
);
123 static int gsm411_sms_report(struct osmocom_ms
*ms
, struct gsm_sms
*sms
,
126 vty_notify(ms
, NULL
);
128 vty_notify(ms
, "SMS to %s successfull\n", sms
->address
);
130 vty_notify(ms
, "SMS to %s failed: %s\n", sms
->address
,
131 get_value_string(gsm411_rp_cause_strs
, cause
));
133 mobile_prim_ntfy_sms_status(ms
, sms
, cause
);
140 /* SMS Specific transaction release.
141 * gets called by trans_free, DO NOT CALL YOURSELF!
143 void _gsm411_sms_trans_free(struct gsm_trans
*trans
)
145 gsm411_smr_clear(&trans
->sms
.smr_inst
);
146 gsm411_smc_clear(&trans
->sms
.smc_inst
);
148 if (trans
->sms
.sms
) {
149 LOGP(DLSMS
, LOGL_ERROR
, "Transaction contains SMS.\n");
150 gsm411_sms_report(trans
->ms
, trans
->sms
.sms
,
151 GSM411_RP_CAUSE_MO_SMS_REJECTED
);
152 sms_free(trans
->sms
.sms
);
153 trans
->sms
.sms
= NULL
;
157 /* release MM connection, free transaction */
158 static int gsm411_trans_free(struct gsm_trans
*trans
)
162 /* release MM connection */
163 nmsg
= gsm48_mmxx_msgb_alloc(GSM48_MMSMS_REL_REQ
, trans
->callref
,
164 trans
->transaction_id
, trans
->sms
.sapi
);
167 LOGP(DLSMS
, LOGL_INFO
, "Sending MMSMS_REL_REQ\n");
168 gsm48_mmxx_downmsg(trans
->ms
, nmsg
);
180 /* store the SMS to disk */
181 static int sms_store(struct osmocom_ms
*ms
, struct msgb
*msg
,
182 struct gsm_sms
*gsms
)
184 const char osmocomsms
[] = ".osmocom/bb/sms.txt";
187 char vty_text
[sizeof(gsms
->text
)], *p
;
190 /* remove linefeeds and show at VTY */
191 strcpy(vty_text
, gsms
->text
);
192 for (p
= vty_text
; *p
; p
++) {
193 if (*p
== '\n' || *p
== '\r')
196 vty_notify(ms
, NULL
);
197 vty_notify(ms
, "SMS from %s: '%s'\n", gsms
->address
, vty_text
);
199 home
= getenv("HOME");
202 fprintf(stderr
, "Can't deliver SMS, be sure to create '%s' in "
203 "your home directory.\n", osmocomsms
);
204 return GSM411_RP_CAUSE_MT_MEM_EXCEEDED
;
206 sms_file
= talloc_asprintf(l23_ctx
, "%s/%s", home
, osmocomsms
);
210 fp
= fopen(sms_file
, "a");
212 talloc_free(sms_file
);
215 fprintf(fp
, "[SMS from %s]\n%s\n", gsms
->address
, gsms
->text
);
218 talloc_free(sms_file
);
223 /* now here comes our SMS */
224 static int gsm340_rx_sms_deliver(struct osmocom_ms
*ms
, struct msgb
*msg
,
225 struct gsm_sms
*gsms
)
227 mobile_prim_ntfy_sms_new(ms
, gsms
);
228 if (!ms
->settings
.store_sms
)
230 return sms_store(ms
, msg
, gsms
);
233 /* process an incoming TPDU (called from RP-DATA)
234 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
235 static int gsm340_rx_tpdu(struct gsm_trans
*trans
, struct msgb
*msg
, uint8_t msg_ref
)
237 uint8_t *smsp
= msgb_sms(msg
);
238 struct gsm_sms
*gsms
;
239 unsigned int sms_alphabet
;
241 uint8_t oa_len_bytes
;
242 uint8_t address_lv
[12]; /* according to 03.40 / 9.1.2.5 */
246 gsms
->msg_ref
= msg_ref
;
248 /* invert those fields where 0 means active/present */
249 sms_mti
= *smsp
& 0x03;
250 /* uint8_t sms_mms = !!(*smsp & 0x04); */
251 gsms
->status_rep_req
= (*smsp
& 0x20);
252 gsms
->ud_hdr_ind
= (*smsp
& 0x40);
253 gsms
->reply_path_req
= (*smsp
& 0x80);
256 /* length in bytes of the originate address */
257 oa_len_bytes
= 2 + *smsp
/2 + *smsp
%2;
258 if (oa_len_bytes
> 12) {
259 LOGP(DLSMS
, LOGL_ERROR
, "Originate Address > 12 bytes ?!?\n");
260 rc
= GSM411_RP_CAUSE_SEMANT_INC_MSG
;
263 memset(address_lv
, 0, sizeof(address_lv
));
264 memcpy(address_lv
, smsp
, oa_len_bytes
);
265 /* mangle first byte to reflect length in bytes, not digits */
266 address_lv
[0] = oa_len_bytes
- 1;
267 /* convert to real number */
268 if (((smsp
[1] & 0x70) >> 4) == 1)
269 strcpy(gsms
->address
, "+");
270 else if (((smsp
[1] & 0x70) >> 4) == 2)
271 strcpy(gsms
->address
, "0");
273 gsms
->address
[0] = '\0';
274 gsm48_decode_bcd_number2(gsms
->address
+ strlen(gsms
->address
),
275 sizeof(gsms
->address
) - strlen(gsms
->address
), address_lv
, sizeof(address_lv
), 1);
276 smsp
+= oa_len_bytes
;
278 gsms
->protocol_id
= *smsp
++;
279 gsms
->data_coding_scheme
= *smsp
++;
281 sms_alphabet
= gsm338_get_sms_alphabet(gsms
->data_coding_scheme
);
282 if (sms_alphabet
== 0xffffffff) {
284 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER
;
288 gsms
->time
= gsm340_scts(smsp
);
292 gsms
->user_data_len
= *smsp
++;
293 if (gsms
->user_data_len
) {
294 memcpy(gsms
->user_data
, smsp
, gsms
->user_data_len
);
296 switch (sms_alphabet
) {
297 case DCS_7BIT_DEFAULT
:
298 gsm_7bit_decode_n(gsms
->text
, sizeof(gsms
->text
),
299 smsp
, gsms
->user_data_len
);
308 LOGP(DLSMS
, LOGL_INFO
, "RX SMS: MTI: 0x%02x, "
309 "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, OA: %s, "
310 "UserDataLength: 0x%02x, UserData: \"%s\"\n",
311 sms_mti
, gsms
->msg_ref
,
312 gsms
->protocol_id
, gsms
->data_coding_scheme
, gsms
->address
,
314 sms_alphabet
== DCS_7BIT_DEFAULT
? gsms
->text
:
315 osmo_hexdump(gsms
->user_data
,
316 gsms
->user_data_len
));
319 case GSM340_SMS_DELIVER_SC2MS
:
320 /* MS is receiving an SMS */
321 rc
= gsm340_rx_sms_deliver(trans
->ms
, msg
, gsms
);
323 case GSM340_SMS_STATUS_REP_SC2MS
:
324 case GSM340_SMS_SUBMIT_REP_SC2MS
:
325 LOGP(DLSMS
, LOGL_NOTICE
, "Unimplemented MTI 0x%02x\n", sms_mti
);
326 rc
= GSM411_RP_CAUSE_IE_NOTEXIST
;
329 LOGP(DLSMS
, LOGL_NOTICE
, "Undefined MTI 0x%02x\n", sms_mti
);
330 rc
= GSM411_RP_CAUSE_IE_NOTEXIST
;
340 static int gsm411_send_rp_ack(struct gsm_trans
*trans
, uint8_t msg_ref
)
342 struct msgb
*msg
= gsm411_msgb_alloc();
344 LOGP(DLSMS
, LOGL_INFO
, "TX: SMS RP ACK\n");
346 gsm411_push_rp_header(msg
, GSM411_MT_RP_ACK_MO
, msg_ref
);
347 return gsm411_smr_send(&trans
->sms
.smr_inst
, GSM411_SM_RL_REPORT_REQ
,
351 static int gsm411_send_rp_error(struct gsm_trans
*trans
,
352 uint8_t msg_ref
, uint8_t cause
)
354 struct msgb
*msg
= gsm411_msgb_alloc();
356 msgb_tv_put(msg
, 1, cause
);
358 LOGP(DLSMS
, LOGL_NOTICE
, "TX: SMS RP ERROR, cause %d (%s)\n", cause
,
359 get_value_string(gsm411_rp_cause_strs
, cause
));
361 gsm411_push_rp_header(msg
, GSM411_MT_RP_ERROR_MO
, msg_ref
);
362 return gsm411_smr_send(&trans
->sms
.smr_inst
, GSM411_SM_RL_REPORT_REQ
,
366 /* Receive a 04.11 TPDU inside RP-DATA / user data */
367 static int gsm411_rx_rp_ud(struct msgb
*msg
, struct gsm_trans
*trans
,
368 struct gsm411_rp_hdr
*rph
,
369 uint8_t src_len
, uint8_t *src
,
370 uint8_t dst_len
, uint8_t *dst
,
371 uint8_t tpdu_len
, uint8_t *tpdu
)
376 LOGP(DLSMS
, LOGL_ERROR
, "RP-DATA (MT) with DST ?!?\n");
378 if (!src_len
|| !src
|| !tpdu_len
|| !tpdu
) {
379 LOGP(DLSMS
, LOGL_ERROR
,
380 "RP-DATA (MO) without DST or TPDU ?!?\n");
381 gsm411_send_rp_error(trans
, rph
->msg_ref
,
382 GSM411_RP_CAUSE_INV_MAND_INF
);
387 LOGP(DLSMS
, LOGL_INFO
, "DST(%u,%s)\n", src_len
,
388 osmo_hexdump(src
, src_len
));
389 LOGP(DLSMS
, LOGL_INFO
, "TPDU(%ti,%s)\n", msg
->tail
-msg
->l4h
,
390 osmo_hexdump(msg
->l4h
, msg
->tail
-msg
->l4h
));
392 rc
= gsm340_rx_tpdu(trans
, msg
, rph
->msg_ref
);
394 return gsm411_send_rp_ack(trans
, rph
->msg_ref
);
396 return gsm411_send_rp_error(trans
, rph
->msg_ref
, rc
);
401 /* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
402 static int gsm411_rx_rp_data(struct msgb
*msg
, struct gsm_trans
*trans
,
403 struct gsm411_rp_hdr
*rph
)
405 uint8_t src_len
, dst_len
, rpud_len
;
406 uint8_t *src
= NULL
, *dst
= NULL
, *rp_ud
= NULL
;
408 /* in the MO case, this should always be zero length */
409 src_len
= rph
->data
[0];
413 dst_len
= rph
->data
[1+src_len
];
415 dst
= &rph
->data
[1+src_len
+1];
417 rpud_len
= rph
->data
[1+src_len
+1+dst_len
];
419 rp_ud
= &rph
->data
[1+src_len
+1+dst_len
+1];
421 LOGP(DLSMS
, LOGL_INFO
, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
422 src_len
, dst_len
, rpud_len
);
423 return gsm411_rx_rp_ud(msg
, trans
, rph
, src_len
, src
, dst_len
, dst
,
427 /* receive RL DATA */
428 static int gsm411_rx_rl_data(struct msgb
*msg
, struct gsm48_hdr
*gh
,
429 struct gsm_trans
*trans
)
431 struct gsm411_rp_hdr
*rp_data
= (struct gsm411_rp_hdr
*)&gh
->data
;
432 uint8_t msg_type
= rp_data
->msg_type
& 0x07;
436 case GSM411_MT_RP_DATA_MT
:
437 LOGP(DLSMS
, LOGL_INFO
, "RX SMS RP-DATA (MT)\n");
438 rc
= gsm411_rx_rp_data(msg
, trans
, rp_data
);
441 LOGP(DLSMS
, LOGL_NOTICE
, "Invalid RP type 0x%02x\n", msg_type
);
442 gsm411_trans_free(trans
);
454 /* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
455 static int gsm411_rx_rp_ack(struct msgb
*msg
, struct gsm_trans
*trans
,
456 struct gsm411_rp_hdr
*rph
)
458 struct osmocom_ms
*ms
= trans
->ms
;
459 struct gsm_sms
*sms
= trans
->sms
.sms
;
461 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
462 * successfully received a SMS. We can now safely mark it as
466 LOGP(DLSMS
, LOGL_ERROR
, "RX RP-ACK but no sms in "
468 return gsm411_send_rp_error(trans
, rph
->msg_ref
,
469 GSM411_RP_CAUSE_PROTOCOL_ERR
);
472 gsm411_sms_report(ms
, sms
, 0);
475 trans
->sms
.sms
= NULL
;
480 static int gsm411_rx_rp_error(struct msgb
*msg
, struct gsm_trans
*trans
,
481 struct gsm411_rp_hdr
*rph
)
483 struct osmocom_ms
*ms
= trans
->ms
;
484 struct gsm_sms
*sms
= trans
->sms
.sms
;
485 uint8_t cause_len
= rph
->data
[0];
486 uint8_t cause
= rph
->data
[1];
488 /* Error in response to MT RP_DATA, i.e. the MS did not
489 * successfully receive the SMS. We need to investigate
490 * the cause and take action depending on it */
492 LOGP(DLSMS
, LOGL_NOTICE
, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
493 trans
->ms
->name
, cause_len
, cause
,
494 get_value_string(gsm411_rp_cause_strs
, cause
));
497 LOGP(DLSMS
, LOGL_ERROR
,
498 "RX RP-ERR, but no sms in transaction?!?\n");
501 return gsm411_send_rp_error(trans
, rph
->msg_ref
,
502 GSM411_RP_CAUSE_PROTOCOL_ERR
);
506 gsm411_sms_report(ms
, sms
, cause
);
509 trans
->sms
.sms
= NULL
;
514 /* receive RL REPORT */
515 static int gsm411_rx_rl_report(struct msgb
*msg
, struct gsm48_hdr
*gh
,
516 struct gsm_trans
*trans
)
518 struct gsm411_rp_hdr
*rp_data
= (struct gsm411_rp_hdr
*)&gh
->data
;
519 uint8_t msg_type
= rp_data
->msg_type
& 0x07;
523 case GSM411_MT_RP_ACK_MT
:
524 LOGP(DLSMS
, LOGL_INFO
, "RX SMS RP-ACK (MT)\n");
525 rc
= gsm411_rx_rp_ack(msg
, trans
, rp_data
);
527 case GSM411_MT_RP_ERROR_MT
:
528 LOGP(DLSMS
, LOGL_INFO
, "RX SMS RP-ERROR (MT)\n");
529 rc
= gsm411_rx_rp_error(msg
, trans
, rp_data
);
532 LOGP(DLSMS
, LOGL_NOTICE
, "Invalid RP type 0x%02x\n", msg_type
);
533 gsm411_trans_free(trans
);
541 /* generate a msgb containing a TPDU derived from struct gsm_sms,
542 * returns total size of TPDU */
543 static int gsm340_gen_tpdu(struct msgb
*msg
, struct gsm_sms
*sms
)
546 uint8_t da
[12]; /* max len per 03.40 */
549 unsigned int old_msg_len
= msg
->len
;
550 uint8_t sms_vpf
= GSM340_TP_VPF_NONE
;
553 /* generate first octet with masked bits */
554 smsp
= msgb_put(msg
, 1);
555 /* TP-MTI (message type indicator) */
556 *smsp
= GSM340_SMS_SUBMIT_MS2SC
;
561 *smsp
|= (sms_vpf
<< 3);
562 /* TP-SRI(deliver)/SRR(submit) */
563 if (sms
->status_rep_req
)
565 /* TP-UDHI (indicating TP-UD contains a header) */
569 if (sms
->reply_path_req
)
572 /* generate message ref */
573 smsp
= msgb_put(msg
, 1);
574 *smsp
= sms
->msg_ref
;
576 /* generate destination address */
577 if (sms
->address
[0] == '+')
578 da_len
= gsm340_gen_oa(da
, sizeof(da
), 0x1, 0x1,
581 da_len
= gsm340_gen_oa(da
, sizeof(da
), 0x0, 0x1, sms
->address
);
585 smsp
= msgb_put(msg
, da_len
);
586 memcpy(smsp
, da
, da_len
);
588 /* generate TP-PID */
589 smsp
= msgb_put(msg
, 1);
590 *smsp
= sms
->protocol_id
;
592 /* generate TP-DCS */
593 smsp
= msgb_put(msg
, 1);
594 *smsp
= sms
->data_coding_scheme
;
598 case GSM340_TP_VPF_NONE
:
602 fprintf(stderr
, "VPF unsupported, please fix!\n");
605 smsp
= msgb_put(msg
, sms_vp
);
607 /* generate TP-UDL */
608 smsp
= msgb_put(msg
, 1);
609 *smsp
= sms
->user_data_len
;
612 switch (gsm338_get_sms_alphabet(sms
->data_coding_scheme
)) {
613 case DCS_7BIT_DEFAULT
:
614 octet_len
= sms
->user_data_len
*7/8;
615 if (sms
->user_data_len
*7%8 != 0)
617 /* Warning, user_data_len indicates the amount of septets
618 * (characters), we need amount of octets occupied */
619 smsp
= msgb_put(msg
, octet_len
);
620 memcpy(smsp
, sms
->user_data
, octet_len
);
624 smsp
= msgb_put(msg
, sms
->user_data_len
);
625 memcpy(smsp
, sms
->user_data
, sms
->user_data_len
);
628 LOGP(DLSMS
, LOGL_NOTICE
, "Unhandled Data Coding Scheme: "
629 "0x%02X\n", sms
->data_coding_scheme
);
633 return msg
->len
- old_msg_len
;
636 /* Take a SMS in gsm_sms structure and send it. */
637 int gsm411_tx_sms_submit(struct osmocom_ms
*ms
, const char *sms_sca
,
641 struct gsm_trans
*trans
;
642 uint8_t *data
, *rp_ud_len
;
645 uint8_t sca
[11]; /* max len per 03.40 */
647 LOGP(DLSMS
, LOGL_INFO
, "..._sms_submit()\n");
649 /* no running, no transaction */
650 if (!ms
->started
|| ms
->shutdown
!= MS_SHUTDOWN_NONE
) {
651 LOGP(DLSMS
, LOGL_ERROR
, "Phone is down\n");
652 gsm411_sms_report(ms
, sms
, GSM411_RP_CAUSE_MO_TEMP_FAIL
);
657 /* allocate transaction with dummy reference */
658 transaction_id
= trans_assign_trans_id(ms
, GSM48_PDISC_SMS
, 0);
659 if (transaction_id
< 0) {
660 LOGP(DLSMS
, LOGL_ERROR
, "No transaction ID available\n");
661 gsm411_sms_report(ms
, sms
, GSM411_RP_CAUSE_MO_CONGESTION
);
665 trans
= trans_alloc(ms
, GSM48_PDISC_SMS
, transaction_id
, new_callref
++);
667 LOGP(DLSMS
, LOGL_ERROR
, "No memory for trans\n");
668 gsm411_sms_report(ms
, sms
, GSM411_RP_CAUSE_MO_TEMP_FAIL
);
672 gsm411_smc_init(&trans
->sms
.smc_inst
, transaction_id
, 0,
673 gsm411_mn_recv
, gsm411_mm_send
);
674 gsm411_smr_init(&trans
->sms
.smr_inst
, transaction_id
, 0,
675 gsm411_rl_recv
, gsm411_mn_send
);
676 trans
->sms
.sms
= sms
;
677 trans
->sms
.sapi
= UM_SAPI_SMS
;
679 msg
= gsm411_msgb_alloc();
681 /* no orig Address */
682 data
= (uint8_t *)msgb_put(msg
, 1);
683 data
[0] = 0x00; /* originator length == 0 */
685 /* Destination Address */
686 sca
[1] = 0x80; /* no extension */
687 sca
[1] |= ((sms_sca
[0] == '+') ? 0x01 : 0x00) << 4; /* type */
688 sca
[1] |= 0x1; /* plan*/
690 rc
= gsm48_encode_bcd_number(sca
, sizeof(sca
), 1,
691 sms_sca
+ (sms_sca
[0] == '+'));
694 gsm411_sms_report(ms
, sms
, GSM411_RP_CAUSE_SEMANT_INC_MSG
);
695 gsm411_trans_free(trans
);
699 data
= msgb_put(msg
, rc
);
700 memcpy(data
, sca
, rc
);
702 /* obtain a pointer for the rp_ud_len, so we can fill it later */
703 rp_ud_len
= (uint8_t *)msgb_put(msg
, 1);
705 /* generate the 03.40 TPDU */
706 rc
= gsm340_gen_tpdu(msg
, sms
);
711 LOGP(DLSMS
, LOGL_INFO
, "TX: SMS DELIVER\n");
713 gsm411_push_rp_header(msg
, GSM411_MT_RP_DATA_MO
, sms
->msg_ref
);
714 return gsm411_smr_send(&trans
->sms
.smr_inst
, GSM411_SM_RL_DATA_REQ
,
718 /* create and send SMS */
719 int sms_send(struct osmocom_ms
*ms
, const char *sms_sca
, const char *number
,
720 const char *text
, uint8_t msg_ref
)
722 struct gsm_sms
*sms
= sms_from_text(number
, 0, text
);
727 sms
->msg_ref
= msg_ref
;
728 return gsm411_tx_sms_submit(ms
, sms_sca
, sms
);
732 * message flow between layers
735 /* push MMSMS header and send to MM */
736 static int gsm411_to_mm(struct msgb
*msg
, struct gsm_trans
*trans
,
739 struct gsm48_mmxx_hdr
*mmh
;
742 msgb_push(msg
, sizeof(struct gsm48_mmxx_hdr
));
743 mmh
= (struct gsm48_mmxx_hdr
*)msg
->data
;
744 mmh
->msg_type
= msg_type
;
745 mmh
->ref
= trans
->callref
;
746 mmh
->transaction_id
= trans
->transaction_id
;
747 mmh
->sapi
= trans
->sms
.sapi
;
750 /* send message to MM */
751 LOGP(DLSMS
, LOGL_INFO
, "Sending '%s' to MM (callref=%x, "
752 "transaction_id=%d, sapi=%d)\n", get_mmxx_name(msg_type
),
753 trans
->callref
, trans
->transaction_id
, trans
->sms
.sapi
);
754 return gsm48_mmxx_downmsg(trans
->ms
, msg
);
757 /* mm_send: receive MMSMS sap message from SMC */
758 static int gsm411_mm_send(struct gsm411_smc_inst
*inst
, int msg_type
,
759 struct msgb
*msg
, int cp_msg_type
)
761 struct gsm_trans
*trans
=
762 container_of(inst
, struct gsm_trans
, sms
.smc_inst
);
766 case GSM411_MMSMS_EST_REQ
:
767 gsm411_to_mm(msg
, trans
, msg_type
);
769 case GSM411_MMSMS_DATA_REQ
:
770 gsm411_push_cp_header(msg
, trans
->protocol
,
771 trans
->transaction_id
, cp_msg_type
);
772 msg
->l3h
= msg
->data
;
773 LOGP(DLSMS
, LOGL_INFO
, "sending CP message (trans=%x)\n",
774 trans
->transaction_id
);
775 rc
= gsm411_to_mm(msg
, trans
, msg_type
);
777 case GSM411_MMSMS_REL_REQ
:
778 LOGP(DLSMS
, LOGL_INFO
, "Got MMSMS_REL_REQ, destroying "
780 gsm411_to_mm(msg
, trans
, msg_type
);
781 gsm411_trans_free(trans
);
791 /* mm_send: receive MNSMS sap message from SMR */
792 static int gsm411_mn_send(struct gsm411_smr_inst
*inst
, int msg_type
,
795 struct gsm_trans
*trans
=
796 container_of(inst
, struct gsm_trans
, sms
.smr_inst
);
799 return gsm411_smc_send(&trans
->sms
.smc_inst
, msg_type
, msg
);
802 /* receive SM-RL sap message from SMR
803 * NOTE: Message is freed by sender
805 static int gsm411_rl_recv(struct gsm411_smr_inst
*inst
, int msg_type
,
808 struct gsm_trans
*trans
=
809 container_of(inst
, struct gsm_trans
, sms
.smr_inst
);
810 struct gsm48_hdr
*gh
= msgb_l3(msg
);
814 case GSM411_SM_RL_DATA_IND
:
815 rc
= gsm411_rx_rl_data(msg
, gh
, trans
);
817 case GSM411_SM_RL_REPORT_IND
:
819 LOGP(DLSMS
, LOGL_INFO
, "Release transaction on empty "
822 LOGP(DLSMS
, LOGL_INFO
, "Release transaction on RL "
824 rc
= gsm411_rx_rl_report(msg
, gh
, trans
);
834 /* receive MNSMS sap message from SMC
835 * NOTE: Message is freed by sender
837 static int gsm411_mn_recv(struct gsm411_smc_inst
*inst
, int msg_type
,
840 struct gsm_trans
*trans
=
841 container_of(inst
, struct gsm_trans
, sms
.smc_inst
);
842 struct gsm48_hdr
*gh
= msgb_l3(msg
);
846 case GSM411_MNSMS_EST_IND
:
847 case GSM411_MNSMS_DATA_IND
:
848 LOGP(DLSMS
, LOGL_INFO
, "MNSMS-DATA/EST-IND\n");
849 rc
= gsm411_smr_recv(&trans
->sms
.smr_inst
, msg_type
, msg
);
851 case GSM411_MNSMS_ERROR_IND
:
853 LOGP(DLSMS
, LOGL_INFO
, "MNSMS-ERROR-IND, cause %d "
854 "(%s)\n", gh
->data
[0],
855 get_value_string(gsm411_cp_cause_strs
,
858 LOGP(DLSMS
, LOGL_INFO
, "MNSMS-ERROR-IND, no cause\n");
859 rc
= gsm411_smr_recv(&trans
->sms
.smr_inst
, msg_type
, msg
);
868 /* receive est/data message from MM layer */
869 static int gsm411_mmsms_ind(int mmsms_msg
, struct gsm_trans
*trans
,
872 struct osmocom_ms
*ms
= trans
->ms
;
873 struct gsm48_hdr
*gh
= msgb_l3(msg
);
874 int msg_type
= gh
->msg_type
& 0xbf;
875 uint8_t transaction_id
= ((gh
->proto_discr
& 0xf0) ^ 0x80) >> 4;
878 /* pull the MMSMS header */
879 msgb_pull(msg
, sizeof(struct gsm48_mmxx_hdr
));
881 LOGP(DLSMS
, LOGL_INFO
, "(ms %s) Received est/data '%u'\n", ms
->name
,
884 /* 5.4: For MO, if a CP-DATA is received for a new
885 * transaction, equals reception of an implicit
886 * last CP-ACK for previous transaction */
887 if (trans
->sms
.smc_inst
.cp_state
== GSM411_CPS_IDLE
888 && msg_type
== GSM411_MT_CP_DATA
) {
890 struct gsm_trans
*ptrans
;
892 /* Scan through all remote initiated transactions */
893 for (i
=8; i
<15; i
++) {
894 if (i
== transaction_id
)
897 ptrans
= trans_find_by_id(ms
, GSM48_PDISC_SMS
, i
);
901 LOGP(DLSMS
, LOGL_INFO
, "Implicit CP-ACK for "
904 /* Finish it for good */
905 gsm411_trans_free(ptrans
);
908 return gsm411_smc_recv(&trans
->sms
.smc_inst
, mmsms_msg
, msg
, msg_type
);
911 /* receive message from MM layer */
912 int gsm411_rcv_sms(struct osmocom_ms
*ms
, struct msgb
*msg
)
914 struct gsm48_mmxx_hdr
*mmh
= (struct gsm48_mmxx_hdr
*)msg
->data
;
915 int msg_type
= mmh
->msg_type
;
916 int sapi
= mmh
->sapi
;
917 struct gsm_trans
*trans
;
920 trans
= trans_find_by_callref(ms
, mmh
->ref
);
922 LOGP(DLSMS
, LOGL_INFO
, " -> (new transaction sapi=%d)\n", sapi
);
923 trans
= trans_alloc(ms
, GSM48_PDISC_SMS
, mmh
->transaction_id
,
927 gsm411_smc_init(&trans
->sms
.smc_inst
, trans
->transaction_id
, 0,
928 gsm411_mn_recv
, gsm411_mm_send
);
929 gsm411_smr_init(&trans
->sms
.smr_inst
, trans
->transaction_id
, 0,
930 gsm411_rl_recv
, gsm411_mn_send
);
931 trans
->sms
.sapi
= mmh
->sapi
;
934 LOGP(DLSMS
, LOGL_INFO
, "(ms %s) Received '%s' from MM\n", ms
->name
,
935 get_mmxx_name(msg_type
));
938 case GSM48_MMSMS_EST_CNF
:
939 rc
= gsm411_smc_recv(&trans
->sms
.smc_inst
, GSM411_MMSMS_EST_CNF
,
942 case GSM48_MMSMS_EST_IND
:
943 case GSM48_MMSMS_DATA_IND
:
944 rc
= gsm411_mmsms_ind(msg_type
, trans
, msg
);
946 case GSM48_MMSMS_REL_IND
:
947 case GSM48_MMSMS_ERR_IND
:
948 LOGP(DLSMS
, LOGL_INFO
, "MM connection released.\n");
952 LOGP(DLSMS
, LOGL_NOTICE
, "Message unhandled.\n");