blob: 35fc12ec422dcf69258e70c786224dd9eacc3885 [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
Holger Freyther77217de2009-02-23 04:03:27 +0000108 free(sms->user_data);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000109 free(sms);
110
111 return 0;
112}
113
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000114static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
115 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000116{
117 struct msgb *msg = gsm411_msgb_alloc();
118 struct gsm48_hdr *gh;
119 struct gsm411_rp_hdr *rp;
120
121 msg->lchan = lchan;
122
123 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000124 // Outgoing needs the highest bit set
125 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
126 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000127
128 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000129 rp->len = 2;
Daniel Willmann471712b2008-12-29 01:54:02 +0000130 rp->msg_type = GSM411_MT_RP_ACK_MT;
131 rp->msg_ref = msg_ref;
132
133 DEBUGP(DSMS, "TX: SMS RP ACK\n");
134
135 return gsm0411_sendmsg(msg);
136}
137
Holger Freytherca362a62009-01-04 21:05:01 +0000138#if 0
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000139static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
140 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000141{
142 struct msgb *msg = gsm411_msgb_alloc();
143 struct gsm48_hdr *gh;
144 struct gsm411_rp_hdr *rp;
145
146 msg->lchan = lchan;
147
148 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000149 // Outgoing needs the highest bit set
150 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
151 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000152
153 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
154 rp->msg_type = GSM411_MT_RP_ERROR_MT;
155 rp->msg_ref = msg_ref;
156
157 DEBUGP(DSMS, "TX: SMS RP ERROR\n");
158
159 return gsm0411_sendmsg(msg);
160}
Holger Freytherca362a62009-01-04 21:05:01 +0000161#endif
Daniel Willmann471712b2008-12-29 01:54:02 +0000162
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000163static int gsm411_cp_data(struct msgb *msg)
164{
165 struct gsm48_hdr *gh = msgb_l3(msg);
166 int rc = 0;
167
Daniel Willmann471712b2008-12-29 01:54:02 +0000168 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000169 u_int8_t msg_type = rp_data->msg_type & 0x07;
170
171 switch (msg_type) {
172 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000173 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
174 /* Skip SMSC no and RP-UD length */
175 msg->smsh = &rp_data->data[1] + rp_data->data[1] + 2;
176 gsm411_sms_submit_from_msgb(msg);
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000177 gsm411_send_rp_ack(msg->lchan, (gh->proto_discr & 0xf0)>>4, rp_data->msg_ref);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000178 break;
179 default:
180 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
181 break;
182 }
183
184 return rc;
185}
186
187int gsm0411_rcv_sms(struct msgb *msg)
188{
189 struct gsm48_hdr *gh = msgb_l3(msg);
190 u_int8_t msg_type = gh->msg_type;
191 int rc = 0;
192
193 DEBUGP(DSMS, "SMS Message\n");
194
195 switch(msg_type) {
196 case GSM411_MT_CP_DATA:
197 DEBUGP(DSMS, "SMS CP-DATA\n");
198 rc = gsm411_cp_data(msg);
199 break;
200 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000201 DEBUGP(DSMS, "SMS CP-ACK\n");
202 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000203 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000204 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
205 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000206 default:
207 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
208 break;
209 }
210
211
212 return rc;
213}
214
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000215/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000216#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000217static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000218 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
219 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
220 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
221 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
222 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
223 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
224 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000225};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000226#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000227/* Test TPDU - ALL YOUR */
228static u_int8_t tpdu_test[] = {
229 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
230 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
231 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
232 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000233};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000234#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000235
236int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
237{
238 struct msgb *msg = gsm411_msgb_alloc();
239 struct gsm48_hdr *gh;
240 struct gsm411_rp_hdr *rp;
Holger Freytherca362a62009-01-04 21:05:01 +0000241 u_int8_t *data;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000242
243 msg->lchan = lchan;
244
245 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
246 gh->proto_discr = GSM48_PDISC_SMS;
247 gh->msg_type = GSM411_MT_CP_DATA;
248
249 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmanna3e29842008-12-29 16:03:54 +0000250 rp->len = sizeof(tpdu_test) + 10;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000251 rp->msg_type = GSM411_MT_RP_DATA_MT;
252 rp->msg_ref = 42; /* FIXME: Choose randomly */
Daniel Willmannfad5d0d2008-12-29 16:04:14 +0000253 /* Hardcode OA for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000254 data = (u_int8_t *)msgb_put(msg, 8);
255 data[0] = 0x07;
256 data[1] = 0x91;
257 data[2] = 0x44;
258 data[3] = 0x77;
259 data[4] = 0x58;
260 data[5] = 0x10;
261 data[6] = 0x06;
262 data[7] = 0x50;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000263 data = (u_int8_t *)msgb_put(msg, 1);
264 data[0] = 0;
265
266 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000267 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
268
269 /* RPDU length */
270 data = (u_int8_t *)msgb_put(msg, 1);
271 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000272
273 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
274
275 //memcpy(data, tpdu, smslen);
276 memcpy(data, tpdu_test, sizeof(tpdu_test));
277
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000278 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
279
280 return gsm0411_sendmsg(msg);
281}
282