comparison src/g23m-gprs/sndcp/sndcp_ciap.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 : GPRS (8441)
4 | Modul : sndcp_ciap.c
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 SNDCP and implements all
18 | functions to handles the incoming primitives as described in
19 | the SDL-documentation (CIA-statemachine)
20 +-----------------------------------------------------------------------------
21 */
22
23
24 #define ENTITY_SNDCP
25
26 /*==== INCLUDES =============================================================*/
27
28 #include "typedefs.h" /* to get Condat data types */
29 #include "vsi.h" /* to get a lot of macros */
30 #include "macdef.h"
31 #include "gsm.h" /* to get a lot of macros */
32 #include "prim.h" /* to get the definitions of used SAP and directions */
33
34 #include "dti.h"
35
36 #include "sndcp.h" /* to get the global entity definitions */
37 #include "sndcp_f.h" /* to get the functions to access the global arrays*/
38
39 #include <string.h> /* to get memcpy() */
40 #include "sndcp_mgf.h" /* to get the local functions of service mg */
41 #include "sndcp_sus.h" /* to get signals to service su */
42 #include "sndcp_suas.h"/* to get signals to service sua */
43 #include "sndcp_sds.h" /* to get signals to service sd */
44 #include "sndcp_sdas.h"/* to get signals to service sda */
45 #include "sndcp_ciap.h"
46
47
48 /*==== CONST ================================================================*/
49
50
51 /*==== LOCAL VARS ===========================================================*/
52
53 /*==== PRIVATE FUNCTIONS ====================================================*/
54
55 /*
56 +------------------------------------------------------------------------------
57 | Function : cia_vj_decomp
58 +------------------------------------------------------------------------------
59 | Description : decompresses the TCP/IP header of the given packet
60 | (Van Jacobson algorithm). A part of this routine has been taken
61 | from implementation of University of California, Berkeley.
62 |
63 | Parameters : com_buf - received packet, packet length, packet type
64 |
65 | Return : new packet length
66 |
67 +------------------------------------------------------------------------------
68 */
69 #ifndef CF_FAST_EXEC
70
71 LOCAL USHORT cia_vj_decomp(struct comp_buf *cbuf)
72 {
73 struct slcompress *comp = &sndcp_data->cia.comp;
74 UBYTE *cp; /* pointer to the compressed TCP/IP packet */
75 UBYTE hlen = 0;
76 ULONG change_mask = 0;
77 T_SNDCP_TCP_HEADER *th;
78 struct cstate *cs;
79 ULONG tmp;
80 USHORT th_off;
81
82 TRACE_FUNCTION( "cia_vj_decomp" );
83
84 switch (cbuf->p_type) {
85
86 case TYPE_UNCOMPRESSED_TCP:
87 {
88 UBYTE *hdr_ptr = (UBYTE*)cbuf->c_hdr;
89 UBYTE slot_nr = hdr_ptr[9];
90 if (slot_nr >= sndcp_data->cia.comp.slots_to_use){
91 TRACE_EVENT_P2("ERROR DECOMP: slot_nr(%d) > slots_to_use(%d)",
92 slot_nr, sndcp_data->cia.comp.slots_to_use);
93 comp->flags |= SLF_TOSS;
94 return (0);
95 }
96 /* set last received state */
97 comp->last_recv = slot_nr;
98 /* get related compressed state */
99 cs = &comp->rstate[comp->last_recv];
100 /* clear toss flag */
101 comp->flags &=~ SLF_TOSS;
102 /* set protocol type to TCP/IP */
103 hdr_ptr[9] = PROT_TCPIP;
104 /* get IP header length */
105 hlen = hdr_ptr[0] & HL_MASK;
106 /* get TCP header */
107 th_off = hdr_ptr[hlen*4 + 12];
108 th_off = (th_off & 0xf0) >> 4;
109 /* calculate IP+TCP header length */
110 hlen += th_off;
111 hlen <<= 2;
112 /* copy TCP+IP header */
113 memcpy(cs->cs_ip, hdr_ptr, hlen);
114 cs->cs_ip->ip_sum = 0;
115 cs->cs_hlen = hlen;
116 return ((USHORT)cbuf->pack_len);
117 }
118
119 case TYPE_COMPRESSED_TCP:
120 break;
121
122 default:
123 comp->flags |= SLF_TOSS;
124 TRACE_EVENT_P1("ERROR DECOMP unknown packet type (%d)", cbuf->p_type);
125 return (0);
126 }
127
128 /* We've got a compressed packet. */
129 cp = (UBYTE *)cbuf->c_hdr;
130 change_mask = *cp++;
131 if (change_mask & NEW_C) {
132 /* Make sure the state index is in range, then grab the state.
133 * If we have a good state index, clear the 'discard' flag. */
134 if (*cp >= sndcp_data->cia.comp.slots_to_use){
135 comp->flags |= SLF_TOSS;
136 return (0);
137 }
138
139 comp->flags &=~ SLF_TOSS;
140 /* store connection number */
141 comp->last_recv = *cp++;
142 } else {
143 /* this packet has an implicit state index. If we've
144 * had a line error since the last time we got an
145 * explicit state index, we have to toss the packet. */
146 if (comp->flags & SLF_TOSS) {
147 return (0);
148 }
149 }
150 /* get related connection state */
151 cs = &comp->rstate[comp->last_recv];
152 /* get IP header length */
153 hlen = (cs->cs_ip->ip_vhl & HL_MASK) << 2;
154 /* get TCP header */
155 th = (T_SNDCP_TCP_HEADER *)&((UBYTE *)cs->cs_ip)[hlen];
156 /* store new TCP check sum */
157 th->th_sum = sndcp_swap2((USHORT)((*cp << 8) | cp[1]));
158 cp += 2;
159 /* check if push bit is set */
160 if (change_mask & TCP_PUSH_BIT)
161 th->th_flags |= TH_PUSH;
162 else
163 th->th_flags &=~ TH_PUSH;
164
165 switch (change_mask & SPECIALS_MASK) {
166
167 case SPECIAL_I:
168 {
169 ULONG deltaL = sndcp_swap2(cs->cs_ip->ip_len) - cs->cs_hlen;
170 th->th_ack = sndcp_swap4(sndcp_swap4(th->th_ack) + deltaL);
171 th->th_seq = sndcp_swap4(sndcp_swap4(th->th_seq) + deltaL);
172 }
173 break;
174
175 case SPECIAL_D:
176 th->th_seq = sndcp_swap4(sndcp_swap4(th->th_seq)
177 + sndcp_swap2(cs->cs_ip->ip_len)
178 - cs->cs_hlen);
179 break;
180
181 /* no special case */
182 default:
183 /* urgend data field */
184 if (change_mask & NEW_U) {
185 th->th_flags |= TH_URG;
186 if (*cp == 0) {
187 th->th_urp = sndcp_swap2((USHORT)((cp[1] << 8) | cp[2]));
188 cp += 3;
189 } else {
190 th->th_urp = sndcp_swap2((USHORT)((ULONG)*cp++));
191 }
192 } else {
193 th->th_flags &=~ TH_URG;
194 }
195 /*
196 * window size
197 */
198 if (change_mask & NEW_W){
199 if (*cp == 0) {
200 th->th_win = sndcp_swap2((USHORT)(sndcp_swap2(th->th_win)
201 + ((cp[1] << 8) | cp[2])));
202 cp += 3;
203 } else {
204 th->th_win = sndcp_swap2((USHORT)(sndcp_swap2(th->th_win) + (ULONG)*cp++));
205 }
206 }
207 /*
208 * acknowledgement number
209 */
210 if (change_mask & NEW_A){
211 if (*cp == 0) {
212 th->th_ack = sndcp_swap4(sndcp_swap4(th->th_ack) + ((cp[1] << 8) | cp[2]));
213 cp += 3;
214 } else {
215 th->th_ack = sndcp_swap4(sndcp_swap4(th->th_ack) + (ULONG)*cp++);
216 }
217 }
218 /*
219 * sequence number
220 */
221 if (change_mask & NEW_S){
222 if (*cp == 0) {
223 (th->th_seq) = sndcp_swap4(sndcp_swap4(th->th_seq) + ((cp[1] << 8) | cp[2]));
224 cp += 3;
225 } else {
226 (th->th_seq) = sndcp_swap4(sndcp_swap4(th->th_seq) + (ULONG)*cp++);
227 }
228 }
229 break;
230 }
231 /*
232 * packet ID
233 */
234 if (change_mask & NEW_I) {
235 if (*cp == 0) {
236 cs->cs_ip->ip_id = sndcp_swap2((USHORT)(sndcp_swap2(cs->cs_ip->ip_id)
237 + ((cp[1] << 8) | cp[2])));
238 cp += 3;
239 } else {
240 cs->cs_ip->ip_id = sndcp_swap2((USHORT)(sndcp_swap2(cs->cs_ip->ip_id)
241 + (ULONG)*cp++));
242 }
243 } else
244 cs->cs_ip->ip_id = sndcp_swap2((USHORT)(sndcp_swap2(cs->cs_ip->ip_id) + 1));
245
246 /*
247 * At this point, cp points to the first byte of data in the
248 * packet. If we're not aligned on a 4-byte boundary, copy the
249 * data down so the ip & tcp headers will be aligned. Then back up
250 * cp by the tcp/ip header length to make room for the reconstructed
251 * header (we assume the packet we were handed has enough space to
252 * prepend 120 bytes of header). Adjust the length to account for
253 * the new header & fill in the IP total length.
254 */
255 tmp = cp - (UBYTE*)cbuf->c_hdr;
256 cbuf->pack_len -= cp - (UBYTE*)cbuf->c_hdr;
257 if ((UBYTE*)cbuf->c_hdr > cp){
258 /* we must have dropped some characters (crc should detect
259 * this but the old slip framing won't) */
260 comp->flags |= SLF_TOSS;
261 return (0);
262 }
263
264 cbuf->c_hdr += tmp;
265 cbuf->hdr_len -= (USHORT)tmp;
266 tmp = (ULONG)cp & 3;
267 if (tmp) {
268 if (cbuf->pack_len > 0)
269 memcpy(cp - tmp, cp, cbuf->hdr_len);
270 cbuf->c_hdr -= tmp;
271 cp -= tmp;
272 }
273 cbuf->c_hdr -= cs->cs_hlen;
274 cp -= cs->cs_hlen;
275 cbuf->hdr_len += cs->cs_hlen;
276 cbuf->pack_len += cs->cs_hlen;
277 cs->cs_ip->ip_len = sndcp_swap2(cbuf->pack_len);
278 memcpy(cp, cs->cs_ip, cs->cs_hlen);
279
280 /* recompute the ip header checksum */
281 {
282 USHORT *bp = (USHORT *)cp;
283
284 for (change_mask = 0; hlen > 0; hlen -= 2)
285 change_mask += *bp++;
286 change_mask = (change_mask & 0xffff) + (change_mask >> 16);
287 change_mask = (change_mask & 0xffff) + (change_mask >> 16);
288 ((T_SNDCP_IP_HEADER *)cp)->ip_sum = ~ (USHORT)change_mask;
289 }
290 return (cbuf->pack_len);
291 }
292
293 #endif /* CF_FAST_EXEC */
294
295
296 /*
297 +------------------------------------------------------------------------------
298 | Function : cia_header_decomp
299 +------------------------------------------------------------------------------
300 | Description : de-compresses the TCP/IP header of the given packet
301 | (Van Jacobson algorithm)
302 |
303 | Parameters : packet as desc_list, packet_type
304 |
305 +------------------------------------------------------------------------------
306 */
307 #ifndef CF_FAST_EXEC
308
309 #ifdef _SNDCP_DTI_2_
310 GLOBAL void cia_header_decomp(T_desc_list2* desc_list, UBYTE* packet_type)
311 {
312 #else /*_SNDCP_DTI_2_*/
313 GLOBAL void cia_header_decomp(T_desc_list* desc_list, UBYTE* packet_type)
314 {
315 #endif /*_SNDCP_DTI_2_*/
316
317 struct comp_buf cbuf;
318 /* the length of decompressed header + payload */
319 USHORT decomp_len;
320
321 #ifdef _SNDCP_DTI_2_
322 T_desc2* desc = (T_desc2*) desc_list->first;
323 T_desc2* decomp_desc;
324 U8 *desc_buff = &desc->buffer[desc->offset];
325 #else
326 T_desc* desc = (T_desc*) desc_list->first;
327 T_desc* decomp_desc;
328 U8 *desc_buff = &desc->buffer[0];
329 #endif
330
331 TRACE_FUNCTION( "cia_header_decomp" );
332
333 #ifdef SNDCP_TRACE_BUFFER
334 TRACE_EVENT("INFO DECOMP: Input Packet");
335 sndcp_trace_desc_list(desc_list);
336 #endif /* SNDCP_TRACE_BUFFER */
337
338 switch(*packet_type)
339 {
340 /*
341 * packet type IP: do nothing
342 */
343 case TYPE_IP:
344 TRACE_EVENT("INFO DECOMP: TYPE_IP");
345 *packet_type = TYPE_IP;
346 break;
347
348 /*
349 * packet type uncompressed TCP
350 */
351 case TYPE_UNCOMPRESSED_TCP:
352 TRACE_EVENT("INFO DECOMP: TYPE_UNCOMPRESSED_TCP");
353 cbuf.c_hdr = (ULONG)&desc_buff[0];
354 cbuf.hdr_len = desc->len;
355 cbuf.pack_len = desc_list->list_len;
356 cbuf.p_type = *packet_type;
357 decomp_len = cia_vj_decomp(&cbuf);
358 if(decomp_len == 0)
359 {
360 TRACE_EVENT("ERROR DECOMP: decomp_len = 0, TYPE_ERROR");
361 *packet_type = TYPE_ERROR;
362 }
363 else
364 {
365 *packet_type = TYPE_IP;
366 }
367 break;
368
369 /*
370 * packet type compressed TCP
371 */
372 case TYPE_COMPRESSED_TCP:
373 TRACE_EVENT("INFO DECOMP: TYPE_COMPRESSED_TCP");
374 /*
375 * Because we don't know the length of compressed TCP/IP header,
376 * we have to copy max. 40 bytes, wich sure contain compressed
377 * header + maybe some payload bytes.
378 */
379 cbuf.hdr_len = (desc->len < 40) ? desc->len : 40;
380 cbuf.c_hdr = (ULONG)&sndcp_data->cia.comp.
381 tcpip_hdr[TMP_HDR_LEN-1-cbuf.hdr_len];
382 cbuf.pack_len = desc_list->list_len;
383 cbuf.p_type = *packet_type;
384 memcpy((UBYTE*)cbuf.c_hdr, &desc_buff[0], cbuf.hdr_len);
385 decomp_len = cia_vj_decomp(&cbuf);
386 if(decomp_len != 0)
387 {
388 /*
389 * Build destination descriptor list
390 */
391 USHORT offset = cbuf.pack_len - desc_list->list_len;
392 #ifdef _SNDCP_DTI_2_
393 MALLOC(decomp_desc, (USHORT)(sizeof(T_desc2) - 1 + desc->len + offset));
394 #else
395 MALLOC(decomp_desc, (USHORT)(sizeof(T_desc) - 1 + desc->len + offset));
396 #endif
397 /* copy compressed header + piece of data */
398 memcpy(&decomp_desc->buffer[0], (UBYTE*)cbuf.c_hdr, cbuf.hdr_len);
399 /* copy the rest of data */
400 memcpy(&decomp_desc->buffer[cbuf.hdr_len],
401 &desc->buffer[cbuf.hdr_len-offset],
402 desc->len-cbuf.hdr_len+offset);
403 decomp_desc->next = desc->next;
404 decomp_desc->len = desc->len + offset;
405 #ifdef _SNDCP_DTI_2_
406 decomp_desc->size = desc->size + offset;
407 decomp_desc->offset = desc->offset;
408 #endif
409 desc_list->first = (ULONG)decomp_desc;
410 desc_list->list_len = desc_list->list_len - desc->len + decomp_desc->len;
411 MFREE(desc);
412 *packet_type = TYPE_IP;
413 }
414 else
415 {
416 TRACE_EVENT("ERROR DECOMP: decomp_len = 0, TYPE_ERROR");
417 *packet_type = TYPE_ERROR;
418 }
419 break;
420
421 default:
422 TRACE_EVENT_P1("ERROR DECOMP: unexpected packet type: %d", packet_type);
423 *packet_type = TYPE_ERROR;
424 break;
425
426 }
427
428 } /* cia_header_decomp() */
429
430 #endif /* CF_FAST_EXEC */
431
432
433 /*==== PUBLIC FUNCTIONS =====================================================*/
434
435 /*
436 +------------------------------------------------------------------------------
437 | Function : cia_cia_decomp_ind
438 +------------------------------------------------------------------------------
439 | Description : Handles the primitive CIA_DECOMP_IND
440 |
441 | Parameters : *cia_decomp_ind - Ptr to primitive payload
442 |
443 +------------------------------------------------------------------------------
444 */
445 #ifndef CF_FAST_EXEC
446
447 GLOBAL void cia_cia_decomp_ind ( T_CIA_DECOMP_IND *cia_decomp_ind )
448 {
449 UBYTE nsapi = cia_decomp_ind->pdu_ref.ref_nsapi;
450 BOOL ack = FALSE;
451 BOOL compressed = FALSE;
452 UBYTE pcomp = cia_decomp_ind->pcomp;
453 UBYTE pntt = 0;
454 UBYTE sapi = 0;
455 BOOL pcomp_ok = FALSE;
456
457 #ifndef _SNDCP_DTI_2_
458 T_desc_list temp_desc_list;
459 #endif /*_SNDCP_DTI_2_*/
460
461 UBYTE p_id = DTI_PID_IP;
462
463 TRACE_FUNCTION( "cia_cia_decomp_ind" );
464
465 #ifdef SNDCP_TRACE_ALL
466 TRACE_EVENT_P1("cia_decomp_ind->pcomp: %02x", cia_decomp_ind->pcomp);
467 #endif /* SNDCP_TRACE_ALL */
468
469 /*
470 * Is nsapi in ack mode?
471 */
472 sndcp_get_nsapi_ack(nsapi, &ack);
473
474 switch( GET_STATE(CIA) )
475 {
476 case CIA_DEFAULT:
477 sndcp_is_nsapi_header_compressed(nsapi, &compressed);
478 /*
479 * Only compress if pcomp in sn pdu is assigned to context.
480 */
481 sndcp_get_nsapi_sapi(nsapi, &sapi);
482 mg_get_sapi_pcomp_pntt(sapi,
483 pcomp,
484 &pntt);
485
486 mg_get_sapi_pntt_nsapi(sapi, pntt, nsapi, &pcomp_ok);
487
488 if (compressed && pcomp_ok && pcomp != 0) {
489 UBYTE packet_type = TYPE_COMPRESSED_TCP;
490
491 if (pcomp == sndcp_data->cia.cur_xid_block.vj.pcomp1) {
492 packet_type = TYPE_UNCOMPRESSED_TCP;
493 }
494 #ifndef _SNDCP_DTI_2_
495 temp_desc_list.list_len = cia_decomp_ind->desc_list2.list_len;
496 temp_desc_list.first = cia_decomp_ind->desc_list2.first;
497 cia_header_decomp(&temp_desc_list1, &packet_type);
498 cia_decomp_ind->desc_list2.list_len = temp_desc_list.list_len;
499 cia_decomp_ind->desc_list2.first = temp_desc_list.first;
500 #else /*_SNDCP_DTI_2_*/
501 cia_header_decomp(&cia_decomp_ind->desc_list2, &packet_type);
502 #endif /*_SNDCP_DTI_2_*/
503 if (packet_type != TYPE_IP) {
504 #ifdef SNDCP_TRACE_ALL
505 sndcp_data->cia.cia_decomp_ind_number[nsapi] --;
506 TRACE_EVENT_P1("number of cia_decomp_ind: % d",
507 sndcp_data->cia.cia_decomp_ind_number[nsapi]);
508 #endif /* SNDCP_TRACE_ALL */
509
510 MFREE_PRIM(cia_decomp_ind);
511 cia_decomp_ind = NULL;
512 /*
513 * Corupted segment, request next one.
514 */
515 TRACE_EVENT("WARNING DECOMP: Corupted segment, request next one!");
516 if (ack) {
517 sig_cia_sda_getdata(sapi, nsapi);
518 } else {
519 sig_cia_sd_getunitdata(sapi, nsapi);
520 }
521 return;
522 }
523 }
524 /*
525 * Is the cnf for sd or sda?
526 */
527 if (ack) {
528 sig_cia_sda_cia_decomp_ind(cia_decomp_ind, p_id);
529 } else {
530 sig_cia_sd_cia_decomp_ind(cia_decomp_ind, p_id);
531 }
532 break;
533 default:
534 TRACE_ERROR( "CIA_DECOMP_IND unexpected" );
535 MFREE_PRIM(cia_decomp_ind);
536 break;
537 }
538 } /* cia_cia_decomp_ind() */
539
540 #endif /* CF_FAST_EXEC */
541
542 /*
543 +------------------------------------------------------------------------------
544 | Function : cia_cia_comp_ind
545 +------------------------------------------------------------------------------
546 | Description : Handles the primitive CIA_COMP_IND
547 |
548 | Parameters : *cia_comp_ind - Ptr to primitive payload
549 |
550 +------------------------------------------------------------------------------
551 */
552 #ifndef CF_FAST_EXEC
553
554 GLOBAL void cia_cia_comp_ind ( T_CIA_COMP_IND *cia_comp_ind )
555 {
556 UBYTE nsapi = cia_comp_ind->pdu_ref.ref_nsapi;
557 BOOL ack = FALSE;
558
559 TRACE_FUNCTION( "cia_cia_comp_ind" );
560
561
562 #ifdef SNDCP_TRACE_ALL
563 switch (cia_comp_ind->packet_type) {
564 case TYPE_IP:
565 TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
566 cia_comp_ind->packet_type,
567 "TYPE_IP");
568 break;
569 case TYPE_UNCOMPRESSED_TCP:
570 TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
571 cia_comp_ind->packet_type,
572 "TYPE_UNCOMPRESSED_TCP");
573 break;
574 case TYPE_COMPRESSED_TCP:
575 TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
576 cia_comp_ind->packet_type,
577 "TYPE_COMPRESSED_TCP");
578 break;
579 case TYPE_ERROR:
580 TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
581 cia_comp_ind->packet_type,
582 "TYPE_ERROR");
583 break;
584 default:
585 TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
586 cia_comp_ind->packet_type,
587 "unknown");
588
589
590 }
591 #endif /* SNDCP_TRACE_ALL */
592
593 switch( GET_STATE(CIA) )
594 {
595 case CIA_DEFAULT:
596 /*
597 * Is the cnf for su or sua?
598 */
599 sndcp_get_nsapi_ack(nsapi, &ack);
600 if (ack) {
601 sig_cia_sua_cia_comp_ind(cia_comp_ind);
602 } else {
603 sig_cia_su_cia_comp_ind(cia_comp_ind);
604 }
605 break;
606 default:
607 TRACE_ERROR( "CIA_CIA_COMP_IND unexpected" );
608 sndcp_cl_desc3_free((T_desc3*)cia_comp_ind->desc_list3.first);
609 MFREE(cia_comp_ind);
610 break;
611 }
612 } /* cia_cia_comp_ind() */
613
614 #endif /* CF_FAST_EXEC */
615
616
617
618