/*===========================================================================

FUNCTION DSM_PKT_TO_SDU_CHAIN_BIT

DESCRIPTION            
  Pullup whole packet in chain into provided SDU buffer and return the copied
  length in bits.
  
  The bit size is read from the app_field in the packet header.

DEPENDENCIES
  None.
  
RETURN VALUE
  The number of bits read into the provided buffer.

SIDE EFFECTS
  The last byte being pulled out from a dsm item, this dsm item is returned 
  to the free pool. 
===========================================================================*/
word dsm_pkt_to_sdu_chain_bit
(
  dsm_item_type **pkt_head_ptr,     /* Address of ptr to head of packet     */
  void          *buf                /* Ptr. to bits to copy                 */
)
{
  uint16  size = 0, size_tmp, size_read;

  if ((*pkt_head_ptr)->app_field > 0)
  {
    size = (uint16)((*pkt_head_ptr)->app_field);

    /* convert size in bits into one in bytes */
    size_read = (size + 7) >> 3;

    size_tmp = dsm_pullup(pkt_head_ptr, buf, size_read);

    /* The size pulled out from the dsm items chain is not the same as  */
    /* the recorded size in the app_field. Some thing is wrong. Give    */
    /* what we have read in bits, and report an ERROR.                  */
    if (size_tmp != size_read)
    {
      MSG(MSG_SSID_DFLT, MSG_LEGACY_ERROR,"DSM read error in bit");
      /* size is counted in bits  */
      size = size_tmp * 8; 
    }
  }
/*===========================================================================

FUNCTION DSM_PKT_TO_SDU_CHAIN_BYTE
DESCRIPTION
  Pullup whole packet in chain into provided SDU buffer and return the copied
  length in bytes.

DEPENDENCIES
  None.

RETURN VALUE
  The number of bytes that read into the provided buffer

SIDE EFFECTS
  The last byte being pulled out from a dsm item, this dsm item is returned 
  to the free pool. 

===========================================================================*/
uint16 dsm_pkt_to_sdu_chain_byte
(
  dsm_item_type **pkt_head_ptr,    /* Address of ptr to head of packet     */
  void          *buf               /* Ptr. to bytes to copy                */
)
{
  return (dsm_pullup(
    pkt_head_ptr, buf, (uint16) dsm_length_packet(*pkt_head_ptr)));
}
Beispiel #3
0
/*===========================================================================

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() */