comparison src/g23m-gprs/llc/llc_rxf.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e78acac3d88 1:fa8dc04885d8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project :
4 | Modul :
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : This modul is part of the entity LLC and implements all
18 | procedures and functions as described in the
19 | SDL-documentation (RX-statemachine)
20 +-----------------------------------------------------------------------------
21 */
22
23 #ifndef LLC_RXF_C
24 #define LLC_RXF_C
25 #endif
26
27 #define ENTITY_LLC
28
29 /*==== INCLUDES =============================================================*/
30
31 #include <string.h> /* to get memcpy() */
32
33 #include "typedefs.h" /* to get Condat data types */
34 #include "vsi.h" /* to get a lot of macros */
35 #include "macdef.h"
36 #include "gprs.h"
37 #include "gsm.h" /* to get a lot of macros */
38 #include "cnf_llc.h" /* to get cnf-definitions */
39 #include "mon_llc.h" /* to get mon-definitions */
40 #include "prim.h" /* to get the definitions of used SAP and directions */
41 #include "llc.h" /* to get the global entity definitions */
42
43 #include "llc_rxf.h" /* to get local defines */
44 #include "llc_rxp.h" /* to get the function rx_cci_decipher_cnf */
45 #include "llc_f.h" /* to get global functions, e.g. llc_generate_input */
46 #ifndef TI_PS_OP_CIPH_DRIVER
47 #include "cci_fbsf.h" /* to get functional interface */
48 #endif
49 /*==== CONST ================================================================*/
50
51 /*==== LOCAL VARS ===========================================================*/
52
53 /*==== PRIVATE FUNCTIONS ====================================================*/
54 #ifndef CF_FAST_EXEC
55
56 GLOBAL UBYTE rx_get_desc_octet (T_desc_list *desc_list,
57 USHORT offset,
58 UBYTE *data_ptr);
59 #endif /* CF_FAST_EXEC */
60
61 /*==== PUBLIC FUNCTIONS =====================================================*/
62
63
64 /*
65 +------------------------------------------------------------------------------
66 | Function : rx_init
67 +------------------------------------------------------------------------------
68 | Description : This procedure initialises all necessary variables of
69 | receive_pdu.
70 |
71 | Parameters :
72 |
73 +------------------------------------------------------------------------------
74 */
75 #ifndef CF_FAST_EXEC
76
77 GLOBAL void rx_init (void)
78 {
79 TRACE_FUNCTION( "rx_init" );
80
81 /*
82 * Initialise service RX with state TLLI_UNASSIGNED.
83 */
84 INIT_STATE (RX, RX_TLLI_UNASSIGNED);
85
86 return;
87 } /* rx_init() */
88
89 #endif /* CF_FAST_EXEC */
90
91
92 /*
93 +------------------------------------------------------------------------------
94 | Function : rx_analyse_ctrl_field
95 +------------------------------------------------------------------------------
96 | Description : This procedure analyses the received LLC frame control field
97 | and sets frame_type according to the frame type (U, UI, I/S).
98 | protected_mode is set according to the protected mode of the
99 | frame (U and I/S always protected, UI depends on setting of
100 | PM bit). The type of protected_mode is the same as in
101 | CCI_DECIPHER_REQ. ns is set to N(S) for I frames, N(U) for
102 | UI frames, or an undefined value for S and U frames. ciphering
103 | is set to TRUE if the frame is ciphered (U never, I/S always,
104 | UI depends on setting of E bit), otherwise to FALSE. frame_ok
105 | indicates if the frame contains enough octets to contain a
106 | known control field (i.e. all necessary information is
107 | accessible, not the control field is complete!).
108 |
109 | Parameters : grlc_unitdata_ind - a valid pointer to a GRLC_UNITDATA_IND
110 | primitive
111 | frame_type - a valid pointer to a T_PDU_TYPE variable
112 | protected_mode - a valid pointer to a UBYTE variable
113 | sapi - a valid pointer to a UBYTE variable
114 | ns - a valid pointer to a T_FRAME_NUM variable
115 | ciphering - a valid pointer to a BOOL variable
116 | header_size - a valid pointer to a USHORT variable
117 | frame_ok - a valid pointer to a BOOL variable
118 |
119 +------------------------------------------------------------------------------
120 */
121
122 #ifndef CF_FAST_EXEC
123
124 GLOBAL void rx_analyse_ctrl_field (T_GRLC_UNITDATA_IND *grlc_unitdata_ind,
125 T_PDU_TYPE *frame_type,
126 UBYTE *protected_mode,
127 UBYTE *sapi,
128 T_FRAME_NUM *ns,
129 BOOL *ciphering,
130 USHORT *header_size,
131 BOOL *frame_ok)
132 {
133 UBYTE first_octet;
134 UBYTE sec_octet;
135 UBYTE command_octet;
136 UBYTE sack_k_octet;
137
138
139 TRACE_FUNCTION( "rx_analyse_ctrl_field" );
140
141 /*
142 * Check if the frame contains enough octets to access the first octet of
143 * the control field to find out the type of the frame.
144 */
145 if (grlc_unitdata_ind->desc_list.list_len < CTRL_MIN_OCTETS)
146 {
147 *frame_ok = FALSE;
148 return;
149 }
150
151 /*
152 * Assume initially that the frame is ok.
153 */
154 *frame_ok = TRUE;
155
156 /*
157 * Set first_octet to the value of the first frame octet (offset 0), which
158 * is the address field.
159 */
160 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 0, &first_octet);
161
162 *sapi = first_octet & 0x0F;
163
164 /*
165 * Set sec_octet to the value of the second frame octet (offset 1), which
166 * is the first octet of the control field.
167 */
168 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 1, &sec_octet);
169
170
171 /*
172 * Determine frame_type, along with ns, protected_mode, and ciphering,
173 * depending on the frame type.
174 */
175 if ((sec_octet & I_FRAME_MASK) EQ I_FRAME_ID)
176 {
177 /*
178 * I frame, protected, ciphered, at least 4 octets required to access all
179 * requested information (1 Address, 3 Control).
180 */
181 *frame_type = I_FRAME;
182 *protected_mode = CCI_PM_PROTECTED;
183 *ciphering = TRUE;
184
185 /*
186 * Check if the frame contains enough octets to access the complete
187 * I frame control field.
188 */
189 if (grlc_unitdata_ind->desc_list.list_len < I_CTRL_MIN_OCTETS)
190 {
191 *frame_ok = FALSE;
192 return;
193 }
194
195 /*
196 * Determine the header_size
197 */
198 *header_size = I_CTRL_MIN_OCTETS;
199
200 /*
201 * Add bytes in case of SACK-Bitmap (add K+1). Therefore get at first
202 * the command octet (offset 3). In case of an SACK, get next the k
203 * octet (offset 4) and add the additional size.
204 */
205 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 3, &command_octet);
206
207 if ( (command_octet & 0x03) == I_FRAME_SACK )
208 {
209 *header_size += 1; /* k octet */
210
211 if (grlc_unitdata_ind->desc_list.list_len < *header_size)
212 {
213 *frame_ok = FALSE;
214 return;
215 }
216
217 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 4, &sack_k_octet);
218
219 *header_size += (sack_k_octet & 0x1F); /* bitmap size */
220
221 if (grlc_unitdata_ind->desc_list.list_len < *header_size)
222 {
223 *frame_ok = FALSE;
224 return;
225 }
226 }
227
228 /*
229 * Extract N(S) and store it in ns.
230 */
231 *ns = (((T_FRAME_NUM)
232 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 1, NULL)) & 0x1F) << 4;
233 *ns |= (((T_FRAME_NUM)
234 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 2, NULL)) >> 4);
235 }
236 else if ((sec_octet & S_FRAME_MASK) EQ S_FRAME_ID)
237 {
238 /*
239 * S frame, protected, not ciphered. No N(S) present, only N(R).
240 */
241 *frame_type = S_FRAME;
242 *protected_mode = CCI_PM_PROTECTED;
243 *ciphering = FALSE;
244
245 *header_size = S_CTRL_MIN_OCTETS;
246
247 /* not necessary to add bytes in case of SACK - value is not used */
248 }
249 else if ((sec_octet & UI_FRAME_MASK) EQ UI_FRAME_ID)
250 {
251 /*
252 * UI frame, at least 3 octets required to access all requested
253 * information (1 Address, 2 Control).
254 */
255 *frame_type = UI_FRAME;
256
257 /*
258 * Check if the frame contains enough octets to access the complete
259 * UI frame control field.
260 */
261 if (grlc_unitdata_ind->desc_list.list_len < UI_CTRL_MIN_OCTETS)
262 {
263 *frame_ok = FALSE;
264 return;
265 }
266
267 /*
268 * Extract protected mode setting of frame (PM bit).
269 */
270 if (rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 2, NULL) & 0x01)
271 {
272 *protected_mode = CCI_PM_PROTECTED;
273 }
274 else
275 {
276 *protected_mode = CCI_PM_UNPROTECTED;
277 }
278
279 /*
280 * Extract ciphering setting of frame (E bit).
281 */
282 if (rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 2, NULL) & 0x02)
283 {
284 *ciphering = TRUE;
285 }
286 else
287 {
288 *ciphering = FALSE;
289 }
290
291 *header_size = UI_CTRL_MIN_OCTETS;
292
293 /*
294 * Extract N(U) and store it in ns.
295 */
296 *ns = (((T_FRAME_NUM)
297 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 1, NULL)) & 0x07) << 6;
298 *ns |= (((T_FRAME_NUM)
299 rx_get_desc_octet (&grlc_unitdata_ind->desc_list, 2, NULL)) >> 2);
300 }
301 else if ((sec_octet & U_FRAME_MASK) EQ U_FRAME_ID)
302 {
303 /*
304 * U frame, protected, not ciphered. No N(S) present.
305 */
306 *frame_type = U_FRAME;
307 *protected_mode = CCI_PM_PROTECTED;
308 *ciphering = FALSE;
309
310 *header_size = U_CTRL_MIN_OCTETS;
311 }
312
313 return;
314 } /* rx_analyse_ctrl_field() */
315
316 #endif /* CF_FAST_EXEC */
317
318 /*
319 +------------------------------------------------------------------------------
320 | Function : rx_decipher_req
321 +------------------------------------------------------------------------------
322 | Description : Handles the function rx_decipher_req. This functions sets the
323 | ciphering parameters and calls the deciphering driver function.
324 |
325 | Parameters :
326 |
327 +------------------------------------------------------------------------------
328 */
329
330 #ifndef CF_FAST_EXEC
331 GLOBAL void rx_decipher_req (T_CCI_DECIPHER_REQ *decipher_req)
332 {
333 T_CIPH_init_cipher_req_parms init_cipher_req_parms;
334 T_CIPH_cipher_req_parms cipher_req_parms;
335 T_CIPH_in_data_list in_data_list;
336 T_CIPH_out_data out_data;
337 T_CIPH_ck ck;
338 U16 i;
339 U8 status;
340 U16 cnt = 0;
341
342 TRACE_FUNCTION( "rx_decipher_req" );
343
344 #ifdef LLC_TRACE_CIPHERING
345 TRACE_EVENT("DOWNLINK CIPHERED DATA");
346 llc_trace_desc_list(&decipher_req->desc_list);
347 #endif
348
349 /*
350 * Copy pointer to desc's from CIPHER_REQ to the in_data_list
351 * The in_data array in allocated dynamically in this func.
352 */
353 llc_copy_dl_data_to_list(decipher_req, &in_data_list);
354 /*
355 * Set ciphering parameters
356 */
357 cipher_req_parms.gprs_parameters.pm = decipher_req->pm;
358 cipher_req_parms.gprs_parameters.header_size = decipher_req->header_size;
359 cipher_req_parms.gprs_parameters.ciphering_input =
360 decipher_req->ciphering_input;
361 cipher_req_parms.gprs_parameters.threshold = 0;
362 init_cipher_req_parms.direction = CIPH_DOWNLINK_DIR;
363 init_cipher_req_parms.algo = decipher_req->ciphering_algorithm;
364 init_cipher_req_parms.ptr_ck = & ck;
365 /*
366 * Copy ciphering key
367 */
368 for (i = 0; i < 8;i++) {
369 init_cipher_req_parms.ptr_ck->ck_element[i] = decipher_req->kc.key[i];
370 }
371
372 {
373 /* Use GRLC_DATA_REQ instead of CCI_CIPHER_CNF to avoid PPASS in LLC*/
374 PALLOC_SDU (ll_unitdata_ind, LL_UNITDATA_IND,
375 (USHORT)((decipher_req->desc_list.list_len*8) - FCS_SIZE_BITS));
376
377 ll_unitdata_ind->sdu.o_buf = 0;
378 ll_unitdata_ind->sdu.l_buf = 0;
379 out_data.buf =
380 (U32)(&ll_unitdata_ind->sdu.buf[ll_unitdata_ind->sdu.o_buf >> 3]);
381 /*
382 * Initialize ciphering driver and decipher data
383 */
384 #ifdef TI_PS_OP_CIPH_DRIVER
385 ciph_init_cipher_req (&init_cipher_req_parms, NULL);
386 ciph_cipher_req (&cipher_req_parms, &in_data_list, &out_data, &status);
387 #else
388 ciph_init_cipher_req_sim (&init_cipher_req_parms, NULL);
389 ciph_cipher_req_sim (&cipher_req_parms, &in_data_list, &out_data, &status);
390 #endif
391 /*
392 * "Send" DECIPHER_CNF to LLC
393 */
394 ll_unitdata_ind->sdu.l_buf = out_data.len * 8;
395 ll_unitdata_ind->tlli = decipher_req->reference1;
396 ll_unitdata_ind->cipher = (UBYTE)decipher_req->reference2;
397 if (status == CIPH_CIPH_PASS){
398 ll_unitdata_ind->sapi = CCI_FCS_PASSED;
399 } else {
400 ll_unitdata_ind->sapi = CCI_FCS_FAILED;
401 }
402
403 #ifdef LLC_TRACE_CIPHERING
404 TRACE_EVENT("DOWNLINK DECIPHERED DATA");
405 llc_trace_sdu(&ll_unitdata_ind->sdu);
406 #endif
407 rx_cci_decipher_cnf(ll_unitdata_ind);
408 }
409 /*
410 * Free in_data array from in_data_list allocated in llc_copy_dl_data_to_list
411 */
412 if(in_data_list.ptr_in_data != NULL){
413 MFREE(in_data_list.ptr_in_data);
414 in_data_list.ptr_in_data = NULL;
415 }
416 /*
417 * Free descriptors from the deipher_req->desc_list
418 */
419 if (decipher_req != NULL)
420 {
421 T_desc *desc = (T_desc *)decipher_req->desc_list.first;
422 T_desc *next_desc;
423 while (desc NEQ NULL){
424 next_desc = (T_desc *)desc->next;
425 MFREE (desc);
426 desc = next_desc;
427 /* increase freed partitions counter */
428 cnt++;
429 }
430 MFREE(decipher_req);
431 decipher_req = NULL;
432 }
433 llc_data->fbs.cci_freed_partition +=cnt;
434
435 /* trace number of freed partitions */
436 if(llc_data->fbs.cci_info_trace){
437 TRACE_EVENT_P2("INFO CCI: freed partitions %ld, total=%ld",
438 cnt,llc_data->fbs.cci_freed_partition);
439 }
440
441 } /* rx_decipher_req */
442
443 #endif
444
445 /*
446 +------------------------------------------------------------------------------
447 | Function : rx_send_decipher_req
448 +------------------------------------------------------------------------------
449 | Description : This procedure allocates the CCI_DECIPHER_REQ primitive, fills
450 | in all necessary parameters and sends the primitive to CCI.
451 |
452 | Parameters : grlc_unitdata_ind - a valid pointer to a GRLC_UNITDATA_IND
453 | primitive
454 | frame_type - indicates (un)acknowledged operation mode
455 | protected_mode - pm setting for CCI_DECIPHER_REQ
456 | ns - N(S)/N(U) for deciphering, otherwise
457 | undefined value
458 | header_size - size of header bytes (not ciphered bytes)
459 | ciphering - indicates deciphering (TRUE/FALSE)
460 |
461 +------------------------------------------------------------------------------
462 */
463 #ifndef CF_FAST_EXEC
464
465 GLOBAL void rx_send_decipher_req (T_GRLC_UNITDATA_IND *grlc_unitdata_ind,
466 T_PDU_TYPE frame_type,
467 UBYTE protected_mode,
468 T_FRAME_NUM ns,
469 USHORT header_size,
470 BOOL ciphering)
471 {
472 ULONG oc;
473
474 TRACE_FUNCTION ("rx_send_decipher_req");
475
476 {
477 /*
478 * No need to PPASS GRLC_xDATA_IND, because desc_list contains a pointer
479 * which can be simply copied.
480 */
481 T_CCI_DECIPHER_REQ *cci_decipher_req;
482 MALLOC(cci_decipher_req, sizeof(T_CCI_DECIPHER_REQ));
483
484 /*
485 * Requires rx_analyse_ctrl_field() to set a correct CCI value.
486 */
487 cci_decipher_req->pm = protected_mode;
488
489 if (ciphering EQ TRUE)
490 {
491 cci_decipher_req->reference2 = LL_CIPHER_ON; /* re-use of reference is ok */
492 cci_decipher_req->ciphering_algorithm = llc_data->ciphering_algorithm;
493 memcpy (&cci_decipher_req->kc, &llc_data->kc, sizeof(T_kc));
494
495 /*
496 * Calculate the OC which is valid for this ns. This could be the
497 * current OC or OC + 1 in case of an modulo overflow of ns
498 */
499 switch (frame_type)
500 {
501 case I_FRAME:
502 case S_FRAME:
503 if (ns >= llc_data->sapi->vr)
504 oc = llc_data->sapi->oc_i_rx;
505 else
506 oc = llc_data->sapi->oc_i_rx + (MAX_SEQUENCE_NUMBER+1);
507 break;
508
509 default:
510 if (ns >= llc_data->sapi->vur)
511 oc = llc_data->sapi->oc_ui_rx;
512 else
513 oc = llc_data->sapi->oc_ui_rx + (MAX_SEQUENCE_NUMBER+1);
514 break;
515 }
516
517 llc_generate_input (llc_data->current_sapi, frame_type, ns,
518 &cci_decipher_req->ciphering_input, oc);
519
520 cci_decipher_req->direction = CCI_DIRECTION_DOWNLINK;
521 }
522 else /* ciphering EQ FALSE */
523 {
524 cci_decipher_req->reference2 = LL_CIPHER_OFF;
525 cci_decipher_req->ciphering_algorithm = CCI_CIPHER_NO_ALGORITHM;
526 }
527
528 cci_decipher_req->header_size = header_size;
529
530 /*
531 * TLLI must be stored somewhere
532 */
533 cci_decipher_req->reference1 = grlc_unitdata_ind->tlli;
534
535 cci_decipher_req->desc_list = grlc_unitdata_ind->desc_list;
536
537 /* TRACE_EVENT ("CCI thread not available, using functional interface"); */
538
539 rx_decipher_req(cci_decipher_req);
540 }
541
542 return;
543 } /* rx_send_decipher_req() */
544
545 #endif /* CF_FAST_EXEC */
546
547 /*
548 +------------------------------------------------------------------------------
549 | Function : rx_interpret_frame
550 +------------------------------------------------------------------------------
551 | Description : This procedure analyses the LLC header and checksum of the
552 | given frame (U, UI, or I) and sets sapi, pdu_type, command,
553 | cr_bit, pf_bit, nr, and ns accordingly. The FCS field is not
554 | included in frame, it has already been stripped off. frame_ok
555 | is set to TRUE if the frame fulfils the following requirements:
556 | known PDU type, valid length, valid PD bit, valid SAPI.
557 | frame_rej indicates a frame rejection condition if any bit of
558 | W4-W1 is set. If a frame is rejected, frame_rej_ctrl_length
559 | indicates the length of the control field. If this length
560 | could not be determined, frame_rej_ctrl_length is set to the
561 | number of control field octets of the frame.
562 |
563 | Parameters : frame - contains the frame to be analysed, must be
564 | a valid pointer
565 | sapi - will be set to the SAPI of the frame, must be
566 | a valid pointer
567 | pdu_type - will be set to the PDU type of the frame, must be
568 | a valid pointer
569 | command - will be set to the command (I/S, U) of the frame
570 | (if available), must be a valid pointer
571 | cr_bit - will be set to the C/R bit of the frame, must be
572 | a valid pointer
573 | pf_bit - will be set to the P/F bit of the frame (if
574 | available), must be a valid pointer
575 | nr - will be set to N(R) / N(U) of the frame (if
576 | available), must be a valid pointer
577 | ns - will be set to N(S) of the frame (if available),
578 | must be a valid pointer
579 | frame_ok - TRUE if the frame is ok, else FALSE, must be
580 | a valid pointer
581 | frame_rej - indicates a frame rejection condition, must be
582 | a valid pointer
583 | frame_rej_ctrl_length - number of octets in the rejected
584 | control field, must be a valid pointer
585 |
586 +------------------------------------------------------------------------------
587 */
588
589 /*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
590 !defined(REL99) || defined(LL_2to1) */
591
592 GLOBAL void rx_interpret_frame (T_sdu *frame,
593 UBYTE *sapi,
594 T_PDU_TYPE *pdu_type,
595 T_COMMAND *command,
596 T_BIT *cr_bit,
597 T_BIT *pf_bit,
598 T_FRAME_NUM *nr,
599 T_FRAME_NUM *ns,
600 BOOL *frame_ok,
601 UBYTE *frame_rej,
602 USHORT *frame_rej_ctrl_length,
603 UBYTE cipher)
604 {
605 USHORT min_length = 0; /* minimum required frame length */
606 BOOL check_length; /* check/ignore length at the end */
607
608 TRACE_FUNCTION( "rx_interpret_frame" );
609
610 /*
611 * Preset variables with suspected success, control field length is not
612 * yet known, so assume complete frame length.
613 */
614 *frame_ok = TRUE;
615 *frame_rej = FRAME_NOT_REJ;
616 *frame_rej_ctrl_length = frame->l_buf/8 - 1;
617
618 /*
619 * Frame length is selectively activated, depending on frame type, command,
620 * etc. Ignore frame length per default.
621 */
622 check_length = FALSE;
623
624
625 /*
626 * Check if the frame contains enough octets to access the first octet of
627 * the control field to find out the type of the frame.
628 */
629 if (frame->l_buf/8 < CTRL_MIN_OCTETS)
630 {
631 *frame_ok = FALSE;
632 return;
633 }
634
635
636 /*
637 * Check if PD bit is set to 0. If it is not, the frame is invalid.
638 * <R.LLC.XCEPTION.A.001>
639 */
640 if ((frame->buf[frame->o_buf/8] & 0x80) != 0x00)
641 {
642 *frame_ok = FALSE;
643 return;
644 }
645
646
647 /*
648 * Extract C/R bit.
649 */
650 *cr_bit = (frame->buf[frame->o_buf/8] & 0x40) >> 6;
651
652
653 /*
654 * Extract SAPI and check if the frame contains a reserved SAPI.
655 * <R.LLC.XCEPTION.A.001>
656 */
657 *sapi = frame->buf[frame->o_buf/8] & 0x0F;
658 switch (*sapi) /* !!!!! constants or function/macro to determine invalid sapis */
659 {
660 case 0:
661 case 2:
662 case 4:
663 case 6:
664 case 8:
665 case 10:
666 case 12:
667 case 13:
668 case 14:
669 case 15:
670 {
671 *frame_ok = FALSE;
672 return;
673 }
674 }
675
676
677 /*
678 * Determine the PDU type of the frame, along with the minimum length
679 * required for this PDU type to constitute a complete frame.
680 * Additionally, extract available variables for each PDU type.
681 */
682 if ((frame->buf[(frame->o_buf/8)+1] & I_FRAME_MASK) EQ I_FRAME_ID)
683 {
684 /*
685 * I frame, at least 5 octets (1 Address, 3 Control, 1(++)
686 * Information, no FCS)
687 */
688 *pdu_type = I_FRAME;
689 min_length = I_FRAME_MIN_OCTETS_WITHOUT_FCS;
690 *frame_rej_ctrl_length = I_CTRL_OCTETS;
691
692 /*
693 * Extract A bit (stored in P/F bit)
694 */
695 *pf_bit = (frame->buf[(frame->o_buf/8)+1] & 0x40) >> 6;
696
697 /*
698 * Check if the frame contains enough octets to access the complete
699 * I frame control field.
700 */
701 if (frame->l_buf/8 < I_CTRL_MIN_OCTETS)
702 {
703 *frame_ok = FALSE;
704 return;
705 }
706
707 /*
708 * Extract N(S), N(R)
709 */
710 *ns = (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+1] & 0x1F) << 4;
711 *ns |= (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+2] >> 4);
712
713 *nr = (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+2] & 0x07) << 6;
714 *nr |= (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+3] >> 2);
715
716 /*
717 * Determine the command of the I frame (S1 & S2 bits)
718 */
719 switch (frame->buf[(frame->o_buf/8)+3] & 0x03)
720 {
721 case I_FRAME_RR:
722 TRACE_4_PARA("I-RR s:%d len:%d nr:%d ns:%d", *sapi, BYTELEN(frame->l_buf), *nr, *ns);
723 *command = I_RR;
724 break;
725
726 case I_FRAME_ACK:
727 TRACE_4_PARA("I-ACK s:%d len:%d nr:%d ns:%d", *sapi, BYTELEN(frame->l_buf), *nr, *ns);
728 *command = I_ACK;
729 break;
730
731 case I_FRAME_RNR:
732 TRACE_4_PARA("I-RNR s:%d len:%d nr:%d ns:%d", *sapi, BYTELEN(frame->l_buf), *nr, *ns);
733 *command = I_RNR;
734 break;
735
736 case I_FRAME_SACK:
737 TRACE_4_PARA("I-SACK s:%d len:%d nr:%d ns:%d", *sapi, BYTELEN(frame->l_buf), *nr, *ns);
738 *command = I_SACK;
739
740 /*
741 * Check if the frame contains enough octets to access the complete
742 * I frame SACK control field. K is at octet I_CTRL_MIN_OCTETS + 1
743 * and there must be at least K+1 octets within the bitmap. Therefore
744 * the frame must contain a minimum of I_CTRL_MIN_OCTETS+2.
745 */
746 if (frame->l_buf/8 < I_CTRL_MIN_OCTETS+2)
747 {
748 *frame_ok = FALSE;
749 return;
750 }
751
752 /*
753 * min_length is being modified to be more accurate for SACK frames,
754 * according to the Bitmap Length Indicator K in
755 * frame->buf[(frame->o_buf/8)+4].
756 */
757 min_length += (frame->buf[(frame->o_buf/8)+4] & 0x1F) + 1;
758
759 check_length = TRUE;
760 break;
761
762 default:
763 /*
764 * Frame rejection condition due to receipt of a command or
765 * response field that is undefined or not implemented (set
766 * W3 bit to 1).
767 * <R.LLC.XCEPTION.A.002>
768 */
769 *frame_ok = FALSE;
770 *frame_rej = FRAME_REJ_W3;
771 return;
772 }
773 }
774 else if ((frame->buf[(frame->o_buf/8)+1] & S_FRAME_MASK) EQ S_FRAME_ID)
775 {
776 /*
777 * S frame, fixed 3 octets (1 Address, 2 Control, 0 Information, no FCS)
778 */
779 *pdu_type = S_FRAME;
780 min_length = S_FRAME_MIN_OCTETS_WITHOUT_FCS;
781 *frame_rej_ctrl_length = S_CTRL_OCTETS;
782
783 /*
784 * Extract A bit (stored in P/F bit)
785 */
786 *pf_bit = (frame->buf[(frame->o_buf/8)+1] & 0x20) >> 5;
787
788 /*
789 * Check if the frame contains enough octets to access the complete
790 * S frame control field.
791 */
792 if (frame->l_buf/8 < S_CTRL_MIN_OCTETS)
793 {
794 *frame_ok = FALSE;
795 *frame_rej = FRAME_REJ_W1;
796 *frame_rej_ctrl_length = frame->l_buf/8 - 1;
797 return;
798 }
799
800 /*
801 * Extract N(R)
802 */
803 *nr = (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+1] & 0x07) << 6;
804 *nr |= (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+2] >> 2);
805
806 /*
807 * Determine the command of the S frame (S1 & S2 bits)
808 */
809 switch (frame->buf[(frame->o_buf/8)+2] & 0x03)
810 {
811 case I_FRAME_RR:
812 TRACE_2_PARA("S-RR s:%d nr:%d", *sapi, *nr);
813 *command = I_RR;
814 check_length = TRUE;
815 break;
816
817 case I_FRAME_ACK:
818 TRACE_2_PARA("S-ACK s:%d nr:%d", *sapi, *nr);
819 *command = I_ACK;
820 check_length = TRUE;
821 break;
822
823 case I_FRAME_RNR:
824 TRACE_2_PARA("S-RNR s:%d nr:%d", *sapi, *nr);
825 *command = I_RNR;
826 check_length = TRUE;
827 break;
828
829 case I_FRAME_SACK:
830 TRACE_2_PARA("S-SACK s:%d nr:%d", *sapi, *nr);
831 *command = I_SACK;
832 /*
833 * min_length is being modified to be more accurate for SACK frames.
834 * The S frame SACK format adds a number of up to 32 octets to the
835 * control field.
836 */
837 min_length += S_FRAME_SACK_MIN_CTRL_OCTETS;
838
839 check_length = FALSE;
840 break;
841
842 default:
843 /*
844 * Frame rejection condition due to receipt of a command or
845 * response field that is undefined or not implemented (set
846 * W3 bit to 1).
847 * <R.LLC.XCEPTION.A.002>
848 */
849 *frame_ok = FALSE;
850 *frame_rej = FRAME_REJ_W3;
851 return;
852 }
853 }
854 else if ((frame->buf[(frame->o_buf/8)+1] & UI_FRAME_MASK) EQ UI_FRAME_ID)
855 {
856 /*
857 * UI frame, at least 3 octets (1 Address, 2 Control, 0(++)
858 * Information, no FCS)
859 */
860 *pdu_type = UI_FRAME;
861 min_length = UI_FRAME_MIN_OCTETS_WITHOUT_FCS;
862 *frame_rej_ctrl_length = UI_CTRL_OCTETS;
863
864 /*
865 * Check if the frame contains enough octets to access the complete
866 * UI frame control field.
867 */
868 if (frame->l_buf/8 < UI_CTRL_MIN_OCTETS)
869 {
870 *frame_ok = FALSE;
871 return;
872 }
873
874 /*
875 * Extract N(U) (is stored in N(R))
876 */
877 *nr = (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+1] & 0x07) << 6;
878 *nr |= (T_FRAME_NUM)(frame->buf[(frame->o_buf/8)+2] >> 2);
879
880 TRACE_4_PARA("UI s:%d len:%d nr:%d c:%d", *sapi, BYTELEN(frame->l_buf), *nr, cipher);
881 }
882 else if ((frame->buf[(frame->o_buf/8)+1] & U_FRAME_MASK) EQ U_FRAME_ID)
883 {
884 /*
885 * U frame, at least 2 octets (1 Address, 1 Control, 0(++)
886 * Information, no FCS)
887 */
888 *pdu_type = U_FRAME;
889 min_length = U_FRAME_MIN_OCTETS_WITHOUT_FCS;
890 *frame_rej_ctrl_length = U_CTRL_OCTETS;
891
892 /*
893 * Extract P/F bit
894 */
895 *pf_bit = (frame->buf[(frame->o_buf/8)+1] & 0x10) >> 4;
896
897 /*
898 * Check if the frame contains enough octets to access the complete
899 * U frame control field.
900 * NOTE:
901 * This check could be omitted, because the U frame control field size
902 * is only one octet.
903 */
904 if (frame->l_buf/8 < U_CTRL_MIN_OCTETS)
905 {
906 *frame_ok = FALSE;
907 *frame_rej = FRAME_REJ_W1;
908 return;
909 }
910
911 /*
912 * Determine the command of the U frame (M4, M3, M2, M1).
913 * Adjust the minimum length of the frame, if possible.
914 */
915 switch (frame->buf[(frame->o_buf/8)+1] & 0x0F)
916 {
917 case U_FRAME_DM:
918 TRACE_1_PARA("DM s:%d", *sapi);
919 *command = U_DM;
920 /*
921 * No information field is permitted.
922 */
923 check_length = TRUE;
924 break;
925 case U_FRAME_DISC:
926 TRACE_1_PARA("DISC s:%d", *sapi);
927 *command = U_DISC;
928 /*
929 * No information field is permitted.
930 */
931 check_length = TRUE;
932 break;
933 case U_FRAME_UA:
934 TRACE_2_PARA("UA s:%d len:%d", *sapi, BYTELEN(frame->l_buf));
935 *command = U_UA;
936 /*
937 * No knowledge if an information field is permitted, because
938 * this is only the case when UA is the response to SABM.
939 */
940 break;
941 case U_FRAME_SABM:
942 TRACE_2_PARA("SABM s:%d len:%d", *sapi, BYTELEN(frame->l_buf));
943 *command = U_SABM;
944 /*
945 * An information field is permitted, containing XID
946 * parameters. Therefore the size of the information field
947 * is not (yet) known.
948 */
949 break;
950 case U_FRAME_FRMR:
951 TRACE_1_PARA("FRMR s:%d", *sapi);
952 *command = U_FRMR;
953 /*
954 * FRMR response contains an information field of 10 octets.
955 * <R.LLC.XCEPTION.A.008>
956 */
957 min_length += U_FRAME_FRMR_INFO_OCTETS;
958 check_length = TRUE;
959 break;
960 case U_FRAME_XID:
961 if( *cr_bit == SGSN_COMMAND )
962 {
963 TRACE_2_PARA("XID REQ s:%d len:%d", *sapi, BYTELEN(frame->l_buf));
964 }
965 else
966 {
967 TRACE_2_PARA("XID RSP s:%d len:%d", *sapi, BYTELEN(frame->l_buf));
968 }
969 *command = U_XID;
970 /*
971 * An information field is required, containing XID
972 * parameters. Therefore the size of the information field
973 * is not (yet) known.
974 */
975 break;
976 default:
977 TRACE_0_INFO("Not supported U frame received");
978 /*
979 * Frame rejection condition due to receipt of a command or
980 * response field that is undefined or not implemented (set
981 * W3 bit to 1).
982 * <R.LLC.XCEPTION.A.002>
983 */
984 *frame_ok = FALSE;
985 *frame_rej = FRAME_REJ_W3;
986 return;
987 }
988 }
989
990
991 /*
992 * Determine if it is requested to check the frame length exactly
993 * (check_length EQ TRUE), or just to check the minimum frame length
994 * (check_length EQ FALSE).
995 */
996 if (check_length AND (frame->l_buf/8 NEQ min_length))
997 {
998 /*
999 * Actual length of frame doesn't correspond with computed length.
1000 */
1001 *frame_ok = FALSE;
1002
1003 /*
1004 * Check if frame rejection condition occured: S or U frame with
1005 * incorrect length (= W1 + W3 bits). frame_rej_ctrl_length has already
1006 * been set above to the correct control field length.
1007 * <R.LLC.XCEPTION.A.002>, <R.LLC.XCEPTION.A.010>
1008 */
1009 if ((*pdu_type EQ S_FRAME) OR (*pdu_type EQ U_FRAME))
1010 {
1011 *frame_rej = FRAME_REJ_W1 | FRAME_REJ_W3;
1012 }
1013 return;
1014 }
1015 else if (frame->l_buf/8 < min_length)
1016 {
1017 /*
1018 * Frame doesn't contain enough octets to include the address field,
1019 * control field, information field, and FCS field necessary to constitute
1020 * a complete frame according to the PDU type.
1021 * <R.LLC.XCEPTION.A.001>
1022 */
1023 *frame_ok = FALSE;
1024 return;
1025 }
1026
1027 return;
1028 } /* rx_interpret_frame() */
1029
1030 /* #endif */ /* CF_FAST_EXEC || _SIMULATION_ */
1031
1032
1033 /*
1034 +------------------------------------------------------------------------------
1035 | Function : rx_strip_llc_header
1036 +------------------------------------------------------------------------------
1037 | Description : This procedure strips the LLC header field off of the sdu
1038 | so that the sdu contains only the remaining L3-PDU.
1039 |
1040 | Parameters : sdu - contains the SDU (frame), must be a valid pointer
1041 | pdu_type - contains the PDU type of the frame, must be
1042 | a valid PDU type
1043 | command - contains the command (I/S, U) of the frame, must be
1044 | a valid command for the given PDU type
1045 |
1046 +------------------------------------------------------------------------------
1047 */
1048
1049 #ifndef CF_FAST_EXEC
1050
1051 GLOBAL void rx_strip_llc_header (T_sdu *sdu,
1052 T_PDU_TYPE pdu_type,
1053 T_COMMAND command)
1054 {
1055 UBYTE header_len = 0;
1056
1057
1058 TRACE_FUNCTION ("rx_strip_llc_header");
1059
1060 switch (pdu_type)
1061 {
1062 case I_FRAME:
1063 /*
1064 * I frame 4 octets. Leave SACK Bitmap in PDU, will be stripped later!
1065 * (1 Address, 3Control).
1066 */
1067 header_len = I_CTRL_MIN_OCTETS;
1068 break;
1069 case S_FRAME:
1070 /*
1071 * S frame 3 octets. Leave SACK Bitmap in PDU, will be stripped later!
1072 * (1 Address, 2(+32 max) Control).
1073 */
1074 header_len = S_CTRL_MIN_OCTETS;
1075 break;
1076 case UI_FRAME:
1077 /*
1078 * UI frame, 3 octets (1 Address, 2 Control).
1079 */
1080 header_len = UI_CTRL_MIN_OCTETS;
1081 break;
1082 case U_FRAME:
1083 /*
1084 * U frame, 2 octets (1 Address, 1 Control).
1085 */
1086 header_len = U_CTRL_MIN_OCTETS;
1087 break;
1088 default:
1089 TRACE_ERROR ("Unknown PDU type");
1090 break;
1091 }
1092
1093 /*
1094 * Adjust the beginning of the PDU using the determined header_len.
1095 */
1096 sdu->o_buf += header_len * 8;
1097
1098 /*
1099 * Adjust the length of the PDU by the size of the header field.
1100 */
1101 sdu->l_buf -= header_len * 8;
1102
1103 return;
1104 } /* rx_strip_llc_header() */
1105
1106 #endif /* CF_FAST_EXEC */
1107
1108 /*
1109 +------------------------------------------------------------------------------
1110 | Function : rx_get_desc_octet
1111 +------------------------------------------------------------------------------
1112 | Description : This procedure maps the given linear offset to a descriptor
1113 | list and returns the value of the octet at this offset. If
1114 | offset is too large for descriptor list, 0x00 is returned.
1115 | Each descriptor in descriptor list is evaluated until the
1116 | requested offset is reached. The resulting octet value is
1117 | written to the referenced parameter data_ptr (if not set to
1118 | NULL), and is additionally returned.
1119 |
1120 | Parameters : desc_list - a valid pointer to a valid descriptor list
1121 | offset - linear octet offset, beginning with 0
1122 | data_ptr - a valid pointer to be set to the resulting octet
1123 | value, or NULL
1124 |
1125 +------------------------------------------------------------------------------
1126 */
1127
1128 #ifndef CF_FAST_EXEC
1129
1130 GLOBAL UBYTE rx_get_desc_octet (T_desc_list *desc_list,
1131 USHORT offset,
1132 UBYTE *data_ptr)
1133 {
1134 T_desc *desc;
1135 UBYTE *desc_data; /* local pointer to data octet */
1136
1137 /*
1138 * Check if offset is contained in descriptor list. Return 0x00 if not.
1139 */
1140 if (offset >= desc_list->list_len)
1141 {
1142 TRACE_ERROR ("offset too large for descriptor list");
1143 return 0x00;
1144 }
1145
1146 /*
1147 * Search requested data with given linear offset in descriptor list.
1148 * Empty descriptors are skipped. Check for each descriptor if requested
1149 * offset is in descriptor, until it is found.
1150 */
1151 desc = (T_desc *)desc_list->first;
1152 desc_data = NULL;
1153 do
1154 {
1155 if (offset < desc->len)
1156 {
1157 /*
1158 * Requested data is in current descriptor. Set desc_data to point to
1159 * requested octet with remaining offset (has been decremented by
1160 * already passed descriptor payload).
1161 */
1162 /*lint -e662 Possible creation of out-of-bounds pointer */
1163 desc_data = &(desc->buffer[offset]);
1164 }
1165 else
1166 {
1167 /*
1168 * Requested data is not in current descriptor. Remember data payload
1169 * of current descriptor as already passed.
1170 */
1171 offset -= desc->len;
1172 }
1173
1174 desc = (T_desc *)desc->next;
1175 }
1176 while ((desc NEQ NULL) AND (desc_data EQ NULL));
1177
1178
1179 if (desc_data EQ NULL)
1180 {
1181 TRACE_ERROR ("descriptor list ended before offset found");
1182
1183 if (data_ptr NEQ NULL)
1184 {
1185 *data_ptr = 0;
1186 }
1187
1188 return 0;
1189 }
1190 else
1191 {
1192 /*
1193 * Store value of found octet in data_ptr, if pointer is valid.
1194 */
1195 if (data_ptr NEQ NULL)
1196 {
1197 /*lint -e661 Possible access of out-of-bounds pointer */
1198 *data_ptr = *desc_data;
1199 }
1200
1201 return *desc_data;
1202 }
1203 } /* rx_get_desc_octet() */
1204
1205 #endif /* CF_FAST_EXEC */