diff --git a/include/net/lwm2m.h b/include/net/lwm2m.h index dd7627a7306c1e..abaea7c3403a20 100644 --- a/include/net/lwm2m.h +++ b/include/net/lwm2m.h @@ -61,13 +61,10 @@ struct lwm2m_ctx { struct coap_reply replies[CONFIG_LWM2M_ENGINE_MAX_REPLIES]; struct k_delayed_work retransmit_work; -#if defined(CONFIG_NET_APP_DTLS) - /** Pre-Shared Key Information*/ - unsigned char *client_psk; - size_t client_psk_len; - char *client_psk_id; - size_t client_psk_id_len; + /* current security object index */ + int sec_obj_inst; +#if defined(CONFIG_NET_APP_DTLS) /** DTLS support structures */ char *cert_host; u8_t *dtls_result_buf; @@ -233,16 +230,16 @@ int lwm2m_engine_set_net_pkt_pool(struct lwm2m_ctx *ctx, net_pkt_get_slab_func_t tx_slab, net_pkt_get_pool_func_t data_pool); #endif -int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, - char *peer_str, u16_t peer_port); +int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, bool is_bootstrap_mode); /* LWM2M RD Client */ /* Client events */ enum lwm2m_rd_client_event { LWM2M_RD_CLIENT_EVENT_NONE, - LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_FAILURE, - LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_COMPLETE, + LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE, + LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE, + LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE, LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE, LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE, @@ -256,7 +253,6 @@ typedef void (*lwm2m_ctx_event_cb_t)(struct lwm2m_ctx *ctx, enum lwm2m_rd_client_event event); int lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, - char *peer_str, u16_t peer_port, const char *ep_name, lwm2m_ctx_event_cb_t event_cb); diff --git a/samples/net/lwm2m_client/overlay-dtls.conf b/samples/net/lwm2m_client/overlay-dtls.conf index eb1c154537c8c4..6a0de691896eb5 100644 --- a/samples/net/lwm2m_client/overlay-dtls.conf +++ b/samples/net/lwm2m_client/overlay-dtls.conf @@ -6,3 +6,7 @@ CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=8192 CONFIG_MBEDTLS_CFG_FILE="config-coap.h" CONFIG_LWM2M_PEER_PORT=5684 + +# DTLS urls +CONFIG_NET_APP_PEER_IPV6_ADDR="coaps://[2001:db8::2]:5684" +CONFIG_NET_APP_PEER_IPV4_ADDR="coaps://192.0.2.2:5684" diff --git a/samples/net/lwm2m_client/prj.conf b/samples/net/lwm2m_client/prj.conf index 94fcbad7605cca..43c1480f40f020 100644 --- a/samples/net/lwm2m_client/prj.conf +++ b/samples/net/lwm2m_client/prj.conf @@ -35,6 +35,6 @@ CONFIG_LWM2M_IPSO_TEMP_SENSOR=y CONFIG_LWM2M_IPSO_LIGHT_CONTROL=y CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1" -CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2" +CONFIG_NET_APP_PEER_IPV6_ADDR="coap://2001:db8::2" CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" -CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2" +CONFIG_NET_APP_PEER_IPV4_ADDR="coap://192.0.2.2" diff --git a/samples/net/lwm2m_client/src/lwm2m-client.c b/samples/net/lwm2m_client/src/lwm2m-client.c index 40378802655de4..5eaa34fd9ad609 100644 --- a/samples/net/lwm2m_client/src/lwm2m-client.c +++ b/samples/net/lwm2m_client/src/lwm2m-client.c @@ -77,7 +77,7 @@ static struct lwm2m_ctx client; NET_APP_TLS_POOL_DEFINE(dtls_pool, 10); /* "000102030405060708090a0b0c0d0e0f" */ -static unsigned char client_psk[] = { +static const unsigned char client_psk[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; @@ -222,8 +222,37 @@ static int firmware_block_received_cb(u16_t obj_inst_id, static int lwm2m_setup(void) { struct float32_value float_value; + int ret; + char *server_url; + u16_t server_url_len; + u8_t server_url_flags; /* setup SECURITY object */ + + /* Server URL */ + ret = lwm2m_engine_get_res_data("0/0/0", + (void **)&server_url, &server_url_len, + &server_url_flags); + if (ret < 0) { + return ret; + } + + snprintk(server_url, server_url_len, "%s", + IS_ENABLED(CONFIG_NET_IPV6) ? CONFIG_NET_APP_PEER_IPV6_ADDR : + CONFIG_NET_APP_PEER_IPV4_ADDR); + + /* Bootstrap Mode */ + lwm2m_engine_set_bool("0/0/1", + IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)); + /* Security Mode */ + lwm2m_engine_set_u8("0/0/2", IS_ENABLED(CONFIG_NET_APP_DTLS) ? 0 : 3); +#if defined(CONFIG_NET_APP_DTLS) + lwm2m_engine_set_opaque("0/0/3", + (void *)client_psk_id, sizeof(client_psk_id)); + lwm2m_engine_set_opaque("0/0/5", + (void *)client_psk, sizeof(client_psk)); +#endif /* CONFIG_NET_APP_DTLS */ + /* setup SERVER object */ /* setup DEVICE object */ @@ -309,12 +338,16 @@ static void rd_client_event(struct lwm2m_ctx *client, /* do nothing */ break; - case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_FAILURE: - SYS_LOG_DBG("Bootstrap failure!"); + case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE: + SYS_LOG_DBG("Bootstrap registration failure!"); break; - case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_COMPLETE: - SYS_LOG_DBG("Bootstrap complete"); + case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE: + SYS_LOG_DBG("Bootstrap registration complete"); + break; + + case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE: + SYS_LOG_DBG("Bootstrap transfer complete"); break; case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE: @@ -367,10 +400,6 @@ void main(void) #endif #if defined(CONFIG_NET_APP_DTLS) - client.client_psk = client_psk; - client.client_psk_len = 16; - client.client_psk_id = (char *)client_psk_id; - client.client_psk_id_len = strlen(client_psk_id); client.cert_host = HOSTNAME; client.dtls_pool = &dtls_pool; client.dtls_result_buf = dtls_result; @@ -379,18 +408,7 @@ void main(void) client.dtls_stack_len = K_THREAD_STACK_SIZEOF(net_app_dtls_stack); #endif /* CONFIG_NET_APP_DTLS */ -#if defined(CONFIG_NET_IPV6) - ret = lwm2m_rd_client_start(&client, CONFIG_NET_APP_PEER_IPV6_ADDR, - CONFIG_LWM2M_PEER_PORT, CONFIG_BOARD, - rd_client_event); -#elif defined(CONFIG_NET_IPV4) - ret = lwm2m_rd_client_start(&client, CONFIG_NET_APP_PEER_IPV4_ADDR, - CONFIG_LWM2M_PEER_PORT, CONFIG_BOARD, - rd_client_event); -#else - SYS_LOG_ERR("LwM2M client requires IPv4 or IPv6."); - ret = -EPROTONOSUPPORT; -#endif + ret = lwm2m_rd_client_start(&client, CONFIG_BOARD, rd_client_event); if (ret < 0) { SYS_LOG_ERR("LWM2M init LWM2M RD client error (%d)", ret); diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index fdb27fac43cdd2..5ace7ddce7ac7b 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -118,6 +118,7 @@ struct notification_attrs { }; static struct observe_node observe_node_data[CONFIG_LWM2M_ENGINE_MAX_OBSERVER]; +static bool bootstrap_mode; #define MAX_PERIODIC_SERVICE 10 @@ -3926,25 +3927,88 @@ static int setup_cert(struct net_app_ctx *app_ctx, void *cert) struct lwm2m_ctx *client_ctx = CONTAINER_OF(app_ctx, struct lwm2m_ctx, net_app_ctx); + char path[MAX_RESOURCE_LEN]; + u8_t *psk, *psk_id; + int ret; + u16_t psk_len, psk_id_len; + u8_t psk_data_flags, psk_id_data_flags; + + snprintk(path, sizeof(path), "0/%d/3", client_ctx->sec_obj_inst); + ret = lwm2m_engine_get_res_data(path, (void **)&psk_id, &psk_id_len, + &psk_id_data_flags); + if (ret < 0) { + return ret; + } + + snprintk(path, sizeof(path), "0/%d/5", client_ctx->sec_obj_inst); + ret = lwm2m_engine_get_res_data(path, (void **)&psk, &psk_len, + &psk_data_flags); + if (ret < 0) { + return ret; + } + return mbedtls_ssl_conf_psk( &app_ctx->tls.mbedtls.conf, - (const unsigned char *)client_ctx->client_psk, - client_ctx->client_psk_len, - (const unsigned char *)client_ctx->client_psk_id, - client_ctx->client_psk_id_len); + (const unsigned char *)psk, (size_t)psk_len, + (const unsigned char *)psk_id, strlen(psk_id)); #else return 0; #endif } #endif /* CONFIG_NET_APP_DTLS */ -int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, - char *peer_str, u16_t peer_port) +int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, bool is_bootstrap_mode) { + char pathstr[MAX_RESOURCE_LEN]; + char *data_ptr, *peer_str; struct sockaddr client_addr; int ret = 0; + u16_t peer_strlen; + u8_t peer_data_flags; +#if defined(CONFIG_NET_APP_DTLS) + bool use_dtls = false; +#endif + + /* get the server URL */ + snprintk(pathstr, sizeof(pathstr), "0/%d/0", client_ctx->sec_obj_inst); + ret = lwm2m_engine_get_res_data(pathstr, (void **)&data_ptr, + &peer_strlen, + &peer_data_flags); + if (ret < 0) { + return ret; + } - /* TODO: use security object for initial setup */ + /* walk forward till colon shifting to lower case */ + peer_str = data_ptr; + while (*peer_str != '\0' && *peer_str != ':') { + *peer_str = tolower(*peer_str); + peer_str += 1; + } + + /* check to make sure there was a colon */ + if (*peer_str != ':') { + return -EINVAL; + } + + if (strncmp(data_ptr, "coap:", 5) != 0 && + strncmp(data_ptr, "coaps:", 6) != 0) { + return -EPROTONOSUPPORT; + } + + if (strncmp(data_ptr, "coaps:", 6) == 0) { +#if defined(CONFIG_NET_APP_DTLS) + use_dtls = true; +#else + return -EPROTONOSUPPORT; +#endif + } + + /* skip the colons and slashes */ + while (*peer_str == ':' || *peer_str == '/') { + peer_str += 1; + } + + SYS_LOG_DBG("URL: %s", data_ptr); /* setup the local client port */ memset(&client_addr, 0, sizeof(client_addr)); @@ -3956,10 +4020,13 @@ int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, net_sin(&client_addr)->sin_port = htons(CONFIG_LWM2M_LOCAL_PORT); #endif + /* save bootstrap_mode for later */ + bootstrap_mode = is_bootstrap_mode; + ret = net_app_init_udp_client(&client_ctx->net_app_ctx, &client_addr, NULL, peer_str, - peer_port, + CONFIG_LWM2M_PEER_PORT, client_ctx->net_init_timeout, client_ctx); if (ret) { @@ -3978,20 +4045,22 @@ int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, } #if defined(CONFIG_NET_APP_DTLS) - ret = net_app_client_tls(&client_ctx->net_app_ctx, - client_ctx->dtls_result_buf, - client_ctx->dtls_result_buf_len, - INSTANCE_INFO, - strlen(INSTANCE_INFO), - setup_cert, - client_ctx->cert_host, - NULL, - client_ctx->dtls_pool, - client_ctx->dtls_stack, - client_ctx->dtls_stack_len); - if (ret < 0) { - SYS_LOG_ERR("Cannot init DTLS (%d)", ret); - goto error_start; + if (use_dtls) { + ret = net_app_client_tls(&client_ctx->net_app_ctx, + client_ctx->dtls_result_buf, + client_ctx->dtls_result_buf_len, + INSTANCE_INFO, + strlen(INSTANCE_INFO), + setup_cert, + client_ctx->cert_host, + NULL, + client_ctx->dtls_pool, + client_ctx->dtls_stack, + client_ctx->dtls_stack_len); + if (ret < 0) { + SYS_LOG_ERR("Cannot init DTLS (%d)", ret); + goto error_start; + } } #endif @@ -4002,6 +4071,18 @@ int lwm2m_engine_start(struct lwm2m_ctx *client_ctx, goto error_start; } +#if defined(CONFIG_NET_APP_DTLS) + if (use_dtls) { + SYS_LOG_DBG("Waiting for TLS handshake"); + while (!client_ctx->net_app_ctx.tls.handshake_done) { + k_sleep(K_SECONDS(1)); + SYS_LOG_DBG("Check TLS handshake: %d", client_ctx->net_app_ctx.tls.handshake_done); + } + + SYS_LOG_DBG("TLS handshake complete!"); + } +#endif + return 0; error_start: diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index dcd9629a00369c..ab54c21ee990a5 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -76,9 +76,12 @@ */ enum sm_engine_state { ENGINE_INIT, - ENGINE_DO_BOOTSTRAP, - ENGINE_BOOTSTRAP_SENT, - ENGINE_BOOTSTRAP_DONE, +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) + ENGINE_DO_BOOTSTRAP_REG, + ENGINE_BOOTSTRAP_REG_SENT, + ENGINE_BOOTSTRAP_REG_DONE, + ENGINE_BOOTSTRAP_TRANS_DONE, +#endif ENGINE_DO_REGISTRATION, ENGINE_REGISTRATION_SENT, ENGINE_REGISTRATION_DONE, @@ -90,18 +93,12 @@ enum sm_engine_state { }; struct lwm2m_rd_client_info { - u16_t lifetime; struct lwm2m_ctx *ctx; + s64_t last_update; + u32_t lifetime; u8_t engine_state; - u8_t use_bootstrap; - u8_t has_bs_server_info; - u8_t use_registration; - u8_t has_registration_info; - u8_t bootstrapped; /* bootstrap done */ u8_t trigger_update; - s64_t last_update; - char ep_name[CLIENT_EP_LEN]; char server_ep[CLIENT_EP_LEN]; @@ -117,16 +114,20 @@ static void set_sm_state(u8_t sm_state) enum lwm2m_rd_client_event event = LWM2M_RD_CLIENT_EVENT_NONE; /* Determine if a callback to the app is needed */ - if (sm_state == ENGINE_BOOTSTRAP_DONE) { - event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_COMPLETE; - } else if (client.engine_state == ENGINE_UPDATE_SENT && +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) + if (sm_state == ENGINE_BOOTSTRAP_REG_DONE) { + event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE; + } else if (sm_state == ENGINE_BOOTSTRAP_TRANS_DONE) { + event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE; +#endif + if (client.engine_state == ENGINE_UPDATE_SENT && sm_state == ENGINE_REGISTRATION_DONE) { event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE; } else if (sm_state == ENGINE_REGISTRATION_DONE) { event = LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE; } else if ((sm_state == ENGINE_INIT || sm_state == ENGINE_DEREGISTERED) && - (client.engine_state > ENGINE_BOOTSTRAP_DONE && + (client.engine_state > ENGINE_DO_REGISTRATION && client.engine_state < ENGINE_DEREGISTER)) { event = LWM2M_RD_CLIENT_EVENT_DISCONNECT; } @@ -156,9 +157,12 @@ static void sm_handle_timeout_state(struct lwm2m_message *msg, { enum lwm2m_rd_client_event event = LWM2M_RD_CLIENT_EVENT_NONE; - if (client.engine_state == ENGINE_BOOTSTRAP_SENT) { - event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_FAILURE; - } else if (client.engine_state == ENGINE_REGISTRATION_SENT) { +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) + if (client.engine_state == ENGINE_BOOTSTRAP_REG_SENT) { + event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE; + } else +#endif + if (client.engine_state == ENGINE_REGISTRATION_SENT) { event = LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE; } else if (client.engine_state == ENGINE_UPDATE_SENT) { event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE; @@ -184,6 +188,7 @@ void engine_trigger_update(void) /* state machine reply callbacks */ +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) static int do_bootstrap_reply_cb(const struct coap_packet *response, struct coap_reply *reply, const struct sockaddr *from) @@ -196,12 +201,14 @@ static int do_bootstrap_reply_cb(const struct coap_packet *response, COAP_RESPONSE_CODE_DETAIL(code)); if (code == COAP_RESPONSE_CODE_CHANGED) { - SYS_LOG_DBG("Considered done!"); - set_sm_state(ENGINE_BOOTSTRAP_DONE); + SYS_LOG_INF("Bootstrap registration done!"); + set_sm_state(ENGINE_BOOTSTRAP_REG_DONE); } else if (code == COAP_RESPONSE_CODE_NOT_FOUND) { + /* TODO: try and find another bootstrap server entry? */ SYS_LOG_ERR("Failed: NOT_FOUND. Not Retrying."); set_sm_state(ENGINE_DO_REGISTRATION); } else if (code == COAP_RESPONSE_CODE_FORBIDDEN) { + /* TODO: try and find another bootstrap server entry? */ SYS_LOG_ERR("Failed: 4.03 - Forbidden. Not Retrying."); set_sm_state(ENGINE_DO_REGISTRATION); } else { @@ -215,13 +222,18 @@ static int do_bootstrap_reply_cb(const struct coap_packet *response, return 0; } -static void do_bootstrap_timeout_cb(struct lwm2m_message *msg) +static void do_bootstrap_reg_timeout_cb(struct lwm2m_message *msg) { SYS_LOG_WRN("Bootstrap Timeout"); + /* TODO: + * Look for the "next" BOOTSTRAP server entry in our security info + */ + /* Restart from scratch */ sm_handle_timeout_state(msg, ENGINE_INIT); } +#endif static int do_registration_reply_cb(const struct coap_packet *response, struct coap_reply *reply, @@ -286,6 +298,10 @@ static void do_registration_timeout_cb(struct lwm2m_message *msg) { SYS_LOG_WRN("Registration Timeout"); + /* TODO: + * Look for the "next" normal server entry in our security info + */ + /* Restart from scratch */ sm_handle_timeout_state(msg, ENGINE_INIT); } @@ -361,148 +377,218 @@ static void do_deregister_timeout_cb(struct lwm2m_message *msg) sm_handle_timeout_state(msg, ENGINE_INIT); } +/* utility functions */ + +static int sm_select_next_sec_inst(bool bootstrap_server, + int *sec_obj_inst, u32_t *lifetime) +{ + char pathstr[MAX_RESOURCE_LEN]; + int ret, end, i, obj_inst_id, found = -1; + bool is_bootstrap_server; + + /* lookup existing index */ + i = lwm2m_security_inst_id_to_index(*sec_obj_inst); + if (i < 0) { + *sec_obj_inst = -1; + i = -1; + } + + /* store end marker, due to looping */ + end = (i == -1 ? CONFIG_LWM2M_SECURITY_INSTANCE_COUNT : i); + + /* loop through servers starting from the index after the current one */ + for (i++; i != end; i++) { + if (i >= CONFIG_LWM2M_SECURITY_INSTANCE_COUNT) { + i = 0; + } + + obj_inst_id = lwm2m_security_index_to_inst_id(i); + if (obj_inst_id < 0) { + continue; + } + + snprintk(pathstr, sizeof(pathstr), "0/%d/1", + obj_inst_id); + ret = lwm2m_engine_get_bool(pathstr, &is_bootstrap_server); + if (ret < 0) { + continue; + } + +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) + if (is_bootstrap_server == bootstrap_server) { +#else + if (is_bootstrap_server == false) { +#endif + found = obj_inst_id; + break; + } + } + + if (found > -1) { + *sec_obj_inst = found; + + /* query the lifetime */ + /* TODO: use Short Server ID to link to server info */ + snprintk(pathstr, sizeof(pathstr), "1/%d/1", + obj_inst_id); + if (lwm2m_engine_get_u32(pathstr, lifetime) < 0) { + *lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME; + SYS_LOG_DBG("Using default lifetime: %u", *lifetime); + } + } + + if (*sec_obj_inst < 0) { + /* no servers found */ + SYS_LOG_DBG("sec_obj_inst: NOT_FOUND"); + return -ENOENT; + } + + SYS_LOG_DBG("sec_obj_inst: %d", *sec_obj_inst); + return 0; +} + /* state machine step functions */ static int sm_do_init(void) { - SYS_LOG_INF("RD Client started with endpoint " - "'%s' and client lifetime %d", - client.ep_name, - client.lifetime); - /* Zephyr has joined network already */ - client.has_registration_info = 1; - client.bootstrapped = 0; client.trigger_update = 0; -#if defined(CONFIG_LWM2M_BOOTSTRAP_SERVER) - client.use_bootstrap = 1; + + /* reset security object instance */ + client.ctx->sec_obj_inst = -1; + +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) + set_sm_state(ENGINE_DO_BOOTSTRAP_REG); #else - client.use_registration = 1; + set_sm_state(ENGINE_DO_REGISTRATION); #endif - if (client.lifetime == 0) { - client.lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME; - } - /* Do bootstrap or registration */ - if (client.use_bootstrap) { - set_sm_state(ENGINE_DO_BOOTSTRAP); - } else { - set_sm_state(ENGINE_DO_REGISTRATION); - } return 0; } -static int sm_do_bootstrap(void) +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) +static int sm_do_bootstrap_reg(void) { struct lwm2m_message *msg; struct net_app_ctx *app_ctx = NULL; int ret; struct sockaddr *remote = NULL; - if (client.use_bootstrap && - client.bootstrapped == 0 && - client.has_bs_server_info) { - app_ctx = &client.ctx->net_app_ctx; - msg = lwm2m_get_message(client.ctx); - if (!msg) { - SYS_LOG_ERR("Unable to get a lwm2m message!"); - return -ENOMEM; - } + /* TODO: clear out connection data? */ - msg->type = COAP_TYPE_CON; - msg->code = COAP_METHOD_POST; - msg->mid = 0; - msg->reply_cb = do_bootstrap_reply_cb; - msg->message_timeout_cb = do_bootstrap_timeout_cb; + ret = sm_select_next_sec_inst(true, + &client.ctx->sec_obj_inst, + &client.lifetime); + if (ret < 0) { + /* try again */ + return ret; + } - ret = lwm2m_init_message(msg); - if (ret) { - goto cleanup; - } + if (client.lifetime == 0) { + client.lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME; + } - /* TODO: handle return error */ - coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH, - "bs", strlen("bs")); + SYS_LOG_INF("Bootstrap started with endpoint " + "'%s' with client lifetime %d", + client.ep_name, client.lifetime); - snprintk(query_buffer, sizeof(query_buffer) - 1, - "ep=%s", client.ep_name); - /* TODO: handle return error */ - coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY, - query_buffer, strlen(query_buffer)); + ret = lwm2m_engine_start(client.ctx, true); + if (ret < 0) { + SYS_LOG_ERR("Cannot init LWM2M engine (%d)", ret); + goto cleanup_engine; + } + + if (!client.ctx->net_app_ctx.default_ctx) { + SYS_LOG_ERR("Default net_app_ctx not selected!"); + ret = -EINVAL; + goto cleanup_engine; + } + + app_ctx = &client.ctx->net_app_ctx; + msg = lwm2m_get_message(client.ctx); + if (!msg) { + SYS_LOG_ERR("Unable to get a lwm2m message!"); + return -ENOMEM; + } - /* log the bootstrap attempt */ + msg->type = COAP_TYPE_CON; + msg->code = COAP_METHOD_POST; + msg->mid = 0; + msg->reply_cb = do_bootstrap_reply_cb; + msg->message_timeout_cb = do_bootstrap_reg_timeout_cb; + + ret = lwm2m_init_message(msg); + if (ret) { + goto cleanup; + } + + /* TODO: handle return error */ + coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH, + "bs", strlen("bs")); + + snprintk(query_buffer, sizeof(query_buffer) - 1, "ep=%s", + client.ep_name); + /* TODO: handle return error */ + coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY, + query_buffer, strlen(query_buffer)); + + /* log the bootstrap attempt */ #if defined(CONFIG_NET_APP_DTLS) - if (app_ctx->dtls.ctx) { - remote = &app_ctx->dtls.ctx->remote; - } + if (app_ctx->dtls.ctx) { + remote = &app_ctx->dtls.ctx->remote; + } #endif - if (!remote) { - remote = &app_ctx->default_ctx->remote; - } - - SYS_LOG_DBG("Register ID with bootstrap server [%s] as '%s'", - lwm2m_sprint_ip_addr(remote), - query_buffer); + if (!remote) { + remote = &app_ctx->default_ctx->remote; + } - ret = lwm2m_send_message(msg); - if (ret < 0) { - SYS_LOG_ERR("Error sending LWM2M packet (err:%d).", - ret); - goto cleanup; - } + SYS_LOG_DBG("Register ID with bootstrap server [%s] as '%s'", + lwm2m_sprint_ip_addr(remote), + query_buffer); - set_sm_state(ENGINE_BOOTSTRAP_SENT); + ret = lwm2m_send_message(msg); + if (ret < 0) { + SYS_LOG_ERR("Error sending LWM2M packet (err:%d).", + ret); + goto cleanup; } + + set_sm_state(ENGINE_BOOTSTRAP_REG_SENT); return 0; cleanup: lwm2m_reset_message(msg, true); return ret; + +cleanup_engine: + lwm2m_engine_context_close(client.ctx); + return ret; } static int sm_bootstrap_done(void) { - /* TODO: Fix this */ - /* check that we should still use bootstrap */ - if (client.use_bootstrap) { -#ifdef CONFIG_LWM2M_SECURITY_OBJ_SUPPORT - int i; - - SYS_LOG_DBG("*** Bootstrap - checking for server info ..."); - - /* get the server URI */ - if (sec_data->server_uri_len > 0) { - /* TODO: Write endpoint parsing function */ -#if 0 - if (!parse_endpoint(sec_data->server_uri, - sec_data->server_uri_len, - &client.reg_server)) { -#else - if (true) { -#endif - SYS_LOG_ERR("Failed to parse URI!"); - } else { - client.has_registration_info = 1; - client.bootstrapped++; - } - } else { - SYS_LOG_ERR("** failed to parse URI"); - } + return 0; +} - /* if we did not register above - then fail this and restart */ - if (client.bootstrapped == 0) { - /* Not ready - Retry with the bootstrap server again */ - set_sm_state(ENGINE_DO_BOOTSTRAP); - } else { - set_sm_state(ENGINE_DO_REGISTRATION); - } - } else { -#endif - set_sm_state(ENGINE_DO_REGISTRATION); - } +void engine_bootstrap_finish(void) +{ + SYS_LOG_INF("Bootstrap data transfer done!"); + set_sm_state(ENGINE_BOOTSTRAP_TRANS_DONE); +} + +static int sm_bootstrap_trans_done(void) +{ + /* close down net_app contexts */ + lwm2m_engine_context_close(client.ctx); + + /* reset security object instance */ + client.ctx->sec_obj_inst = -1; + + set_sm_state(ENGINE_DO_REGISTRATION); return 0; } +#endif static int sm_send_registration(bool send_obj_support_data, coap_reply_t reply_cb, @@ -619,9 +705,37 @@ static int sm_do_registration(void) { int ret = 0; - if (client.use_registration && - !sm_is_registered() && - client.has_registration_info) { + /* TODO: clear out connection data? */ + + ret = sm_select_next_sec_inst(false, + &client.ctx->sec_obj_inst, + &client.lifetime); + if (ret < 0) { + set_sm_state(ENGINE_INIT); + return -EINVAL; + } + + if (client.lifetime == 0) { + client.lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME; + } + + SYS_LOG_INF("RD Client started with endpoint " + "'%s' with client lifetime %d", + client.ep_name, client.lifetime); + + ret = lwm2m_engine_start(client.ctx, false); + if (ret < 0) { + SYS_LOG_ERR("Cannot init LWM2M engine (%d)", ret); + goto cleanup_engine; + } + + if (!client.ctx->net_app_ctx.default_ctx) { + SYS_LOG_ERR("Default net_app_ctx not selected!"); + ret = -EINVAL; + goto cleanup_engine; + } + + if (!sm_is_registered()) { ret = sm_send_registration(true, do_registration_reply_cb, do_registration_timeout_cb); @@ -633,6 +747,10 @@ static int sm_do_registration(void) } return ret; + +cleanup_engine: + lwm2m_engine_context_close(client.ctx); + return ret; } static int sm_registration_done(void) @@ -718,18 +836,25 @@ static void lwm2m_rd_client_service(void) sm_do_init(); break; - case ENGINE_DO_BOOTSTRAP: - sm_do_bootstrap(); +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) + case ENGINE_DO_BOOTSTRAP_REG: + sm_do_bootstrap_reg(); break; - case ENGINE_BOOTSTRAP_SENT: - /* wait for bootstrap to be done or timeout */ + case ENGINE_BOOTSTRAP_REG_SENT: + /* wait for bootstrap registration done */ break; - case ENGINE_BOOTSTRAP_DONE: + case ENGINE_BOOTSTRAP_REG_DONE: sm_bootstrap_done(); + /* wait for transfer done */ break; + case ENGINE_BOOTSTRAP_TRANS_DONE: + sm_bootstrap_trans_done(); + break; +#endif + case ENGINE_DO_REGISTRATION: sm_do_registration(); break; @@ -768,24 +893,9 @@ static void lwm2m_rd_client_service(void) } int lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, - char *peer_str, u16_t peer_port, const char *ep_name, lwm2m_ctx_event_cb_t event_cb) { - int ret = 0; - - ret = lwm2m_engine_start(client_ctx, peer_str, peer_port); - if (ret < 0) { - SYS_LOG_ERR("Cannot init LWM2M engine (%d)", ret); - goto cleanup; - } - - if (!client_ctx->net_app_ctx.default_ctx) { - SYS_LOG_ERR("Default net_app_ctx not selected!"); - return -EINVAL; - } - - /* TODO: use server URI data from security */ client.ctx = client_ctx; client.event_cb = event_cb; set_sm_state(ENGINE_INIT); @@ -793,11 +903,6 @@ int lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, SYS_LOG_INF("LWM2M Client: %s", client.ep_name); return 0; - -cleanup: - net_app_close(&client_ctx->net_app_ctx); - net_app_release(&client_ctx->net_app_ctx); - return ret; } static int lwm2m_rd_client_init(struct device *dev) diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.h b/subsys/net/lib/lwm2m/lwm2m_rd_client.h index 39453ab2aa7c70..61fa8480bf9d2d 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.h +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.h @@ -38,5 +38,8 @@ #define LWM2M_RD_CLIENT_H void engine_trigger_update(void); +#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) +void engine_bootstrap_finish(void); +#endif #endif /* LWM2M_RD_CLIENT_H */