1c87c5fbaSopenharmony_ci/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ 2c87c5fbaSopenharmony_ci 3c87c5fbaSopenharmony_ci/* coap -- simple implementation of the Constrained Application Protocol (CoAP) 4c87c5fbaSopenharmony_ci * as defined in RFC 7252 5c87c5fbaSopenharmony_ci * 6c87c5fbaSopenharmony_ci * Copyright (C) 2010--2015,2022-2023 Olaf Bergmann <bergmann@tzi.org> 7c87c5fbaSopenharmony_ci * 8c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 9c87c5fbaSopenharmony_ci * 10c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see README for terms of 11c87c5fbaSopenharmony_ci * use. 12c87c5fbaSopenharmony_ci */ 13c87c5fbaSopenharmony_ci 14c87c5fbaSopenharmony_ci 15c87c5fbaSopenharmony_ci/** 16c87c5fbaSopenharmony_ci * @file coap-rd.c 17c87c5fbaSopenharmony_ci * @brief CoRE resource directory 18c87c5fbaSopenharmony_ci * 19c87c5fbaSopenharmony_ci * @see https://tools.ietf.org/html/draft-ietf-core-resource-directory 20c87c5fbaSopenharmony_ci */ 21c87c5fbaSopenharmony_ci 22c87c5fbaSopenharmony_ci#include <string.h> 23c87c5fbaSopenharmony_ci#include <stdlib.h> 24c87c5fbaSopenharmony_ci#include <stdio.h> 25c87c5fbaSopenharmony_ci#include <ctype.h> 26c87c5fbaSopenharmony_ci#include <sys/types.h> 27c87c5fbaSopenharmony_ci#include <sys/stat.h> 28c87c5fbaSopenharmony_ci#include <errno.h> 29c87c5fbaSopenharmony_ci#include <signal.h> 30c87c5fbaSopenharmony_ci#ifdef _WIN32 31c87c5fbaSopenharmony_ci#define strcasecmp _stricmp 32c87c5fbaSopenharmony_ci#include "getopt.c" 33c87c5fbaSopenharmony_ci#if !defined(S_ISDIR) 34c87c5fbaSopenharmony_ci#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 35c87c5fbaSopenharmony_ci#endif 36c87c5fbaSopenharmony_ci#else 37c87c5fbaSopenharmony_ci#include <unistd.h> 38c87c5fbaSopenharmony_ci#include <sys/select.h> 39c87c5fbaSopenharmony_ci#include <sys/socket.h> 40c87c5fbaSopenharmony_ci#include <netinet/in.h> 41c87c5fbaSopenharmony_ci#include <arpa/inet.h> 42c87c5fbaSopenharmony_ci#include <netdb.h> 43c87c5fbaSopenharmony_ci#include <dirent.h> 44c87c5fbaSopenharmony_ci#endif 45c87c5fbaSopenharmony_ci 46c87c5fbaSopenharmony_ci#include <coap3/coap.h> 47c87c5fbaSopenharmony_ci 48c87c5fbaSopenharmony_ci#define COAP_RESOURCE_CHECK_TIME 2 49c87c5fbaSopenharmony_ci 50c87c5fbaSopenharmony_ci#define RD_ROOT_STR "rd" 51c87c5fbaSopenharmony_ci#define RD_ROOT_SIZE 2 52c87c5fbaSopenharmony_ci 53c87c5fbaSopenharmony_cistatic char *cert_file = NULL; /* Combined certificate and private key in PEM */ 54c87c5fbaSopenharmony_cistatic char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM */ 55c87c5fbaSopenharmony_cistatic char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */ 56c87c5fbaSopenharmony_cistatic int verify_peer_cert = 1; /* PKI granularity - by default set */ 57c87c5fbaSopenharmony_ci#define MAX_KEY 64 /* Maximum length of a pre-shared key in bytes. */ 58c87c5fbaSopenharmony_cistatic uint8_t key[MAX_KEY]; 59c87c5fbaSopenharmony_cistatic ssize_t key_length = 0; 60c87c5fbaSopenharmony_cistatic int key_defined = 0; 61c87c5fbaSopenharmony_cistatic const char *hint = "CoAP"; 62c87c5fbaSopenharmony_cistatic size_t extended_token_size = COAP_TOKEN_DEFAULT_MAX; 63c87c5fbaSopenharmony_cistatic int enable_ws = 0; 64c87c5fbaSopenharmony_cistatic int ws_port = 80; 65c87c5fbaSopenharmony_cistatic int wss_port = 443; 66c87c5fbaSopenharmony_ci 67c87c5fbaSopenharmony_ci#ifndef min 68c87c5fbaSopenharmony_ci#define min(a,b) ((a) < (b) ? (a) : (b)) 69c87c5fbaSopenharmony_ci#endif 70c87c5fbaSopenharmony_ci 71c87c5fbaSopenharmony_citypedef struct rd_t { 72c87c5fbaSopenharmony_ci size_t etag_len; /**< actual length of @c etag */ 73c87c5fbaSopenharmony_ci unsigned char etag[8]; /**< ETag for current description */ 74c87c5fbaSopenharmony_ci 75c87c5fbaSopenharmony_ci coap_string_t data; /**< points to the resource description */ 76c87c5fbaSopenharmony_ci} rd_t; 77c87c5fbaSopenharmony_ci 78c87c5fbaSopenharmony_cird_t *resources = NULL; 79c87c5fbaSopenharmony_ci 80c87c5fbaSopenharmony_cistatic ssize_t 81c87c5fbaSopenharmony_cicmdline_read_key(char *arg, unsigned char *buf, size_t maxlen) { 82c87c5fbaSopenharmony_ci size_t len = strnlen(arg, maxlen); 83c87c5fbaSopenharmony_ci if (len) { 84c87c5fbaSopenharmony_ci memcpy(buf, arg, len); 85c87c5fbaSopenharmony_ci return len; 86c87c5fbaSopenharmony_ci } 87c87c5fbaSopenharmony_ci return -1; 88c87c5fbaSopenharmony_ci} 89c87c5fbaSopenharmony_ci 90c87c5fbaSopenharmony_cistatic int 91c87c5fbaSopenharmony_cicmdline_ws(char *arg) { 92c87c5fbaSopenharmony_ci char *cp = strchr(arg, ','); 93c87c5fbaSopenharmony_ci 94c87c5fbaSopenharmony_ci if (cp) { 95c87c5fbaSopenharmony_ci if (cp != arg) 96c87c5fbaSopenharmony_ci ws_port = atoi(arg); 97c87c5fbaSopenharmony_ci cp++; 98c87c5fbaSopenharmony_ci if (*cp != '\000') 99c87c5fbaSopenharmony_ci wss_port = atoi(cp); 100c87c5fbaSopenharmony_ci } else { 101c87c5fbaSopenharmony_ci ws_port = atoi(arg); 102c87c5fbaSopenharmony_ci } 103c87c5fbaSopenharmony_ci return 1; 104c87c5fbaSopenharmony_ci} 105c87c5fbaSopenharmony_ci 106c87c5fbaSopenharmony_cistatic inline rd_t * 107c87c5fbaSopenharmony_cird_new(void) { 108c87c5fbaSopenharmony_ci rd_t *rd; 109c87c5fbaSopenharmony_ci rd = (rd_t *)coap_malloc(sizeof(rd_t)); 110c87c5fbaSopenharmony_ci if (rd) 111c87c5fbaSopenharmony_ci memset(rd, 0, sizeof(rd_t)); 112c87c5fbaSopenharmony_ci 113c87c5fbaSopenharmony_ci return rd; 114c87c5fbaSopenharmony_ci} 115c87c5fbaSopenharmony_ci 116c87c5fbaSopenharmony_cistatic void 117c87c5fbaSopenharmony_cird_delete(rd_t *rd) { 118c87c5fbaSopenharmony_ci if (rd) { 119c87c5fbaSopenharmony_ci coap_free(rd->data.s); 120c87c5fbaSopenharmony_ci coap_free(rd); 121c87c5fbaSopenharmony_ci } 122c87c5fbaSopenharmony_ci} 123c87c5fbaSopenharmony_ci 124c87c5fbaSopenharmony_cistatic void 125c87c5fbaSopenharmony_ciresource_rd_delete(void *ptr) { 126c87c5fbaSopenharmony_ci rd_delete(ptr); 127c87c5fbaSopenharmony_ci} 128c87c5fbaSopenharmony_ci 129c87c5fbaSopenharmony_cistatic int quit = 0; 130c87c5fbaSopenharmony_ci 131c87c5fbaSopenharmony_ci/* SIGINT handler: set quit to 1 for graceful termination */ 132c87c5fbaSopenharmony_cistatic void 133c87c5fbaSopenharmony_cihandle_sigint(int signum COAP_UNUSED) { 134c87c5fbaSopenharmony_ci quit = 1; 135c87c5fbaSopenharmony_ci} 136c87c5fbaSopenharmony_ci 137c87c5fbaSopenharmony_cistatic void 138c87c5fbaSopenharmony_cihnd_get_resource(coap_resource_t *resource, 139c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 140c87c5fbaSopenharmony_ci const coap_pdu_t *request COAP_UNUSED, 141c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 142c87c5fbaSopenharmony_ci coap_pdu_t *response) { 143c87c5fbaSopenharmony_ci rd_t *rd = coap_resource_get_userdata(resource); 144c87c5fbaSopenharmony_ci unsigned char buf[3]; 145c87c5fbaSopenharmony_ci 146c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 147c87c5fbaSopenharmony_ci 148c87c5fbaSopenharmony_ci coap_add_option(response, 149c87c5fbaSopenharmony_ci COAP_OPTION_CONTENT_TYPE, 150c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 151c87c5fbaSopenharmony_ci COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), 152c87c5fbaSopenharmony_ci buf); 153c87c5fbaSopenharmony_ci 154c87c5fbaSopenharmony_ci if (rd && rd->etag_len) 155c87c5fbaSopenharmony_ci coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag); 156c87c5fbaSopenharmony_ci 157c87c5fbaSopenharmony_ci if (rd && rd->data.s) 158c87c5fbaSopenharmony_ci coap_add_data(response, rd->data.length, rd->data.s); 159c87c5fbaSopenharmony_ci} 160c87c5fbaSopenharmony_ci 161c87c5fbaSopenharmony_cistatic void 162c87c5fbaSopenharmony_cihnd_put_resource(coap_resource_t *resource COAP_UNUSED, 163c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 164c87c5fbaSopenharmony_ci const coap_pdu_t *request COAP_UNUSED, 165c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 166c87c5fbaSopenharmony_ci coap_pdu_t *response) { 167c87c5fbaSopenharmony_ci#if 1 168c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_IMPLEMENTED); 169c87c5fbaSopenharmony_ci#else /* FIXME */ 170c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 171c87c5fbaSopenharmony_ci coap_opt_t *token, *etag; 172c87c5fbaSopenharmony_ci coap_pdu_t *response; 173c87c5fbaSopenharmony_ci size_t size = sizeof(coap_hdr_t); 174c87c5fbaSopenharmony_ci int type = (request->hdr->type == COAP_MESSAGE_CON) 175c87c5fbaSopenharmony_ci ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; 176c87c5fbaSopenharmony_ci rd_t *rd = NULL; 177c87c5fbaSopenharmony_ci unsigned char code; /* result code */ 178c87c5fbaSopenharmony_ci const uint8_t *data; 179c87c5fbaSopenharmony_ci coap_string_t tmp; 180c87c5fbaSopenharmony_ci 181c87c5fbaSopenharmony_ci HASH_FIND(hh, resources, resource->uri_path.s, resource->uri_path.length, rd); 182c87c5fbaSopenharmony_ci if (rd) { 183c87c5fbaSopenharmony_ci /* found resource object, now check Etag */ 184c87c5fbaSopenharmony_ci etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter); 185c87c5fbaSopenharmony_ci if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len) 186c87c5fbaSopenharmony_ci || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) { 187c87c5fbaSopenharmony_ci 188c87c5fbaSopenharmony_ci if (coap_get_data(request, &tmp.length, &data)) { 189c87c5fbaSopenharmony_ci 190c87c5fbaSopenharmony_ci tmp.s = (unsigned char *)coap_malloc(tmp.length); 191c87c5fbaSopenharmony_ci if (!tmp.s) { 192c87c5fbaSopenharmony_ci coap_log_debug("hnd_put_rd: cannot allocate storage for new rd\n"); 193c87c5fbaSopenharmony_ci code = COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE; 194c87c5fbaSopenharmony_ci goto finish; 195c87c5fbaSopenharmony_ci } 196c87c5fbaSopenharmony_ci 197c87c5fbaSopenharmony_ci coap_free(rd->data.s); 198c87c5fbaSopenharmony_ci rd->data.s = tmp.s; 199c87c5fbaSopenharmony_ci rd->data.length = tmp.length; 200c87c5fbaSopenharmony_ci memcpy(rd->data.s, data, rd->data.length); 201c87c5fbaSopenharmony_ci } 202c87c5fbaSopenharmony_ci } 203c87c5fbaSopenharmony_ci 204c87c5fbaSopenharmony_ci if (etag) { 205c87c5fbaSopenharmony_ci rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); 206c87c5fbaSopenharmony_ci memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); 207c87c5fbaSopenharmony_ci } 208c87c5fbaSopenharmony_ci 209c87c5fbaSopenharmony_ci code = COAP_RESPONSE_CODE_CHANGED; 210c87c5fbaSopenharmony_ci /* FIXME: update lifetime */ 211c87c5fbaSopenharmony_ci 212c87c5fbaSopenharmony_ci } else { 213c87c5fbaSopenharmony_ci 214c87c5fbaSopenharmony_ci code = COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE; 215c87c5fbaSopenharmony_ci } 216c87c5fbaSopenharmony_ci 217c87c5fbaSopenharmony_cifinish: 218c87c5fbaSopenharmony_ci /* FIXME: do not create a new response but use the old one instead */ 219c87c5fbaSopenharmony_ci response = coap_pdu_init(type, code, request->hdr->id, size); 220c87c5fbaSopenharmony_ci 221c87c5fbaSopenharmony_ci if (!response) { 222c87c5fbaSopenharmony_ci coap_log_debug("cannot create response for mid=0x%x\n", 223c87c5fbaSopenharmony_ci request->hdr->id); 224c87c5fbaSopenharmony_ci return; 225c87c5fbaSopenharmony_ci } 226c87c5fbaSopenharmony_ci 227c87c5fbaSopenharmony_ci if (request->hdr->token_length) 228c87c5fbaSopenharmony_ci coap_add_token(response, request->hdr->token_length, request->hdr->token); 229c87c5fbaSopenharmony_ci 230c87c5fbaSopenharmony_ci if (coap_send(ctx, peer, response) == COAP_INVALID_MID) { 231c87c5fbaSopenharmony_ci coap_log_debug("hnd_get_rd: cannot send response for mid=0x%x\n", 232c87c5fbaSopenharmony_ci request->hdr->id); 233c87c5fbaSopenharmony_ci } 234c87c5fbaSopenharmony_ci#endif 235c87c5fbaSopenharmony_ci} 236c87c5fbaSopenharmony_ci 237c87c5fbaSopenharmony_cistatic void 238c87c5fbaSopenharmony_cihnd_delete_resource(coap_resource_t *resource, 239c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 240c87c5fbaSopenharmony_ci const coap_pdu_t *request COAP_UNUSED, 241c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 242c87c5fbaSopenharmony_ci coap_pdu_t *response) { 243c87c5fbaSopenharmony_ci rd_t *rd = coap_resource_get_userdata(resource); 244c87c5fbaSopenharmony_ci 245c87c5fbaSopenharmony_ci if (rd) { 246c87c5fbaSopenharmony_ci rd_delete(rd); 247c87c5fbaSopenharmony_ci } 248c87c5fbaSopenharmony_ci /* FIXME: link attributes for resource have been created dynamically 249c87c5fbaSopenharmony_ci * using coap_malloc() and must be released. */ 250c87c5fbaSopenharmony_ci coap_delete_resource(NULL, resource); 251c87c5fbaSopenharmony_ci 252c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); 253c87c5fbaSopenharmony_ci} 254c87c5fbaSopenharmony_ci 255c87c5fbaSopenharmony_cistatic void 256c87c5fbaSopenharmony_cihnd_get_rd(coap_resource_t *resource COAP_UNUSED, 257c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 258c87c5fbaSopenharmony_ci const coap_pdu_t *request COAP_UNUSED, 259c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 260c87c5fbaSopenharmony_ci coap_pdu_t *response) { 261c87c5fbaSopenharmony_ci unsigned char buf[3]; 262c87c5fbaSopenharmony_ci 263c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 264c87c5fbaSopenharmony_ci 265c87c5fbaSopenharmony_ci coap_add_option(response, 266c87c5fbaSopenharmony_ci COAP_OPTION_CONTENT_TYPE, 267c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 268c87c5fbaSopenharmony_ci COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), 269c87c5fbaSopenharmony_ci buf); 270c87c5fbaSopenharmony_ci 271c87c5fbaSopenharmony_ci coap_add_option(response, 272c87c5fbaSopenharmony_ci COAP_OPTION_MAXAGE, 273c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf); 274c87c5fbaSopenharmony_ci} 275c87c5fbaSopenharmony_ci 276c87c5fbaSopenharmony_cistatic int 277c87c5fbaSopenharmony_ciparse_param(const uint8_t *search, 278c87c5fbaSopenharmony_ci size_t search_len, 279c87c5fbaSopenharmony_ci unsigned char *data, 280c87c5fbaSopenharmony_ci size_t data_len, 281c87c5fbaSopenharmony_ci coap_string_t *result) { 282c87c5fbaSopenharmony_ci 283c87c5fbaSopenharmony_ci if (result) 284c87c5fbaSopenharmony_ci memset(result, 0, sizeof(coap_string_t)); 285c87c5fbaSopenharmony_ci 286c87c5fbaSopenharmony_ci if (!search_len) 287c87c5fbaSopenharmony_ci return 0; 288c87c5fbaSopenharmony_ci 289c87c5fbaSopenharmony_ci while (search_len <= data_len) { 290c87c5fbaSopenharmony_ci 291c87c5fbaSopenharmony_ci /* handle parameter if found */ 292c87c5fbaSopenharmony_ci if (memcmp(search, data, search_len) == 0) { 293c87c5fbaSopenharmony_ci data += search_len; 294c87c5fbaSopenharmony_ci data_len -= search_len; 295c87c5fbaSopenharmony_ci 296c87c5fbaSopenharmony_ci /* key is only valid if we are at end of string or delimiter follows */ 297c87c5fbaSopenharmony_ci if (!data_len || *data == '=' || *data == '&') { 298c87c5fbaSopenharmony_ci while (data_len && *data != '=') { 299c87c5fbaSopenharmony_ci ++data; 300c87c5fbaSopenharmony_ci --data_len; 301c87c5fbaSopenharmony_ci } 302c87c5fbaSopenharmony_ci 303c87c5fbaSopenharmony_ci if (data_len > 1 && result) { 304c87c5fbaSopenharmony_ci /* value begins after '=' */ 305c87c5fbaSopenharmony_ci 306c87c5fbaSopenharmony_ci result->s = ++data; 307c87c5fbaSopenharmony_ci while (--data_len && *data != '&') { 308c87c5fbaSopenharmony_ci ++data; 309c87c5fbaSopenharmony_ci result->length++; 310c87c5fbaSopenharmony_ci } 311c87c5fbaSopenharmony_ci } 312c87c5fbaSopenharmony_ci 313c87c5fbaSopenharmony_ci return 1; 314c87c5fbaSopenharmony_ci } 315c87c5fbaSopenharmony_ci } 316c87c5fbaSopenharmony_ci 317c87c5fbaSopenharmony_ci /* otherwise proceed to next */ 318c87c5fbaSopenharmony_ci while (--data_len && *data++ != '&') 319c87c5fbaSopenharmony_ci ; 320c87c5fbaSopenharmony_ci } 321c87c5fbaSopenharmony_ci 322c87c5fbaSopenharmony_ci return 0; 323c87c5fbaSopenharmony_ci} 324c87c5fbaSopenharmony_ci 325c87c5fbaSopenharmony_cistatic void 326c87c5fbaSopenharmony_ciadd_source_address(coap_resource_t *resource, 327c87c5fbaSopenharmony_ci const coap_address_t *peer) { 328c87c5fbaSopenharmony_ci#define BUFSIZE 64 329c87c5fbaSopenharmony_ci char *buf; 330c87c5fbaSopenharmony_ci size_t n = 1; 331c87c5fbaSopenharmony_ci coap_str_const_t attr_val; 332c87c5fbaSopenharmony_ci 333c87c5fbaSopenharmony_ci buf = (char *)coap_malloc(BUFSIZE); 334c87c5fbaSopenharmony_ci if (!buf) 335c87c5fbaSopenharmony_ci return; 336c87c5fbaSopenharmony_ci 337c87c5fbaSopenharmony_ci n = coap_print_addr(peer, (uint8_t *)buf, BUFSIZE); 338c87c5fbaSopenharmony_ci if (n) { 339c87c5fbaSopenharmony_ci attr_val.s = (const uint8_t *)buf; 340c87c5fbaSopenharmony_ci attr_val.length = n; 341c87c5fbaSopenharmony_ci coap_add_attr(resource, 342c87c5fbaSopenharmony_ci coap_make_str_const("A"), 343c87c5fbaSopenharmony_ci &attr_val, 344c87c5fbaSopenharmony_ci 0); 345c87c5fbaSopenharmony_ci } 346c87c5fbaSopenharmony_ci coap_free(buf); 347c87c5fbaSopenharmony_ci#undef BUFSIZE 348c87c5fbaSopenharmony_ci} 349c87c5fbaSopenharmony_ci 350c87c5fbaSopenharmony_cistatic rd_t * 351c87c5fbaSopenharmony_cimake_rd(const coap_pdu_t *pdu) { 352c87c5fbaSopenharmony_ci rd_t *rd; 353c87c5fbaSopenharmony_ci const uint8_t *data; 354c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 355c87c5fbaSopenharmony_ci coap_opt_t *etag; 356c87c5fbaSopenharmony_ci 357c87c5fbaSopenharmony_ci rd = rd_new(); 358c87c5fbaSopenharmony_ci 359c87c5fbaSopenharmony_ci if (!rd) { 360c87c5fbaSopenharmony_ci coap_log_debug("hnd_get_rd: cannot allocate storage for rd\n"); 361c87c5fbaSopenharmony_ci return NULL; 362c87c5fbaSopenharmony_ci } 363c87c5fbaSopenharmony_ci 364c87c5fbaSopenharmony_ci if (coap_get_data(pdu, &rd->data.length, &data)) { 365c87c5fbaSopenharmony_ci rd->data.s = (unsigned char *)coap_malloc(rd->data.length); 366c87c5fbaSopenharmony_ci if (!rd->data.s) { 367c87c5fbaSopenharmony_ci coap_log_debug("hnd_get_rd: cannot allocate storage for rd->data\n"); 368c87c5fbaSopenharmony_ci rd_delete(rd); 369c87c5fbaSopenharmony_ci return NULL; 370c87c5fbaSopenharmony_ci } 371c87c5fbaSopenharmony_ci memcpy(rd->data.s, data, rd->data.length); 372c87c5fbaSopenharmony_ci } 373c87c5fbaSopenharmony_ci 374c87c5fbaSopenharmony_ci etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); 375c87c5fbaSopenharmony_ci if (etag) { 376c87c5fbaSopenharmony_ci rd->etag_len = min(coap_opt_length(etag), sizeof(rd->etag)); 377c87c5fbaSopenharmony_ci memcpy(rd->etag, coap_opt_value(etag), rd->etag_len); 378c87c5fbaSopenharmony_ci } 379c87c5fbaSopenharmony_ci 380c87c5fbaSopenharmony_ci return rd; 381c87c5fbaSopenharmony_ci} 382c87c5fbaSopenharmony_ci 383c87c5fbaSopenharmony_cistatic void 384c87c5fbaSopenharmony_cihnd_post_rd(coap_resource_t *resource COAP_UNUSED, 385c87c5fbaSopenharmony_ci coap_session_t *session, 386c87c5fbaSopenharmony_ci const coap_pdu_t *request, 387c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 388c87c5fbaSopenharmony_ci coap_pdu_t *response) { 389c87c5fbaSopenharmony_ci coap_resource_t *r; 390c87c5fbaSopenharmony_ci#define LOCSIZE 68 391c87c5fbaSopenharmony_ci unsigned char *loc; 392c87c5fbaSopenharmony_ci size_t loc_size; 393c87c5fbaSopenharmony_ci coap_string_t h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */ 394c87c5fbaSopenharmony_ci unsigned char *buf; 395c87c5fbaSopenharmony_ci coap_str_const_t attr_val; 396c87c5fbaSopenharmony_ci coap_str_const_t resource_val; 397c87c5fbaSopenharmony_ci 398c87c5fbaSopenharmony_ci loc = (unsigned char *)coap_malloc(LOCSIZE); 399c87c5fbaSopenharmony_ci if (!loc) { 400c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 401c87c5fbaSopenharmony_ci return; 402c87c5fbaSopenharmony_ci } 403c87c5fbaSopenharmony_ci memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); 404c87c5fbaSopenharmony_ci 405c87c5fbaSopenharmony_ci loc_size = RD_ROOT_SIZE; 406c87c5fbaSopenharmony_ci loc[loc_size++] = '/'; 407c87c5fbaSopenharmony_ci 408c87c5fbaSopenharmony_ci /* store query parameters for later use */ 409c87c5fbaSopenharmony_ci if (query) { 410c87c5fbaSopenharmony_ci parse_param((const uint8_t *)"h", 1, query->s, query->length, &h); 411c87c5fbaSopenharmony_ci parse_param((const uint8_t *)"ins", 3, query->s, query->length, &ins); 412c87c5fbaSopenharmony_ci parse_param((const uint8_t *)"lt", 2, query->s, query->length, <); 413c87c5fbaSopenharmony_ci parse_param((const uint8_t *)"rt", 2, query->s, query->length, &rt); 414c87c5fbaSopenharmony_ci } 415c87c5fbaSopenharmony_ci 416c87c5fbaSopenharmony_ci if (h.length) { /* client has specified a node name */ 417c87c5fbaSopenharmony_ci memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); 418c87c5fbaSopenharmony_ci loc_size += min(h.length, LOCSIZE - loc_size - 1); 419c87c5fbaSopenharmony_ci 420c87c5fbaSopenharmony_ci if (ins.length && loc_size > 1) { 421c87c5fbaSopenharmony_ci loc[loc_size++] = '-'; 422c87c5fbaSopenharmony_ci memcpy((char *)(loc + loc_size), 423c87c5fbaSopenharmony_ci ins.s, min(ins.length, LOCSIZE - loc_size - 1)); 424c87c5fbaSopenharmony_ci loc_size += min(ins.length, LOCSIZE - loc_size - 1); 425c87c5fbaSopenharmony_ci } 426c87c5fbaSopenharmony_ci 427c87c5fbaSopenharmony_ci } else { /* generate node identifier */ 428c87c5fbaSopenharmony_ci loc_size += 429c87c5fbaSopenharmony_ci snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, 430c87c5fbaSopenharmony_ci "%x", coap_pdu_get_mid(request)); 431c87c5fbaSopenharmony_ci 432c87c5fbaSopenharmony_ci if (loc_size > 1) { 433c87c5fbaSopenharmony_ci if (ins.length) { 434c87c5fbaSopenharmony_ci loc[loc_size++] = '-'; 435c87c5fbaSopenharmony_ci memcpy((char *)(loc + loc_size), 436c87c5fbaSopenharmony_ci ins.s, 437c87c5fbaSopenharmony_ci min(ins.length, LOCSIZE - loc_size - 1)); 438c87c5fbaSopenharmony_ci loc_size += min(ins.length, LOCSIZE - loc_size - 1); 439c87c5fbaSopenharmony_ci } else { 440c87c5fbaSopenharmony_ci coap_tick_t now; 441c87c5fbaSopenharmony_ci coap_ticks(&now); 442c87c5fbaSopenharmony_ci 443c87c5fbaSopenharmony_ci loc_size += snprintf((char *)(loc + loc_size), 444c87c5fbaSopenharmony_ci LOCSIZE - loc_size - 1, 445c87c5fbaSopenharmony_ci "-%x", 446c87c5fbaSopenharmony_ci (unsigned int)(now & (unsigned int)-1)); 447c87c5fbaSopenharmony_ci } 448c87c5fbaSopenharmony_ci } 449c87c5fbaSopenharmony_ci } 450c87c5fbaSopenharmony_ci 451c87c5fbaSopenharmony_ci /* TODO: 452c87c5fbaSopenharmony_ci * - use lt to check expiration 453c87c5fbaSopenharmony_ci */ 454c87c5fbaSopenharmony_ci 455c87c5fbaSopenharmony_ci resource_val.s = loc; 456c87c5fbaSopenharmony_ci resource_val.length = loc_size; 457c87c5fbaSopenharmony_ci r = coap_resource_init(&resource_val, 0); 458c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_resource); 459c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_resource); 460c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); 461c87c5fbaSopenharmony_ci 462c87c5fbaSopenharmony_ci if (ins.s) { 463c87c5fbaSopenharmony_ci buf = (unsigned char *)coap_malloc(ins.length + 2); 464c87c5fbaSopenharmony_ci if (buf) { 465c87c5fbaSopenharmony_ci /* add missing quotes */ 466c87c5fbaSopenharmony_ci buf[0] = '"'; 467c87c5fbaSopenharmony_ci memcpy(buf + 1, ins.s, ins.length); 468c87c5fbaSopenharmony_ci buf[ins.length + 1] = '"'; 469c87c5fbaSopenharmony_ci attr_val.s = buf; 470c87c5fbaSopenharmony_ci attr_val.length = ins.length + 2; 471c87c5fbaSopenharmony_ci coap_add_attr(r, 472c87c5fbaSopenharmony_ci coap_make_str_const("ins"), 473c87c5fbaSopenharmony_ci &attr_val, 474c87c5fbaSopenharmony_ci 0); 475c87c5fbaSopenharmony_ci coap_free(buf); 476c87c5fbaSopenharmony_ci } 477c87c5fbaSopenharmony_ci } 478c87c5fbaSopenharmony_ci 479c87c5fbaSopenharmony_ci if (rt.s) { 480c87c5fbaSopenharmony_ci buf = (unsigned char *)coap_malloc(rt.length + 2); 481c87c5fbaSopenharmony_ci if (buf) { 482c87c5fbaSopenharmony_ci /* add missing quotes */ 483c87c5fbaSopenharmony_ci buf[0] = '"'; 484c87c5fbaSopenharmony_ci memcpy(buf + 1, rt.s, rt.length); 485c87c5fbaSopenharmony_ci buf[rt.length + 1] = '"'; 486c87c5fbaSopenharmony_ci attr_val.s = buf; 487c87c5fbaSopenharmony_ci attr_val.length = rt.length + 2; 488c87c5fbaSopenharmony_ci coap_add_attr(r, 489c87c5fbaSopenharmony_ci coap_make_str_const("rt"), 490c87c5fbaSopenharmony_ci &attr_val, 491c87c5fbaSopenharmony_ci 0); 492c87c5fbaSopenharmony_ci coap_free(buf); 493c87c5fbaSopenharmony_ci } 494c87c5fbaSopenharmony_ci } 495c87c5fbaSopenharmony_ci 496c87c5fbaSopenharmony_ci add_source_address(r, coap_session_get_addr_remote(session)); 497c87c5fbaSopenharmony_ci 498c87c5fbaSopenharmony_ci { 499c87c5fbaSopenharmony_ci rd_t *rd; 500c87c5fbaSopenharmony_ci rd = make_rd(request); 501c87c5fbaSopenharmony_ci if (rd) { 502c87c5fbaSopenharmony_ci coap_resource_set_userdata(r, rd); 503c87c5fbaSopenharmony_ci } else { 504c87c5fbaSopenharmony_ci /* FIXME: send error response and delete r */ 505c87c5fbaSopenharmony_ci } 506c87c5fbaSopenharmony_ci } 507c87c5fbaSopenharmony_ci 508c87c5fbaSopenharmony_ci coap_add_resource(coap_session_get_context(session), r); 509c87c5fbaSopenharmony_ci 510c87c5fbaSopenharmony_ci 511c87c5fbaSopenharmony_ci /* create response */ 512c87c5fbaSopenharmony_ci 513c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); 514c87c5fbaSopenharmony_ci 515c87c5fbaSopenharmony_ci { 516c87c5fbaSopenharmony_ci /* split path into segments and add Location-Path options */ 517c87c5fbaSopenharmony_ci unsigned char _b[LOCSIZE]; 518c87c5fbaSopenharmony_ci unsigned char *b = _b; 519c87c5fbaSopenharmony_ci size_t buflen = sizeof(_b); 520c87c5fbaSopenharmony_ci int nseg; 521c87c5fbaSopenharmony_ci 522c87c5fbaSopenharmony_ci nseg = coap_split_path(loc, loc_size, b, &buflen); 523c87c5fbaSopenharmony_ci while (nseg--) { 524c87c5fbaSopenharmony_ci coap_add_option(response, 525c87c5fbaSopenharmony_ci COAP_OPTION_LOCATION_PATH, 526c87c5fbaSopenharmony_ci coap_opt_length(b), 527c87c5fbaSopenharmony_ci coap_opt_value(b)); 528c87c5fbaSopenharmony_ci b += coap_opt_size(b); 529c87c5fbaSopenharmony_ci } 530c87c5fbaSopenharmony_ci } 531c87c5fbaSopenharmony_ci coap_free(loc); 532c87c5fbaSopenharmony_ci} 533c87c5fbaSopenharmony_ci 534c87c5fbaSopenharmony_cistatic void 535c87c5fbaSopenharmony_ciinit_resources(coap_context_t *ctx) { 536c87c5fbaSopenharmony_ci coap_resource_t *r; 537c87c5fbaSopenharmony_ci 538c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const(RD_ROOT_STR), 0); 539c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_rd); 540c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_POST, hnd_post_rd); 541c87c5fbaSopenharmony_ci 542c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("40"), 0); 543c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"core.rd\""), 0); 544c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ins"), coap_make_str_const("\"default\""), 0); 545c87c5fbaSopenharmony_ci 546c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 547c87c5fbaSopenharmony_ci 548c87c5fbaSopenharmony_ci coap_resource_release_userdata_handler(ctx, resource_rd_delete); 549c87c5fbaSopenharmony_ci} 550c87c5fbaSopenharmony_ci 551c87c5fbaSopenharmony_cistatic void 552c87c5fbaSopenharmony_ciusage(const char *program, const char *version) { 553c87c5fbaSopenharmony_ci const char *p; 554c87c5fbaSopenharmony_ci char buffer[120]; 555c87c5fbaSopenharmony_ci const char *lib_build = coap_package_build(); 556c87c5fbaSopenharmony_ci 557c87c5fbaSopenharmony_ci p = strrchr(program, '/'); 558c87c5fbaSopenharmony_ci if (p) 559c87c5fbaSopenharmony_ci program = ++p; 560c87c5fbaSopenharmony_ci 561c87c5fbaSopenharmony_ci fprintf(stderr, "%s v%s -- CoRE Resource Directory implementation\n" 562c87c5fbaSopenharmony_ci "(c) 2011-2012,2019-2023 Olaf Bergmann <bergmann@tzi.org> and others\n\n" 563c87c5fbaSopenharmony_ci "Build: %s\n" 564c87c5fbaSopenharmony_ci "%s\n" 565c87c5fbaSopenharmony_ci , program, version, lib_build, 566c87c5fbaSopenharmony_ci coap_string_tls_version(buffer, sizeof(buffer))); 567c87c5fbaSopenharmony_ci fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); 568c87c5fbaSopenharmony_ci fprintf(stderr, "\n" 569c87c5fbaSopenharmony_ci "Usage: %s [-g group] [-G group_if] [-p port] [-v num] [-A address]\n" 570c87c5fbaSopenharmony_ci "\t [-w [port][,secure_port]] [-T max_token_size] [-V num]\n" 571c87c5fbaSopenharmony_ci "\t [[-h hint] [-k key]]\n" 572c87c5fbaSopenharmony_ci "\t [[-c certfile] [-C cafile] [-n] [-R trust_casfile]]\n" 573c87c5fbaSopenharmony_ci "General Options\n" 574c87c5fbaSopenharmony_ci "\t-g group\tJoin the given multicast group.\n" 575c87c5fbaSopenharmony_ci "\t \t\tNote: DTLS over multicast is not currently supported\n" 576c87c5fbaSopenharmony_ci "\t-G group_if\tUse this interface for listening for the multicast\n" 577c87c5fbaSopenharmony_ci "\t \t\tgroup. This can be different from the implied interface\n" 578c87c5fbaSopenharmony_ci "\t \t\tif the -A option is used\n" 579c87c5fbaSopenharmony_ci "\t-p port\t\tListen on specified port\n" 580c87c5fbaSopenharmony_ci "\t-v num \t\tVerbosity level (default 4, maximum is 8) for general\n" 581c87c5fbaSopenharmony_ci "\t \t\tCoAP logging\n" 582c87c5fbaSopenharmony_ci "\t-w [port][,secure_port]\n" 583c87c5fbaSopenharmony_ci "\t \t\tEnable WebSockets support on port (WS) and/or secure_port\n" 584c87c5fbaSopenharmony_ci "\t \t\t(WSS), comma separated\n" 585c87c5fbaSopenharmony_ci "\t-A address\tInterface address to bind to\n" 586c87c5fbaSopenharmony_ci "\t-T max_token_length\tSet the maximum token length (8-65804)\n" 587c87c5fbaSopenharmony_ci "\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n" 588c87c5fbaSopenharmony_ci "\t \t\tlibrary logging\n" 589c87c5fbaSopenharmony_ci "PSK Options (if supported by underlying (D)TLS library)\n" 590c87c5fbaSopenharmony_ci "\t-h hint\t\tIdentity Hint. Default is CoAP. Zero length is no hint\n" 591c87c5fbaSopenharmony_ci "\t-k key \t\tPre-Shared Key. This argument requires (D)TLS with PSK\n" 592c87c5fbaSopenharmony_ci "\t \t\tto be available. This cannot be empty if defined.\n" 593c87c5fbaSopenharmony_ci "\t \t\tNote that both -c and -k need to be defined\n" 594c87c5fbaSopenharmony_ci "\t \t\tfor both PSK and PKI to be concurrently supported\n" 595c87c5fbaSopenharmony_ci "PKI Options (if supported by underlying (D)TLS library)\n" 596c87c5fbaSopenharmony_ci "\t-c certfile\tPEM file containing both CERTIFICATE and PRIVATE KEY\n" 597c87c5fbaSopenharmony_ci "\t \t\tThis argument requires (D)TLS with PKI to be available\n" 598c87c5fbaSopenharmony_ci "\t-n \t\tDisable remote peer certificate checking. This gives\n" 599c87c5fbaSopenharmony_ci "\t \t\tclients the ability to use PKI, but without any defined\n" 600c87c5fbaSopenharmony_ci "\t \t\tcertificates\n" 601c87c5fbaSopenharmony_ci "\t-C cafile\tPEM file that contains a list of one or\n" 602c87c5fbaSopenharmony_ci "\t \t\tmore CAs that are to be passed to the client for the\n" 603c87c5fbaSopenharmony_ci "\t \t\tclient to determine what client certificate to use.\n" 604c87c5fbaSopenharmony_ci "\t \t\tNormally, this list of CAs would be the root CA and and\n" 605c87c5fbaSopenharmony_ci "\t \t\tany intermediate CAs. Ideally the server certificate\n" 606c87c5fbaSopenharmony_ci "\t \t\tshould be signed by the same CA so that mutual\n" 607c87c5fbaSopenharmony_ci "\t \t\tauthentication can take place. The contents of cafile\n" 608c87c5fbaSopenharmony_ci "\t \t\tare added to the trusted store of root CAs.\n" 609c87c5fbaSopenharmony_ci "\t \t\tUsing the -C or -R options will will trigger the\n" 610c87c5fbaSopenharmony_ci "\t \t\tvalidation of the client certificate unless overridden\n" 611c87c5fbaSopenharmony_ci "\t \t\tby the -n option\n" 612c87c5fbaSopenharmony_ci "\t-R trust_casfile\tPEM file containing the set of trusted root CAs\n" 613c87c5fbaSopenharmony_ci "\t \t\tthat are to be used to validate the client certificate.\n" 614c87c5fbaSopenharmony_ci "\t \t\tAlternatively, this can point to a directory containing\n" 615c87c5fbaSopenharmony_ci "\t \t\ta set of CA PEM files.\n" 616c87c5fbaSopenharmony_ci "\t \t\tUsing '-R trust_casfile' disables common CA mutual\n" 617c87c5fbaSopenharmony_ci "\t \t\tauthentication which can only be done by using\n" 618c87c5fbaSopenharmony_ci "\t \t\t'-C cafile'.\n" 619c87c5fbaSopenharmony_ci "\t \t\tUsing the -C or -R options will will trigger the\n" 620c87c5fbaSopenharmony_ci "\t \t\tvalidation of the client certificate unless overridden\n" 621c87c5fbaSopenharmony_ci "\t \t\tby the -n option\n" 622c87c5fbaSopenharmony_ci , 623c87c5fbaSopenharmony_ci program); 624c87c5fbaSopenharmony_ci} 625c87c5fbaSopenharmony_ci 626c87c5fbaSopenharmony_cistatic void 627c87c5fbaSopenharmony_cifill_keystore(coap_context_t *ctx) { 628c87c5fbaSopenharmony_ci if (cert_file == NULL && key_defined == 0) { 629c87c5fbaSopenharmony_ci if (coap_dtls_is_supported() || coap_tls_is_supported()) { 630c87c5fbaSopenharmony_ci coap_log_debug("(D)TLS not enabled as neither -k or -c options specified\n"); 631c87c5fbaSopenharmony_ci } 632c87c5fbaSopenharmony_ci } 633c87c5fbaSopenharmony_ci if (cert_file) { 634c87c5fbaSopenharmony_ci coap_dtls_pki_t dtls_pki; 635c87c5fbaSopenharmony_ci memset(&dtls_pki, 0, sizeof(dtls_pki)); 636c87c5fbaSopenharmony_ci dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; 637c87c5fbaSopenharmony_ci if (ca_file || root_ca_file) { 638c87c5fbaSopenharmony_ci /* 639c87c5fbaSopenharmony_ci * Add in additional certificate checking. 640c87c5fbaSopenharmony_ci * This list of enabled can be tuned for the specific 641c87c5fbaSopenharmony_ci * requirements - see 'man coap_encryption'. 642c87c5fbaSopenharmony_ci */ 643c87c5fbaSopenharmony_ci dtls_pki.verify_peer_cert = verify_peer_cert; 644c87c5fbaSopenharmony_ci dtls_pki.check_common_ca = !root_ca_file; 645c87c5fbaSopenharmony_ci dtls_pki.allow_self_signed = 1; 646c87c5fbaSopenharmony_ci dtls_pki.allow_expired_certs = 1; 647c87c5fbaSopenharmony_ci dtls_pki.cert_chain_validation = 1; 648c87c5fbaSopenharmony_ci dtls_pki.cert_chain_verify_depth = 2; 649c87c5fbaSopenharmony_ci dtls_pki.check_cert_revocation = 1; 650c87c5fbaSopenharmony_ci dtls_pki.allow_no_crl = 1; 651c87c5fbaSopenharmony_ci dtls_pki.allow_expired_crl = 1; 652c87c5fbaSopenharmony_ci dtls_pki.validate_cn_call_back = NULL; 653c87c5fbaSopenharmony_ci dtls_pki.cn_call_back_arg = NULL; 654c87c5fbaSopenharmony_ci dtls_pki.validate_sni_call_back = NULL; 655c87c5fbaSopenharmony_ci dtls_pki.sni_call_back_arg = NULL; 656c87c5fbaSopenharmony_ci } 657c87c5fbaSopenharmony_ci dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; 658c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem.public_cert = cert_file; 659c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem.private_key = cert_file; 660c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem.ca_file = ca_file; 661c87c5fbaSopenharmony_ci /* If general root CAs are defined */ 662c87c5fbaSopenharmony_ci if (root_ca_file) { 663c87c5fbaSopenharmony_ci struct stat stbuf; 664c87c5fbaSopenharmony_ci if ((stat(root_ca_file, &stbuf) == 0) && S_ISDIR(stbuf.st_mode)) { 665c87c5fbaSopenharmony_ci coap_context_set_pki_root_cas(ctx, NULL, root_ca_file); 666c87c5fbaSopenharmony_ci } else { 667c87c5fbaSopenharmony_ci coap_context_set_pki_root_cas(ctx, root_ca_file, NULL); 668c87c5fbaSopenharmony_ci } 669c87c5fbaSopenharmony_ci } 670c87c5fbaSopenharmony_ci coap_context_set_pki(ctx, &dtls_pki); 671c87c5fbaSopenharmony_ci } 672c87c5fbaSopenharmony_ci if (key_defined) { 673c87c5fbaSopenharmony_ci coap_dtls_spsk_t dtls_psk; 674c87c5fbaSopenharmony_ci memset(&dtls_psk, 0, sizeof(dtls_psk)); 675c87c5fbaSopenharmony_ci dtls_psk.version = COAP_DTLS_SPSK_SETUP_VERSION; 676c87c5fbaSopenharmony_ci dtls_psk.validate_id_call_back = NULL; 677c87c5fbaSopenharmony_ci dtls_psk.validate_sni_call_back = NULL; 678c87c5fbaSopenharmony_ci dtls_psk.psk_info.hint.s = (const uint8_t *)hint; 679c87c5fbaSopenharmony_ci dtls_psk.psk_info.hint.length = hint ? strlen(hint) : 0; 680c87c5fbaSopenharmony_ci dtls_psk.psk_info.key.s = key; 681c87c5fbaSopenharmony_ci dtls_psk.psk_info.key.length = key_length; 682c87c5fbaSopenharmony_ci coap_context_set_psk2(ctx, &dtls_psk); 683c87c5fbaSopenharmony_ci } 684c87c5fbaSopenharmony_ci} 685c87c5fbaSopenharmony_ci 686c87c5fbaSopenharmony_cistatic coap_context_t * 687c87c5fbaSopenharmony_ciget_context(const char *node, const char *port) { 688c87c5fbaSopenharmony_ci coap_context_t *ctx = NULL; 689c87c5fbaSopenharmony_ci coap_addr_info_t *info = NULL; 690c87c5fbaSopenharmony_ci coap_addr_info_t *info_list = NULL; 691c87c5fbaSopenharmony_ci coap_str_const_t local; 692c87c5fbaSopenharmony_ci int have_ep = 0; 693c87c5fbaSopenharmony_ci uint16_t u_s_port = 0; 694c87c5fbaSopenharmony_ci uint16_t s_port = 0; 695c87c5fbaSopenharmony_ci int scheme_hint_bits = 0; 696c87c5fbaSopenharmony_ci 697c87c5fbaSopenharmony_ci ctx = coap_new_context(NULL); 698c87c5fbaSopenharmony_ci if (!ctx) { 699c87c5fbaSopenharmony_ci return NULL; 700c87c5fbaSopenharmony_ci } 701c87c5fbaSopenharmony_ci 702c87c5fbaSopenharmony_ci /* Need PKI/RPK/PSK set up before we set up (D)TLS endpoints */ 703c87c5fbaSopenharmony_ci fill_keystore(ctx); 704c87c5fbaSopenharmony_ci 705c87c5fbaSopenharmony_ci if (node) { 706c87c5fbaSopenharmony_ci local.s = (const uint8_t *)node; 707c87c5fbaSopenharmony_ci local.length = strlen(node); 708c87c5fbaSopenharmony_ci } 709c87c5fbaSopenharmony_ci 710c87c5fbaSopenharmony_ci if (port) { 711c87c5fbaSopenharmony_ci u_s_port = atoi(port); 712c87c5fbaSopenharmony_ci s_port = u_s_port + 1; 713c87c5fbaSopenharmony_ci } 714c87c5fbaSopenharmony_ci scheme_hint_bits = 715c87c5fbaSopenharmony_ci coap_get_available_scheme_hint_bits(cert_file != NULL || key_defined != 0, 716c87c5fbaSopenharmony_ci enable_ws, COAP_PROTO_NONE); 717c87c5fbaSopenharmony_ci info_list = coap_resolve_address_info(node ? &local : NULL, u_s_port, s_port, 718c87c5fbaSopenharmony_ci ws_port, wss_port, 719c87c5fbaSopenharmony_ci AI_PASSIVE | AI_NUMERICHOST, 720c87c5fbaSopenharmony_ci scheme_hint_bits, 721c87c5fbaSopenharmony_ci COAP_RESOLVE_TYPE_LOCAL); 722c87c5fbaSopenharmony_ci for (info = info_list; info != NULL; info = info->next) { 723c87c5fbaSopenharmony_ci coap_endpoint_t *ep; 724c87c5fbaSopenharmony_ci 725c87c5fbaSopenharmony_ci ep = coap_new_endpoint(ctx, &info->addr, info->proto); 726c87c5fbaSopenharmony_ci if (!ep) { 727c87c5fbaSopenharmony_ci coap_log_warn("cannot create endpoint for proto %u\n", 728c87c5fbaSopenharmony_ci info->proto); 729c87c5fbaSopenharmony_ci } else { 730c87c5fbaSopenharmony_ci have_ep = 1; 731c87c5fbaSopenharmony_ci } 732c87c5fbaSopenharmony_ci } 733c87c5fbaSopenharmony_ci coap_free_address_info(info_list); 734c87c5fbaSopenharmony_ci if (!have_ep) { 735c87c5fbaSopenharmony_ci coap_log_err("No context available for interface '%s'\n", node); 736c87c5fbaSopenharmony_ci coap_free_context(ctx); 737c87c5fbaSopenharmony_ci return NULL; 738c87c5fbaSopenharmony_ci } 739c87c5fbaSopenharmony_ci return ctx; 740c87c5fbaSopenharmony_ci} 741c87c5fbaSopenharmony_ci 742c87c5fbaSopenharmony_cistatic int 743c87c5fbaSopenharmony_cicmdline_read_extended_token_size(char *arg) { 744c87c5fbaSopenharmony_ci extended_token_size = strtoul(arg, NULL, 0); 745c87c5fbaSopenharmony_ci if (extended_token_size < COAP_TOKEN_DEFAULT_MAX) { 746c87c5fbaSopenharmony_ci coap_log_err("Extended Token Length must be 8 or greater\n"); 747c87c5fbaSopenharmony_ci return 0; 748c87c5fbaSopenharmony_ci } else if (extended_token_size > COAP_TOKEN_EXT_MAX) { 749c87c5fbaSopenharmony_ci coap_log_err("Extended Token Length must be 65804 or less\n"); 750c87c5fbaSopenharmony_ci return 0; 751c87c5fbaSopenharmony_ci } 752c87c5fbaSopenharmony_ci return 1; 753c87c5fbaSopenharmony_ci} 754c87c5fbaSopenharmony_ci 755c87c5fbaSopenharmony_ciint 756c87c5fbaSopenharmony_cimain(int argc, char **argv) { 757c87c5fbaSopenharmony_ci coap_context_t *ctx; 758c87c5fbaSopenharmony_ci int result; 759c87c5fbaSopenharmony_ci char addr_str[NI_MAXHOST] = "::"; 760c87c5fbaSopenharmony_ci char port_str[NI_MAXSERV] = "5683"; 761c87c5fbaSopenharmony_ci char *group = NULL; 762c87c5fbaSopenharmony_ci char *group_if = NULL; 763c87c5fbaSopenharmony_ci int opt; 764c87c5fbaSopenharmony_ci coap_log_t log_level = COAP_LOG_WARN; 765c87c5fbaSopenharmony_ci coap_log_t dtls_log_level = COAP_LOG_ERR; 766c87c5fbaSopenharmony_ci#ifndef _WIN32 767c87c5fbaSopenharmony_ci struct sigaction sa; 768c87c5fbaSopenharmony_ci#endif 769c87c5fbaSopenharmony_ci 770c87c5fbaSopenharmony_ci /* Initialize libcoap library */ 771c87c5fbaSopenharmony_ci coap_startup(); 772c87c5fbaSopenharmony_ci 773c87c5fbaSopenharmony_ci while ((opt = getopt(argc, argv, "A:c:C:g:G:h:k:n:R:p:v:T:V:w:")) != -1) { 774c87c5fbaSopenharmony_ci switch (opt) { 775c87c5fbaSopenharmony_ci case 'A' : 776c87c5fbaSopenharmony_ci strncpy(addr_str, optarg, NI_MAXHOST-1); 777c87c5fbaSopenharmony_ci addr_str[NI_MAXHOST - 1] = '\0'; 778c87c5fbaSopenharmony_ci break; 779c87c5fbaSopenharmony_ci case 'c' : 780c87c5fbaSopenharmony_ci cert_file = optarg; 781c87c5fbaSopenharmony_ci break; 782c87c5fbaSopenharmony_ci case 'C' : 783c87c5fbaSopenharmony_ci ca_file = optarg; 784c87c5fbaSopenharmony_ci break; 785c87c5fbaSopenharmony_ci case 'g' : 786c87c5fbaSopenharmony_ci group = optarg; 787c87c5fbaSopenharmony_ci break; 788c87c5fbaSopenharmony_ci case 'G' : 789c87c5fbaSopenharmony_ci group_if = optarg; 790c87c5fbaSopenharmony_ci break; 791c87c5fbaSopenharmony_ci case 'h' : 792c87c5fbaSopenharmony_ci if (!optarg[0]) { 793c87c5fbaSopenharmony_ci hint = NULL; 794c87c5fbaSopenharmony_ci break; 795c87c5fbaSopenharmony_ci } 796c87c5fbaSopenharmony_ci hint = optarg; 797c87c5fbaSopenharmony_ci break; 798c87c5fbaSopenharmony_ci case 'k' : 799c87c5fbaSopenharmony_ci key_length = cmdline_read_key(optarg, key, MAX_KEY); 800c87c5fbaSopenharmony_ci if (key_length < 0) { 801c87c5fbaSopenharmony_ci coap_log_crit("Invalid Pre-Shared Key specified\n"); 802c87c5fbaSopenharmony_ci break; 803c87c5fbaSopenharmony_ci } 804c87c5fbaSopenharmony_ci key_defined = 1; 805c87c5fbaSopenharmony_ci break; 806c87c5fbaSopenharmony_ci case 'n': 807c87c5fbaSopenharmony_ci verify_peer_cert = 0; 808c87c5fbaSopenharmony_ci break; 809c87c5fbaSopenharmony_ci case 'p' : 810c87c5fbaSopenharmony_ci strncpy(port_str, optarg, NI_MAXSERV-1); 811c87c5fbaSopenharmony_ci port_str[NI_MAXSERV - 1] = '\0'; 812c87c5fbaSopenharmony_ci break; 813c87c5fbaSopenharmony_ci case 'R' : 814c87c5fbaSopenharmony_ci root_ca_file = optarg; 815c87c5fbaSopenharmony_ci break; 816c87c5fbaSopenharmony_ci case 'T': 817c87c5fbaSopenharmony_ci if (!cmdline_read_extended_token_size(optarg)) { 818c87c5fbaSopenharmony_ci exit(1); 819c87c5fbaSopenharmony_ci } 820c87c5fbaSopenharmony_ci break; 821c87c5fbaSopenharmony_ci case 'v' : 822c87c5fbaSopenharmony_ci log_level = strtol(optarg, NULL, 10); 823c87c5fbaSopenharmony_ci break; 824c87c5fbaSopenharmony_ci case 'V': 825c87c5fbaSopenharmony_ci dtls_log_level = strtol(optarg, NULL, 10); 826c87c5fbaSopenharmony_ci break; 827c87c5fbaSopenharmony_ci case 'w': 828c87c5fbaSopenharmony_ci if (!coap_ws_is_supported() || !cmdline_ws(optarg)) { 829c87c5fbaSopenharmony_ci fprintf(stderr, "WebSockets not enabled in libcoap\n"); 830c87c5fbaSopenharmony_ci exit(1); 831c87c5fbaSopenharmony_ci } 832c87c5fbaSopenharmony_ci enable_ws = 1; 833c87c5fbaSopenharmony_ci break; 834c87c5fbaSopenharmony_ci default: 835c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 836c87c5fbaSopenharmony_ci exit(1); 837c87c5fbaSopenharmony_ci } 838c87c5fbaSopenharmony_ci } 839c87c5fbaSopenharmony_ci 840c87c5fbaSopenharmony_ci coap_set_log_level(log_level); 841c87c5fbaSopenharmony_ci coap_dtls_set_log_level(dtls_log_level); 842c87c5fbaSopenharmony_ci 843c87c5fbaSopenharmony_ci ctx = get_context(addr_str, port_str); 844c87c5fbaSopenharmony_ci if (!ctx) 845c87c5fbaSopenharmony_ci return -1; 846c87c5fbaSopenharmony_ci 847c87c5fbaSopenharmony_ci if (group) 848c87c5fbaSopenharmony_ci coap_join_mcast_group_intf(ctx, group, group_if); 849c87c5fbaSopenharmony_ci 850c87c5fbaSopenharmony_ci init_resources(ctx); 851c87c5fbaSopenharmony_ci if (extended_token_size > COAP_TOKEN_DEFAULT_MAX) 852c87c5fbaSopenharmony_ci coap_context_set_max_token_size(ctx, extended_token_size); 853c87c5fbaSopenharmony_ci 854c87c5fbaSopenharmony_ci#ifdef _WIN32 855c87c5fbaSopenharmony_ci signal(SIGINT, handle_sigint); 856c87c5fbaSopenharmony_ci#else 857c87c5fbaSopenharmony_ci memset(&sa, 0, sizeof(sa)); 858c87c5fbaSopenharmony_ci sigemptyset(&sa.sa_mask); 859c87c5fbaSopenharmony_ci sa.sa_handler = handle_sigint; 860c87c5fbaSopenharmony_ci sa.sa_flags = 0; 861c87c5fbaSopenharmony_ci sigaction(SIGINT, &sa, NULL); 862c87c5fbaSopenharmony_ci sigaction(SIGTERM, &sa, NULL); 863c87c5fbaSopenharmony_ci /* So we do not exit on a SIGPIPE */ 864c87c5fbaSopenharmony_ci sa.sa_handler = SIG_IGN; 865c87c5fbaSopenharmony_ci sigaction(SIGPIPE, &sa, NULL); 866c87c5fbaSopenharmony_ci#endif 867c87c5fbaSopenharmony_ci 868c87c5fbaSopenharmony_ci while (!quit) { 869c87c5fbaSopenharmony_ci result = coap_io_process(ctx, COAP_RESOURCE_CHECK_TIME * 1000); 870c87c5fbaSopenharmony_ci if (result >= 0) { 871c87c5fbaSopenharmony_ci /* coap_check_resource_list( ctx ); */ 872c87c5fbaSopenharmony_ci } 873c87c5fbaSopenharmony_ci } 874c87c5fbaSopenharmony_ci 875c87c5fbaSopenharmony_ci coap_free_context(ctx); 876c87c5fbaSopenharmony_ci coap_cleanup(); 877c87c5fbaSopenharmony_ci 878c87c5fbaSopenharmony_ci return 0; 879c87c5fbaSopenharmony_ci} 880