blob: d3546633ef2121bd9f2f17ef972172f0312f3ef6 [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>
38#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000039#include <openbsc/signal.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000040
Daniel Willmann471712b2008-12-29 01:54:02 +000041#define GSM411_ALLOC_SIZE 1024
42#define GSM411_ALLOC_HEADROOM 128
43
Holger Freythera553d092009-01-04 20:16:25 +000044struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000045{
46 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM);
47}
48
Holger Freythera553d092009-01-04 20:16:25 +000049int gsm0411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000050{
51 if (msg->lchan)
52 msg->trx = msg->lchan->ts->trx;
53
54 msg->l3h = msg->data;
55
56 return rsl_data_request(msg, 0);
57}
58
Daniel Willmanne0fbec82008-12-29 00:44:41 +000059static char *gsm411_7bit_decode(u_int8_t *user_data, u_int8_t length)
60{
61 u_int8_t d_off = 0, b_off = 0;
62 u_int8_t i;
63 char *text = malloc(length+1);
64
65 for (i=0;i<length;i++) {
66 text[i] = ((user_data[d_off] + (user_data[d_off+1]<<8)) & (0x7f<<b_off))>>b_off;
67 b_off += 7;
68 if (b_off >= 8) {
69 d_off += 1;
70 b_off -= 8;
71 }
72 }
73 text[i] = 0;
74 return text;
75}
76
Holger Freytherca362a62009-01-04 21:05:01 +000077#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +000078static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
79{
Daniel Willmann6fe997e2008-12-29 04:20:41 +000080}
Holger Freytherca362a62009-01-04 21:05:01 +000081#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +000082
Daniel Willmanne0fbec82008-12-29 00:44:41 +000083static int gsm411_sms_submit_from_msgb(struct msgb *msg)
84{
85 u_int8_t *smsp = msgb_sms(msg);
86 struct sms_submit *sms;
87
88 sms = malloc(sizeof(*sms));
89 sms->mti = *smsp & 0x03;
90 sms->mms = !!(*smsp & 0x04);
91 sms->vpf = (*smsp & 0x18) >> 3;
92 sms->sri = !!(*smsp & 0x20);
93 sms->udhi= !!(*smsp & 0x40);
94 sms->rp = !!(*smsp & 0x80);
95
96 smsp++;
97 sms->msg_ref = *smsp++;
98
99 /* Skip destination address for now */
100 smsp += 2 + *smsp/2 + *smsp%2;
101
102 sms->pid = *smsp++;
103 sms->dcs = *smsp++;
104 switch (sms->vpf)
105 {
106 case 2: /* relative */
107 sms->vp = *smsp++;
108 break;
109 default:
110 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
111 sms->vpf);
112 }
113 sms->ud_len = *smsp++;
114
Holger Freytherca362a62009-01-04 21:05:01 +0000115 sms->user_data = (u_int8_t *)gsm411_7bit_decode(smsp, sms->ud_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000116
117 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x\n"
118 "PID: 0x%02x, DCS: 0x%02x, UserDataLength: 0x%02x\n"
119 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
120 sms->pid, sms->dcs, sms->ud_len, sms->user_data);
121
Holger Freyther9b177762009-02-16 19:07:18 +0000122 struct sms_signal_data sig = {
123 .data = {
124 .area = S_SMS,
125 },
126
127 .sms = sms,
128 };
129 dispatch_signal(&sig.data);
130
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000131 free(sms);
132
133 return 0;
134}
135
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000136static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
137 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000138{
139 struct msgb *msg = gsm411_msgb_alloc();
140 struct gsm48_hdr *gh;
141 struct gsm411_rp_hdr *rp;
142
143 msg->lchan = lchan;
144
145 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000146 // Outgoing needs the highest bit set
147 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
148 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000149
150 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000151 rp->len = 2;
Daniel Willmann471712b2008-12-29 01:54:02 +0000152 rp->msg_type = GSM411_MT_RP_ACK_MT;
153 rp->msg_ref = msg_ref;
154
155 DEBUGP(DSMS, "TX: SMS RP ACK\n");
156
157 return gsm0411_sendmsg(msg);
158}
159
Holger Freytherca362a62009-01-04 21:05:01 +0000160#if 0
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000161static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
162 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000163{
164 struct msgb *msg = gsm411_msgb_alloc();
165 struct gsm48_hdr *gh;
166 struct gsm411_rp_hdr *rp;
167
168 msg->lchan = lchan;
169
170 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000171 // Outgoing needs the highest bit set
172 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
173 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000174
175 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
176 rp->msg_type = GSM411_MT_RP_ERROR_MT;
177 rp->msg_ref = msg_ref;
178
179 DEBUGP(DSMS, "TX: SMS RP ERROR\n");
180
181 return gsm0411_sendmsg(msg);
182}
Holger Freytherca362a62009-01-04 21:05:01 +0000183#endif
Daniel Willmann471712b2008-12-29 01:54:02 +0000184
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000185static int gsm411_cp_data(struct msgb *msg)
186{
187 struct gsm48_hdr *gh = msgb_l3(msg);
188 int rc = 0;
189
Daniel Willmann471712b2008-12-29 01:54:02 +0000190 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000191 u_int8_t msg_type = rp_data->msg_type & 0x07;
192
193 switch (msg_type) {
194 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000195 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
196 /* Skip SMSC no and RP-UD length */
197 msg->smsh = &rp_data->data[1] + rp_data->data[1] + 2;
198 gsm411_sms_submit_from_msgb(msg);
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000199 gsm411_send_rp_ack(msg->lchan, (gh->proto_discr & 0xf0)>>4, rp_data->msg_ref);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000200 break;
201 default:
202 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
203 break;
204 }
205
206 return rc;
207}
208
209int gsm0411_rcv_sms(struct msgb *msg)
210{
211 struct gsm48_hdr *gh = msgb_l3(msg);
212 u_int8_t msg_type = gh->msg_type;
213 int rc = 0;
214
215 DEBUGP(DSMS, "SMS Message\n");
216
217 switch(msg_type) {
218 case GSM411_MT_CP_DATA:
219 DEBUGP(DSMS, "SMS CP-DATA\n");
220 rc = gsm411_cp_data(msg);
221 break;
222 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000223 DEBUGP(DSMS, "SMS CP-ACK\n");
224 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000225 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000226 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
227 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000228 default:
229 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
230 break;
231 }
232
233
234 return rc;
235}
236
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000237/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000238#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000239static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000240 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
241 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
242 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
243 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
244 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
245 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
246 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000247};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000248#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000249/* Test TPDU - ALL YOUR */
250static u_int8_t tpdu_test[] = {
251 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
252 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
253 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
254 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000255};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000256#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000257
258int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
259{
260 struct msgb *msg = gsm411_msgb_alloc();
261 struct gsm48_hdr *gh;
262 struct gsm411_rp_hdr *rp;
Holger Freytherca362a62009-01-04 21:05:01 +0000263 u_int8_t *data;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000264
265 msg->lchan = lchan;
266
267 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
268 gh->proto_discr = GSM48_PDISC_SMS;
269 gh->msg_type = GSM411_MT_CP_DATA;
270
271 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmanna3e29842008-12-29 16:03:54 +0000272 rp->len = sizeof(tpdu_test) + 10;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000273 rp->msg_type = GSM411_MT_RP_DATA_MT;
274 rp->msg_ref = 42; /* FIXME: Choose randomly */
Daniel Willmannfad5d0d2008-12-29 16:04:14 +0000275 /* Hardcode OA for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000276 data = (u_int8_t *)msgb_put(msg, 8);
277 data[0] = 0x07;
278 data[1] = 0x91;
279 data[2] = 0x44;
280 data[3] = 0x77;
281 data[4] = 0x58;
282 data[5] = 0x10;
283 data[6] = 0x06;
284 data[7] = 0x50;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000285 data = (u_int8_t *)msgb_put(msg, 1);
286 data[0] = 0;
287
288 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000289 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
290
291 /* RPDU length */
292 data = (u_int8_t *)msgb_put(msg, 1);
293 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000294
295 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
296
297 //memcpy(data, tpdu, smslen);
298 memcpy(data, tpdu_test, sizeof(tpdu_test));
299
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000300 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
301
302 return gsm0411_sendmsg(msg);
303}
304