libqmi-qmuxd/gobi-api/GobiAPI_2013-07-31-1347/Gobi3000Translation/Gobi3000TranslationWDS.cpp

3486 lines
99 KiB
C++

/*===========================================================================
FILE:
Gobi3000TranslationWDS.cpp
DESCRIPTION:
QUALCOMM Translation for Gobi 3000 (WDS Service)
Copyright (c) 2013, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
==========================================================================*/
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "Gobi3000Translation.h"
/*===========================================================================
METHOD:
ParseGetSessionState
DESCRIPTION:
This function returns the state of the current packet data session
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pState [ O ] - State of the current packet session
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetSessionState(
ULONG inLen,
const BYTE * pIn,
ULONG * pState )
{
// Validate arguments
if (pIn == 0 || pState == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the TLV
const sWDSGetPacketServiceStatusResponse_Status * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx01 < sizeof( sWDSGetPacketServiceStatusResponse_Status ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pState = pTLVx01->mConnectionStatus;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetSessionDuration
DESCRIPTION:
This function returns the duration of the current packet data session
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pDuration [ O ] - Duration of the current packet session
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetSessionDuration(
ULONG inLen,
const BYTE * pIn,
ULONGLONG * pDuration )
{
// Validate arguments
if (pIn == 0 || pDuration == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the TLV
const sWDSGetDataSessionDurationResponse_Duration * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx01 < sizeof( sWDSGetDataSessionDurationResponse_Duration ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pDuration = pTLVx01->mDataSessionDuration;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetDormancyState
DESCRIPTION:
This function returns the dormancy state of the current packet
data session (when connected)
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pState [ O ] - Dormancy state of the current packet session
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetDormancyState(
ULONG inLen,
const BYTE * pIn,
ULONG * pState )
{
// Validate arguments
if (pIn == 0 || pState == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the TLV
const sWDSGetDormancyResponse_DormancyStatus * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx01 < sizeof( sWDSGetDormancyResponse_DormancyStatus ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pState = pTLVx01->mDormancyStatus;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetEnhancedAutoconnect
DESCRIPTION:
This function returns the current autoconnect data session setting
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pSetting [ O ] - NDIS autoconnect setting
pRoamSetting [ O ] - NDIS autoconnect roam setting
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetEnhancedAutoconnect(
ULONG inLen,
const BYTE * pIn,
ULONG * pSetting,
ULONG * pRoamSetting )
{
// Validate arguments
if (pIn == 0 || pSetting == 0 || pRoamSetting == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
*pSetting = 0xffffffff;
*pRoamSetting = 0xffffffff;
// Find the first TLV
const sWDSGetAutoconnectSettingResponse_Autoconnect * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx01 < sizeof( sWDSGetAutoconnectSettingResponse_Autoconnect ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pSetting = pTLVx01->mAutoconnectSetting;
// Find the second TLV (optional)
const sWDSGetAutoconnectSettingResponse_Roam * pTLVx10;
ULONG outLenx10;
rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc == eGOBI_ERR_NONE)
{
// Is the TLV large enough?
if (outLenx10 < sizeof( sWDSGetAutoconnectSettingResponse_Roam ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pRoamSetting = pTLVx10->mAutoconnectRoamSetting;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackSetEnhancedAutoconnect
DESCRIPTION:
This function sets the autoconnect data session setting
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
setting [ I ] - NDIS autoconnect setting
pRoamSetting [ I ] - (Optional) NDIS autoconnect roam setting
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetEnhancedAutoconnect(
ULONG * pOutLen,
BYTE * pOut,
ULONG setting,
ULONG * pRoamSetting )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add setting
// Check size
WORD tlvx01Sz = sizeof( sWDSSetAutoconnectSettingRequest_Autoconnect );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSSetAutoconnectSettingRequest_Autoconnect * pTLVx01;
pTLVx01 = (sWDSSetAutoconnectSettingRequest_Autoconnect*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the value
pTLVx01->mAutoconnectSetting = (eQMIWDSAutoconnectSettings)setting;
offset += tlvx01Sz;
// Add roam setting, if specified
if (pRoamSetting != 0)
{
// Check size
WORD tlvx10Sz = sizeof( sWDSSetAutoconnectSettingRequest_Roam );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetAutoconnectSettingRequest_Roam * pTLVx10;
pTLVx10 = (sWDSSetAutoconnectSettingRequest_Roam*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mAutoconnectRoamSetting = (eQMIWDSAutoconnectRoamSettings)*pRoamSetting;
offset += tlvx10Sz;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackSetDefaultProfile
DESCRIPTION:
This function writes the default profile settings to the device, the
default profile is used during autoconnect
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
profileType [ I ] - Profile type being written
pPDPType [ I ] - (Optional) PDP type
pIPAddress [ I ] - (Optional) Preferred assigned IPv4 address
pPrimaryDNS [ I ] - (Optional) Primary DNS IPv4 address
pSecondaryDNS [ I ] - (Optional) Secondary DNS IPv4 address
pAuthentication [ I ] - (Optional) Authentication algorithm bitmap
pName [ I ] - (Optional) The profile name or description
pAPNName [ I ] - (Optional) Access point name
pUsername [ I ] - (Optional) Username used during authentication
pPassword [ I ] - (Optional) Password used during authentication
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetDefaultProfile(
ULONG * pOutLen,
BYTE * pOut,
ULONG profileType,
ULONG * pPDPType,
ULONG * pIPAddress,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS,
ULONG * pAuthentication,
CHAR * pName,
CHAR * pAPNName,
CHAR * pUsername,
CHAR * pPassword )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add profileType
// Check size
WORD tlvx01Sz = sizeof( sWDSModifyProfileRequest_ProfileIdentifier );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSModifyProfileRequest_ProfileIdentifier * pTLVx01;
pTLVx01 = (sWDSModifyProfileRequest_ProfileIdentifier*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the value
pTLVx01->mProfileType = (eQMIProfileTypes)profileType;
pTLVx01->mProfileIndex = 1;
offset += tlvx01Sz;
// Add name, if specified
if (pName != 0)
{
std::string name( pName );
// Check size
WORD tlvx10Sz = (WORD)name.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( pOut + offset, name.c_str(), name.size() );
offset += tlvx10Sz;
}
// Add PDP type, if specified
if (pPDPType != 0)
{
// Check size
WORD tlvx11Sz = sizeof( sWDSModifyProfileRequest_PDPType );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSModifyProfileRequest_PDPType * pTLVx11;
pTLVx11 = (sWDSModifyProfileRequest_PDPType*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
// Set the value
pTLVx11->mPDPType = (eQMIPDPTypes)*pPDPType;
offset += tlvx11Sz;
}
// Add APN Name, if specified
if (pAPNName != 0)
{
std::string apnName( pAPNName );
// Check size
WORD tlvx14Sz = (WORD)apnName.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx14Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x14;
pHeader->mLength = tlvx14Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), apnName.c_str(), apnName.size() );
offset += tlvx14Sz;
}
// Add Primary DNS, if specified
if (pPrimaryDNS != 0)
{
// Check size
WORD tlvx15Sz = sizeof( sWDSModifyProfileRequest_PrimaryDNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx15Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x15;
pHeader->mLength = tlvx15Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSModifyProfileRequest_PrimaryDNS * pTLVx15;
pTLVx15 = (sWDSModifyProfileRequest_PrimaryDNS*)(pOut + offset);
memset( pTLVx15, 0, tlvx15Sz );
ULONG ip0 = (*pPrimaryDNS & 0x000000FF);
ULONG ip1 = (*pPrimaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryDNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pPrimaryDNS & 0xFF000000) >> 24;
// Set the value
pTLVx15->mIPV4Address[0] = (INT8)ip0;
pTLVx15->mIPV4Address[1] = (INT8)ip1;
pTLVx15->mIPV4Address[2] = (INT8)ip2;
pTLVx15->mIPV4Address[3] = (INT8)ip3;
offset += tlvx15Sz;
}
// Add Secondary DNS, if specified
if (pSecondaryDNS != 0)
{
// Check size
WORD tlvx16Sz = sizeof( sWDSModifyProfileRequest_SecondaryDNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx16Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x16;
pHeader->mLength = tlvx16Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSModifyProfileRequest_SecondaryDNS * pTLVx16;
pTLVx16 = (sWDSModifyProfileRequest_SecondaryDNS*)(pOut + offset);
memset( pTLVx16, 0, tlvx16Sz );
ULONG ip0 = (*pSecondaryDNS & 0x000000FF);
ULONG ip1 = (*pSecondaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryDNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pSecondaryDNS & 0xFF000000) >> 24;
// Set the value
pTLVx16->mIPV4Address[0] = (INT8)ip0;
pTLVx16->mIPV4Address[1] = (INT8)ip1;
pTLVx16->mIPV4Address[2] = (INT8)ip2;
pTLVx16->mIPV4Address[3] = (INT8)ip3;
offset += tlvx16Sz;
}
// Add Username, if specified
if (pUsername != 0)
{
std::string username( pUsername );
// Check size
WORD tlvx1BSz = (WORD)username.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx1BSz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x1B;
pHeader->mLength = tlvx1BSz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), username.c_str(), username.size() );
offset += tlvx1BSz;
}
// Add Password, if specified
if (pPassword != 0)
{
std::string password( pPassword );
// Check size
WORD tlvx1CSz = (WORD)password.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx1CSz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x1C;
pHeader->mLength = tlvx1CSz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), password.c_str(), password.size() );
offset += tlvx1CSz;
}
// Add Authentication, if specified
if (pAuthentication != 0)
{
// Check size
WORD tlvx1DSz = sizeof( sWDSModifyProfileRequest_Authentication );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx1DSz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x1D;
pHeader->mLength = tlvx1DSz;
offset += sizeof( sQMIRawContentHeader );
sWDSModifyProfileRequest_Authentication * pTLVx1D;
pTLVx1D = (sWDSModifyProfileRequest_Authentication*)(pOut + offset);
memset( pTLVx1D, 0, tlvx1DSz );
// Set the value
pTLVx1D->mEnablePAP = ((*pAuthentication & 0x00000001) != 0);
pTLVx1D->mEnableCHAP = ((*pAuthentication & 0x00000002) != 0);
offset += tlvx1DSz;
}
// Add IP Address, if specified
if (pIPAddress != 0)
{
// Check size
WORD tlvx1ESz = sizeof( sWDSModifyProfileRequest_IPAddress );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx1ESz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x1E;
pHeader->mLength = tlvx1ESz;
offset += sizeof( sQMIRawContentHeader );
sWDSModifyProfileRequest_IPAddress * pTLVx1E;
pTLVx1E = (sWDSModifyProfileRequest_IPAddress*)(pOut + offset);
memset( pTLVx1E, 0, tlvx1ESz );
ULONG ip0 = (*pIPAddress & 0x000000FF);
ULONG ip1 = (*pIPAddress & 0x0000FF00) >> 8;
ULONG ip2 = (*pIPAddress & 0x00FF0000) >> 16;
ULONG ip3 = (*pIPAddress & 0xFF000000) >> 24;
// Set the value
pTLVx1E->mIPV4Address[0] = (INT8)ip0;
pTLVx1E->mIPV4Address[1] = (INT8)ip1;
pTLVx1E->mIPV4Address[2] = (INT8)ip2;
pTLVx1E->mIPV4Address[3] = (INT8)ip3;
offset += tlvx1ESz;
}
// At least one of the optional parameters must have been set
if (offset <= sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_INVALID_ARG;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackGetDefaultProfile
DESCRIPTION:
This function reads the default profile settings from the device, the
default profile is used during autoconnect
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
profileType [ I ] - Profile type being read
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackGetDefaultProfile(
ULONG * pOutLen,
BYTE * pOut,
ULONG profileType )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add profileType
// Check size
WORD tlvx01Sz = sizeof( sWDSGetDefaultSettingsRequest_ProfileType );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSGetDefaultSettingsRequest_ProfileType * pTLVx01;
pTLVx01 = (sWDSGetDefaultSettingsRequest_ProfileType*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the value
pTLVx01->mProfileType = (eQMIProfileTypes)profileType;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetDefaultProfile
DESCRIPTION:
This function reads the default profile settings from the device, the
default profile is used during autoconnect
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pPDPType [ O ] - PDP type
pIPAddress [ O ] - Preferred assigned IPv4 address
pPrimaryDNS [ O ] - Primary DNS IPv4 address
pSecondaryDNS [ O ] - Secondary DNS IPv4 address
pAuthentication [ O ] - Authentication algorithm bitmap
nameSize [ I ] - The maximum number of characters (including
NULL terminator) that the profile name array
can contain
pName [ O ] - The profile name or description
apnSize [ I ] - The maximum number of characters (including
NULL terminator) that the APN name array
can contain
pAPNName [ O ] - Access point name represented as a NULL
terminated string (empty string returned when
unknown)
userSize [ I ] - The maximum number of characters (including
NULL terminator) that the username array
can contain
pUsername [ O ] - Username used during authentication
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetDefaultProfile(
ULONG inLen,
const BYTE * pIn,
ULONG * pPDPType,
ULONG * pIPAddress,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS,
ULONG * pAuthentication,
BYTE nameSize,
CHAR * pName,
BYTE apnSize,
CHAR * pAPNName,
BYTE userSize,
CHAR * pUsername )
{
// Validate arguments
if (pIn == 0
|| pPDPType == 0
|| pIPAddress == 0
|| pPrimaryDNS == 0
|| pSecondaryDNS == 0
|| pAuthentication == 0
|| nameSize == 0
|| pName == 0
|| apnSize == 0
|| pAPNName == 0
|| userSize == 0
|| pUsername == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Set defaults
*pPDPType = 0xffffffff;
*pIPAddress = 0xffffffff;
*pPrimaryDNS = 0xffffffff;
*pSecondaryDNS = 0xffffffff;
*pAuthentication = 0xffffffff;
pName[0] = 0;
pAPNName[0] = 0;
pUsername[0] = 0;
// Find the name
const sWDSGetDefaultSettingsResponse_ProfileName * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc == eGOBI_ERR_NONE)
{
if (nameSize < outLenx10 + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( pName, (const BYTE *)pTLVx10, outLenx10 );
// Null terminate
pName[outLenx10] = 0;
}
// Find the PDP type
const sWDSGetDefaultSettingsResponse_PDPType * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx11 < sizeof( sWDSGetDefaultSettingsResponse_PDPType ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pPDPType = pTLVx11->mPDPType;
}
// Find the APN name
const sWDSGetDefaultSettingsResponse_APNName * pTLVx14;
ULONG outLenx14;
rc = GetTLV( inLen, pIn, 0x14, &outLenx14, (const BYTE **)&pTLVx14 );
if (rc == eGOBI_ERR_NONE)
{
if (apnSize < outLenx14 + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( pAPNName, (const BYTE *)pTLVx14, outLenx14 );
// Null terminate
pAPNName[outLenx14] = 0;
}
// Find the Primary DNS
const sWDSGetDefaultSettingsResponse_PrimaryDNS * pTLVx15;
ULONG outLenx15;
rc = GetTLV( inLen, pIn, 0x15, &outLenx15, (const BYTE **)&pTLVx15 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx15 < sizeof( sWDSGetDefaultSettingsResponse_PrimaryDNS ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx15->mIPV4Address[0];
ULONG ip1 = pTLVx15->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx15->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx15->mIPV4Address[3] << 24;
*pPrimaryDNS = (ip0 | ip1 | ip2 | ip3);
}
// Find the Secondary DNS
const sWDSGetDefaultSettingsResponse_SecondaryDNS * pTLVx16;
ULONG outLenx16;
rc = GetTLV( inLen, pIn, 0x16, &outLenx16, (const BYTE **)&pTLVx16 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx16 < sizeof( sWDSGetDefaultSettingsResponse_SecondaryDNS ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx16->mIPV4Address[0];
ULONG ip1 = pTLVx16->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx16->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx16->mIPV4Address[3] << 24;
*pSecondaryDNS = (ip0 | ip1 | ip2 | ip3);
}
// Find the Username
const sWDSGetDefaultSettingsResponse_APNName * pTLVx1B;
ULONG outLenx1B;
rc = GetTLV( inLen, pIn, 0x1B, &outLenx1B, (const BYTE **)&pTLVx1B );
if (rc == eGOBI_ERR_NONE)
{
if (userSize < outLenx1B + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( pAPNName, (const BYTE *)pTLVx1B, outLenx1B );
// Null terminate
pAPNName[outLenx1B] = 0;
}
// Find the Authentication
const sWDSGetDefaultSettingsResponse_Authentication * pTLVx1D;
ULONG outLenx1D;
rc = GetTLV( inLen, pIn, 0x1D, &outLenx1D, (const BYTE **)&pTLVx1D );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx1D < sizeof( sWDSGetDefaultSettingsResponse_Authentication ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG pap = pTLVx1D->mEnablePAP;
ULONG chap = pTLVx1D->mEnableCHAP << 1;
*pAuthentication = (pap | chap);
}
// Find the IP Address
const sWDSGetDefaultSettingsResponse_IPAddress * pTLVx1E;
ULONG outLenx1E;
rc = GetTLV( inLen, pIn, 0x1E, &outLenx1E, (const BYTE **)&pTLVx1E );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx1E < sizeof( sWDSGetDefaultSettingsResponse_IPAddress ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx1E->mIPV4Address[0];
ULONG ip1 = pTLVx1E->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx1E->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx1E->mIPV4Address[3] << 24;
*pIPAddress = (ip0 | ip1 | ip2 | ip3);
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackStartDataSession
DESCRIPTION:
This function activates a packet data session
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pTechnology [ I ] - (Optional) Technology bitmap
pPrimaryDNS [ I ] - (Optional) Primary DNS IPv4 address
pSecondaryDNS [ I ] - (Optional) Secondary DNS IPv4 address
pPrimaryNBNS [ I ] - (Optional) Primary NetBIOS NS IPv4 address
pSecondaryNBNS [ I ] - (Optional) Secondary NetBIOS NS IPv4 address
pAPNName [ I ] - (Optional) Access point name
pIPAddress [ I ] - (Optional) Preferred assigned IPv4 address
pAuthentication [ I ] - (Optional) Authentication algorithm bitmap
pUsername [ I ] - (Optional) Username used during authentication
pPassword [ I ] - (Optional) Password used during authentication
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackStartDataSession(
ULONG * pOutLen,
BYTE * pOut,
ULONG * pTechnology,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS,
ULONG * pPrimaryNBNS,
ULONG * pSecondaryNBNS,
CHAR * pAPNName,
ULONG * pIPAddress,
ULONG * pAuthentication,
CHAR * pUsername,
CHAR * pPassword )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
sQMIRawContentHeader * pHeader;
ULONG offset = 0;
// Add technology, if specified
if (pTechnology != 0)
{
// Check size
WORD tlvx30Sz = sizeof( sWDSStartNetworkInterfaceRequest_TechnologyPreference );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx30Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x30;
pHeader->mLength = tlvx30Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_TechnologyPreference * pTLVx30;
pTLVx30 = (sWDSStartNetworkInterfaceRequest_TechnologyPreference*)(pOut + offset);
memset( pTLVx30, 0, tlvx30Sz );
// Set the value
pTLVx30->mEnable3GPP = ((*pTechnology & 0x00000001) != 0);
pTLVx30->mEnable3GPP2 = ((*pTechnology & 0x00000002) != 0);
offset += tlvx30Sz;
}
// Add Primary DNS, if specified
if (pPrimaryDNS != 0)
{
// Check size
WORD tlvx10Sz = sizeof( sWDSStartNetworkInterfaceRequest_PrimaryDNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_PrimaryDNS * pTLVx10;
pTLVx10 = (sWDSStartNetworkInterfaceRequest_PrimaryDNS*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
ULONG ip0 = (*pPrimaryDNS & 0x000000FF);
ULONG ip1 = (*pPrimaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryDNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pPrimaryDNS & 0xFF000000) >> 24;
// Set the value
pTLVx10->mIPV4Address[0] = (INT8)ip0;
pTLVx10->mIPV4Address[1] = (INT8)ip1;
pTLVx10->mIPV4Address[2] = (INT8)ip2;
pTLVx10->mIPV4Address[3] = (INT8)ip3;
offset += tlvx10Sz;
}
// Add Secondary DNS, if specified
if (pSecondaryDNS != 0)
{
// Check size
WORD tlvx11Sz = sizeof( sWDSStartNetworkInterfaceRequest_SecondaryDNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_SecondaryDNS * pTLVx11;
pTLVx11 = (sWDSStartNetworkInterfaceRequest_SecondaryDNS*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
ULONG ip0 = (*pSecondaryDNS & 0x000000FF);
ULONG ip1 = (*pSecondaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryDNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pSecondaryDNS & 0xFF000000) >> 24;
// Set the value
pTLVx11->mIPV4Address[0] = (INT8)ip0;
pTLVx11->mIPV4Address[1] = (INT8)ip1;
pTLVx11->mIPV4Address[2] = (INT8)ip2;
pTLVx11->mIPV4Address[3] = (INT8)ip3;
offset += tlvx11Sz;
}
// Add Primary NBNS, if specified
if (pPrimaryNBNS != 0)
{
// Check size
WORD tlvx12Sz = sizeof( sWDSStartNetworkInterfaceRequest_PrimaryNBNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx12Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x12;
pHeader->mLength = tlvx12Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_PrimaryNBNS * pTLVx12;
pTLVx12 = (sWDSStartNetworkInterfaceRequest_PrimaryNBNS*)(pOut + offset);
memset( pTLVx12, 0, tlvx12Sz );
ULONG ip0 = (*pPrimaryNBNS & 0x000000FF);
ULONG ip1 = (*pPrimaryNBNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryNBNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pPrimaryNBNS & 0xFF000000) >> 24;
// Set the value
pTLVx12->mIPV4Address[0] = (INT8)ip0;
pTLVx12->mIPV4Address[1] = (INT8)ip1;
pTLVx12->mIPV4Address[2] = (INT8)ip2;
pTLVx12->mIPV4Address[3] = (INT8)ip3;
offset += tlvx12Sz;
}
// Add Secondary NBNS, if specified
if (pSecondaryNBNS != 0)
{
// Check size
WORD tlvx13Sz = sizeof( sWDSStartNetworkInterfaceRequest_SecondaryNBNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx13Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x13;
pHeader->mLength = tlvx13Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_SecondaryNBNS * pTLVx13;
pTLVx13 = (sWDSStartNetworkInterfaceRequest_SecondaryNBNS*)(pOut + offset);
memset( pTLVx13, 0, tlvx13Sz );
ULONG ip0 = (*pSecondaryNBNS & 0x000000FF);
ULONG ip1 = (*pSecondaryNBNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryNBNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pSecondaryNBNS & 0xFF000000) >> 24;
// Set the value
pTLVx13->mIPV4Address[0] = (INT8)ip0;
pTLVx13->mIPV4Address[1] = (INT8)ip1;
pTLVx13->mIPV4Address[2] = (INT8)ip2;
pTLVx13->mIPV4Address[3] = (INT8)ip3;
offset += tlvx13Sz;
}
// Add APN Name, if specified
if (pAPNName != 0)
{
std::string apnName( pAPNName );
// Check size
WORD tlvx14Sz = (WORD)apnName.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx14Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x14;
pHeader->mLength = tlvx14Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), apnName.c_str(), apnName.size() );
offset += tlvx14Sz;
}
// Add IP Address, if specified
if (pIPAddress != 0)
{
// Check size
WORD tlvx15Sz = sizeof( sWDSStartNetworkInterfaceRequest_IPAddress );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx15Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x15;
pHeader->mLength = tlvx15Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_IPAddress * pTLVx15;
pTLVx15 = (sWDSStartNetworkInterfaceRequest_IPAddress*)(pOut + offset);
memset( pTLVx15, 0, tlvx15Sz );
ULONG ip0 = (*pIPAddress & 0x000000FF);
ULONG ip1 = (*pIPAddress & 0x0000FF00) >> 8;
ULONG ip2 = (*pIPAddress & 0x00FF0000) >> 16;
ULONG ip3 = (*pIPAddress & 0xFF000000) >> 24;
// Set the value
pTLVx15->mIPV4Address[0] = (INT8)ip0;
pTLVx15->mIPV4Address[1] = (INT8)ip1;
pTLVx15->mIPV4Address[2] = (INT8)ip2;
pTLVx15->mIPV4Address[3] = (INT8)ip3;
offset += tlvx15Sz;
}
// Add Authentication, if specified
if (pAuthentication != 0)
{
// Check size
WORD tlvx16Sz = sizeof( sWDSStartNetworkInterfaceRequest_Authentication );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx16Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x16;
pHeader->mLength = tlvx16Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSStartNetworkInterfaceRequest_Authentication * pTLVx16;
pTLVx16 = (sWDSStartNetworkInterfaceRequest_Authentication*)(pOut + offset);
memset( pTLVx16, 0, tlvx16Sz );
// Set the value
pTLVx16->mEnablePAP = ((*pAuthentication & 0x00000001) != 0);
pTLVx16->mEnableCHAP = ((*pAuthentication & 0x00000002) != 0);
offset += tlvx16Sz;
}
// Add Username, if specified
if (pUsername != 0)
{
std::string username( pUsername );
// Check size
WORD tlvx17Sz = (WORD)username.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx17Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x17;
pHeader->mLength = tlvx17Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), username.c_str(), username.size() );
offset += tlvx17Sz;
}
// Add Password, if specified
if (pPassword != 0)
{
std::string password( pPassword );
// Check size
WORD tlvx18Sz = (WORD)password.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx18Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x18;
pHeader->mLength = tlvx18Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), password.c_str(), password.size() );
offset += tlvx18Sz;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseStartDataSession
DESCRIPTION:
This function activates a packet data session
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pSessionId [ O ] - The assigned session ID
pFailureReason [ O ] - Upon call failure the failure reason provided
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseStartDataSession(
ULONG inLen,
const BYTE * pIn,
ULONG * pSessionId,
ULONG * pFailureReason )
{
// Validate arguments
if (pIn == 0
|| pSessionId == 0
|| pFailureReason == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Check mandatory response
const sResultCode * pTLVx02;
ULONG outLenx02;
ULONG rc = GetTLV( inLen, pIn, 0x02, &outLenx02, (const BYTE **)&pTLVx02 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
if (outLenx02 < sizeof( sResultCode ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
if (pTLVx02->mQMIResult != eQMIResults_Success)
{
rc = pTLVx02->mQMIError + eGOBI_ERR_QMI_OFFSET;
}
if (rc != eGOBI_ERR_NONE)
{
// Still parse call end reason, if present
const sWDSStartNetworkInterfaceResponse_CallEndReason * pTLVx10;
ULONG outLenx10;
ULONG rc2 = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc2 == eGOBI_ERR_NONE)
{
if (outLenx10 >= sizeof( sWDSStartNetworkInterfaceResponse_CallEndReason ))
{
*pFailureReason = pTLVx10->mCallEnd;
}
}
return rc;
}
// Find the Session ID
const sWDSStartNetworkInterfaceResponse_PacketDataHandle * pTLVx01;
ULONG outLenx01;
rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx01 < sizeof( sWDSStartNetworkInterfaceResponse_PacketDataHandle ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pSessionId = pTLVx01->mPacketDataHandle;
}
// Session ID is mandatory, if it failed return that error
return rc;
}
/*===========================================================================
METHOD:
PackStopDataSession
DESCRIPTION:
This function stops the current data session
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
sessionId [ I ] - The ID of the session to terminate
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackStopDataSession(
ULONG * pOutLen,
BYTE * pOut,
ULONG sessionId )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add session ID
// Check size
WORD tlvx01Sz = sizeof( sWDSStopNetworkInterfaceRequest_PacketDataHandle );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSStopNetworkInterfaceRequest_PacketDataHandle * pTLVx01;
pTLVx01 = (sWDSStopNetworkInterfaceRequest_PacketDataHandle*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the value
pTLVx01->mPacketDataHandle = sessionId;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackGetIPAddress
DESCRIPTION:
This function returns the current packet data session IP address
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackGetIPAddress(
ULONG * pOutLen,
BYTE * pOut )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Request the settings
// Check size
WORD tlvx10Sz = sizeof( sWDSGetCurrentSettingsRequest_RequestedSettings );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSGetCurrentSettingsRequest_RequestedSettings * pTLVx10;
pTLVx10 = (sWDSGetCurrentSettingsRequest_RequestedSettings*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mIPAddress = true;
offset += tlvx10Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetIPAddress
DESCRIPTION:
This function returns the current packet data session IP address
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pIPAddress [ O ] - Assigned IPv4 address
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetIPAddress(
ULONG inLen,
const BYTE * pIn,
ULONG * pIPAddress )
{
// Validate arguments
if (pIn == 0 || pIPAddress == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the IP Address
const sWDSGetDefaultSettingsResponse_IPAddress * pTLVx1E;
ULONG outLenx1E;
ULONG rc = GetTLV( inLen, pIn, 0x1E, &outLenx1E, (const BYTE **)&pTLVx1E );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx1E < sizeof( sWDSGetDefaultSettingsResponse_IPAddress ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx1E->mIPV4Address[0];
ULONG ip1 = pTLVx1E->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx1E->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx1E->mIPV4Address[3] << 24;
*pIPAddress = (ip0 | ip1 | ip2 | ip3);
}
// If no IP address is found, fail
return rc;
}
/*===========================================================================
METHOD:
ParseGetConnectionRate
DESCRIPTION:
This function returns connection rate information for the packet data
connection
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pCurrentChannelTXRate [ O ] - Current channel TX rate (bps)
pCurrentChannelRXRate [ O ] - Current channel RX rate (bps)
pMaxChannelTXRate [ O ] - Maximum channel TX rate (bps)
pMaxChannelRXRate [ O ] - Maximum channel RX rate (bps)
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetConnectionRate(
ULONG inLen,
const BYTE * pIn,
ULONG * pCurrentChannelTXRate,
ULONG * pCurrentChannelRXRate,
ULONG * pMaxChannelTXRate,
ULONG * pMaxChannelRXRate )
{
// Validate arguments
if (pIn == 0
|| pCurrentChannelTXRate == 0
|| pCurrentChannelRXRate == 0
|| pMaxChannelTXRate == 0
|| pMaxChannelRXRate == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the rates
const sWDSGetChannelRatesResponse_ChannelRates * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx01 < sizeof( sWDSGetChannelRatesResponse_ChannelRates ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Get the values
*pCurrentChannelTXRate = pTLVx01->mChannelTXRatebps;
*pCurrentChannelRXRate = pTLVx01->mChannelRXRatebps;
*pMaxChannelTXRate = pTLVx01->mMaxChannelTXRatebps;
*pMaxChannelRXRate = pTLVx01->mMaxChannelRXRatebps;
}
// If no rates are found, fail
return rc;
}
/*===========================================================================
METHOD:
PackGetPacketStatus
DESCRIPTION:
This function returns the packet data transfer statistics since the start
of the current packet data session
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackGetPacketStatus(
ULONG * pOutLen,
BYTE * pOut )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Request the settings
// Check size
WORD tlvx01Sz = sizeof( sWDSGetPacketStatisticsRequest_PacketStatsMask );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSGetPacketStatisticsRequest_PacketStatsMask * pTLVx01;
pTLVx01 = (sWDSGetPacketStatisticsRequest_PacketStatsMask*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
pTLVx01->mReportTXPacketSuccesses = true;
pTLVx01->mReportRXPacketSuccesses = true;
pTLVx01->mReportTXPacketErrors = true;
pTLVx01->mReportRXPacketErrors = true;
pTLVx01->mReportTXOverflows = true;
pTLVx01->mReportRXOverflows = true;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetPacketStatus
DESCRIPTION:
This function returns the packet data transfer statistics since the start
of the current packet data session
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pTXPacketSuccesses [ O ] - Packets transmitted without error
pRXPacketSuccesses [ O ] - Packets received without error
pTXPacketErrors [ O ] - Outgoing packets with framing errors
pRXPacketErrors [ O ] - Incoming packets with framing errors
pTXPacketOverflows [ O ] - Packets dropped because TX buffer overflowed
pRXPacketOverflows [ O ] - Packets dropped because RX buffer overflowed
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetPacketStatus(
ULONG inLen,
const BYTE * pIn,
ULONG * pTXPacketSuccesses,
ULONG * pRXPacketSuccesses,
ULONG * pTXPacketErrors,
ULONG * pRXPacketErrors,
ULONG * pTXPacketOverflows,
ULONG * pRXPacketOverflows )
{
// Validate arguments
if (pIn == 0
|| pTXPacketSuccesses == 0
|| pRXPacketSuccesses == 0
|| pTXPacketErrors == 0
|| pRXPacketErrors == 0
|| pTXPacketOverflows == 0
|| pRXPacketOverflows == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// NOTE: All TLVs are required. If any fail then all fail
// Find the TX packet sucesses
const sWDSGetPacketStatisticsResponse_TXPacketSuccesses * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx10 < sizeof( sWDSGetPacketStatisticsResponse_TXPacketSuccesses ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Find the RX packet sucesses
const sWDSGetPacketStatisticsResponse_RXPacketSuccesses * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx11 < sizeof( sWDSGetPacketStatisticsResponse_RXPacketSuccesses ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Find the TX packet errors
const sWDSGetPacketStatisticsResponse_TXPacketErrors * pTLVx12;
ULONG outLenx12;
rc = GetTLV( inLen, pIn, 0x12, &outLenx12, (const BYTE **)&pTLVx12 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx12 < sizeof( sWDSGetPacketStatisticsResponse_TXPacketErrors ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Find the RX packet errors
const sWDSGetPacketStatisticsResponse_RXPacketErrors * pTLVx13;
ULONG outLenx13;
rc = GetTLV( inLen, pIn, 0x13, &outLenx13, (const BYTE **)&pTLVx13 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx13 < sizeof( sWDSGetPacketStatisticsResponse_RXPacketErrors ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Find the TX packet overflows
const sWDSGetPacketStatisticsResponse_TXOverflows * pTLVx14;
ULONG outLenx14;
rc = GetTLV( inLen, pIn, 0x14, &outLenx14, (const BYTE **)&pTLVx14 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx14 < sizeof( sWDSGetPacketStatisticsResponse_TXOverflows ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Find the RX packet overflows
const sWDSGetPacketStatisticsResponse_RXOverflows * pTLVx15;
ULONG outLenx15;
rc = GetTLV( inLen, pIn, 0x15, &outLenx15, (const BYTE **)&pTLVx15 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx15 < sizeof( sWDSGetPacketStatisticsResponse_RXOverflows ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Populate the statistics
*pTXPacketSuccesses = pTLVx10->mTXPacketSuccesses;
*pRXPacketSuccesses = pTLVx11->mRXPacketSuccesses;
*pTXPacketErrors = pTLVx12->mTXPacketErrors;
*pRXPacketErrors = pTLVx13->mRXPacketErrors;
*pTXPacketOverflows = pTLVx14->mTXOverflows;
*pRXPacketOverflows = pTLVx15->mRXOverflows;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackGetByteTotals
DESCRIPTION:
This function returns the RX/TX byte counts since the start of the
current packet data session
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackGetByteTotals(
ULONG * pOutLen,
BYTE * pOut )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Request the settings
// Check size
WORD tlvx01Sz = sizeof( sWDSGetPacketStatisticsRequest_PacketStatsMask );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSGetPacketStatisticsRequest_PacketStatsMask * pTLVx01;
pTLVx01 = (sWDSGetPacketStatisticsRequest_PacketStatsMask*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
pTLVx01->mTXByteTotal = true;
pTLVx01->mRXByteTotal = true;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetByteTotals
DESCRIPTION:
This function returns the RX/TX byte counts since the start of the
current packet data session
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pTXTotalBytes [ O ] - Bytes transmitted without error
pRXTotalBytes [ O ] - Bytes received without error
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetByteTotals(
ULONG inLen,
const BYTE * pIn,
ULONGLONG * pTXTotalBytes,
ULONGLONG * pRXTotalBytes )
{
// Validate arguments
if (pIn == 0
|| pTXTotalBytes == 0
|| pRXTotalBytes == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// NOTE: All TLVs are required. If any fail then all fail
// Find the TX bytes
const sWDSGetPacketStatisticsResponse_TXBytes * pTLVx19;
ULONG outLenx19;
ULONG rc = GetTLV( inLen, pIn, 0x19, &outLenx19, (const BYTE **)&pTLVx19 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx19 < sizeof( sWDSGetPacketStatisticsResponse_TXBytes ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Find the RX bytes
const sWDSGetPacketStatisticsResponse_RXBytes * pTLVx1A;
ULONG outLenx1A;
rc = GetTLV( inLen, pIn, 0x1A, &outLenx1A, (const BYTE **)&pTLVx1A );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx1A < sizeof( sWDSGetPacketStatisticsResponse_RXBytes ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
}
else
{
return rc;
}
// Populate the statistics
*pTXTotalBytes = pTLVx19->mTXByteTotal;
*pRXTotalBytes = pTLVx1A->mRXByteTotal;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackSetMobileIP
DESCRIPTION:
This function sets the current mobile IP setting
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
mode [ I ] - Desired mobile IP setting
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetMobileIP(
ULONG * pOutLen,
BYTE * pOut,
ULONG mode )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Set the mode
// Check size
WORD tlvx01Sz = sizeof( sWDSSetMIPModeRequest_MobileIPMode );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSSetMIPModeRequest_MobileIPMode * pTLVx01;
pTLVx01 = (sWDSSetMIPModeRequest_MobileIPMode*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
pTLVx01->mMIPMode = (eQMIMobileIPModes)mode;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetMobileIP
DESCRIPTION:
This function gets the current mobile IP setting
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pMode [ O ] - Current mobile IP setting
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetMobileIP(
ULONG inLen,
const BYTE * pIn,
ULONG * pMode )
{
// Validate arguments
if (pIn == 0 || pMode == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the mode
const sWDSGetMIPModeResponse_MobileIPMode * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx01 < sizeof( sWDSGetMIPModeResponse_MobileIPMode ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pMode = pTLVx01->mMIPMode;
}
return rc;
}
/*===========================================================================
METHOD:
PackSetActiveMobileIPProfile
DESCRIPTION:
This function sets the active mobile IP profile index
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pSPC [ I ] - Six digit service programming code
index [ I ] - Desired mobile IP profile index
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetActiveMobileIPProfile(
ULONG * pOutLen,
BYTE * pOut,
CHAR * pSPC,
BYTE index )
{
// Validate arguments
if (pOut == 0 || pSPC == 0 || pSPC[0] == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
std::string spc( pSPC );
if (spc.size() > 6)
{
return eGOBI_ERR_INVALID_ARG;
}
if (spc.find_first_not_of( "0123456789" ) != std::string::npos )
{
return eGOBI_ERR_INVALID_ARG;
}
// Check size
WORD tlvx01Sz = sizeof( sWDSSetActiveMIPProfileRequest_Index );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSSetActiveMIPProfileRequest_Index * pTLVx01;
pTLVx01 = (sWDSSetActiveMIPProfileRequest_Index*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
memcpy( &pTLVx01->mSPC[0], spc.c_str(), spc.size() );
pTLVx01->mProfileIndex = index;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetActiveMobileIPProfile
DESCRIPTION:
This function gets the the active mobile IP profile index
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pIndex [ O ] - Active mobile IP profile index
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetActiveMobileIPProfile(
ULONG inLen,
const BYTE * pIn,
BYTE * pIndex )
{
// Validate arguments
if (pIn == 0 || pIndex == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the mode
const sWDSGetActiveMIPProfileResponse_Index * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx01 < sizeof( sWDSGetActiveMIPProfileResponse_Index ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pIndex = pTLVx01->mProfileIndex;
}
return rc;
}
/*===========================================================================
METHOD:
PackSetMobileIPProfile
DESCRIPTION:
This function sets the specified mobile IP profile settings
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pSPC [ I ] - Six digit service programming code
index [ I ] - Mobile IP profile ID
pEnabled [ I ] - (Optional) Enable MIP profile?
pAddress [ I ] - (Optional) Home IPv4 address
pPrimaryHA [ I ] - (Optional) Primary home agent IPv4 address
pSecondaryHA [ I ] - (Optional) Secondary home agent IPv4 address
bRevTunneling [ I ] - (Optional) Enable reverse tunneling?
pNAI [ I ] - (Optional) Network access identifier string
pHASPI [ I ] - (Optional) HA security parameter index
pAAASPI [ I ] - (Optional) AAA security parameter index
pMNHA [ I ] - (Optional) MN-HA string
pMNAAA [ I ] - (Optional) MN-AAA string
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetMobileIPProfile(
ULONG * pOutLen,
BYTE * pOut,
CHAR * pSPC,
BYTE index,
BYTE * pEnabled,
ULONG * pAddress,
ULONG * pPrimaryHA,
ULONG * pSecondaryHA,
BYTE * pRevTunneling,
CHAR * pNAI,
ULONG * pHASPI,
ULONG * pAAASPI,
CHAR * pMNHA,
CHAR * pMNAAA )
{
// Validate arguments
if (pOut == 0 || pSPC == 0 || pSPC[0] == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
std::string spc( pSPC );
if (spc.size() > 6)
{
return eGOBI_ERR_INVALID_ARG;
}
if (spc.find_first_not_of( "0123456789" ) != std::string::npos )
{
return eGOBI_ERR_INVALID_ARG;
}
// Check size
WORD tlvx01Sz = sizeof( sWDSSetMIPProfileRequest_Index );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_Index * pTLVx01;
pTLVx01 = (sWDSSetMIPProfileRequest_Index*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
memcpy( &pTLVx01->mSPC[0], spc.c_str(), spc.size() );
pTLVx01->mProfileIndex = index;
offset += tlvx01Sz;
// Add Enabled, if specified
if (pEnabled != 0)
{
// Check size
WORD tlvx10Sz = sizeof( sWDSSetMIPProfileRequest_State );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_State * pTLVx10;
pTLVx10 = (sWDSSetMIPProfileRequest_State*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mEnabled = (*pEnabled == 0 ? 0 : 1);
offset += tlvx10Sz;
}
// Add Home Address, if specified
if (pAddress != 0)
{
// Check size
WORD tlvx11Sz = sizeof( sWDSSetMIPProfileRequest_HomeAddress );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_HomeAddress * pTLVx11;
pTLVx11 = (sWDSSetMIPProfileRequest_HomeAddress*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
ULONG ip0 = (*pAddress & 0x000000FF);
ULONG ip1 = (*pAddress & 0x0000FF00) >> 8;
ULONG ip2 = (*pAddress & 0x00FF0000) >> 16;
ULONG ip3 = (*pAddress & 0xFF000000) >> 24;
// Set the value
pTLVx11->mIPV4Address[0] = (INT8)ip0;
pTLVx11->mIPV4Address[1] = (INT8)ip1;
pTLVx11->mIPV4Address[2] = (INT8)ip2;
pTLVx11->mIPV4Address[3] = (INT8)ip3;
offset += tlvx11Sz;
}
// Add Primary Home Agent Address, if specified
if (pPrimaryHA != 0)
{
// Check size
WORD tlvx12Sz = sizeof( sWDSSetMIPProfileRequest_PrimaryHomeAgentAddress );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx12Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x12;
pHeader->mLength = tlvx12Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_PrimaryHomeAgentAddress * pTLVx12;
pTLVx12 = (sWDSSetMIPProfileRequest_PrimaryHomeAgentAddress*)(pOut + offset);
memset( pTLVx12, 0, tlvx12Sz );
ULONG ip0 = (*pPrimaryHA & 0x000000FF);
ULONG ip1 = (*pPrimaryHA & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryHA & 0x00FF0000) >> 16;
ULONG ip3 = (*pPrimaryHA & 0xFF000000) >> 24;
// Set the value
pTLVx12->mIPV4Address[0] = (INT8)ip0;
pTLVx12->mIPV4Address[1] = (INT8)ip1;
pTLVx12->mIPV4Address[2] = (INT8)ip2;
pTLVx12->mIPV4Address[3] = (INT8)ip3;
offset += tlvx12Sz;
}
// Add Secondary Home Agent Address, if specified
if (pSecondaryHA != 0)
{
// Check size
WORD tlvx13Sz = sizeof( sWDSSetMIPProfileRequest_SecondaryHomeAgentAddress );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx13Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x13;
pHeader->mLength = tlvx13Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_SecondaryHomeAgentAddress * pTLVx13;
pTLVx13 = (sWDSSetMIPProfileRequest_SecondaryHomeAgentAddress*)(pOut + offset);
memset( pTLVx13, 0, tlvx13Sz );
ULONG ip0 = (*pSecondaryHA & 0x000000FF);
ULONG ip1 = (*pSecondaryHA & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryHA & 0x00FF0000) >> 16;
ULONG ip3 = (*pSecondaryHA & 0xFF000000) >> 24;
// Set the value
pTLVx13->mIPV4Address[0] = (INT8)ip0;
pTLVx13->mIPV4Address[1] = (INT8)ip1;
pTLVx13->mIPV4Address[2] = (INT8)ip2;
pTLVx13->mIPV4Address[3] = (INT8)ip3;
offset += tlvx13Sz;
}
// Add reverse tunneling, if specified
if (pRevTunneling != 0)
{
// Check size
WORD tlvx14Sz = sizeof( sWDSSetMIPProfileRequest_ReverseTunneling );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx14Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x14;
pHeader->mLength = tlvx14Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_ReverseTunneling * pTLVx14;
pTLVx14 = (sWDSSetMIPProfileRequest_ReverseTunneling*)(pOut + offset);
memset( pTLVx14, 0, tlvx14Sz );
// Set the value
pTLVx14->mReverseTunneling = (*pRevTunneling == 0 ? 0 : 1);
offset += tlvx14Sz;
}
// Add NAI, if specified
if (pNAI != 0)
{
std::string nai( pNAI );
// Check size
WORD tlvx15Sz = (WORD)nai.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx15Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x15;
pHeader->mLength = tlvx15Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), nai.c_str(), nai.size() );
offset += tlvx15Sz;
}
// Add HA SPI, if specified
if (pHASPI != 0)
{
// Check size
WORD tlvx16Sz = sizeof( sWDSSetMIPProfileRequest_HASPI );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx16Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x16;
pHeader->mLength = tlvx16Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequest_HASPI * pTLVx16;
pTLVx16 = (sWDSSetMIPProfileRequest_HASPI*)(pOut + offset);
memset( pTLVx16, 0, tlvx16Sz );
// Set the value
pTLVx16->mHASPI = *pHASPI;
offset += tlvx16Sz;
}
// Add AAA SPI, if specified
if (pAAASPI != 0)
{
// Check size
WORD tlvx17Sz = sizeof( sWDSSetMIPProfileRequeste_AAASPI );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx17Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x17;
pHeader->mLength = tlvx17Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPProfileRequeste_AAASPI * pTLVx17;
pTLVx17 = (sWDSSetMIPProfileRequeste_AAASPI*)(pOut + offset);
memset( pTLVx17, 0, tlvx17Sz );
// Set the value
pTLVx17->mAAASPI = *pAAASPI;
offset += tlvx17Sz;
}
// Add MN-HA key, if specified
if (pMNHA != 0)
{
std::string mnha( pMNHA );
// Check size
WORD tlvx18Sz = (WORD)mnha.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx18Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x18;
pHeader->mLength = tlvx18Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), mnha.c_str(), mnha.size() );
offset += tlvx18Sz;
}
// Add MN-AAA key, if specified
if (pMNHA != 0)
{
std::string mnaaa( pMNAAA );
// Check size
WORD tlvx19Sz = (WORD)mnaaa.size();
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx19Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x19;
pHeader->mLength = tlvx19Sz;
offset += sizeof( sQMIRawContentHeader );
// Set the value
memcpy( (pOut + offset), mnaaa.c_str(), mnaaa.size() );
offset += tlvx19Sz;
}
// At least one of the optional parameters must have been set
if (offset <= sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_INVALID_ARG;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackGetMobileIPProfile
DESCRIPTION:
This function gets the specified mobile IP profile settings
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
index [ I ] - Mobile IP profile ID
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackGetMobileIPProfile(
ULONG * pOutLen,
BYTE * pOut,
BYTE index )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Check size
WORD tlvx01Sz = sizeof( sWDSGetMIPProfileRequest_Index );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSGetMIPProfileRequest_Index * pTLVx01;
pTLVx01 = (sWDSGetMIPProfileRequest_Index*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
pTLVx01->mProfileIndex = index;
offset += tlvx01Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetMobileIPProfile
DESCRIPTION:
This function gets the specified mobile IP profile settings
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pEnabled [ O ] - Mobile IP profile enabled?
pAddress [ O ] - Home IPv4 address
pPrimaryHA [ O ] - Primary home agent IPv4 address
pSecondaryHA [ O ] - Secondary home agent IPv4 address
pRevTunneling [ O ] - Reverse tunneling enabled?
naiSize [ I ] - The maximum number of characters (including NULL
terminator) that the NAI array can contain
pNAI [ O ] - Network access identifier string
pHASPI [ O ] - HA security parameter index
pAAASPI [ O ] - AAA security parameter index
pHAState [ O ] - HA key state
pAAAState [ O ] - AAA key state
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetMobileIPProfile(
ULONG inLen,
const BYTE * pIn,
BYTE * pEnabled,
ULONG * pAddress,
ULONG * pPrimaryHA,
ULONG * pSecondaryHA,
BYTE * pRevTunneling,
BYTE naiSize,
CHAR * pNAI,
ULONG * pHASPI,
ULONG * pAAASPI,
ULONG * pHAState,
ULONG * pAAAState )
{
// Validate arguments
if (pIn == 0
|| pEnabled == 0
|| pAddress == 0
|| pPrimaryHA == 0
|| pSecondaryHA == 0
|| pRevTunneling == 0
|| naiSize == 0
|| pNAI == 0
|| pHASPI == 0
|| pAAASPI == 0
|| pHAState == 0
|| pAAAState == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Assume errors
*pEnabled = 0xff;
*pAddress = 0xffffffff;
*pPrimaryHA = 0xffffffff;
*pSecondaryHA = 0xffffffff;
*pRevTunneling = 0xff;
*pHASPI = 0xffffffff;
*pAAASPI = 0xffffffff;
*pHAState = 0xffffffff;
*pAAAState = 0xffffffff;
// Find the State
const sWDSGetMIPProfileResponse_State * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx10 < sizeof( sWDSGetMIPProfileResponse_State ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pEnabled = pTLVx10->mEnabled;
}
// Find the Home Address
const sWDSGetMIPProfileResponse_HomeAddress * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx11 < sizeof( sWDSGetMIPProfileResponse_HomeAddress ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx11->mIPV4Address[0];
ULONG ip1 = pTLVx11->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx11->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx11->mIPV4Address[3] << 24;
*pAddress = (ip0 | ip1 | ip2 | ip3);
}
// Find the Primary Home Agent Address
const sWDSGetMIPProfileResponse_PrimaryHomeAgentAddress * pTLVx12;
ULONG outLenx12;
rc = GetTLV( inLen, pIn, 0x12, &outLenx12, (const BYTE **)&pTLVx12 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx12 < sizeof( sWDSGetMIPProfileResponse_PrimaryHomeAgentAddress ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx12->mIPV4Address[0];
ULONG ip1 = pTLVx12->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx12->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx12->mIPV4Address[3] << 24;
*pPrimaryHA = (ip0 | ip1 | ip2 | ip3);
}
// Find the Secondary Home Agent Address
const sWDSGetMIPProfileResponse_SecondaryHomeAgentAddress * pTLVx13;
ULONG outLenx13;
rc = GetTLV( inLen, pIn, 0x13, &outLenx13, (const BYTE **)&pTLVx13 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx13 < sizeof( sWDSGetMIPProfileResponse_SecondaryHomeAgentAddress ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx13->mIPV4Address[0];
ULONG ip1 = pTLVx13->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx13->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx13->mIPV4Address[3] << 24;
*pSecondaryHA = (ip0 | ip1 | ip2 | ip3);
}
// Find the Reverse tunneling, if enabled
const sWDSGetMIPProfileResponse_ReverseTunneling * pTLVx14;
ULONG outLenx14;
rc = GetTLV( inLen, pIn, 0x14, &outLenx14, (const BYTE **)&pTLVx14 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx10 < sizeof( sWDSGetMIPProfileResponse_ReverseTunneling ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pRevTunneling = pTLVx14->mReverseTunneling;
}
// Find the NAI, if enabled
const sWDSGetMIPProfileResponse_NAI * pTLVx15;
ULONG outLenx15;
rc = GetTLV( inLen, pIn, 0x15, &outLenx15, (const BYTE **)&pTLVx15 );
if (rc == eGOBI_ERR_NONE)
{
if (naiSize < outLenx15 + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( pNAI, (const BYTE *)pTLVx15, outLenx15 );
// Null terminate
pNAI[outLenx15] = 0;
}
// Find the HA SPI
const sWDSGetMIPProfileResponse_HASPI * pTLVx16;
ULONG outLenx16;
rc = GetTLV( inLen, pIn, 0x16, &outLenx16, (const BYTE **)&pTLVx16 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx16 < sizeof( sWDSGetMIPProfileResponse_HASPI ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pHASPI = pTLVx16->mHASPI;
}
// Find the AAA SPI
const sWDSGetMIPProfileResponse_AAASPI * pTLVx17;
ULONG outLenx17;
rc = GetTLV( inLen, pIn, 0x17, &outLenx17, (const BYTE **)&pTLVx17 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx17 < sizeof( sWDSGetMIPProfileResponse_AAASPI ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pAAASPI = pTLVx17->mAAASPI;
}
// Find the HA state
const sWDSGetMIPProfileResponse_HAState * pTLVx1A;
ULONG outLenx1A;
rc = GetTLV( inLen, pIn, 0x1A, &outLenx1A, (const BYTE **)&pTLVx1A );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx1A < sizeof( sWDSGetMIPProfileResponse_HAState ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pHAState = pTLVx1A->mKeyState;
}
// Find the AAA state
const sWDSGetMIPProfileResponse_AAAState * pTLVx1B;
ULONG outLenx1B;
rc = GetTLV( inLen, pIn, 0x1B, &outLenx1B, (const BYTE **)&pTLVx1B );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx1B < sizeof( sWDSGetMIPProfileResponse_AAAState ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pAAAState = pTLVx1B->mKeyState;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackSetMobileIPParameters
DESCRIPTION:
This function sets the specified mobile IP parameters
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pSPC [ I ] - Six digit service programming code
pMode [ I ] - (Optional) Desired mobile IP setting
pRetryLimit [ I ] - (Optional) Retry attempt limit
pRetryInterval [ I ] - (Optional) Retry attempt interval
pReRegPeriod [ I ] - (Optional) Re-registration period
pReRegTraffic [ I ] - (Optional) Re-registration only with traffic?
pHAAuthenticator [ I ] - (Optional) MH-HA authenticator calculator?
pHA2002bis [ I ] - (Optional) MH-HA RFC 2002bis authentication?
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetMobileIPParameters(
ULONG * pOutLen,
BYTE * pOut,
CHAR * pSPC,
ULONG * pMode,
BYTE * pRetryLimit,
BYTE * pRetryInterval,
BYTE * pReRegPeriod,
BYTE * pReRegTraffic,
BYTE * pHAAuthenticator,
BYTE * pHA2002bis )
{
// Validate arguments
if (pOut == 0 || pSPC == 0 || pSPC[0] == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
std::string spc( pSPC );
if (spc.size() > 6)
{
return eGOBI_ERR_INVALID_ARG;
}
if (spc.find_first_not_of( "0123456789" ) != std::string::npos )
{
return eGOBI_ERR_INVALID_ARG;
}
// Check size
WORD tlvx01Sz = sizeof( sWDSSetMIPParametersRequest_SPC );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_SPC * pTLVx01;
pTLVx01 = (sWDSSetMIPParametersRequest_SPC*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the values
memcpy( &pTLVx01->mSPC[0], spc.c_str(), spc.size() );
offset += tlvx01Sz;
// Add Mode, if specified
if (pMode != 0)
{
// Check size
WORD tlvx10Sz = sizeof( sWDSSetMIPParametersRequest_MobileIPMode );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_MobileIPMode * pTLVx10;
pTLVx10 = (sWDSSetMIPParametersRequest_MobileIPMode*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mMIPMode = (eQMIMobileIPModes)*pMode;
offset += tlvx10Sz;
}
// Add Retry Limit, if specified
if (pRetryLimit != 0)
{
// Check size
WORD tlvx11Sz = sizeof( sWDSSetMIPParametersRequest_RetryAttemptLimit );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_RetryAttemptLimit * pTLVx11;
pTLVx11 = (sWDSSetMIPParametersRequest_RetryAttemptLimit*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
// Set the value
pTLVx11->mRetryAttemptLimit = *pRetryLimit;
offset += tlvx11Sz;
}
// Add Retry interval, if specified
if (pRetryInterval != 0)
{
// Check size
WORD tlvx12Sz = sizeof( sWDSSetMIPParametersRequest_RetryAttemptInterval );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx12Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x12;
pHeader->mLength = tlvx12Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_RetryAttemptInterval * pTLVx12;
pTLVx12 = (sWDSSetMIPParametersRequest_RetryAttemptInterval*)(pOut + offset);
memset( pTLVx12, 0, tlvx12Sz );
// Set the value
pTLVx12->mRetryAttemptInterval = *pRetryInterval;
offset += tlvx12Sz;
}
// Add Re-registration period, if specified
if (pReRegPeriod != 0)
{
// Check size
WORD tlvx13Sz = sizeof( sWDSSetMIPParametersRequest_ReRegistrationPeriod );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx13Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x13;
pHeader->mLength = tlvx13Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_ReRegistrationPeriod * pTLVx13;
pTLVx13 = (sWDSSetMIPParametersRequest_ReRegistrationPeriod*)(pOut + offset);
memset( pTLVx13, 0, tlvx13Sz );
// Set the value
pTLVx13->mReRegistrationPeriod = *pReRegPeriod;
offset += tlvx13Sz;
}
// Add Re-registration on traffic flag, if specified
if (pReRegTraffic != 0)
{
// Check size
WORD tlvx14Sz = sizeof( sWDSSetMIPParametersRequest_ReRegistrationOnlyWithTraffic );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx14Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x14;
pHeader->mLength = tlvx14Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_ReRegistrationOnlyWithTraffic * pTLVx14;
pTLVx14 = (sWDSSetMIPParametersRequest_ReRegistrationOnlyWithTraffic*)(pOut + offset);
memset( pTLVx14, 0, tlvx14Sz );
// Set the value
pTLVx14->mReRegistrationOnlyWithTraffic = (*pReRegTraffic == 0 ? 0 : 1);
offset += tlvx14Sz;
}
// Add HA authenticator flag, if specified
if (pHAAuthenticator != 0)
{
// Check size
WORD tlvx15Sz = sizeof( sWDSSetMIPParametersRequest_MNHAAuthenticatorCalculator );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx15Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x15;
pHeader->mLength = tlvx15Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_MNHAAuthenticatorCalculator * pTLVx15;
pTLVx15 = (sWDSSetMIPParametersRequest_MNHAAuthenticatorCalculator*)(pOut + offset);
memset( pTLVx15, 0, tlvx15Sz );
// Set the value
pTLVx15->mMNHAAuthenticatorCalculator = (*pHAAuthenticator == 0 ? 0 : 1);
offset += tlvx15Sz;
}
// Add HA RFC2002bis authentication flag, if specified
if (pHA2002bis != 0)
{
// Check size
WORD tlvx16Sz = sizeof( sWDSSetMIPParametersRequest_MNHARFC2002BISAuthentication );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx16Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x16;
pHeader->mLength = tlvx16Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetMIPParametersRequest_MNHARFC2002BISAuthentication * pTLVx16;
pTLVx16 = (sWDSSetMIPParametersRequest_MNHARFC2002BISAuthentication*)(pOut + offset);
memset( pTLVx16, 0, tlvx16Sz );
// Set the value
pTLVx16->mMNHARFC2002BISAuthentication = (*pHA2002bis == 0 ? 0 : 1);
offset += tlvx16Sz;
}
// At least one of the optional parameters must have been set
if (offset <= sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_INVALID_ARG;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetMobileIPParameters
DESCRIPTION:
This function gets the mobile IP parameters
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pMode [ O ] - Current mobile IP setting
pRetryLimit [ O ] - Retry attempt limit
pRetryInterval [ O ] - Retry attempt interval
pReRegPeriod [ O ] - Re-registration period
pReRegTraffic [ O ] - Re-registration only with traffic?
pHAAuthenticator [ O ] - MH-HA authenticator calculator?
pHA2002bis [ O ] - MH-HA RFC 2002bis authentication?
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetMobileIPParameters(
ULONG inLen,
const BYTE * pIn,
ULONG * pMode,
BYTE * pRetryLimit,
BYTE * pRetryInterval,
BYTE * pReRegPeriod,
BYTE * pReRegTraffic,
BYTE * pHAAuthenticator,
BYTE * pHA2002bis )
{
// Validate arguments
if (pIn == 0
|| pMode == 0
|| pRetryLimit == 0
|| pRetryInterval == 0
|| pReRegPeriod == 0
|| pReRegTraffic == 0
|| pHAAuthenticator == 0
|| pHA2002bis == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
*pMode = 0xffffffff;
*pRetryLimit = 0xff;
*pRetryInterval = 0xff;
*pReRegPeriod = 0xff;
*pReRegTraffic = 0xff;
*pHAAuthenticator = 0xff;
*pHA2002bis = 0xff;
// Find the mode
const sWDSGetMIPParametersResponse_MobileIPMode * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx10 < sizeof( sWDSGetMIPParametersResponse_MobileIPMode ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pMode = pTLVx10->mMIPMode;
}
// Find the Retry limit
const sWDSGetMIPParametersResponse_RetryAttemptLimit * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx11 < sizeof( sWDSGetMIPParametersResponse_RetryAttemptLimit ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pRetryLimit = pTLVx11->mRetryAttemptLimit;
}
// Find the Retry Interval
const sWDSGetMIPParametersResponse_RetryAttemptInterval * pTLVx12;
ULONG outLenx12;
rc = GetTLV( inLen, pIn, 0x12, &outLenx12, (const BYTE **)&pTLVx12 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx12 < sizeof( sWDSGetMIPParametersResponse_RetryAttemptInterval ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pRetryInterval = pTLVx12->mRetryAttemptInterval;
}
// Find the Re-registration period
const sWDSGetMIPParametersResponse_ReRegistrationPeriod * pTLVx13;
ULONG outLenx13;
rc = GetTLV( inLen, pIn, 0x13, &outLenx13, (const BYTE **)&pTLVx13 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx13 < sizeof( sWDSGetMIPParametersResponse_ReRegistrationPeriod ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pReRegPeriod = pTLVx13->mReRegistrationPeriod;
}
// Find the Re-register on traffic flag
const sWDSGetMIPParametersResponse_ReRegistrationOnlyWithTraffic * pTLVx14;
ULONG outLenx14;
rc = GetTLV( inLen, pIn, 0x14, &outLenx14, (const BYTE **)&pTLVx14 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx14 < sizeof( sWDSGetMIPParametersResponse_ReRegistrationOnlyWithTraffic ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pReRegTraffic = pTLVx14->mReRegistrationOnlyWithTraffic;
}
// Find the HA authenticator
const sWDSGetMIPParametersResponse_MNHAAuthenticatorCalculator * pTLVx15;
ULONG outLenx15;
rc = GetTLV( inLen, pIn, 0x15, &outLenx15, (const BYTE **)&pTLVx15 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx15 < sizeof( sWDSGetMIPParametersResponse_MNHAAuthenticatorCalculator ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pHAAuthenticator = pTLVx15->mMNHAAuthenticatorCalculator;
}
// Find the HA RFC2002bis authentication flag
const sWDSGetMIPParametersResponse_MNHARFC2002BISAuthentication * pTLVx16;
ULONG outLenx16;
rc = GetTLV( inLen, pIn, 0x16, &outLenx16, (const BYTE **)&pTLVx16 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx16 < sizeof( sWDSGetMIPParametersResponse_MNHARFC2002BISAuthentication ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pHA2002bis = pTLVx16->mMNHARFC2002BISAuthentication;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetLastMobileIPError
DESCRIPTION:
This function gets the last mobile IP error
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pError [ O ] - Last mobile IP error
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetLastMobileIPError(
ULONG inLen,
const BYTE * pIn,
ULONG * pError )
{
// Validate arguments
if (pIn == 0 || pError == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the TLV
const sWDSGetLastMIPStatusResponse_Status * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx01 < sizeof( sWDSGetLastMIPStatusResponse_Status ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pError = pTLVx01->mLastMIPStatus;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackSetDNSSettings
DESCRIPTION:
This function sets the DNS settings for the device
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pPrimaryDNS [ I ] - (Optional) Primary DNS IPv4 address
pSecondaryDNS [ I ] - (Optional) Secondary DNS IPv4 address
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetDNSSettings(
ULONG * pOutLen,
BYTE * pOut,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS )
{
// Validate arguments
// At least one must be specified
if (pOut == 0 || (pPrimaryDNS == 0 && pSecondaryDNS == 0))
{
return eGOBI_ERR_INVALID_ARG;
}
sQMIRawContentHeader * pHeader;
ULONG offset = 0;
// Add Primary DNS, if specified
if (pPrimaryDNS != 0)
{
// Check size
WORD tlvx10Sz = sizeof( sWDSSetDNSSettingRequest_PrimaryDNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetDNSSettingRequest_PrimaryDNS * pTLVx10;
pTLVx10 = (sWDSSetDNSSettingRequest_PrimaryDNS*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
ULONG ip0 = (*pPrimaryDNS & 0x000000FF);
ULONG ip1 = (*pPrimaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryDNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pPrimaryDNS & 0xFF000000) >> 24;
// Set the value
pTLVx10->mIPV4Address[0] = (INT8)ip0;
pTLVx10->mIPV4Address[1] = (INT8)ip1;
pTLVx10->mIPV4Address[2] = (INT8)ip2;
pTLVx10->mIPV4Address[3] = (INT8)ip3;
offset += tlvx10Sz;
}
// Add Secondary DNS, if specified
if (pSecondaryDNS != 0)
{
// Check size
WORD tlvx11Sz = sizeof( sWDSSetDNSSettingRequest_SecondaryDNS );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
offset += sizeof( sQMIRawContentHeader );
sWDSSetDNSSettingRequest_SecondaryDNS * pTLVx11;
pTLVx11 = (sWDSSetDNSSettingRequest_SecondaryDNS*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
ULONG ip0 = (*pSecondaryDNS & 0x000000FF);
ULONG ip1 = (*pSecondaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryDNS & 0x00FF0000) >> 16;
ULONG ip3 = (*pSecondaryDNS & 0xFF000000) >> 24;
// Set the value
pTLVx11->mIPV4Address[0] = (INT8)ip0;
pTLVx11->mIPV4Address[1] = (INT8)ip1;
pTLVx11->mIPV4Address[2] = (INT8)ip2;
pTLVx11->mIPV4Address[3] = (INT8)ip3;
offset += tlvx11Sz;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetDNSSettings
DESCRIPTION:
This function gets the DNS settings for the device
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pPrimaryDNS [ O ] - Primary DNS IPv4 address
pSecondaryDNS [ O ] - Secondary DNS IPv4 address
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetDNSSettings(
ULONG inLen,
const BYTE * pIn,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS )
{
// Validate arguments
if (pIn == 0 || pPrimaryDNS == 0 || pSecondaryDNS == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the Primary DNS
const sWDSGetDNSSettingResponse_PrimaryDNS * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx10 < sizeof( sWDSGetDNSSettingResponse_PrimaryDNS ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx10->mIPV4Address[0];
ULONG ip1 = pTLVx10->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx10->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx10->mIPV4Address[3] << 24;
*pPrimaryDNS = (ip0 | ip1 | ip2 | ip3);
}
// Find the Secondary DNS
const sWDSGetDNSSettingResponse_SecondaryDNS * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc == eGOBI_ERR_NONE)
{
if (outLenx11 < sizeof( sWDSGetDNSSettingResponse_SecondaryDNS ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
ULONG ip0 = pTLVx11->mIPV4Address[0];
ULONG ip1 = pTLVx11->mIPV4Address[1] << 8;
ULONG ip2 = pTLVx11->mIPV4Address[2] << 16;
ULONG ip3 = pTLVx11->mIPV4Address[3] << 24;
*pSecondaryDNS = (ip0 | ip1 | ip2 | ip3);
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseGetDataBearerTechnology
DESCRIPTION:
This function retrieves the current data bearer technology (only
valid when connected)
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pDataCaps [ O ] - The data bearer technology
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetDataBearerTechnology(
ULONG inLen,
const BYTE * pIn,
ULONG * pDataBearer )
{
// Validate arguments
if (pIn == 0 || pDataBearer == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the TLV
const sWDSGetDataBearerTechnologyResponse_Technology * pTLVx01;
ULONG outLenx01;
ULONG rc = GetTLV( inLen, pIn, 0x01, &outLenx01, (const BYTE **)&pTLVx01 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx01 < sizeof( sWDSGetDataBearerTechnologyResponse_Technology ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pDataBearer = pTLVx01->mDataBearerTechnology;
return eGOBI_ERR_NONE;
}