| /* |
| * Copyright (c) 2012-2013 Qualcomm Atheros, Inc. |
| * All Rights Reserved. |
| * Qualcomm Atheros Confidential and Proprietary. |
| */ |
| /* |
| * Woodside Networks, Inc proprietary. All rights reserved. |
| * File: $File: //depot/software/projects/feature_branches/nova_phase1/ap/apps/asf/aniAsfPacket.c $ |
| * Contains definitions for packet manipulation routines that make it |
| * easy to create and parse multi-layered network frames. This module |
| * minimizes buffer copies while adding or removing headers, and |
| * adding or removing payload. |
| * |
| * Author: Mayank D. Upadhyay |
| * Date: 19-June-2002 |
| * History:- |
| * Date Modified by Modification Information |
| * ------------------------------------------------------ |
| * |
| */ |
| #include "vos_types.h" |
| #include "vos_trace.h" |
| #include <bapRsnAsfPacket.h> |
| #include <bapRsnErrors.h> |
| #include "vos_memory.h" |
| #include "vos_packet.h" |
| |
| /* |
| * Allocate one more than required because the last bytes is waste. We |
| * waste the last byte because in the adopted model, the tail always |
| * points to the next location where data should be stored. In a full |
| * buffer we don't want to position the tail to memory we haven't |
| * allocated ourself. |
| */ |
| #define ANI_INTERNAL_DEFAULT_PACKET_SIZE (ANI_DEFAULT_PACKET_SIZE + 4) |
| |
| #define TAIL_SPACE(packet) \ |
| ((packet)->buf + (packet)->size - (packet)->tail) |
| |
| #define HEAD_SPACE(packet) \ |
| ((packet)->head - (packet)->buf) |
| |
| #define ANI_CHECK_RANGE(x , upper) \ |
| ( (x) <= (upper) ) |
| |
| /** |
| * Opaque packet structure with internal storage for raw bytes. |
| * Conceptually, a tAniPacket is a pre-allocated buffer that contains |
| * data in the middle and free space on either side. The start of the |
| * data is called the head. Routines are provided to add data at the |
| * front or at the rear. The length of the packet is the total number |
| * of valid data bytes contained in it. The size of the packet is the |
| * total number of preallocated bytes. |
| */ |
| struct tAniPacket { |
| v_U8_t *buf; |
| v_U32_t size; |
| v_U8_t *head; |
| v_U8_t *tail; |
| v_U8_t *recordHeader; |
| v_U32_t len; |
| }; |
| |
| /** |
| * aniAsfPacketAllocate |
| * |
| * FUNCTION: |
| * Create a packet of size 2*ANI_DEFAULT_PACKET_SIZE and positions the |
| * head of the packet in the center. The allocated storage can be free |
| * with a call to aniAsfPacketFree. |
| * |
| * LOGIC: |
| * Allocates storage for tAniPacket and its internal raw data |
| * buffer. Positions the head and tail pointers in the middle of the |
| * raw data buffer. |
| * |
| * @param packetPtr pointer that will be set to newly allocated |
| * tAniPacket if the operation succeeds. |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_MALLOC_FAILED if |
| * memory could not be allocated. |
| * @see aniAsfPacketFree |
| */ |
| int |
| aniAsfPacketAllocate(tAniPacket **packetPtr) |
| { |
| return aniAsfPacketAllocateExplicit(packetPtr, |
| ANI_INTERNAL_DEFAULT_PACKET_SIZE, |
| ANI_INTERNAL_DEFAULT_PACKET_SIZE/2); |
| } |
| |
| /** |
| * aniAsfPacketAllocateExplicit |
| * |
| * FUNCTION: |
| * Create a packet of the desired size and position the head of the |
| * packet at the desired offset in the internal raw data buffer. An |
| * application would normally set this offset to the expected length |
| * of the protocol header, then append the payload, and finally, |
| * prepend the header. The allocated storage can be free with a call |
| * to aniAsfPacketFree. |
| * |
| * LOGIC: |
| * Allocates storage for tAniPacket and its internal raw data |
| * buffer. Positions the head and tail pointers at the given offset in |
| * the internal raw data buffer. |
| * |
| * @param packetPtr pointer that will be set to newly allocated |
| * tAniPacket if the operation succeeds. |
| * @param size the size of the internal raw data buffer |
| * @param offset the offset in the internal raw data buffer where the |
| * head of the packet will be positioned initially |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_MALLOC_FAILED if |
| * memory could not be allocated. |
| * @see aniAsfPacketFree |
| */ |
| int |
| aniAsfPacketAllocateExplicit(tAniPacket **packetPtr, |
| v_U32_t size, |
| v_U32_t offset) |
| { |
| tAniPacket *packet = NULL; |
| v_U32_t maxHead = size; |
| |
| *packetPtr = NULL; |
| if (size == 0) |
| return ANI_E_ILLEGAL_ARG; |
| |
| VOS_ASSERT(ANI_CHECK_RANGE(offset, maxHead)); |
| if (!ANI_CHECK_RANGE(offset, maxHead)) |
| return ANI_E_ILLEGAL_ARG; |
| |
| packet = (tAniPacket *) vos_mem_malloc( sizeof(tAniPacket) ); |
| |
| if (packet == NULL) |
| { |
| VOS_ASSERT( 0 ); |
| return ANI_E_MALLOC_FAILED; |
| } |
| |
| // transparently add one to the size since last byte is wasted |
| size = (size + 4) & 0xfffffffc; |
| |
| packet->buf = (v_U8_t *)vos_mem_malloc( sizeof(v_U8_t) * size ); |
| if (packet->buf == NULL) |
| { |
| vos_mem_free( packet ); |
| VOS_ASSERT( 0 ); |
| return ANI_E_MALLOC_FAILED; |
| } |
| |
| packet->size = size; // Should not be visible to the user |
| packet->head = packet->buf + offset; |
| packet->tail = packet->head; |
| packet->len = 0; |
| |
| *packetPtr = packet; |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketDuplicate |
| * |
| * Duplicates a given packet exactly. That is, the contents, the size |
| * of the packet, and the positions of the pointers are maintained in |
| * the new copy. |
| * |
| * @param newPacketPtr is set to a newly allocated packet that is a |
| * duplicate of oldPacket |
| * @param oldPacket the original packet that should be duplicated |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_NULL if oldPacket |
| * is NULL; |
| */ |
| int |
| aniAsfPacketDuplicate(tAniPacket **newPacketPtr, tAniPacket *oldPacket) |
| { |
| int retVal; |
| int recordPos; |
| tAniPacket *packet = NULL; |
| |
| if (oldPacket == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| retVal = aniAsfPacketAllocateExplicit(&packet, |
| oldPacket->size, |
| oldPacket->head - oldPacket->buf); |
| if (retVal != ANI_OK) |
| return retVal; |
| |
| retVal = aniAsfPacketAppendBuffer(packet, |
| oldPacket->head, |
| oldPacket->len); |
| if (retVal != ANI_OK) |
| { |
| VOS_ASSERT( 0 ); |
| aniAsfPacketFree(packet); |
| return ANI_E_FAILED; |
| } |
| |
| if (oldPacket->recordHeader != NULL) |
| { |
| recordPos = oldPacket->recordHeader - oldPacket->buf; |
| packet->recordHeader = packet->buf + recordPos; |
| } |
| *newPacketPtr = packet; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketFree |
| * |
| * FUNCTION: |
| * Free a previously allocated tAniPacket and its internal raw data |
| * buffer. |
| * |
| * @param packet the packet to free |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_NULL_VALUE if an |
| * unexpected NULL pointer is encountered |
| */ |
| int |
| aniAsfPacketFree(tAniPacket *packet) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (packet->buf != NULL) |
| vos_mem_free( packet->buf ); |
| |
| vos_mem_free( packet ); |
| |
| return ANI_OK; |
| } |
| |
| |
| /** |
| * aniAsfPacketAppendBuffer |
| * |
| * FUNCTION: |
| * Appends the data contained in buf to the end of the data in |
| * destAniPacket. The head of destAniPacket remains unchanged, while its |
| * length increases by len. |
| * |
| * If there isn't enough free space in destAniPacket for all len bytes |
| * then the routine fails and the length of destAniPacket remains |
| * unchanged. |
| * |
| * LOGIC: |
| * Check that there is enough free space in the packet to append the |
| * buffer. If not, bail. Otherwise, copy bytes from the buffer into |
| * the packet's internal raw data buffer and increase the value of its |
| * length to reflect this. |
| * |
| * @param packet the packet to append to |
| * @param buf the buffer containing data to be appended to the packet |
| * @param len the number of bytes to append |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_FAILED if the |
| * packet does not have enough free space for the complete buffer |
| * @see aniAsfPacketPrependBuffer |
| */ |
| int |
| aniAsfPacketAppendBuffer(tAniPacket *destPacket, |
| const v_U8_t *buf, |
| v_U32_t len) |
| { |
| if (aniAsfPacketCanAppendBuffer(destPacket, len) != ANI_OK) |
| return ANI_E_FAILED; |
| |
| if (buf == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| vos_mem_copy(destPacket->tail, buf, len); |
| destPacket->tail += len; |
| destPacket->len += len; |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketPrependBuffer |
| * |
| * FUNCTION: |
| * Prepends the data contained in buf to the start of the data in |
| * destPacket. The head of destPacket is repositioned and the length |
| * of destPacket increases by len. |
| * |
| * If there isn't enough free space in destPacket for all len bytes |
| * then the routine fails and the length of destPacket remains |
| * unchanged. |
| * |
| * LOGIC: |
| * Check that there is enough free space in the packet to prepend the |
| * buffer. If not, bail. Otherwise, copy bytes from the buffer into |
| * the packet's internal raw data buffer and increase the value of its |
| * length to reflect this. |
| * |
| * @param packet the packet to prepend to |
| * @param buf the buffer containing data to be prepended to the packet |
| * @param len the number of bytes to prepend |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_FAILED if the |
| * packet does not have enough free space for the complete buffer |
| * @see aniAsfPacketAppendBuffer |
| */ |
| int |
| aniAsfPacketPrependBuffer(tAniPacket *destPacket, |
| const v_U8_t *buf, |
| v_U32_t len) |
| { |
| if (aniAsfPacketCanPrependBuffer(destPacket, len) != ANI_OK) |
| return ANI_E_FAILED; |
| |
| if (buf == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| destPacket->head -= len; |
| destPacket->len += len; |
| vos_mem_copy(destPacket->head, buf, len); |
| return ANI_OK; |
| |
| } |
| |
| /** |
| * aniAsfPacketCanAppendBuffer |
| * |
| * FUNCTION: |
| * Determines if len bytes can be safely appended to destPacket |
| * without overflowing. |
| * |
| * LOGIC: |
| * Current packet tail plus len of buffer should not exceed packet |
| * start plus packet size |
| * |
| * Note: This does not return a boolean value, but instead an integer |
| * code. |
| * |
| * @param packet the packet to append to |
| * @param len the number of bytes to append |
| * |
| * @return ANI_OK if the append operation would succeed; ANI_E_FAILED |
| * otherwise |
| */ |
| int |
| aniAsfPacketCanAppendBuffer(tAniPacket *destPacket, |
| v_U32_t len) |
| { |
| if (destPacket == NULL) |
| return ANI_E_FAILED; |
| |
| if ((int)len <= TAIL_SPACE(destPacket)) |
| return ANI_OK; |
| else |
| return ANI_E_FAILED; |
| } |
| |
| /** |
| * aniAsfPacketCanPrependBuffer |
| * |
| * FUNCTION: |
| * Determines if len bytes can be safely prepended to destPacket |
| * without overflowing. |
| * |
| * LOGIC: |
| * Current packet head minus len of buffer should not be less than |
| * start of packet. |
| * |
| * Note: This does not return a boolean value, but instead an integer |
| * code. |
| * |
| * @param packet the packet to prepend to |
| * @param len the number of bytes to prepend |
| * |
| * @return ANI_OK if the append operation would succeed; ANI_E_FAILED |
| * otherwise |
| */ |
| int |
| aniAsfPacketCanPrependBuffer(tAniPacket *destPacket, |
| v_U32_t len) |
| { |
| if (destPacket == NULL) |
| return ANI_E_FAILED; |
| |
| if (!(len > 0)) |
| return ANI_E_FAILED; |
| |
| if ((int)len <= HEAD_SPACE(destPacket)) |
| return ANI_OK; |
| else |
| return ANI_E_FAILED; |
| } |
| |
| /** |
| * aniAsfPacketTruncateFromFront |
| * |
| * FUNCTION: |
| * Removes len bytes from the front of the packet by moving its |
| * head. The length of the packet is decremented by len. |
| * |
| * @param packet the packet to truncate from the front |
| * @param len the number of bytes to truncate |
| * |
| * @return ANI_OK if the append operation would succeed; ANI_E_FAILED |
| * otherwise |
| */ |
| int |
| aniAsfPacketTruncateFromFront(tAniPacket *packet, |
| v_U32_t len) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (!ANI_CHECK_RANGE(len, packet->len)) |
| return ANI_E_FAILED; |
| |
| packet->head += len; |
| packet->len -= len; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketTruncateFromRear |
| * |
| * FUNCTION: |
| * Removes len bytes from the rear of the packet by moving its |
| * tail. The length of the packet is decremented by len. |
| * |
| * @param packet the packet to truncate from the rear |
| * @param len the number of bytes to truncate |
| * |
| * @return ANI_OK if the append operation would succeed; ANI_E_FAILED |
| * otherwise |
| */ |
| int |
| aniAsfPacketTruncateFromRear(tAniPacket *packet, |
| v_U32_t len) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (!ANI_CHECK_RANGE(len, packet->len)) |
| return ANI_E_FAILED; |
| |
| packet->tail -= len; |
| packet->len -= len; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketGetLen |
| * |
| * FUNCTION: |
| * Returns the number of valid data bytes stored in the packet. |
| * |
| * @param packet the packet whose len we need |
| * |
| * @return the non-negative number of bytes stored in the packet |
| */ |
| int |
| aniAsfPacketGetLen(tAniPacket *packet) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| return packet->len; |
| } |
| |
| /** |
| * aniAsfPacketGetBytes |
| * |
| * FUNCTION: |
| * Returns a pointer to the head of the valid data stored in the |
| * packet. |
| * |
| * @param packet the packet whose bytes we need |
| * @param rawBytesPtr the pointer that will be set the start of the |
| * raw bytes. |
| * |
| * @return The non-negative number of bytes stored in the packet if |
| * the operation succeeded. That is the same value as what would be |
| * returned by aniAsfPacketGetLen. |
| */ |
| int |
| aniAsfPacketGetBytes(tAniPacket *packet, v_U8_t **rawBytesPtr) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| *rawBytesPtr = packet->head; |
| return packet->len; |
| } |
| |
| /** |
| * aniAsfPacketGetN |
| * |
| * Returns N bytes from the packet and moves the head of the packet |
| * beyond those bytes. |
| * |
| * @param packet the packet to read from |
| * @param n the number of bytes to read |
| * @param bytesPtr is set to the start of the octets |
| * |
| * @return ANI_OK if the operation succeeds; ANI_E_SHORT_PACKET if the |
| * packet does not have n bytes. |
| */ |
| int |
| aniAsfPacketGetN(tAniPacket *packet, int n, v_U8_t **bytesPtr) |
| { |
| int retVal; |
| v_U8_t *bytes = NULL; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| retVal = aniAsfPacketGetBytes(packet, &bytes); |
| if (retVal < n) |
| return ANI_E_SHORT_PACKET; |
| |
| aniAsfPacketTruncateFromFront(packet, n); |
| |
| *bytesPtr = bytes; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketEmpty |
| * |
| * FUNCTION: |
| * Re-initializes the packet by positioning the head to the middle and |
| * setting the length to zero. |
| * |
| * @param packet the packet to empty |
| * |
| * @return ANI_OK if the operation succeeded |
| */ |
| int |
| aniAsfPacketEmpty(tAniPacket *packet) |
| { |
| return aniAsfPacketEmptyExplicit(packet, packet->size/2); |
| } |
| |
| /** |
| * aniAsfPacketEmptyExplicit |
| * |
| * FUNCTION: |
| * Re-initializes the packet by positioning the head to the desired |
| * offset and setting the length to zero. |
| * |
| * @param packet the packet to empty |
| * @param offset the offset that the head of the packet should be set |
| * to. An application will be able to prepend and append data relative |
| * to this offset. |
| * |
| * @return ANI_OK if the operation succeeded |
| */ |
| int |
| aniAsfPacketEmptyExplicit(tAniPacket *packet, |
| v_U32_t offset) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| VOS_ASSERT(ANI_CHECK_RANGE(offset, packet->size)); |
| if (!ANI_CHECK_RANGE(offset, packet->size)) |
| return ANI_E_ILLEGAL_ARG; |
| |
| packet->head = packet->buf + offset; |
| packet->tail = packet->head; |
| packet->len = 0; |
| |
| return ANI_OK; |
| } |
| |
| |
| |
| /** |
| * aniAsfPacketPrependHdr |
| * |
| * FUNCTION: |
| * Prepends a tAniHdr at the start of the packet. All host to network |
| * byte order translation is also taken care of. |
| * |
| * @param packet the packet to write to |
| * @param msgType the message type to write as part of the header |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketPrependHdr(tAniPacket *packet, v_U16_t msgType) |
| { |
| int retVal; |
| int length; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| length = 4; |
| |
| length = 2 + 2 + packet->len; |
| |
| retVal = aniAsfPacketPrepend16(packet, length); |
| if (retVal < 0) |
| return retVal; |
| |
| retVal = aniAsfPacketPrepend16(packet, msgType); |
| if (retVal < 0) |
| return retVal; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketGet32 |
| * |
| * FUNCTION: |
| * Reads a ANI_U32 out of the packet and returns it. The packet's head |
| * is advanced and its length decremented by the appropriate length. |
| * All network to host byte order translation is also taken care of. |
| * |
| * @param packet the packet to read from |
| * @param val the value to fill in |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketGet32(tAniPacket *packet, v_U32_t *val) |
| { |
| v_U8_t u32Arr[4]; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (val == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (packet->len < 4) |
| return ANI_E_SHORT_PACKET; |
| |
| //packet is in network order, make sure it is align |
| u32Arr[0] = packet->head[0]; |
| u32Arr[1] = packet->head[1]; |
| u32Arr[2] = packet->head[2]; |
| u32Arr[3] = packet->head[3]; |
| *val = vos_be32_to_cpu( *(v_U32_t *)u32Arr ); |
| aniAsfPacketTruncateFromFront(packet, 4); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketAppend32 |
| * |
| * FUNCTION: |
| * Appends a ANI_U32 to the end of the packet. |
| * All host to network byte order translation is also taken care of. |
| * |
| * @param packet the packet to write to |
| * @param val the value to append |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketAppend32(tAniPacket *packet, v_U32_t val) |
| { |
| v_U8_t *p8; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (TAIL_SPACE(packet) < 4) |
| return ANI_E_FAILED; |
| |
| val = vos_cpu_to_be32( val ); |
| p8 = (v_U8_t *)&val; |
| packet->tail[0] = p8[0]; |
| packet->tail[1] = p8[1]; |
| packet->tail[2] = p8[2]; |
| packet->tail[3] = p8[3]; |
| aniAsfPacketMoveRight(packet, 4); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketGet16 |
| * |
| * FUNCTION: |
| * Reads a ANI_U16 out of the packet and returns it. The packet's head |
| * is advanced and its length decremented by the appropriate length. |
| * All network to host byte order translation is also taken care of. |
| * |
| * @param packet the packet to read from |
| * @param val the value to fill in |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketGet16(tAniPacket *packet, v_U16_t *val) |
| { |
| v_U8_t u16Arr[2]; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (val == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (packet->len < 2) |
| return ANI_E_SHORT_PACKET; |
| |
| u16Arr[0] = packet->head[0]; |
| u16Arr[1] = packet->head[1]; |
| *val = vos_be16_to_cpu( *(v_U16_t *)u16Arr ); |
| aniAsfPacketTruncateFromFront(packet, 2); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketPrepend16 |
| * |
| * FUNCTION: |
| * Prepends a ANI_U16 to the start of the packet. |
| * All host to network byte order translation is also taken care of. |
| * |
| * @param packet the packet to write to |
| * @param val the value to prepend |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketPrepend16(tAniPacket *packet, v_U16_t val) |
| { |
| v_U8_t *p8; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (HEAD_SPACE(packet) < 2) |
| return ANI_E_FAILED; |
| |
| aniAsfPacketMoveLeft(packet, 2); |
| val = vos_cpu_to_be16( val ); |
| p8 = (v_U8_t *)&val; |
| packet->head[0] = p8[0]; |
| packet->head[1] = p8[1]; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketAppend16 |
| * |
| * FUNCTION: |
| * Appends a ANI_U16 to the end of the packet. |
| * All host to network byte order translation is also taken care of. |
| * |
| * @param packet the packet to write to |
| * @param val the value to append |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketAppend16(tAniPacket *packet, v_U16_t val) |
| { |
| v_U8_t *p8; |
| |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (TAIL_SPACE(packet) < 2) |
| return ANI_E_FAILED; |
| |
| val = vos_cpu_to_be16( val ); |
| p8 = (v_U8_t *)&val; |
| packet->tail[0] = p8[0]; |
| packet->tail[1] = p8[1]; |
| aniAsfPacketMoveRight(packet, 2); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketGet8 |
| * |
| * FUNCTION: |
| * Reads a ANI_U8 out of the packet and returns it. The packet's head |
| * is advanced and its length decremented by the appropriate length. |
| * All network to host byte order translation is also taken care of. |
| * |
| * @param packet the packet to read from |
| * @param val the value to fill in |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketGet8(tAniPacket *packet, v_U8_t *val) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (val == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (packet->len < 1) |
| return ANI_E_SHORT_PACKET; |
| |
| *val = *(packet->head); |
| aniAsfPacketTruncateFromFront(packet, 1); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketPrepend8 |
| * |
| * FUNCTION: |
| * Prepends a ANI_U8 to the start of the packet. |
| * All host to network byte order translation is also taken care of. |
| * |
| * @param packet the packet to read from |
| * @param val the value to prepend |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketPrepend8(tAniPacket *packet, v_U8_t val) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| VOS_ASSERT(HEAD_SPACE(packet) >= 1); |
| if (HEAD_SPACE(packet) < 1) |
| return ANI_E_FAILED; |
| |
| aniAsfPacketMoveLeft(packet, 1); |
| *(packet->head) = val; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketAppend8 |
| * |
| * FUNCTION: |
| * Appends a ANI_U8 to the end of the packet. |
| * All host to network byte order translation is also taken care of. |
| * |
| * @param packet the packet to write to |
| * @param val the value to append |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketAppend8(tAniPacket *packet, v_U8_t val) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| if (TAIL_SPACE(packet) < 1) |
| return ANI_E_FAILED; |
| |
| *(packet->tail) = val; |
| aniAsfPacketMoveRight(packet, 1); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketGetMac |
| * |
| * FUNCTION: |
| * Returns a tAniMacAddr from the start of the packet. |
| * |
| * @param packet the packet to read from |
| * @param macAddr the destination to copy the MAC address to |
| * |
| * @return ANI_OK if the operation succeeds. Also, the packet head |
| * pointer is advanced past the MAC address. |
| */ |
| int |
| aniAsfPacketGetMac(tAniPacket *packet, tAniMacAddr macAddr) |
| { |
| if (packet->len < sizeof(tAniMacAddr)) |
| return ANI_E_SHORT_PACKET; |
| |
| vos_mem_copy(macAddr, packet->head, sizeof(tAniMacAddr)); |
| |
| packet->head += sizeof(tAniMacAddr); |
| packet->len -= sizeof(tAniMacAddr); |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketMoveLeft |
| * |
| * FUNCTION: |
| * Pretends that a certain number of bytes have been prepended to the |
| * packet, without actually copying any bytes in. The packet head and |
| * length are appropriately changed. This function is useful while |
| * interfacing with other libraries that only support byte array |
| * manipulation. |
| * |
| * WARNING: |
| * Applications are discouraged from using this function |
| * because correct usage is a two-step process - one: copy some bytes |
| * to the packet's internal buffer, two: move head and length. This |
| * violates the encapsulation the packet library aims to provide. |
| * |
| * @param packet the packet whose head and length needs to be modified |
| * @param count the number of bytes to modify by |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketMoveLeft(tAniPacket *packet, v_U32_t count) |
| { |
| if (aniAsfPacketCanPrependBuffer(packet, count) != ANI_OK) |
| return ANI_E_FAILED; |
| |
| packet->head -= count; |
| packet->len += count; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketMoveRight |
| * |
| * FUNCTION: |
| * Pretends that a certain number of bytes have been appended to the |
| * packet, without actually copying any bytes in. The packet tail and |
| * length are appropriately changed. This function is useful while |
| * interfacing with other libraries that only support byte array |
| * manipulation. |
| * |
| * WARNING: |
| * Applications are discouraged from using this function |
| * because correct usage is a two-step process - one: copy some bytes |
| * to the packet's internal buffer, two: move tail and length. This |
| * violates the encapsulation the packet library aims to provide. |
| * |
| * @param packet the packet whose head and length needs to be modified |
| * @param count the number of bytes to modify by |
| * |
| * @return ANI_OK if the operation succeeds |
| */ |
| int |
| aniAsfPacketMoveRight(tAniPacket *packet, v_U32_t count) |
| { |
| if (aniAsfPacketCanAppendBuffer(packet, count) != ANI_OK) |
| return ANI_E_FAILED; |
| |
| packet->tail += count; |
| packet->len += count; |
| |
| return ANI_OK; |
| } |
| |
| /** |
| * aniAsfPacketGetBytesFromTail |
| * |
| * FUNCTION: |
| * Returns a pointer to the tail of the valid data stored |
| * in the packet. |
| * |
| * WARNING: |
| * Applications are discouraged from using this function |
| * because correct usage is a three-step process - one: call this |
| * routine to obtain a pointer to the current tail of the packet. |
| * two: treat this returned pointer like a simple array and copy |
| * some bytes to the packet's internal buffer, and finally |
| * three: move tail and length. This violates the encapsulation |
| * the packet library aims to provide. |
| * |
| * @param packet the packet whose bytes we need |
| * @param rawBytesPtr the pointer that will be set the start of the |
| * raw bytes. |
| * |
| * @return The non-negative number of bytes stored in the packet if |
| * the operation succeeded. That is the same value as what would be |
| * returned by aniAsfPacketGetLen. |
| */ |
| int |
| aniAsfPacketGetBytesFromTail(tAniPacket *packet, v_U8_t **rawBytesPtr) |
| { |
| if (packet == NULL) |
| return ANI_E_NULL_VALUE; |
| |
| *rawBytesPtr = packet->tail; |
| return 0; // The length of used bytes returned is zero |
| } |
| |