blob: 7d24657301f737be37509c5a1a0d7ebea8f8edc3 [file] [log] [blame]
Harald Welte9b455bf2010-03-14 15:45:01 +08001/* 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
4/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Harald Welteeaa614c2010-05-02 11:26:34 +020027#include <stdint.h>
Harald Welte9b455bf2010-03-14 15:45:01 +080028#include <errno.h>
29
30#include <netinet/in.h>
31
32#include <openbsc/db.h>
33#include <osmocore/msgb.h>
34#include <osmocore/tlv.h>
35#include <openbsc/debug.h>
36#include <openbsc/gsm_data.h>
37#include <osmocore/gsm_utils.h>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_08.h>
40#include <openbsc/gsm_04_08_gprs.h>
41#include <openbsc/paging.h>
42#include <osmocore/signal.h>
43#include <osmocore/talloc.h>
44#include <openbsc/transaction.h>
45#include <openbsc/gprs_llc.h>
46#include <openbsc/gprs_sgsn.h>
47
48/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */
49struct value_string gmm_cause_names[] = {
50 /* FIXME */
51 { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
52 { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
53 { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
54 "Message type non-existant or not implemented" },
55 { GMM_CAUSE_MSGT_INCOMP_P_STATE,
56 "Message type not compatible with protocol state" },
57 { GMM_CAUSE_IE_NOTEXIST_NOTIMPL,
58 "Information element non-existent or not implemented" },
59 { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" },
60 { GMM_CAUSE_MSG_INCOMP_P_STATE,
61 "Message not compatible with protocol state " },
62 { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
63 { 0, NULL }
64};
65
66/* 10.5.6.6 SM Cause / Table 10.5.157 */
67struct value_string gsm_cause_names[] = {
68 { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" },
69 { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" },
70 { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
71 { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" },
72 { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" },
73 { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" },
74 { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" },
75 { GSM_CAUSE_REQ_SERV_OPT_NOTSUB,
76 "Requested service option not subscribed" },
77 { GSM_CAUSE_SERV_OPT_TEMP_OOO,
78 "Service option temporarily out of order" },
79 { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" },
80 { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" },
81 { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" },
82 { GSM_CAUSE_NET_FAIL, "Network Failure" },
83 { GSM_CAUSE_REACT_RQD, "Reactivation required" },
84 { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " },
85 { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" },
86 { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
87 { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
88 { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
89 "Message type non-existant or not implemented" },
90 { GSM_CAUSE_MSGT_INCOMP_P_STATE,
91 "Message type not compatible with protocol state" },
92 { GSM_CAUSE_IE_NOTEXIST_NOTIMPL,
93 "Information element non-existent or not implemented" },
94 { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" },
95 { GSM_CAUSE_MSG_INCOMP_P_STATE,
96 "Message not compatible with protocol state " },
97 { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
98 { 0, NULL }
99};
100
Harald Welteeaa614c2010-05-02 11:26:34 +0200101static const char *att_name(uint8_t type)
Harald Welte9b455bf2010-03-14 15:45:01 +0800102{
103 switch (type) {
104 case GPRS_ATT_T_ATTACH:
105 return "GPRS attach";
106 case GPRS_ATT_T_ATT_WHILE_IMSI:
107 return "GPRS attach while IMSI attached";
108 case GPRS_ATT_T_COMBINED:
109 return "Combined GPRS/IMSI attach";
110 default:
111 return "unknown";
112 }
113}
114
Harald Welteeaa614c2010-05-02 11:26:34 +0200115static const char *upd_name(uint8_t type)
Harald Welte9b455bf2010-03-14 15:45:01 +0800116{
117 switch (type) {
118 case GPRS_UPD_T_RA:
119 return "RA updating";
120 case GPRS_UPD_T_RA_LA:
121 return "combined RA/LA updating";
122 case GPRS_UPD_T_RA_LA_IMSI_ATT:
123 return "combined RA/LA updating + IMSI attach";
124 case GPRS_UPD_T_PERIODIC:
125 return "periodic updating";
126 }
127 return "unknown";
128}
129
Harald Welte9b455bf2010-03-14 15:45:01 +0800130/* Send a message through the underlying layer */
131static int gsm48_gmm_sendmsg(struct msgb *msg, int command)
132{
133 return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command);
134}
135
Harald Welte9b455bf2010-03-14 15:45:01 +0800136/* Chapter 9.4.2: Attach accept */
137static int gsm48_tx_gmm_att_ack(struct msgb *old_msg)
138{
139 struct msgb *msg = gsm48_msgb_alloc();
140 struct gsm48_hdr *gh;
141 struct gsm48_attach_ack *aa;
142
143 DEBUGP(DMM, "<- GPRS ATTACH ACCEPT\n");
144
Harald Welte943c5bc2010-04-30 16:33:12 +0200145 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800146 msg->trx = old_msg->trx;
147
148 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
149 gh->proto_discr = GSM48_PDISC_MM_GPRS;
150 gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
151
152 aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
153 aa->force_stby = 0; /* not indicated */
154 aa->att_result = 1; /* GPRS only */
155 aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
156 aa->radio_prio = 4; /* lowest */
Harald Welte288be162010-05-01 16:48:27 +0200157 //FIXME gsm48_ra_id_by_bts(aa->ra_id.digits, old_msg->trx->bts);
Harald Welte9b455bf2010-03-14 15:45:01 +0800158
159 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
160 return gsm48_gmm_sendmsg(msg, 0);
161}
162
163/* Chapter 9.4.5: Attach reject */
Harald Welteeaa614c2010-05-02 11:26:34 +0200164static int gsm48_tx_gmm_att_rej(struct msgb *old_msg, uint8_t gmm_cause)
Harald Welte9b455bf2010-03-14 15:45:01 +0800165{
166 struct msgb *msg = gsm48_msgb_alloc();
167 struct gsm48_hdr *gh;
168
169 DEBUGP(DMM, "<- GPRS ATTACH REJECT\n");
170
Harald Welte943c5bc2010-04-30 16:33:12 +0200171 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800172 msg->trx = old_msg->trx;
173
174 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
175 gh->proto_discr = GSM48_PDISC_MM_GPRS;
176 gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
177 gh->data[0] = gmm_cause;
178
179 return gsm48_gmm_sendmsg(msg, 0);
180}
181
182/* Transmit Chapter 9.4.12 Identity Request */
Harald Welteeaa614c2010-05-02 11:26:34 +0200183static int gsm48_tx_gmm_id_req(struct msgb *old_msg, uint8_t id_type)
Harald Welte9b455bf2010-03-14 15:45:01 +0800184{
185 struct msgb *msg = gsm48_msgb_alloc();
186 struct gsm48_hdr *gh;
187
188 DEBUGP(DMM, "-> GPRS IDENTITY REQUEST: mi_type=%02x\n", id_type);
189
Harald Welte943c5bc2010-04-30 16:33:12 +0200190 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800191 msg->trx = old_msg->trx;
192
193 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
194 gh->proto_discr = GSM48_PDISC_MM_GPRS;
195 gh->msg_type = GSM48_MT_GMM_ID_REQ;
196 /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
197 gh->data[0] = id_type & 0xf;
198
199 return gsm48_gmm_sendmsg(msg, 0);
200}
201
202/* Check if we can already authorize a subscriber */
203static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx, struct msgb *msg)
204{
205 if (strlen(ctx->imei) && strlen(ctx->imsi)) {
206 ctx->mm_state = GMM_REGISTERED_NORMAL;
207 return gsm48_tx_gmm_att_ack(msg);
208 }
209 if (!strlen(ctx->imei))
210 return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMEI);
211
212 if (!strlen(ctx->imsi))
213 return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMSI);
214
215 return 0;
216}
217
218/* Parse Chapter 9.4.13 Identity Response */
219static int gsm48_rx_gmm_id_resp(struct msgb *msg)
220{
Harald Welte943c5bc2010-04-30 16:33:12 +0200221 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welteeaa614c2010-05-02 11:26:34 +0200222 uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
Harald Welte9b455bf2010-03-14 15:45:01 +0800223 char mi_string[GSM48_MI_SIZE];
224 struct gprs_ra_id ra_id;
225 struct sgsn_mm_ctx *ctx;
226
227 gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
228 DEBUGP(DMM, "GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ",
229 mi_type, mi_string);
230
Harald Welte288be162010-05-01 16:48:27 +0200231 //FIXME gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
Harald Welte943c5bc2010-04-30 16:33:12 +0200232 ctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
Harald Welte9b455bf2010-03-14 15:45:01 +0800233 if (!ctx) {
Harald Welte943c5bc2010-04-30 16:33:12 +0200234 DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msgb_tlli(msg));
Harald Welte9b455bf2010-03-14 15:45:01 +0800235 return -EINVAL;
236 }
237
238 switch (mi_type) {
239 case GSM_MI_TYPE_IMSI:
240 /* we already have a mm context with current TLLI, but no
241 * P-TMSI / IMSI yet. What we now need to do is to fill
242 * this initial context with data from the HLR */
243 strncpy(ctx->imsi, mi_string, sizeof(ctx->imei));
244 break;
245 case GSM_MI_TYPE_IMEI:
246 strncpy(ctx->imei, mi_string, sizeof(ctx->imei));
247 break;
248 case GSM_MI_TYPE_IMEISV:
249 break;
250 }
251
252 DEBUGPC(DMM, "\n");
253 /* Check if we can let the mobile station enter */
254 return gsm48_gmm_authorize(ctx, msg);
255}
256
257static void attach_rej_cb(void *data)
258{
259 struct sgsn_mm_ctx *ctx = data;
260
261 /* FIXME: determine through which BTS/TRX to send this */
262 //gsm48_tx_gmm_att_rej(ctx->tlli, GMM_CAUSE_MS_ID_NOT_DERIVED);
263 ctx->mm_state = GMM_DEREGISTERED;
264 /* FIXME: release the context */
265}
266
267static void schedule_reject(struct sgsn_mm_ctx *ctx)
268{
269 ctx->T = 3370;
270 ctx->timer.cb = attach_rej_cb;
271 ctx->timer.data = ctx;
272 bsc_schedule_timer(&ctx->timer, 6, 0);
273}
274
275/* Section 9.4.1 Attach request */
276static int gsm48_rx_gmm_att_req(struct msgb *msg)
277{
Harald Welte943c5bc2010-04-30 16:33:12 +0200278 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welteeaa614c2010-05-02 11:26:34 +0200279 uint8_t *cur = gh->data, *msnc, *mi, *old_ra_info;
280 uint8_t msnc_len, att_type, mi_len, mi_type;
281 uint16_t drx_par;
282 uint32_t tmsi;
Harald Welte9b455bf2010-03-14 15:45:01 +0800283 char mi_string[GSM48_MI_SIZE];
284 struct gprs_ra_id ra_id;
285 struct sgsn_mm_ctx *ctx;
286
287 DEBUGP(DMM, "GMM ATTACH REQUEST ");
288
289 /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
290 * with a foreign TLLI (P-TMSI that was allocated to the MS before),
291 * or with random TLLI. */
292
Harald Welte288be162010-05-01 16:48:27 +0200293 //FIXME gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
Harald Welte9b455bf2010-03-14 15:45:01 +0800294
295 /* MS network capability 10.5.5.12 */
296 msnc_len = *cur++;
297 msnc = cur;
298 if (msnc_len > 2)
299 goto err_inval;
300 cur += msnc_len;
301
302 /* aTTACH Type 10.5.5.2 */
303 att_type = *cur++ & 0x0f;
304
305 /* DRX parameter 10.5.5.6 */
306 drx_par = *cur++;
307 drx_par |= *cur++ << 8;
308
309 /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
310 mi_len = *cur++;
311 mi = cur;
312 if (mi_len > 8)
313 goto err_inval;
314 mi_type = *mi & GSM_MI_TYPE_MASK;
315 cur += mi_len;
316
317 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
318
319 DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string, att_name(att_type));
320
321 /* Old routing area identification 10.5.5.15 */
322 old_ra_info = cur;
323 cur += 6;
324
325 /* MS Radio Access Capability 10.5.5.12a */
326
327 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
328
329 switch (mi_type) {
330 case GSM_MI_TYPE_IMSI:
331 /* Try to find MM context based on IMSI */
332 ctx = sgsn_mm_ctx_by_imsi(mi_string);
333 if (!ctx) {
334#if 0
335 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
336#else
337 /* As a temorary hack, we simply assume that the IMSI exists */
338 ctx = sgsn_mm_ctx_alloc(0, &ra_id);
339 if (!ctx)
340 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_NET_FAIL);
341 strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
342#endif
343 }
344 /* FIXME: Start some timer */
345 ctx->mm_state = GMM_COMMON_PROC_INIT;
Harald Welte943c5bc2010-04-30 16:33:12 +0200346 ctx->tlli = msgb_tlli(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800347 break;
348 case GSM_MI_TYPE_TMSI:
349 tmsi = strtoul(mi_string, NULL, 10);
350 /* Try to find MM context based on P-TMSI */
351 ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
352 if (!ctx) {
Harald Welte943c5bc2010-04-30 16:33:12 +0200353 ctx = sgsn_mm_ctx_alloc(msgb_tlli(msg), &ra_id);
Harald Welte9b455bf2010-03-14 15:45:01 +0800354 /* FIXME: Start some timer */
355 ctx->mm_state = GMM_COMMON_PROC_INIT;
Harald Welte943c5bc2010-04-30 16:33:12 +0200356 ctx->tlli = msgb_tlli(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800357 }
358 break;
359 default:
360 break;
361 }
362
363 /* FIXME: allocate a new P-TMSI (+ P-TMSI signature) */
364 /* FIXME: update the TLLI with the new local TLLI based on the P-TMSI */
365
366 DEBUGPC(DMM, "\n");
367
368 return ctx ? gsm48_gmm_authorize(ctx, msg) : 0;
369
370err_inval:
371 DEBUGPC(DMM, "\n");
372 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_SEM_INCORR_MSG);
373}
374
375/* Chapter 9.4.15: Routing area update accept */
376static int gsm48_tx_gmm_ra_upd_ack(struct msgb *old_msg)
377{
378 struct msgb *msg = gsm48_msgb_alloc();
379 struct gsm48_hdr *gh;
380 struct gsm48_ra_upd_ack *rua;
381
382 DEBUGP(DMM, "<- ROUTING AREA UPDATE ACCEPT\n");
383
Harald Welte943c5bc2010-04-30 16:33:12 +0200384 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800385 msg->trx = old_msg->trx;
386
387 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
388 gh->proto_discr = GSM48_PDISC_MM_GPRS;
389 gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
390
391 rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
392 rua->force_stby = 0; /* not indicated */
393 rua->upd_result = 0; /* RA updated */
394 rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
Harald Welte288be162010-05-01 16:48:27 +0200395 //FIXME gsm48_ra_id_by_bts(rua->ra_id.digits, old_msg->trx->bts);
Harald Welte9b455bf2010-03-14 15:45:01 +0800396
397 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
398 return gsm48_gmm_sendmsg(msg, 0);
399}
400
401/* Chapter 9.4.17: Routing area update reject */
Harald Welteeaa614c2010-05-02 11:26:34 +0200402static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
Harald Welte9b455bf2010-03-14 15:45:01 +0800403{
404 struct msgb *msg = gsm48_msgb_alloc();
405 struct gsm48_hdr *gh;
406
407 DEBUGP(DMM, "<- ROUTING AREA UPDATE REJECT\n");
408
Harald Welte943c5bc2010-04-30 16:33:12 +0200409 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800410 msg->trx = old_msg->trx;
411
412 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
413 gh->proto_discr = GSM48_PDISC_MM_GPRS;
414 gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
415 gh->data[0] = cause;
416 gh->data[1] = 0; /* ? */
417
418 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
419 return gsm48_gmm_sendmsg(msg, 0);
420}
421
422/* Chapter 9.4.14: Routing area update request */
423static int gsm48_rx_gmm_ra_upd_req(struct msgb *msg)
424{
Harald Welte943c5bc2010-04-30 16:33:12 +0200425 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800426 struct sgsn_mm_ctx *mmctx;
Harald Welteeaa614c2010-05-02 11:26:34 +0200427 uint8_t *cur = gh->data;
Harald Welte9b455bf2010-03-14 15:45:01 +0800428 struct gprs_ra_id old_ra_id;
Harald Welteeaa614c2010-05-02 11:26:34 +0200429 uint8_t upd_type;
Harald Welte9b455bf2010-03-14 15:45:01 +0800430
431 /* Update Type 10.5.5.18 */
432 upd_type = *cur++ & 0x0f;
433
434 DEBUGP(DMM, "GMM RA UPDATE REQUEST type=\"%s\" ", upd_name(upd_type));
435
436 /* Old routing area identification 10.5.5.15 */
437 gsm48_parse_ra(&old_ra_id, cur);
438 cur += 6;
439
440 /* MS Radio Access Capability 10.5.5.12a */
441
442 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
443 * DRX parameter, MS network capability */
444
445 switch (upd_type) {
446 case GPRS_UPD_T_RA_LA:
447 case GPRS_UPD_T_RA_LA_IMSI_ATT:
448 DEBUGPC(DMM, " unsupported in Mode III, is your SI13 corrupt?\n");
449 return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
450 break;
451 case GPRS_UPD_T_RA:
452 case GPRS_UPD_T_PERIODIC:
453 break;
454 }
455
456 /* Look-up the MM context based on old RA-ID and TLLI */
Harald Welte943c5bc2010-04-30 16:33:12 +0200457 mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &old_ra_id);
Harald Welte9b455bf2010-03-14 15:45:01 +0800458 if (!mmctx || mmctx->mm_state == GMM_DEREGISTERED) {
459 /* The MS has to perform GPRS attach */
460 DEBUGPC(DMM, " REJECT\n");
461 return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_IMPL_DETACHED);
462 }
463
464 /* FIXME: Update the MM context with the new RA-ID */
465 /* FIXME: Update the MM context with the new TLLI */
466 /* FIXME: Update the MM context with the MS radio acc capabilities */
467 /* FIXME: Update the MM context with the MS network capabilities */
468
469 DEBUGPC(DMM, " ACCEPT\n");
470 return gsm48_tx_gmm_ra_upd_ack(msg);
471}
472
473static int gsm48_rx_gmm_status(struct msgb *msg)
474{
475 struct gsm48_hdr *gh = msgb_l3(msg);
476
477 DEBUGP(DMM, "GPRS MM STATUS (cause: %s)\n",
478 get_value_string(gmm_cause_names, gh->data[0]));
479
480 return 0;
481}
482
483/* GPRS Mobility Management */
484static int gsm0408_rcv_gmm(struct msgb *msg)
485{
Harald Welte943c5bc2010-04-30 16:33:12 +0200486 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800487 int rc;
488
489 switch (gh->msg_type) {
490 case GSM48_MT_GMM_RA_UPD_REQ:
491 rc = gsm48_rx_gmm_ra_upd_req(msg);
492 break;
493 case GSM48_MT_GMM_ATTACH_REQ:
494 rc = gsm48_rx_gmm_att_req(msg);
495 break;
496 case GSM48_MT_GMM_ID_RESP:
497 rc = gsm48_rx_gmm_id_resp(msg);
498 break;
499 case GSM48_MT_GMM_STATUS:
500 rc = gsm48_rx_gmm_status(msg);
501 break;
502 case GSM48_MT_GMM_RA_UPD_COMPL:
503 /* only in case SGSN offered new P-TMSI */
504 case GSM48_MT_GMM_ATTACH_COMPL:
505 /* only in case SGSN offered new P-TMSI */
506 case GSM48_MT_GMM_DETACH_REQ:
507 case GSM48_MT_GMM_PTMSI_REALL_COMPL:
508 case GSM48_MT_GMM_AUTH_CIPH_RESP:
509 DEBUGP(DMM, "Unimplemented GSM 04.08 GMM msg type 0x%02x\n",
510 gh->msg_type);
511 break;
512 default:
513 DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
514 gh->msg_type);
515 break;
516 }
517
518 return rc;
519}
520
521/* Section 9.5.2: Ativate PDP Context Accept */
522static int gsm48_tx_gsm_act_pdp_acc(struct msgb *old_msg, struct gsm48_act_pdp_ctx_req *req)
523{
Harald Welte943c5bc2010-04-30 16:33:12 +0200524 struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800525 struct msgb *msg = gsm48_msgb_alloc();
526 struct gsm48_act_pdp_ctx_ack *act_ack;
527 struct gsm48_hdr *gh;
Harald Welteeaa614c2010-05-02 11:26:34 +0200528 uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
Harald Welte9b455bf2010-03-14 15:45:01 +0800529
530 DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT ACK\n");
531
Harald Welte943c5bc2010-04-30 16:33:12 +0200532 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800533 msg->trx = old_msg->trx;
534
535 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
536 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
537 gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
538 act_ack = (struct gsm48_act_pdp_ctx_ack *)
539 msgb_put(msg, sizeof(*act_ack));
540 act_ack->llc_sapi = req->req_llc_sapi;
541 memcpy(act_ack->qos_lv, req->req_qos_lv, sizeof(act_ack->qos_lv));
542 //act_ack->radio_prio = 4;
543
544 return gsm48_gmm_sendmsg(msg, 0);
545}
546
547/* Section 9.5.9: Deactivate PDP Context Accept */
548static int gsm48_tx_gsm_deact_pdp_acc(struct msgb *old_msg)
549{
Harald Welte943c5bc2010-04-30 16:33:12 +0200550 struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800551 struct msgb *msg = gsm48_msgb_alloc();
552 struct gsm48_hdr *gh;
Harald Welteeaa614c2010-05-02 11:26:34 +0200553 uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
Harald Welte9b455bf2010-03-14 15:45:01 +0800554
555 DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n");
556
Harald Welte943c5bc2010-04-30 16:33:12 +0200557 msgb_tlli(msg) = msgb_tlli(old_msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800558 msg->trx = old_msg->trx;
559
560 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
561 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
562 gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
563
564 return gsm48_gmm_sendmsg(msg, 0);
565}
566
567/* Section 9.5.1: Activate PDP Context Request */
568static int gsm48_rx_gsm_act_pdp_req(struct msgb *msg)
569{
Harald Welte943c5bc2010-04-30 16:33:12 +0200570 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800571 struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
Harald Welteeaa614c2010-05-02 11:26:34 +0200572 uint8_t *pdp_addr_lv = act_req->data;
Harald Welte9b455bf2010-03-14 15:45:01 +0800573
574 DEBUGP(DMM, "ACTIVATE PDP CONTEXT REQ\n");
575
576 /* FIXME: parse access point name + IPCP config options */
577
578 return gsm48_tx_gsm_act_pdp_acc(msg, act_req);
579}
580
581/* Section 9.5.8: Deactivate PDP Context Request */
582static int gsm48_rx_gsm_deact_pdp_req(struct msgb *msg)
583{
Harald Welte943c5bc2010-04-30 16:33:12 +0200584 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800585
586 DEBUGP(DMM, "DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
587 get_value_string(gsm_cause_names, gh->data[0]));
588
589 return gsm48_tx_gsm_deact_pdp_acc(msg);
590}
591
592static int gsm48_rx_gsm_status(struct msgb *msg)
593{
594 struct gsm48_hdr *gh = msgb_l3(msg);
595
596 DEBUGP(DMM, "GPRS SM STATUS (cause: %s)\n",
597 get_value_string(gsm_cause_names, gh->data[0]));
598
599 return 0;
600}
601
602/* GPRS Session Management */
603static int gsm0408_rcv_gsm(struct msgb *msg)
604{
Harald Welte943c5bc2010-04-30 16:33:12 +0200605 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte9b455bf2010-03-14 15:45:01 +0800606 int rc;
607
608 switch (gh->msg_type) {
609 case GSM48_MT_GSM_ACT_PDP_REQ:
610 rc = gsm48_rx_gsm_act_pdp_req(msg);
611 break;
612 case GSM48_MT_GSM_DEACT_PDP_REQ:
613 rc = gsm48_rx_gsm_deact_pdp_req(msg);
614 case GSM48_MT_GSM_STATUS:
615 rc = gsm48_rx_gsm_status(msg);
616 break;
617 case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
618 case GSM48_MT_GSM_ACT_AA_PDP_REQ:
619 case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
620 DEBUGP(DMM, "Unimplemented GSM 04.08 GSM msg type 0x%02x\n",
621 gh->msg_type);
622 break;
623 default:
624 DEBUGP(DMM, "Unknown GSM 04.08 GSM msg type 0x%02x\n",
625 gh->msg_type);
626 break;
627
628 }
629
630 return rc;
631}
632
633/* Main entry point for incoming 04.08 GPRS messages */
634int gsm0408_gprs_rcvmsg(struct msgb *msg)
635{
Harald Welte943c5bc2010-04-30 16:33:12 +0200636 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welteeaa614c2010-05-02 11:26:34 +0200637 uint8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte9b455bf2010-03-14 15:45:01 +0800638 int rc = -EINVAL;
639
640 switch (pdisc) {
641 case GSM48_PDISC_MM_GPRS:
642 rc = gsm0408_rcv_gmm(msg);
643 break;
644 case GSM48_PDISC_SM_GPRS:
645 rc = gsm0408_rcv_gsm(msg);
646 break;
647 default:
648 DEBUGP(DMM, "Unknown GSM 04.08 discriminator 0x%02x\n",
649 pdisc);
650 break;
651 }
652
653 return rc;
654}
655
656/* Determine the 'struct gsm_bts' from a RA ID */
657struct gsm_bts *gsm48_bts_by_ra_id(struct gsm_network *net,
Harald Welteeaa614c2010-05-02 11:26:34 +0200658 const uint8_t *buf, unsigned int len)
Harald Welte9b455bf2010-03-14 15:45:01 +0800659{
660 struct gprs_ra_id raid;
661 struct gsm_bts *bts;
662
663 if (len < 6)
664 return NULL;
665
666 gsm48_parse_ra(&raid, buf);
667
668 if (net->country_code != raid.mcc ||
669 net->network_code != raid.mnc)
670 return NULL;
671
672 llist_for_each_entry(bts, &net->bts_list, list) {
673 /* FIXME: we actually also need to check the
674 * routing area code! */
675 if (bts->location_area_code == raid.lac)
676 return bts;
677 }
678
679 return NULL;
680}
681