/*===========================================================================
FUNCTION DIAGCOMM_SMD_SEND

DESCRIPTION
  Sends a packet over SMD channel
  
PARAMETERS
  req_pkt - packet to send
  pkt_len - length of 'req_pkt'
  port_num - channel to send pkt on
  
RETURN VALUE
  None
  
===========================================================================*/
void diagcomm_smd_send( void *req_pkt, uint16 pkt_len, 
                        diagcomm_enum_port_type port_num )
{
  diagcomm_io_tx_params_type tx_params;
  dsm_item_type *app_req_item_ptr = NULL;
  
  if( diagcomm_status() && diagcomm_smd_status(port_num) )
  {
    ASSERT(req_pkt != NULL);

    if( dsm_pushdown_tail(&app_req_item_ptr, req_pkt, pkt_len, 
        DSM_DIAG_SMD_RX_ITEM_POOL) == pkt_len )
    { 
      tx_params.dsm_ptr = app_req_item_ptr;
      diagcomm_io_transmit( &diagcomm_io_conn[DIAGCOMM_PORT_SMD][port_num], &tx_params, FALSE );
      diag_sleep_vote(DIAG_SLEEP_DIAG, TRUE);
    }
    else
    {
      dsm_free_packet(&app_req_item_ptr);
      MSG(MSG_SSID_DIAG, MSG_LEGACY_HIGH,
            "diagcomm_smd_send - Ran out of DSM items");
    }
  }
} /* diagcomm_smd_send */
示例#2
0
文件: dsrlpdel.c 项目: bgtwoigu/1110
/*===========================================================================
FUNCTION       DSRLPDEL_ADD

DESCRIPTION    Adds an element to the frame detection array.  Puts it in
               order in the array.

DEPENDENCIES   None

RETURN VALUE   None

SIDE EFFECTS   None
===========================================================================*/
void dsrlpdel_add
(
  dsrlpi_sess_ctl_blk_type *rscb_ptr,
  dsm_item_type            *fr_item_ptr,
  dsrlpi_curr_fr_info_type *curr_info_ptr
)
{
  rlpdel_fr_array_type     *fr_arr_ptr;  /* points to array to add to      */
  rlpdel_fr_detect_type    *fr_detect_ptr;/* points to delay frame struct  */
  byte      curr_idx;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  ASSERT(rscb_ptr->state.del_fr_id < DSRLPI_MAX_SESSIONS);
  ASSERT(rlpdel_fr_detect[rscb_ptr->state.del_fr_id].used == TRUE);

  if (fr_item_ptr == NULL)
  {
    ERR("Passed null item ptr",0,0,0);
    return;
  }

  fr_detect_ptr = &(rlpdel_fr_detect[rscb_ptr->state.del_fr_id]);
  fr_arr_ptr    = &(fr_detect_ptr->del_fr_arr[fr_detect_ptr->add_idx]);

  if (fr_arr_ptr->index >= RLP_MAX_FWD_PDU)
  {
    ERR("too many items in del. fr array",0,0,0);
    dsm_free_packet(&fr_item_ptr);
    return;
  }

  curr_idx = fr_arr_ptr->index;
  fr_arr_ptr->index++;

  /*-------------------------------------------------------------------------
     Insert this frame into the array, in sorted order.  If the loop 
     terminates, then this frame goes into the first slot.
  -------------------------------------------------------------------------*/
  while(curr_idx > 0)
  {
    if(DSRLPSEQ_GE_SEQ_CHECK(curr_info_ptr->seq_num,
                          fr_arr_ptr->fr_arr[curr_idx - 1].curr_info.seq_num,
                          rscb_ptr->ver_ptr->seq_modulus))
    {
      fr_arr_ptr->fr_arr[curr_idx].fr_item_ptr = fr_item_ptr;
      fr_arr_ptr->fr_arr[curr_idx].curr_info = *curr_info_ptr;
      return;
    }
    else
    {
      fr_arr_ptr->fr_arr[curr_idx] = fr_arr_ptr->fr_arr[curr_idx - 1];
      curr_idx--;
    }
  } /* while */ 

  fr_arr_ptr->fr_arr[0].fr_item_ptr = fr_item_ptr;
  fr_arr_ptr->fr_arr[0].curr_info   = *curr_info_ptr;
} /* dsrlpdel_add() */
/*===========================================================================

FUNCTION dsmutili_new_packet

DESCRIPTION
    Based on the dsm_size_requested, this function will allocate a dsm items
    which can hold 'dsm_size_requested'.
    This function will do necessary chaining of DSM items if requested size
    doesnt fit in one DSM item.
    
    Total Size of the DSM chain is expected to be equal or greater than
    requested size.

DEPENDENCIES
    None

PARAMETERS
  pool_id - DSM Pool from which new item should be allocated

  dsm_size_requested - requested size of the buffer

RETURN VALUE
  Chain of DSM pointers w/ empty payload such that total size of chain is 
  equal to or greater than dsm_size_requested. It returns NULL if it fails 
  to allocate requested size.

SIDE EFFECTS
  Caller of this function is expected to have necessary handling whenever this
  function returns chain of DSM items.

===========================================================================*/
dsm_item_type *dsmutili_new_packet
(
  dsm_mempool_id_type pool_id,
  uint32 dsm_size_requested,
  const char * file,
  uint32 line
)
{
  dsm_item_type *head_dsm_ptr = NULL, *tail_dsm_ptr = NULL;
  dsm_item_type *allocated_dsm_ptr = NULL;
  int16 remaining_size = (int16) dsm_size_requested;
  uint16 allocated_dsm_size = DSM_POOL_ITEM_SIZE(pool_id);

  while (remaining_size > 0)
  {
    if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(pool_id, file, line)))
    {
      /* No free DSM items are available in a given pool id,
         exit out of the loop */
      break;
    }

    if (remaining_size != (int16) dsm_size_requested)
    {
      tail_dsm_ptr->pkt_ptr = allocated_dsm_ptr;
      tail_dsm_ptr = allocated_dsm_ptr;
    }
    else
    {
      head_dsm_ptr = allocated_dsm_ptr;
      tail_dsm_ptr = allocated_dsm_ptr;
    }

    /* update remaining size */
    remaining_size -= allocated_dsm_size;
  }

  /* check whether a given pool has run out of the free items.
     If yes, then free any allocated dsm items */
  if (NULL != allocated_dsm_ptr)
  {
    return(head_dsm_ptr);
  }
  else
  {
    dsm_free_packet(&head_dsm_ptr);
    head_dsm_ptr = NULL;
    return(head_dsm_ptr);
  }
}
示例#4
0
文件: dssicmp.c 项目: bgtwoigu/1110
/*===========================================================================

FUNCTION DSSICMP_CLOSE()

DESCRIPTION
  This function is the ICMP specific dss_close() function.  It simply sets 
  the socket state to DSSOCKI_NULL and frees up the socket control block and
  related data structures.

DEPENDENCIES
  None.

RETURN VALUE
  DSS_SUCCESS on success; DSS_ERROR otherwise. 

SIDE EFFECTS
  None. 
  
===========================================================================*/
extern sint15 dssicmp_close
(
  struct scb_s* scb_ptr,     /* Ptr to socket control block for the socket */
  sint15 *dss_errno                               /* error condition value */
)
{
  struct icmp_cb *icmp_cb_ptr;              /* ICMP protocol control block */
  dsm_item_type *item_ptr;                           /* temporary item ptr */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*-------------------------------------------------------------------------
    Assert that a valid ptr to a dss_errno variable was specified - Prevents
    dereferencing of NULL ptrs.
  -------------------------------------------------------------------------*/
    if (dss_errno == NULL) 
    {
      ASSERT(0);
      return(DSS_ERROR);
    }
    *dss_errno = DSS_SUCCESS;

    icmp_cb_ptr = (struct icmp_cb *) scb_ptr->protocol_ctl_blk.icb;

    /*-------------------------------------------------------------------------
      Free the receive queue for the ICMP control block.
     ------------------------------------------------------------------------*/
    while(( item_ptr = (dsm_item_type *) q_get( &(icmp_cb_ptr->rcvq))) != NULL)
    {
      dsm_free_packet(&item_ptr);
    }

    /*-------------------------------------------------------------------------
      Free the ICMP control block.
     ------------------------------------------------------------------------*/
    dssicmpi_free_icmp_cb(icmp_cb_ptr);

    /*-------------------------------------------------------------------------
      Free the socket control block.
    ------------------------------------------------------------------------*/
    dssocki_freescb(scb_ptr);

    return (DSS_SUCCESS);
} /* dssicmp_close () */
/*===========================================================================

FUNCTION DSM_SDU_TO_PKT_CHAIN_BYTE
DESCRIPTION
  Copy the given SDU to an allocating DSM item packet in size bytes.

DEPENDENCIES
  None.

RETURN VALUE
  The allocated dsm item packet chain pointer. 
  If failed, it returns NULL pointer.

SIDE EFFECTS
  None

===========================================================================*/
dsm_item_type *dsm_sdu_to_pkt_chain_byte
(
  void   *buf,                    /* Ptr. to bytes to copy                */
  word    size                    /* size in bytes of copying             */
)
{
  dsm_item_type *pkt_head_ptr = NULL; /* Address of ptr to head of packet  */

  if ((dsm_pushdown_tail(&pkt_head_ptr, 
                         buf, 
                         size, 
                         DSM_DS_SMALL_ITEM_POOL)) != size)
  {
    /* Failed to allocated needed dsm items. Release those dsm    */
    /* item being allocated and set pkt_head_ptr to NULL          */
    dsm_free_packet(&pkt_head_ptr);
    pkt_head_ptr = NULL;
    MSG(MSG_SSID_DFLT, MSG_LEGACY_ERROR,"Failed to obtain enough memory");
  }
  return (pkt_head_ptr);
}
示例#6
0
文件: dsrlpdel.c 项目: bgtwoigu/1110
/*===========================================================================
FUNCTION       DSRLPDEL_RESET

DESCRIPTION    Cleans up the arrays, and resets struct back to initial state.

DEPENDENCIES   None

RETURN VALUE   NONE

SIDE EFFECTS   None
===========================================================================*/
void dsrlpdel_reset
(
  uint32  rlpdel_id
)
{
  rlpdel_fr_array_type*       fr_arr_ptr;  /* points to struct to clean up */
  word                        i, j;        /* for loop indices             */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  ASSERT(rlpdel_id < DSRLPI_MAX_SESSIONS);
  ASSERT(rlpdel_fr_detect[rlpdel_id].used == TRUE);

  for (i = 0; i < RLPDEL_ARR_SIZ; i++)
  {
    fr_arr_ptr = &(rlpdel_fr_detect[rlpdel_id].del_fr_arr[i]);
    for( j = 0; j < fr_arr_ptr->index; j++)
    {
      dsm_free_packet( &( fr_arr_ptr->fr_arr[j].fr_item_ptr));
    }
    fr_arr_ptr->index = 0;
  }

  rlpdel_fr_detect[rlpdel_id].add_idx =0;
  rlpdel_fr_detect[rlpdel_id].remove_idx =0;
}
示例#7
0
sint15 send_tcp
(
  register struct tcb  *tcb,            /* ptr to TCP Control Block        */
  dsm_item_type        *new_item_ptr   /* ptr to data item for TCP output */
)
{
  word          cnt;                 /* holds count of new data bytes      */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#ifdef FEATURE_DSM_MEM_CHK
  /*---------------------------------------------------------
   Set tracer to indicate where the item is being stored
  ---------------------------------------------------------*/
  new_item_ptr->tracer = DSM_TCP_SNDQ;
#endif
  if(tcb == NULL || new_item_ptr == NULL)
  {
    dsm_free_packet( &new_item_ptr);
    return -1;
  }
  cnt = 0;
  switch(tcb->state)
  {
    case TCP_CLOSED:
      dsm_free_packet( &new_item_ptr);
      return -1;

    case TCP_LISTEN:
      /* --------------------------------------------------------------
        If any remote address is 0, then it is a passive connection (LtoM).
        We stay in LISTEN state till we receive TCP packets from the IWF.
        Earlier the remote address was set to 0 in psmgr.c, so we enter
        the if when we are in passive mode and don't have dest. port #
        yet
      ----------------------------------------------------------------*/

      if(tcb->conn.remote.address == 0 || tcb->conn.remote.port == 0)
      {
        /* Save data for later */
        cnt = append_to_sndq( tcb, new_item_ptr);
        break;
      }
      /* Change state from passive to active */
      tcb->flags.active = 1;
      send_syn(tcb);
      setstate(tcb,TCP_SYN_SENT);      /* Note fall-thru */

    case TCP_SYN_SENT:
    case TCP_SYN_RECEIVED:
    case TCP_ESTABLISHED:
    case TCP_CLOSE_WAIT:
      cnt = append_to_sndq( tcb, new_item_ptr);
      tcp_output(tcb);
      break;

    case TCP_FINWAIT1:
    case TCP_FINWAIT2:
    case TCP_CLOSING:
    case TCP_LAST_ACK:
    case TCP_TIME_WAIT:
      dsm_free_packet( &new_item_ptr);
      return -1;
  }
  return cnt;
}
示例#8
0
文件: dssicmp.c 项目: bgtwoigu/1110
/*===========================================================================

FUNCTION DSSICMP_READ()

DESCRIPTION
  Reads 'nbytes' bytes into the buffer from the ICMP transport.  Fills in
  address structure with values from who sent the data in fromaddr.
  This function asserts that fromaddr is not NULL. This function is the 
  ICMP specific dss_recvfrom()

DEPENDENCIES
  None. 

PARAMETERS
  struct scb_s* scb_ptr      -  Ptr to socket control block for the socket
  void   *buffer             -  user buffer from which to copy the data 
  uint16 nbytes              -  number of bytes app wants to read
  struct sockaddr_in *fromaddr  -  source address 
  sint15 *dss_errno          -  error condition value 

RETURN VALUE
  n - the number of bytes to be written, which could be less than the number
      of bytes specified.

  On error, return DSS_ERROR and places the error condition value in
  *dss_errno.

  Errno Values
  ------------
  DS_EWOULDBLOCK      operation would block

SIDE EFFECTS
  None.

===========================================================================*/
extern sint15 dssicmp_read
(
  struct scb_s* scb_ptr,     /* Ptr to socket control block for the socket */
  struct iovec * iov,         /* user buffer from which to copy the data   */
  uint16         iovcount,     /* length of the iovec array                */
  struct sockaddr_in *fromaddr,                          /* source address */
  sint15 *dss_errno                               /* error condition value */
)
{
  struct icmp_cb *icmp_cb_ptr;              /* ICMP protocol control block */
  dsm_item_type *item_ptr;         /* ptr to head of dsm memory pool items */
  uint16 cnt=0;                                /* tmp # of bytes retrieved */
  uint16 bytes_read =0;                    /* # of bytes to read from rcvq */
  uint16 read_cnt=0;              /* # of bytes read in each iteration     */
  uint16 payload_len=0;                        /* packet length            */
  int    i;                                  /* local loop index           */
  uint16 bytes_requested;        /* # of bytes requested in each iteration */

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  MSG_LOW("In dssicmp_read()", 0, 0, 0);
  /*-------------------------------------------------------------------------
    Ensure that the "from address" is not NULL.  This function fills in this
    structure, thus, needs to ASSERT against dereferencing a NULL pointer.
  ------------------------------------------------------------------------*/
  ASSERT( fromaddr != NULL);

  /*-------------------------------------------------------------------------
    Set the socket and ICMP control block pointers, and set the family to
    AF_INET.
  -------------------------------------------------------------------------*/
  icmp_cb_ptr = scb_ptr->protocol_ctl_blk.icb;
  fromaddr->sin_family = AF_INET;
  MSG_LOW("ICMP CB pointer successfully set", 0, 0, 0);

  /*-------------------------------------------------------------------------
    Check if there is anything in the ICMP receive queue. If not, return
    DS_EWOULDBLOCK.
  -------------------------------------------------------------------------*/
  if ( (item_ptr = (dsm_item_type *) q_get( (&(icmp_cb_ptr->rcvq)))) == NULL)
  {
    MSG_LOW("Nothing on ICMP revq", 0, 0, 0);
    *dss_errno = DS_EWOULDBLOCK;
    return (DSS_ERROR);
  }
  MSG_LOW("There is indeed something on the ICMP rcvq", 0, 0, 0);

  /*-------------------------------------------------------------------------
    Extract the payload length, server's IP address and store in fromaddr.  
    ASSERT that bytes to read, are equal to the number of bytes pulled up.
    The port field will be undefined in the fromaddr structure returned to
    the application. 
  -------------------------------------------------------------------------*/
  cnt = dsm_pullup(&item_ptr, &(fromaddr->sin_addr), 
                   sizeof(fromaddr->sin_addr));
  ASSERT( cnt == sizeof(fromaddr->sin_addr) );
  MSG_MED("extracted server's IP %x", fromaddr->sin_addr.s_addr, 0, 0);

  /*-------------------------------------------------------------------------
    Extract the number of bytes which the application wants to read.
  -------------------------------------------------------------------------*/
  payload_len = dsm_length_packet( item_ptr );
  for(i=0;i< iovcount && payload_len > 0 ; i++)
  { 
    /*-----------------------------------------------------------------------
      Extract the number of bytes which the application wants to read.
      -----------------------------------------------------------------------*/
    bytes_requested = MIN( payload_len, iov[i].iov_len);
    if(bytes_requested > 0)
    {
      read_cnt = dsm_pullup( &(item_ptr), iov[i].iov_base, bytes_requested);
    }

    /*-----------------------------------------------------------------------
      ASSERT that we read the expected number of bytes from the buffer.
      -----------------------------------------------------------------------*/
    ASSERT(read_cnt == bytes_requested);
    payload_len -= read_cnt;
    bytes_read += read_cnt;
    read_cnt = 0;
  }
 

  if (payload_len > 0 ) 
  {
    ERR("User provided buffer is smaller than received datagram (%d bytes)",
	bytes_read + payload_len, 0, 0);
  }

  MSG_LOW("Successfully read nbytes of data in DSSICMP_READ", 0, 0, 0);

  /*-------------------------------------------------------------------------
    Free the packet in dsm buffer. 
  -------------------------------------------------------------------------*/
  dsm_free_packet ( &item_ptr );
  MSG_LOW("Packet is successfully freed in DSSICMP_READ", 0, 0, 0);
  
  /*-------------------------------------------------------------------------
    Check if there are any remaining ICMP packets in the receive queue. Set
    the readable flag to FALSE, if there are no remaining ICMP packets.  
    Access to global SCB array item is protected through 
    INTLOCK()/INTFREE().
  -------------------------------------------------------------------------*/
  if ( (item_ptr = (dsm_item_type *) q_check( &(icmp_cb_ptr->rcvq))) == NULL)
  {
    INTLOCK();
    scb_ptr->data_available = FALSE;
    INTFREE();
  }

  /*-------------------------------------------------------------------------
    Convert the server IP address into the Network byte order. 
    Note, only the IP address is in host order, the port number is not.
  -------------------------------------------------------------------------*/
  (fromaddr->sin_addr).s_addr =  dss_htonl( (fromaddr->sin_addr).s_addr);

  /*-------------------------------------------------------------------------
    Return the number of bytes read from the buffer.
  -------------------------------------------------------------------------*/
  MSG_LOW("DONE ICMPREAD", 0, 0, 0);
  return ( (sint15) bytes_read); 

} /* dssudp_read() */
示例#9
0
/*===========================================================================
FUNCTION LCP_CHECK()

DESCRIPTION
  This function will Check the options, updating the working values.

DEPENDENCIES
  None

RETURN VALUE
  Returns -1 if ran out of data, ACK/NAK/REJ as appropriate.

SIDE EFFECTS
  None
===========================================================================*/
static int lcp_check
(
  ppp_fsm_type      *fsm_ptr,
  struct option_hdr *ohp,
  dsm_item_type    **bpp,
  int                request
)
{
  lcp_value_type * lworkp; 
  lcp_value_type * rworkp; 
  ppp_fsm_side_type * side_p;
  lcp_value_type * s_want_ptr;
  lcp_value_type * s_work_ptr;
  int used = 0;
  int option_result = CONFIG_ACK;   /* Assume good values   */
  int n_type = 0;
  int16 rx_chap_digest; /* chap digest from peer */

  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

  if( bpp == NULL )
  {
    MSG_ERROR("Invalid DSM", 0, 0, 0);
    return -1;
  }

  if( fsm_ptr == NULL || 
      ohp == NULL || 
      ohp->length < OPTION_HDR_LEN ||
      fsm_ptr->device >= PPP_MAX_DEV )
  {
    MSG_ERROR("Invalid args", 0, 0, 0);
    dsm_free_packet(bpp);
    return -1;
  }

  used = ohp->length - OPTION_HDR_LEN; 
  n_type = fsm_n_option(fsm_ptr->pdc,ohp->type);
  lworkp = (lcp_value_type *)fsm_ptr->local.work_pdv;
  rworkp = (lcp_value_type *)fsm_ptr->remote.work_pdv;
  side_p =
     (ppp_fsm_side_type *)(request ? &(fsm_ptr->remote) : &(fsm_ptr->local));
  s_want_ptr = (lcp_value_type *)side_p->want_pdv;
  s_work_ptr = (lcp_value_type *)side_p->work_pdv;

  /*-------------------------------------------------------------------------
    see if we allow this option
  -------------------------------------------------------------------------*/
  if (ohp->type > LCP_OPTION_LIMIT        ||
      ohp->length < option_length[n_type] ||
      !((side_p->will | side_p->want) & (1 << n_type)))
  {
    /*-----------------------------------------------------------------------
      toss any bytes in option
    -----------------------------------------------------------------------*/
    while( used-- > 0 )
    {
      if ( dsm_pull8(bpp) == -1 )
      {
        return -1;
      }
    }
    return CONFIG_REJ;

  } /* if(unsupported option) */

  switch(ohp->type)
  {
  case LCP_MRU: /* max receive unit */
    s_work_ptr->mru = dsm_pull16(bpp);
    used -= 2;

    /*-----------------------------------------------------------------------
      Check if new value is appropriate
   -----------------------------------------------------------------------*/
    if(s_work_ptr->mru < LCP_MRU_LO)
    {
      s_work_ptr->mru   = LCP_MRU_LO;
      option_result = CONFIG_NAK;
    }
    else if (s_work_ptr->mru > LCP_MRU_HI)
    {
      s_work_ptr->mru = LCP_MRU_HI;
      option_result = CONFIG_NAK;
    }
      
    if(request                    &&
       (side_p->want & LCP_N_MRU) &&
       s_work_ptr->mru > s_want_ptr->mru)
    {
      /*---------------------------------------------------------------------
        send a smaller packet anyway
      -----------------------------------------------------------------------*/
      s_work_ptr->mru = s_want_ptr->mru;
    }
    break;

  case LCP_ACCM: /* async control character map */
    s_work_ptr->accm = dsm_pull32(bpp);
    used -= 4;

    /*-----------------------------------------------------------------------
      Remote host may ask to escape more control characters than we require,
      but must escape at least the control chars that we require.
    -----------------------------------------------------------------------*/
    if ((side_p->want & LCP_N_ACCM) &&
        s_work_ptr->accm != (s_work_ptr->accm | s_want_ptr->accm))
    {
      s_work_ptr->accm |= s_want_ptr->accm;
      option_result = CONFIG_NAK;
    }
    break;

  case LCP_AP: /* Authentication protocol */
    s_work_ptr->authentication = dsm_pull16(bpp); /* get the protocol */
    used -= 2;

    /*-----------------------------------------------------------------------
      Check if requested authentication protocol is PAP or CHAP or NONE
    -----------------------------------------------------------------------*/
    switch (s_work_ptr->authentication)
    {
    case PPP_PAP_PROTOCOL:
      /*---------------------------------------------------------------------
        Setting it to send PAP pkts in auth. phase.
      ---------------------------------------------------------------------*/
      ppp_cb_array[fsm_ptr->device].auth.mode = PPP_DO_PAP;
      MSG_MED(" Received Config. Req. with PAP option",0,0,0);
      break;

    case PPP_CHAP_PROTOCOL:
      /*---------------------------------------------------------------------
        Setting it to send CHAP pkts in auth. phase.
      ---------------------------------------------------------------------*/
      ppp_cb_array[fsm_ptr->device].auth.mode  = PPP_DO_CHAP;

      /*---------------------------------------------------------------------
        In the incoming packet the CHAP protocol has algorithm field attached
        to it, i.e. C223 for CHAP and 05 for MD5 or 80 for MD4.  Since the
        current implementation implements only MD5, check if the algorithm is
        MD5.

        Since we pulled out one more byte from the incoming packet reduce the
        used field by one.

        If the algorithm is not MD5, then send a Config NAK to the base
        station and request for the MD5.
      ---------------------------------------------------------------------*/
      rx_chap_digest = dsm_pull8(bpp);
      if(rx_chap_digest == -1)
      {
        return -1;
      }
      used--;
      if((s_work_ptr->chap_digest = (uint8)rx_chap_digest) != PPP_CHAP_MD5)
      {
        s_work_ptr->chap_digest = PPP_CHAP_MD5;
        option_result = CONFIG_NAK;
      }
      MSG_MED("dev %d got C-req with chap digest: %d",
              fsm_ptr->device,
              rx_chap_digest,
              0);
      break;

    default:
      /*---------------------------------------------------------------------
        Got an unrecognized authentication protocol.  Ask for CHAP/PAP in the
        nak and Send a config_nak which asks for CHAP as the authentication
        protocol.
      ---------------------------------------------------------------------*/
      MSG_MED("Rxd Unknown Auth proto:0x%x ",s_work_ptr->authentication,0,0);
      s_work_ptr->authentication = PPP_CHAP_PROTOCOL;
      s_work_ptr->chap_digest    = PPP_CHAP_MD5;
      option_result = CONFIG_NAK;
      break;
    } /* switch(auth type in req) */
    break; /* case LCP_AP */

  case LCP_MAGIC: /* magic number */
    s_work_ptr->magic_number = dsm_pull32(bpp);
    used -= 4;

    /*-----------------------------------------------------------------------
      Ensure that magic numbers are different
    -----------------------------------------------------------------------*/
    if ( s_work_ptr->magic_number == 0L )
    {
      s_work_ptr->magic_number = (uint32)s_work_ptr;
      option_result = CONFIG_NAK;
    } else if ( rworkp->magic_number == lworkp->magic_number )
    {
      s_work_ptr->magic_number += msclock();
      option_result = CONFIG_NAK;
    }
    break;

  case LCP_PFC:  /* protocol field compression */
  case LCP_ACFC: /* addr/control field compression */
    /* nothing to store here */
    break;

  default:
    option_result = CONFIG_REJ;
    break;
  } /* switch(option type) */

  if ( used < 0 )
  {
    return -1;
  }

  /*-------------------------------------------------------------------------
    if there are extra bytes in option toss them.
  -------------------------------------------------------------------------*/
  if ( used > 0 )
  {
    while( used-- > 0 )
    {
      if ( dsm_pull8(bpp) == -1 )
      {
        return -1;
      }
    }
  }

  return (option_result);

} /* lcp_check() */
/*===========================================================================

FUNCTION DIAGCOMM_BUFFER_ENQUEUE_STREAM

DESCRIPTION
This function enqueues data onto the sio_tx_wmq depending on the current mode.  
 
PARAMETERS
    item_ptr - pointer to the DSM item that has to be enqueued
    port_type - Control channel port type (SIO/SMD)
    stream_id - Specifies which stream should the data be enqueued
  
RETURN VALUE
  None
  
===========================================================================*/
void diagcomm_buffer_enqueue_stream( dsm_item_type ** item_ptr, 
									 diagcomm_port_type port_type,
								     uint8 stream_id )
{
  dsm_item_type * dsm_dequeue_item_ptr = NULL;
  dsm_item_type * dsm_chained_ptr = NULL;
  uint32 dsm_cnt = 0;
  uint32 dsm_dropped_cnt = 0;
  uint32 bytes_dropped_cnt = 0;
  uint32 dsm_alloc_cnt = 0;
  uint32 bytes_alloc_cnt = 0;
  uint8 stream_index = 0;

  if( (stream_id < DIAG_MIN_STREAM_ID) || (stream_id > DIAG_MAX_STREAM_ID) )
  {
    MSG_1(MSG_SSID_DIAG, MSG_LEGACY_ERROR, "diagcomm_buffer_enqueue_stream - Invalid stream_id (%d)", stream_id);
    return;
  }

  stream_index = DIAG_ID_TO_INDEX(stream_id);
    
  /* Dequeue and count dropped DSMs only in Buffered Cir mode. */
  if( diag_tx_mode[stream_index].mode == DIAG_TX_MODE_BUFFERED_CIR )
  {
    dsm_cnt = diag_buffering_pool_used_cnt( stream_id );
	diag_tx_mode[stream_index].cur_dsm_cnt[port_type] = dsm_cnt; //Save dsm count read

	if( DIAG_BUFFERED_DSM_CNT_TO_BYTES(dsm_cnt) >= diag_tx_mode[stream_index].buffered_many_bytes_mark )
	{
	  if( port_type == DIAGCOMM_PORT_SMD )
	    dsm_dequeue_item_ptr = diagcomm_io_dequeue_rx_wmq( &diagcomm_io_conn[port_type][DIAGCOMM_PORT_1] );
	  else if( port_type == DIAGCOMM_PORT_SIO )
	    dsm_dequeue_item_ptr = diagcomm_io_dequeue_tx_wmq( &diagcomm_io_conn[port_type][DIAGCOMM_PORT_1], 0 );
		
	  ASSERT( dsm_dequeue_item_ptr != NULL );
	  
	  //bytes_dropped_cnt += dsm_length_packet( dsm_dequeue_item_ptr );
	  dsm_chained_ptr = dsm_dequeue_item_ptr;
	  do
      {  
	    dsm_dropped_cnt += 1;
		bytes_dropped_cnt += dsm_chained_ptr->used;
		
		// Point to next DSM in the chain 
        dsm_chained_ptr = dsm_chained_ptr->pkt_ptr;
		
        // Continue to count chained DSMs 
	  } while( dsm_chained_ptr != NULL );
      //} while( (dsm_chained_ptr != NULL) && (dsm_chained_ptr->data_ptr != NULL) && (dsm_chained_ptr->used > 0) );
	  
	  // Update dropped count health statistics 
	  if( (diag_tx_mode[stream_index].dsm_dropped_cnt + dsm_dropped_cnt) >= MAX_VALUE_UINT32 )
	    diag_tx_mode[stream_index].dsm_dropped_cnt = MAX_VALUE_UINT32;
	  else
	    diag_tx_mode[stream_index].dsm_dropped_cnt += dsm_dropped_cnt;
	  
	  if( (diag_tx_mode[stream_index].byte_dropped_cnt + bytes_dropped_cnt) >= MAX_VALUE_UINT32 )
	    diag_tx_mode[stream_index].byte_dropped_cnt = MAX_VALUE_UINT32;
	  else
        diag_tx_mode[stream_index].byte_dropped_cnt += bytes_dropped_cnt;
	  
	  // Free the dequeued DSM item, including it's chained items 
	  dsm_free_packet( &dsm_dequeue_item_ptr );
	}
  }

  /* We don't drop/dequeue DSMs in Buffered Threshold mode. Just count alloc
     counts and enqueue. */
  if( (diag_tx_mode[stream_index].mode == DIAG_TX_MODE_BUFFERED_THRESH) || 
      (diag_tx_mode[stream_index].mode == DIAG_TX_MODE_BUFFERED_CIR) )
  {
	//bytes_alloc_cnt += dsm_length_packet( *item_ptr );
	dsm_chained_ptr = *item_ptr;
	do
	{
	   dsm_alloc_cnt += 1;
	   bytes_alloc_cnt += dsm_chained_ptr->used;
	   
	   // Point to next DSM in the chain 
       dsm_chained_ptr = dsm_chained_ptr->pkt_ptr;
	   
	  // Continue to count chained DSMs 
	} while( dsm_chained_ptr != NULL );
	
	// Update alloc count health statistics 
	if( (diag_tx_mode[stream_index].dsm_alloc_cnt + dsm_alloc_cnt) >= MAX_VALUE_UINT32 )
	  diag_tx_mode[stream_index].dsm_alloc_cnt = MAX_VALUE_UINT32;
	else
	  diag_tx_mode[stream_index].dsm_alloc_cnt += dsm_alloc_cnt;
	  
	if( (diag_tx_mode[stream_index].byte_alloc_cnt + bytes_alloc_cnt) >= MAX_VALUE_UINT32 )
	  diag_tx_mode[stream_index].byte_alloc_cnt = MAX_VALUE_UINT32;
	else
	  diag_tx_mode[stream_index].byte_alloc_cnt += bytes_alloc_cnt;
	#ifdef DIAG_SIO_SUPPORT
	if( port_type == DIAGCOMM_PORT_SMD )
	  dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.rx_queue, item_ptr);
	else if( port_type == DIAGCOMM_PORT_SIO )
	  dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.tx_queue, item_ptr);
	#elif defined (DIAG_SMDL_SUPPORT)
	  dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.smdl_params.tx_queue, item_ptr);
	#endif
	
  }
  else
  {
    /* Streaming mode; Just enqueue it. */
	#ifdef DIAG_SIO_SUPPORT
	if( port_type == DIAGCOMM_PORT_SMD )
      dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.rx_queue, item_ptr);
	else if( port_type == DIAGCOMM_PORT_SIO )
	  dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.sio_params.params.tx_queue, item_ptr);
	#elif defined (DIAG_SMDL_SUPPORT)
	   dsm_enqueue (diagcomm_io_conn[port_type][DIAGCOMM_PORT_1].open_params.smdl_params.tx_queue, item_ptr);
	#endif
  }

} /* diagcomm_buffer_enqueue_stream */
/*===========================================================================

FUNCTION dsm_new_packet_flexible

DESCRIPTION            
  Based on the dsm_size_requested, function dsmutili_new_packet_flexible() 
  will identify the best pool (SMALL or LARGE) and allocates first item 
  from that pool.

  This function will return a pointer to the DSM item chain based on
  the size requested.
  
  Total Size of the DSM chain is expected to be equal or greater than
  requested size.

DEPENDENCIES
  None

PARAMETERS
  dsm_size_requested - requested size of the buffer

RETURN VALUE
  Chain of DSM pointers w/ empty payload such that total size of chain is 
  equal to or greater than dsm_size_requested. It returns NULL if it fails 
  to allocate requested size.

SIDE EFFECTS
  Caller of this function is expected to have necessary handling whenever this
  function returns chain of DSM items.

===========================================================================*/
dsm_item_type *dsmutili_new_packet_flexible
(
  dsm_mempool_id_type pool_id,
  uint32 dsm_size_requested,
  const char * file,
  uint32 line
)
{
#ifdef FEATURE_DSM_DYNAMIC_POOL_SELECTION
  dsm_item_type *head_dsm_ptr = NULL, *tail_dsm_ptr = NULL;
  dsm_item_type *allocated_dsm_ptr = NULL;
  int16 remaining_size = dsm_size_requested;
  uint16 allocated_size = 0;

  while (remaining_size > 0)
  {
    /* select pool if according to the memory size requested */
    if (remaining_size > DSM_FLEXIBLE_LARGE_ITEM_THRESHOLD)
    {
      allocated_size = DSM_DS_LARGE_ITEM_SIZ;
      if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_LARGE_ITEM_POOL, file, line)))
      {
        allocated_size = DSM_DS_SMALL_ITEM_SIZ;
        if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_SMALL_ITEM_POOL, file, line)))
        {
          /* All the free items have been consumed from both the pools,
             exit out of the loop */
          break;
        }
      }
    }
    else /* allocate SMALL Item */
    {
      allocated_size = DSM_DS_SMALL_ITEM_SIZ;
      if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_SMALL_ITEM_POOL, file, line)))
      {
        allocated_size = DSM_DS_LARGE_ITEM_SIZ;
        if (NULL == (allocated_dsm_ptr = dsmi_new_buffer(DSM_DS_LARGE_ITEM_POOL, file, line)))
        {
          /* All the free items have been consumed from both the pools,
             exit out of do..while loop */
          break;
        }
      }
    }

    if ((uint32)remaining_size != dsm_size_requested)
    {
      tail_dsm_ptr->pkt_ptr = allocated_dsm_ptr;
      tail_dsm_ptr = allocated_dsm_ptr;
    }
    else
    {
      head_dsm_ptr = allocated_dsm_ptr;
      tail_dsm_ptr = allocated_dsm_ptr;
    }
    /* update remaining size */
    remaining_size -= allocated_size;
  }

  /* check whether both the pools have run out of the free items.
     If yes, then free any allocated dsm items */
  if (NULL != allocated_dsm_ptr)
  {
    return(head_dsm_ptr); 
  }
  else
  {
    dsm_free_packet(&head_dsm_ptr);
    head_dsm_ptr = NULL;
    return(head_dsm_ptr);
  }
#else
  return (dsmutili_new_packet(pool_id, dsm_size_requested, __FILE__,__LINE__));
#endif
}