I am using:
nRF52840DK
nRF5 SDK for Thread and Zigbee v4.1.0
CLI example with added code
Border Router on Raspberry Pi 3+
Using the CLI, I can get an IPv6 address for a remote website:
> dns resolve ipv4.google.com fdde:ad00:beef:0:3467:65f8:4139:dad5 > DNS response for ipv4.google.com - 64:ff9b:0:0:0:0:8efb:6f8a TTL: 60 Done
I need to do this in the firmware, so tried the following:
otIp6Address m_mesh_address;
otIp6Address m_host_address;
const char GOOGLE[] = "ipv4.google.com";
void dns_response_handler(void * aContext, const char * aHostname, const otIp6Address *aAddress, uint32_t aTtl, otError aResult)
{
char ipv6_str[40] = {0};
if ((aResult == OT_ERROR_NONE) && (aAddress != NULL))
udp_address_to_string(ipv6_str, aAddress, sizeof(ipv6_str));
NRF_LOG_INFO("DNS response: %s %s TTL %d error %d\r\n", aHostname, ipv6_str, aTtl, aResult);
}
static void thread_state_changed_callback(uint32_t flags, void * p_context)
{
bool addr_found = false;
otSockAddr sock_addr;
otOperationalDataset dataset;
otDeviceRole role = otThreadGetDeviceRole(p_context);
NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n",
flags, otThreadGetDeviceRole(p_context));
if (role >= OT_DEVICE_ROLE_CHILD)
{
otError err;
err = otDatasetGetActive( thread_ot_instance_get(), &dataset);
// Mesh local ipv6 address
for (const otNetifAddress *address = otIp6GetUnicastAddresses(thread_ot_instance_get()); address; address = address->mNext)
{
// Mesh local only, not RLOC address
if ((address->mAddress.mFields.m8[0] == 0xfd) && !address->mRloc && !addr_found)
{
addr_found = true;
sock_addr.mAddress = address->mAddress;
m_mesh_address = address->mAddress;
}
}
if (addr_found)
{
for (int i=0; i<OT_MESH_LOCAL_PREFIX_SIZE; i++)
m_host_address.mFields.m8[i] = dataset.mMeshLocalPrefix.m8[i]; // copy mesh local prefix
// Raspberry Pi
m_host_address.mFields.m16[4] = 0x0000;
m_host_address.mFields.m16[5] = 0x6734;
m_host_address.mFields.m16[6] = 0xf865;
m_host_address.mFields.m16[7] = 0xd5da; // RLOC16 of border router
otDnsQuery query;
otMessageInfo msgInfo;
msgInfo.mPeerAddr = m_host_address;
msgInfo.mPeerPort = OT_DNS_DEFAULT_SERVER_PORT; //53
msgInfo.mIsHostInterface = false;
msgInfo.mAllowZeroHopLimit = false;
msgInfo.mSockAddr = m_mesh_address;
msgInfo.mSockPort = 0;
query.mHostname = GOOGLE;
query.mMessageInfo = &msgInfo;
query.mNoRecursion = false;
err = otDnsClientQuery(thread_ot_instance_get(),
&query,
dns_response_handler,
NULL);
NRF_LOG_INFO("DnsClientQuery(): err = %d\n\r", err);
}
}
}
The result is:
<info> app: State changed! Flags: 0x00001035 Current role: 1 <info> app: State changed! Flags: 0x00801064 Current role: 3 <info> app: DnsClientQuery(): err = 0 <info> app: State changed! Flags: 0x00000200 Current role: 3 <info> app: DnsClientQuery(): err = 0 <info> app: DNS response: ipv4.google.com `ÿ ÿ + TTL 0 error 28 <info> app: DNS response: ipv4.google.com `ÿ ÿ + TTL 0 error 28
Error 28 is a response timeout.
How do you get an IPV6 address in firmware? Is there an example? (I couldn't find one).
Thanks,
Mary