blob: e94f9adf3c2a215f620113d8e6fac93c9eee4fd1 [file] [log] [blame]
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001/* Point-to-Point (PP) Short Message Service (SMS)
2 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
4
5/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <netinet/in.h>
31
32#include <openbsc/msgb.h>
33#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000034#include <openbsc/gsm_data.h>
35#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000036#include <openbsc/gsm_04_11.h>
37#include <openbsc/gsm_04_08.h>
Holger Freyther76c95692009-02-17 20:31:30 +000038#include <openbsc/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000040#include <openbsc/signal.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000041
Daniel Willmann471712b2008-12-29 01:54:02 +000042#define GSM411_ALLOC_SIZE 1024
43#define GSM411_ALLOC_HEADROOM 128
44
Holger Freythera553d092009-01-04 20:16:25 +000045struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000046{
47 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM);
48}
49
Holger Freythera553d092009-01-04 20:16:25 +000050int gsm0411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000051{
52 if (msg->lchan)
53 msg->trx = msg->lchan->ts->trx;
54
55 msg->l3h = msg->data;
56
57 return rsl_data_request(msg, 0);
58}
59
Daniel Willmanne0fbec82008-12-29 00:44:41 +000060
Holger Freytherca362a62009-01-04 21:05:01 +000061#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +000062static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
63{
Daniel Willmann6fe997e2008-12-29 04:20:41 +000064}
Holger Freytherca362a62009-01-04 21:05:01 +000065#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +000066
Daniel Willmanne0fbec82008-12-29 00:44:41 +000067static int gsm411_sms_submit_from_msgb(struct msgb *msg)
68{
69 u_int8_t *smsp = msgb_sms(msg);
70 struct sms_submit *sms;
71
72 sms = malloc(sizeof(*sms));
73 sms->mti = *smsp & 0x03;
74 sms->mms = !!(*smsp & 0x04);
75 sms->vpf = (*smsp & 0x18) >> 3;
76 sms->sri = !!(*smsp & 0x20);
77 sms->udhi= !!(*smsp & 0x40);
78 sms->rp = !!(*smsp & 0x80);
79
80 smsp++;
81 sms->msg_ref = *smsp++;
82
83 /* Skip destination address for now */
84 smsp += 2 + *smsp/2 + *smsp%2;
85
86 sms->pid = *smsp++;
87 sms->dcs = *smsp++;
88 switch (sms->vpf)
89 {
90 case 2: /* relative */
91 sms->vp = *smsp++;
92 break;
93 default:
94 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
95 sms->vpf);
96 }
97 sms->ud_len = *smsp++;
98
Holger Freyther76c95692009-02-17 20:31:30 +000099 sms->user_data = (u_int8_t *)gsm_7bit_decode(smsp, sms->ud_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000100
101 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x\n"
102 "PID: 0x%02x, DCS: 0x%02x, UserDataLength: 0x%02x\n"
103 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
104 sms->pid, sms->dcs, sms->ud_len, sms->user_data);
105
Harald Welte595ad7b2009-02-16 22:05:44 +0000106 dispatch_signal(SS_SMS, 0, sms);
Holger Freyther9b177762009-02-16 19:07:18 +0000107
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000108 free(sms);
109
110 return 0;
111}
112
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000113static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
114 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000115{
116 struct msgb *msg = gsm411_msgb_alloc();
117 struct gsm48_hdr *gh;
118 struct gsm411_rp_hdr *rp;
119
120 msg->lchan = lchan;
121
122 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000123 // Outgoing needs the highest bit set
124 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
125 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000126
127 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000128 rp->len = 2;
Daniel Willmann471712b2008-12-29 01:54:02 +0000129 rp->msg_type = GSM411_MT_RP_ACK_MT;
130 rp->msg_ref = msg_ref;
131
132 DEBUGP(DSMS, "TX: SMS RP ACK\n");
133
134 return gsm0411_sendmsg(msg);
135}
136
Holger Freytherca362a62009-01-04 21:05:01 +0000137#if 0
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000138static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
139 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000140{
141 struct msgb *msg = gsm411_msgb_alloc();
142 struct gsm48_hdr *gh;
143 struct gsm411_rp_hdr *rp;
144
145 msg->lchan = lchan;
146
147 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000148 // Outgoing needs the highest bit set
149 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
150 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000151
152 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
153 rp->msg_type = GSM411_MT_RP_ERROR_MT;
154 rp->msg_ref = msg_ref;
155
156 DEBUGP(DSMS, "TX: SMS RP ERROR\n");
157
158 return gsm0411_sendmsg(msg);
159}
Holger Freytherca362a62009-01-04 21:05:01 +0000160#endif
Daniel Willmann471712b2008-12-29 01:54:02 +0000161
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000162static int gsm411_cp_data(struct msgb *msg)
163{
164 struct gsm48_hdr *gh = msgb_l3(msg);
165 int rc = 0;
166
Daniel Willmann471712b2008-12-29 01:54:02 +0000167 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000168 u_int8_t msg_type = rp_data->msg_type & 0x07;
169
170 switch (msg_type) {
171 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000172 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
173 /* Skip SMSC no and RP-UD length */
174 msg->smsh = &rp_data->data[1] + rp_data->data[1] + 2;
175 gsm411_sms_submit_from_msgb(msg);
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000176 gsm411_send_rp_ack(msg->lchan, (gh->proto_discr & 0xf0)>>4, rp_data->msg_ref);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000177 break;
178 default:
179 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
180 break;
181 }
182
183 return rc;
184}
185
186int gsm0411_rcv_sms(struct msgb *msg)
187{
188 struct gsm48_hdr *gh = msgb_l3(msg);
189 u_int8_t msg_type = gh->msg_type;
190 int rc = 0;
191
192 DEBUGP(DSMS, "SMS Message\n");
193
194 switch(msg_type) {
195 case GSM411_MT_CP_DATA:
196 DEBUGP(DSMS, "SMS CP-DATA\n");
197 rc = gsm411_cp_data(msg);
198 break;
199 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000200 DEBUGP(DSMS, "SMS CP-ACK\n");
201 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000202 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000203 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
204 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000205 default:
206 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
207 break;
208 }
209
210
211 return rc;
212}
213
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000214/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000215#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000216static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000217 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
218 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
219 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
220 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
221 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
222 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
223 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000224};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000225#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000226/* Test TPDU - ALL YOUR */
227static u_int8_t tpdu_test[] = {
228 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
229 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
230 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
231 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000232};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000233#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000234
235int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
236{
237 struct msgb *msg = gsm411_msgb_alloc();
238 struct gsm48_hdr *gh;
239 struct gsm411_rp_hdr *rp;
Holger Freytherca362a62009-01-04 21:05:01 +0000240 u_int8_t *data;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000241
242 msg->lchan = lchan;
243
244 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
245 gh->proto_discr = GSM48_PDISC_SMS;
246 gh->msg_type = GSM411_MT_CP_DATA;
247
248 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmanna3e29842008-12-29 16:03:54 +0000249 rp->len = sizeof(tpdu_test) + 10;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000250 rp->msg_type = GSM411_MT_RP_DATA_MT;
251 rp->msg_ref = 42; /* FIXME: Choose randomly */
Daniel Willmannfad5d0d2008-12-29 16:04:14 +0000252 /* Hardcode OA for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000253 data = (u_int8_t *)msgb_put(msg, 8);
254 data[0] = 0x07;
255 data[1] = 0x91;
256 data[2] = 0x44;
257 data[3] = 0x77;
258 data[4] = 0x58;
259 data[5] = 0x10;
260 data[6] = 0x06;
261 data[7] = 0x50;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000262 data = (u_int8_t *)msgb_put(msg, 1);
263 data[0] = 0;
264
265 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000266 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
267
268 /* RPDU length */
269 data = (u_int8_t *)msgb_put(msg, 1);
270 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000271
272 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
273
274 //memcpy(data, tpdu, smslen);
275 memcpy(data, tpdu_test, sizeof(tpdu_test));
276
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000277 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
278
279 return gsm0411_sendmsg(msg);
280}
281