aboutsummaryrefslogtreecommitdiffstats
path: root/gobi-api/Gobi_2011-11-28-1533/Gobi3000Translation/Gobi3000TranslationWDS.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gobi-api/Gobi_2011-11-28-1533/Gobi3000Translation/Gobi3000TranslationWDS.cpp')
-rwxr-xr-xgobi-api/Gobi_2011-11-28-1533/Gobi3000Translation/Gobi3000TranslationWDS.cpp3486
1 files changed, 3486 insertions, 0 deletions
diff --git a/gobi-api/Gobi_2011-11-28-1533/Gobi3000Translation/Gobi3000TranslationWDS.cpp b/gobi-api/Gobi_2011-11-28-1533/Gobi3000Translation/Gobi3000TranslationWDS.cpp
new file mode 100755
index 0000000..9a22144
--- /dev/null
+++ b/gobi-api/Gobi_2011-11-28-1533/Gobi3000Translation/Gobi3000TranslationWDS.cpp
@@ -0,0 +1,3486 @@
+/*===========================================================================
+FILE:
+ Gobi3000TranslationWDS.cpp
+
+DESCRIPTION:
+ QUALCOMM Translation for Gobi 3000 (WDS Service)
+
+Copyright (c) 2011, 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;
+}