blob: 9d9cde70ddeb510a42ec07c8ed98735a57f3a79b [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
Harald Weltebf5e8df2009-02-03 12:59:45 +00004/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Harald Welte498b0bb2009-01-09 21:27:43 +00005 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * 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>
Harald Weltedb253af2008-12-30 17:56:55 +000030#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000031#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000032
Harald Welte75a983f2008-12-27 21:34:06 +000033#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/msgb.h>
Harald Welte7584aea2009-02-11 11:44:12 +000035#include <openbsc/tlv.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
Daniel Willmanneea93372009-08-13 03:42:07 +020038#include <openbsc/gsm_utils.h>
Harald Welte8470bf22008-12-25 23:28:35 +000039#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000040#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000041#include <openbsc/gsm_04_08.h>
42#include <openbsc/abis_rsl.h>
Holger Freytherca362a62009-01-04 21:05:01 +000043#include <openbsc/chan_alloc.h>
Harald Welte0b4c34e2009-02-09 17:54:43 +000044#include <openbsc/paging.h>
Holger Freyther053e09d2009-02-14 22:51:06 +000045#include <openbsc/signal.h>
Harald Welte45b407a2009-05-23 15:51:12 +000046#include <openbsc/trau_frame.h>
Harald Welte11fa29c2009-02-19 17:24:39 +000047#include <openbsc/trau_mux.h>
Harald Welte805f6442009-07-28 18:25:29 +020048#include <openbsc/rtp_proxy.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020049#include <openbsc/talloc.h>
Harald Weltedcaf5652009-07-23 18:56:43 +020050#include <openbsc/transaction.h>
Harald Welte52b1f982008-12-23 20:25:15 +000051
Harald Welte8470bf22008-12-25 23:28:35 +000052#define GSM48_ALLOC_SIZE 1024
53#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000054
Harald Welte0c389302009-06-10 12:08:54 +080055#define GSM_MAX_FACILITY 128
56#define GSM_MAX_SSVERSION 128
57#define GSM_MAX_USERUSER 128
58
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020059void *tall_locop_ctx;
Harald Welte2cf161b2009-06-20 22:36:41 +020060
Harald Welte805f6442009-07-28 18:25:29 +020061/* should ip.access BTS use direct RTP streams between each other (1),
62 * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
63int ipacc_rtp_direct = 1;
64
Harald Welte09e38af2009-02-16 22:52:23 +000065static const struct tlv_definition rsl_att_tlvdef = {
66 .def = {
67 [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
68 [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
69 [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
70 [GSM48_IE_UTC] = { TLV_TYPE_TV },
71 [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
72 [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
73
74 [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
75 [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
76 [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
77 [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
78 [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
79 [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
80 [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
Harald Welte0c389302009-06-10 12:08:54 +080081 [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
Harald Welte09e38af2009-02-16 22:52:23 +000082 [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
83 [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
Harald Welte0c389302009-06-10 12:08:54 +080084 [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
85 [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
Harald Welte09e38af2009-02-16 22:52:23 +000086 [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
87 [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
88 [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
89 [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
90 [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
91 [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
92 [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
93 [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
94 [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
95 [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
96 [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
97 [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
98 [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
99 [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
Harald Welte0c389302009-06-10 12:08:54 +0800100 [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
101 [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
Harald Welte09e38af2009-02-16 22:52:23 +0000102 /* FIXME: more elements */
103 },
104};
Harald Weltecf5b3592009-05-01 18:28:42 +0000105
106static const char *rr_cause_names[] = {
107 [GSM48_RR_CAUSE_NORMAL] = "Normal event",
108 [GSM48_RR_CAUSE_ABNORMAL_UNSPEC] = "Abnormal release, unspecified",
109 [GSM48_RR_CAUSE_ABNORMAL_UNACCT] = "Abnormal release, channel unacceptable",
110 [GSM48_RR_CAUSE_ABNORMAL_TIMER] = "Abnormal release, timer expired",
111 [GSM48_RR_CAUSE_ABNORMAL_NOACT] = "Abnormal release, no activity on radio path",
112 [GSM48_RR_CAUSE_PREMPTIVE_REL] = "Preemptive release",
113 [GSM48_RR_CAUSE_HNDOVER_IMP] = "Handover impossible, timing advance out of range",
114 [GSM48_RR_CAUSE_CHAN_MODE_UNACCT] = "Channel mode unacceptable",
115 [GSM48_RR_CAUSE_FREQ_NOT_IMPL] = "Frequency not implemented",
116 [GSM48_RR_CAUSE_CALL_CLEARED] = "Call already cleared",
117 [GSM48_RR_CAUSE_SEMANT_INCORR] = "Semantically incorrect message",
118 [GSM48_RR_CAUSE_INVALID_MAND_INF] = "Invalid mandatory information",
119 [GSM48_RR_CAUSE_MSG_TYPE_N] = "Message type non-existant or not implemented",
120 [GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT] = "Message type not compatible with protocol state",
121 [GSM48_RR_CAUSE_COND_IE_ERROR] = "Conditional IE error",
122 [GSM48_RR_CAUSE_NO_CELL_ALLOC_A] = "No cell allocation available",
123 [GSM48_RR_CAUSE_PROT_ERROR_UNSPC] = "Protocol error unspecified",
124};
125
Harald Welte4bfdfe72009-06-10 23:11:52 +0800126static const char *cc_state_names[] = {
127 "NULL",
128 "INITIATED",
129 "illegal state 2",
130 "MO_CALL_PROC",
131 "CALL_DELIVERED",
132 "illegal state 5",
133 "CALL_PRESENT",
134 "CALL_RECEIVED",
135 "CONNECT_REQUEST",
136 "MO_TERM_CALL_CONF",
137 "ACTIVE",
138 "DISCONNECT_REQ",
139 "DISCONNECT_IND",
140 "illegal state 13",
141 "illegal state 14",
142 "illegal state 15",
143 "illegal state 16",
144 "illegal state 17",
145 "illegal state 18",
146 "RELEASE_REQ",
147 "illegal state 20",
148 "illegal state 21",
149 "illegal state 22",
150 "illegal state 23",
151 "illegal state 24",
152 "illegal state 25",
153 "MO_ORIG_MODIFY",
154 "MO_TERM_MODIFY",
155 "CONNECT_IND",
156 "illegal state 29",
157 "illegal state 30",
158 "illegal state 31",
159};
160
161static const char *cc_msg_names[] = {
162 "unknown 0x00",
163 "ALERTING",
164 "CALL_PROC",
165 "PROGRESS",
166 "ESTAB",
167 "SETUP",
168 "ESTAB_CONF",
169 "CONNECT",
170 "CALL_CONF",
171 "START_CC",
172 "unknown 0x0a",
173 "RECALL",
174 "unknown 0x0c",
175 "unknown 0x0d",
176 "EMERG_SETUP",
177 "CONNECT_ACK",
178 "USER_INFO",
179 "unknown 0x11",
180 "unknown 0x12",
181 "MODIFY_REJECT",
182 "unknown 0x14",
183 "unknown 0x15",
184 "unknown 0x16",
185 "MODIFY",
186 "HOLD",
187 "HOLD_ACK",
188 "HOLD_REJ",
189 "unknown 0x1b",
190 "RETR",
191 "RETR_ACK",
192 "RETR_REJ",
193 "MODIFY_COMPL",
194 "unknown 0x20",
195 "unknown 0x21",
196 "unknown 0x22",
197 "unknown 0x23",
198 "unknown 0x24",
199 "DISCONNECT",
200 "unknown 0x26",
201 "unknown 0x27",
202 "unknown 0x28",
203 "unknown 0x29",
204 "RELEASE_COMPL",
205 "unknown 0x2b",
206 "unknown 0x2c",
207 "RELEASE",
208 "unknown 0x2e",
209 "unknown 0x2f",
210 "unknown 0x30",
211 "STOP_DTMF",
212 "STOP_DTMF_ACK",
213 "unknown 0x33",
214 "STATUS_ENQ",
215 "START_DTMF",
216 "START_DTMF_ACK",
217 "START_DTMF_REJ",
218 "unknown 0x38",
219 "CONG_CTRL",
220 "FACILITY",
221 "unknown 0x3b",
222 "STATUS",
223 "unknown 0x3c",
224 "NOTIFY",
225 "unknown 0x3f",
226};
227
Harald Weltecf5b3592009-05-01 18:28:42 +0000228static char strbuf[64];
229
230static const char *rr_cause_name(u_int8_t cause)
231{
232 if (cause < ARRAY_SIZE(rr_cause_names) &&
233 rr_cause_names[cause])
234 return rr_cause_names[cause];
235
236 snprintf(strbuf, sizeof(strbuf), "0x%02x", cause);
237 return strbuf;
238}
239
Harald Weltef7c43522009-06-09 20:24:21 +0000240static void parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
241 int len)
242{
243 memset(rep, 0, sizeof(*rep));
244
245 if (data[0] & 0x80)
246 rep->flags |= MEAS_REP_F_BA1;
247 if (data[0] & 0x40)
248 rep->flags |= MEAS_REP_F_DTX;
Harald Welte5a691b52009-07-05 04:05:44 +0200249 if ((data[1] & 0x40) == 0x00)
Harald Weltef7c43522009-06-09 20:24:21 +0000250 rep->flags |= MEAS_REP_F_VALID;
251
252 rep->rxlev_full = data[0] & 0x3f;
253 rep->rxlev_sub = data[1] & 0x3f;
254 rep->rxqual_full = (data[3] >> 4) & 0x7;
255 rep->rxqual_sub = (data[3] >> 1) & 0x7;
256 rep->num_cell = data[4] >> 6 | ((data[3] & 0x01) << 2);
257 if (rep->num_cell < 1)
258 return;
259
260 /* an encoding nightmare in perfection */
261
262 rep->cell[0].rxlev = data[4] & 0x3f;
263 rep->cell[0].bcch_freq = data[5] >> 2;
264 rep->cell[0].bsic = ((data[5] & 0x03) << 3) | (data[6] >> 5);
265 if (rep->num_cell < 2)
266 return;
267
268 rep->cell[1].rxlev = ((data[6] & 0x1f) << 1) | (data[7] >> 7);
269 rep->cell[1].bcch_freq = (data[7] >> 2) & 0x1f;
270 rep->cell[1].bsic = ((data[7] & 0x03) << 4) | (data[8] >> 4);
271 if (rep->num_cell < 3)
272 return;
273
274 rep->cell[2].rxlev = ((data[8] & 0x0f) << 2) | (data[9] >> 6);
275 rep->cell[2].bcch_freq = (data[9] >> 1) & 0x1f;
276 rep->cell[2].bsic = ((data[9] & 0x01) << 6) | (data[10] >> 3);
277 if (rep->num_cell < 4)
278 return;
279
280 rep->cell[3].rxlev = ((data[10] & 0x07) << 3) | (data[11] >> 5);
281 rep->cell[3].bcch_freq = data[11] & 0x1f;
282 rep->cell[3].bsic = data[12] >> 2;
283 if (rep->num_cell < 5)
284 return;
285
286 rep->cell[4].rxlev = ((data[12] & 0x03) << 4) | (data[13] >> 4);
287 rep->cell[4].bcch_freq = ((data[13] & 0xf) << 1) | (data[14] >> 7);
288 rep->cell[4].bsic = (data[14] >> 1) & 0x3f;
289 if (rep->num_cell < 6)
290 return;
291
292 rep->cell[5].rxlev = ((data[14] & 0x01) << 5) | (data[15] >> 3);
293 rep->cell[5].bcch_freq = ((data[15] & 0x07) << 2) | (data[16] >> 6);
294 rep->cell[5].bsic = data[16] & 0x3f;
295}
296
Holger Freytherd51524f2009-06-09 08:27:07 +0000297int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
Harald Welte65e74cc2008-12-29 01:55:35 +0000298static int gsm48_tx_simple(struct gsm_lchan *lchan,
299 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +0000300static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte65e74cc2008-12-29 01:55:35 +0000301
Harald Welte52b1f982008-12-23 20:25:15 +0000302struct gsm_lai {
303 u_int16_t mcc;
304 u_int16_t mnc;
305 u_int16_t lac;
306};
307
Holger Freythere97f7fb2008-12-31 18:52:11 +0000308static int reject_cause = 0;
309void gsm0408_set_reject_cause(int cause)
310{
311 reject_cause = cause;
312}
313
Harald Welte4bfdfe72009-06-10 23:11:52 +0800314static u_int32_t new_callref = 0x80000001;
315
Holger Freyther73487a22008-12-31 18:53:57 +0000316static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
317 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +0000318{
319 if (!subscriber)
320 return 0;
321
Holger Freyther73487a22008-12-31 18:53:57 +0000322 /*
323 * Do not send accept yet as more information should arrive. Some
324 * phones will not send us the information and we will have to check
325 * what we want to do with that.
326 */
327 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
328 return 0;
329
Jan Luebbe06513f22009-08-12 12:48:00 +0200330 switch (subscriber->net->auth_policy) {
331 case GSM_AUTH_POLICY_CLOSED:
332 return subscriber->authorized;
Harald Welte (local)aa9dc192009-08-13 13:49:51 +0200333 case GSM_AUTH_POLICY_TOKEN:
Harald Welte (local)ee9afe32009-08-13 20:44:23 +0200334 if (subscriber->authorized)
335 return subscriber->authorized;
Harald Welte (local)aa9dc192009-08-13 13:49:51 +0200336 return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT);
Jan Luebbe06513f22009-08-12 12:48:00 +0200337 case GSM_AUTH_POLICY_ACCEPT_ALL:
Holger Freyther89824fc2008-12-30 16:18:18 +0000338 return 1;
Jan Luebbe06513f22009-08-12 12:48:00 +0200339 default:
340 return 0;
341 }
Holger Freyther89824fc2008-12-30 16:18:18 +0000342}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000343
Holger Freyther73487a22008-12-31 18:53:57 +0000344static void release_loc_updating_req(struct gsm_lchan *lchan)
345{
Harald Welte179f0642008-12-31 23:59:18 +0000346 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +0000347 return;
348
Harald Welteff117a82009-05-23 05:22:08 +0000349 bsc_del_timer(&lchan->loc_operation->updating_timer);
Harald Welte2cf161b2009-06-20 22:36:41 +0200350 talloc_free(lchan->loc_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000351 lchan->loc_operation = 0;
Holger Freyther3eaa7922009-01-01 02:59:03 +0000352 put_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000353}
354
355static void allocate_loc_updating_req(struct gsm_lchan *lchan)
356{
Holger Freyther67b4b9a2009-01-01 03:46:11 +0000357 use_lchan(lchan);
Holger Freyther73487a22008-12-31 18:53:57 +0000358 release_loc_updating_req(lchan);
359
Harald Welte470ec292009-06-26 20:25:23 +0200360 lchan->loc_operation = talloc_zero(tall_locop_ctx,
361 struct gsm_loc_updating_operation);
Holger Freyther73487a22008-12-31 18:53:57 +0000362}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000363
Holger Freytherd51524f2009-06-09 08:27:07 +0000364static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
365{
366 u_int32_t tmsi;
367
368 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
Harald Welteee5ad162009-08-09 19:07:00 +0200369 int rc;
370
Holger Freytherd51524f2009-06-09 08:27:07 +0000371 db_subscriber_alloc_tmsi(lchan->subscr);
Holger Freytherd51524f2009-06-09 08:27:07 +0000372 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
373 release_loc_updating_req(lchan);
Harald Welteee5ad162009-08-09 19:07:00 +0200374 rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
375 /* call subscr_update after putting the loc_upd_acc
376 * in the transmit queue, since S_SUBSCR_ATTACHED might
377 * trigger further action like SMS delivery */
378 subscr_update(lchan->subscr, msg->trx->bts,
379 GSM_SUBSCRIBER_UPDATE_ATTACHED);
380 return rc;
Holger Freytherd51524f2009-06-09 08:27:07 +0000381 }
382
383 return 0;
384}
385
Holger Freyther7c19f742009-06-06 13:54:35 +0000386static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
387 void *handler_data, void *signal_data)
388{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800389 struct gsm_trans *trans, *temp;
390
Holger Freyther7c19f742009-06-06 13:54:35 +0000391 if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
392 return 0;
393
394 /*
395 * Cancel any outstanding location updating request
396 * operation taking place on the lchan.
397 */
Harald Welte1a5c6bd2009-07-04 09:35:21 +0200398 struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
Harald Weltec05677b2009-06-26 20:17:06 +0200399 if (!lchan)
400 return 0;
401
Holger Freyther7c19f742009-06-06 13:54:35 +0000402 release_loc_updating_req(lchan);
403
Harald Welte4bfdfe72009-06-10 23:11:52 +0800404 /* Free all transactions that are associated with the released lchan */
Harald Weltedcaf5652009-07-23 18:56:43 +0200405 /* FIXME: this is not neccessarily the right thing to do, we should
406 * only set trans->lchan to NULL and wait for another lchan to be
407 * established to the same MM entity (phone/subscriber) */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800408 llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
409 if (trans->lchan == lchan)
Harald Weltedcaf5652009-07-23 18:56:43 +0200410 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +0800411 }
412
Holger Freyther7c19f742009-06-06 13:54:35 +0000413 return 0;
414}
415
Harald Welte52b1f982008-12-23 20:25:15 +0000416static void to_bcd(u_int8_t *bcd, u_int16_t val)
417{
Harald Welte4b634542008-12-27 01:55:51 +0000418 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000419 val = val / 10;
420 bcd[1] = val % 10;
421 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000422 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000423 val = val / 10;
424}
425
Holger Freyther17746612008-12-28 16:32:44 +0000426void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000427 u_int16_t mnc, u_int16_t lac)
428{
429 u_int8_t bcd[3];
430
431 to_bcd(bcd, mcc);
432 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
433 lai48->digits[1] = bcd[2];
434
435 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000436 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
437#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000438 lai48->digits[1] |= bcd[2] << 4;
439 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000440#else
441 lai48->digits[1] |= 0xf << 4;
442 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
443#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000444
Harald Welte4b634542008-12-27 01:55:51 +0000445 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000446}
447
Harald Welte255539c2008-12-28 02:26:27 +0000448#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000449#define MID_TMSI_LEN (TMSI_LEN + 2)
450
Harald Welte255539c2008-12-28 02:26:27 +0000451int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000452{
Harald Welte65e74cc2008-12-29 01:55:35 +0000453 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000454
Harald Welte4b634542008-12-27 01:55:51 +0000455 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000456 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000457 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000458 *tptr = htonl(tmsi);
459
460 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000461}
462
Harald Welte09e38af2009-02-16 22:52:23 +0000463static const char bcd_num_digits[] = {
464 '0', '1', '2', '3', '4', '5', '6', '7',
465 '8', '9', '*', '#', 'a', 'b', 'c', '\0'
466};
467
Harald Welte0c389302009-06-10 12:08:54 +0800468/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
469int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
470 int h_len)
Harald Welte09e38af2009-02-16 22:52:23 +0000471{
472 u_int8_t in_len = bcd_lv[0];
473 int i;
474
Harald Welte0c389302009-06-10 12:08:54 +0800475 for (i = 1 + h_len; i <= in_len; i++) {
Harald Welte09e38af2009-02-16 22:52:23 +0000476 /* lower nibble */
477 output_len--;
478 if (output_len <= 1)
479 break;
480 *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
481
482 /* higher nibble */
483 output_len--;
484 if (output_len <= 1)
485 break;
486 *output++ = bcd_num_digits[bcd_lv[i] >> 4];
487 }
488 if (output_len >= 1)
489 *output++ = '\0';
490
Harald Welte0c389302009-06-10 12:08:54 +0800491 return 0;
Harald Welte09e38af2009-02-16 22:52:23 +0000492}
493
494/* convert a single ASCII character to call-control BCD */
495static int asc_to_bcd(const char asc)
496{
497 int i;
498
499 for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
500 if (bcd_num_digits[i] == asc)
501 return i;
502 }
503 return -EINVAL;
504}
505
Harald Welte0c389302009-06-10 12:08:54 +0800506/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
Harald Welte09e38af2009-02-16 22:52:23 +0000507int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
Harald Welte0c389302009-06-10 12:08:54 +0800508 int h_len, const char *input)
Harald Welte09e38af2009-02-16 22:52:23 +0000509{
510 int in_len = strlen(input);
511 int i;
Harald Welte0c389302009-06-10 12:08:54 +0800512 u_int8_t *bcd_cur = bcd_lv + 1 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000513
514 /* two digits per byte, plus type byte */
Harald Welte0c389302009-06-10 12:08:54 +0800515 bcd_lv[0] = in_len/2 + h_len;
Harald Welte09e38af2009-02-16 22:52:23 +0000516 if (in_len % 2)
517 bcd_lv[0]++;
518
Harald Welte0c389302009-06-10 12:08:54 +0800519 if (bcd_lv[0] > max_len)
520 return -EIO;
Harald Welte09e38af2009-02-16 22:52:23 +0000521
522 for (i = 0; i < in_len; i++) {
523 int rc = asc_to_bcd(input[i]);
524 if (rc < 0)
525 return rc;
526 if (i % 2 == 0)
527 *bcd_cur = rc;
528 else
529 *bcd_cur++ |= (rc << 4);
530 }
531 /* append padding nibble in case of odd length */
532 if (i % 2)
533 *bcd_cur++ |= 0xf0;
534
535 /* return how many bytes we used */
536 return (bcd_cur - bcd_lv);
537}
538
Harald Welte0c389302009-06-10 12:08:54 +0800539/* decode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800540static int decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
Harald Welte0c389302009-06-10 12:08:54 +0800541 const u_int8_t *lv)
542{
543 u_int8_t in_len = lv[0];
544 int i, s;
545
546 if (in_len < 1)
547 return -EINVAL;
548
Harald Welte4bfdfe72009-06-10 23:11:52 +0800549 bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
Harald Welte0c389302009-06-10 12:08:54 +0800550
551 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800552 bcap->transfer = lv[1] & 0x07;
553 bcap->mode = (lv[1] & 0x08) >> 3;
554 bcap->coding = (lv[1] & 0x10) >> 4;
555 bcap->radio = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800556
557 i = 1;
558 s = 0;
559 while(!(lv[i] & 0x80)) {
560 i++; /* octet 3a etc */
561 if (in_len < i)
562 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800563 bcap->speech_ver[s++] = lv[i] & 0x0f;
564 bcap->speech_ver[s] = -1; /* end of list */
Harald Welte0c389302009-06-10 12:08:54 +0800565 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800566 bcap->speech_ctm = (lv[i] & 0x20) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800567 if (s == 7) /* maximum speech versions + end of list */
568 return 0;
569 }
570
571 return 0;
572}
573
574/* encode 'bearer capability' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800575static int encode_bearer_cap(struct msgb *msg, int lv_only,
576 const struct gsm_mncc_bearer_cap *bcap)
Harald Welte0c389302009-06-10 12:08:54 +0800577{
578 u_int8_t lv[32 + 1];
579 int i, s;
580
Harald Welte4bfdfe72009-06-10 23:11:52 +0800581 lv[1] = bcap->transfer;
582 lv[1] |= bcap->mode << 3;
583 lv[1] |= bcap->coding << 4;
584 lv[1] |= bcap->radio << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800585
586 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800587 for (s = 0; bcap->speech_ver[s] >= 0; s++) {
Harald Welte0c389302009-06-10 12:08:54 +0800588 i++; /* octet 3a etc */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800589 lv[i] = bcap->speech_ver[s];
Harald Welte0c389302009-06-10 12:08:54 +0800590 if (i == 2) /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800591 lv[i] |= bcap->speech_ctm << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800592 }
593 lv[i] |= 0x80; /* last IE of octet 3 etc */
594
595 lv[0] = i;
596 if (lv_only)
597 msgb_lv_put(msg, lv[0], lv+1);
598 else
599 msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
600
601 return 0;
602}
603
604/* decode 'call control cap' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800605static int decode_cccap(struct gsm_mncc_cccap *ccap, const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800606{
607 u_int8_t in_len = lv[0];
608
609 if (in_len < 1)
610 return -EINVAL;
611
612 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800613 ccap->dtmf = lv[1] & 0x01;
614 ccap->pcp = (lv[1] & 0x02) >> 1;
Harald Welte0c389302009-06-10 12:08:54 +0800615
616 return 0;
617}
618
619/* decode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800620static int decode_called(struct gsm_mncc_number *called,
621 const u_int8_t *lv)
Harald Welte0c389302009-06-10 12:08:54 +0800622{
623 u_int8_t in_len = lv[0];
624
625 if (in_len < 1)
626 return -EINVAL;
627
628 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800629 called->plan = lv[1] & 0x0f;
630 called->type = (lv[1] & 0x70) >> 4;
Harald Welte0c389302009-06-10 12:08:54 +0800631
632 /* octet 4..N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800633 decode_bcd_number(called->number, sizeof(called->number), lv, 1);
Harald Welte0c389302009-06-10 12:08:54 +0800634
635 return 0;
636}
637
638/* encode 'called party BCD number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800639static int encode_called(struct msgb *msg,
640 const struct gsm_mncc_number *called)
Harald Welte0c389302009-06-10 12:08:54 +0800641{
642 u_int8_t lv[18];
643 int ret;
644
645 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800646 lv[1] = called->plan;
647 lv[1] |= called->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800648
649 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800650 ret = encode_bcd_number(lv, sizeof(lv), 1, called->number);
Harald Welte0c389302009-06-10 12:08:54 +0800651 if (ret < 0)
652 return ret;
653
654 msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
655
656 return 0;
657}
658
659/* encode callerid of various IEs */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800660static int encode_callerid(struct msgb *msg, int ie,
661 const struct gsm_mncc_number *callerid)
Harald Welte0c389302009-06-10 12:08:54 +0800662{
663 u_int8_t lv[13];
664 int h_len = 1;
665 int ret;
666
667 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800668 lv[1] = callerid->plan;
669 lv[1] |= callerid->type << 4;
Harald Welte0c389302009-06-10 12:08:54 +0800670
Harald Welte4bfdfe72009-06-10 23:11:52 +0800671 if (callerid->present || callerid->screen) {
Harald Welte0c389302009-06-10 12:08:54 +0800672 /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800673 lv[2] = callerid->screen;
674 lv[2] |= callerid->present << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800675 lv[2] |= 0x80;
676 h_len++;
677 } else
678 lv[1] |= 0x80;
679
680 /* octet 4..N, octet 2 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800681 ret = encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
Harald Welte0c389302009-06-10 12:08:54 +0800682 if (ret < 0)
683 return ret;
684
685 msgb_tlv_put(msg, ie, lv[0], lv+1);
686
687 return 0;
688}
689
690/* decode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800691static int decode_cause(struct gsm_mncc_cause *cause,
Harald Welte0c389302009-06-10 12:08:54 +0800692 const u_int8_t *lv)
693{
694 u_int8_t in_len = lv[0];
695 int i;
696
697 if (in_len < 2)
698 return -EINVAL;
699
Harald Welte4bfdfe72009-06-10 23:11:52 +0800700 cause->diag_len = 0;
Harald Welte0c389302009-06-10 12:08:54 +0800701
702 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800703 cause->location = lv[1] & 0x0f;
704 cause->coding = (lv[1] & 0x60) >> 5;
Harald Welte0c389302009-06-10 12:08:54 +0800705
706 i = 1;
707 if (!(lv[i] & 0x80)) {
708 i++; /* octet 3a */
709 if (in_len < i+1)
710 return 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800711 cause->rec = 1;
712 cause->rec_val = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800713
714 }
715 i++;
716
717 /* octet 4 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800718 cause->value = lv[i] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800719 i++;
720
721 if (in_len < i) /* no diag */
722 return 0;
723
724 if (in_len - (i-1) > 32) /* maximum 32 octets */
725 return 0;
726
727 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800728 memcpy(cause->diag, lv + i, in_len - (i-1));
729 cause->diag_len = in_len - (i-1);
Harald Welte0c389302009-06-10 12:08:54 +0800730
731 return 0;
732}
733
734/* encode 'cause' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800735static int encode_cause(struct msgb *msg, int lv_only,
736 const struct gsm_mncc_cause *cause)
Harald Welte0c389302009-06-10 12:08:54 +0800737{
738 u_int8_t lv[32+4];
739 int i;
740
Harald Welte4bfdfe72009-06-10 23:11:52 +0800741 if (cause->diag_len > 32)
Harald Welte0c389302009-06-10 12:08:54 +0800742 return -EINVAL;
743
744 /* octet 3 */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800745 lv[1] = cause->location;
746 lv[1] |= cause->coding << 5;
Harald Welte0c389302009-06-10 12:08:54 +0800747
748 i = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800749 if (cause->rec) {
Harald Welte0c389302009-06-10 12:08:54 +0800750 i++; /* octet 3a */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800751 lv[i] = cause->rec_val;
Harald Welte0c389302009-06-10 12:08:54 +0800752 }
753 lv[i] |= 0x80; /* end of octet 3 */
754
755 /* octet 4 */
756 i++;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800757 lv[i] = 0x80 | cause->value;
Harald Welte0c389302009-06-10 12:08:54 +0800758
759 /* octet 5-N */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800760 if (cause->diag_len) {
761 memcpy(lv + i, cause->diag, cause->diag_len);
762 i += cause->diag_len;
Harald Welte0c389302009-06-10 12:08:54 +0800763 }
764
765 lv[0] = i;
766 if (lv_only)
767 msgb_lv_put(msg, lv[0], lv+1);
768 else
769 msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
770
771 return 0;
772}
773
774/* encode 'calling number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800775static int encode_calling(struct msgb *msg,
776 const struct gsm_mncc_number *calling)
Harald Welte0c389302009-06-10 12:08:54 +0800777{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800778 return encode_callerid(msg, GSM48_IE_CALLING_BCD, calling);
Harald Welte0c389302009-06-10 12:08:54 +0800779}
780
781/* encode 'connected number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800782static int encode_connected(struct msgb *msg,
783 const struct gsm_mncc_number *connected)
Harald Welte0c389302009-06-10 12:08:54 +0800784{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800785 return encode_callerid(msg, GSM48_IE_CONN_BCD, connected);
Harald Welte0c389302009-06-10 12:08:54 +0800786}
787
788/* encode 'redirecting number' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800789static int encode_redirecting(struct msgb *msg,
790 const struct gsm_mncc_number *redirecting)
Harald Welte0c389302009-06-10 12:08:54 +0800791{
Harald Welte4bfdfe72009-06-10 23:11:52 +0800792 return encode_callerid(msg, GSM48_IE_REDIR_BCD, redirecting);
Harald Welte0c389302009-06-10 12:08:54 +0800793}
794
795/* decode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800796static int decode_facility(struct gsm_mncc_facility *facility,
Harald Welte0c389302009-06-10 12:08:54 +0800797 const u_int8_t *lv)
798{
799 u_int8_t in_len = lv[0];
800
801 if (in_len < 1)
802 return -EINVAL;
803
Harald Welte4bfdfe72009-06-10 23:11:52 +0800804 if (in_len > sizeof(facility->info))
Harald Welte0c389302009-06-10 12:08:54 +0800805 return -EINVAL;
806
Harald Welte4bfdfe72009-06-10 23:11:52 +0800807 memcpy(facility->info, lv+1, in_len);
808 facility->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800809
810 return 0;
811}
812
813/* encode 'facility' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800814static int encode_facility(struct msgb *msg, int lv_only,
815 const struct gsm_mncc_facility *facility)
Harald Welte0c389302009-06-10 12:08:54 +0800816{
817 u_int8_t lv[GSM_MAX_FACILITY + 1];
818
Harald Welte4bfdfe72009-06-10 23:11:52 +0800819 if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
Harald Welte0c389302009-06-10 12:08:54 +0800820 return -EINVAL;
821
Harald Welte4bfdfe72009-06-10 23:11:52 +0800822 memcpy(lv+1, facility->info, facility->len);
823 lv[0] = facility->len;
Harald Welte0c389302009-06-10 12:08:54 +0800824 if (lv_only)
825 msgb_lv_put(msg, lv[0], lv+1);
826 else
827 msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
828
829 return 0;
830}
831
832/* decode 'notify' */
833static int decode_notify(int *notify, const u_int8_t *v)
834{
835 *notify = v[0] & 0x7f;
836
837 return 0;
838}
839
840/* encode 'notify' */
841static int encode_notify(struct msgb *msg, int notify)
842{
843 msgb_v_put(msg, notify | 0x80);
844
845 return 0;
846}
847
848/* encode 'signal' */
849static int encode_signal(struct msgb *msg, int signal)
850{
851 msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
852
853 return 0;
854}
855
856/* decode 'keypad' */
857static int decode_keypad(int *keypad, const u_int8_t *lv)
858{
859 u_int8_t in_len = lv[0];
860
861 if (in_len < 1)
862 return -EINVAL;
863
864 *keypad = lv[1] & 0x7f;
865
866 return 0;
867}
868
869/* encode 'keypad' */
870static int encode_keypad(struct msgb *msg, int keypad)
871{
872 msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
873
874 return 0;
875}
876
877/* decode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800878static int decode_progress(struct gsm_mncc_progress *progress,
Harald Welte0c389302009-06-10 12:08:54 +0800879 const u_int8_t *lv)
880{
881 u_int8_t in_len = lv[0];
882
883 if (in_len < 2)
884 return -EINVAL;
885
Harald Welte4bfdfe72009-06-10 23:11:52 +0800886 progress->coding = (lv[1] & 0x60) >> 5;
887 progress->location = lv[1] & 0x0f;
888 progress->descr = lv[2] & 0x7f;
Harald Welte0c389302009-06-10 12:08:54 +0800889
890 return 0;
891}
892
893/* encode 'progress' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800894static int encode_progress(struct msgb *msg, int lv_only,
895 const struct gsm_mncc_progress *p)
Harald Welte0c389302009-06-10 12:08:54 +0800896{
897 u_int8_t lv[3];
898
899 lv[0] = 2;
Harald Welte4bfdfe72009-06-10 23:11:52 +0800900 lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
901 lv[2] = 0x80 | (p->descr & 0x7f);
Harald Welte0c389302009-06-10 12:08:54 +0800902 if (lv_only)
903 msgb_lv_put(msg, lv[0], lv+1);
904 else
905 msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
906
907 return 0;
908}
909
910/* decode 'user-user' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800911static int decode_useruser(struct gsm_mncc_useruser *uu,
Harald Welte0c389302009-06-10 12:08:54 +0800912 const u_int8_t *lv)
913{
914 u_int8_t in_len = lv[0];
Harald Welte4bfdfe72009-06-10 23:11:52 +0800915 char *info = uu->info;
916 int info_len = sizeof(uu->info);
Harald Welte0c389302009-06-10 12:08:54 +0800917 int i;
918
919 if (in_len < 1)
920 return -EINVAL;
921
Harald Welte4bfdfe72009-06-10 23:11:52 +0800922 uu->proto = lv[1];
Harald Welte0c389302009-06-10 12:08:54 +0800923
924 for (i = 2; i <= in_len; i++) {
925 info_len--;
926 if (info_len <= 1)
927 break;
928 *info++ = lv[i];
929 }
930 if (info_len >= 1)
931 *info++ = '\0';
932
933 return 0;
934}
935
936/* encode 'useruser' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800937static int encode_useruser(struct msgb *msg, int lv_only,
938 const struct gsm_mncc_useruser *uu)
Harald Welte0c389302009-06-10 12:08:54 +0800939{
940 u_int8_t lv[GSM_MAX_USERUSER + 2];
941
Harald Welte4bfdfe72009-06-10 23:11:52 +0800942 if (strlen(uu->info) > GSM_MAX_USERUSER)
Harald Welte0c389302009-06-10 12:08:54 +0800943 return -EINVAL;
944
Harald Welte4bfdfe72009-06-10 23:11:52 +0800945 lv[0] = 1 + strlen(uu->info);
946 lv[1] = uu->proto;
947 memcpy(lv + 2, uu->info, strlen(uu->info));
Harald Welte0c389302009-06-10 12:08:54 +0800948 if (lv_only)
949 msgb_lv_put(msg, lv[0], lv+1);
950 else
951 msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
952
953 return 0;
954}
955
956/* decode 'ss version' */
Harald Welte4bfdfe72009-06-10 23:11:52 +0800957static int decode_ssversion(struct gsm_mncc_ssversion *ssv,
Harald Welte0c389302009-06-10 12:08:54 +0800958 const u_int8_t *lv)
959{
960 u_int8_t in_len = lv[0];
961
Harald Welte4bfdfe72009-06-10 23:11:52 +0800962 if (in_len < 1 || in_len < sizeof(ssv->info))
Harald Welte0c389302009-06-10 12:08:54 +0800963 return -EINVAL;
964
Harald Welte4bfdfe72009-06-10 23:11:52 +0800965 memcpy(ssv->info, lv + 1, in_len);
966 ssv->len = in_len;
Harald Welte0c389302009-06-10 12:08:54 +0800967
968 return 0;
969}
970
971/* encode 'more data' */
972static int encode_more(struct msgb *msg)
973{
974 u_int8_t *ie;
975
976 ie = msgb_put(msg, 1);
977 ie[0] = GSM48_IE_MORE_DATA;
978
979 return 0;
980}
981
Holger Freyther819dd202009-01-04 03:52:50 +0000982struct msgb *gsm48_msgb_alloc(void)
Harald Welte8470bf22008-12-25 23:28:35 +0000983{
Harald Welte966636f2009-06-26 19:39:35 +0200984 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
985 "GSM 04.08");
Harald Welte8470bf22008-12-25 23:28:35 +0000986}
987
Harald Welte39e2ead2009-07-23 21:13:03 +0200988int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
Harald Welte52b1f982008-12-23 20:25:15 +0000989{
Harald Welte39e2ead2009-07-23 21:13:03 +0200990 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
991
992 /* if we get passed a transaction reference, do some common
993 * work that the caller no longer has to do */
994 if (trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +0200995 gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
Harald Welte39e2ead2009-07-23 21:13:03 +0200996 msg->lchan = trans->lchan;
997 }
998
Harald Welte65e74cc2008-12-29 01:55:35 +0000999 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +00001000 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +00001001
Harald Welte4bfdfe72009-06-10 23:11:52 +08001002 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
1003 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
1004 "Sending '%s' to MS.\n", msg->trx->bts->nr,
1005 msg->trx->nr, msg->lchan->ts->nr,
1006 gh->proto_discr & 0xf0,
1007 cc_msg_names[gh->msg_type & 0x3f]);
1008 else
1009 DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
1010 "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
1011 msg->trx->nr, msg->lchan->ts->nr,
1012 gh->proto_discr, gh->msg_type);
Harald Welte65e74cc2008-12-29 01:55:35 +00001013 }
1014
Harald Welte4b634542008-12-27 01:55:51 +00001015 msg->l3h = msg->data;
1016
Harald Welte8470bf22008-12-25 23:28:35 +00001017 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001018}
1019
Holger Freyther429e7762008-12-30 13:28:30 +00001020/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +00001021int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +00001022{
Harald Welte8470bf22008-12-25 23:28:35 +00001023 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001024 struct gsm48_hdr *gh;
1025
Harald Welte8470bf22008-12-25 23:28:35 +00001026 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001027
1028 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1029 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +00001030 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +00001031 gh->data[0] = cause;
1032
Harald Weltedb253af2008-12-30 17:56:55 +00001033 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
1034
Harald Welte39e2ead2009-07-23 21:13:03 +02001035 return gsm48_sendmsg(msg, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +00001036}
1037
1038/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +00001039int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +00001040{
Harald Welte8470bf22008-12-25 23:28:35 +00001041 struct gsm_bts *bts = lchan->ts->trx->bts;
1042 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +00001043 struct gsm48_hdr *gh;
1044 struct gsm48_loc_area_id *lai;
1045 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +00001046 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001047
Harald Welte8470bf22008-12-25 23:28:35 +00001048 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +00001049
1050 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1051 gh->proto_discr = GSM48_PDISC_MM;
1052 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
1053
1054 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +00001055 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +00001056 bts->network->network_code, bts->location_area_code);
1057
1058 mid = msgb_put(msg, MID_TMSI_LEN);
1059 generate_mid_from_tmsi(mid, tmsi);
1060
1061 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
1062
Harald Welte39e2ead2009-07-23 21:13:03 +02001063 ret = gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001064
Harald Welteee5ad162009-08-09 19:07:00 +02001065 /* send MM INFO with network name */
Harald Weltedb253af2008-12-30 17:56:55 +00001066 ret = gsm48_tx_mm_info(lchan);
Harald Weltedb253af2008-12-30 17:56:55 +00001067
Holger Freyther07cc8d82008-12-29 06:23:46 +00001068 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001069}
1070
Harald Weltefc977a82008-12-27 10:19:37 +00001071static char bcd2char(u_int8_t bcd)
1072{
1073 if (bcd < 0xa)
1074 return '0' + bcd;
1075 else
1076 return 'A' + (bcd - 0xa);
1077}
1078
Harald Weltebf5e8df2009-02-03 12:59:45 +00001079/* Convert Mobile Identity (10.5.1.4) to string */
Harald Weltefc977a82008-12-27 10:19:37 +00001080static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
1081{
1082 int i;
1083 u_int8_t mi_type;
1084 char *str_cur = string;
Harald Welte4ed0e922009-01-10 03:17:30 +00001085 u_int32_t tmsi;
Harald Weltefc977a82008-12-27 10:19:37 +00001086
1087 mi_type = mi[0] & GSM_MI_TYPE_MASK;
1088
1089 switch (mi_type) {
1090 case GSM_MI_TYPE_NONE:
1091 break;
1092 case GSM_MI_TYPE_TMSI:
Harald Welte4ed0e922009-01-10 03:17:30 +00001093 /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
1094 if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
1095 memcpy(&tmsi, &mi[1], 4);
1096 tmsi = ntohl(tmsi);
1097 return snprintf(string, str_len, "%u", tmsi);
Harald Weltefc977a82008-12-27 10:19:37 +00001098 }
1099 break;
1100 case GSM_MI_TYPE_IMSI:
1101 case GSM_MI_TYPE_IMEI:
1102 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +00001103 *str_cur++ = bcd2char(mi[0] >> 4);
1104
1105 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +00001106 if (str_cur + 2 >= string + str_len)
1107 return str_cur - string;
1108 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +00001109 /* skip last nibble in last input byte when GSM_EVEN */
1110 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
1111 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +00001112 }
1113 break;
1114 default:
1115 break;
1116 }
Harald Weltefc977a82008-12-27 10:19:37 +00001117 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +00001118
Harald Weltefc977a82008-12-27 10:19:37 +00001119 return str_cur - string;
1120}
1121
Harald Weltebf5e8df2009-02-03 12:59:45 +00001122/* Transmit Chapter 9.2.10 Identity Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001123static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
1124{
1125 struct msgb *msg = gsm48_msgb_alloc();
1126 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +00001127
Harald Welte231ad4f2008-12-27 11:15:38 +00001128 msg->lchan = lchan;
1129
1130 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1131 gh->proto_discr = GSM48_PDISC_MM;
1132 gh->msg_type = GSM48_MT_MM_ID_REQ;
1133 gh->data[0] = id_type;
1134
Harald Welte39e2ead2009-07-23 21:13:03 +02001135 return gsm48_sendmsg(msg, NULL);
Harald Welte231ad4f2008-12-27 11:15:38 +00001136}
1137
1138#define MI_SIZE 32
1139
Harald Weltebf5e8df2009-02-03 12:59:45 +00001140/* Parse Chapter 9.2.11 Identity Response */
Harald Welte231ad4f2008-12-27 11:15:38 +00001141static int mm_rx_id_resp(struct msgb *msg)
1142{
1143 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +00001144 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001145 struct gsm_bts *bts = lchan->ts->trx->bts;
1146 struct gsm_network *net = bts->network;
Harald Welte231ad4f2008-12-27 11:15:38 +00001147 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
1148 char mi_string[MI_SIZE];
1149
1150 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +00001151 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +00001152 mi_type, mi_string);
1153
Harald Welte75a983f2008-12-27 21:34:06 +00001154 switch (mi_type) {
1155 case GSM_MI_TYPE_IMSI:
Jan Luebbe370b41d2009-08-12 10:19:34 +02001156 /* look up subscriber based on IMSI, create if not found */
1157 if (!lchan->subscr) {
1158 lchan->subscr = subscr_get_by_imsi(net, mi_string);
Harald Welte (local)aa9dc192009-08-13 13:49:51 +02001159 if (!lchan->subscr)
1160 lchan->subscr = db_create_subscriber(net, mi_string);
Jan Luebbeb0dfc312009-08-12 10:12:52 +02001161 }
Holger Freyther73487a22008-12-31 18:53:57 +00001162 if (lchan->loc_operation)
1163 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001164 break;
1165 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +00001166 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +00001167 /* update subscribe <-> IMEI mapping */
1168 if (lchan->subscr)
1169 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +00001170 if (lchan->loc_operation)
1171 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +00001172 break;
1173 }
Holger Freyther73487a22008-12-31 18:53:57 +00001174
1175 /* Check if we can let the mobile station enter */
Holger Freytherd51524f2009-06-09 08:27:07 +00001176 return gsm0408_authorize(lchan, msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001177}
1178
Harald Welte255539c2008-12-28 02:26:27 +00001179
1180static void loc_upd_rej_cb(void *data)
1181{
1182 struct gsm_lchan *lchan = data;
1183
Holger Freyther73487a22008-12-31 18:53:57 +00001184 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +00001185 gsm0408_loc_upd_rej(lchan, reject_cause);
Holger Freyther67b4b9a2009-01-01 03:46:11 +00001186 lchan_auto_release(lchan);
Harald Welte255539c2008-12-28 02:26:27 +00001187}
1188
Holger Freytherb7193e42008-12-29 17:44:08 +00001189static void schedule_reject(struct gsm_lchan *lchan)
1190{
Holger Freyther73487a22008-12-31 18:53:57 +00001191 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
1192 lchan->loc_operation->updating_timer.data = lchan;
Harald Welteff117a82009-05-23 05:22:08 +00001193 bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +00001194}
1195
Harald Welte2a139372009-02-22 21:14:55 +00001196static const char *lupd_name(u_int8_t type)
1197{
1198 switch (type) {
1199 case GSM48_LUPD_NORMAL:
1200 return "NORMAL";
1201 case GSM48_LUPD_PERIODIC:
1202 return "PEROIDOC";
1203 case GSM48_LUPD_IMSI_ATT:
1204 return "IMSI ATTACH";
1205 default:
1206 return "UNKNOWN";
1207 }
1208}
1209
Harald Welte231ad4f2008-12-27 11:15:38 +00001210#define MI_SIZE 32
Harald Weltebf5e8df2009-02-03 12:59:45 +00001211/* Chapter 9.2.15: Receive Location Updating Request */
Harald Welte231ad4f2008-12-27 11:15:38 +00001212static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001213{
Harald Welte8470bf22008-12-25 23:28:35 +00001214 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001215 struct gsm48_loc_upd_req *lu;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001216 struct gsm_subscriber *subscr = NULL;
Harald Welte255539c2008-12-28 02:26:27 +00001217 struct gsm_lchan *lchan = msg->lchan;
Harald Welte9176bd42009-07-23 18:46:00 +02001218 struct gsm_bts *bts = lchan->ts->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001219 u_int8_t mi_type;
Harald Welte231ad4f2008-12-27 11:15:38 +00001220 char mi_string[MI_SIZE];
1221 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001222
Harald Welte8470bf22008-12-25 23:28:35 +00001223 lu = (struct gsm48_loc_upd_req *) gh->data;
1224
1225 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +00001226
Harald Weltefc977a82008-12-27 10:19:37 +00001227 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
1228
Harald Weltea0368542009-06-27 02:58:43 +02001229 DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
Harald Welte2a139372009-02-22 21:14:55 +00001230 lupd_name(lu->type));
Holger Freyther73487a22008-12-31 18:53:57 +00001231
Holger Freythereaf04692009-06-06 13:54:44 +00001232 /*
1233 * Pseudo Spoof detection: Just drop a second/concurrent
1234 * location updating request.
1235 */
1236 if (lchan->loc_operation) {
Harald Weltea0368542009-06-27 02:58:43 +02001237 DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
Holger Freythereaf04692009-06-06 13:54:44 +00001238 lchan->loc_operation);
1239 gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
1240 return 0;
1241 }
1242
Holger Freyther73487a22008-12-31 18:53:57 +00001243 allocate_loc_updating_req(lchan);
1244
Harald Welte52b1f982008-12-23 20:25:15 +00001245 switch (mi_type) {
1246 case GSM_MI_TYPE_IMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001247 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001248 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001249 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001250 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001251
Jan Luebbe370b41d2009-08-12 10:19:34 +02001252 /* look up subscriber based on IMSI, create if not found */
1253 subscr = subscr_get_by_imsi(bts->network, mi_string);
1254 if (!subscr) {
1255 subscr = db_create_subscriber(bts->network, mi_string);
1256 }
Harald Welte4b634542008-12-27 01:55:51 +00001257 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001258 case GSM_MI_TYPE_TMSI:
Harald Weltea0368542009-06-27 02:58:43 +02001259 DEBUGPC(DMM, "\n");
Harald Welte231ad4f2008-12-27 11:15:38 +00001260 /* we always want the IMEI, too */
Harald Welte015b9ad2009-02-28 18:22:03 +00001261 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
Holger Freyther73487a22008-12-31 18:53:57 +00001262 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +00001263
Harald Welte52b1f982008-12-23 20:25:15 +00001264 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Welte9176bd42009-07-23 18:46:00 +02001265 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte52b1f982008-12-23 20:25:15 +00001266 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +00001267 /* send IDENTITY REQUEST message to get IMSI */
Harald Welte255539c2008-12-28 02:26:27 +00001268 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +00001269 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +00001270 }
1271 break;
1272 case GSM_MI_TYPE_IMEI:
1273 case GSM_MI_TYPE_IMEISV:
1274 /* no sim card... FIXME: what to do ? */
Harald Weltea0368542009-06-27 02:58:43 +02001275 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001276 break;
1277 default:
Harald Weltea0368542009-06-27 02:58:43 +02001278 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001279 break;
1280 }
1281
Harald Welte24516ea2009-07-04 10:18:00 +02001282 /* schedule the reject timer */
1283 schedule_reject(lchan);
1284
Harald Welte4bfdfe72009-06-10 23:11:52 +08001285 if (!subscr) {
Harald Weltea0368542009-06-27 02:58:43 +02001286 DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte4bfdfe72009-06-10 23:11:52 +08001287 /* FIXME: request id? close channel? */
1288 return -EINVAL;
1289 }
1290
Harald Welte255539c2008-12-28 02:26:27 +00001291 lchan->subscr = subscr;
1292
Harald Welte24516ea2009-07-04 10:18:00 +02001293 /* check if we can let the subscriber into our network immediately
1294 * or if we need to wait for identity responses. */
Holger Freytherd51524f2009-06-09 08:27:07 +00001295 return gsm0408_authorize(lchan, msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001296}
1297
Harald Welte13cac662009-07-29 12:10:35 +02001298/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
Harald Welte7584aea2009-02-11 11:44:12 +00001299int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
1300{
1301 struct msgb *msg = gsm48_msgb_alloc();
1302 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1303 struct gsm48_chan_mode_modify *cmm =
1304 (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
Harald Welte4a543e82009-02-28 13:17:55 +00001305 u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
Harald Welte7584aea2009-02-11 11:44:12 +00001306
Harald Welte4a543e82009-02-28 13:17:55 +00001307 DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
Harald Welte7ccf7782009-02-17 01:43:01 +00001308
Harald Welte45b407a2009-05-23 15:51:12 +00001309 lchan->tch_mode = mode;
Harald Welte7584aea2009-02-11 11:44:12 +00001310 msg->lchan = lchan;
1311 gh->proto_discr = GSM48_PDISC_RR;
1312 gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
1313
1314 /* fill the channel information element, this code
1315 * should probably be shared with rsl_rx_chan_rqd() */
1316 cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte02b0e092009-02-28 13:11:07 +00001317 cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
Harald Welte7584aea2009-02-11 11:44:12 +00001318 cmm->chan_desc.h0.h = 0;
1319 cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
1320 cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
1321 cmm->mode = mode;
1322
Harald Welte39e2ead2009-07-23 21:13:03 +02001323 return gsm48_sendmsg(msg, NULL);
Harald Welte7584aea2009-02-11 11:44:12 +00001324}
1325
Harald Welte4bfdfe72009-06-10 23:11:52 +08001326#if 0
1327static u_int8_t to_bcd8(u_int8_t val)
1328{
1329 return ((val / 10) << 4) | (val % 10);
1330}
1331#endif
1332
Harald Weltedb253af2008-12-30 17:56:55 +00001333/* Section 9.2.15a */
1334int gsm48_tx_mm_info(struct gsm_lchan *lchan)
1335{
1336 struct msgb *msg = gsm48_msgb_alloc();
1337 struct gsm48_hdr *gh;
1338 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Weltedb253af2008-12-30 17:56:55 +00001339 u_int8_t *ptr8;
1340 u_int16_t *ptr16;
Daniel Willmanneea93372009-08-13 03:42:07 +02001341 int name_len, name_pad;
Harald Weltedb253af2008-12-30 17:56:55 +00001342 int i;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001343#if 0
1344 time_t cur_t;
1345 struct tm* cur_time;
1346 int tz15min;
1347#endif
Harald Weltedb253af2008-12-30 17:56:55 +00001348
1349 msg->lchan = lchan;
1350
1351 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1352 gh->proto_discr = GSM48_PDISC_MM;
1353 gh->msg_type = GSM48_MT_MM_INFO;
1354
1355 if (net->name_long) {
Daniel Willmanneea93372009-08-13 03:42:07 +02001356#if 0
Harald Weltedb253af2008-12-30 17:56:55 +00001357 name_len = strlen(net->name_long);
1358 /* 10.5.3.5a */
1359 ptr8 = msgb_put(msg, 3);
1360 ptr8[0] = GSM48_IE_NAME_LONG;
1361 ptr8[1] = name_len*2 +1;
1362 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1363
1364 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
1365 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001366 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +00001367
1368 /* FIXME: Use Cell Broadcast, not UCS-2, since
1369 * UCS-2 is only supported by later revisions of the spec */
Daniel Willmanneea93372009-08-13 03:42:07 +02001370#endif
1371 name_len = (strlen(net->name_long)*7)/8;
1372 name_pad = (8 - strlen(net->name_long)*7)%8;
1373 if (name_pad > 0)
1374 name_len++;
1375 /* 10.5.3.5a */
1376 ptr8 = msgb_put(msg, 3);
1377 ptr8[0] = GSM48_IE_NAME_LONG;
1378 ptr8[1] = name_len +1;
1379 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1380
1381 ptr8 = msgb_put(msg, name_len);
1382 gsm_7bit_encode(ptr8, net->name_long);
1383
Harald Weltedb253af2008-12-30 17:56:55 +00001384 }
1385
1386 if (net->name_short) {
Daniel Willmanneea93372009-08-13 03:42:07 +02001387#if 0
Harald Weltedb253af2008-12-30 17:56:55 +00001388 name_len = strlen(net->name_short);
1389 /* 10.5.3.5a */
1390 ptr8 = (u_int8_t *) msgb_put(msg, 3);
Harald Welte7543eb72009-07-19 17:51:36 +02001391 ptr8[0] = GSM48_IE_NAME_SHORT;
Harald Weltedb253af2008-12-30 17:56:55 +00001392 ptr8[1] = name_len*2 + 1;
1393 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
1394
Harald Weltee872cb12009-01-01 00:33:37 +00001395 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +00001396 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +00001397 ptr16[i] = htons(net->name_short[i]);
Daniel Willmanneea93372009-08-13 03:42:07 +02001398#endif
1399 name_len = (strlen(net->name_short)*7)/8;
1400 name_pad = (8 - strlen(net->name_short)*7)%8;
1401 if (name_pad > 0)
1402 name_len++;
1403 /* 10.5.3.5a */
1404 ptr8 = (u_int8_t *) msgb_put(msg, 3);
1405 ptr8[0] = GSM48_IE_NAME_SHORT;
1406 ptr8[1] = name_len +1;
1407 ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
1408
1409 ptr8 = msgb_put(msg, name_len);
1410 gsm_7bit_encode(ptr8, net->name_short);
1411
Harald Weltedb253af2008-12-30 17:56:55 +00001412 }
1413
1414#if 0
1415 /* Section 10.5.3.9 */
1416 cur_t = time(NULL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001417 cur_time = gmtime(&cur_t);
Harald Weltedb253af2008-12-30 17:56:55 +00001418 ptr8 = msgb_put(msg, 8);
1419 ptr8[0] = GSM48_IE_NET_TIME_TZ;
1420 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
1421 ptr8[2] = to_bcd8(cur_time->tm_mon);
1422 ptr8[3] = to_bcd8(cur_time->tm_mday);
1423 ptr8[4] = to_bcd8(cur_time->tm_hour);
1424 ptr8[5] = to_bcd8(cur_time->tm_min);
1425 ptr8[6] = to_bcd8(cur_time->tm_sec);
1426 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
1427 tz15min = (cur_time->tm_gmtoff)/(60*15);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001428 ptr8[7] = to_bcd8(tz15min);
Harald Weltedb253af2008-12-30 17:56:55 +00001429 if (tz15min < 0)
Harald Welte4bfdfe72009-06-10 23:11:52 +08001430 ptr8[7] |= 0x80;
Harald Weltedb253af2008-12-30 17:56:55 +00001431#endif
1432
Daniel Willmanneea93372009-08-13 03:42:07 +02001433 DEBUGP(DMM, "-> MM INFO\n");
1434
Harald Welte39e2ead2009-07-23 21:13:03 +02001435 return gsm48_sendmsg(msg, NULL);
Harald Weltedb253af2008-12-30 17:56:55 +00001436}
1437
Harald Welte7984d5c2009-08-12 22:56:50 +02001438/* Section 9.2.2 */
1439int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand)
1440{
1441 struct msgb *msg = gsm48_msgb_alloc();
1442 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1443 u_int8_t *r;
1444
1445 DEBUGP(DMM, "-> AUTH REQ\n");
1446
1447 msg->lchan = lchan;
1448 gh->proto_discr = GSM48_PDISC_MM;
1449 gh->msg_type = GSM48_MT_MM_AUTH_REQ;
1450
1451 /* 16 bytes RAND parameters */
1452 r = msgb_put(msg, 16);
1453 if (rand)
1454 memcpy(r, rand, 16);
1455
1456 return gsm48_sendmsg(msg, NULL);
1457}
1458
1459/* Section 9.2.1 */
1460int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan)
1461{
1462 DEBUGP(DMM, "-> AUTH REJECT\n");
1463 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
1464}
1465
Harald Welte4b634542008-12-27 01:55:51 +00001466static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
1467{
Harald Welte4b634542008-12-27 01:55:51 +00001468 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +00001469 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +00001470}
Harald Welteba4cf162009-01-10 01:49:35 +00001471
1472/* 9.2.6 CM service reject */
1473static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
1474 enum gsm48_reject_value value)
1475{
1476 struct msgb *msg = gsm48_msgb_alloc();
1477 struct gsm48_hdr *gh;
1478
1479 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
1480
1481 msg->lchan = lchan;
1482 use_lchan(lchan);
1483
1484 gh->proto_discr = GSM48_PDISC_MM;
1485 gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
1486 gh->data[0] = value;
1487 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
1488
Harald Welte39e2ead2009-07-23 21:13:03 +02001489 return gsm48_sendmsg(msg, NULL);
Harald Welteba4cf162009-01-10 01:49:35 +00001490}
1491
Harald Welte3ac7f102009-08-10 10:12:45 +02001492static int send_siemens_mrpci(struct gsm_lchan *lchan,
1493 u_int8_t *classmark2_lv)
1494{
1495 struct rsl_mrpci mrpci;
1496
1497 if (classmark2_lv[0] < 2)
1498 return -EINVAL;
1499
1500 mrpci.power_class = classmark2_lv[1] & 0x7;
1501 mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
1502 mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
1503 mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
1504
1505 return rsl_siemens_mrpci(lchan, &mrpci);
1506}
Harald Welte4ed0e922009-01-10 03:17:30 +00001507
1508/*
1509 * Handle CM Service Requests
1510 * a) Verify that the packet is long enough to contain the information
1511 * we require otherwsie reject with INCORRECT_MESSAGE
1512 * b) Try to parse the TMSI. If we do not have one reject
1513 * c) Check that we know the subscriber with the TMSI otherwise reject
1514 * with a HLR cause
1515 * d) Set the subscriber on the gsm_lchan and accept
1516 */
Harald Welte4b634542008-12-27 01:55:51 +00001517static int gsm48_rx_mm_serv_req(struct msgb *msg)
1518{
Harald Welteba4cf162009-01-10 01:49:35 +00001519 u_int8_t mi_type;
Harald Welte4ed0e922009-01-10 03:17:30 +00001520 char mi_string[MI_SIZE];
Harald Welte4b634542008-12-27 01:55:51 +00001521
Harald Welte9176bd42009-07-23 18:46:00 +02001522 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welteba4cf162009-01-10 01:49:35 +00001523 struct gsm_subscriber *subscr;
1524 struct gsm48_hdr *gh = msgb_l3(msg);
1525 struct gsm48_service_request *req =
1526 (struct gsm48_service_request *)gh->data;
Harald Weltec9e02182009-05-01 19:07:53 +00001527 /* unfortunately in Phase1 the classmar2 length is variable */
1528 u_int8_t classmark2_len = gh->data[1];
1529 u_int8_t *classmark2 = gh->data+2;
1530 u_int8_t mi_len = *(classmark2 + classmark2_len);
1531 u_int8_t *mi = (classmark2 + classmark2_len + 1);
Harald Welteba4cf162009-01-10 01:49:35 +00001532
Harald Weltec9e02182009-05-01 19:07:53 +00001533 DEBUGP(DMM, "<- CM SERVICE REQUEST ");
Harald Welteba4cf162009-01-10 01:49:35 +00001534 if (msg->data_len < sizeof(struct gsm48_service_request*)) {
Harald Weltec9e02182009-05-01 19:07:53 +00001535 DEBUGPC(DMM, "wrong sized message\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001536 return gsm48_tx_mm_serv_rej(msg->lchan,
1537 GSM48_REJECT_INCORRECT_MESSAGE);
1538 }
1539
1540 if (msg->data_len < req->mi_len + 6) {
Harald Weltec9e02182009-05-01 19:07:53 +00001541 DEBUGPC(DMM, "does not fit in packet\n");
Harald Welteba4cf162009-01-10 01:49:35 +00001542 return gsm48_tx_mm_serv_rej(msg->lchan,
1543 GSM48_REJECT_INCORRECT_MESSAGE);
1544 }
1545
Harald Weltec9e02182009-05-01 19:07:53 +00001546 mi_type = mi[0] & GSM_MI_TYPE_MASK;
Harald Welteba4cf162009-01-10 01:49:35 +00001547 if (mi_type != GSM_MI_TYPE_TMSI) {
Harald Weltec9e02182009-05-01 19:07:53 +00001548 DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
Harald Welteba4cf162009-01-10 01:49:35 +00001549 return gsm48_tx_mm_serv_rej(msg->lchan,
1550 GSM48_REJECT_INCORRECT_MESSAGE);
1551 }
1552
Harald Weltec9e02182009-05-01 19:07:53 +00001553 mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
Harald Weltec9e02182009-05-01 19:07:53 +00001554 DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
Harald Welte4ed0e922009-01-10 03:17:30 +00001555 req->cm_service_type, mi_type, mi_string);
Harald Weltebcae43f2008-12-27 21:45:37 +00001556
Harald Welte3ac7f102009-08-10 10:12:45 +02001557 if (is_siemens_bts(bts))
1558 send_siemens_mrpci(msg->lchan, classmark2-1);
1559
Harald Welte9176bd42009-07-23 18:46:00 +02001560 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Holger Freythereb443982009-06-04 13:58:42 +00001561
Harald Welte2a139372009-02-22 21:14:55 +00001562 /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
Harald Welte4ed0e922009-01-10 03:17:30 +00001563 if (!subscr)
1564 return gsm48_tx_mm_serv_rej(msg->lchan,
1565 GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
1566
1567 if (!msg->lchan->subscr)
1568 msg->lchan->subscr = subscr;
Harald Welte9bb7c702009-01-10 03:21:41 +00001569 else if (msg->lchan->subscr != subscr) {
1570 DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
1571 subscr_put(subscr);
1572 }
1573
Harald Weltec2e302d2009-07-05 14:08:13 +02001574 subscr->equipment.classmark2_len = classmark2_len;
1575 memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
1576 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001577
Harald Welte4b634542008-12-27 01:55:51 +00001578 return gsm48_tx_mm_serv_ack(msg->lchan);
1579}
1580
Harald Welte2a139372009-02-22 21:14:55 +00001581static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
1582{
Harald Welte9176bd42009-07-23 18:46:00 +02001583 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2a139372009-02-22 21:14:55 +00001584 struct gsm48_hdr *gh = msgb_l3(msg);
1585 struct gsm48_imsi_detach_ind *idi =
1586 (struct gsm48_imsi_detach_ind *) gh->data;
1587 u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
1588 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001589 struct gsm_subscriber *subscr = NULL;
Harald Welte2a139372009-02-22 21:14:55 +00001590
1591 mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
1592 DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
1593 mi_type, mi_string);
1594
1595 switch (mi_type) {
1596 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001597 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001598 break;
1599 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001600 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Welte2a139372009-02-22 21:14:55 +00001601 break;
1602 case GSM_MI_TYPE_IMEI:
1603 case GSM_MI_TYPE_IMEISV:
1604 /* no sim card... FIXME: what to do ? */
Holger Freyther79f4ae62009-06-02 03:25:04 +00001605 DEBUGPC(DMM, "unimplemented mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001606 break;
1607 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001608 DEBUGPC(DMM, "unknown mobile identity type\n");
Harald Welte2a139372009-02-22 21:14:55 +00001609 break;
1610 }
1611
Holger Freyther4a49e772009-04-12 05:37:29 +00001612 if (subscr) {
1613 subscr_update(subscr, msg->trx->bts,
1614 GSM_SUBSCRIBER_UPDATE_DETACHED);
Harald Welte2a139372009-02-22 21:14:55 +00001615 DEBUGP(DMM, "Subscriber: %s\n",
1616 subscr->name ? subscr->name : subscr->imsi);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001617 subscr_put(subscr);
Holger Freyther4a49e772009-04-12 05:37:29 +00001618 } else
Harald Welte2a139372009-02-22 21:14:55 +00001619 DEBUGP(DMM, "Unknown Subscriber ?!?\n");
1620
Harald Welte2a139372009-02-22 21:14:55 +00001621 return 0;
1622}
1623
Harald Welted2a7f5a2009-06-05 20:08:20 +00001624static int gsm48_rx_mm_status(struct msgb *msg)
1625{
1626 struct gsm48_hdr *gh = msgb_l3(msg);
1627
1628 DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
1629
1630 return 0;
1631}
1632
Harald Weltebf5e8df2009-02-03 12:59:45 +00001633/* Receive a GSM 04.08 Mobility Management (MM) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001634static int gsm0408_rcv_mm(struct msgb *msg)
1635{
1636 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001637 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001638
1639 switch (gh->msg_type & 0xbf) {
1640 case GSM48_MT_MM_LOC_UPD_REQUEST:
Harald Weltea0368542009-06-27 02:58:43 +02001641 DEBUGP(DMM, "LOCATION UPDATING REQUEST: ");
Harald Welte231ad4f2008-12-27 11:15:38 +00001642 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001643 break;
1644 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +00001645 rc = mm_rx_id_resp(msg);
1646 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001647 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +00001648 rc = gsm48_rx_mm_serv_req(msg);
1649 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001650 case GSM48_MT_MM_STATUS:
Harald Welted2a7f5a2009-06-05 20:08:20 +00001651 rc = gsm48_rx_mm_status(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +00001652 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001653 case GSM48_MT_MM_TMSI_REALL_COMPL:
Harald Welte69b2af22009-01-06 19:47:00 +00001654 DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
1655 msg->lchan->subscr ?
1656 msg->lchan->subscr->imsi :
1657 "unknown subscriber");
1658 break;
Harald Welte231ad4f2008-12-27 11:15:38 +00001659 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte2a139372009-02-22 21:14:55 +00001660 rc = gsm48_rx_mm_imsi_detach_ind(msg);
1661 break;
1662 case GSM48_MT_MM_CM_REEST_REQ:
1663 DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
1664 break;
1665 case GSM48_MT_MM_AUTH_RESP:
1666 DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001667 break;
1668 default:
1669 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
1670 gh->msg_type);
1671 break;
1672 }
1673
1674 return rc;
1675}
Harald Weltebf5e8df2009-02-03 12:59:45 +00001676
Harald Welte2d35ae62009-02-06 12:02:13 +00001677/* Receive a PAGING RESPONSE message from the MS */
1678static int gsm48_rr_rx_pag_resp(struct msgb *msg)
1679{
Harald Welte9176bd42009-07-23 18:46:00 +02001680 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte2d35ae62009-02-06 12:02:13 +00001681 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte61548982009-02-22 21:26:29 +00001682 u_int8_t *classmark2_lv = gh->data + 1;
1683 u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
1684 u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
Harald Welte2d35ae62009-02-06 12:02:13 +00001685 char mi_string[MI_SIZE];
Harald Welte4bfdfe72009-06-10 23:11:52 +08001686 struct gsm_subscriber *subscr = NULL;
Harald Welte595ad7b2009-02-16 22:05:44 +00001687 struct paging_signal_data sig_data;
Harald Welte2d35ae62009-02-06 12:02:13 +00001688 int rc = 0;
1689
Harald Welte61548982009-02-22 21:26:29 +00001690 mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv);
Harald Welte2d35ae62009-02-06 12:02:13 +00001691 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
1692 mi_type, mi_string);
Harald Welte3ac7f102009-08-10 10:12:45 +02001693
1694 if (is_siemens_bts(bts))
1695 send_siemens_mrpci(msg->lchan, classmark2_lv);
1696
Harald Weltefe18d8f2009-02-22 21:14:24 +00001697 switch (mi_type) {
1698 case GSM_MI_TYPE_TMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001699 subscr = subscr_get_by_tmsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001700 break;
1701 case GSM_MI_TYPE_IMSI:
Harald Welte9176bd42009-07-23 18:46:00 +02001702 subscr = subscr_get_by_imsi(bts->network, mi_string);
Harald Weltefe18d8f2009-02-22 21:14:24 +00001703 break;
1704 }
Harald Welte2d35ae62009-02-06 12:02:13 +00001705
1706 if (!subscr) {
1707 DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
Harald Welte09e38af2009-02-16 22:52:23 +00001708 /* FIXME: request id? close channel? */
Harald Welte2d35ae62009-02-06 12:02:13 +00001709 return -EINVAL;
1710 }
1711 DEBUGP(DRR, "<- Channel was requested by %s\n",
Harald Welte76042182009-08-08 16:03:15 +02001712 subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi);
Holger Freyther053e09d2009-02-14 22:51:06 +00001713
Harald Weltec2e302d2009-07-05 14:08:13 +02001714 subscr->equipment.classmark2_len = *classmark2_lv;
1715 memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
1716 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001717
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001718 if (!msg->lchan->subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001719 msg->lchan->subscr = subscr;
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001720 } else if (msg->lchan->subscr != subscr) {
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001721 DEBUGP(DRR, "<- Channel already owned by someone else?\n");
1722 subscr_put(subscr);
Holger Freytherc21cfbc2009-06-02 02:54:57 +00001723 return -EINVAL;
1724 } else {
1725 DEBUGP(DRR, "<- Channel already owned by us\n");
1726 subscr_put(subscr);
1727 subscr = msg->lchan->subscr;
Holger Freyther2fa4cb52009-02-14 23:53:15 +00001728 }
1729
Harald Welte595ad7b2009-02-16 22:05:44 +00001730 sig_data.subscr = subscr;
1731 sig_data.bts = msg->lchan->ts->trx->bts;
1732 sig_data.lchan = msg->lchan;
1733
1734 dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
Harald Weltebe143102009-06-10 11:21:55 +08001735
1736 /* Stop paging on the bts we received the paging response */
Harald Welte7ccf7782009-02-17 01:43:01 +00001737 paging_request_stop(msg->trx->bts, subscr, msg->lchan);
Harald Welte2d35ae62009-02-06 12:02:13 +00001738
Harald Welte7584aea2009-02-11 11:44:12 +00001739 /* FIXME: somehow signal the completion of the PAGING to
1740 * the entity that requested the paging */
1741
Harald Welte2d35ae62009-02-06 12:02:13 +00001742 return rc;
1743}
1744
Harald Weltef7c43522009-06-09 20:24:21 +00001745static int gsm48_rx_rr_classmark(struct msgb *msg)
1746{
1747 struct gsm48_hdr *gh = msgb_l3(msg);
1748 struct gsm_subscriber *subscr = msg->lchan->subscr;
1749 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1750 u_int8_t cm2_len, cm3_len = 0;
1751 u_int8_t *cm2, *cm3 = NULL;
1752
1753 DEBUGP(DRR, "CLASSMARK CHANGE ");
1754
1755 /* classmark 2 */
1756 cm2_len = gh->data[0];
1757 cm2 = &gh->data[1];
1758 DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
1759
1760 if (payload_len > cm2_len + 1) {
1761 /* we must have a classmark3 */
1762 if (gh->data[cm2_len+1] != 0x20) {
1763 DEBUGPC(DRR, "ERR CM3 TAG\n");
1764 return -EINVAL;
1765 }
1766 if (cm2_len > 3) {
1767 DEBUGPC(DRR, "CM2 too long!\n");
1768 return -EINVAL;
1769 }
1770
1771 cm3_len = gh->data[cm2_len+2];
1772 cm3 = &gh->data[cm2_len+3];
1773 if (cm3_len > 14) {
1774 DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
1775 return -EINVAL;
1776 }
1777 DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
1778 }
1779 if (subscr) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001780 subscr->equipment.classmark2_len = cm2_len;
1781 memcpy(subscr->equipment.classmark2, cm2, cm2_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001782 if (cm3) {
Harald Weltec2e302d2009-07-05 14:08:13 +02001783 subscr->equipment.classmark3_len = cm3_len;
1784 memcpy(subscr->equipment.classmark3, cm3, cm3_len);
Harald Weltef7c43522009-06-09 20:24:21 +00001785 }
Harald Weltec2e302d2009-07-05 14:08:13 +02001786 db_sync_equipment(&subscr->equipment);
Harald Weltef7c43522009-06-09 20:24:21 +00001787 }
1788
Harald Weltef7c43522009-06-09 20:24:21 +00001789 return 0;
1790}
1791
Harald Weltecf5b3592009-05-01 18:28:42 +00001792static int gsm48_rx_rr_status(struct msgb *msg)
1793{
1794 struct gsm48_hdr *gh = msgb_l3(msg);
1795
1796 DEBUGP(DRR, "STATUS rr_cause = %s\n",
1797 rr_cause_name(gh->data[0]));
1798
1799 return 0;
1800}
1801
Harald Weltef7c43522009-06-09 20:24:21 +00001802static int gsm48_rx_rr_meas_rep(struct msgb *msg)
1803{
1804 struct gsm48_hdr *gh = msgb_l3(msg);
1805 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1806 static struct gsm_meas_rep meas_rep;
1807
Harald Welte10d0e672009-06-27 02:53:10 +02001808 DEBUGP(DMEAS, "MEASUREMENT REPORT ");
Harald Weltef7c43522009-06-09 20:24:21 +00001809 parse_meas_rep(&meas_rep, gh->data, payload_len);
1810 if (meas_rep.flags & MEAS_REP_F_DTX)
Harald Welte10d0e672009-06-27 02:53:10 +02001811 DEBUGPC(DMEAS, "DTX ");
Harald Weltef7c43522009-06-09 20:24:21 +00001812 if (meas_rep.flags & MEAS_REP_F_BA1)
Harald Welte10d0e672009-06-27 02:53:10 +02001813 DEBUGPC(DMEAS, "BA1 ");
Harald Weltef7c43522009-06-09 20:24:21 +00001814 if (!(meas_rep.flags & MEAS_REP_F_VALID))
Harald Welte10d0e672009-06-27 02:53:10 +02001815 DEBUGPC(DMEAS, "NOT VALID ");
Harald Weltef7c43522009-06-09 20:24:21 +00001816 else
Harald Welte10d0e672009-06-27 02:53:10 +02001817 DEBUGPC(DMEAS, "FULL(lev=%u, qual=%u) SUB(lev=%u, qual=%u) ",
Harald Weltef7c43522009-06-09 20:24:21 +00001818 meas_rep.rxlev_full, meas_rep.rxqual_full, meas_rep.rxlev_sub,
1819 meas_rep.rxqual_sub);
1820
Harald Welte10d0e672009-06-27 02:53:10 +02001821 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", meas_rep.num_cell);
Harald Weltef7c43522009-06-09 20:24:21 +00001822
1823 /* FIXME: put the results somwhere */
1824
1825 return 0;
1826}
1827
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001828static int gsm48_rx_rr_app_info(struct msgb *msg)
1829{
1830 struct gsm48_hdr *gh = msgb_l3(msg);
1831 u_int8_t apdu_id_flags;
1832 u_int8_t apdu_len;
1833 u_int8_t *apdu_data;
1834
1835 apdu_id_flags = gh->data[0];
1836 apdu_len = gh->data[1];
1837 apdu_data = gh->data+2;
1838
1839 DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
1840 apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len));
1841
1842 return 0;
1843}
1844
1845
Harald Weltebf5e8df2009-02-03 12:59:45 +00001846/* Receive a GSM 04.08 Radio Resource (RR) message */
Harald Welte52b1f982008-12-23 20:25:15 +00001847static int gsm0408_rcv_rr(struct msgb *msg)
1848{
1849 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte2d35ae62009-02-06 12:02:13 +00001850 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001851
1852 switch (gh->msg_type) {
1853 case GSM48_MT_RR_CLSM_CHG:
Harald Weltef7c43522009-06-09 20:24:21 +00001854 rc = gsm48_rx_rr_classmark(msg);
Harald Welte52b1f982008-12-23 20:25:15 +00001855 break;
Harald Weltefc977a82008-12-27 10:19:37 +00001856 case GSM48_MT_RR_GPRS_SUSP_REQ:
1857 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
1858 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001859 case GSM48_MT_RR_PAG_RESP:
Harald Welte2d35ae62009-02-06 12:02:13 +00001860 rc = gsm48_rr_rx_pag_resp(msg);
1861 break;
Harald Welte7ccf7782009-02-17 01:43:01 +00001862 case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
1863 DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
Harald Welte13cac662009-07-29 12:10:35 +02001864 /* We've successfully modified the MS side of the channel,
1865 * now go on to modify the BTS side of the channel */
Harald Welte9943c5b2009-07-29 15:41:29 +02001866 msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
Harald Welte2c38aa82009-02-18 03:44:24 +00001867 rc = rsl_chan_mode_modify_req(msg->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00001868 break;
Harald Weltecf5b3592009-05-01 18:28:42 +00001869 case GSM48_MT_RR_STATUS:
1870 rc = gsm48_rx_rr_status(msg);
1871 break;
Harald Weltef7c43522009-06-09 20:24:21 +00001872 case GSM48_MT_RR_MEAS_REP:
1873 rc = gsm48_rx_rr_meas_rep(msg);
1874 break;
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001875 case GSM48_MT_RR_APP_INFO:
1876 rc = gsm48_rx_rr_app_info(msg);
1877 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001878 default:
Harald Welte2d35ae62009-02-06 12:02:13 +00001879 fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001880 gh->msg_type);
1881 break;
1882 }
1883
Harald Welte2d35ae62009-02-06 12:02:13 +00001884 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001885}
1886
Harald Welte115d1032009-08-10 11:43:22 +02001887/* 7.1.7 and 9.1.7: RR CHANnel RELease */
Holger Freythere64a7a32009-02-06 21:55:37 +00001888int gsm48_send_rr_release(struct gsm_lchan *lchan)
1889{
1890 struct msgb *msg = gsm48_msgb_alloc();
1891 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1892 u_int8_t *cause;
1893
1894 msg->lchan = lchan;
1895 gh->proto_discr = GSM48_PDISC_RR;
1896 gh->msg_type = GSM48_MT_RR_CHAN_REL;
1897
1898 cause = msgb_put(msg, 1);
1899 cause[0] = GSM48_RR_CAUSE_NORMAL;
1900
1901 DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
1902 lchan->nr, lchan->type);
1903
Harald Welteae0f2362009-07-19 18:36:49 +02001904 /* Send actual release request to MS */
Harald Welte39e2ead2009-07-23 21:13:03 +02001905 gsm48_sendmsg(msg, NULL);
Harald Welte76042182009-08-08 16:03:15 +02001906 /* FIXME: Start Timer T3109 */
Harald Welteae0f2362009-07-19 18:36:49 +02001907
1908 /* Deactivate the SACCH on the BTS side */
1909 return rsl_deact_sacch(lchan);
Holger Freythere64a7a32009-02-06 21:55:37 +00001910}
1911
Harald Welte (local)6eef5642009-08-15 23:32:44 +02001912int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
1913 u_int8_t apdu_len, u_int8_t *apdu)
1914{
1915 struct msgb *msg = gsm48_msgb_alloc();
1916 struct gsm48_hdr *gh;
1917
1918 msg->lchan = lchan;
1919
1920 DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
1921 apdu_id, apdu_len);
1922
1923 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2 + apdu_len);
1924 gh->proto_discr = GSM48_PDISC_RR;
1925 gh->msg_type = GSM48_MT_RR_APP_INFO;
1926 gh->data[0] = apdu_id;
1927 gh->data[1] = apdu_len;
1928 memcpy(gh->data+2, apdu, apdu_len);
1929
1930 return gsm48_sendmsg(msg, NULL);
1931}
1932
Harald Welte4bc90a12008-12-27 16:32:52 +00001933/* Call Control */
1934
Harald Welte7584aea2009-02-11 11:44:12 +00001935/* The entire call control code is written in accordance with Figure 7.10c
1936 * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
1937 * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
1938 * it for voice */
1939
Harald Welte4bfdfe72009-06-10 23:11:52 +08001940static void new_cc_state(struct gsm_trans *trans, int state)
1941{
1942 if (state > 31 || state < 0)
1943 return;
1944
1945 DEBUGP(DCC, "new state %s -> %s\n",
Harald Weltedcaf5652009-07-23 18:56:43 +02001946 cc_state_names[trans->cc.state], cc_state_names[state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08001947
Harald Weltedcaf5652009-07-23 18:56:43 +02001948 trans->cc.state = state;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001949}
1950
1951static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
Harald Welte4bc90a12008-12-27 16:32:52 +00001952{
1953 struct msgb *msg = gsm48_msgb_alloc();
1954 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1955 u_int8_t *cause, *call_state;
1956
Harald Welte4bc90a12008-12-27 16:32:52 +00001957 gh->msg_type = GSM48_MT_CC_STATUS;
1958
1959 cause = msgb_put(msg, 3);
1960 cause[0] = 2;
1961 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
1962 cause[2] = 0x80 | 30; /* response to status inquiry */
1963
1964 call_state = msgb_put(msg, 1);
1965 call_state[0] = 0xc0 | 0x00;
1966
Harald Welte39e2ead2009-07-23 21:13:03 +02001967 return gsm48_sendmsg(msg, trans);
Harald Welte4bc90a12008-12-27 16:32:52 +00001968}
1969
Harald Welte6f4b7532008-12-29 00:39:37 +00001970static int gsm48_tx_simple(struct gsm_lchan *lchan,
1971 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +00001972{
1973 struct msgb *msg = gsm48_msgb_alloc();
1974 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1975
1976 msg->lchan = lchan;
1977
Harald Welte6f4b7532008-12-29 00:39:37 +00001978 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +00001979 gh->msg_type = msg_type;
1980
Harald Welte39e2ead2009-07-23 21:13:03 +02001981 return gsm48_sendmsg(msg, NULL);
Harald Welte4bc90a12008-12-27 16:32:52 +00001982}
1983
Harald Welte4bfdfe72009-06-10 23:11:52 +08001984static void gsm48_stop_cc_timer(struct gsm_trans *trans)
1985{
Harald Weltedcaf5652009-07-23 18:56:43 +02001986 if (bsc_timer_pending(&trans->cc.timer)) {
1987 DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
1988 bsc_del_timer(&trans->cc.timer);
1989 trans->cc.Tcurrent = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08001990 }
1991}
1992
1993static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
1994 int msg_type, struct gsm_mncc *mncc)
1995{
1996 struct msgb *msg;
1997
1998 if (trans)
1999 if (trans->lchan)
Harald Welte6f5aee02009-07-23 21:21:14 +02002000 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08002001 "Sending '%s' to MNCC.\n",
2002 trans->lchan->ts->trx->bts->nr,
2003 trans->lchan->ts->trx->nr,
2004 trans->lchan->ts->nr, trans->transaction_id,
2005 (trans->subscr)?(trans->subscr->extension):"-",
2006 get_mncc_name(msg_type));
2007 else
2008 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
2009 "Sending '%s' to MNCC.\n",
2010 (trans->subscr)?(trans->subscr->extension):"-",
2011 get_mncc_name(msg_type));
2012 else
2013 DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
2014 "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
2015
2016 mncc->msg_type = msg_type;
2017
Harald Welte966636f2009-06-26 19:39:35 +02002018 msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
Harald Welte4bfdfe72009-06-10 23:11:52 +08002019 if (!msg)
2020 return -ENOMEM;
2021 memcpy(msg->data, mncc, sizeof(struct gsm_mncc));
2022 msgb_enqueue(&net->upqueue, msg);
2023
2024 return 0;
2025}
2026
2027int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
2028 u_int32_t callref, int location, int value)
2029{
2030 struct gsm_mncc rel;
2031
Harald Welte92f70c52009-06-12 01:54:08 +08002032 memset(&rel, 0, sizeof(rel));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002033 rel.callref = callref;
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002034 mncc_set_cause(&rel, location, value);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002035 return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
2036}
2037
Harald Weltedcaf5652009-07-23 18:56:43 +02002038/* Call Control Specific transaction release.
2039 * gets called by trans_free, DO NOT CALL YOURSELF! */
2040void _gsm48_cc_trans_free(struct gsm_trans *trans)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002041{
Harald Welte4bfdfe72009-06-10 23:11:52 +08002042 gsm48_stop_cc_timer(trans);
2043
2044 /* send release to L4, if callref still exists */
2045 if (trans->callref) {
2046 /* Ressource unavailable */
Harald Welte596fed42009-07-23 19:06:52 +02002047 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002048 GSM48_CAUSE_LOC_PRN_S_LU,
2049 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002050 }
Harald Weltedcaf5652009-07-23 18:56:43 +02002051 if (trans->cc.state != GSM_CSTATE_NULL)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002052 new_cc_state(trans, GSM_CSTATE_NULL);
Harald Weltedcaf5652009-07-23 18:56:43 +02002053 if (trans->lchan)
2054 trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002055}
2056
2057static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
2058
Harald Welte09e38af2009-02-16 22:52:23 +00002059/* call-back from paging the B-end of the connection */
2060static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
Harald Welte7ccf7782009-02-17 01:43:01 +00002061 struct msgb *msg, void *_lchan, void *param)
Harald Welte09e38af2009-02-16 22:52:23 +00002062{
Harald Welte7ccf7782009-02-17 01:43:01 +00002063 struct gsm_lchan *lchan = _lchan;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002064 struct gsm_subscriber *subscr = param;
2065 struct gsm_trans *transt, *tmp;
2066 struct gsm_network *net;
Harald Weltec05677b2009-06-26 20:17:06 +02002067
Harald Welte09e38af2009-02-16 22:52:23 +00002068 if (hooknum != GSM_HOOK_RR_PAGING)
2069 return -EINVAL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002070
2071 if (!subscr)
2072 return -EINVAL;
2073 net = subscr->net;
2074 if (!net) {
2075 DEBUGP(DCC, "Error Network not set!\n");
2076 return -EINVAL;
Harald Welte5a065df2009-02-22 21:13:18 +00002077 }
Harald Welte7584aea2009-02-11 11:44:12 +00002078
Harald Welte4bfdfe72009-06-10 23:11:52 +08002079 /* check all tranactions (without lchan) for subscriber */
2080 llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
2081 if (transt->subscr != subscr || transt->lchan)
2082 continue;
2083 switch (event) {
2084 case GSM_PAGING_SUCCEEDED:
2085 if (!lchan) // paranoid
2086 break;
2087 DEBUGP(DCC, "Paging subscr %s succeeded!\n",
2088 subscr->extension);
2089 /* Assign lchan */
2090 if (!transt->lchan) {
2091 transt->lchan = lchan;
2092 use_lchan(lchan);
2093 }
2094 /* send SETUP request to called party */
Harald Weltedcaf5652009-07-23 18:56:43 +02002095 gsm48_cc_tx_setup(transt, &transt->cc.msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002096 break;
2097 case GSM_PAGING_EXPIRED:
2098 DEBUGP(DCC, "Paging subscr %s expired!\n",
2099 subscr->extension);
2100 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002101 mncc_release_ind(transt->subscr->net, transt,
2102 transt->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002103 GSM48_CAUSE_LOC_PRN_S_LU,
2104 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002105 transt->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002106 trans_free(transt);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002107 break;
2108 }
2109 }
Harald Welte09e38af2009-02-16 22:52:23 +00002110 return 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00002111}
Harald Welte7584aea2009-02-11 11:44:12 +00002112
Harald Welte805f6442009-07-28 18:25:29 +02002113/* some other part of the code sends us a signal */
2114static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
2115 void *handler_data, void *signal_data)
2116{
2117 struct gsm_lchan *lchan = signal_data;
2118 struct gsm_bts_trx_ts *ts;
2119 int rc;
2120
2121 if (subsys != SS_ABISIP)
2122 return 0;
2123
2124 /* in case we use direct BTS-to-BTS RTP */
2125 if (ipacc_rtp_direct)
2126 return 0;
2127
2128 ts = lchan->ts;
2129
2130 switch (signal) {
2131 case S_ABISIP_BIND_ACK:
2132 /* the BTS has successfully bound a TCH to a local ip/port,
2133 * which means we can connect our UDP socket to it */
2134 if (ts->abis_ip.rtp_socket) {
2135 rtp_socket_free(ts->abis_ip.rtp_socket);
2136 ts->abis_ip.rtp_socket = NULL;
2137 }
2138
2139 ts->abis_ip.rtp_socket = rtp_socket_create();
2140 if (!ts->abis_ip.rtp_socket)
2141 goto out_err;
2142
2143 rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
2144 ts->abis_ip.bound_ip,
2145 ts->abis_ip.bound_port);
2146 if (rc < 0)
2147 goto out_err;
2148 break;
2149 case S_ABISIP_DISC_IND:
2150 /* the BTS tells us a RTP stream has been disconnected */
2151 if (ts->abis_ip.rtp_socket) {
2152 rtp_socket_free(ts->abis_ip.rtp_socket);
2153 ts->abis_ip.rtp_socket = NULL;
2154 }
2155 break;
2156 }
2157
2158 return 0;
2159out_err:
2160 /* FIXME: do something */
2161 return 0;
2162}
2163
2164/* bind rtp proxy to local IP/port and tell BTS to connect to it */
2165static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
2166{
2167 struct gsm_bts_trx_ts *ts = lchan->ts;
2168 struct rtp_socket *rs = ts->abis_ip.rtp_socket;
2169 int rc;
2170
2171 rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
2172 ntohs(rs->rtp.sin_local.sin_port),
2173 ts->abis_ip.conn_id,
2174 /* FIXME: use RTP payload of bound socket, not BTS*/
2175 ts->abis_ip.rtp_payload2);
2176
2177 return rc;
2178}
2179
Harald Welte49f48b82009-02-17 15:29:33 +00002180/* map two ipaccess RTP streams onto each other */
Harald Welte11fa29c2009-02-19 17:24:39 +00002181static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
Harald Welte49f48b82009-02-17 15:29:33 +00002182{
Harald Welte11fa29c2009-02-19 17:24:39 +00002183 struct gsm_bts *bts = lchan->ts->trx->bts;
2184 struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
Harald Welte49f48b82009-02-17 15:29:33 +00002185 struct gsm_bts_trx_ts *ts;
Harald Welte805f6442009-07-28 18:25:29 +02002186 int rc;
Harald Welte49f48b82009-02-17 15:29:33 +00002187
Harald Welte11fa29c2009-02-19 17:24:39 +00002188 DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
2189 bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
2190 remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
2191
2192 if (bts->type != remote_bts->type) {
2193 DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
2194 return -EINVAL;
2195 }
Harald Welte49f48b82009-02-17 15:29:33 +00002196
Harald Welte11fa29c2009-02-19 17:24:39 +00002197 switch (bts->type) {
2198 case GSM_BTS_TYPE_NANOBTS_900:
2199 case GSM_BTS_TYPE_NANOBTS_1800:
Harald Welte805f6442009-07-28 18:25:29 +02002200 if (!ipacc_rtp_direct) {
2201 /* connect the TCH's to our RTP proxy */
2202 rc = ipacc_connect_proxy_bind(lchan);
2203 if (rc < 0)
2204 return rc;
2205 rc = ipacc_connect_proxy_bind(remote_lchan);
2206
2207 /* connect them with each other */
2208 rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
2209 remote_lchan->ts->abis_ip.rtp_socket);
2210 } else {
2211 /* directly connect TCH RTP streams to each other */
2212 ts = remote_lchan->ts;
2213 rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
2214 ts->abis_ip.bound_port,
2215 lchan->ts->abis_ip.conn_id,
2216 ts->abis_ip.rtp_payload2);
2217 if (rc < 0)
2218 return rc;
2219 ts = lchan->ts;
2220 rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
2221 ts->abis_ip.bound_port,
2222 remote_lchan->ts->abis_ip.conn_id,
2223 ts->abis_ip.rtp_payload2);
2224 }
Harald Welte11fa29c2009-02-19 17:24:39 +00002225 break;
2226 case GSM_BTS_TYPE_BS11:
2227 trau_mux_map_lchan(lchan, remote_lchan);
2228 break;
2229 default:
2230 DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
Harald Welte805f6442009-07-28 18:25:29 +02002231 rc = -EINVAL;
Harald Welte11fa29c2009-02-19 17:24:39 +00002232 break;
2233 }
Harald Welte49f48b82009-02-17 15:29:33 +00002234
2235 return 0;
2236}
2237
Harald Welte4bfdfe72009-06-10 23:11:52 +08002238/* bridge channels of two transactions */
2239static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
Harald Welte7ccf7782009-02-17 01:43:01 +00002240{
Harald Weltedcaf5652009-07-23 18:56:43 +02002241 struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
2242 struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
Harald Welte7ccf7782009-02-17 01:43:01 +00002243
Harald Welte4bfdfe72009-06-10 23:11:52 +08002244 if (!trans1 || !trans2)
Harald Welte7ccf7782009-02-17 01:43:01 +00002245 return -EIO;
2246
Harald Welte4bfdfe72009-06-10 23:11:52 +08002247 if (!trans1->lchan || !trans2->lchan)
2248 return -EIO;
2249
2250 /* through-connect channel */
2251 return tch_map(trans1->lchan, trans2->lchan);
Harald Welte7ccf7782009-02-17 01:43:01 +00002252}
2253
Harald Welte4bfdfe72009-06-10 23:11:52 +08002254/* enable receive of channels to upqueue */
2255static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
2256{
2257 struct gsm_trans *trans;
Harald Welte7ccf7782009-02-17 01:43:01 +00002258
Harald Welte4bfdfe72009-06-10 23:11:52 +08002259 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002260 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002261 if (!trans)
2262 return -EIO;
2263 if (!trans->lchan)
2264 return 0;
2265
2266 // todo IPACCESS
2267 if (enable)
2268 return trau_recv_lchan(trans->lchan, data->callref);
2269 return trau_mux_unmap(NULL, data->callref);
2270}
2271
2272/* send a frame to channel */
2273static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
2274{
2275 struct gsm_trans *trans;
2276
2277 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02002278 trans = trans_find_by_callref(net, frame->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002279 if (!trans)
2280 return -EIO;
2281 if (!trans->lchan)
2282 return 0;
2283 if (trans->lchan->type != GSM_LCHAN_TCH_F &&
2284 trans->lchan->type != GSM_LCHAN_TCH_H)
2285 return 0;
2286
2287 // todo IPACCESS
2288 return trau_send_lchan(trans->lchan,
2289 (struct decoded_trau_frame *)frame->data);
2290}
2291
2292
2293static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
2294{
2295 DEBUGP(DCC, "-> STATUS ENQ\n");
2296 return gsm48_cc_tx_status(trans, msg);
2297}
2298
2299static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
2300static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
2301
2302static void gsm48_cc_timeout(void *arg)
2303{
2304 struct gsm_trans *trans = arg;
2305 int disconnect = 0, release = 0;
Harald Weltec66b71c2009-06-11 14:23:20 +08002306 int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
2307 int mo_location = GSM48_CAUSE_LOC_USER;
2308 int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
2309 int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002310 struct gsm_mncc mo_rel, l4_rel;
2311
2312 memset(&mo_rel, 0, sizeof(struct gsm_mncc));
2313 mo_rel.callref = trans->callref;
2314 memset(&l4_rel, 0, sizeof(struct gsm_mncc));
2315 l4_rel.callref = trans->callref;
2316
Harald Weltedcaf5652009-07-23 18:56:43 +02002317 switch(trans->cc.Tcurrent) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002318 case 0x303:
2319 release = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002320 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002321 break;
2322 case 0x310:
2323 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002324 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002325 break;
2326 case 0x313:
2327 disconnect = 1;
2328 /* unknown, did not find it in the specs */
2329 break;
2330 case 0x301:
2331 disconnect = 1;
Harald Weltec66b71c2009-06-11 14:23:20 +08002332 l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002333 break;
2334 case 0x308:
Harald Weltedcaf5652009-07-23 18:56:43 +02002335 if (!trans->cc.T308_second) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002336 /* restart T308 a second time */
Harald Weltedcaf5652009-07-23 18:56:43 +02002337 gsm48_cc_tx_release(trans, &trans->cc.msg);
2338 trans->cc.T308_second = 1;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002339 break; /* stay in release state */
2340 }
Harald Weltedcaf5652009-07-23 18:56:43 +02002341 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002342 return;
2343// release = 1;
2344// l4_cause = 14;
2345// break;
2346 case 0x306:
2347 release = 1;
Harald Weltedcaf5652009-07-23 18:56:43 +02002348 mo_cause = trans->cc.msg.cause.value;
2349 mo_location = trans->cc.msg.cause.location;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002350 break;
2351 case 0x323:
2352 disconnect = 1;
2353 break;
2354 default:
2355 release = 1;
2356 }
2357
2358 if (release && trans->callref) {
2359 /* process release towards layer 4 */
Harald Welte596fed42009-07-23 19:06:52 +02002360 mncc_release_ind(trans->subscr->net, trans, trans->callref,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002361 l4_location, l4_cause);
2362 trans->callref = 0;
2363 }
2364
2365 if (disconnect && trans->callref) {
2366 /* process disconnect towards layer 4 */
2367 mncc_set_cause(&l4_rel, l4_location, l4_cause);
Harald Welte596fed42009-07-23 19:06:52 +02002368 mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002369 }
2370
2371 /* process disconnect towards mobile station */
2372 if (disconnect || release) {
2373 mncc_set_cause(&mo_rel, mo_location, mo_cause);
Harald Weltedcaf5652009-07-23 18:56:43 +02002374 mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
2375 mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
2376 mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
Harald Welte4bfdfe72009-06-10 23:11:52 +08002377 mo_rel.cause.diag_len = 3;
2378
2379 if (disconnect)
2380 gsm48_cc_tx_disconnect(trans, &mo_rel);
2381 if (release)
2382 gsm48_cc_tx_release(trans, &mo_rel);
2383 }
2384
2385}
2386
2387static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
2388 int sec, int micro)
2389{
2390 DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
Harald Weltedcaf5652009-07-23 18:56:43 +02002391 trans->cc.timer.cb = gsm48_cc_timeout;
2392 trans->cc.timer.data = trans;
2393 bsc_schedule_timer(&trans->cc.timer, sec, micro);
2394 trans->cc.Tcurrent = current;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002395}
2396
2397static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
2398{
2399 struct gsm48_hdr *gh = msgb_l3(msg);
2400 u_int8_t msg_type = gh->msg_type & 0xbf;
2401 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2402 struct tlv_parsed tp;
2403 struct gsm_mncc setup;
2404
2405 memset(&setup, 0, sizeof(struct gsm_mncc));
2406 setup.callref = trans->callref;
2407 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2408 /* emergency setup is identified by msg_type */
2409 if (msg_type == GSM48_MT_CC_EMERG_SETUP)
2410 setup.emergency = 1;
2411
2412 /* use subscriber as calling party number */
2413 if (trans->subscr) {
2414 setup.fields |= MNCC_F_CALLING;
2415 strncpy(setup.calling.number, trans->subscr->extension,
2416 sizeof(setup.calling.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002417 strncpy(setup.imsi, trans->subscr->imsi,
2418 sizeof(setup.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002419 }
2420 /* bearer capability */
2421 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2422 setup.fields |= MNCC_F_BEARER_CAP;
2423 decode_bearer_cap(&setup.bearer_cap,
2424 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2425 }
2426 /* facility */
2427 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2428 setup.fields |= MNCC_F_FACILITY;
2429 decode_facility(&setup.facility,
2430 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2431 }
2432 /* called party bcd number */
2433 if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
2434 setup.fields |= MNCC_F_CALLED;
2435 decode_called(&setup.called,
2436 TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
2437 }
2438 /* user-user */
2439 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2440 setup.fields |= MNCC_F_USERUSER;
2441 decode_useruser(&setup.useruser,
2442 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2443 }
2444 /* ss-version */
2445 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2446 setup.fields |= MNCC_F_SSVERSION;
2447 decode_ssversion(&setup.ssversion,
2448 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2449 }
2450 /* CLIR suppression */
2451 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
2452 setup.clir.sup = 1;
2453 /* CLIR invocation */
2454 if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
2455 setup.clir.inv = 1;
2456 /* cc cap */
2457 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2458 setup.fields |= MNCC_F_CCCAP;
2459 decode_cccap(&setup.cccap,
2460 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2461 }
2462
Harald Welte4bfdfe72009-06-10 23:11:52 +08002463 new_cc_state(trans, GSM_CSTATE_INITIATED);
2464
2465 /* indicate setup to MNCC */
Harald Welte596fed42009-07-23 19:06:52 +02002466 mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002467
Harald Welte13cac662009-07-29 12:10:35 +02002468 /* MNCC code will modify the channel asynchronously, we should
2469 * ipaccess-bind only after the modification has been made to the
2470 * lchan->tch_mode */
Harald Welte4bfdfe72009-06-10 23:11:52 +08002471 return 0;
2472}
2473
2474static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
Harald Welte65e74cc2008-12-29 01:55:35 +00002475{
2476 struct msgb *msg = gsm48_msgb_alloc();
2477 struct gsm48_hdr *gh;
Harald Welte4bfdfe72009-06-10 23:11:52 +08002478 struct gsm_mncc *setup = arg;
Harald Welte78283ef2009-07-23 21:36:44 +02002479 int rc, trans_id;
Harald Welte65e74cc2008-12-29 01:55:35 +00002480
Harald Welte7ccf7782009-02-17 01:43:01 +00002481 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Harald Welte65e74cc2008-12-29 01:55:35 +00002482
Harald Welte4bfdfe72009-06-10 23:11:52 +08002483 /* transaction id must not be assigned */
2484 if (trans->transaction_id != 0xff) { /* unasssigned */
2485 DEBUGP(DCC, "TX Setup with assigned transaction. "
2486 "This is not allowed!\n");
2487 /* Temporarily out of order */
Harald Welte596fed42009-07-23 19:06:52 +02002488 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002489 GSM48_CAUSE_LOC_PRN_S_LU,
2490 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002491 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002492 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002493 return rc;
2494 }
2495
2496 /* Get free transaction_id */
Harald Welte78283ef2009-07-23 21:36:44 +02002497 trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
2498 if (trans_id < 0) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002499 /* no free transaction ID */
Harald Welte596fed42009-07-23 19:06:52 +02002500 rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
Andreas Eversberg7563ac92009-06-14 22:14:12 +08002501 GSM48_CAUSE_LOC_PRN_S_LU,
2502 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002503 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002504 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002505 return rc;
2506 }
Harald Welte78283ef2009-07-23 21:36:44 +02002507 trans->transaction_id = trans_id;
Harald Welte49f48b82009-02-17 15:29:33 +00002508
Harald Welte65e74cc2008-12-29 01:55:35 +00002509 gh->msg_type = GSM48_MT_CC_SETUP;
Harald Welte09e38af2009-02-16 22:52:23 +00002510
Harald Welte4bfdfe72009-06-10 23:11:52 +08002511 gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
Harald Welte65e74cc2008-12-29 01:55:35 +00002512
Harald Welte4bfdfe72009-06-10 23:11:52 +08002513 /* bearer capability */
2514 if (setup->fields & MNCC_F_BEARER_CAP)
2515 encode_bearer_cap(msg, 0, &setup->bearer_cap);
2516 /* facility */
2517 if (setup->fields & MNCC_F_FACILITY)
2518 encode_facility(msg, 0, &setup->facility);
2519 /* progress */
2520 if (setup->fields & MNCC_F_PROGRESS)
2521 encode_progress(msg, 0, &setup->progress);
2522 /* calling party BCD number */
2523 if (setup->fields & MNCC_F_CALLING)
2524 encode_calling(msg, &setup->calling);
2525 /* called party BCD number */
2526 if (setup->fields & MNCC_F_CALLED)
2527 encode_called(msg, &setup->called);
2528 /* user-user */
2529 if (setup->fields & MNCC_F_USERUSER)
2530 encode_useruser(msg, 0, &setup->useruser);
2531 /* redirecting party BCD number */
2532 if (setup->fields & MNCC_F_REDIRECTING)
2533 encode_redirecting(msg, &setup->redirecting);
2534 /* signal */
2535 if (setup->fields & MNCC_F_SIGNAL)
2536 encode_signal(msg, setup->signal);
2537
2538 new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
Harald Welte65e74cc2008-12-29 01:55:35 +00002539
Harald Welte39e2ead2009-07-23 21:13:03 +02002540 return gsm48_sendmsg(msg, trans);
Harald Welte65e74cc2008-12-29 01:55:35 +00002541}
2542
Harald Welte4bfdfe72009-06-10 23:11:52 +08002543static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
2544{
2545 struct gsm48_hdr *gh = msgb_l3(msg);
2546 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2547 struct tlv_parsed tp;
2548 struct gsm_mncc call_conf;
2549
2550 gsm48_stop_cc_timer(trans);
2551 gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
2552
2553 memset(&call_conf, 0, sizeof(struct gsm_mncc));
2554 call_conf.callref = trans->callref;
2555 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2556#if 0
2557 /* repeat */
2558 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
2559 call_conf.repeat = 1;
2560 if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
2561 call_conf.repeat = 2;
2562#endif
2563 /* bearer capability */
2564 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
2565 call_conf.fields |= MNCC_F_BEARER_CAP;
2566 decode_bearer_cap(&call_conf.bearer_cap,
2567 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
2568 }
2569 /* cause */
2570 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2571 call_conf.fields |= MNCC_F_CAUSE;
2572 decode_cause(&call_conf.cause,
2573 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2574 }
2575 /* cc cap */
2576 if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
2577 call_conf.fields |= MNCC_F_CCCAP;
2578 decode_cccap(&call_conf.cccap,
2579 TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
2580 }
2581
2582 new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
2583
Harald Welte596fed42009-07-23 19:06:52 +02002584 return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
2585 &call_conf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002586}
2587
2588static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
2589{
2590 struct gsm_mncc *proceeding = arg;
2591 struct msgb *msg = gsm48_msgb_alloc();
2592 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2593
Harald Welte4bfdfe72009-06-10 23:11:52 +08002594 gh->msg_type = GSM48_MT_CC_CALL_PROC;
2595
2596 new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
2597
2598 /* bearer capability */
2599 if (proceeding->fields & MNCC_F_BEARER_CAP)
2600 encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
2601 /* facility */
2602 if (proceeding->fields & MNCC_F_FACILITY)
2603 encode_facility(msg, 0, &proceeding->facility);
2604 /* progress */
2605 if (proceeding->fields & MNCC_F_PROGRESS)
2606 encode_progress(msg, 0, &proceeding->progress);
2607
Harald Welte39e2ead2009-07-23 21:13:03 +02002608 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002609}
2610
2611static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
2612{
2613 struct gsm48_hdr *gh = msgb_l3(msg);
2614 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2615 struct tlv_parsed tp;
2616 struct gsm_mncc alerting;
2617
2618 gsm48_stop_cc_timer(trans);
2619 gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
2620
2621 memset(&alerting, 0, sizeof(struct gsm_mncc));
2622 alerting.callref = trans->callref;
2623 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2624 /* facility */
2625 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2626 alerting.fields |= MNCC_F_FACILITY;
2627 decode_facility(&alerting.facility,
2628 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2629 }
2630
2631 /* progress */
2632 if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
2633 alerting.fields |= MNCC_F_PROGRESS;
2634 decode_progress(&alerting.progress,
2635 TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
2636 }
2637 /* ss-version */
2638 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2639 alerting.fields |= MNCC_F_SSVERSION;
2640 decode_ssversion(&alerting.ssversion,
2641 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2642 }
2643
2644 new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
2645
Harald Welte596fed42009-07-23 19:06:52 +02002646 return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
2647 &alerting);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002648}
2649
2650static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
2651{
2652 struct gsm_mncc *alerting = arg;
2653 struct msgb *msg = gsm48_msgb_alloc();
2654 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2655
Harald Welte4bfdfe72009-06-10 23:11:52 +08002656 gh->msg_type = GSM48_MT_CC_ALERTING;
2657
2658 /* facility */
2659 if (alerting->fields & MNCC_F_FACILITY)
2660 encode_facility(msg, 0, &alerting->facility);
2661 /* progress */
2662 if (alerting->fields & MNCC_F_PROGRESS)
2663 encode_progress(msg, 0, &alerting->progress);
2664 /* user-user */
2665 if (alerting->fields & MNCC_F_USERUSER)
2666 encode_useruser(msg, 0, &alerting->useruser);
2667
2668 new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
2669
Harald Welte39e2ead2009-07-23 21:13:03 +02002670 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002671}
2672
2673static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
2674{
2675 struct gsm_mncc *progress = arg;
2676 struct msgb *msg = gsm48_msgb_alloc();
2677 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2678
Harald Welte4bfdfe72009-06-10 23:11:52 +08002679 gh->msg_type = GSM48_MT_CC_PROGRESS;
2680
2681 /* progress */
2682 encode_progress(msg, 1, &progress->progress);
2683 /* user-user */
2684 if (progress->fields & MNCC_F_USERUSER)
2685 encode_useruser(msg, 0, &progress->useruser);
2686
Harald Welte39e2ead2009-07-23 21:13:03 +02002687 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002688}
2689
2690static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
2691{
2692 struct gsm_mncc *connect = arg;
2693 struct msgb *msg = gsm48_msgb_alloc();
2694 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2695
Harald Welte4bfdfe72009-06-10 23:11:52 +08002696 gh->msg_type = GSM48_MT_CC_CONNECT;
2697
2698 gsm48_stop_cc_timer(trans);
2699 gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
2700
2701 /* facility */
2702 if (connect->fields & MNCC_F_FACILITY)
2703 encode_facility(msg, 0, &connect->facility);
2704 /* progress */
2705 if (connect->fields & MNCC_F_PROGRESS)
2706 encode_progress(msg, 0, &connect->progress);
2707 /* connected number */
2708 if (connect->fields & MNCC_F_CONNECTED)
2709 encode_connected(msg, &connect->connected);
2710 /* user-user */
2711 if (connect->fields & MNCC_F_USERUSER)
2712 encode_useruser(msg, 0, &connect->useruser);
2713
2714 new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
2715
Harald Welte39e2ead2009-07-23 21:13:03 +02002716 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002717}
2718
2719static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
2720{
2721 struct gsm48_hdr *gh = msgb_l3(msg);
2722 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2723 struct tlv_parsed tp;
2724 struct gsm_mncc connect;
2725
2726 gsm48_stop_cc_timer(trans);
2727
2728 memset(&connect, 0, sizeof(struct gsm_mncc));
2729 connect.callref = trans->callref;
2730 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2731 /* use subscriber as connected party number */
2732 if (trans->subscr) {
2733 connect.fields |= MNCC_F_CONNECTED;
2734 strncpy(connect.connected.number, trans->subscr->extension,
2735 sizeof(connect.connected.number)-1);
Andreas Eversbergc079be42009-06-15 23:22:09 +02002736 strncpy(connect.imsi, trans->subscr->imsi,
2737 sizeof(connect.imsi)-1);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002738 }
2739 /* facility */
2740 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2741 connect.fields |= MNCC_F_FACILITY;
2742 decode_facility(&connect.facility,
2743 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2744 }
2745 /* user-user */
2746 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2747 connect.fields |= MNCC_F_USERUSER;
2748 decode_useruser(&connect.useruser,
2749 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2750 }
2751 /* ss-version */
2752 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2753 connect.fields |= MNCC_F_SSVERSION;
2754 decode_ssversion(&connect.ssversion,
2755 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2756 }
2757
2758 new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
2759
Harald Welte596fed42009-07-23 19:06:52 +02002760 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002761}
2762
2763
2764static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
2765{
2766 struct gsm_mncc connect_ack;
2767
2768 gsm48_stop_cc_timer(trans);
2769
2770 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2771
2772 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
2773 connect_ack.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02002774 return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
Harald Welte4bfdfe72009-06-10 23:11:52 +08002775 &connect_ack);
2776}
2777
2778static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
2779{
2780 struct msgb *msg = gsm48_msgb_alloc();
2781 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2782
Harald Welte4bfdfe72009-06-10 23:11:52 +08002783 gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
2784
2785 new_cc_state(trans, GSM_CSTATE_ACTIVE);
2786
Harald Welte39e2ead2009-07-23 21:13:03 +02002787 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002788}
2789
2790static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
2791{
2792 struct gsm48_hdr *gh = msgb_l3(msg);
2793 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2794 struct tlv_parsed tp;
2795 struct gsm_mncc disc;
2796
2797 gsm48_stop_cc_timer(trans);
2798
2799 new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
2800
2801 memset(&disc, 0, sizeof(struct gsm_mncc));
2802 disc.callref = trans->callref;
2803 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
2804 /* cause */
2805 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2806 disc.fields |= MNCC_F_CAUSE;
2807 decode_cause(&disc.cause,
2808 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2809 }
2810 /* facility */
2811 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2812 disc.fields |= MNCC_F_FACILITY;
2813 decode_facility(&disc.facility,
2814 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2815 }
2816 /* user-user */
2817 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2818 disc.fields |= MNCC_F_USERUSER;
2819 decode_useruser(&disc.useruser,
2820 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2821 }
2822 /* ss-version */
2823 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2824 disc.fields |= MNCC_F_SSVERSION;
2825 decode_ssversion(&disc.ssversion,
2826 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2827 }
2828
Harald Welte596fed42009-07-23 19:06:52 +02002829 return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002830
2831}
2832
Harald Weltec66b71c2009-06-11 14:23:20 +08002833static struct gsm_mncc_cause default_cause = {
2834 .location = GSM48_CAUSE_LOC_PRN_S_LU,
2835 .coding = 0,
2836 .rec = 0,
2837 .rec_val = 0,
2838 .value = GSM48_CC_CAUSE_NORMAL_UNSPEC,
2839 .diag_len = 0,
2840 .diag = { 0 },
2841};
Harald Welte4bfdfe72009-06-10 23:11:52 +08002842
2843static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
2844{
2845 struct gsm_mncc *disc = arg;
2846 struct msgb *msg = gsm48_msgb_alloc();
2847 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2848
Harald Welte4bfdfe72009-06-10 23:11:52 +08002849 gh->msg_type = GSM48_MT_CC_DISCONNECT;
2850
2851 gsm48_stop_cc_timer(trans);
2852 gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
2853
2854 /* cause */
2855 if (disc->fields & MNCC_F_CAUSE)
2856 encode_cause(msg, 1, &disc->cause);
2857 else
2858 encode_cause(msg, 1, &default_cause);
2859
2860 /* facility */
2861 if (disc->fields & MNCC_F_FACILITY)
2862 encode_facility(msg, 0, &disc->facility);
2863 /* progress */
2864 if (disc->fields & MNCC_F_PROGRESS)
2865 encode_progress(msg, 0, &disc->progress);
2866 /* user-user */
2867 if (disc->fields & MNCC_F_USERUSER)
2868 encode_useruser(msg, 0, &disc->useruser);
2869
2870 /* store disconnect cause for T306 expiry */
Harald Weltedcaf5652009-07-23 18:56:43 +02002871 memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002872
2873 new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
2874
Harald Welte39e2ead2009-07-23 21:13:03 +02002875 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002876}
2877
2878static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
2879{
2880 struct gsm48_hdr *gh = msgb_l3(msg);
2881 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2882 struct tlv_parsed tp;
2883 struct gsm_mncc rel;
2884 int rc;
2885
2886 gsm48_stop_cc_timer(trans);
2887
2888 memset(&rel, 0, sizeof(struct gsm_mncc));
2889 rel.callref = trans->callref;
2890 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2891 /* cause */
2892 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2893 rel.fields |= MNCC_F_CAUSE;
2894 decode_cause(&rel.cause,
2895 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2896 }
2897 /* facility */
2898 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2899 rel.fields |= MNCC_F_FACILITY;
2900 decode_facility(&rel.facility,
2901 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2902 }
2903 /* user-user */
2904 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2905 rel.fields |= MNCC_F_USERUSER;
2906 decode_useruser(&rel.useruser,
2907 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2908 }
2909 /* ss-version */
2910 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2911 rel.fields |= MNCC_F_SSVERSION;
2912 decode_ssversion(&rel.ssversion,
2913 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
2914 }
2915
Harald Weltedcaf5652009-07-23 18:56:43 +02002916 if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08002917 /* release collision 5.4.5 */
Harald Welte596fed42009-07-23 19:06:52 +02002918 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002919 } else {
Harald Welte596fed42009-07-23 19:06:52 +02002920 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02002921 GSM48_PDISC_CC | (trans->transaction_id << 4),
Harald Welte596fed42009-07-23 19:06:52 +02002922 GSM48_MT_CC_RELEASE_COMPL);
2923 rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002924 }
2925
2926 new_cc_state(trans, GSM_CSTATE_NULL);
2927
2928 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02002929 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002930
2931 return rc;
2932}
2933
2934static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
2935{
2936 struct gsm_mncc *rel = arg;
2937 struct msgb *msg = gsm48_msgb_alloc();
2938 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2939
Harald Welte4bfdfe72009-06-10 23:11:52 +08002940 gh->msg_type = GSM48_MT_CC_RELEASE;
2941
2942 trans->callref = 0;
2943
2944 gsm48_stop_cc_timer(trans);
2945 gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
2946
2947 /* cause */
2948 if (rel->fields & MNCC_F_CAUSE)
2949 encode_cause(msg, 0, &rel->cause);
2950 /* facility */
2951 if (rel->fields & MNCC_F_FACILITY)
2952 encode_facility(msg, 0, &rel->facility);
2953 /* user-user */
2954 if (rel->fields & MNCC_F_USERUSER)
2955 encode_useruser(msg, 0, &rel->useruser);
2956
Harald Weltedcaf5652009-07-23 18:56:43 +02002957 trans->cc.T308_second = 0;
2958 memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
Harald Welte4bfdfe72009-06-10 23:11:52 +08002959
Harald Weltedcaf5652009-07-23 18:56:43 +02002960 if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
Harald Welte4bfdfe72009-06-10 23:11:52 +08002961 new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
2962
Harald Welte39e2ead2009-07-23 21:13:03 +02002963 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08002964}
2965
2966static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
2967{
2968 struct gsm48_hdr *gh = msgb_l3(msg);
2969 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2970 struct tlv_parsed tp;
2971 struct gsm_mncc rel;
2972 int rc = 0;
2973
2974 gsm48_stop_cc_timer(trans);
2975
2976 memset(&rel, 0, sizeof(struct gsm_mncc));
2977 rel.callref = trans->callref;
2978 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
2979 /* cause */
2980 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
2981 rel.fields |= MNCC_F_CAUSE;
2982 decode_cause(&rel.cause,
2983 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
2984 }
2985 /* facility */
2986 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
2987 rel.fields |= MNCC_F_FACILITY;
2988 decode_facility(&rel.facility,
2989 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
2990 }
2991 /* user-user */
2992 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
2993 rel.fields |= MNCC_F_USERUSER;
2994 decode_useruser(&rel.useruser,
2995 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
2996 }
2997 /* ss-version */
2998 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
2999 rel.fields |= MNCC_F_SSVERSION;
3000 decode_ssversion(&rel.ssversion,
3001 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3002 }
3003
3004 if (trans->callref) {
Harald Weltedcaf5652009-07-23 18:56:43 +02003005 switch (trans->cc.state) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003006 case GSM_CSTATE_CALL_PRESENT:
Harald Welte596fed42009-07-23 19:06:52 +02003007 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003008 MNCC_REJ_IND, &rel);
3009 break;
3010 case GSM_CSTATE_RELEASE_REQ:
Harald Welte596fed42009-07-23 19:06:52 +02003011 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003012 MNCC_REL_CNF, &rel);
3013 break;
3014 default:
Harald Welte596fed42009-07-23 19:06:52 +02003015 rc = mncc_recvmsg(trans->subscr->net, trans,
Harald Welte4bfdfe72009-06-10 23:11:52 +08003016 MNCC_REL_IND, &rel);
3017 }
3018 }
3019
3020 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02003021 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003022
3023 return rc;
3024}
3025
3026static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
3027{
3028 struct gsm_mncc *rel = arg;
3029 struct msgb *msg = gsm48_msgb_alloc();
3030 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3031
Harald Welte4bfdfe72009-06-10 23:11:52 +08003032 gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
3033
3034 trans->callref = 0;
3035
3036 gsm48_stop_cc_timer(trans);
3037
3038 /* cause */
3039 if (rel->fields & MNCC_F_CAUSE)
3040 encode_cause(msg, 0, &rel->cause);
3041 /* facility */
3042 if (rel->fields & MNCC_F_FACILITY)
3043 encode_facility(msg, 0, &rel->facility);
3044 /* user-user */
3045 if (rel->fields & MNCC_F_USERUSER)
3046 encode_useruser(msg, 0, &rel->useruser);
3047
Harald Weltedcaf5652009-07-23 18:56:43 +02003048 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003049
Harald Welte39e2ead2009-07-23 21:13:03 +02003050 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003051}
3052
3053static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
3054{
3055 struct gsm48_hdr *gh = msgb_l3(msg);
3056 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3057 struct tlv_parsed tp;
3058 struct gsm_mncc fac;
3059
3060 memset(&fac, 0, sizeof(struct gsm_mncc));
3061 fac.callref = trans->callref;
3062 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
3063 /* facility */
3064 if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
3065 fac.fields |= MNCC_F_FACILITY;
3066 decode_facility(&fac.facility,
3067 TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
3068 }
3069 /* ss-version */
3070 if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
3071 fac.fields |= MNCC_F_SSVERSION;
3072 decode_ssversion(&fac.ssversion,
3073 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
3074 }
3075
Harald Welte596fed42009-07-23 19:06:52 +02003076 return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003077}
3078
3079static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
3080{
3081 struct gsm_mncc *fac = arg;
3082 struct msgb *msg = gsm48_msgb_alloc();
3083 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3084
Harald Welte4bfdfe72009-06-10 23:11:52 +08003085 gh->msg_type = GSM48_MT_CC_FACILITY;
3086
3087 /* facility */
3088 encode_facility(msg, 1, &fac->facility);
3089
Harald Welte39e2ead2009-07-23 21:13:03 +02003090 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003091}
3092
3093static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
3094{
3095 struct gsm_mncc hold;
3096
3097 memset(&hold, 0, sizeof(struct gsm_mncc));
3098 hold.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003099 return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003100}
3101
3102static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
3103{
3104 struct msgb *msg = gsm48_msgb_alloc();
3105 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3106
Harald Welte4bfdfe72009-06-10 23:11:52 +08003107 gh->msg_type = GSM48_MT_CC_HOLD_ACK;
3108
Harald Welte39e2ead2009-07-23 21:13:03 +02003109 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003110}
3111
3112static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
3113{
3114 struct gsm_mncc *hold_rej = arg;
3115 struct msgb *msg = gsm48_msgb_alloc();
3116 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3117
Harald Welte4bfdfe72009-06-10 23:11:52 +08003118 gh->msg_type = GSM48_MT_CC_HOLD_REJ;
3119
3120 /* cause */
3121 if (hold_rej->fields & MNCC_F_CAUSE)
3122 encode_cause(msg, 1, &hold_rej->cause);
3123 else
3124 encode_cause(msg, 1, &default_cause);
3125
Harald Welte39e2ead2009-07-23 21:13:03 +02003126 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003127}
3128
3129static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
3130{
3131 struct gsm_mncc retrieve;
3132
3133 memset(&retrieve, 0, sizeof(struct gsm_mncc));
3134 retrieve.callref = trans->callref;
Harald Welte596fed42009-07-23 19:06:52 +02003135 return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
3136 &retrieve);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003137}
3138
3139static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
3140{
3141 struct msgb *msg = gsm48_msgb_alloc();
3142 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3143
Harald Welte4bfdfe72009-06-10 23:11:52 +08003144 gh->msg_type = GSM48_MT_CC_RETR_ACK;
3145
Harald Welte39e2ead2009-07-23 21:13:03 +02003146 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003147}
3148
3149static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
3150{
3151 struct gsm_mncc *retrieve_rej = arg;
3152 struct msgb *msg = gsm48_msgb_alloc();
3153 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3154
Harald Welte4bfdfe72009-06-10 23:11:52 +08003155 gh->msg_type = GSM48_MT_CC_RETR_REJ;
3156
3157 /* cause */
3158 if (retrieve_rej->fields & MNCC_F_CAUSE)
3159 encode_cause(msg, 1, &retrieve_rej->cause);
3160 else
3161 encode_cause(msg, 1, &default_cause);
3162
Harald Welte39e2ead2009-07-23 21:13:03 +02003163 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003164}
3165
3166static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
3167{
3168 struct gsm48_hdr *gh = msgb_l3(msg);
3169 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3170 struct tlv_parsed tp;
3171 struct gsm_mncc dtmf;
3172
3173 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3174 dtmf.callref = trans->callref;
3175 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0);
3176 /* keypad facility */
3177 if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
3178 dtmf.fields |= MNCC_F_KEYPAD;
3179 decode_keypad(&dtmf.keypad,
3180 TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
3181 }
3182
Harald Welte596fed42009-07-23 19:06:52 +02003183 return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003184}
3185
3186static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
3187{
3188 struct gsm_mncc *dtmf = arg;
3189 struct msgb *msg = gsm48_msgb_alloc();
3190 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3191
Harald Welte4bfdfe72009-06-10 23:11:52 +08003192 gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
3193
3194 /* keypad */
3195 if (dtmf->fields & MNCC_F_KEYPAD)
3196 encode_keypad(msg, dtmf->keypad);
3197
Harald Welte39e2ead2009-07-23 21:13:03 +02003198 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003199}
3200
3201static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
3202{
3203 struct gsm_mncc *dtmf = arg;
3204 struct msgb *msg = gsm48_msgb_alloc();
3205 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3206
Harald Welte4bfdfe72009-06-10 23:11:52 +08003207 gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
3208
3209 /* cause */
3210 if (dtmf->fields & MNCC_F_CAUSE)
3211 encode_cause(msg, 1, &dtmf->cause);
3212 else
3213 encode_cause(msg, 1, &default_cause);
3214
Harald Welte39e2ead2009-07-23 21:13:03 +02003215 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003216}
3217
3218static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
3219{
3220 struct msgb *msg = gsm48_msgb_alloc();
3221 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3222
Harald Welte4bfdfe72009-06-10 23:11:52 +08003223 gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
3224
Harald Welte39e2ead2009-07-23 21:13:03 +02003225 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003226}
3227
3228static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
3229{
3230 struct gsm_mncc dtmf;
3231
3232 memset(&dtmf, 0, sizeof(struct gsm_mncc));
3233 dtmf.callref = trans->callref;
3234
Harald Welte596fed42009-07-23 19:06:52 +02003235 return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003236}
3237
3238static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
3239{
3240 struct gsm48_hdr *gh = msgb_l3(msg);
3241 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3242 struct tlv_parsed tp;
3243 struct gsm_mncc modify;
3244
3245 memset(&modify, 0, sizeof(struct gsm_mncc));
3246 modify.callref = trans->callref;
3247 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3248 /* bearer capability */
3249 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3250 modify.fields |= MNCC_F_BEARER_CAP;
3251 decode_bearer_cap(&modify.bearer_cap,
3252 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3253 }
3254
3255 new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
3256
Harald Welte596fed42009-07-23 19:06:52 +02003257 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003258}
3259
3260static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
3261{
3262 struct gsm_mncc *modify = arg;
3263 struct msgb *msg = gsm48_msgb_alloc();
3264 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3265
Harald Welte4bfdfe72009-06-10 23:11:52 +08003266 gh->msg_type = GSM48_MT_CC_MODIFY;
3267
3268 gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
3269
3270 /* bearer capability */
3271 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3272
3273 new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
3274
Harald Welte39e2ead2009-07-23 21:13:03 +02003275 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003276}
3277
3278static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
3279{
3280 struct gsm48_hdr *gh = msgb_l3(msg);
3281 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3282 struct tlv_parsed tp;
3283 struct gsm_mncc modify;
3284
3285 gsm48_stop_cc_timer(trans);
3286
3287 memset(&modify, 0, sizeof(struct gsm_mncc));
3288 modify.callref = trans->callref;
3289 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
3290 /* bearer capability */
3291 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3292 modify.fields |= MNCC_F_BEARER_CAP;
3293 decode_bearer_cap(&modify.bearer_cap,
3294 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3295 }
3296
3297 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3298
Harald Welte596fed42009-07-23 19:06:52 +02003299 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003300}
3301
3302static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
3303{
3304 struct gsm_mncc *modify = arg;
3305 struct msgb *msg = gsm48_msgb_alloc();
3306 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3307
Harald Welte4bfdfe72009-06-10 23:11:52 +08003308 gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
3309
3310 /* bearer capability */
3311 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3312
3313 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3314
Harald Welte39e2ead2009-07-23 21:13:03 +02003315 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003316}
3317
3318static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
3319{
3320 struct gsm48_hdr *gh = msgb_l3(msg);
3321 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3322 struct tlv_parsed tp;
3323 struct gsm_mncc modify;
3324
3325 gsm48_stop_cc_timer(trans);
3326
3327 memset(&modify, 0, sizeof(struct gsm_mncc));
3328 modify.callref = trans->callref;
3329 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
3330 /* bearer capability */
3331 if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
3332 modify.fields |= GSM48_IE_BEARER_CAP;
3333 decode_bearer_cap(&modify.bearer_cap,
3334 TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
3335 }
3336 /* cause */
3337 if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
3338 modify.fields |= MNCC_F_CAUSE;
3339 decode_cause(&modify.cause,
3340 TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
3341 }
3342
3343 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3344
Harald Welte596fed42009-07-23 19:06:52 +02003345 return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003346}
3347
3348static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
3349{
3350 struct gsm_mncc *modify = arg;
3351 struct msgb *msg = gsm48_msgb_alloc();
3352 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3353
Harald Welte4bfdfe72009-06-10 23:11:52 +08003354 gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
3355
3356 /* bearer capability */
3357 encode_bearer_cap(msg, 1, &modify->bearer_cap);
3358 /* cause */
3359 encode_cause(msg, 1, &modify->cause);
3360
3361 new_cc_state(trans, GSM_CSTATE_ACTIVE);
3362
Harald Welte39e2ead2009-07-23 21:13:03 +02003363 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003364}
3365
3366static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
3367{
3368 struct gsm_mncc *notify = arg;
3369 struct msgb *msg = gsm48_msgb_alloc();
3370 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3371
Harald Welte4bfdfe72009-06-10 23:11:52 +08003372 gh->msg_type = GSM48_MT_CC_NOTIFY;
3373
3374 /* notify */
3375 encode_notify(msg, notify->notify);
3376
Harald Welte39e2ead2009-07-23 21:13:03 +02003377 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003378}
3379
3380static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
3381{
3382 struct gsm48_hdr *gh = msgb_l3(msg);
3383 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3384// struct tlv_parsed tp;
3385 struct gsm_mncc notify;
3386
3387 memset(&notify, 0, sizeof(struct gsm_mncc));
3388 notify.callref = trans->callref;
3389// tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len);
3390 if (payload_len >= 1)
3391 decode_notify(&notify.notify, gh->data);
3392
Harald Welte596fed42009-07-23 19:06:52 +02003393 return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003394}
3395
3396static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
3397{
3398 struct gsm_mncc *user = arg;
3399 struct msgb *msg = gsm48_msgb_alloc();
3400 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
3401
Harald Welte4bfdfe72009-06-10 23:11:52 +08003402 gh->msg_type = GSM48_MT_CC_USER_INFO;
3403
3404 /* user-user */
3405 if (user->fields & MNCC_F_USERUSER)
3406 encode_useruser(msg, 1, &user->useruser);
3407 /* more data */
3408 if (user->more)
3409 encode_more(msg);
3410
Harald Welte39e2ead2009-07-23 21:13:03 +02003411 return gsm48_sendmsg(msg, trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003412}
3413
3414static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
3415{
3416 struct gsm48_hdr *gh = msgb_l3(msg);
3417 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
3418 struct tlv_parsed tp;
3419 struct gsm_mncc user;
3420
3421 memset(&user, 0, sizeof(struct gsm_mncc));
3422 user.callref = trans->callref;
3423 tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
3424 /* user-user */
3425 if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
3426 user.fields |= MNCC_F_USERUSER;
3427 decode_useruser(&user.useruser,
3428 TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
3429 }
3430 /* more data */
3431 if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
3432 user.more = 1;
3433
Harald Welte596fed42009-07-23 19:06:52 +02003434 return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003435}
3436
3437static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
3438{
3439 struct gsm_mncc *mode = arg;
Harald Welte13cac662009-07-29 12:10:35 +02003440 int rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003441
Harald Welte13cac662009-07-29 12:10:35 +02003442 rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
3443 if (rc < 0)
3444 return rc;
3445
3446 /* FIXME: we not only need to do this after mode modify, but
3447 * also after channel activation */
3448 if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
3449 mode->lchan_mode != GSM48_CMODE_SIGN)
3450 rc = rsl_ipacc_bind(trans->lchan);
3451
3452 return rc;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003453}
3454
3455static struct downstate {
3456 u_int32_t states;
3457 int type;
3458 int (*rout) (struct gsm_trans *trans, void *arg);
3459} downstatelist[] = {
3460 /* mobile originating call establishment */
3461 {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
3462 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc},
3463 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
3464 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
3465 {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC) | SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.2 | 5.2.1.6 | 5.2.1.6 */
3466 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
3467 {SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
3468 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
3469 /* mobile terminating call establishment */
3470 {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
3471 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
3472 {SBIT(GSM_CSTATE_CONNECT_REQUEST),
3473 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
3474 /* signalling during call */
3475 {SBIT(GSM_CSTATE_ACTIVE),
3476 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
3477 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
3478 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
3479 {ALL_STATES,
3480 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
3481 {ALL_STATES,
3482 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
3483 {ALL_STATES,
3484 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
3485 {SBIT(GSM_CSTATE_ACTIVE),
3486 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
3487 {SBIT(GSM_CSTATE_ACTIVE),
3488 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
3489 {SBIT(GSM_CSTATE_ACTIVE),
3490 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
3491 {SBIT(GSM_CSTATE_ACTIVE),
3492 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
3493 {SBIT(GSM_CSTATE_ACTIVE),
3494 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
3495 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3496 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
3497 {SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
3498 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
3499 {SBIT(GSM_CSTATE_ACTIVE),
3500 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
3501 /* clearing */
3502 {SBIT(GSM_CSTATE_INITIATED),
3503 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
3504 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
3505 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
3506 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3507 MNCC_REL_REQ, gsm48_cc_tx_release},
3508 /* special */
3509 {ALL_STATES,
3510 MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
3511};
3512
3513#define DOWNSLLEN \
3514 (sizeof(downstatelist) / sizeof(struct downstate))
3515
3516
3517int mncc_send(struct gsm_network *net, int msg_type, void *arg)
3518{
Harald Welte1a6f7982009-08-09 18:52:33 +02003519 int i, rc = 0;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003520 struct gsm_trans *trans = NULL, *transt;
3521 struct gsm_subscriber *subscr;
Harald Welte1a6f7982009-08-09 18:52:33 +02003522 struct gsm_lchan *lchan = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003523 struct gsm_bts *bts = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003524 struct gsm_mncc *data = arg, rel;
3525
3526 /* handle special messages */
3527 switch(msg_type) {
3528 case MNCC_BRIDGE:
3529 return tch_bridge(net, arg);
3530 case MNCC_FRAME_DROP:
3531 return tch_recv(net, arg, 0);
3532 case MNCC_FRAME_RECV:
3533 return tch_recv(net, arg, 1);
3534 case GSM_TRAU_FRAME:
3535 return tch_frame(net, arg);
3536 }
3537
3538 memset(&rel, 0, sizeof(struct gsm_mncc));
3539 rel.callref = data->callref;
3540
3541 /* Find callref */
Harald Weltedcaf5652009-07-23 18:56:43 +02003542 trans = trans_find_by_callref(net, data->callref);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003543
3544 /* Callref unknown */
3545 if (!trans) {
Harald Welte4a3464c2009-07-04 10:11:24 +02003546 if (msg_type != MNCC_SETUP_REQ) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003547 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3548 "Received '%s' from MNCC with "
3549 "unknown callref %d\n", data->called.number,
3550 get_mncc_name(msg_type), data->callref);
3551 /* Invalid call reference */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003552 return mncc_release_ind(net, NULL, data->callref,
3553 GSM48_CAUSE_LOC_PRN_S_LU,
3554 GSM48_CC_CAUSE_INVAL_TRANS_ID);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003555 }
Andreas Eversbergc079be42009-06-15 23:22:09 +02003556 if (!data->called.number[0] && !data->imsi[0]) {
3557 DEBUGP(DCC, "(bts - trx - ts - ti) "
3558 "Received '%s' from MNCC with "
3559 "no number or IMSI\n", get_mncc_name(msg_type));
3560 /* Invalid number */
3561 return mncc_release_ind(net, NULL, data->callref,
3562 GSM48_CAUSE_LOC_PRN_S_LU,
3563 GSM48_CC_CAUSE_INV_NR_FORMAT);
3564 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003565 /* New transaction due to setup, find subscriber */
Andreas Eversbergc079be42009-06-15 23:22:09 +02003566 if (data->called.number[0])
Harald Welte9176bd42009-07-23 18:46:00 +02003567 subscr = subscr_get_by_extension(net,
3568 data->called.number);
Andreas Eversbergc079be42009-06-15 23:22:09 +02003569 else
Harald Welte9176bd42009-07-23 18:46:00 +02003570 subscr = subscr_get_by_imsi(net, data->imsi);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003571 /* If subscriber is not found */
3572 if (!subscr) {
3573 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3574 "Received '%s' from MNCC with "
3575 "unknown subscriber %s\n", data->called.number,
3576 get_mncc_name(msg_type), data->called.number);
3577 /* Unknown subscriber */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003578 return mncc_release_ind(net, NULL, data->callref,
3579 GSM48_CAUSE_LOC_PRN_S_LU,
3580 GSM48_CC_CAUSE_UNASSIGNED_NR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003581 }
3582 /* If subscriber is not "attached" */
3583 if (!subscr->lac) {
3584 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3585 "Received '%s' from MNCC with "
3586 "detached subscriber %s\n", data->called.number,
3587 get_mncc_name(msg_type), data->called.number);
3588 subscr_put(subscr);
3589 /* Temporarily out of order */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003590 return mncc_release_ind(net, NULL, data->callref,
3591 GSM48_CAUSE_LOC_PRN_S_LU,
3592 GSM48_CC_CAUSE_DEST_OOO);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003593 }
3594 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003595 trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
3596 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003597 DEBUGP(DCC, "No memory for trans.\n");
3598 subscr_put(subscr);
3599 /* Ressource unavailable */
Andreas Eversberg7563ac92009-06-14 22:14:12 +08003600 mncc_release_ind(net, NULL, data->callref,
3601 GSM48_CAUSE_LOC_PRN_S_LU,
3602 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003603 return -ENOMEM;
3604 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003605 /* Find lchan */
Harald Welte1a6f7982009-08-09 18:52:33 +02003606 lchan = lchan_for_subscr(subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003607 /* If subscriber has no lchan */
3608 if (!lchan) {
3609 /* find transaction with this subscriber already paging */
3610 llist_for_each_entry(transt, &net->trans_list, entry) {
3611 /* Transaction of our lchan? */
3612 if (transt == trans ||
3613 transt->subscr != subscr)
3614 continue;
3615 DEBUGP(DCC, "(bts %d trx - ts - ti -- sub %s) "
3616 "Received '%s' from MNCC with "
3617 "unallocated channel, paging already "
3618 "started.\n", bts->nr,
3619 data->called.number,
3620 get_mncc_name(msg_type));
3621 return 0;
3622 }
3623 /* store setup informations until paging was successfull */
Harald Weltedcaf5652009-07-23 18:56:43 +02003624 memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
Harald Weltea1b28582009-08-01 19:31:47 +02003625 /* Trigger paging */
3626 paging_request(net, subscr, RSL_CHANNEED_TCH_F,
3627 setup_trig_pag_evt, subscr);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003628 return 0;
3629 }
3630 /* Assign lchan */
3631 trans->lchan = lchan;
3632 use_lchan(lchan);
3633 }
3634 lchan = trans->lchan;
3635
3636 /* if paging did not respond yet */
3637 if (!lchan) {
3638 DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
3639 "Received '%s' from MNCC in paging state\n",
3640 (trans->subscr)?(trans->subscr->extension):"-",
3641 get_mncc_name(msg_type));
Harald Weltec66b71c2009-06-11 14:23:20 +08003642 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
3643 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003644 if (msg_type == MNCC_REL_REQ)
3645 rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
3646 else
3647 rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
3648 trans->callref = 0;
Harald Weltedcaf5652009-07-23 18:56:43 +02003649 trans_free(trans);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003650 return rc;
3651 }
3652
3653 DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
3654 "Received '%s' from MNCC in state %d (%s)\n",
3655 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3656 trans->transaction_id,
3657 (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003658 get_mncc_name(msg_type), trans->cc.state,
3659 cc_state_names[trans->cc.state]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003660
3661 /* Find function for current state and message */
3662 for (i = 0; i < DOWNSLLEN; i++)
3663 if ((msg_type == downstatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003664 && ((1 << trans->cc.state) & downstatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003665 break;
3666 if (i == DOWNSLLEN) {
3667 DEBUGP(DCC, "Message unhandled at this state.\n");
3668 return 0;
3669 }
3670
3671 rc = downstatelist[i].rout(trans, arg);
3672
3673 return rc;
3674}
3675
3676
3677static struct datastate {
3678 u_int32_t states;
3679 int type;
3680 int (*rout) (struct gsm_trans *trans, struct msgb *msg);
3681} datastatelist[] = {
3682 /* mobile originating call establishment */
3683 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3684 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
3685 {SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
3686 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
3687 {SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
3688 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
3689 /* mobile terminating call establishment */
3690 {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
3691 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
3692 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
3693 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
3694 {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */
3695 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
3696 /* signalling during call */
3697 {ALL_STATES - SBIT(GSM_CSTATE_NULL),
3698 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
3699 {SBIT(GSM_CSTATE_ACTIVE),
3700 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
3701 {ALL_STATES,
3702 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
3703 {ALL_STATES,
3704 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
3705 {ALL_STATES,
3706 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
3707 {SBIT(GSM_CSTATE_ACTIVE),
3708 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
3709 {SBIT(GSM_CSTATE_ACTIVE),
3710 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
3711 {SBIT(GSM_CSTATE_ACTIVE),
3712 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
3713 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3714 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
3715 {SBIT(GSM_CSTATE_MO_TERM_MODIFY),
3716 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
3717 {SBIT(GSM_CSTATE_ACTIVE),
3718 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
3719 /* clearing */
3720 {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
3721 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
3722 {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
3723 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
3724 {ALL_STATES, /* 5.4.3.4 */
3725 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
3726};
3727
3728#define DATASLLEN \
3729 (sizeof(datastatelist) / sizeof(struct datastate))
3730
Harald Welte4bc90a12008-12-27 16:32:52 +00003731static int gsm0408_rcv_cc(struct msgb *msg)
3732{
3733 struct gsm48_hdr *gh = msgb_l3(msg);
3734 u_int8_t msg_type = gh->msg_type & 0xbf;
Harald Welte6f5aee02009-07-23 21:21:14 +02003735 u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003736 struct gsm_lchan *lchan = msg->lchan;
Harald Weltedcaf5652009-07-23 18:56:43 +02003737 struct gsm_trans *trans = NULL;
Harald Welte4bfdfe72009-06-10 23:11:52 +08003738 int i, rc = 0;
Harald Welte4bc90a12008-12-27 16:32:52 +00003739
Harald Welte4bfdfe72009-06-10 23:11:52 +08003740 if (msg_type & 0x80) {
3741 DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
3742 return -EINVAL;
Harald Welte4bc90a12008-12-27 16:32:52 +00003743 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003744
3745 /* Find transaction */
Harald Welteb8b40732009-07-23 21:58:40 +02003746 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
Harald Weltedcaf5652009-07-23 18:56:43 +02003747
Harald Welte6f5aee02009-07-23 21:21:14 +02003748 DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003749 "Received '%s' from MS in state %d (%s)\n",
3750 lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
3751 transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
Harald Weltedcaf5652009-07-23 18:56:43 +02003752 cc_msg_names[msg_type], trans?(trans->cc.state):0,
3753 cc_state_names[trans?(trans->cc.state):0]);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003754
3755 /* Create transaction */
3756 if (!trans) {
Harald Welte6f5aee02009-07-23 21:21:14 +02003757 DEBUGP(DCC, "Unknown transaction ID %x, "
Harald Welte4bfdfe72009-06-10 23:11:52 +08003758 "creating new trans.\n", transaction_id);
3759 /* Create transaction */
Harald Weltedcaf5652009-07-23 18:56:43 +02003760 trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
3761 transaction_id, new_callref++);
3762 if (!trans) {
Harald Welte4bfdfe72009-06-10 23:11:52 +08003763 DEBUGP(DCC, "No memory for trans.\n");
3764 rc = gsm48_tx_simple(msg->lchan,
Harald Welte6f5aee02009-07-23 21:21:14 +02003765 GSM48_PDISC_CC | (transaction_id << 4),
Harald Welte4bfdfe72009-06-10 23:11:52 +08003766 GSM48_MT_CC_RELEASE_COMPL);
3767 return -ENOMEM;
3768 }
Harald Welte4bfdfe72009-06-10 23:11:52 +08003769 /* Assign transaction */
Harald Welte4bfdfe72009-06-10 23:11:52 +08003770 trans->lchan = lchan;
3771 use_lchan(lchan);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003772 }
3773
3774 /* find function for current state and message */
3775 for (i = 0; i < DATASLLEN; i++)
3776 if ((msg_type == datastatelist[i].type)
Harald Weltedcaf5652009-07-23 18:56:43 +02003777 && ((1 << trans->cc.state) & datastatelist[i].states))
Harald Welte4bfdfe72009-06-10 23:11:52 +08003778 break;
3779 if (i == DATASLLEN) {
3780 DEBUGP(DCC, "Message unhandled at this state.\n");
3781 return 0;
3782 }
3783
3784 rc = datastatelist[i].rout(trans, msg);
Harald Welte4bc90a12008-12-27 16:32:52 +00003785
3786 return rc;
3787}
3788
Harald Welte52b1f982008-12-23 20:25:15 +00003789/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
Harald Welte (local)daef6062009-08-14 11:41:12 +02003790int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +00003791{
3792 struct gsm48_hdr *gh = msgb_l3(msg);
3793 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +00003794 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00003795
3796 switch (pdisc) {
3797 case GSM48_PDISC_CC:
3798 rc = gsm0408_rcv_cc(msg);
3799 break;
3800 case GSM48_PDISC_MM:
3801 rc = gsm0408_rcv_mm(msg);
3802 break;
3803 case GSM48_PDISC_RR:
3804 rc = gsm0408_rcv_rr(msg);
3805 break;
Harald Weltebcae43f2008-12-27 21:45:37 +00003806 case GSM48_PDISC_SMS:
Harald Welte (local)daef6062009-08-14 11:41:12 +02003807 rc = gsm0411_rcv_sms(msg, link_id);
Harald Weltebcae43f2008-12-27 21:45:37 +00003808 break;
Harald Welte52b1f982008-12-23 20:25:15 +00003809 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +00003810 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +00003811 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
3812 pdisc);
3813 break;
3814 default:
3815 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
3816 pdisc);
3817 break;
3818 }
3819
3820 return rc;
3821}
Harald Welte8470bf22008-12-25 23:28:35 +00003822
Harald Welte8470bf22008-12-25 23:28:35 +00003823/* Section 9.1.8 / Table 9.9 */
3824struct chreq {
3825 u_int8_t val;
3826 u_int8_t mask;
3827 enum chreq_type type;
3828};
3829
3830/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
3831static const struct chreq chreq_type_neci1[] = {
3832 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3833 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
3834 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
3835 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
3836 { 0xe0, 0xe0, CHREQ_T_SDCCH },
3837 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
3838 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3839 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
3840 { 0x10, 0xf0, CHREQ_T_SDCCH },
3841 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3842 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3843 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3844};
3845
3846/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
3847static const struct chreq chreq_type_neci0[] = {
3848 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
3849 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
3850 { 0xe0, 0xe0, CHREQ_T_TCH_F },
3851 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
3852 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
3853 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
3854 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
3855 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
3856};
3857
3858static const enum gsm_chan_t ctype_by_chreq[] = {
3859 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
3860 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
3861 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
3862 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
3863 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
3864 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
3865 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3866 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
3867 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
3868 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
3869 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
3870 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
3871};
3872
Harald Weltee14a57c2008-12-29 04:08:28 +00003873static const enum gsm_chreq_reason_t reason_by_chreq[] = {
3874 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
3875 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
3876 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
3877 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
3878 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
3879 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
3880 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3881 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
3882 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
3883 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
3884 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
3885 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
3886};
3887
Harald Welte8470bf22008-12-25 23:28:35 +00003888enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3889{
3890 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003891 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Welte8470bf22008-12-25 23:28:35 +00003892
Harald Weltee58ca7c2009-08-10 02:14:46 +02003893 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3894 const struct chreq *chr = &chreq_type_neci0[i];
Harald Welte8470bf22008-12-25 23:28:35 +00003895 if ((ra & chr->mask) == chr->val)
3896 return ctype_by_chreq[chr->type];
3897 }
3898 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
3899 return GSM_LCHAN_SDCCH;
3900}
Harald Weltee14a57c2008-12-29 04:08:28 +00003901
3902enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
3903{
3904 int i;
Harald Weltee58ca7c2009-08-10 02:14:46 +02003905 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
Harald Weltee14a57c2008-12-29 04:08:28 +00003906
Harald Weltee58ca7c2009-08-10 02:14:46 +02003907 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
3908 const struct chreq *chr = &chreq_type_neci0[i];
Harald Weltee14a57c2008-12-29 04:08:28 +00003909 if ((ra & chr->mask) == chr->val)
3910 return reason_by_chreq[chr->type];
3911 }
3912 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
3913 return GSM_CHREQ_REASON_OTHER;
3914}
Harald Welte4bfdfe72009-06-10 23:11:52 +08003915
3916/* dequeue messages to layer 4 */
3917int bsc_upqueue(struct gsm_network *net)
3918{
3919 struct gsm_mncc *mncc;
3920 struct msgb *msg;
3921 int work = 0;
3922
3923 if (net)
3924 while ((msg = msgb_dequeue(&net->upqueue))) {
3925 mncc = (struct gsm_mncc *)msg->data;
3926 if (net->mncc_recv)
3927 net->mncc_recv(net, mncc->msg_type, mncc);
3928 work = 1; /* work done */
Harald Welte316c8252009-06-26 19:40:48 +02003929 talloc_free(msg);
Harald Welte4bfdfe72009-06-10 23:11:52 +08003930 }
3931
3932 return work;
3933}
Harald Weltedcaf5652009-07-23 18:56:43 +02003934
Harald Welte805f6442009-07-28 18:25:29 +02003935/*
3936 * This will be ran by the linker when loading the DSO. We use it to
3937 * do system initialization, e.g. registration of signal handlers.
3938 */
3939static __attribute__((constructor)) void on_dso_load_0408(void)
3940{
Harald Welte805f6442009-07-28 18:25:29 +02003941 register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
3942 register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
3943}