diff src/g23m-gprs/sndcp/sndcp_ciap.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/sndcp/sndcp_ciap.c	Sun Jul 15 04:40:46 2018 +0000
@@ -0,0 +1,618 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :  GPRS (8441)
+|  Modul   :  sndcp_ciap.c
++-----------------------------------------------------------------------------
+|  Copyright 2002 Texas Instruments Berlin, AG
+|                 All rights reserved.
+|
+|                 This file is confidential and a trade secret of Texas
+|                 Instruments Berlin, AG
+|                 The receipt of or possession of this file does not convey
+|                 any rights to reproduce or disclose its contents or to
+|                 manufacture, use, or sell anything it may describe, in
+|                 whole, or in part, without the specific written consent of
+|                 Texas Instruments Berlin, AG.
++-----------------------------------------------------------------------------
+|  Purpose :  This modul is part of the entity SNDCP and implements all
+|             functions to handles the incoming primitives as described in
+|             the SDL-documentation (CIA-statemachine)
++-----------------------------------------------------------------------------
+*/
+
+
+#define ENTITY_SNDCP
+
+/*==== INCLUDES =============================================================*/
+
+#include "typedefs.h"  /* to get Condat data types */
+#include "vsi.h"       /* to get a lot of macros */
+#include "macdef.h"
+#include "gsm.h"       /* to get a lot of macros */
+#include "prim.h"      /* to get the definitions of used SAP and directions */
+
+#include "dti.h"
+
+#include "sndcp.h"     /* to get the global entity definitions */
+#include "sndcp_f.h"   /* to get the functions to access the global arrays*/
+
+#include <string.h>    /* to get memcpy() */
+#include "sndcp_mgf.h" /* to get the local functions of service mg */
+#include "sndcp_sus.h" /* to get signals to service su */
+#include "sndcp_suas.h"/* to get signals to service sua */
+#include "sndcp_sds.h" /* to get signals to service sd */
+#include "sndcp_sdas.h"/* to get signals to service sda */
+#include "sndcp_ciap.h"
+
+
+/*==== CONST ================================================================*/
+
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_vj_decomp
++------------------------------------------------------------------------------
+| Description : decompresses the TCP/IP header of the given packet
+|               (Van Jacobson algorithm). A part of this routine has been taken
+|               from implementation of University of California, Berkeley.
+|
+| Parameters  : com_buf - received packet, packet length, packet type
+|
+| Return      : new packet length
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+LOCAL USHORT cia_vj_decomp(struct comp_buf *cbuf)
+{
+  struct slcompress         *comp = &sndcp_data->cia.comp;
+  UBYTE                     *cp;     /* pointer to the compressed TCP/IP packet */
+  UBYTE                     hlen = 0;
+  ULONG                     change_mask = 0;
+  T_SNDCP_TCP_HEADER        *th;
+  struct cstate             *cs;
+  ULONG                     tmp;
+  USHORT                    th_off;
+
+  TRACE_FUNCTION( "cia_vj_decomp" );
+
+  switch (cbuf->p_type) {
+
+  case TYPE_UNCOMPRESSED_TCP:
+  {
+    UBYTE *hdr_ptr = (UBYTE*)cbuf->c_hdr;
+    UBYTE slot_nr   = hdr_ptr[9];
+    if (slot_nr >= sndcp_data->cia.comp.slots_to_use){
+      TRACE_EVENT_P2("ERROR DECOMP: slot_nr(%d) > slots_to_use(%d)",
+                     slot_nr, sndcp_data->cia.comp.slots_to_use);
+      comp->flags |= SLF_TOSS;
+      return (0);
+    }
+    /* set last received state */
+    comp->last_recv = slot_nr;
+    /* get related compressed state */
+    cs = &comp->rstate[comp->last_recv];
+    /* clear toss flag */
+    comp->flags &=~ SLF_TOSS;
+    /* set protocol type to TCP/IP */
+    hdr_ptr[9] = PROT_TCPIP;
+    /* get IP header length */
+    hlen = hdr_ptr[0] & HL_MASK;
+    /* get TCP header */
+    th_off = hdr_ptr[hlen*4 + 12];
+    th_off = (th_off & 0xf0) >> 4;
+    /* calculate IP+TCP header length  */
+    hlen += th_off;
+    hlen <<= 2;
+    /* copy TCP+IP header */
+    memcpy(cs->cs_ip, hdr_ptr, hlen);
+    cs->cs_ip->ip_sum = 0;
+    cs->cs_hlen = hlen;
+    return ((USHORT)cbuf->pack_len);
+  }
+
+  case TYPE_COMPRESSED_TCP:
+    break;
+
+  default:
+    comp->flags |= SLF_TOSS;
+    TRACE_EVENT_P1("ERROR DECOMP unknown packet type (%d)", cbuf->p_type);
+    return (0);
+  }
+
+  /* We've got a compressed packet. */
+  cp = (UBYTE *)cbuf->c_hdr;
+  change_mask = *cp++;
+  if (change_mask & NEW_C) {
+    /* Make sure the state index is in range, then grab the state.
+     * If we have a good state index, clear the 'discard' flag. */
+    if (*cp >= sndcp_data->cia.comp.slots_to_use){
+      comp->flags |= SLF_TOSS;
+      return (0);
+    }
+
+    comp->flags &=~ SLF_TOSS;
+    /* store connection number */
+    comp->last_recv = *cp++;
+  } else {
+    /* this packet has an implicit state index.  If we've
+     * had a line error since the last time we got an
+     * explicit state index, we have to toss the packet. */
+    if (comp->flags & SLF_TOSS) {
+      return (0);
+    }
+  }
+  /* get related connection state */
+  cs = &comp->rstate[comp->last_recv];
+  /* get IP header length */
+  hlen = (cs->cs_ip->ip_vhl & HL_MASK) << 2;
+  /* get TCP header */
+  th = (T_SNDCP_TCP_HEADER *)&((UBYTE *)cs->cs_ip)[hlen];
+  /* store new TCP check sum */
+  th->th_sum = sndcp_swap2((USHORT)((*cp << 8) | cp[1]));
+  cp += 2;
+  /* check if push bit is set */
+  if (change_mask & TCP_PUSH_BIT)
+    th->th_flags |= TH_PUSH;
+  else
+    th->th_flags &=~ TH_PUSH;
+
+  switch (change_mask & SPECIALS_MASK) {
+
+    case SPECIAL_I:
+    {
+      ULONG deltaL = sndcp_swap2(cs->cs_ip->ip_len) - cs->cs_hlen;
+      th->th_ack   = sndcp_swap4(sndcp_swap4(th->th_ack) + deltaL);
+      th->th_seq   = sndcp_swap4(sndcp_swap4(th->th_seq) + deltaL);
+    }
+      break;
+
+    case SPECIAL_D:
+      th->th_seq = sndcp_swap4(sndcp_swap4(th->th_seq)
+                   + sndcp_swap2(cs->cs_ip->ip_len)
+                   - cs->cs_hlen);
+      break;
+
+    /* no special case */
+    default:
+      /* urgend data field */
+      if (change_mask & NEW_U) {
+        th->th_flags |= TH_URG;
+        if (*cp == 0) {
+          th->th_urp = sndcp_swap2((USHORT)((cp[1] << 8) | cp[2]));
+          cp += 3;
+        } else {
+          th->th_urp = sndcp_swap2((USHORT)((ULONG)*cp++));
+        }
+      } else {
+        th->th_flags &=~ TH_URG;
+      }
+      /*
+       * window size
+       */
+      if (change_mask & NEW_W){
+        if (*cp == 0) {
+          th->th_win = sndcp_swap2((USHORT)(sndcp_swap2(th->th_win)
+                                 + ((cp[1] << 8) | cp[2])));
+          cp += 3;
+        } else {
+          th->th_win = sndcp_swap2((USHORT)(sndcp_swap2(th->th_win) + (ULONG)*cp++));
+        }
+      }
+      /*
+       * acknowledgement number
+       */
+      if (change_mask & NEW_A){
+        if (*cp == 0) {
+          th->th_ack = sndcp_swap4(sndcp_swap4(th->th_ack) + ((cp[1] << 8) | cp[2]));
+          cp += 3;
+        } else {
+          th->th_ack = sndcp_swap4(sndcp_swap4(th->th_ack) + (ULONG)*cp++);
+        }
+      }
+      /*
+       * sequence number
+       */
+      if (change_mask & NEW_S){
+        if (*cp == 0) {
+          (th->th_seq) = sndcp_swap4(sndcp_swap4(th->th_seq) + ((cp[1] << 8) | cp[2]));
+          cp += 3;
+        } else {
+          (th->th_seq) = sndcp_swap4(sndcp_swap4(th->th_seq) + (ULONG)*cp++);
+        }
+      }
+      break;
+  }
+  /*
+   * packet ID
+   */
+  if (change_mask & NEW_I) {
+    if (*cp == 0) {
+      cs->cs_ip->ip_id = sndcp_swap2((USHORT)(sndcp_swap2(cs->cs_ip->ip_id)
+                                         + ((cp[1] << 8) | cp[2])));
+      cp += 3;
+    } else {
+      cs->cs_ip->ip_id = sndcp_swap2((USHORT)(sndcp_swap2(cs->cs_ip->ip_id)
+                                                   + (ULONG)*cp++));
+    }
+  } else
+    cs->cs_ip->ip_id = sndcp_swap2((USHORT)(sndcp_swap2(cs->cs_ip->ip_id) + 1));
+
+  /*
+   * At this point, cp points to the first byte of data in the
+   * packet.  If we're not aligned on a 4-byte boundary, copy the
+   * data down so the ip & tcp headers will be aligned.  Then back up
+   * cp by the tcp/ip header length to make room for the reconstructed
+   * header (we assume the packet we were handed has enough space to
+   * prepend 120 bytes of header).  Adjust the length to account for
+   * the new header & fill in the IP total length.
+   */
+  tmp = cp - (UBYTE*)cbuf->c_hdr;
+  cbuf->pack_len -= cp - (UBYTE*)cbuf->c_hdr;
+  if ((UBYTE*)cbuf->c_hdr > cp){
+    /* we must have dropped some characters (crc should detect
+     * this but the old slip framing won't) */
+    comp->flags |= SLF_TOSS;
+    return (0);
+  }
+
+  cbuf->c_hdr    += tmp;
+  cbuf->hdr_len -= (USHORT)tmp;
+  tmp = (ULONG)cp & 3;
+  if (tmp) {
+    if (cbuf->pack_len > 0)
+      memcpy(cp - tmp, cp, cbuf->hdr_len);
+    cbuf->c_hdr -= tmp;
+    cp -= tmp;
+  }
+  cbuf->c_hdr -= cs->cs_hlen;
+  cp -= cs->cs_hlen;
+  cbuf->hdr_len  += cs->cs_hlen;
+  cbuf->pack_len += cs->cs_hlen;
+  cs->cs_ip->ip_len = sndcp_swap2(cbuf->pack_len);
+  memcpy(cp, cs->cs_ip, cs->cs_hlen);
+
+  /* recompute the ip header checksum */
+  {
+    USHORT *bp = (USHORT *)cp;
+
+    for (change_mask = 0; hlen > 0; hlen -= 2)
+      change_mask += *bp++;
+    change_mask = (change_mask & 0xffff) + (change_mask >> 16);
+    change_mask = (change_mask & 0xffff) + (change_mask >> 16);
+    ((T_SNDCP_IP_HEADER *)cp)->ip_sum = ~ (USHORT)change_mask;
+  }
+  return (cbuf->pack_len);
+}
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_header_decomp
++------------------------------------------------------------------------------
+| Description : de-compresses the TCP/IP header of the given packet
+|               (Van Jacobson algorithm)
+|
+| Parameters  : packet as desc_list, packet_type
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+#ifdef _SNDCP_DTI_2_
+GLOBAL void cia_header_decomp(T_desc_list2* desc_list, UBYTE* packet_type)
+{
+#else /*_SNDCP_DTI_2_*/
+GLOBAL void cia_header_decomp(T_desc_list* desc_list, UBYTE* packet_type)
+{
+#endif /*_SNDCP_DTI_2_*/
+
+  struct comp_buf     cbuf;
+  /* the length of decompressed header + payload */
+  USHORT              decomp_len;
+
+#ifdef _SNDCP_DTI_2_
+  T_desc2* desc = (T_desc2*) desc_list->first;
+  T_desc2* decomp_desc;
+  U8 *desc_buff = &desc->buffer[desc->offset];
+#else
+  T_desc*  desc = (T_desc*) desc_list->first;
+  T_desc*  decomp_desc;
+  U8 *desc_buff = &desc->buffer[0];
+#endif
+
+  TRACE_FUNCTION( "cia_header_decomp" );
+
+#ifdef SNDCP_TRACE_BUFFER
+  TRACE_EVENT("INFO DECOMP: Input Packet");
+  sndcp_trace_desc_list(desc_list);
+#endif /* SNDCP_TRACE_BUFFER */
+
+  switch(*packet_type)
+  {
+  /*
+   * packet type IP: do nothing
+   */
+  case TYPE_IP:
+    TRACE_EVENT("INFO DECOMP: TYPE_IP");
+    *packet_type = TYPE_IP;
+    break;
+
+  /*
+   * packet type uncompressed TCP
+   */
+  case TYPE_UNCOMPRESSED_TCP:
+    TRACE_EVENT("INFO DECOMP: TYPE_UNCOMPRESSED_TCP");
+    cbuf.c_hdr    = (ULONG)&desc_buff[0];
+    cbuf.hdr_len  = desc->len;
+    cbuf.pack_len = desc_list->list_len;
+    cbuf.p_type   = *packet_type;
+    decomp_len = cia_vj_decomp(&cbuf);
+    if(decomp_len == 0)
+    {
+      TRACE_EVENT("ERROR DECOMP: decomp_len = 0, TYPE_ERROR");
+      *packet_type = TYPE_ERROR;
+    }
+    else
+    {
+      *packet_type = TYPE_IP;
+     }
+    break;
+
+  /*
+   * packet type compressed TCP
+   */
+  case TYPE_COMPRESSED_TCP:
+    TRACE_EVENT("INFO DECOMP: TYPE_COMPRESSED_TCP");
+    /*
+     * Because we don't know the length of compressed TCP/IP header,
+     * we have to copy max. 40 bytes, wich sure contain compressed
+     * header + maybe some payload bytes.
+     */
+    cbuf.hdr_len = (desc->len < 40) ? desc->len : 40;
+    cbuf.c_hdr = (ULONG)&sndcp_data->cia.comp.
+                               tcpip_hdr[TMP_HDR_LEN-1-cbuf.hdr_len];
+    cbuf.pack_len = desc_list->list_len;
+    cbuf.p_type   = *packet_type;
+    memcpy((UBYTE*)cbuf.c_hdr, &desc_buff[0], cbuf.hdr_len);
+    decomp_len = cia_vj_decomp(&cbuf);
+    if(decomp_len != 0)
+    {
+      /*
+       * Build destination descriptor list
+       */
+      USHORT offset = cbuf.pack_len - desc_list->list_len;
+#ifdef _SNDCP_DTI_2_
+      MALLOC(decomp_desc, (USHORT)(sizeof(T_desc2) - 1 + desc->len + offset));
+#else
+      MALLOC(decomp_desc, (USHORT)(sizeof(T_desc) - 1 + desc->len + offset));
+#endif
+      /* copy compressed header + piece of data */
+      memcpy(&decomp_desc->buffer[0], (UBYTE*)cbuf.c_hdr, cbuf.hdr_len);
+      /* copy the rest of data */
+      memcpy(&decomp_desc->buffer[cbuf.hdr_len],
+             &desc->buffer[cbuf.hdr_len-offset],
+              desc->len-cbuf.hdr_len+offset);
+      decomp_desc->next   = desc->next;
+      decomp_desc->len  = desc->len + offset;
+#ifdef _SNDCP_DTI_2_
+      decomp_desc->size = desc->size + offset;
+      decomp_desc->offset = desc->offset;
+#endif
+      desc_list->first  = (ULONG)decomp_desc;
+      desc_list->list_len = desc_list->list_len - desc->len + decomp_desc->len;
+      MFREE(desc);
+      *packet_type = TYPE_IP;
+    }
+    else
+    {
+      TRACE_EVENT("ERROR DECOMP: decomp_len = 0, TYPE_ERROR");
+      *packet_type = TYPE_ERROR;
+    }
+    break;
+
+  default:
+      TRACE_EVENT_P1("ERROR DECOMP: unexpected packet type: %d", packet_type);
+      *packet_type = TYPE_ERROR;
+    break;
+
+  }
+
+} /* cia_header_decomp() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_cia_decomp_ind
++------------------------------------------------------------------------------
+| Description : Handles the primitive CIA_DECOMP_IND
+|
+| Parameters  : *cia_decomp_ind - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void cia_cia_decomp_ind ( T_CIA_DECOMP_IND *cia_decomp_ind )
+{
+  UBYTE nsapi = cia_decomp_ind->pdu_ref.ref_nsapi;
+  BOOL ack = FALSE;
+  BOOL compressed = FALSE;
+  UBYTE pcomp = cia_decomp_ind->pcomp;
+  UBYTE pntt = 0;
+  UBYTE sapi = 0;
+  BOOL pcomp_ok = FALSE;
+
+#ifndef _SNDCP_DTI_2_
+  T_desc_list temp_desc_list;
+#endif /*_SNDCP_DTI_2_*/
+
+  UBYTE p_id = DTI_PID_IP;
+
+  TRACE_FUNCTION( "cia_cia_decomp_ind" );
+
+#ifdef SNDCP_TRACE_ALL
+  TRACE_EVENT_P1("cia_decomp_ind->pcomp: %02x", cia_decomp_ind->pcomp);
+#endif /* SNDCP_TRACE_ALL */
+
+  /* 
+   * Is nsapi in ack mode?
+   */
+  sndcp_get_nsapi_ack(nsapi, &ack);
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      sndcp_is_nsapi_header_compressed(nsapi, &compressed);
+      /*
+       * Only compress if pcomp in sn pdu is assigned to context.
+       */
+      sndcp_get_nsapi_sapi(nsapi, &sapi);
+      mg_get_sapi_pcomp_pntt(sapi,
+                             pcomp,
+                             &pntt);
+
+      mg_get_sapi_pntt_nsapi(sapi, pntt, nsapi, &pcomp_ok);
+
+      if (compressed && pcomp_ok && pcomp != 0) {
+        UBYTE packet_type = TYPE_COMPRESSED_TCP;
+
+        if (pcomp == sndcp_data->cia.cur_xid_block.vj.pcomp1) {
+          packet_type = TYPE_UNCOMPRESSED_TCP;
+        }
+#ifndef _SNDCP_DTI_2_
+        temp_desc_list.list_len = cia_decomp_ind->desc_list2.list_len;
+        temp_desc_list.first = cia_decomp_ind->desc_list2.first;
+        cia_header_decomp(&temp_desc_list1, &packet_type);
+        cia_decomp_ind->desc_list2.list_len = temp_desc_list.list_len;
+        cia_decomp_ind->desc_list2.first = temp_desc_list.first;
+#else  /*_SNDCP_DTI_2_*/
+        cia_header_decomp(&cia_decomp_ind->desc_list2, &packet_type);
+#endif /*_SNDCP_DTI_2_*/
+        if (packet_type != TYPE_IP) {
+#ifdef SNDCP_TRACE_ALL
+          sndcp_data->cia.cia_decomp_ind_number[nsapi] --;
+          TRACE_EVENT_P1("number of cia_decomp_ind: % d",
+                         sndcp_data->cia.cia_decomp_ind_number[nsapi]);
+#endif /* SNDCP_TRACE_ALL */
+
+          MFREE_PRIM(cia_decomp_ind);
+          cia_decomp_ind = NULL;
+          /*
+           * Corupted segment, request next one.
+           */
+          TRACE_EVENT("WARNING DECOMP: Corupted segment, request next one!");
+          if (ack) {
+            sig_cia_sda_getdata(sapi, nsapi);
+          } else {
+            sig_cia_sd_getunitdata(sapi, nsapi);
+          }
+          return;
+        }
+      }
+      /*
+       * Is the cnf for sd or sda?
+       */
+      if (ack) {
+        sig_cia_sda_cia_decomp_ind(cia_decomp_ind, p_id);
+      } else {
+        sig_cia_sd_cia_decomp_ind(cia_decomp_ind, p_id);
+      }
+      break;
+    default:
+      TRACE_ERROR( "CIA_DECOMP_IND unexpected" );
+      MFREE_PRIM(cia_decomp_ind); 
+      break;
+  }
+} /* cia_cia_decomp_ind() */
+
+#endif /* CF_FAST_EXEC */
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_cia_comp_ind
++------------------------------------------------------------------------------
+| Description : Handles the primitive CIA_COMP_IND
+|
+| Parameters  : *cia_comp_ind - Ptr to primitive payload
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void cia_cia_comp_ind ( T_CIA_COMP_IND *cia_comp_ind )
+{
+  UBYTE nsapi = cia_comp_ind->pdu_ref.ref_nsapi;
+  BOOL ack = FALSE;
+
+  TRACE_FUNCTION( "cia_cia_comp_ind" );
+
+
+#ifdef SNDCP_TRACE_ALL
+  switch (cia_comp_ind->packet_type) {
+  case TYPE_IP:
+    TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
+                   cia_comp_ind->packet_type,
+                   "TYPE_IP");
+    break;
+  case TYPE_UNCOMPRESSED_TCP:
+    TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
+                   cia_comp_ind->packet_type,
+                   "TYPE_UNCOMPRESSED_TCP");
+    break;
+  case TYPE_COMPRESSED_TCP:
+    TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
+                   cia_comp_ind->packet_type,
+                   "TYPE_COMPRESSED_TCP");
+    break;
+  case TYPE_ERROR:
+    TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
+                   cia_comp_ind->packet_type,
+                   "TYPE_ERROR");
+    break;
+  default:
+    TRACE_EVENT_P2("cia_comp_ind->packet_type: %02x (%s)",
+                   cia_comp_ind->packet_type,
+                   "unknown");
+
+
+  }
+#endif /* SNDCP_TRACE_ALL */
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      /*
+       * Is the cnf for su or sua?
+       */
+      sndcp_get_nsapi_ack(nsapi, &ack);
+      if (ack) {
+        sig_cia_sua_cia_comp_ind(cia_comp_ind);
+      } else {
+        sig_cia_su_cia_comp_ind(cia_comp_ind);
+      }
+      break;
+    default:
+      TRACE_ERROR( "CIA_CIA_COMP_IND unexpected" );
+      sndcp_cl_desc3_free((T_desc3*)cia_comp_ind->desc_list3.first);
+      MFREE(cia_comp_ind); 
+      break;
+  }
+} /* cia_cia_comp_ind() */
+
+#endif /* CF_FAST_EXEC */
+
+
+
+