Error -22 in mqtt_connect() - nRF52840dk with Azure IoT Hub using OpenThread and TCP

I am attempting to connect a nRF52840dk to Azure IoT Hub using OpenThread and TCP. I combined the azure_iot_hub and azure_fota samples into one project, which ran successfully on an nRF9160dk using Connect SDK v1.9.1. I have modified that project for a nRF52840dk, OpenThread, TCP, and Connect SDK 2.0.0. I think that I am close, but I am getting error -22 ("invalid argument") in azure_iot_hub.c's mqtt_connect().

Wireshark capture using nRF sniffer:

Serial output (I added the "Error in zsock_connect!" log in mqtt_transport_socket_tls.c):

I've repurposed CONFIG_AZURE_IOT_HUB_STATIC_IPV4 to be an ipv6 address as seen in my prj further below. The getaddrinfo() DNS resolver is working, but I'd have to add a conversion from the returned ipv4 to ipv6 and I'd prefer to bypass that for now unless this is causing the issue. In azure_iot_hub.c's broket_init(), I changed &broker to &broker4 to resolve an error and made some other updates to switch from ipv4 to ipv6. These are the only changes I made in azure_iot_hub.c. The IoT Hub setup is kicked off in main() via err = azure_iot_hub_connect();

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#if defined(CONFIG_AZURE_IOT_HUB_STATIC_IPV4)
static int broker_init(bool dps)
{
//TB changed sockaddr's from sockaddr_in to sockaddr_in6
struct sockaddr_in6 *broker4 =
((struct sockaddr_in6 *)&broker);
//TB changed "AF_INET" to "AF_INET6" twice and "&broker" to "&broker4" on 7/20/22
inet_pton(AF_INET6, CONFIG_AZURE_IOT_HUB_STATIC_IPV4_ADDR,
&broker4->sin6_addr);//&broker->sin_addr);
broker4->sin6_family = AF_INET6;
broker4->sin6_port = htons(CONFIG_AZURE_IOT_HUB_PORT);
//TB added:
char ipv6_addr[NET_IPV6_ADDR_LEN];
inet_ntop(AF_INET6, &broker4->sin6_addr.s6_addr, ipv6_addr,
sizeof(ipv6_addr));
LOG_DBG("IPv6 address set in broker_init to %s", log_strdup(ipv6_addr));
return 0;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

prj.conf:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#
# Copyright (c) 2020 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
# General config
CONFIG_REBOOT=y
CONFIG_DEBUG=y
# Heap and stacks
CONFIG_HEAP_MEM_POOL_SIZE=6144
CONFIG_MAIN_STACK_SIZE=8192
# Log
CONFIG_LOG=y
CONFIG_PRINTK=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PROCESS_THREAD=y
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Certificate format:

Fullscreen
1
2
3
4
"-----BEGIN CA CERTIFICATE-----\n"
"abcd+efgh\n"
"ijkl/mnop\n"
"-----END CA CERTIFICATE-----\n"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Fullscreen
1
2
3
4
"-----BEGIN CLIENT CERTIFICATE-----\n"
"abcd+efgh\n"
"ijkl/mnop\n"
"-----END CLIENT CERTIFICATE-----\n"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Fullscreen
1
2
3
4
"-----BEGIN PRIVATE KEY-----\n"
"abcd+efgh\n"
"ijkl/mnop\n"
"-----END PRIVATE KEY-----\n"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Per this DevZone ticket and this Microsoft documentation, maybe I am missing something with the CBC ciphers and MBedTLS? TCP messages appear to be going back and forth between the IoT Hub MQTT and my OpenThread end device in the Wireshark sniffer trace, so hopefully I am close to the finish line. Thank you in advance for the assistance.

Parents
  • Hi  ,

    Thanks for the pointers! I just switched from using joiner/commissioner to simply specifying channel and networkkey. This enables the client and server boards to begin exchanging the data messages via TCP upon startup. That closes my question in my comment above. I list my client and server prj.conf contents below in case they can be of help to others.

    Client prj.conf (no overlays used...all overlay configs were combined into this prj):

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # Generic networking options
    CONFIG_NETWORKING=y
    CONFIG_NET_UDP=n
    CONFIG_NET_TCP=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_NET_SOCKETS_POLL_MAX=4
    CONFIG_NET_CONNECTION_MANAGER=y
    # Kernel options
    CONFIG_MAIN_STACK_SIZE=4096
    #2048
    CONFIG_ENTROPY_GENERATOR=y
    CONFIG_TEST_RANDOM_GENERATOR=y
    CONFIG_INIT_STACKS=y
    # Logging
    CONFIG_NET_LOG=y
    CONFIG_LOG=y
    CONFIG_NET_STATISTICS=y
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Server prj.conf (no overlays used...all overlay configs were combined into this prj):

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # Generic networking options
    CONFIG_NETWORKING=y
    CONFIG_NET_UDP=n
    CONFIG_NET_TCP=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_NET_CONNECTION_MANAGER=y
    # Kernel options
    CONFIG_MAIN_STACK_SIZE=4096
    #2048
    CONFIG_ENTROPY_GENERATOR=y
    CONFIG_TEST_RANDOM_GENERATOR=y
    CONFIG_INIT_STACKS=y
    # Logging
    CONFIG_NET_LOG=y
    CONFIG_LOG=y
    CONFIG_NET_STATISTICS=y
    CONFIG_PRINTK=y
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Now, I am having trouble enabling TLS. I use the TLS overlay and "$ net tcp connect server:ip:address:here 4242" but see the following error in the server's serial dialog:

    <err> net_echo_server_sample: IPV6 accept error (-22)

    I've also tried modifying the TLS overlay a few ways to no avail. It looks like the TLS "hello" handshake is not occurring as it should after the TCP SYN/ACK process, and I suspect that something might be amiss with my credential configuration? Do you have any recommended prj settings or other advice to get TLS working? Thanks!

  • I will be away until next week, but wanted to share a development regarding the enabling of TLS. Using the prj.conf's below, the client begins the TLS "hello" handshake process but the server gives error "<err> net_echo_server_sample: IPv6 accept error (-113)"

    Client prj.conf:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # Generic networking options
    CONFIG_NETWORKING=y
    CONFIG_NET_UDP=n
    CONFIG_NET_TCP=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_NET_SOCKETS_POLL_MAX=4
    CONFIG_NET_CONNECTION_MANAGER=y
    # Kernel options
    CONFIG_MAIN_STACK_SIZE=4096
    #2048
    CONFIG_ENTROPY_GENERATOR=y
    CONFIG_TEST_RANDOM_GENERATOR=y
    CONFIG_INIT_STACKS=y
    # Logging
    CONFIG_NET_LOG=y
    CONFIG_LOG=y
    CONFIG_NET_STATISTICS=y
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Server prj.conf:

    Fullscreen
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    You can see some other configurations that I have tried from what is commented out. Am I missing a prj.conf setting to enable the proper certificates? Or maybe the certificates are not being attached to the socket properly?

  • Hi,

    Your process now have been:

    1. make TCP work "Thread node <--> Thread node"
    2. Try to make TLS work "Thread node <--> Thread node"

    But your final goal is to be able to MQTT+TLS "Thread node <--> Cloud server", right?
    In this case, can I suggest that you try

    1. make TCP work "Thread node <--> Thread node"
    2. Try to make TCP work "Thread node <--> Cloud server"
    3. Try to make TLS Work "Thread node <--> Cloud server"
    4. Try to make TLS+MQTT Work "Thread node <--> Cloud server"

    This way, you do not need to be able to make a TLS supporting Thread server work.

    Does this make sense, or did I miss in my assumption?

    Regards,
    Sigurd Hellesvik

Reply
  • Hi,

    Your process now have been:

    1. make TCP work "Thread node <--> Thread node"
    2. Try to make TLS work "Thread node <--> Thread node"

    But your final goal is to be able to MQTT+TLS "Thread node <--> Cloud server", right?
    In this case, can I suggest that you try

    1. make TCP work "Thread node <--> Thread node"
    2. Try to make TCP work "Thread node <--> Cloud server"
    3. Try to make TLS Work "Thread node <--> Cloud server"
    4. Try to make TLS+MQTT Work "Thread node <--> Cloud server"

    This way, you do not need to be able to make a TLS supporting Thread server work.

    Does this make sense, or did I miss in my assumption?

    Regards,
    Sigurd Hellesvik

Children