Site Tools


C API changes for IPv6

These API changes are made because of new requirements of IPv6. They are not the only way to meet the new requirements. They are changes that meet the requirements and minimize changes to the existing C API. Feel free to propose changes to the C API, keeping in mind the new requirements.


  • New definition of OCDevAddr
  • Arguments changed for OCDoResource
  • Backward compatibility
  • Adapter name changes
  • New definition of OCConnectivityType

C API changes

OCDevAddr changes

OCDevAddr has always been used to carry network addressing information from the stack to the application in callbacks. It has been generalized to support the functional changes with IPv6, and it is used to provide explicit addressing in OCDoResource. It now looks like this:

typedef enum {
    OCTransportAdapter_t adapter;
    OCTransportFlags_t flags;
    char addr[MAX_ADDR_STRING_LEN];
    uint32_t interface; // network interface selection (default:0);
    uint16_t port;    // for IP
} OCDevAddr_t;


typedef enum {
    // Value zero indicates default behavior.
    // Default behavior depends on context.  (ALL for discovory)
    OC_IP_ADAPTER = 1,      // IPv4 and IPv6, including 6LoWPAN
    OC_GATT_ADAPTER,        // GATT over Bluetooth LE
    OC_RFCOMM_ADAPTER,      // RFCOMM over Bluetooth EDR
} OCTransportAdapter_t;
typedef enum {
    // IPv4 & IPv6 autoselection is the default
    OC_IP_USE_V6       = (1 << 4),   // IP adapter only
    OC_IP_USE_V4       = (1 << 5),   // IP adapter only

    // Insecure transport is the default (subject to change)
    OC_FLAG_SECURE     = (1 << 6),   // secure the transport path

    // Link-Local multicast is the default multicast scope for IPv6.
    // These are placed here to correspond to the IPv6 address bits.
    OC_SCOPE_INTERFACE = 0x1, // IPv6 Interface-Local scope (loopback)
    OC_SCOPE_LINK      = 0x2, // IPv6 Link-Local scope (default)
    OC_SCOPE_REALM     = 0x3, // IPv6 Realm-Local scope
    OC_SCOPE_ADMIN     = 0x4, // IPv6 Admin-Local scope
    OC_SCOPE_SITE      = 0x5, // IPv6 Site-Local scope
    OC_SCOPE_ORG       = 0x8, // IPv6 Organization-Local scope
} OCTransportFlags_t;

In the general case, all this information must be available to make a network connection, though in some special cases only some of the information is needed. Keep this in mind when considering other changes.

  • The remote address is kept as a string (addr) in all cases.
  • The meaning of the string is determined by the adapter type (adapter) and flags (flags) fields.
    • IPv4 address: adapter type IP and adapter flag IPv4.
    • IPv6 address: adapter type IP and adapter flag IPv6.
    • GATT address: adapter type GATT.
  • The length of the null terminated string is long enough for any possible string.
  • The interface in some circumstances disambiguates network interface selection. A zero indicates use of the default interface, which the adapter can usually identify. It is needed when more than one possible network interface is available:
    • When two Bluetooth interfaces are available (e.g., bnep0 and bnep1), 'interface' identifies which one a particular GATT address applies to.
    • When an IPv6 Link Local address is used and more than one IPv6 interface exists (e.g., eth0 and wlan0), 'interface' identifies which interface to use.
    • When only one such interface exists, the default value zero will work.
    • IPv4 can reliably determine the correct interface in all cases.
    • IPv6 can reliably determine the correct interface unless Link Local addressing is used.
    • When in doubt, set it zero, and the adapter will figure it out.
  • The port is only for IP addressing.

OCDoResource argument changes

OCDoResource is the primary C API function involved with client functionality.

  • The biggest change is the addition of an OCDevAddr argument (*destination). This allows explicit network destination addressing in one place.
  • The addition should not break any existing application. The pointer to an OCDevAddr structure replaces a previously unused argument (*referenceUri). I verified that every call in iotivity/resource calls OCDoResource with a NULL for this argument.
  • The new ‘destination’ argument (OCDevAddr *) provides complete addressing capability.
  • The contents of the OCDevAddr structure are copied in OCDoResource, so the caller is responsible for its lifetime.
  • The C++ code has been modified to use the new argument.
  • A new value has been added to the OCMethod argument. OC_REST_DISCOVERY is used by C++ to explicitly indicate discovery with multicast.

Backward compatibility in OCDoResource

Previously, network addressing in OCDoResource consisted of extracting a network address from the prefix of the resourceUri and combining it with OCConnectivityType. If the OCDoResource destination argument (OCDevAddr *) is set to NULL, this addressing will still work. We should explicitly deprecate the previous addressing while continuing to support it. It order for the old method to support general networking, the OCConnectivityType must be extended.

Adapter name changes

The adapters are now named after the transport protocol the adapter supports rather than the underlying transport device.

  • OC_IP_ADAPTER (formerly OC_IPV4)
  • OC_GATT_ADAPTER (formerly OC_LE)

In the near future, almost all IoTivity Bluetooth traffic will be carried over 6LoWPAN, which uses the IP adapter. The name changes insure that no developer will be confused by whether “LE” refers to 6LoWPan over BLE or GATT over BLE. Another example of its generality is that if we should ever want to use Bluetooth PAN profile over EDR, that it will be entirely independent of using RFCOMM over EDR.


In the new C API this type is only used as an optional argument to OCDoResource, as it provides backward compatibility with previous behavior. The previous behavior involved prepending network addressing on the resourceUri variable, then providing additional information about the connection in OCConnectivityType. The reason it still works is that OCConnectivityType has been modified to contain the enlarged set of information needed for addressing now (i.e., all the information in both OCTransportAdapter and OCTransportFlags.) OCConnectivityType is also used by the C++ API.

Previous to these changes, OCConnectivityType was equivalent to the new OCTransportAdapter enum, which is not sufficient with the latest changes. To be perfectly general, it would need to combine the capabilities of both OCTransportAdapter and OCTransportFlags, but that is a lot to ask of a single enum. For discovery, the OCTransportAdapter part is not needed, but all of OCTransportFlags is needed. For the backward compatible form of OCDoResource, both parts are needed, except for discovery. So OCConnectivityType needs to carry both parts,in general. For subscription, both parts are needed, but there’s no place to put them both, so OCConnectivityType needs to carry them. The solution for this is to provide a type that includes both OCTransportAdapter and OCTransport flags that can be used where OCConnectivityType is called for. The type can’t be an enum because on some platforms (those with 16-bit ints) the enum will be 16-bits, which isn’t big enough for all the needed information in the long run. A struct containing both enums would work but requires every application using OCConnectivityType to be modified. I am not sure what the correct solution is to this connundrum, but I have implemented

typedef enum {
    CT_DEFAULT = 0,                // use when defaults are ok

    #if defined (__UINT32_MAX__) && (__UINT32_MAX__ == 65535) // 16-bit int
    CT_IP_ADAPTER       = 0x1000,  // IPv4 and IPv6, including 6LoWPAN
    CT_GATT_ADAPTER     = 0x2000,  // GATT over Bluetooth LE
    CT_RFCOMM_ADAPTER   = 0x3000,  // RFCOMM over Bluetooth EDR
    #define CT_ADAPTER_SHIFT 12
    #define CT_FLAGS_MASK 0x0FFF
    #else   // assume 32-bit int
    CT_IP_ADAPTER       = 0x10000, // IPv4 and IPv6, including 6LoWPAN
    CT_GATT_ADAPTER     = 0x20000, // GATT over Bluetooth LE
    CT_RFCOMM_ADAPTER   = 0x30000, // RFCOMM over Bluetooth EDR
    #define CT_ADAPTER_SHIFT 16
    #define CT_FLAGS_MASK 0xFFFF

    // IPv4 & IPv6 autoselection is the default
    CT_IP_USE_V6       = (1 << 4), // IP adapter only
    CT_IP_USE_V4       = (1 << 5), // IP adapter only

    // Insecure transport is the default (subject to change)
    CT_FLAG_SECURE     = (1 << 6), // secure the transport path

    // Link-Local multicast is the default multicast scope for IPv6.
    // These are placed here to correspond to the IPv6 address bits.
    CT_SCOPE_INTERFACE = 0x1, // IPv6 Interface-Local scope (loopback)
    CT_SCOPE_LINK      = 0x2, // IPv6 Link-Local scope (default)
    CT_SCOPE_REALM     = 0x3, // IPv6 Realm-Local scope
    CT_SCOPE_ADMIN     = 0x4, // IPv6 Admin-Local scope
    CT_SCOPE_SITE      = 0x5, // IPv6 Site-Local scope
    CT_SCOPE_ORG       = 0x8, // IPv6 Organization-Local scope
    CT_SCOPE_GLOBAL    = 0xE, // IPv6 Global scope
} OCConnectivityType;

The preprocessor commands are given so OCConnectivityType will fit in the 16-bit enum of some constrained platforms (e.g., Arduino). This limits expandability on those platforms.

c_api_changes_for_ipv6.txt · Last modified: 2015/06/08 15:46 by rightbrain