The interface between a NIF and the TCP/IP stack.

The network interfaces (NIF's) are registered with the stack using the MNifIfUser::IfUserNewInterfaceL function. Stack has an internal object that represents the interface and the given CNifIfBase object is attached to this.

The stack communicates with the NIF using the public API defined by the CNifIfBase. The NIF sees the stack as an instance of CProtocolBase and can use a subset of public functions to communcite with the stack.

The following CNifBase functions are used by the stack:

  • CNifIfBase::Open, (binding stack and NIF)

  • CNifIfBase::Close, (binding stack and NIF)

  • CNifIfBase::BindL, (binding stack and NIF)

  • CNifIfBase::Control, (for the configuration information)

  • CNifIfBase::Info, (retrieve the interface name)

  • CNifIfBase::Send, (send outbound packets to NIF)

  • CNifIfBase::Notify, (NIFMAN about packet activity)

The following CProtocolBase functions are available for NIFs:

  • CProtocolBase::StartSending, (notify stack that NIF is ready)

  • CProtocolBase::Error, (notify stack about NIF error)

  • CProtocolBase::Process, (feed inbound packets to stack)

The network interface is removed from the stack either by directly deleting it, or by NIFMAN using MNifIfUser::IfUserInterfaceDown.

A pointer to the MNifIfUser object can be obtained from the network layer protocol.
	MNetworkService *iNetwork;
	TPckgBuf<MNifIfUser*> ifUser;
	TInt err = iNetwork->Protocol()->GetOption(KNifOptLevel, KNifOptGetNifIfUser, ifUser);

Binding the NIF and TCP/IP together

MNifIfUser::IfUserNewInterfaceL introduces a new network interface (NIF) to the stack. The introduction consists of the following steps:

  1. retrieve interface info into TNifIfInfo by CNifIfBase::Info function. Stack uses only the interface name (iName) from this. The name cannot be an empty string.

  2. using the name, the stack searches for a matching internal interface object. If it does not exist, it is created. If there was an existing interface with the same name, the stack will disconnect that first.

  3. the stack gives itself to the new NIF by calling CNifIfBase::BindL.

  4. stack does not send any packets to the interface until the NIF has called CProtocolBase::StartSending at least once.

  5. stack executes the interface configuration when the first CProtocolBase::StartSending arrives after MNifIfUser::IfUserNewInterfaceL. The configuration uses the CNifIfBase::Control function with different options to retrieve additional information from the NIF.

MNifIfUser::IfUserInterfaceDown disconnects the NIF from the stack. There is one exception: if the MNifIfUser::IfUserInterfaceDown aResult parameter has a special value KErrLinkConfigChanged, then the internal interface state is only reset to the exact same state as if interface was just introduced by the MNifIfUser::IfUserNewInterfaceL, and a reconfiguration occurs when the NIF calls StartSending.

The Control API

The stack requires the NIF to implement a minimal set of KSOLInterface level options via it's CNifIfBase::Control API.

  • at least one of the information options
    • TSoIfInfo6 with KSoIfInfo6 (for IPv6)

    • TSoIfInfo with KSoIfInfo (for IPv4)

  • at least one of the configuration options
    • TSoInet6IfConfig (iFamily=KAfInet6) with KSoIfConfig

    • TSoInetIfConfig (iFamily=KAfInet) with KSoIfConfig

  • TSoIfHardwareAddr with KSoIfHardwareAddr if the link uses hardware addresses (only used KIfNeedsND is also set.). The returned address is used in the neighbor discovery (ICMPv6 ND or ARP for IPv4), and in sending packets to NIF, the address family is used to indicate that the stack has chosen the destination link layer address (based on the neighbor cache).

  • TSoIfConnectionInfo with KSoIfGetConnectionInfo (for IAP and NET numbers). If this is not supported, the stack will assign unique numbers for the IAP and NET. The scope vector (zone identifiers) is contructed as follows:
    1. [0] The unique interface index (node local scope id)

    2. [1] IAP number (link scope id)

    3. [2] IAP number (subnet scope id)

    4. [3] NET number

    5. [4] NET number (site local scope id)

    6. [5] NET number

    7. [6] NET number

    8. [7] NET number (organization scope id)

    9. [8] NET number

    10. [9] NET number

    11. [10] NET number

    12. [11] NET number

    13. [12] NET number

    14. [13] NET number (IPv6 global scope)

    15. [14] NET number

    16. [15] NET number (highest, NET id, IPv4 global)


To build complete ARP packets in the stack, stack needs to know the hardware type value to be used in the packet (see TInet6HeaderArp). This 16 bit value is assumed to be in the Port() field of the returned hardware address (KSoIfHardwareAddr). An IPv4 NIF that leaves the ARP to the stack, must provide this value (or sniff and fix the outgoing ARP packets).

Inbound packets from the NIF to stack.

The NIF feeds the inbound packets to the stack through the CProtocolBase::Process function (see also MNetworkService::Process). The information block associated with the packet is RMBufPktInfo and the fields must have been set as follows:

  • RMBufPktInfo::iSrcAddr, the link layer source address (using the same address family as returned with the hardware address control option). If the link does not use addresses, then KAFUnspec should be used.

  • RMBufPktInfo::iDstAddr, the link layer destination address (using the same address family as returned with the hardware address control option). If the link does not use addresses, then KAFUnspec should be used.

  • RMBufPktInfo::iProtocol, the type of the packet:
    • KProtocolInetIp, IPv4 packet

    • KProtocolInet6Ip, IPv6 packet

    • KProtocolArp, ARP packet

  • RMBufPktInfo::iLength, the length of the packet in octets

  • RMBufPktInfo::iFlags, should be set to zero (reserved for future use).


The stack is relaxed about the checking of iProtocol field, and anything else except KProtocolArp is assumed to be an IP packet. This is potentially to changed in future, and NIFs should set the protocol field correctly.

The link layer addresses in iSrcAddr and iDstAddr are informative. The values do not affect the processing of the packet within stack. They are made available for the inbound post hooks (CProtocolPosthook).

Outbound packets from the stack to NIF

The stack feeds the outbound packets to the NIF through the CNifIfBase::Send function. The information block associated with the packet follows RMBufPktInfo and the fields need to be interpreted as follows:

  • RMBufPktInfo::iSrcAddr, undefined (must be ignored by the NIF). The NIF must choose the link layer source address.

  • RMBufPktInfo::iDstAddr, three variants, if link layer addresses are used
    • hardware address, using the same address family as NIF returned in harware address control option (TSoIfHardwareAddr ). The packet must be sent to this link layer destination.

    • KAfInet, the address is IPv4 multicast address. and the NIF must select a suitable link layer broadcast address as a destination.

    • KAfInet6, the address is IPv6 multicast address, and the NIF msut select a suitable link layer broadcast address as a destination.

    If the NIF does not use link layer addresses, then iDstAddr is also undefined (must be ingnored byt the NIF). The link is a point-to-point interface.
  • RMBufPktInfo::iProtocol, defines the type of packet
    • KProtocolInetIp, IPv4 packet

    • KProtocolInet6Ip, IPv6 packet

    • KProtocolArp, ARP packet

  • RMBufPktInfo::iLength, the length of the packet in octets.

  • RMBufPktInfo::iFlags, undefined (must be igrnored by the NIF).

The stack interprets the return value from the CNifIfBase::Send as follows:

  • return 1; the NIF is ready to receive more packets.

  • return 0; the NIF is blocked and cannot receive any more packets. The stack does not send anything to the NIF until it calls CProtocolBase::StartSending.

  • return < 0; unspecified, but currently, the error is passed on to all flows attached to this interface. The stack will continue sending packets to the interface (no StartSending is required).

  • return > 1; unspecified, but currently treated same as return 1.