blob: b0d3a0127eaa76cb5a2f932a88ce3f105f49ea50 [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>
39
Daniel Willmann471712b2008-12-29 01:54:02 +000040#define GSM411_ALLOC_SIZE 1024
41#define GSM411_ALLOC_HEADROOM 128
42
Holger Freythera553d092009-01-04 20:16:25 +000043struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000044{
45 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM);
46}
47
Holger Freythera553d092009-01-04 20:16:25 +000048int gsm0411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000049{
50 if (msg->lchan)
51 msg->trx = msg->lchan->ts->trx;
52
53 msg->l3h = msg->data;
54
55 return rsl_data_request(msg, 0);
56}
57
Daniel Willmanne0fbec82008-12-29 00:44:41 +000058static char *gsm411_7bit_decode(u_int8_t *user_data, u_int8_t length)
59{
60 u_int8_t d_off = 0, b_off = 0;
61 u_int8_t i;
62 char *text = malloc(length+1);
63
64 for (i=0;i<length;i++) {
65 text[i] = ((user_data[d_off] + (user_data[d_off+1]<<8)) & (0x7f<<b_off))>>b_off;
66 b_off += 7;
67 if (b_off >= 8) {
68 d_off += 1;
69 b_off -= 8;
70 }
71 }
72 text[i] = 0;
73 return text;
74}
75
Holger Freytherca362a62009-01-04 21:05:01 +000076#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +000077static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
78{
Daniel Willmann6fe997e2008-12-29 04:20:41 +000079}
Holger Freytherca362a62009-01-04 21:05:01 +000080#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +000081
Daniel Willmanne0fbec82008-12-29 00:44:41 +000082static int gsm411_sms_submit_from_msgb(struct msgb *msg)
83{
84 u_int8_t *smsp = msgb_sms(msg);
85 struct sms_submit *sms;
86
87 sms = malloc(sizeof(*sms));
88 sms->mti = *smsp & 0x03;
89 sms->mms = !!(*smsp & 0x04);
90 sms->vpf = (*smsp & 0x18) >> 3;
91 sms->sri = !!(*smsp & 0x20);
92 sms->udhi= !!(*smsp & 0x40);
93 sms->rp = !!(*smsp & 0x80);
94
95 smsp++;
96 sms->msg_ref = *smsp++;
97
98 /* Skip destination address for now */
99 smsp += 2 + *smsp/2 + *smsp%2;
100
101 sms->pid = *smsp++;
102 sms->dcs = *smsp++;
103 switch (sms->vpf)
104 {
105 case 2: /* relative */
106 sms->vp = *smsp++;
107 break;
108 default:
109 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
110 sms->vpf);
111 }
112 sms->ud_len = *smsp++;
113
Holger Freytherca362a62009-01-04 21:05:01 +0000114 sms->user_data = (u_int8_t *)gsm411_7bit_decode(smsp, sms->ud_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000115
116 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x\n"
117 "PID: 0x%02x, DCS: 0x%02x, UserDataLength: 0x%02x\n"
118 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
119 sms->pid, sms->dcs, sms->ud_len, sms->user_data);
120
121 free(sms);
122
123 return 0;
124}
125
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000126static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
127 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000128{
129 struct msgb *msg = gsm411_msgb_alloc();
130 struct gsm48_hdr *gh;
131 struct gsm411_rp_hdr *rp;
132
133 msg->lchan = lchan;
134
135 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000136 // Outgoing needs the highest bit set
137 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
138 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000139
140 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000141 rp->len = 2;
Daniel Willmann471712b2008-12-29 01:54:02 +0000142 rp->msg_type = GSM411_MT_RP_ACK_MT;
143 rp->msg_ref = msg_ref;
144
145 DEBUGP(DSMS, "TX: SMS RP ACK\n");
146
147 return gsm0411_sendmsg(msg);
148}
149
Holger Freytherca362a62009-01-04 21:05:01 +0000150#if 0
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000151static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
152 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000153{
154 struct msgb *msg = gsm411_msgb_alloc();
155 struct gsm48_hdr *gh;
156 struct gsm411_rp_hdr *rp;
157
158 msg->lchan = lchan;
159
160 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000161 // Outgoing needs the highest bit set
162 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
163 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000164
165 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
166 rp->msg_type = GSM411_MT_RP_ERROR_MT;
167 rp->msg_ref = msg_ref;
168
169 DEBUGP(DSMS, "TX: SMS RP ERROR\n");
170
171 return gsm0411_sendmsg(msg);
172}
Holger Freytherca362a62009-01-04 21:05:01 +0000173#endif
Daniel Willmann471712b2008-12-29 01:54:02 +0000174
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000175static int gsm411_cp_data(struct msgb *msg)
176{
177 struct gsm48_hdr *gh = msgb_l3(msg);
178 int rc = 0;
179
Daniel Willmann471712b2008-12-29 01:54:02 +0000180 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000181 u_int8_t msg_type = rp_data->msg_type & 0x07;
182
183 switch (msg_type) {
184 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000185 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
186 /* Skip SMSC no and RP-UD length */
187 msg->smsh = &rp_data->data[1] + rp_data->data[1] + 2;
188 gsm411_sms_submit_from_msgb(msg);
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000189 gsm411_send_rp_ack(msg->lchan, (gh->proto_discr & 0xf0)>>4, rp_data->msg_ref);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000190 break;
191 default:
192 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
193 break;
194 }
195
196 return rc;
197}
198
199int gsm0411_rcv_sms(struct msgb *msg)
200{
201 struct gsm48_hdr *gh = msgb_l3(msg);
202 u_int8_t msg_type = gh->msg_type;
203 int rc = 0;
204
205 DEBUGP(DSMS, "SMS Message\n");
206
207 switch(msg_type) {
208 case GSM411_MT_CP_DATA:
209 DEBUGP(DSMS, "SMS CP-DATA\n");
210 rc = gsm411_cp_data(msg);
211 break;
212 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000213 DEBUGP(DSMS, "SMS CP-ACK\n");
214 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000215 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000216 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
217 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000218 default:
219 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
220 break;
221 }
222
223
224 return rc;
225}
226
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000227/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000228#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000229static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000230 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
231 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
232 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
233 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
234 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
235 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
236 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000237};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000238#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000239/* Test TPDU - ALL YOUR */
240static u_int8_t tpdu_test[] = {
241 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
242 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
243 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
244 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000245};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000246#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000247
248int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
249{
250 struct msgb *msg = gsm411_msgb_alloc();
251 struct gsm48_hdr *gh;
252 struct gsm411_rp_hdr *rp;
Holger Freytherca362a62009-01-04 21:05:01 +0000253 u_int8_t *data;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000254
255 msg->lchan = lchan;
256
257 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
258 gh->proto_discr = GSM48_PDISC_SMS;
259 gh->msg_type = GSM411_MT_CP_DATA;
260
261 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmanna3e29842008-12-29 16:03:54 +0000262 rp->len = sizeof(tpdu_test) + 10;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000263 rp->msg_type = GSM411_MT_RP_DATA_MT;
264 rp->msg_ref = 42; /* FIXME: Choose randomly */
Daniel Willmannfad5d0d2008-12-29 16:04:14 +0000265 /* Hardcode OA for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000266 data = (u_int8_t *)msgb_put(msg, 8);
267 data[0] = 0x07;
268 data[1] = 0x91;
269 data[2] = 0x44;
270 data[3] = 0x77;
271 data[4] = 0x58;
272 data[5] = 0x10;
273 data[6] = 0x06;
274 data[7] = 0x50;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000275 data = (u_int8_t *)msgb_put(msg, 1);
276 data[0] = 0;
277
278 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000279 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
280
281 /* RPDU length */
282 data = (u_int8_t *)msgb_put(msg, 1);
283 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000284
285 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
286
287 //memcpy(data, tpdu, smslen);
288 memcpy(data, tpdu_test, sizeof(tpdu_test));
289
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000290 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
291
292 return gsm0411_sendmsg(msg);
293}
294