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