Writing
the RNDIS Control Application
The RNDIS Control Application needs to handle notifications to
start and stop the uplink. It also needs to configure the NAPT protocol.
The RNDIS Control
Application needs to do the following:
Handle notifications
to start and stop the uplink
The RNDIS Agent uses Publish & Subscribe
(P&S) to provide the RNDIS Control Application with RNDIS connection events
and the Uplink Requirement Notification.
Configure the Network
Address and Port Translation (NAPT) protocol
The NAPT component has
been implemented as IP hooks that modify the IP headers of traffic that is
being transferred between a private and public network. IP hooks are implemented
as protocols and therefore to attach the NAPT IP hooks the NAPT protocol has
to be loaded.
Device creators can start the RNDIS Control Application at either
of the following times:
Note: To ensure the RNDIS Control Application does not miss
the uplink notifications from RNDIS Service, it must start before the RNDIS
Service starts.
The USB Control Application stops the RNDIS
Control Application by killing the RNDIS Control Application process. Then
it stops the RNDIS Service. The Kernel helps to close the handle of the P&S
Key and to stop the AO.
The header
file rndis.h provides
the PID. The header file
rndisuiinterfaces.h provides
the typedef for
TRndisConnectionEvent and
TRndisUplinkRequirementValue.
// Keys to be defined in C32 process (Using C32 process SID as the
//Category 0x101F7989)
static const TUint KKeyRndisConnectionEvent = 0x10286a96;
static const TUint KKeyRndisUplinkRequirement = 0x10286a97;
enum TRndisConnectionEvent
{
ERndisConnectionEstablished, // RNDIS connection established
ERndisConnectionDestroyed, // RNDIS connection destroyed
};
enum TRndisUplinkRequirementValue
{
ERndisUplinkRequired,
ERndisUplinkNotRequired
Note: A process to write these keys must have NetworkControl capability.
The RNDIS Control Application must start an AO and subscribe to the
P&S key: KKeyRndisUplinkRequirement. Then the RNDIS Control
Application must interpret the Connection Event buffer.
The following code shows how to interpret the buffer of the P&S
key:KKeyRndisConnectionEvent:
const TUid KC32ExeSid = {0x101F7989};
rndisConnectionEventProp.Attach(KC32ExeSid, KKeyRndisConnectionEvent)
Tint32 rndisState;
TRndisConnectionEventPckg pckg;
TInt err = rndisConnectionEventProp.Get(pckg);
rndisState = pckg().iEvent;
switch (rndisState)
{
case ERndisConnectionEstablished:
{
TRndisConnectionEventPayloadEstablished &payload =
reinterpret_cast< TRndisConnectionEventPayloadEstablished&>
(pckg ().iPayload[0]);
// Access every field in TRndisConnectionEventPayloadEstablished
// through reference payload.
}
break;
case ERndisConnectionDestroyed:
{
TRndisConnectionEventPayloadDestroyed &payload =
reinterpret_cast< TRndisConnectionEventPayloadDestroyed&>
(pckg ().iPayload[0]);
// Access every field in TRndisConnectionEventPayloadDestroyed
through reference payload.
}
break;
}
When the control application receives the notification ERndisUplinkRequired,
it must do the following:
Get the RNDIS IAP ID from the notification. Then interpret the Uplink
Requirement Buffer.
The following code shows how to interpret the buffer of P&S key KKeyRndisUplinkRequirement:
const TUid KC32ExeSid = {0x101F7989};
rndisUplinkProp.Attach(KC32ExeSid, KKeyRndisUplinkRequirement)
TInt err = rndisUplinkProp.Get(uplinkReq);
switch(uplinkReq().iValue)
{
case ERndisUplinkRequired:
{
TRndisUplinkRequirementPayloadRequired &payload =
reinterpret_cast<TRndisUplinkRequirementPayloadRequired&>
(uplinkReq().iPayload[0]);
// Access every field in TRndisUplinkRequirementPayloadRequired
// through reference payload.
}
break;
case ERndisUplinkNotRequired:
// There is no field in payload for ERndisUplinkNotRequired.
break;
}
Then the RNDIS Control Application must retrieve the Uplink IAP ID from
the Central Repository. (For retrieving the Uplink IAP ID, the device creator
can use other methods, such as retrieving from an INI file.)
Configure the NAPT protocol.
If the RNDIS IAP ID and Uplink IAP ID are retrieved successfully, the
RNDIS Control Application tries to start uplink connection specified by the
Uplink IAP ID and to load NAPT.
IP hooks are implemented as protocols and therefore to attach the NAPT
IP hooks the NAPT protocol has to be loaded, this can be done as follows:
if (iNaptSocket.Open(iSockServ, _L("napt")) == KErrNone)
{
// NAPT successfully loaded, can now be configured
}
If the NAPT protocol is loaded successfully, it must then be configured
before any traffic will be successfully forwarded with translated addresses.
To configure NAPT, a packaged TInterfaceLockInfo structure
has to be passed to a SetOpt call as follows for example:
iNaptInfo().iPublicIap = iUplinkIapId;;
iNaptInfo().iPublicIp.SetAddress(iPublicAddr);
iNaptInfo().iPrivateIap = iRndisIapId;
iNaptInfo().iPrivateIp.SetAddress(iPrivateAddr);
iNaptInfo().iNetmaskLength = 24;
if (iNaptSocket.SetOpt(KSoNaptSetup, KSolNapt, iNaptInfo) == KErrNone)
{
// NAPT successfully configured
}
To ensure that NAPT is configured correctly both the Uplink and the
RNDIS IAP must be started and the corresponding interfaces have the IP addresses
assigned that are used in the NAPT configuration. After configuring NAPT,
you must enable IP forwarding in NAPT:
//This macro introduced by networking to support IP forwarding.
#if defined(SYMBIAN_NETWORKING_ADDRESS_PROVISION)
TPckgBuf<TIpForwardingInfo> ipforwardInfo;
//Set iUplinkAccess to TRUE to enable IP forwarding in NAPT
ipforwardInfo().iUplinkAccess = ETrue;
User::LeaveIfError(iNaptSocket.SetOpt(KSoNaptProvision, KSolNapt,
ipforwardInfo));
#endif
When the control application receives the notification ERndisUplinkNotRequired,
the control application must stop the uplink used by the PC connected using
RNDIS network connection and it must close the NAPT socket.