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

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)));
}
Esempio n. 2
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() */
Esempio n. 3
0
/*===========================================================================

FUNCTION DSSICMP_WRITE()

DESCRIPTION
  Send DSM item out to ICMP (write to ICMP socket). The actual write is
  performed in icmp_output() in icmp.c This function is the ICMP
  specific dss_sendto()

DEPENDENCIES
  None. 

PARAMETERS  
  protocol_ctl_block_type pcb       -   protocol control block 
  struct sockaddr_in      *ta_ptr   -   destination socket info 
  dsm_item_type           *item_ptr -  ptr to head of dsm memory pool items 

RETURN VALUE
  Length of item written. 

SIDE EFFECTS
  None.

===========================================================================*/
extern sint15 dssicmp_write
(
  protocol_ctl_block_type pcb,                   /* protocol control block */
  struct sockaddr_in      *ta_ptr,              /* destination socket info */
  dsm_item_type           *item_ptr,/*ptr to head of dsm memory pool items */
  ps_meta_info_type *meta_info_ptr              /* ptr to meta info        */
)
{
  struct icmp_cb *  icmp_cb_ptr;
  uint32  *dest_ip_ptr;                          /* Ptr to dest IP address */
  struct scb_s *    scb_ptr;
  struct icmp       icmp_hdr;
  uint16            length;                                    
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  MSG_LOW("In dssicmp_write (@ %p)", dssicmp_write, 0, 0);

  /*-------------------------------------------------------------------------
    Since the meta infomation is not used, free the item
  -------------------------------------------------------------------------*/
  PS_META_INFO_FREE(&meta_info_ptr);

  /*-------------------------------------------------------------------------
    Setup the socket and ICMP control block pointers.
  ------------------------------------------------------------------------*/
  icmp_cb_ptr = pcb.icb;
  scb_ptr = icmp_cb_ptr->scb_ptr;

  /*-------------------------------------------------------------------------
    Use destination information from dsm_item chain. If not possible. 
    use the information in scb (may be stale).                        
  ------------------------------------------------------------------------*/
  if (ta_ptr != NULL) 
  {
    dest_ip_ptr = &(ta_ptr->sin_addr.s_addr);
    MSG_LOW("Using parameter ta_ptr", 0, 0, 0);
  }
  else
  {
    dest_ip_ptr = &(scb_ptr->servname.address); 
    MSG_LOW("Using the server addr in SCB", 0, 0, 0);
  }
  MSG_LOW("destination IP address: %x", *dest_ip_ptr, 0, 0);

  /*-------------------------------------------------------------------------
    Fill in all the known header fields, but not the checksum.
  ------------------------------------------------------------------------*/
  icmp_hdr.info.type = icmp_cb_ptr->type;
  icmp_hdr.info.code = icmp_cb_ptr->code;

  MSG_LOW("ICMP header successfully assembled", 0, 0, 0);

  /*-------------------------------------------------------------------------
    Collect length information and pass it down to icmp_output(). 
  ------------------------------------------------------------------------*/

  /*-------------------------------------------------------------------------
    Call icmp_output, which will make up the icmp header and send the 
    packet to IP.
  -------------------------------------------------------------------------*/
  length = dsm_length_packet(item_ptr);

  MSG_LOW("calling icmp_output(%d bytes), item length = %d", 
          length, 
          item_ptr->used, 
          0);
#ifdef FEATURE_DSM_MEM_CHK
  item_ptr->tracer = DSM_IP_SND_PROC;
#endif //FEATURE_DSM_MEM_CHK
  icmp_output( dest_ip_ptr, &icmp_hdr, item_ptr, icmp_cb_ptr, 0);

  /*-------------------------------------------------------------------------
    Return number of bytes sent out.
  ------------------------------------------------------------------------*/
  return (length);
}/* dssicmp_write() */
/*===========================================================================
FUNCTION DSMBIT_PACK32_TAIL

DESCRIPTION
  Packs a given value (up to thirty-two bits) into a given dsm item at a
  specified offset.  

DEPENDENCIES
  Data must be packed into the last used byte or the byte immediately
  following it.

  item_ptr can not be NULL.
  
PARAMETERS
  item_ptr  - Pointer to dsm item where packed data should be placed.
  pack_data - Data to be packed
  offset    - Number of bits to skip before placing this data
  len       - Number of bits of pack_data to pack (LSB of the variable)

RETURN VALUE
  Number of bits successfully packed

SIDE_EFFECTS
  A new dsm item may be acquired and linked.

===========================================================================*/
uint16 dsmbiti_pack32_tail
(
  dsm_item_type * item_ptr,
  uint32 pack_data,
  uint16 offset,
  uint16 len,
  dsm_mempool_id_type pool_id,
  const char * file,
  uint32 line
)
{
  uint32 bit_pack_data;          /* data to bit_pack into last byte */

  uint16 byte_offset;            /* Position in terms of bytes of reqd field */

  uint16 num_pushed_bits = 0;    /* stores number of bits pushed */

  uint16 length_packet;          /* stores the length of the passed packet */

  uint16 pushdown_bytes;          /* number of bytes to push down */

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  byte_offset = (uint16) offset / 8;
  offset = offset % 8;

  /* have to be writing bits into the last used byte, or to the byte
     immediately following.
     dsm_length_packet starts counting at 1, byte_offset starts counting at 0,
     thus the apparent off-by-1 discrepancy. */

  DSM_ASSERT (NULL != item_ptr);

  length_packet = (uint16)dsm_length_packet(item_ptr);

  if (offset == 0)
  {
    DSM_ASSERT( length_packet == byte_offset);
  }
  else //offset != 0
  {
    DSM_ASSERT (length_packet == (byte_offset + 1));
  }

  /* if we are packing some bits into the last used byte, go to it directly
     and pack those bits in */
  if (offset != 0)
  {
    while (item_ptr->pkt_ptr != NULL)
    {
      byte_offset -= item_ptr->used;
      item_ptr = item_ptr->pkt_ptr;
    }

    /* move the bits to be packed into the LSB of the temporary variable */
    bit_pack_data = pack_data >> MAX((len + offset - 8), 0);

    /* pack the bits into the last used byte */
    b_packd (bit_pack_data, (item_ptr->data_ptr + byte_offset),
             offset, (word) MIN(8-offset, len));

    /* count the number of pushed bits */
    num_pushed_bits += MIN(8 - offset, len);

    /* decrease the remaining length by the number of bits pushed */
    len = MAX((len + offset - 8), 0);
  }

  /* len is number of bits to pushdown_tail.  It may have changed from
     the top of the function, as a result of packing some bits directly */
  if (len != 0)
  {
    /* shift out the bits that have already been packed */
    pack_data = pack_data << (32 - len);

    /* swap big-endian to little-endian in 16-bit and 32-bit values
       before pushing down */
    pack_data = NTOHL(pack_data);

    pushdown_bytes = 1 + ((len - 1) / 8);

    /* if the pushdown was successful */
    if (dsmi_pushdown_tail(&item_ptr, &pack_data, pushdown_bytes, pool_id, file, line) ==
        pushdown_bytes)
    {
      /* assume all bits were pushed and increment the counter */
      num_pushed_bits += len;
    }
  }

  return num_pushed_bits;
} /* dsmbit_pack32_tail() */