diff options
Diffstat (limited to 'gobi-api/GobiAPI_2012-09-12-0719/Gobi3000Translation/Gobi3000TranslationWDS.cpp')
-rwxr-xr-x | gobi-api/GobiAPI_2012-09-12-0719/Gobi3000Translation/Gobi3000TranslationWDS.cpp | 3486 |
1 files changed, 3486 insertions, 0 deletions
diff --git a/gobi-api/GobiAPI_2012-09-12-0719/Gobi3000Translation/Gobi3000TranslationWDS.cpp b/gobi-api/GobiAPI_2012-09-12-0719/Gobi3000Translation/Gobi3000TranslationWDS.cpp new file mode 100755 index 0000000..c202fd9 --- /dev/null +++ b/gobi-api/GobiAPI_2012-09-12-0719/Gobi3000Translation/Gobi3000TranslationWDS.cpp @@ -0,0 +1,3486 @@ +/*=========================================================================== +FILE: + Gobi3000TranslationWDS.cpp + +DESCRIPTION: + QUALCOMM Translation for Gobi 3000 (WDS Service) + +Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum 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; +} |