blob: af6a481cb91355517b563de9c420d9cb39f42fe7 [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>
27#include <errno.h>
28
29#include <netinet/in.h>
30
31#include <openbsc/db.h>
32#include <osmocore/msgb.h>
33#include <osmocore/tlv.h>
34#include <openbsc/debug.h>
35#include <openbsc/gsm_data.h>
36#include <osmocore/gsm_utils.h>
37#include <openbsc/gsm_subscriber.h>
38#include <openbsc/gsm_04_08.h>
39#include <openbsc/gsm_04_08_gprs.h>
40#include <openbsc/paging.h>
41#include <osmocore/signal.h>
42#include <osmocore/talloc.h>
43#include <openbsc/transaction.h>
44#include <openbsc/gprs_llc.h>
45#include <openbsc/gprs_sgsn.h>
46
47/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */
48struct value_string gmm_cause_names[] = {
49 /* FIXME */
50 { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
51 { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
52 { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
53 "Message type non-existant or not implemented" },
54 { GMM_CAUSE_MSGT_INCOMP_P_STATE,
55 "Message type not compatible with protocol state" },
56 { GMM_CAUSE_IE_NOTEXIST_NOTIMPL,
57 "Information element non-existent or not implemented" },
58 { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" },
59 { GMM_CAUSE_MSG_INCOMP_P_STATE,
60 "Message not compatible with protocol state " },
61 { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
62 { 0, NULL }
63};
64
65/* 10.5.6.6 SM Cause / Table 10.5.157 */
66struct value_string gsm_cause_names[] = {
67 { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" },
68 { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" },
69 { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
70 { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" },
71 { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" },
72 { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" },
73 { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" },
74 { GSM_CAUSE_REQ_SERV_OPT_NOTSUB,
75 "Requested service option not subscribed" },
76 { GSM_CAUSE_SERV_OPT_TEMP_OOO,
77 "Service option temporarily out of order" },
78 { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" },
79 { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" },
80 { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" },
81 { GSM_CAUSE_NET_FAIL, "Network Failure" },
82 { GSM_CAUSE_REACT_RQD, "Reactivation required" },
83 { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " },
84 { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" },
85 { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
86 { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
87 { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
88 "Message type non-existant or not implemented" },
89 { GSM_CAUSE_MSGT_INCOMP_P_STATE,
90 "Message type not compatible with protocol state" },
91 { GSM_CAUSE_IE_NOTEXIST_NOTIMPL,
92 "Information element non-existent or not implemented" },
93 { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" },
94 { GSM_CAUSE_MSG_INCOMP_P_STATE,
95 "Message not compatible with protocol state " },
96 { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
97 { 0, NULL }
98};
99
100static const char *att_name(u_int8_t type)
101{
102 switch (type) {
103 case GPRS_ATT_T_ATTACH:
104 return "GPRS attach";
105 case GPRS_ATT_T_ATT_WHILE_IMSI:
106 return "GPRS attach while IMSI attached";
107 case GPRS_ATT_T_COMBINED:
108 return "Combined GPRS/IMSI attach";
109 default:
110 return "unknown";
111 }
112}
113
114static const char *upd_name(u_int8_t type)
115{
116 switch (type) {
117 case GPRS_UPD_T_RA:
118 return "RA updating";
119 case GPRS_UPD_T_RA_LA:
120 return "combined RA/LA updating";
121 case GPRS_UPD_T_RA_LA_IMSI_ATT:
122 return "combined RA/LA updating + IMSI attach";
123 case GPRS_UPD_T_PERIODIC:
124 return "periodic updating";
125 }
126 return "unknown";
127}
128
129void gsm48_parse_ra(struct gprs_ra_id *raid, const u_int8_t *buf)
130{
131 raid->mcc = (buf[0] & 0xf) * 100;
132 raid->mcc += (buf[0] >> 4) * 10;
133 raid->mcc += (buf[1] & 0xf) * 1;
134
135 /* I wonder who came up with the stupidity of encoding the MNC
136 * differently depending on how many digits its decimal number has! */
137 if ((buf[1] >> 4) == 0xf) {
138 raid->mnc = (buf[2] & 0xf) * 10;
139 raid->mnc += (buf[2] >> 4) * 1;
140 } else {
141 raid->mnc = (buf[2] & 0xf) * 100;
142 raid->mnc += (buf[2] >> 4) * 10;
143 raid->mnc += (buf[1] >> 4) * 1;
144 }
145
146 raid->lac = ntohs(*(u_int16_t *)(buf + 3));
147 raid->rac = buf[5];
148}
149
150/* Send a message through the underlying layer */
151static int gsm48_gmm_sendmsg(struct msgb *msg, int command)
152{
153 return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command);
154}
155
156/* TS 03.03 Chapter 2.6 */
157int gprs_tlli_type(u_int32_t tlli)
158{
159 if ((tlli & 0xc0000000) == 0xc0000000)
160 return TLLI_LOCAL;
161 else if ((tlli & 0xc0000000) == 0x80000000)
162 return TLLI_FOREIGN;
163 else if ((tlli & 0xf8000000) == 0x78000000)
164 return TLLI_RANDOM;
165 else if ((tlli & 0xf8000000) == 0x70000000)
166 return TLLI_AUXILIARY;
167
168 return TLLI_RESERVED;
169}
170
171/* Chapter 9.4.2: Attach accept */
172static int gsm48_tx_gmm_att_ack(struct msgb *old_msg)
173{
174 struct msgb *msg = gsm48_msgb_alloc();
175 struct gsm48_hdr *gh;
176 struct gsm48_attach_ack *aa;
177
178 DEBUGP(DMM, "<- GPRS ATTACH ACCEPT\n");
179
180 msg->tlli = old_msg->tlli;
181 msg->trx = old_msg->trx;
182
183 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
184 gh->proto_discr = GSM48_PDISC_MM_GPRS;
185 gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
186
187 aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
188 aa->force_stby = 0; /* not indicated */
189 aa->att_result = 1; /* GPRS only */
190 aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
191 aa->radio_prio = 4; /* lowest */
192 gsm48_ra_id_by_bts(aa->ra_id.digits, old_msg->trx->bts);
193
194 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
195 return gsm48_gmm_sendmsg(msg, 0);
196}
197
198/* Chapter 9.4.5: Attach reject */
199static int gsm48_tx_gmm_att_rej(struct msgb *old_msg, u_int8_t gmm_cause)
200{
201 struct msgb *msg = gsm48_msgb_alloc();
202 struct gsm48_hdr *gh;
203
204 DEBUGP(DMM, "<- GPRS ATTACH REJECT\n");
205
206 msg->tlli = old_msg->tlli;
207 msg->trx = old_msg->trx;
208
209 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
210 gh->proto_discr = GSM48_PDISC_MM_GPRS;
211 gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
212 gh->data[0] = gmm_cause;
213
214 return gsm48_gmm_sendmsg(msg, 0);
215}
216
217/* Transmit Chapter 9.4.12 Identity Request */
218static int gsm48_tx_gmm_id_req(struct msgb *old_msg, u_int8_t id_type)
219{
220 struct msgb *msg = gsm48_msgb_alloc();
221 struct gsm48_hdr *gh;
222
223 DEBUGP(DMM, "-> GPRS IDENTITY REQUEST: mi_type=%02x\n", id_type);
224
225 msg->tlli = old_msg->tlli;
226 msg->trx = old_msg->trx;
227
228 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
229 gh->proto_discr = GSM48_PDISC_MM_GPRS;
230 gh->msg_type = GSM48_MT_GMM_ID_REQ;
231 /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
232 gh->data[0] = id_type & 0xf;
233
234 return gsm48_gmm_sendmsg(msg, 0);
235}
236
237/* Check if we can already authorize a subscriber */
238static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx, struct msgb *msg)
239{
240 if (strlen(ctx->imei) && strlen(ctx->imsi)) {
241 ctx->mm_state = GMM_REGISTERED_NORMAL;
242 return gsm48_tx_gmm_att_ack(msg);
243 }
244 if (!strlen(ctx->imei))
245 return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMEI);
246
247 if (!strlen(ctx->imsi))
248 return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMSI);
249
250 return 0;
251}
252
253/* Parse Chapter 9.4.13 Identity Response */
254static int gsm48_rx_gmm_id_resp(struct msgb *msg)
255{
256 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
257 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
258 char mi_string[GSM48_MI_SIZE];
259 struct gprs_ra_id ra_id;
260 struct sgsn_mm_ctx *ctx;
261
262 gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
263 DEBUGP(DMM, "GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ",
264 mi_type, mi_string);
265
266 gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
267 ctx = sgsn_mm_ctx_by_tlli(msg->tlli, &ra_id);
268 if (!ctx) {
269 DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msg->tlli);
270 return -EINVAL;
271 }
272
273 switch (mi_type) {
274 case GSM_MI_TYPE_IMSI:
275 /* we already have a mm context with current TLLI, but no
276 * P-TMSI / IMSI yet. What we now need to do is to fill
277 * this initial context with data from the HLR */
278 strncpy(ctx->imsi, mi_string, sizeof(ctx->imei));
279 break;
280 case GSM_MI_TYPE_IMEI:
281 strncpy(ctx->imei, mi_string, sizeof(ctx->imei));
282 break;
283 case GSM_MI_TYPE_IMEISV:
284 break;
285 }
286
287 DEBUGPC(DMM, "\n");
288 /* Check if we can let the mobile station enter */
289 return gsm48_gmm_authorize(ctx, msg);
290}
291
292static void attach_rej_cb(void *data)
293{
294 struct sgsn_mm_ctx *ctx = data;
295
296 /* FIXME: determine through which BTS/TRX to send this */
297 //gsm48_tx_gmm_att_rej(ctx->tlli, GMM_CAUSE_MS_ID_NOT_DERIVED);
298 ctx->mm_state = GMM_DEREGISTERED;
299 /* FIXME: release the context */
300}
301
302static void schedule_reject(struct sgsn_mm_ctx *ctx)
303{
304 ctx->T = 3370;
305 ctx->timer.cb = attach_rej_cb;
306 ctx->timer.data = ctx;
307 bsc_schedule_timer(&ctx->timer, 6, 0);
308}
309
310/* Section 9.4.1 Attach request */
311static int gsm48_rx_gmm_att_req(struct msgb *msg)
312{
313 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
314 u_int8_t *cur = gh->data, *msnc, *mi, *old_ra_info;
315 u_int8_t msnc_len, att_type, mi_len, mi_type;
316 u_int16_t drx_par;
317 u_int32_t tmsi;
318 char mi_string[GSM48_MI_SIZE];
319 struct gprs_ra_id ra_id;
320 struct sgsn_mm_ctx *ctx;
321
322 DEBUGP(DMM, "GMM ATTACH REQUEST ");
323
324 /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
325 * with a foreign TLLI (P-TMSI that was allocated to the MS before),
326 * or with random TLLI. */
327
328 gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
329
330 /* MS network capability 10.5.5.12 */
331 msnc_len = *cur++;
332 msnc = cur;
333 if (msnc_len > 2)
334 goto err_inval;
335 cur += msnc_len;
336
337 /* aTTACH Type 10.5.5.2 */
338 att_type = *cur++ & 0x0f;
339
340 /* DRX parameter 10.5.5.6 */
341 drx_par = *cur++;
342 drx_par |= *cur++ << 8;
343
344 /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
345 mi_len = *cur++;
346 mi = cur;
347 if (mi_len > 8)
348 goto err_inval;
349 mi_type = *mi & GSM_MI_TYPE_MASK;
350 cur += mi_len;
351
352 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
353
354 DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string, att_name(att_type));
355
356 /* Old routing area identification 10.5.5.15 */
357 old_ra_info = cur;
358 cur += 6;
359
360 /* MS Radio Access Capability 10.5.5.12a */
361
362 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
363
364 switch (mi_type) {
365 case GSM_MI_TYPE_IMSI:
366 /* Try to find MM context based on IMSI */
367 ctx = sgsn_mm_ctx_by_imsi(mi_string);
368 if (!ctx) {
369#if 0
370 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
371#else
372 /* As a temorary hack, we simply assume that the IMSI exists */
373 ctx = sgsn_mm_ctx_alloc(0, &ra_id);
374 if (!ctx)
375 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_NET_FAIL);
376 strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
377#endif
378 }
379 /* FIXME: Start some timer */
380 ctx->mm_state = GMM_COMMON_PROC_INIT;
381 ctx->tlli = msg->tlli;
382 break;
383 case GSM_MI_TYPE_TMSI:
384 tmsi = strtoul(mi_string, NULL, 10);
385 /* Try to find MM context based on P-TMSI */
386 ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
387 if (!ctx) {
388 ctx = sgsn_mm_ctx_alloc(msg->tlli, &ra_id);
389 /* FIXME: Start some timer */
390 ctx->mm_state = GMM_COMMON_PROC_INIT;
391 ctx->tlli = msg->tlli;
392 }
393 break;
394 default:
395 break;
396 }
397
398 /* FIXME: allocate a new P-TMSI (+ P-TMSI signature) */
399 /* FIXME: update the TLLI with the new local TLLI based on the P-TMSI */
400
401 DEBUGPC(DMM, "\n");
402
403 return ctx ? gsm48_gmm_authorize(ctx, msg) : 0;
404
405err_inval:
406 DEBUGPC(DMM, "\n");
407 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_SEM_INCORR_MSG);
408}
409
410/* Chapter 9.4.15: Routing area update accept */
411static int gsm48_tx_gmm_ra_upd_ack(struct msgb *old_msg)
412{
413 struct msgb *msg = gsm48_msgb_alloc();
414 struct gsm48_hdr *gh;
415 struct gsm48_ra_upd_ack *rua;
416
417 DEBUGP(DMM, "<- ROUTING AREA UPDATE ACCEPT\n");
418
419 msg->tlli = old_msg->tlli;
420 msg->trx = old_msg->trx;
421
422 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
423 gh->proto_discr = GSM48_PDISC_MM_GPRS;
424 gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
425
426 rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
427 rua->force_stby = 0; /* not indicated */
428 rua->upd_result = 0; /* RA updated */
429 rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
430 gsm48_ra_id_by_bts(rua->ra_id.digits, old_msg->trx->bts);
431
432 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
433 return gsm48_gmm_sendmsg(msg, 0);
434}
435
436/* Chapter 9.4.17: Routing area update reject */
437static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, u_int8_t cause)
438{
439 struct msgb *msg = gsm48_msgb_alloc();
440 struct gsm48_hdr *gh;
441
442 DEBUGP(DMM, "<- ROUTING AREA UPDATE REJECT\n");
443
444 msg->tlli = old_msg->tlli;
445 msg->trx = old_msg->trx;
446
447 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
448 gh->proto_discr = GSM48_PDISC_MM_GPRS;
449 gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
450 gh->data[0] = cause;
451 gh->data[1] = 0; /* ? */
452
453 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
454 return gsm48_gmm_sendmsg(msg, 0);
455}
456
457/* Chapter 9.4.14: Routing area update request */
458static int gsm48_rx_gmm_ra_upd_req(struct msgb *msg)
459{
460 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
461 struct sgsn_mm_ctx *mmctx;
462 u_int8_t *cur = gh->data;
463 struct gprs_ra_id old_ra_id;
464 u_int8_t upd_type;
465
466 /* Update Type 10.5.5.18 */
467 upd_type = *cur++ & 0x0f;
468
469 DEBUGP(DMM, "GMM RA UPDATE REQUEST type=\"%s\" ", upd_name(upd_type));
470
471 /* Old routing area identification 10.5.5.15 */
472 gsm48_parse_ra(&old_ra_id, cur);
473 cur += 6;
474
475 /* MS Radio Access Capability 10.5.5.12a */
476
477 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
478 * DRX parameter, MS network capability */
479
480 switch (upd_type) {
481 case GPRS_UPD_T_RA_LA:
482 case GPRS_UPD_T_RA_LA_IMSI_ATT:
483 DEBUGPC(DMM, " unsupported in Mode III, is your SI13 corrupt?\n");
484 return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
485 break;
486 case GPRS_UPD_T_RA:
487 case GPRS_UPD_T_PERIODIC:
488 break;
489 }
490
491 /* Look-up the MM context based on old RA-ID and TLLI */
492 mmctx = sgsn_mm_ctx_by_tlli(msg->tlli, &old_ra_id);
493 if (!mmctx || mmctx->mm_state == GMM_DEREGISTERED) {
494 /* The MS has to perform GPRS attach */
495 DEBUGPC(DMM, " REJECT\n");
496 return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_IMPL_DETACHED);
497 }
498
499 /* FIXME: Update the MM context with the new RA-ID */
500 /* FIXME: Update the MM context with the new TLLI */
501 /* FIXME: Update the MM context with the MS radio acc capabilities */
502 /* FIXME: Update the MM context with the MS network capabilities */
503
504 DEBUGPC(DMM, " ACCEPT\n");
505 return gsm48_tx_gmm_ra_upd_ack(msg);
506}
507
508static int gsm48_rx_gmm_status(struct msgb *msg)
509{
510 struct gsm48_hdr *gh = msgb_l3(msg);
511
512 DEBUGP(DMM, "GPRS MM STATUS (cause: %s)\n",
513 get_value_string(gmm_cause_names, gh->data[0]));
514
515 return 0;
516}
517
518/* GPRS Mobility Management */
519static int gsm0408_rcv_gmm(struct msgb *msg)
520{
521 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
522 int rc;
523
524 switch (gh->msg_type) {
525 case GSM48_MT_GMM_RA_UPD_REQ:
526 rc = gsm48_rx_gmm_ra_upd_req(msg);
527 break;
528 case GSM48_MT_GMM_ATTACH_REQ:
529 rc = gsm48_rx_gmm_att_req(msg);
530 break;
531 case GSM48_MT_GMM_ID_RESP:
532 rc = gsm48_rx_gmm_id_resp(msg);
533 break;
534 case GSM48_MT_GMM_STATUS:
535 rc = gsm48_rx_gmm_status(msg);
536 break;
537 case GSM48_MT_GMM_RA_UPD_COMPL:
538 /* only in case SGSN offered new P-TMSI */
539 case GSM48_MT_GMM_ATTACH_COMPL:
540 /* only in case SGSN offered new P-TMSI */
541 case GSM48_MT_GMM_DETACH_REQ:
542 case GSM48_MT_GMM_PTMSI_REALL_COMPL:
543 case GSM48_MT_GMM_AUTH_CIPH_RESP:
544 DEBUGP(DMM, "Unimplemented GSM 04.08 GMM msg type 0x%02x\n",
545 gh->msg_type);
546 break;
547 default:
548 DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
549 gh->msg_type);
550 break;
551 }
552
553 return rc;
554}
555
556/* Section 9.5.2: Ativate PDP Context Accept */
557static int gsm48_tx_gsm_act_pdp_acc(struct msgb *old_msg, struct gsm48_act_pdp_ctx_req *req)
558{
559 struct gsm48_hdr *old_gh = (struct gsm48_hdr *) old_msg->gmmh;
560 struct msgb *msg = gsm48_msgb_alloc();
561 struct gsm48_act_pdp_ctx_ack *act_ack;
562 struct gsm48_hdr *gh;
563 u_int8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
564
565 DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT ACK\n");
566
567 msg->tlli = old_msg->tlli;
568 msg->trx = old_msg->trx;
569
570 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
571 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
572 gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
573 act_ack = (struct gsm48_act_pdp_ctx_ack *)
574 msgb_put(msg, sizeof(*act_ack));
575 act_ack->llc_sapi = req->req_llc_sapi;
576 memcpy(act_ack->qos_lv, req->req_qos_lv, sizeof(act_ack->qos_lv));
577 //act_ack->radio_prio = 4;
578
579 return gsm48_gmm_sendmsg(msg, 0);
580}
581
582/* Section 9.5.9: Deactivate PDP Context Accept */
583static int gsm48_tx_gsm_deact_pdp_acc(struct msgb *old_msg)
584{
585 struct gsm48_hdr *old_gh = (struct gsm48_hdr *) old_msg->gmmh;
586 struct msgb *msg = gsm48_msgb_alloc();
587 struct gsm48_hdr *gh;
588 u_int8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
589
590 DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n");
591
592 msg->tlli = old_msg->tlli;
593 msg->trx = old_msg->trx;
594
595 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
596 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
597 gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
598
599 return gsm48_gmm_sendmsg(msg, 0);
600}
601
602/* Section 9.5.1: Activate PDP Context Request */
603static int gsm48_rx_gsm_act_pdp_req(struct msgb *msg)
604{
605 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
606 struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
607 u_int8_t *pdp_addr_lv = act_req->data;
608
609 DEBUGP(DMM, "ACTIVATE PDP CONTEXT REQ\n");
610
611 /* FIXME: parse access point name + IPCP config options */
612
613 return gsm48_tx_gsm_act_pdp_acc(msg, act_req);
614}
615
616/* Section 9.5.8: Deactivate PDP Context Request */
617static int gsm48_rx_gsm_deact_pdp_req(struct msgb *msg)
618{
619 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
620
621 DEBUGP(DMM, "DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
622 get_value_string(gsm_cause_names, gh->data[0]));
623
624 return gsm48_tx_gsm_deact_pdp_acc(msg);
625}
626
627static int gsm48_rx_gsm_status(struct msgb *msg)
628{
629 struct gsm48_hdr *gh = msgb_l3(msg);
630
631 DEBUGP(DMM, "GPRS SM STATUS (cause: %s)\n",
632 get_value_string(gsm_cause_names, gh->data[0]));
633
634 return 0;
635}
636
637/* GPRS Session Management */
638static int gsm0408_rcv_gsm(struct msgb *msg)
639{
640 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
641 int rc;
642
643 switch (gh->msg_type) {
644 case GSM48_MT_GSM_ACT_PDP_REQ:
645 rc = gsm48_rx_gsm_act_pdp_req(msg);
646 break;
647 case GSM48_MT_GSM_DEACT_PDP_REQ:
648 rc = gsm48_rx_gsm_deact_pdp_req(msg);
649 case GSM48_MT_GSM_STATUS:
650 rc = gsm48_rx_gsm_status(msg);
651 break;
652 case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
653 case GSM48_MT_GSM_ACT_AA_PDP_REQ:
654 case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
655 DEBUGP(DMM, "Unimplemented GSM 04.08 GSM msg type 0x%02x\n",
656 gh->msg_type);
657 break;
658 default:
659 DEBUGP(DMM, "Unknown GSM 04.08 GSM msg type 0x%02x\n",
660 gh->msg_type);
661 break;
662
663 }
664
665 return rc;
666}
667
668/* Main entry point for incoming 04.08 GPRS messages */
669int gsm0408_gprs_rcvmsg(struct msgb *msg)
670{
671 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->gmmh;
672 u_int8_t pdisc = gh->proto_discr & 0x0f;
673 int rc = -EINVAL;
674
675 switch (pdisc) {
676 case GSM48_PDISC_MM_GPRS:
677 rc = gsm0408_rcv_gmm(msg);
678 break;
679 case GSM48_PDISC_SM_GPRS:
680 rc = gsm0408_rcv_gsm(msg);
681 break;
682 default:
683 DEBUGP(DMM, "Unknown GSM 04.08 discriminator 0x%02x\n",
684 pdisc);
685 break;
686 }
687
688 return rc;
689}
690
691/* Determine the 'struct gsm_bts' from a RA ID */
692struct gsm_bts *gsm48_bts_by_ra_id(struct gsm_network *net,
693 const u_int8_t *buf, unsigned int len)
694{
695 struct gprs_ra_id raid;
696 struct gsm_bts *bts;
697
698 if (len < 6)
699 return NULL;
700
701 gsm48_parse_ra(&raid, buf);
702
703 if (net->country_code != raid.mcc ||
704 net->network_code != raid.mnc)
705 return NULL;
706
707 llist_for_each_entry(bts, &net->bts_list, list) {
708 /* FIXME: we actually also need to check the
709 * routing area code! */
710 if (bts->location_area_code == raid.lac)
711 return bts;
712 }
713
714 return NULL;
715}
716