1c87c5fbaSopenharmony_ci/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2c87c5fbaSopenharmony_ci 3c87c5fbaSopenharmony_ci/* coap-client -- simple CoAP client 4c87c5fbaSopenharmony_ci * 5c87c5fbaSopenharmony_ci * Copyright (C) 2010--2023 Olaf Bergmann <bergmann@tzi.org> and others 6c87c5fbaSopenharmony_ci * 7c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 8c87c5fbaSopenharmony_ci * 9c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see README for terms of 10c87c5fbaSopenharmony_ci * use. 11c87c5fbaSopenharmony_ci */ 12c87c5fbaSopenharmony_ci 13c87c5fbaSopenharmony_ci#include <string.h> 14c87c5fbaSopenharmony_ci#include <stdlib.h> 15c87c5fbaSopenharmony_ci#include <stdio.h> 16c87c5fbaSopenharmony_ci#include <ctype.h> 17c87c5fbaSopenharmony_ci#include <signal.h> 18c87c5fbaSopenharmony_ci#include <inttypes.h> 19c87c5fbaSopenharmony_ci#include <sys/types.h> 20c87c5fbaSopenharmony_ci#include <sys/stat.h> 21c87c5fbaSopenharmony_ci#ifdef _WIN32 22c87c5fbaSopenharmony_ci#define strcasecmp _stricmp 23c87c5fbaSopenharmony_ci#define strncasecmp _strnicmp 24c87c5fbaSopenharmony_ci#define fileno _fileno 25c87c5fbaSopenharmony_ci#define getpid GetCurrentProcessId 26c87c5fbaSopenharmony_ci#include "getopt.c" 27c87c5fbaSopenharmony_ci#if !defined(S_ISDIR) 28c87c5fbaSopenharmony_ci#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 29c87c5fbaSopenharmony_ci#endif 30c87c5fbaSopenharmony_cichar *strndup(const char *s1, size_t n); 31c87c5fbaSopenharmony_cichar * 32c87c5fbaSopenharmony_cistrndup(const char *s1, size_t n) { 33c87c5fbaSopenharmony_ci char *copy = (char *)malloc(n + 1); 34c87c5fbaSopenharmony_ci if (copy) { 35c87c5fbaSopenharmony_ci memcpy(copy, s1, n); 36c87c5fbaSopenharmony_ci copy[n] = 0; 37c87c5fbaSopenharmony_ci } 38c87c5fbaSopenharmony_ci return copy; 39c87c5fbaSopenharmony_ci} 40c87c5fbaSopenharmony_ci#else 41c87c5fbaSopenharmony_ci#include <unistd.h> 42c87c5fbaSopenharmony_ci#include <sys/select.h> 43c87c5fbaSopenharmony_ci#include <sys/socket.h> 44c87c5fbaSopenharmony_ci#include <netinet/in.h> 45c87c5fbaSopenharmony_ci#include <arpa/inet.h> 46c87c5fbaSopenharmony_ci#include <netdb.h> 47c87c5fbaSopenharmony_ci#include <syslog.h> 48c87c5fbaSopenharmony_ci#endif 49c87c5fbaSopenharmony_ci 50c87c5fbaSopenharmony_ci#include <coap3/coap.h> 51c87c5fbaSopenharmony_ci 52c87c5fbaSopenharmony_ci#define MAX_USER 128 /* Maximum length of a user name (i.e., PSK 53c87c5fbaSopenharmony_ci * identity) in bytes. */ 54c87c5fbaSopenharmony_ci#define MAX_KEY 64 /* Maximum length of a key (i.e., PSK) in bytes. */ 55c87c5fbaSopenharmony_ci 56c87c5fbaSopenharmony_ciint flags = 0; 57c87c5fbaSopenharmony_ci 58c87c5fbaSopenharmony_cistatic unsigned char _token_data[24]; /* With support for RFC8974 */ 59c87c5fbaSopenharmony_cicoap_binary_t the_token = { 0, _token_data }; 60c87c5fbaSopenharmony_ci 61c87c5fbaSopenharmony_citypedef struct { 62c87c5fbaSopenharmony_ci coap_binary_t *token; 63c87c5fbaSopenharmony_ci int observe; 64c87c5fbaSopenharmony_ci} track_token; 65c87c5fbaSopenharmony_ci 66c87c5fbaSopenharmony_citrack_token *tracked_tokens = NULL; 67c87c5fbaSopenharmony_cisize_t tracked_tokens_count = 0; 68c87c5fbaSopenharmony_ci 69c87c5fbaSopenharmony_ci#define FLAGS_BLOCK 0x01 70c87c5fbaSopenharmony_ci 71c87c5fbaSopenharmony_cistatic coap_optlist_t *optlist = NULL; 72c87c5fbaSopenharmony_ci/* Request URI. 73c87c5fbaSopenharmony_ci * TODO: associate the resources with transaction id and make it expireable */ 74c87c5fbaSopenharmony_cistatic coap_uri_t uri; 75c87c5fbaSopenharmony_cistatic coap_uri_t proxy = { {0, NULL}, 0, {0, NULL}, {0, NULL}, 0 }; 76c87c5fbaSopenharmony_cistatic int proxy_scheme_option = 0; 77c87c5fbaSopenharmony_cistatic int uri_host_option = 0; 78c87c5fbaSopenharmony_cistatic unsigned int ping_seconds = 0; 79c87c5fbaSopenharmony_ci 80c87c5fbaSopenharmony_ci#define REPEAT_DELAY_MS 1000 81c87c5fbaSopenharmony_cistatic size_t repeat_count = 1; 82c87c5fbaSopenharmony_ci 83c87c5fbaSopenharmony_ci/* reading is done when this flag is set */ 84c87c5fbaSopenharmony_cistatic int ready = 0; 85c87c5fbaSopenharmony_ci 86c87c5fbaSopenharmony_ci/* processing a block response when this flag is set */ 87c87c5fbaSopenharmony_cistatic int doing_getting_block = 0; 88c87c5fbaSopenharmony_cistatic int single_block_requested = 0; 89c87c5fbaSopenharmony_cistatic uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP; 90c87c5fbaSopenharmony_ci 91c87c5fbaSopenharmony_cistatic coap_string_t output_file = { 0, NULL }; /* output file name */ 92c87c5fbaSopenharmony_cistatic FILE *file = NULL; /* output file stream */ 93c87c5fbaSopenharmony_ci 94c87c5fbaSopenharmony_cistatic coap_string_t payload = { 0, NULL }; /* optional payload to send */ 95c87c5fbaSopenharmony_ci 96c87c5fbaSopenharmony_cistatic int reliable = 0; 97c87c5fbaSopenharmony_ci 98c87c5fbaSopenharmony_cistatic int add_nl = 0; 99c87c5fbaSopenharmony_cistatic int is_mcast = 0; 100c87c5fbaSopenharmony_cistatic uint32_t csm_max_message_size = 0; 101c87c5fbaSopenharmony_ci 102c87c5fbaSopenharmony_ciunsigned char msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */ 103c87c5fbaSopenharmony_ci 104c87c5fbaSopenharmony_cistatic char *cert_file = NULL; /* certificate and optional private key in PEM, 105c87c5fbaSopenharmony_ci or PKCS11 URI*/ 106c87c5fbaSopenharmony_cistatic char *key_file = NULL; /* private key in PEM, DER or PKCS11 URI */ 107c87c5fbaSopenharmony_cistatic char *pkcs11_pin = NULL; /* PKCS11 pin to unlock access to token */ 108c87c5fbaSopenharmony_cistatic char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM, 109c87c5fbaSopenharmony_ci DER or PKCS11 URI */ 110c87c5fbaSopenharmony_cistatic char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */ 111c87c5fbaSopenharmony_cistatic int is_rpk_not_cert = 0; /* Cert is RPK if set */ 112c87c5fbaSopenharmony_cistatic uint8_t *cert_mem = NULL; /* certificate and private key in PEM_BUF */ 113c87c5fbaSopenharmony_cistatic uint8_t *key_mem = NULL; /* private key in PEM_BUF */ 114c87c5fbaSopenharmony_cistatic uint8_t *ca_mem = NULL; /* CA for cert checking in PEM_BUF */ 115c87c5fbaSopenharmony_cistatic size_t cert_mem_len = 0; 116c87c5fbaSopenharmony_cistatic size_t key_mem_len = 0; 117c87c5fbaSopenharmony_cistatic size_t ca_mem_len = 0; 118c87c5fbaSopenharmony_cistatic int verify_peer_cert = 1; /* PKI granularity - by default set */ 119c87c5fbaSopenharmony_ci 120c87c5fbaSopenharmony_citypedef struct ih_def_t { 121c87c5fbaSopenharmony_ci char *hint_match; 122c87c5fbaSopenharmony_ci coap_bin_const_t *new_identity; 123c87c5fbaSopenharmony_ci coap_bin_const_t *new_key; 124c87c5fbaSopenharmony_ci} ih_def_t; 125c87c5fbaSopenharmony_ci 126c87c5fbaSopenharmony_citypedef struct valid_ihs_t { 127c87c5fbaSopenharmony_ci size_t count; 128c87c5fbaSopenharmony_ci ih_def_t *ih_list; 129c87c5fbaSopenharmony_ci} valid_ihs_t; 130c87c5fbaSopenharmony_ci 131c87c5fbaSopenharmony_cistatic valid_ihs_t valid_ihs = {0, NULL}; 132c87c5fbaSopenharmony_ci 133c87c5fbaSopenharmony_citypedef unsigned char method_t; 134c87c5fbaSopenharmony_cimethod_t method = 1; /* the method we are using in our requests */ 135c87c5fbaSopenharmony_ci 136c87c5fbaSopenharmony_cicoap_block_t block = { .num = 0, .m = 0, .szx = 6 }; 137c87c5fbaSopenharmony_ciuint16_t last_block1_mid = 0; 138c87c5fbaSopenharmony_ci 139c87c5fbaSopenharmony_ci#define DEFAULT_WAIT_TIME 90 140c87c5fbaSopenharmony_ci 141c87c5fbaSopenharmony_ciunsigned int wait_seconds = DEFAULT_WAIT_TIME; /* default timeout in seconds */ 142c87c5fbaSopenharmony_ciunsigned int wait_ms = 0; 143c87c5fbaSopenharmony_ciint obs_started = 0; 144c87c5fbaSopenharmony_ciunsigned int obs_seconds = 30; /* default observe time */ 145c87c5fbaSopenharmony_ciunsigned int obs_ms = 0; /* timeout for current subscription */ 146c87c5fbaSopenharmony_ciint obs_ms_reset = 0; 147c87c5fbaSopenharmony_ciint doing_observe = 0; 148c87c5fbaSopenharmony_ci 149c87c5fbaSopenharmony_ci#ifndef min 150c87c5fbaSopenharmony_ci#define min(a,b) ((a) < (b) ? (a) : (b)) 151c87c5fbaSopenharmony_ci#endif 152c87c5fbaSopenharmony_ci 153c87c5fbaSopenharmony_cistatic coap_oscore_conf_t *oscore_conf = NULL; 154c87c5fbaSopenharmony_cistatic int doing_oscore = 0; 155c87c5fbaSopenharmony_ci 156c87c5fbaSopenharmony_cistatic int quit = 0; 157c87c5fbaSopenharmony_ci 158c87c5fbaSopenharmony_ci/* SIGINT handler: set quit to 1 for graceful termination */ 159c87c5fbaSopenharmony_cistatic void 160c87c5fbaSopenharmony_cihandle_sigint(int signum COAP_UNUSED) { 161c87c5fbaSopenharmony_ci quit = 1; 162c87c5fbaSopenharmony_ci} 163c87c5fbaSopenharmony_ci 164c87c5fbaSopenharmony_cistatic int 165c87c5fbaSopenharmony_ciappend_to_output(const uint8_t *data, size_t len) { 166c87c5fbaSopenharmony_ci size_t written; 167c87c5fbaSopenharmony_ci 168c87c5fbaSopenharmony_ci if (!file) { 169c87c5fbaSopenharmony_ci if (!output_file.s || (output_file.length && output_file.s[0] == '-')) { 170c87c5fbaSopenharmony_ci file = stdout; 171c87c5fbaSopenharmony_ci } else { 172c87c5fbaSopenharmony_ci if (!(file = fopen((char *)output_file.s, "w"))) { 173c87c5fbaSopenharmony_ci perror("fopen"); 174c87c5fbaSopenharmony_ci return -1; 175c87c5fbaSopenharmony_ci } 176c87c5fbaSopenharmony_ci } 177c87c5fbaSopenharmony_ci } 178c87c5fbaSopenharmony_ci 179c87c5fbaSopenharmony_ci do { 180c87c5fbaSopenharmony_ci written = fwrite(data, 1, len, file); 181c87c5fbaSopenharmony_ci len -= written; 182c87c5fbaSopenharmony_ci data += written; 183c87c5fbaSopenharmony_ci } while (written && len); 184c87c5fbaSopenharmony_ci fflush(file); 185c87c5fbaSopenharmony_ci 186c87c5fbaSopenharmony_ci return 0; 187c87c5fbaSopenharmony_ci} 188c87c5fbaSopenharmony_ci 189c87c5fbaSopenharmony_cistatic void 190c87c5fbaSopenharmony_ciclose_output(void) { 191c87c5fbaSopenharmony_ci if (file) { 192c87c5fbaSopenharmony_ci 193c87c5fbaSopenharmony_ci /* add a newline before closing if no option '-o' was specified */ 194c87c5fbaSopenharmony_ci if (!output_file.s) 195c87c5fbaSopenharmony_ci (void)fwrite("\n", 1, 1, file); 196c87c5fbaSopenharmony_ci 197c87c5fbaSopenharmony_ci fflush(file); 198c87c5fbaSopenharmony_ci fclose(file); 199c87c5fbaSopenharmony_ci } 200c87c5fbaSopenharmony_ci} 201c87c5fbaSopenharmony_ci 202c87c5fbaSopenharmony_cistatic void 203c87c5fbaSopenharmony_cifree_xmit_data(coap_session_t *session COAP_UNUSED, void *app_ptr) { 204c87c5fbaSopenharmony_ci coap_free(app_ptr); 205c87c5fbaSopenharmony_ci return; 206c87c5fbaSopenharmony_ci} 207c87c5fbaSopenharmony_ci 208c87c5fbaSopenharmony_cistatic void 209c87c5fbaSopenharmony_citrack_new_token(size_t tokenlen, uint8_t *token) { 210c87c5fbaSopenharmony_ci track_token *new_list = realloc(tracked_tokens, 211c87c5fbaSopenharmony_ci (tracked_tokens_count + 1) * sizeof(tracked_tokens[0])); 212c87c5fbaSopenharmony_ci if (!new_list) { 213c87c5fbaSopenharmony_ci coap_log_info("Unable to track new token\n"); 214c87c5fbaSopenharmony_ci return; 215c87c5fbaSopenharmony_ci } 216c87c5fbaSopenharmony_ci tracked_tokens = new_list; 217c87c5fbaSopenharmony_ci tracked_tokens[tracked_tokens_count].token = coap_new_binary(tokenlen); 218c87c5fbaSopenharmony_ci if (!tracked_tokens[tracked_tokens_count].token) 219c87c5fbaSopenharmony_ci return; 220c87c5fbaSopenharmony_ci memcpy(tracked_tokens[tracked_tokens_count].token->s, token, tokenlen); 221c87c5fbaSopenharmony_ci tracked_tokens[tracked_tokens_count].observe = doing_observe; 222c87c5fbaSopenharmony_ci tracked_tokens_count++; 223c87c5fbaSopenharmony_ci} 224c87c5fbaSopenharmony_ci 225c87c5fbaSopenharmony_cistatic int 226c87c5fbaSopenharmony_citrack_check_token(coap_bin_const_t *token) { 227c87c5fbaSopenharmony_ci size_t i; 228c87c5fbaSopenharmony_ci 229c87c5fbaSopenharmony_ci for (i = 0; i < tracked_tokens_count; i++) { 230c87c5fbaSopenharmony_ci if (coap_binary_equal(token, tracked_tokens[i].token)) { 231c87c5fbaSopenharmony_ci return 1; 232c87c5fbaSopenharmony_ci } 233c87c5fbaSopenharmony_ci } 234c87c5fbaSopenharmony_ci return 0; 235c87c5fbaSopenharmony_ci} 236c87c5fbaSopenharmony_ci 237c87c5fbaSopenharmony_cistatic void 238c87c5fbaSopenharmony_citrack_flush_token(coap_bin_const_t *token, int force) { 239c87c5fbaSopenharmony_ci size_t i; 240c87c5fbaSopenharmony_ci 241c87c5fbaSopenharmony_ci for (i = 0; i < tracked_tokens_count; i++) { 242c87c5fbaSopenharmony_ci if (coap_binary_equal(token, tracked_tokens[i].token)) { 243c87c5fbaSopenharmony_ci if (force || !tracked_tokens[i].observe || !obs_started) { 244c87c5fbaSopenharmony_ci /* Only remove if not Observing */ 245c87c5fbaSopenharmony_ci coap_delete_binary(tracked_tokens[i].token); 246c87c5fbaSopenharmony_ci if (tracked_tokens_count-i > 1) { 247c87c5fbaSopenharmony_ci memmove(&tracked_tokens[i], 248c87c5fbaSopenharmony_ci &tracked_tokens[i+1], 249c87c5fbaSopenharmony_ci (tracked_tokens_count-i-1) * sizeof(tracked_tokens[0])); 250c87c5fbaSopenharmony_ci } 251c87c5fbaSopenharmony_ci tracked_tokens_count--; 252c87c5fbaSopenharmony_ci } 253c87c5fbaSopenharmony_ci break; 254c87c5fbaSopenharmony_ci } 255c87c5fbaSopenharmony_ci } 256c87c5fbaSopenharmony_ci} 257c87c5fbaSopenharmony_ci 258c87c5fbaSopenharmony_ci 259c87c5fbaSopenharmony_cistatic coap_pdu_t * 260c87c5fbaSopenharmony_cicoap_new_request(coap_context_t *ctx, 261c87c5fbaSopenharmony_ci coap_session_t *session, 262c87c5fbaSopenharmony_ci method_t m, 263c87c5fbaSopenharmony_ci coap_optlist_t **options, 264c87c5fbaSopenharmony_ci unsigned char *data, 265c87c5fbaSopenharmony_ci size_t length) { 266c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 267c87c5fbaSopenharmony_ci uint8_t token[8]; 268c87c5fbaSopenharmony_ci size_t tokenlen; 269c87c5fbaSopenharmony_ci (void)ctx; 270c87c5fbaSopenharmony_ci 271c87c5fbaSopenharmony_ci if (!(pdu = coap_new_pdu(msgtype, m, session))) { 272c87c5fbaSopenharmony_ci free_xmit_data(session, data); 273c87c5fbaSopenharmony_ci return NULL; 274c87c5fbaSopenharmony_ci } 275c87c5fbaSopenharmony_ci 276c87c5fbaSopenharmony_ci /* 277c87c5fbaSopenharmony_ci * Create unique token for this request for handling unsolicited / 278c87c5fbaSopenharmony_ci * delayed responses. 279c87c5fbaSopenharmony_ci * Note that only up to 8 bytes are returned 280c87c5fbaSopenharmony_ci */ 281c87c5fbaSopenharmony_ci if (the_token.length > COAP_TOKEN_DEFAULT_MAX) { 282c87c5fbaSopenharmony_ci coap_session_new_token(session, &tokenlen, token); 283c87c5fbaSopenharmony_ci /* Update the last part 8 bytes of the large token */ 284c87c5fbaSopenharmony_ci memcpy(&the_token.s[the_token.length - tokenlen], token, tokenlen); 285c87c5fbaSopenharmony_ci } else { 286c87c5fbaSopenharmony_ci coap_session_new_token(session, &the_token.length, the_token.s); 287c87c5fbaSopenharmony_ci } 288c87c5fbaSopenharmony_ci track_new_token(the_token.length, the_token.s); 289c87c5fbaSopenharmony_ci if (!coap_add_token(pdu, the_token.length, the_token.s)) { 290c87c5fbaSopenharmony_ci coap_log_debug("cannot add token to request\n"); 291c87c5fbaSopenharmony_ci } 292c87c5fbaSopenharmony_ci 293c87c5fbaSopenharmony_ci if (options) 294c87c5fbaSopenharmony_ci coap_add_optlist_pdu(pdu, options); 295c87c5fbaSopenharmony_ci 296c87c5fbaSopenharmony_ci if (length) { 297c87c5fbaSopenharmony_ci /* Let the underlying libcoap decide how this data should be sent */ 298c87c5fbaSopenharmony_ci coap_add_data_large_request(session, pdu, length, data, 299c87c5fbaSopenharmony_ci free_xmit_data, data); 300c87c5fbaSopenharmony_ci } 301c87c5fbaSopenharmony_ci 302c87c5fbaSopenharmony_ci return pdu; 303c87c5fbaSopenharmony_ci} 304c87c5fbaSopenharmony_ci 305c87c5fbaSopenharmony_cistatic int 306c87c5fbaSopenharmony_cievent_handler(coap_session_t *session COAP_UNUSED, 307c87c5fbaSopenharmony_ci const coap_event_t event) { 308c87c5fbaSopenharmony_ci 309c87c5fbaSopenharmony_ci switch (event) { 310c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_CLOSED: 311c87c5fbaSopenharmony_ci case COAP_EVENT_TCP_CLOSED: 312c87c5fbaSopenharmony_ci case COAP_EVENT_SESSION_CLOSED: 313c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_DECRYPTION_FAILURE: 314c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_NOT_ENABLED: 315c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD: 316c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_NO_SECURITY: 317c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_INTERNAL_ERROR: 318c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_DECODE_ERROR: 319c87c5fbaSopenharmony_ci case COAP_EVENT_WS_PACKET_SIZE: 320c87c5fbaSopenharmony_ci case COAP_EVENT_WS_CLOSED: 321c87c5fbaSopenharmony_ci quit = 1; 322c87c5fbaSopenharmony_ci break; 323c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_CONNECTED: 324c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_RENEGOTIATE: 325c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_ERROR: 326c87c5fbaSopenharmony_ci case COAP_EVENT_TCP_CONNECTED: 327c87c5fbaSopenharmony_ci case COAP_EVENT_TCP_FAILED: 328c87c5fbaSopenharmony_ci case COAP_EVENT_SESSION_CONNECTED: 329c87c5fbaSopenharmony_ci case COAP_EVENT_SESSION_FAILED: 330c87c5fbaSopenharmony_ci case COAP_EVENT_PARTIAL_BLOCK: 331c87c5fbaSopenharmony_ci case COAP_EVENT_XMIT_BLOCK_FAIL: 332c87c5fbaSopenharmony_ci case COAP_EVENT_SERVER_SESSION_NEW: 333c87c5fbaSopenharmony_ci case COAP_EVENT_SERVER_SESSION_DEL: 334c87c5fbaSopenharmony_ci case COAP_EVENT_BAD_PACKET: 335c87c5fbaSopenharmony_ci case COAP_EVENT_MSG_RETRANSMITTED: 336c87c5fbaSopenharmony_ci case COAP_EVENT_WS_CONNECTED: 337c87c5fbaSopenharmony_ci case COAP_EVENT_KEEPALIVE_FAILURE: 338c87c5fbaSopenharmony_ci default: 339c87c5fbaSopenharmony_ci break; 340c87c5fbaSopenharmony_ci } 341c87c5fbaSopenharmony_ci return 0; 342c87c5fbaSopenharmony_ci} 343c87c5fbaSopenharmony_ci 344c87c5fbaSopenharmony_cistatic void 345c87c5fbaSopenharmony_cinack_handler(coap_session_t *session COAP_UNUSED, 346c87c5fbaSopenharmony_ci const coap_pdu_t *sent, 347c87c5fbaSopenharmony_ci const coap_nack_reason_t reason, 348c87c5fbaSopenharmony_ci const coap_mid_t mid COAP_UNUSED) { 349c87c5fbaSopenharmony_ci if (sent) { 350c87c5fbaSopenharmony_ci coap_bin_const_t token = coap_pdu_get_token(sent); 351c87c5fbaSopenharmony_ci 352c87c5fbaSopenharmony_ci if (!track_check_token(&token)) { 353c87c5fbaSopenharmony_ci coap_log_err("nack_handler: Unexpected token\n"); 354c87c5fbaSopenharmony_ci } 355c87c5fbaSopenharmony_ci } 356c87c5fbaSopenharmony_ci 357c87c5fbaSopenharmony_ci switch (reason) { 358c87c5fbaSopenharmony_ci case COAP_NACK_TOO_MANY_RETRIES: 359c87c5fbaSopenharmony_ci case COAP_NACK_NOT_DELIVERABLE: 360c87c5fbaSopenharmony_ci case COAP_NACK_RST: 361c87c5fbaSopenharmony_ci case COAP_NACK_TLS_FAILED: 362c87c5fbaSopenharmony_ci case COAP_NACK_WS_FAILED: 363c87c5fbaSopenharmony_ci case COAP_NACK_TLS_LAYER_FAILED: 364c87c5fbaSopenharmony_ci case COAP_NACK_WS_LAYER_FAILED: 365c87c5fbaSopenharmony_ci coap_log_err("cannot send CoAP pdu\n"); 366c87c5fbaSopenharmony_ci quit = 1; 367c87c5fbaSopenharmony_ci break; 368c87c5fbaSopenharmony_ci case COAP_NACK_ICMP_ISSUE: 369c87c5fbaSopenharmony_ci case COAP_NACK_BAD_RESPONSE: 370c87c5fbaSopenharmony_ci default: 371c87c5fbaSopenharmony_ci ; 372c87c5fbaSopenharmony_ci } 373c87c5fbaSopenharmony_ci return; 374c87c5fbaSopenharmony_ci} 375c87c5fbaSopenharmony_ci 376c87c5fbaSopenharmony_ci/* 377c87c5fbaSopenharmony_ci * Response handler used for coap_send() responses 378c87c5fbaSopenharmony_ci */ 379c87c5fbaSopenharmony_cistatic coap_response_t 380c87c5fbaSopenharmony_cimessage_handler(coap_session_t *session COAP_UNUSED, 381c87c5fbaSopenharmony_ci const coap_pdu_t *sent, 382c87c5fbaSopenharmony_ci const coap_pdu_t *received, 383c87c5fbaSopenharmony_ci const coap_mid_t id COAP_UNUSED) { 384c87c5fbaSopenharmony_ci 385c87c5fbaSopenharmony_ci coap_opt_t *block_opt; 386c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 387c87c5fbaSopenharmony_ci size_t len; 388c87c5fbaSopenharmony_ci const uint8_t *databuf; 389c87c5fbaSopenharmony_ci size_t offset; 390c87c5fbaSopenharmony_ci size_t total; 391c87c5fbaSopenharmony_ci coap_pdu_code_t rcv_code = coap_pdu_get_code(received); 392c87c5fbaSopenharmony_ci coap_pdu_type_t rcv_type = coap_pdu_get_type(received); 393c87c5fbaSopenharmony_ci coap_bin_const_t token = coap_pdu_get_token(received); 394c87c5fbaSopenharmony_ci 395c87c5fbaSopenharmony_ci coap_log_debug("** process incoming %d.%02d response:\n", 396c87c5fbaSopenharmony_ci COAP_RESPONSE_CLASS(rcv_code), rcv_code & 0x1F); 397c87c5fbaSopenharmony_ci if (coap_get_log_level() < COAP_LOG_DEBUG) 398c87c5fbaSopenharmony_ci coap_show_pdu(COAP_LOG_INFO, received); 399c87c5fbaSopenharmony_ci 400c87c5fbaSopenharmony_ci /* check if this is a response to our original request */ 401c87c5fbaSopenharmony_ci if (!track_check_token(&token)) { 402c87c5fbaSopenharmony_ci /* drop if this was just some message, or send RST in case of notification */ 403c87c5fbaSopenharmony_ci if (!sent && (rcv_type == COAP_MESSAGE_CON || 404c87c5fbaSopenharmony_ci rcv_type == COAP_MESSAGE_NON)) { 405c87c5fbaSopenharmony_ci /* Cause a CoAP RST to be sent */ 406c87c5fbaSopenharmony_ci return COAP_RESPONSE_FAIL; 407c87c5fbaSopenharmony_ci } 408c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 409c87c5fbaSopenharmony_ci } 410c87c5fbaSopenharmony_ci 411c87c5fbaSopenharmony_ci if (rcv_type == COAP_MESSAGE_RST) { 412c87c5fbaSopenharmony_ci coap_log_info("got RST\n"); 413c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 414c87c5fbaSopenharmony_ci } 415c87c5fbaSopenharmony_ci 416c87c5fbaSopenharmony_ci /* output the received data, if any */ 417c87c5fbaSopenharmony_ci if (COAP_RESPONSE_CLASS(rcv_code) == 2) { 418c87c5fbaSopenharmony_ci 419c87c5fbaSopenharmony_ci /* set obs timer if we have successfully subscribed a resource */ 420c87c5fbaSopenharmony_ci if (doing_observe && !obs_started && 421c87c5fbaSopenharmony_ci coap_check_option(received, COAP_OPTION_OBSERVE, &opt_iter)) { 422c87c5fbaSopenharmony_ci coap_log_debug("observation relationship established, set timeout to %d\n", 423c87c5fbaSopenharmony_ci obs_seconds); 424c87c5fbaSopenharmony_ci obs_started = 1; 425c87c5fbaSopenharmony_ci obs_ms = obs_seconds * 1000; 426c87c5fbaSopenharmony_ci obs_ms_reset = 1; 427c87c5fbaSopenharmony_ci } 428c87c5fbaSopenharmony_ci 429c87c5fbaSopenharmony_ci if (coap_get_data_large(received, &len, &databuf, &offset, &total)) { 430c87c5fbaSopenharmony_ci append_to_output(databuf, len); 431c87c5fbaSopenharmony_ci if ((len + offset == total) && add_nl) 432c87c5fbaSopenharmony_ci append_to_output((const uint8_t *)"\n", 1); 433c87c5fbaSopenharmony_ci } 434c87c5fbaSopenharmony_ci 435c87c5fbaSopenharmony_ci /* Check if Block2 option is set */ 436c87c5fbaSopenharmony_ci block_opt = coap_check_option(received, COAP_OPTION_BLOCK2, &opt_iter); 437c87c5fbaSopenharmony_ci if (!single_block_requested && block_opt) { /* handle Block2 */ 438c87c5fbaSopenharmony_ci 439c87c5fbaSopenharmony_ci /* TODO: check if we are looking at the correct block number */ 440c87c5fbaSopenharmony_ci if (coap_opt_block_num(block_opt) == 0) { 441c87c5fbaSopenharmony_ci /* See if observe is set in first response */ 442c87c5fbaSopenharmony_ci ready = doing_observe ? coap_check_option(received, 443c87c5fbaSopenharmony_ci COAP_OPTION_OBSERVE, &opt_iter) == NULL : 1; 444c87c5fbaSopenharmony_ci } 445c87c5fbaSopenharmony_ci if (COAP_OPT_BLOCK_MORE(block_opt)) { 446c87c5fbaSopenharmony_ci doing_getting_block = 1; 447c87c5fbaSopenharmony_ci } else { 448c87c5fbaSopenharmony_ci doing_getting_block = 0; 449c87c5fbaSopenharmony_ci if (!is_mcast) 450c87c5fbaSopenharmony_ci track_flush_token(&token, 0); 451c87c5fbaSopenharmony_ci } 452c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 453c87c5fbaSopenharmony_ci } 454c87c5fbaSopenharmony_ci } else { /* no 2.05 */ 455c87c5fbaSopenharmony_ci /* check if an error was signaled and output payload if so */ 456c87c5fbaSopenharmony_ci if (COAP_RESPONSE_CLASS(rcv_code) >= 4) { 457c87c5fbaSopenharmony_ci fprintf(stderr, "%d.%02d", COAP_RESPONSE_CLASS(rcv_code), 458c87c5fbaSopenharmony_ci rcv_code & 0x1F); 459c87c5fbaSopenharmony_ci if (coap_get_data_large(received, &len, &databuf, &offset, &total)) { 460c87c5fbaSopenharmony_ci fprintf(stderr, " "); 461c87c5fbaSopenharmony_ci while (len--) { 462c87c5fbaSopenharmony_ci fprintf(stderr, "%c", isprint(*databuf) ? *databuf : '.'); 463c87c5fbaSopenharmony_ci databuf++; 464c87c5fbaSopenharmony_ci } 465c87c5fbaSopenharmony_ci } 466c87c5fbaSopenharmony_ci fprintf(stderr, "\n"); 467c87c5fbaSopenharmony_ci track_flush_token(&token, 1); 468c87c5fbaSopenharmony_ci } 469c87c5fbaSopenharmony_ci 470c87c5fbaSopenharmony_ci } 471c87c5fbaSopenharmony_ci if (!is_mcast) 472c87c5fbaSopenharmony_ci track_flush_token(&token, 0); 473c87c5fbaSopenharmony_ci 474c87c5fbaSopenharmony_ci /* our job is done, we can exit at any time */ 475c87c5fbaSopenharmony_ci ready = doing_observe ? coap_check_option(received, 476c87c5fbaSopenharmony_ci COAP_OPTION_OBSERVE, &opt_iter) == NULL : 1; 477c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 478c87c5fbaSopenharmony_ci} 479c87c5fbaSopenharmony_ci 480c87c5fbaSopenharmony_cistatic void 481c87c5fbaSopenharmony_ciusage(const char *program, const char *version) { 482c87c5fbaSopenharmony_ci const char *p; 483c87c5fbaSopenharmony_ci char buffer[120]; 484c87c5fbaSopenharmony_ci const char *lib_build = coap_package_build(); 485c87c5fbaSopenharmony_ci 486c87c5fbaSopenharmony_ci p = strrchr(program, '/'); 487c87c5fbaSopenharmony_ci if (p) 488c87c5fbaSopenharmony_ci program = ++p; 489c87c5fbaSopenharmony_ci 490c87c5fbaSopenharmony_ci fprintf(stderr, "%s v%s -- a small CoAP implementation\n" 491c87c5fbaSopenharmony_ci "Copyright (C) 2010-2023 Olaf Bergmann <bergmann@tzi.org> and others\n\n" 492c87c5fbaSopenharmony_ci "Build: %s\n" 493c87c5fbaSopenharmony_ci "%s\n" 494c87c5fbaSopenharmony_ci , program, version, lib_build, 495c87c5fbaSopenharmony_ci coap_string_tls_version(buffer, sizeof(buffer))); 496c87c5fbaSopenharmony_ci fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); 497c87c5fbaSopenharmony_ci fprintf(stderr, "\n" 498c87c5fbaSopenharmony_ci "Usage: %s [-a addr] [-b [num,]size] [-e text] [-f file] [-l loss]\n" 499c87c5fbaSopenharmony_ci "\t\t[-m method] [-o file] [-p port] [-r] [-s duration] [-t type]\n" 500c87c5fbaSopenharmony_ci "\t\t[-v num] [-w] [-A type] [-B seconds]\n" 501c87c5fbaSopenharmony_ci "\t\t[-E oscore_conf_file[,seq_file]] [-G count] [-H hoplimit]\n" 502c87c5fbaSopenharmony_ci "\t\t[-K interval] [-N] [-O num,text] [-P scheme://address[:port]\n" 503c87c5fbaSopenharmony_ci "\t\t[-T token] [-U] [-V num] [-X size]\n" 504c87c5fbaSopenharmony_ci "\t\t[[-h match_hint_file] [-k key] [-u user]]\n" 505c87c5fbaSopenharmony_ci "\t\t[[-c certfile] [-j keyfile] [-n] [-C cafile]\n" 506c87c5fbaSopenharmony_ci "\t\t[-J pkcs11_pin] [-M raw_pk] [-R trust_casfile]\n" 507c87c5fbaSopenharmony_ci "\t\t[-S match_pki_sni_file]] URI\n" 508c87c5fbaSopenharmony_ci "\tURI can be an absolute URI or a URI prefixed with scheme and host\n\n" 509c87c5fbaSopenharmony_ci "General Options\n" 510c87c5fbaSopenharmony_ci "\t-a addr\t\tThe local interface address to use\n" 511c87c5fbaSopenharmony_ci "\t-b [num,]size\tBlock size to be used in GET/PUT/POST requests\n" 512c87c5fbaSopenharmony_ci "\t \t\t(value must be a multiple of 16 not larger than 1024)\n" 513c87c5fbaSopenharmony_ci "\t \t\tIf num is present, the request chain will start at\n" 514c87c5fbaSopenharmony_ci "\t \t\tblock num\n" 515c87c5fbaSopenharmony_ci "\t-e text\t\tInclude text as payload (use percent-encoding for\n" 516c87c5fbaSopenharmony_ci "\t \t\tnon-ASCII characters)\n" 517c87c5fbaSopenharmony_ci "\t-f file\t\tFile to send with PUT/POST (use '-' for STDIN)\n" 518c87c5fbaSopenharmony_ci "\t-l list\t\tFail to send some datagrams specified by a comma\n" 519c87c5fbaSopenharmony_ci "\t \t\tseparated list of numbers or number ranges\n" 520c87c5fbaSopenharmony_ci "\t \t\t(for debugging only)\n" 521c87c5fbaSopenharmony_ci "\t-l loss%%\tRandomly fail to send datagrams with the specified\n" 522c87c5fbaSopenharmony_ci "\t \t\tprobability - 100%% all datagrams, 0%% no datagrams\n" 523c87c5fbaSopenharmony_ci "\t-m method\tRequest method (get|put|post|delete|fetch|patch|ipatch),\n" 524c87c5fbaSopenharmony_ci "\t \t\tdefault is 'get'\n" 525c87c5fbaSopenharmony_ci "\t-o file\t\tOutput received data to this file (use '-' for STDOUT)\n" 526c87c5fbaSopenharmony_ci "\t-p port\t\tSend from the specified port\n" 527c87c5fbaSopenharmony_ci "\t-r \t\tUse reliable protocol (TCP or TLS); requires TCP support\n" 528c87c5fbaSopenharmony_ci "\t-s duration\tSubscribe to / Observe resource for given duration\n" 529c87c5fbaSopenharmony_ci "\t \t\tin seconds\n" 530c87c5fbaSopenharmony_ci "\t-t type\t\tContent format for given resource for PUT/POST\n" 531c87c5fbaSopenharmony_ci "\t-v num \t\tVerbosity level (default 4, maximum is 8) for general\n" 532c87c5fbaSopenharmony_ci "\t \t\tCoAP logging\n" 533c87c5fbaSopenharmony_ci "\t-w \t\tAppend a newline to received data\n" 534c87c5fbaSopenharmony_ci "\t-A type\t\tAccepted media type\n" 535c87c5fbaSopenharmony_ci "\t-B seconds\tBreak operation after waiting given seconds\n" 536c87c5fbaSopenharmony_ci "\t \t\t(default is %d)\n" 537c87c5fbaSopenharmony_ci "\t-E oscore_conf_file[,seq_file]\n" 538c87c5fbaSopenharmony_ci "\t \t\toscore_conf_file contains OSCORE configuration. See\n" 539c87c5fbaSopenharmony_ci "\t \t\tcoap-oscore-conf(5) for definitions.\n" 540c87c5fbaSopenharmony_ci "\t \t\tOptional seq_file is used to save the current transmit\n" 541c87c5fbaSopenharmony_ci "\t \t\tsequence number, so on restart sequence numbers continue\n" 542c87c5fbaSopenharmony_ci "\t-G count\tRepeat the Request 'count' times with a second delay\n" 543c87c5fbaSopenharmony_ci "\t \t\tbetween each one. Must have a value between 1 and 255\n" 544c87c5fbaSopenharmony_ci "\t \t\tinclusive. Default is '1'\n" 545c87c5fbaSopenharmony_ci "\t-H hoplimit\tSet the Hop Limit count to hoplimit for proxies. Must\n" 546c87c5fbaSopenharmony_ci "\t \t\thave a value between 1 and 255 inclusive.\n" 547c87c5fbaSopenharmony_ci "\t \t\tDefault is '16'\n" 548c87c5fbaSopenharmony_ci "\t-K interval\tSend a ping after interval seconds of inactivity\n" 549c87c5fbaSopenharmony_ci "\t-L value\tSum of one or more COAP_BLOCK_* flag valuess for block\n" 550c87c5fbaSopenharmony_ci "\t \t\thandling methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP)\n" 551c87c5fbaSopenharmony_ci "\t \t\t(Sum of one or more of 1,2 and 16)\n" 552c87c5fbaSopenharmony_ci "\t-N \t\tSend NON-confirmable message\n" 553c87c5fbaSopenharmony_ci "\t-O num,text\tAdd option num with contents text to request. If the\n" 554c87c5fbaSopenharmony_ci "\t \t\ttext begins with 0x, then the hex text (two [0-9a-f] per\n" 555c87c5fbaSopenharmony_ci "\t \t\tbyte) is converted to binary data\n" 556c87c5fbaSopenharmony_ci "\t-P scheme://address[:port]\n" 557c87c5fbaSopenharmony_ci "\t \t\tScheme, address and optional port to define how to\n" 558c87c5fbaSopenharmony_ci "\t \t\tconnect to a CoAP proxy (automatically adds Proxy-Uri\n" 559c87c5fbaSopenharmony_ci "\t \t\toption to request) to forward the request to.\n" 560c87c5fbaSopenharmony_ci "\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n" 561c87c5fbaSopenharmony_ci "\t-T token\tDefine the initial starting token (up to 24 characters)\n" 562c87c5fbaSopenharmony_ci "\t-U \t\tNever include Uri-Host or Uri-Port options\n" 563c87c5fbaSopenharmony_ci "\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n" 564c87c5fbaSopenharmony_ci "\t \t\tlibrary logging\n" 565c87c5fbaSopenharmony_ci "\t-X size\t\tMaximum message size to use for TCP based connections\n" 566c87c5fbaSopenharmony_ci "\t \t\t(default is 8388864). Maximum value of 2^32 -1\n" 567c87c5fbaSopenharmony_ci ,program, wait_seconds); 568c87c5fbaSopenharmony_ci fprintf(stderr, 569c87c5fbaSopenharmony_ci "PSK Options (if supported by underlying (D)TLS library)\n" 570c87c5fbaSopenharmony_ci "\t-h match_hint_file\n" 571c87c5fbaSopenharmony_ci "\t \t\tThis is a file that contains one or more lines of\n" 572c87c5fbaSopenharmony_ci "\t \t\treceived Identity Hints to match to use different\n" 573c87c5fbaSopenharmony_ci "\t \t\tuser identity and associated pre-shared key (PSK) (comma\n" 574c87c5fbaSopenharmony_ci "\t \t\tseparated) instead of the '-k key' and '-u user'\n" 575c87c5fbaSopenharmony_ci "\t \t\toptions. E.g., per line\n" 576c87c5fbaSopenharmony_ci "\t \t\t hint_to_match,use_user,with_key\n" 577c87c5fbaSopenharmony_ci "\t \t\tNote: -k and -u still need to be defined for the default\n" 578c87c5fbaSopenharmony_ci "\t \t\tin case there is no match\n" 579c87c5fbaSopenharmony_ci "\t-k key \t\tPre-shared key for the specified user identity\n" 580c87c5fbaSopenharmony_ci "\t-u user\t\tUser identity to send for pre-shared key mode\n" 581c87c5fbaSopenharmony_ci "PKI Options (if supported by underlying (D)TLS library)\n" 582c87c5fbaSopenharmony_ci "\tNote: If any one of '-c certfile', '-j keyfile' or '-C cafile' is in\n" 583c87c5fbaSopenharmony_ci "\tPKCS11 URI naming format (pkcs11: prefix), then any remaining non\n" 584c87c5fbaSopenharmony_ci "\tPKCS11 URI file definitions have to be in DER, not PEM, format.\n" 585c87c5fbaSopenharmony_ci "\tOtherwise all of '-c certfile', '-j keyfile' or '-C cafile' are in\n" 586c87c5fbaSopenharmony_ci "\tPEM format.\n\n" 587c87c5fbaSopenharmony_ci "\t-c certfile\tPEM file or PKCS11 URI for the certificate. The private\n" 588c87c5fbaSopenharmony_ci "\t \t\tkey can also be in the PEM file, or has the same PKCS11\n" 589c87c5fbaSopenharmony_ci "\t \t\tURI. If not, the private key is defined by '-j keyfile'\n" 590c87c5fbaSopenharmony_ci "\t-j keyfile\tPEM file or PKCS11 URI for the private key for the\n" 591c87c5fbaSopenharmony_ci "\t \t\tcertificate in '-c certfile' if the parameter is\n" 592c87c5fbaSopenharmony_ci "\t \t\tdifferent from certfile in '-c certfile'\n" 593c87c5fbaSopenharmony_ci "\t-n \t\tDisable remote peer certificate checking\n" 594c87c5fbaSopenharmony_ci "\t-C cafile\tPEM file or PKCS11 URI for the CA certificate that was\n" 595c87c5fbaSopenharmony_ci "\t \t\tused to sign the server certfile. Ideally the client\n" 596c87c5fbaSopenharmony_ci "\t \t\tcertificate should be signed by the same CA so that\n" 597c87c5fbaSopenharmony_ci "\t \t\tmutual authentication can take place. The contents of\n" 598c87c5fbaSopenharmony_ci "\t \t\tcafile are added to the trusted store of root CAs.\n" 599c87c5fbaSopenharmony_ci "\t \t\tUsing the -C or -R options will trigger the\n" 600c87c5fbaSopenharmony_ci "\t \t\tvalidation of the server certificate unless overridden\n" 601c87c5fbaSopenharmony_ci "\t \t\tby the -n option\n" 602c87c5fbaSopenharmony_ci "\t-J pkcs11_pin\tThe user pin to unlock access to the PKCS11 token\n" 603c87c5fbaSopenharmony_ci "\t-M rpk_file\tRaw Public Key (RPK) PEM file or PKCS11 URI that\n" 604c87c5fbaSopenharmony_ci "\t \t\tcontains both PUBLIC KEY and PRIVATE KEY or just\n" 605c87c5fbaSopenharmony_ci "\t \t\tEC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support only).\n" 606c87c5fbaSopenharmony_ci "\t \t\t'-C cafile' or '-R trust_casfile' are not required\n" 607c87c5fbaSopenharmony_ci "\t-R trust_casfile\n" 608c87c5fbaSopenharmony_ci "\t \t\tPEM file containing the set of trusted root CAs\n" 609c87c5fbaSopenharmony_ci "\t \t\tthat are to be used to validate the server certificate.\n" 610c87c5fbaSopenharmony_ci "\t \t\tAlternatively, this can point to a directory containing\n" 611c87c5fbaSopenharmony_ci "\t \t\ta set of CA PEM files.\n" 612c87c5fbaSopenharmony_ci "\t \t\tUsing '-R trust_casfile' disables common CA mutual\n" 613c87c5fbaSopenharmony_ci "\t \t\tauthentication which can only be done by using\n" 614c87c5fbaSopenharmony_ci "\t \t\t'-C cafile'.\n" 615c87c5fbaSopenharmony_ci "\t \t\tUsing the -C or -R options will will trigger the\n" 616c87c5fbaSopenharmony_ci "\t \t\tvalidation of the server certificate unless overridden\n" 617c87c5fbaSopenharmony_ci "\t \t\tby the -n option\n" 618c87c5fbaSopenharmony_ci ); 619c87c5fbaSopenharmony_ci fprintf(stderr, 620c87c5fbaSopenharmony_ci "Examples:\n" 621c87c5fbaSopenharmony_ci "\tcoap-client -m get coap://[::1]/\n" 622c87c5fbaSopenharmony_ci "\tcoap-client -m get coap://[::1]/.well-known/core\n" 623c87c5fbaSopenharmony_ci "\tcoap-client -m get coap+tcp://[::1]/.well-known/core\n" 624c87c5fbaSopenharmony_ci "\tcoap-client -m get coap://%%2Funix%%2Fdomain%%2Fpath%%2Fdgram/.well-known/core\n" 625c87c5fbaSopenharmony_ci "\tcoap-client -m get coap+tcp://%%2Funix%%2Fdomain%%2Fpath%%2Fstream/.well-known/core\n" 626c87c5fbaSopenharmony_ci "\tcoap-client -m get coaps://[::1]/.well-known/core\n" 627c87c5fbaSopenharmony_ci "\tcoap-client -m get coaps+tcp://[::1]/.well-known/core\n" 628c87c5fbaSopenharmony_ci "\tcoap-client -m get coaps://%%2Funix%%2Fdomain%%2Fpath%%2Fdtls/.well-known/core\n" 629c87c5fbaSopenharmony_ci "\tcoap-client -m get coaps+tcp://%%2Funix%%2Fdomain%%2Fpath%%2Ftls/.well-known/core\n" 630c87c5fbaSopenharmony_ci "\tcoap-client -m get -T cafe coap://[::1]/time\n" 631c87c5fbaSopenharmony_ci "\techo -n 1000 | coap-client -m put -T cafe coap://[::1]/time -f -\n" 632c87c5fbaSopenharmony_ci ); 633c87c5fbaSopenharmony_ci} 634c87c5fbaSopenharmony_ci 635c87c5fbaSopenharmony_citypedef struct { 636c87c5fbaSopenharmony_ci unsigned char code; 637c87c5fbaSopenharmony_ci const char *media_type; 638c87c5fbaSopenharmony_ci} content_type_t; 639c87c5fbaSopenharmony_ci 640c87c5fbaSopenharmony_cistatic void 641c87c5fbaSopenharmony_cicmdline_content_type(char *arg, uint16_t key) { 642c87c5fbaSopenharmony_ci static content_type_t content_types[] = { 643c87c5fbaSopenharmony_ci { 0, "plain" }, 644c87c5fbaSopenharmony_ci { 0, "text/plain" }, 645c87c5fbaSopenharmony_ci { 40, "link" }, 646c87c5fbaSopenharmony_ci { 40, "link-format" }, 647c87c5fbaSopenharmony_ci { 40, "application/link-format" }, 648c87c5fbaSopenharmony_ci { 41, "xml" }, 649c87c5fbaSopenharmony_ci { 41, "application/xml" }, 650c87c5fbaSopenharmony_ci { 42, "binary" }, 651c87c5fbaSopenharmony_ci { 42, "octet-stream" }, 652c87c5fbaSopenharmony_ci { 42, "application/octet-stream" }, 653c87c5fbaSopenharmony_ci { 47, "exi" }, 654c87c5fbaSopenharmony_ci { 47, "application/exi" }, 655c87c5fbaSopenharmony_ci { 50, "json" }, 656c87c5fbaSopenharmony_ci { 50, "application/json" }, 657c87c5fbaSopenharmony_ci { 60, "cbor" }, 658c87c5fbaSopenharmony_ci { 60, "application/cbor" }, 659c87c5fbaSopenharmony_ci { 255, NULL } 660c87c5fbaSopenharmony_ci }; 661c87c5fbaSopenharmony_ci coap_optlist_t *node; 662c87c5fbaSopenharmony_ci unsigned char i; 663c87c5fbaSopenharmony_ci uint16_t value; 664c87c5fbaSopenharmony_ci uint8_t buf[4]; 665c87c5fbaSopenharmony_ci 666c87c5fbaSopenharmony_ci if (isdigit((int)arg[0])) { 667c87c5fbaSopenharmony_ci value = atoi(arg); 668c87c5fbaSopenharmony_ci } else { 669c87c5fbaSopenharmony_ci for (i=0; 670c87c5fbaSopenharmony_ci content_types[i].media_type && 671c87c5fbaSopenharmony_ci strncmp(arg, content_types[i].media_type, strlen(arg)) != 0 ; 672c87c5fbaSopenharmony_ci ++i) 673c87c5fbaSopenharmony_ci ; 674c87c5fbaSopenharmony_ci 675c87c5fbaSopenharmony_ci if (content_types[i].media_type) { 676c87c5fbaSopenharmony_ci value = content_types[i].code; 677c87c5fbaSopenharmony_ci } else { 678c87c5fbaSopenharmony_ci coap_log_warn("W: unknown content-format '%s'\n",arg); 679c87c5fbaSopenharmony_ci return; 680c87c5fbaSopenharmony_ci } 681c87c5fbaSopenharmony_ci } 682c87c5fbaSopenharmony_ci 683c87c5fbaSopenharmony_ci node = coap_new_optlist(key, coap_encode_var_safe(buf, sizeof(buf), value), buf); 684c87c5fbaSopenharmony_ci if (node) { 685c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, node); 686c87c5fbaSopenharmony_ci } 687c87c5fbaSopenharmony_ci} 688c87c5fbaSopenharmony_ci 689c87c5fbaSopenharmony_cistatic int 690c87c5fbaSopenharmony_cicmdline_hop_limit(char *arg) { 691c87c5fbaSopenharmony_ci coap_optlist_t *node; 692c87c5fbaSopenharmony_ci uint32_t value; 693c87c5fbaSopenharmony_ci uint8_t buf[4]; 694c87c5fbaSopenharmony_ci 695c87c5fbaSopenharmony_ci value = strtol(arg, NULL, 10); 696c87c5fbaSopenharmony_ci if (value < 1 || value > 255) { 697c87c5fbaSopenharmony_ci return 0; 698c87c5fbaSopenharmony_ci } 699c87c5fbaSopenharmony_ci node = coap_new_optlist(COAP_OPTION_HOP_LIMIT, coap_encode_var_safe(buf, sizeof(buf), value), buf); 700c87c5fbaSopenharmony_ci if (node) { 701c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, node); 702c87c5fbaSopenharmony_ci } 703c87c5fbaSopenharmony_ci return 1; 704c87c5fbaSopenharmony_ci} 705c87c5fbaSopenharmony_ci 706c87c5fbaSopenharmony_cistatic uint8_t * 707c87c5fbaSopenharmony_ciread_file_mem(const char *filename, size_t *length) { 708c87c5fbaSopenharmony_ci FILE *f; 709c87c5fbaSopenharmony_ci uint8_t *buf; 710c87c5fbaSopenharmony_ci struct stat statbuf; 711c87c5fbaSopenharmony_ci 712c87c5fbaSopenharmony_ci *length = 0; 713c87c5fbaSopenharmony_ci if (!filename || !(f = fopen(filename, "r"))) 714c87c5fbaSopenharmony_ci return NULL; 715c87c5fbaSopenharmony_ci 716c87c5fbaSopenharmony_ci if (fstat(fileno(f), &statbuf) == -1) { 717c87c5fbaSopenharmony_ci fclose(f); 718c87c5fbaSopenharmony_ci return NULL; 719c87c5fbaSopenharmony_ci } 720c87c5fbaSopenharmony_ci 721c87c5fbaSopenharmony_ci buf = coap_malloc(statbuf.st_size+1); 722c87c5fbaSopenharmony_ci if (!buf) { 723c87c5fbaSopenharmony_ci fclose(f); 724c87c5fbaSopenharmony_ci return NULL; 725c87c5fbaSopenharmony_ci } 726c87c5fbaSopenharmony_ci 727c87c5fbaSopenharmony_ci if (fread(buf, 1, statbuf.st_size, f) != (size_t)statbuf.st_size) { 728c87c5fbaSopenharmony_ci fclose(f); 729c87c5fbaSopenharmony_ci coap_free(buf); 730c87c5fbaSopenharmony_ci return NULL; 731c87c5fbaSopenharmony_ci } 732c87c5fbaSopenharmony_ci buf[statbuf.st_size] = '\000'; 733c87c5fbaSopenharmony_ci *length = (size_t)(statbuf.st_size + 1); 734c87c5fbaSopenharmony_ci fclose(f); 735c87c5fbaSopenharmony_ci return buf; 736c87c5fbaSopenharmony_ci} 737c87c5fbaSopenharmony_ci 738c87c5fbaSopenharmony_cistatic FILE *oscore_seq_num_fp = NULL; 739c87c5fbaSopenharmony_cistatic const char *oscore_conf_file = NULL; 740c87c5fbaSopenharmony_cistatic const char *oscore_seq_save_file = NULL; 741c87c5fbaSopenharmony_ci 742c87c5fbaSopenharmony_cistatic int 743c87c5fbaSopenharmony_cioscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) { 744c87c5fbaSopenharmony_ci if (oscore_seq_num_fp) { 745c87c5fbaSopenharmony_ci rewind(oscore_seq_num_fp); 746c87c5fbaSopenharmony_ci fprintf(oscore_seq_num_fp, "%" PRIu64 "\n", sender_seq_num); 747c87c5fbaSopenharmony_ci fflush(oscore_seq_num_fp); 748c87c5fbaSopenharmony_ci } 749c87c5fbaSopenharmony_ci return 1; 750c87c5fbaSopenharmony_ci} 751c87c5fbaSopenharmony_ci 752c87c5fbaSopenharmony_cistatic coap_oscore_conf_t * 753c87c5fbaSopenharmony_ciget_oscore_conf(void) { 754c87c5fbaSopenharmony_ci uint8_t *buf; 755c87c5fbaSopenharmony_ci size_t length; 756c87c5fbaSopenharmony_ci coap_str_const_t file_mem; 757c87c5fbaSopenharmony_ci uint64_t start_seq_num = 0; 758c87c5fbaSopenharmony_ci 759c87c5fbaSopenharmony_ci /* Need a rw var to free off later and file_mem.s is a const */ 760c87c5fbaSopenharmony_ci buf = read_file_mem(oscore_conf_file, &length); 761c87c5fbaSopenharmony_ci if (buf == NULL) { 762c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE configuration file error: %s\n", oscore_conf_file); 763c87c5fbaSopenharmony_ci return NULL; 764c87c5fbaSopenharmony_ci } 765c87c5fbaSopenharmony_ci file_mem.s = buf; 766c87c5fbaSopenharmony_ci file_mem.length = length; 767c87c5fbaSopenharmony_ci if (oscore_seq_save_file) { 768c87c5fbaSopenharmony_ci oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+"); 769c87c5fbaSopenharmony_ci if (oscore_seq_num_fp == NULL) { 770c87c5fbaSopenharmony_ci /* Try creating it */ 771c87c5fbaSopenharmony_ci oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+"); 772c87c5fbaSopenharmony_ci if (oscore_seq_num_fp == NULL) { 773c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE save restart info file error: %s\n", 774c87c5fbaSopenharmony_ci oscore_seq_save_file); 775c87c5fbaSopenharmony_ci return NULL; 776c87c5fbaSopenharmony_ci } 777c87c5fbaSopenharmony_ci } 778c87c5fbaSopenharmony_ci if (fscanf(oscore_seq_num_fp, "%" PRIu64, &start_seq_num) != 1) { 779c87c5fbaSopenharmony_ci /* Must be empty */ 780c87c5fbaSopenharmony_ci start_seq_num = 0; 781c87c5fbaSopenharmony_ci } 782c87c5fbaSopenharmony_ci } 783c87c5fbaSopenharmony_ci oscore_conf = coap_new_oscore_conf(file_mem, 784c87c5fbaSopenharmony_ci oscore_save_seq_num, 785c87c5fbaSopenharmony_ci NULL, start_seq_num); 786c87c5fbaSopenharmony_ci coap_free(buf); 787c87c5fbaSopenharmony_ci if (oscore_conf == NULL) { 788c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE configuration file error: %s\n", oscore_conf_file); 789c87c5fbaSopenharmony_ci return NULL; 790c87c5fbaSopenharmony_ci } 791c87c5fbaSopenharmony_ci return oscore_conf; 792c87c5fbaSopenharmony_ci} 793c87c5fbaSopenharmony_ci 794c87c5fbaSopenharmony_cistatic int 795c87c5fbaSopenharmony_cicmdline_oscore(char *arg) { 796c87c5fbaSopenharmony_ci if (coap_oscore_is_supported()) { 797c87c5fbaSopenharmony_ci char *sep = strchr(arg, ','); 798c87c5fbaSopenharmony_ci 799c87c5fbaSopenharmony_ci if (sep) 800c87c5fbaSopenharmony_ci *sep = '\000'; 801c87c5fbaSopenharmony_ci oscore_conf_file = arg; 802c87c5fbaSopenharmony_ci 803c87c5fbaSopenharmony_ci if (sep) { 804c87c5fbaSopenharmony_ci sep++; 805c87c5fbaSopenharmony_ci oscore_seq_save_file = sep; 806c87c5fbaSopenharmony_ci } 807c87c5fbaSopenharmony_ci return 1; 808c87c5fbaSopenharmony_ci } 809c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE support not enabled\n"); 810c87c5fbaSopenharmony_ci return 0; 811c87c5fbaSopenharmony_ci} 812c87c5fbaSopenharmony_ci 813c87c5fbaSopenharmony_ci/** 814c87c5fbaSopenharmony_ci * Sets global URI options according to the URI passed as @p arg. 815c87c5fbaSopenharmony_ci * This function returns 0 on success or -1 on error. 816c87c5fbaSopenharmony_ci * 817c87c5fbaSopenharmony_ci * @param arg The URI string. 818c87c5fbaSopenharmony_ci * @param create_uri_opts Flags that indicate whether Uri-Host and 819c87c5fbaSopenharmony_ci * Uri-Port should be suppressed. 820c87c5fbaSopenharmony_ci * @return 0 on success, -1 otherwise 821c87c5fbaSopenharmony_ci */ 822c87c5fbaSopenharmony_cistatic int 823c87c5fbaSopenharmony_cicmdline_uri(char *arg) { 824c87c5fbaSopenharmony_ci 825c87c5fbaSopenharmony_ci if (!proxy_scheme_option && proxy.host.length) { 826c87c5fbaSopenharmony_ci /* create Proxy-Uri from argument */ 827c87c5fbaSopenharmony_ci size_t len = strlen(arg); 828c87c5fbaSopenharmony_ci if (len > 1034) { 829c87c5fbaSopenharmony_ci coap_log_err("Absolute URI length must be <= 1034 bytes for a proxy\n"); 830c87c5fbaSopenharmony_ci return -1; 831c87c5fbaSopenharmony_ci } 832c87c5fbaSopenharmony_ci 833c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, 834c87c5fbaSopenharmony_ci coap_new_optlist(COAP_OPTION_PROXY_URI, 835c87c5fbaSopenharmony_ci len, 836c87c5fbaSopenharmony_ci (unsigned char *)arg)); 837c87c5fbaSopenharmony_ci 838c87c5fbaSopenharmony_ci } else { /* split arg into Uri-* options */ 839c87c5fbaSopenharmony_ci if (coap_split_uri((unsigned char *)arg, strlen(arg), &uri) < 0) { 840c87c5fbaSopenharmony_ci coap_log_err("invalid CoAP URI\n"); 841c87c5fbaSopenharmony_ci return -1; 842c87c5fbaSopenharmony_ci } 843c87c5fbaSopenharmony_ci 844c87c5fbaSopenharmony_ci /* Need to special case use of reliable */ 845c87c5fbaSopenharmony_ci if (uri.scheme == COAP_URI_SCHEME_COAPS && reliable) { 846c87c5fbaSopenharmony_ci if (!coap_tls_is_supported()) { 847c87c5fbaSopenharmony_ci coap_log_emerg("coaps+tcp URI scheme not supported in this version of libcoap\n"); 848c87c5fbaSopenharmony_ci return -1; 849c87c5fbaSopenharmony_ci } else { 850c87c5fbaSopenharmony_ci uri.scheme = COAP_URI_SCHEME_COAPS_TCP; 851c87c5fbaSopenharmony_ci } 852c87c5fbaSopenharmony_ci } 853c87c5fbaSopenharmony_ci 854c87c5fbaSopenharmony_ci if (uri.scheme == COAP_URI_SCHEME_COAP && reliable) { 855c87c5fbaSopenharmony_ci if (!coap_tcp_is_supported()) { 856c87c5fbaSopenharmony_ci coap_log_emerg("coap+tcp URI scheme not supported in this version of libcoap\n"); 857c87c5fbaSopenharmony_ci return -1; 858c87c5fbaSopenharmony_ci } else { 859c87c5fbaSopenharmony_ci uri.scheme = COAP_URI_SCHEME_COAP_TCP; 860c87c5fbaSopenharmony_ci } 861c87c5fbaSopenharmony_ci } 862c87c5fbaSopenharmony_ci } 863c87c5fbaSopenharmony_ci return 0; 864c87c5fbaSopenharmony_ci} 865c87c5fbaSopenharmony_ci 866c87c5fbaSopenharmony_cistatic int 867c87c5fbaSopenharmony_cicmdline_blocksize(char *arg) { 868c87c5fbaSopenharmony_ci uint16_t size; 869c87c5fbaSopenharmony_ci 870c87c5fbaSopenharmony_ciagain: 871c87c5fbaSopenharmony_ci size = 0; 872c87c5fbaSopenharmony_ci while (*arg && *arg != ',') 873c87c5fbaSopenharmony_ci size = size * 10 + (*arg++ - '0'); 874c87c5fbaSopenharmony_ci 875c87c5fbaSopenharmony_ci if (*arg == ',') { 876c87c5fbaSopenharmony_ci arg++; 877c87c5fbaSopenharmony_ci block.num = size; 878c87c5fbaSopenharmony_ci if (size != 0) { 879c87c5fbaSopenharmony_ci /* Random access selection - only handle single response */ 880c87c5fbaSopenharmony_ci single_block_requested = 1; 881c87c5fbaSopenharmony_ci } 882c87c5fbaSopenharmony_ci goto again; 883c87c5fbaSopenharmony_ci } 884c87c5fbaSopenharmony_ci 885c87c5fbaSopenharmony_ci if (size < 16) { 886c87c5fbaSopenharmony_ci coap_log_warn("Minimum block size is 16\n"); 887c87c5fbaSopenharmony_ci return 0; 888c87c5fbaSopenharmony_ci } else if (size > 1024) { 889c87c5fbaSopenharmony_ci coap_log_warn("Maximum block size is 1024\n"); 890c87c5fbaSopenharmony_ci return 0; 891c87c5fbaSopenharmony_ci } else if ((size % 16) != 0) { 892c87c5fbaSopenharmony_ci coap_log_warn("Block size %u is not a multiple of 16\n", size); 893c87c5fbaSopenharmony_ci return 0; 894c87c5fbaSopenharmony_ci } 895c87c5fbaSopenharmony_ci if (size) 896c87c5fbaSopenharmony_ci block.szx = (coap_fls(size >> 4) - 1) & 0x07; 897c87c5fbaSopenharmony_ci 898c87c5fbaSopenharmony_ci flags |= FLAGS_BLOCK; 899c87c5fbaSopenharmony_ci return 1; 900c87c5fbaSopenharmony_ci} 901c87c5fbaSopenharmony_ci 902c87c5fbaSopenharmony_ci/* Called after processing the options from the commandline to set 903c87c5fbaSopenharmony_ci * Block1, Block2, Q-Block1 or Q-Block2 depending on method. */ 904c87c5fbaSopenharmony_cistatic void 905c87c5fbaSopenharmony_ciset_blocksize(void) { 906c87c5fbaSopenharmony_ci static unsigned char buf[4]; /* hack: temporarily take encoded bytes */ 907c87c5fbaSopenharmony_ci uint16_t opt; 908c87c5fbaSopenharmony_ci unsigned int opt_length; 909c87c5fbaSopenharmony_ci 910c87c5fbaSopenharmony_ci if (method != COAP_REQUEST_DELETE) { 911c87c5fbaSopenharmony_ci if (method == COAP_REQUEST_GET || method == COAP_REQUEST_FETCH) { 912c87c5fbaSopenharmony_ci if (coap_q_block_is_supported() && block_mode & COAP_BLOCK_TRY_Q_BLOCK) 913c87c5fbaSopenharmony_ci opt = COAP_OPTION_Q_BLOCK2; 914c87c5fbaSopenharmony_ci else 915c87c5fbaSopenharmony_ci opt = COAP_OPTION_BLOCK2; 916c87c5fbaSopenharmony_ci } else { 917c87c5fbaSopenharmony_ci if (coap_q_block_is_supported() && block_mode & COAP_BLOCK_TRY_Q_BLOCK) 918c87c5fbaSopenharmony_ci opt = COAP_OPTION_Q_BLOCK1; 919c87c5fbaSopenharmony_ci else 920c87c5fbaSopenharmony_ci opt = COAP_OPTION_BLOCK1; 921c87c5fbaSopenharmony_ci } 922c87c5fbaSopenharmony_ci 923c87c5fbaSopenharmony_ci block.m = (opt == COAP_OPTION_BLOCK1 || opt == COAP_OPTION_Q_BLOCK1) && 924c87c5fbaSopenharmony_ci ((1ull << (block.szx + 4)) < payload.length); 925c87c5fbaSopenharmony_ci 926c87c5fbaSopenharmony_ci opt_length = coap_encode_var_safe(buf, sizeof(buf), 927c87c5fbaSopenharmony_ci (block.num << 4 | block.m << 3 | block.szx)); 928c87c5fbaSopenharmony_ci 929c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, coap_new_optlist(opt, opt_length, buf)); 930c87c5fbaSopenharmony_ci } 931c87c5fbaSopenharmony_ci} 932c87c5fbaSopenharmony_ci 933c87c5fbaSopenharmony_cistatic void 934c87c5fbaSopenharmony_cicmdline_subscribe(char *arg) { 935c87c5fbaSopenharmony_ci uint8_t buf[4]; 936c87c5fbaSopenharmony_ci 937c87c5fbaSopenharmony_ci obs_seconds = atoi(arg); 938c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, 939c87c5fbaSopenharmony_ci coap_new_optlist(COAP_OPTION_OBSERVE, 940c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 941c87c5fbaSopenharmony_ci COAP_OBSERVE_ESTABLISH), buf) 942c87c5fbaSopenharmony_ci ); 943c87c5fbaSopenharmony_ci doing_observe = 1; 944c87c5fbaSopenharmony_ci} 945c87c5fbaSopenharmony_ci 946c87c5fbaSopenharmony_cistatic int 947c87c5fbaSopenharmony_cicmdline_proxy(char *arg) { 948c87c5fbaSopenharmony_ci if (coap_split_uri((unsigned char *)arg, strlen(arg), &proxy) < 0 || 949c87c5fbaSopenharmony_ci proxy.path.length != 0 || proxy.query.length != 0) { 950c87c5fbaSopenharmony_ci coap_log_err("invalid CoAP Proxy definition\n"); 951c87c5fbaSopenharmony_ci return 0; 952c87c5fbaSopenharmony_ci } 953c87c5fbaSopenharmony_ci return 1; 954c87c5fbaSopenharmony_ci} 955c87c5fbaSopenharmony_ci 956c87c5fbaSopenharmony_cistatic inline void 957c87c5fbaSopenharmony_cicmdline_token(char *arg) { 958c87c5fbaSopenharmony_ci the_token.length = min(sizeof(_token_data), strlen(arg)); 959c87c5fbaSopenharmony_ci if (the_token.length > 0) { 960c87c5fbaSopenharmony_ci memcpy((char *)the_token.s, arg, the_token.length); 961c87c5fbaSopenharmony_ci } 962c87c5fbaSopenharmony_ci} 963c87c5fbaSopenharmony_ci 964c87c5fbaSopenharmony_ci/** 965c87c5fbaSopenharmony_ci * Utility function to convert a hex digit to its corresponding 966c87c5fbaSopenharmony_ci * numerical value. 967c87c5fbaSopenharmony_ci * 968c87c5fbaSopenharmony_ci * param c The hex digit to convert. Must be in [0-9A-Fa-f]. 969c87c5fbaSopenharmony_ci * 970c87c5fbaSopenharmony_ci * return The numerical representation of @p c. 971c87c5fbaSopenharmony_ci */ 972c87c5fbaSopenharmony_cistatic uint8_t 973c87c5fbaSopenharmony_cihex2char(char c) { 974c87c5fbaSopenharmony_ci assert(isxdigit(c)); 975c87c5fbaSopenharmony_ci if ('a' <= c && c <= 'f') 976c87c5fbaSopenharmony_ci return c - 'a' + 10; 977c87c5fbaSopenharmony_ci else if ('A' <= c && c <= 'F') 978c87c5fbaSopenharmony_ci return c - 'A' + 10; 979c87c5fbaSopenharmony_ci else 980c87c5fbaSopenharmony_ci return c - '0'; 981c87c5fbaSopenharmony_ci} 982c87c5fbaSopenharmony_ci 983c87c5fbaSopenharmony_ci/** 984c87c5fbaSopenharmony_ci * Converts the sequence of hex digits in src to a sequence of bytes. 985c87c5fbaSopenharmony_ci * 986c87c5fbaSopenharmony_ci * This function returns the number of bytes that have been written to 987c87c5fbaSopenharmony_ci * @p dst. 988c87c5fbaSopenharmony_ci * 989c87c5fbaSopenharmony_ci * param[in] src The null-terminated hex string to convert. 990c87c5fbaSopenharmony_ci * param[out] dst Conversion result. 991c87c5fbaSopenharmony_ci * 992c87c5fbaSopenharmony_ci * return The length of @p dst. 993c87c5fbaSopenharmony_ci */ 994c87c5fbaSopenharmony_cistatic size_t 995c87c5fbaSopenharmony_ciconvert_hex_string(const char *src, uint8_t *dst) { 996c87c5fbaSopenharmony_ci uint8_t *p = dst; 997c87c5fbaSopenharmony_ci while (isxdigit((int)src[0]) && isxdigit((int)src[1])) { 998c87c5fbaSopenharmony_ci *p++ = (hex2char(src[0]) << 4) + hex2char(src[1]); 999c87c5fbaSopenharmony_ci src += 2; 1000c87c5fbaSopenharmony_ci } 1001c87c5fbaSopenharmony_ci if (src[0] != '\0') { /* error in hex input */ 1002c87c5fbaSopenharmony_ci coap_log_warn("invalid hex string in option '%s'\n", src); 1003c87c5fbaSopenharmony_ci } 1004c87c5fbaSopenharmony_ci return p - dst; 1005c87c5fbaSopenharmony_ci} 1006c87c5fbaSopenharmony_ci 1007c87c5fbaSopenharmony_cistatic void 1008c87c5fbaSopenharmony_cicmdline_option(char *arg) { 1009c87c5fbaSopenharmony_ci unsigned int num = 0; 1010c87c5fbaSopenharmony_ci 1011c87c5fbaSopenharmony_ci while (*arg && *arg != ',') { 1012c87c5fbaSopenharmony_ci num = num * 10 + (*arg - '0'); 1013c87c5fbaSopenharmony_ci ++arg; 1014c87c5fbaSopenharmony_ci } 1015c87c5fbaSopenharmony_ci if (*arg == ',') 1016c87c5fbaSopenharmony_ci ++arg; 1017c87c5fbaSopenharmony_ci 1018c87c5fbaSopenharmony_ci /* read hex string when arg starts with "0x" */ 1019c87c5fbaSopenharmony_ci if (arg[0] == '0' && arg[1] == 'x') { 1020c87c5fbaSopenharmony_ci /* As the command line option is part of our environment we can do 1021c87c5fbaSopenharmony_ci * the conversion in place. */ 1022c87c5fbaSopenharmony_ci size_t len = convert_hex_string(arg + 2, (uint8_t *)arg); 1023c87c5fbaSopenharmony_ci 1024c87c5fbaSopenharmony_ci /* On success, 2 * len + 2 == strlen(arg) */ 1025c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, 1026c87c5fbaSopenharmony_ci coap_new_optlist(num, len, (unsigned char *)arg)); 1027c87c5fbaSopenharmony_ci } else { /* null-terminated character string */ 1028c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, 1029c87c5fbaSopenharmony_ci coap_new_optlist(num, strlen(arg), (unsigned char *)arg)); 1030c87c5fbaSopenharmony_ci } 1031c87c5fbaSopenharmony_ci if (num == COAP_OPTION_PROXY_SCHEME) { 1032c87c5fbaSopenharmony_ci proxy_scheme_option = 1; 1033c87c5fbaSopenharmony_ci if (strcasecmp(arg, "coaps+tcp") == 0) { 1034c87c5fbaSopenharmony_ci proxy.scheme = COAP_URI_SCHEME_COAPS_TCP; 1035c87c5fbaSopenharmony_ci proxy.port = COAPS_DEFAULT_PORT; 1036c87c5fbaSopenharmony_ci } else if (strcasecmp(arg, "coap+tcp") == 0) { 1037c87c5fbaSopenharmony_ci proxy.scheme = COAP_URI_SCHEME_COAP_TCP; 1038c87c5fbaSopenharmony_ci proxy.port = COAP_DEFAULT_PORT; 1039c87c5fbaSopenharmony_ci } else if (strcasecmp(arg, "coaps") == 0) { 1040c87c5fbaSopenharmony_ci proxy.scheme = COAP_URI_SCHEME_COAPS; 1041c87c5fbaSopenharmony_ci proxy.port = COAPS_DEFAULT_PORT; 1042c87c5fbaSopenharmony_ci } else if (strcasecmp(arg, "coap") == 0) { 1043c87c5fbaSopenharmony_ci proxy.scheme = COAP_URI_SCHEME_COAP; 1044c87c5fbaSopenharmony_ci proxy.port = COAP_DEFAULT_PORT; 1045c87c5fbaSopenharmony_ci } else { 1046c87c5fbaSopenharmony_ci coap_log_warn("%s is not a supported CoAP Proxy-Scheme\n", arg); 1047c87c5fbaSopenharmony_ci } 1048c87c5fbaSopenharmony_ci } 1049c87c5fbaSopenharmony_ci if (num == COAP_OPTION_URI_HOST) { 1050c87c5fbaSopenharmony_ci uri_host_option = 1; 1051c87c5fbaSopenharmony_ci } 1052c87c5fbaSopenharmony_ci} 1053c87c5fbaSopenharmony_ci 1054c87c5fbaSopenharmony_ci/** 1055c87c5fbaSopenharmony_ci * Calculates decimal value from hexadecimal ASCII character given in 1056c87c5fbaSopenharmony_ci * @p c. The caller must ensure that @p c actually represents a valid 1057c87c5fbaSopenharmony_ci * heaxdecimal character, e.g. with isxdigit(3). 1058c87c5fbaSopenharmony_ci * 1059c87c5fbaSopenharmony_ci * @hideinitializer 1060c87c5fbaSopenharmony_ci */ 1061c87c5fbaSopenharmony_ci#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) 1062c87c5fbaSopenharmony_ci 1063c87c5fbaSopenharmony_ci/** 1064c87c5fbaSopenharmony_ci * Decodes percent-encoded characters while copying the string @p seg 1065c87c5fbaSopenharmony_ci * of size @p length to @p buf. The caller of this function must 1066c87c5fbaSopenharmony_ci * ensure that the percent-encodings are correct (i.e. the character 1067c87c5fbaSopenharmony_ci * '%' is always followed by two hex digits. and that @p buf provides 1068c87c5fbaSopenharmony_ci * sufficient space to hold the result. This function is supposed to 1069c87c5fbaSopenharmony_ci * be called by make_decoded_option() only. 1070c87c5fbaSopenharmony_ci * 1071c87c5fbaSopenharmony_ci * @param seg The segment to decode and copy. 1072c87c5fbaSopenharmony_ci * @param length Length of @p seg. 1073c87c5fbaSopenharmony_ci * @param buf The result buffer. 1074c87c5fbaSopenharmony_ci */ 1075c87c5fbaSopenharmony_cistatic void 1076c87c5fbaSopenharmony_cidecode_segment(const uint8_t *seg, size_t length, unsigned char *buf) { 1077c87c5fbaSopenharmony_ci 1078c87c5fbaSopenharmony_ci while (length--) { 1079c87c5fbaSopenharmony_ci 1080c87c5fbaSopenharmony_ci if (*seg == '%') { 1081c87c5fbaSopenharmony_ci *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); 1082c87c5fbaSopenharmony_ci 1083c87c5fbaSopenharmony_ci seg += 2; 1084c87c5fbaSopenharmony_ci length -= 2; 1085c87c5fbaSopenharmony_ci } else { 1086c87c5fbaSopenharmony_ci *buf = *seg; 1087c87c5fbaSopenharmony_ci } 1088c87c5fbaSopenharmony_ci 1089c87c5fbaSopenharmony_ci ++buf; 1090c87c5fbaSopenharmony_ci ++seg; 1091c87c5fbaSopenharmony_ci } 1092c87c5fbaSopenharmony_ci} 1093c87c5fbaSopenharmony_ci 1094c87c5fbaSopenharmony_ci/** 1095c87c5fbaSopenharmony_ci * Runs through the given path (or query) segment and checks if 1096c87c5fbaSopenharmony_ci * percent-encodings are correct. This function returns @c -1 on error 1097c87c5fbaSopenharmony_ci * or the length of @p s when decoded. 1098c87c5fbaSopenharmony_ci */ 1099c87c5fbaSopenharmony_cistatic int 1100c87c5fbaSopenharmony_cicheck_segment(const uint8_t *s, size_t length) { 1101c87c5fbaSopenharmony_ci 1102c87c5fbaSopenharmony_ci int n = 0; 1103c87c5fbaSopenharmony_ci 1104c87c5fbaSopenharmony_ci while (length) { 1105c87c5fbaSopenharmony_ci if (*s == '%') { 1106c87c5fbaSopenharmony_ci if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) 1107c87c5fbaSopenharmony_ci return -1; 1108c87c5fbaSopenharmony_ci 1109c87c5fbaSopenharmony_ci s += 2; 1110c87c5fbaSopenharmony_ci length -= 2; 1111c87c5fbaSopenharmony_ci } 1112c87c5fbaSopenharmony_ci 1113c87c5fbaSopenharmony_ci ++s; 1114c87c5fbaSopenharmony_ci ++n; 1115c87c5fbaSopenharmony_ci --length; 1116c87c5fbaSopenharmony_ci } 1117c87c5fbaSopenharmony_ci 1118c87c5fbaSopenharmony_ci return n; 1119c87c5fbaSopenharmony_ci} 1120c87c5fbaSopenharmony_ci 1121c87c5fbaSopenharmony_cistatic int 1122c87c5fbaSopenharmony_cicmdline_input(char *text, coap_string_t *buf) { 1123c87c5fbaSopenharmony_ci int len; 1124c87c5fbaSopenharmony_ci len = check_segment((unsigned char *)text, strlen(text)); 1125c87c5fbaSopenharmony_ci 1126c87c5fbaSopenharmony_ci if (len < 0) 1127c87c5fbaSopenharmony_ci return 0; 1128c87c5fbaSopenharmony_ci 1129c87c5fbaSopenharmony_ci buf->s = (unsigned char *)coap_malloc(len); 1130c87c5fbaSopenharmony_ci if (!buf->s) 1131c87c5fbaSopenharmony_ci return 0; 1132c87c5fbaSopenharmony_ci 1133c87c5fbaSopenharmony_ci buf->length = len; 1134c87c5fbaSopenharmony_ci decode_segment((unsigned char *)text, strlen(text), buf->s); 1135c87c5fbaSopenharmony_ci return 1; 1136c87c5fbaSopenharmony_ci} 1137c87c5fbaSopenharmony_ci 1138c87c5fbaSopenharmony_cistatic int 1139c87c5fbaSopenharmony_cicmdline_input_from_file(char *filename, coap_string_t *buf) { 1140c87c5fbaSopenharmony_ci FILE *inputfile = NULL; 1141c87c5fbaSopenharmony_ci ssize_t len; 1142c87c5fbaSopenharmony_ci int result = 1; 1143c87c5fbaSopenharmony_ci struct stat statbuf; 1144c87c5fbaSopenharmony_ci 1145c87c5fbaSopenharmony_ci if (!filename || !buf) 1146c87c5fbaSopenharmony_ci return 0; 1147c87c5fbaSopenharmony_ci 1148c87c5fbaSopenharmony_ci if (filename[0] == '-' && !filename[1]) { /* read from stdin */ 1149c87c5fbaSopenharmony_ci buf->length = 20000; 1150c87c5fbaSopenharmony_ci buf->s = (unsigned char *)coap_malloc(buf->length); 1151c87c5fbaSopenharmony_ci if (!buf->s) 1152c87c5fbaSopenharmony_ci return 0; 1153c87c5fbaSopenharmony_ci 1154c87c5fbaSopenharmony_ci inputfile = stdin; 1155c87c5fbaSopenharmony_ci } else { 1156c87c5fbaSopenharmony_ci /* read from specified input file */ 1157c87c5fbaSopenharmony_ci inputfile = fopen(filename, "r"); 1158c87c5fbaSopenharmony_ci if (!inputfile) { 1159c87c5fbaSopenharmony_ci perror("cmdline_input_from_file: fopen"); 1160c87c5fbaSopenharmony_ci return 0; 1161c87c5fbaSopenharmony_ci } 1162c87c5fbaSopenharmony_ci 1163c87c5fbaSopenharmony_ci if (fstat(fileno(inputfile), &statbuf) < 0) { 1164c87c5fbaSopenharmony_ci perror("cmdline_input_from_file: stat"); 1165c87c5fbaSopenharmony_ci fclose(inputfile); 1166c87c5fbaSopenharmony_ci return 0; 1167c87c5fbaSopenharmony_ci } 1168c87c5fbaSopenharmony_ci 1169c87c5fbaSopenharmony_ci buf->length = statbuf.st_size; 1170c87c5fbaSopenharmony_ci buf->s = (unsigned char *)coap_malloc(buf->length); 1171c87c5fbaSopenharmony_ci if (!buf->s) { 1172c87c5fbaSopenharmony_ci fclose(inputfile); 1173c87c5fbaSopenharmony_ci return 0; 1174c87c5fbaSopenharmony_ci } 1175c87c5fbaSopenharmony_ci } 1176c87c5fbaSopenharmony_ci 1177c87c5fbaSopenharmony_ci len = fread(buf->s, 1, buf->length, inputfile); 1178c87c5fbaSopenharmony_ci 1179c87c5fbaSopenharmony_ci if (len < 0 || ((size_t)len < buf->length)) { 1180c87c5fbaSopenharmony_ci if (ferror(inputfile) != 0) { 1181c87c5fbaSopenharmony_ci perror("cmdline_input_from_file: fread"); 1182c87c5fbaSopenharmony_ci coap_free(buf->s); 1183c87c5fbaSopenharmony_ci buf->length = 0; 1184c87c5fbaSopenharmony_ci buf->s = NULL; 1185c87c5fbaSopenharmony_ci result = 0; 1186c87c5fbaSopenharmony_ci } else { 1187c87c5fbaSopenharmony_ci buf->length = len; 1188c87c5fbaSopenharmony_ci } 1189c87c5fbaSopenharmony_ci } 1190c87c5fbaSopenharmony_ci 1191c87c5fbaSopenharmony_ci if (inputfile != stdin) 1192c87c5fbaSopenharmony_ci fclose(inputfile); 1193c87c5fbaSopenharmony_ci 1194c87c5fbaSopenharmony_ci return result; 1195c87c5fbaSopenharmony_ci} 1196c87c5fbaSopenharmony_ci 1197c87c5fbaSopenharmony_cistatic method_t 1198c87c5fbaSopenharmony_cicmdline_method(char *arg) { 1199c87c5fbaSopenharmony_ci static const char *methods[] = 1200c87c5fbaSopenharmony_ci { 0, "get", "post", "put", "delete", "fetch", "patch", "ipatch", 0}; 1201c87c5fbaSopenharmony_ci unsigned char i; 1202c87c5fbaSopenharmony_ci 1203c87c5fbaSopenharmony_ci for (i=1; methods[i] && strcasecmp(arg,methods[i]) != 0 ; ++i) 1204c87c5fbaSopenharmony_ci ; 1205c87c5fbaSopenharmony_ci 1206c87c5fbaSopenharmony_ci return i; /* note that we do not prevent illegal methods */ 1207c87c5fbaSopenharmony_ci} 1208c87c5fbaSopenharmony_ci 1209c87c5fbaSopenharmony_cistatic ssize_t 1210c87c5fbaSopenharmony_cicmdline_read_user(char *arg, unsigned char **buf, size_t maxlen) { 1211c87c5fbaSopenharmony_ci size_t len = strnlen(arg, maxlen); 1212c87c5fbaSopenharmony_ci if (len) { 1213c87c5fbaSopenharmony_ci *buf = (unsigned char *)arg; 1214c87c5fbaSopenharmony_ci /* len is the size or less, so 0 terminate to maxlen */ 1215c87c5fbaSopenharmony_ci (*buf)[len] = '\000'; 1216c87c5fbaSopenharmony_ci } 1217c87c5fbaSopenharmony_ci /* 0 length Identity is valid */ 1218c87c5fbaSopenharmony_ci return len; 1219c87c5fbaSopenharmony_ci} 1220c87c5fbaSopenharmony_ci 1221c87c5fbaSopenharmony_cistatic ssize_t 1222c87c5fbaSopenharmony_cicmdline_read_key(char *arg, unsigned char **buf, size_t maxlen) { 1223c87c5fbaSopenharmony_ci size_t len = strnlen(arg, maxlen); 1224c87c5fbaSopenharmony_ci if (len) { 1225c87c5fbaSopenharmony_ci *buf = (unsigned char *)arg; 1226c87c5fbaSopenharmony_ci return len; 1227c87c5fbaSopenharmony_ci } 1228c87c5fbaSopenharmony_ci /* Need at least one byte for the pre-shared key */ 1229c87c5fbaSopenharmony_ci coap_log_crit("Invalid Pre-Shared Key specified\n"); 1230c87c5fbaSopenharmony_ci return -1; 1231c87c5fbaSopenharmony_ci} 1232c87c5fbaSopenharmony_ci 1233c87c5fbaSopenharmony_cistatic int 1234c87c5fbaSopenharmony_cicmdline_read_hint_check(const char *arg) { 1235c87c5fbaSopenharmony_ci FILE *fp = fopen(arg, "r"); 1236c87c5fbaSopenharmony_ci static char tmpbuf[256]; 1237c87c5fbaSopenharmony_ci if (fp == NULL) { 1238c87c5fbaSopenharmony_ci coap_log_err("Hint file: %s: Unable to open\n", arg); 1239c87c5fbaSopenharmony_ci return 0; 1240c87c5fbaSopenharmony_ci } 1241c87c5fbaSopenharmony_ci while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { 1242c87c5fbaSopenharmony_ci char *cp = tmpbuf; 1243c87c5fbaSopenharmony_ci char *tcp = strchr(cp, '\n'); 1244c87c5fbaSopenharmony_ci 1245c87c5fbaSopenharmony_ci if (tmpbuf[0] == '#') 1246c87c5fbaSopenharmony_ci continue; 1247c87c5fbaSopenharmony_ci if (tcp) 1248c87c5fbaSopenharmony_ci *tcp = '\000'; 1249c87c5fbaSopenharmony_ci 1250c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 1251c87c5fbaSopenharmony_ci if (tcp) { 1252c87c5fbaSopenharmony_ci ih_def_t *new_ih_list; 1253c87c5fbaSopenharmony_ci new_ih_list = realloc(valid_ihs.ih_list, 1254c87c5fbaSopenharmony_ci (valid_ihs.count + 1)*sizeof(valid_ihs.ih_list[0])); 1255c87c5fbaSopenharmony_ci if (new_ih_list == NULL) { 1256c87c5fbaSopenharmony_ci break; 1257c87c5fbaSopenharmony_ci } 1258c87c5fbaSopenharmony_ci valid_ihs.ih_list = new_ih_list; 1259c87c5fbaSopenharmony_ci valid_ihs.ih_list[valid_ihs.count].hint_match = strndup(cp, tcp-cp); 1260c87c5fbaSopenharmony_ci cp = tcp+1; 1261c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 1262c87c5fbaSopenharmony_ci if (tcp) { 1263c87c5fbaSopenharmony_ci valid_ihs.ih_list[valid_ihs.count].new_identity = 1264c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)cp, tcp-cp); 1265c87c5fbaSopenharmony_ci cp = tcp+1; 1266c87c5fbaSopenharmony_ci valid_ihs.ih_list[valid_ihs.count].new_key = 1267c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)cp, strlen(cp)); 1268c87c5fbaSopenharmony_ci valid_ihs.count++; 1269c87c5fbaSopenharmony_ci } else { 1270c87c5fbaSopenharmony_ci /* Badly formatted */ 1271c87c5fbaSopenharmony_ci free(valid_ihs.ih_list[valid_ihs.count].hint_match); 1272c87c5fbaSopenharmony_ci } 1273c87c5fbaSopenharmony_ci } 1274c87c5fbaSopenharmony_ci } 1275c87c5fbaSopenharmony_ci fclose(fp); 1276c87c5fbaSopenharmony_ci return valid_ihs.count > 0; 1277c87c5fbaSopenharmony_ci} 1278c87c5fbaSopenharmony_ci 1279c87c5fbaSopenharmony_cistatic int 1280c87c5fbaSopenharmony_civerify_cn_callback(const char *cn, 1281c87c5fbaSopenharmony_ci const uint8_t *asn1_public_cert COAP_UNUSED, 1282c87c5fbaSopenharmony_ci size_t asn1_length COAP_UNUSED, 1283c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 1284c87c5fbaSopenharmony_ci unsigned depth, 1285c87c5fbaSopenharmony_ci int validated COAP_UNUSED, 1286c87c5fbaSopenharmony_ci void *arg COAP_UNUSED) { 1287c87c5fbaSopenharmony_ci coap_log_info("CN '%s' presented by server (%s)\n", 1288c87c5fbaSopenharmony_ci cn, depth ? "CA" : "Certificate"); 1289c87c5fbaSopenharmony_ci return 1; 1290c87c5fbaSopenharmony_ci} 1291c87c5fbaSopenharmony_ci 1292c87c5fbaSopenharmony_cistatic const coap_dtls_cpsk_info_t * 1293c87c5fbaSopenharmony_civerify_ih_callback(coap_str_const_t *hint, 1294c87c5fbaSopenharmony_ci coap_session_t *c_session COAP_UNUSED, 1295c87c5fbaSopenharmony_ci void *arg) { 1296c87c5fbaSopenharmony_ci coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg; 1297c87c5fbaSopenharmony_ci char lhint[COAP_DTLS_HINT_LENGTH]; 1298c87c5fbaSopenharmony_ci static coap_dtls_cpsk_info_t psk_identity_info; 1299c87c5fbaSopenharmony_ci size_t i; 1300c87c5fbaSopenharmony_ci 1301c87c5fbaSopenharmony_ci snprintf(lhint, sizeof(lhint), "%.*s", (int)hint->length, hint->s); 1302c87c5fbaSopenharmony_ci coap_log_info("Identity Hint '%s' provided\n", lhint); 1303c87c5fbaSopenharmony_ci 1304c87c5fbaSopenharmony_ci /* Test for hint to possibly change identity + key */ 1305c87c5fbaSopenharmony_ci for (i = 0; i < valid_ihs.count; i++) { 1306c87c5fbaSopenharmony_ci if (strcmp(lhint, valid_ihs.ih_list[i].hint_match) == 0) { 1307c87c5fbaSopenharmony_ci /* Preset */ 1308c87c5fbaSopenharmony_ci psk_identity_info = *psk_info; 1309c87c5fbaSopenharmony_ci if (valid_ihs.ih_list[i].new_key) { 1310c87c5fbaSopenharmony_ci psk_identity_info.key = *valid_ihs.ih_list[i].new_key; 1311c87c5fbaSopenharmony_ci } 1312c87c5fbaSopenharmony_ci if (valid_ihs.ih_list[i].new_identity) { 1313c87c5fbaSopenharmony_ci psk_identity_info.identity = *valid_ihs.ih_list[i].new_identity; 1314c87c5fbaSopenharmony_ci } 1315c87c5fbaSopenharmony_ci coap_log_info("Switching to using '%s' identity + '%s' key\n", 1316c87c5fbaSopenharmony_ci psk_identity_info.identity.s, psk_identity_info.key.s); 1317c87c5fbaSopenharmony_ci return &psk_identity_info; 1318c87c5fbaSopenharmony_ci } 1319c87c5fbaSopenharmony_ci } 1320c87c5fbaSopenharmony_ci /* Just use the defined key for now as passed in by arg */ 1321c87c5fbaSopenharmony_ci return psk_info; 1322c87c5fbaSopenharmony_ci} 1323c87c5fbaSopenharmony_ci 1324c87c5fbaSopenharmony_cistatic coap_dtls_pki_t * 1325c87c5fbaSopenharmony_cisetup_pki(coap_context_t *ctx) { 1326c87c5fbaSopenharmony_ci static coap_dtls_pki_t dtls_pki; 1327c87c5fbaSopenharmony_ci static char client_sni[256]; 1328c87c5fbaSopenharmony_ci 1329c87c5fbaSopenharmony_ci /* If general root CAs are defined */ 1330c87c5fbaSopenharmony_ci if (root_ca_file) { 1331c87c5fbaSopenharmony_ci struct stat stbuf; 1332c87c5fbaSopenharmony_ci if ((stat(root_ca_file, &stbuf) == 0) && S_ISDIR(stbuf.st_mode)) { 1333c87c5fbaSopenharmony_ci coap_context_set_pki_root_cas(ctx, NULL, root_ca_file); 1334c87c5fbaSopenharmony_ci } else { 1335c87c5fbaSopenharmony_ci coap_context_set_pki_root_cas(ctx, root_ca_file, NULL); 1336c87c5fbaSopenharmony_ci } 1337c87c5fbaSopenharmony_ci } 1338c87c5fbaSopenharmony_ci 1339c87c5fbaSopenharmony_ci memset(client_sni, 0, sizeof(client_sni)); 1340c87c5fbaSopenharmony_ci memset(&dtls_pki, 0, sizeof(dtls_pki)); 1341c87c5fbaSopenharmony_ci dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; 1342c87c5fbaSopenharmony_ci if (ca_file || root_ca_file) { 1343c87c5fbaSopenharmony_ci /* 1344c87c5fbaSopenharmony_ci * Add in additional certificate checking. 1345c87c5fbaSopenharmony_ci * This list of enabled can be tuned for the specific 1346c87c5fbaSopenharmony_ci * requirements - see 'man coap_encryption'. 1347c87c5fbaSopenharmony_ci * 1348c87c5fbaSopenharmony_ci * Note: root_ca_file is setup separately using 1349c87c5fbaSopenharmony_ci * coap_context_set_pki_root_cas(), but this is used to define what 1350c87c5fbaSopenharmony_ci * checking actually takes place. 1351c87c5fbaSopenharmony_ci */ 1352c87c5fbaSopenharmony_ci dtls_pki.verify_peer_cert = verify_peer_cert; 1353c87c5fbaSopenharmony_ci dtls_pki.check_common_ca = !root_ca_file; 1354c87c5fbaSopenharmony_ci dtls_pki.allow_self_signed = 1; 1355c87c5fbaSopenharmony_ci dtls_pki.allow_expired_certs = 1; 1356c87c5fbaSopenharmony_ci dtls_pki.cert_chain_validation = 1; 1357c87c5fbaSopenharmony_ci dtls_pki.cert_chain_verify_depth = 2; 1358c87c5fbaSopenharmony_ci dtls_pki.check_cert_revocation = 1; 1359c87c5fbaSopenharmony_ci dtls_pki.allow_no_crl = 1; 1360c87c5fbaSopenharmony_ci dtls_pki.allow_expired_crl = 1; 1361c87c5fbaSopenharmony_ci } else if (is_rpk_not_cert) { 1362c87c5fbaSopenharmony_ci dtls_pki.verify_peer_cert = verify_peer_cert; 1363c87c5fbaSopenharmony_ci } 1364c87c5fbaSopenharmony_ci dtls_pki.is_rpk_not_cert = is_rpk_not_cert; 1365c87c5fbaSopenharmony_ci dtls_pki.validate_cn_call_back = verify_cn_callback; 1366c87c5fbaSopenharmony_ci if ((uri.host.length == 3 && memcmp(uri.host.s, "::1", 3) != 0) || 1367c87c5fbaSopenharmony_ci (uri.host.length == 9 && memcmp(uri.host.s, "127.0.0.1", 9) != 0)) 1368c87c5fbaSopenharmony_ci memcpy(client_sni, uri.host.s, min(uri.host.length, sizeof(client_sni)-1)); 1369c87c5fbaSopenharmony_ci else 1370c87c5fbaSopenharmony_ci memcpy(client_sni, "localhost", 9); 1371c87c5fbaSopenharmony_ci 1372c87c5fbaSopenharmony_ci dtls_pki.client_sni = client_sni; 1373c87c5fbaSopenharmony_ci if ((key_file && strncasecmp(key_file, "pkcs11:", 7) == 0) || 1374c87c5fbaSopenharmony_ci (cert_file && strncasecmp(cert_file, "pkcs11:", 7) == 0) || 1375c87c5fbaSopenharmony_ci (ca_file && strncasecmp(ca_file, "pkcs11:", 7) == 0)) { 1376c87c5fbaSopenharmony_ci dtls_pki.pki_key.key_type = COAP_PKI_KEY_PKCS11; 1377c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pkcs11.public_cert = cert_file; 1378c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pkcs11.private_key = key_file ? 1379c87c5fbaSopenharmony_ci key_file : cert_file; 1380c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pkcs11.ca = ca_file; 1381c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pkcs11.user_pin = pkcs11_pin; 1382c87c5fbaSopenharmony_ci } else if (!is_rpk_not_cert) { 1383c87c5fbaSopenharmony_ci dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; 1384c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem.public_cert = cert_file; 1385c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem.private_key = key_file ? key_file : cert_file; 1386c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem.ca_file = ca_file; 1387c87c5fbaSopenharmony_ci } else { 1388c87c5fbaSopenharmony_ci /* Map file into memory */ 1389c87c5fbaSopenharmony_ci if (ca_mem == 0 && cert_mem == 0 && key_mem == 0) { 1390c87c5fbaSopenharmony_ci ca_mem = read_file_mem(ca_file, &ca_mem_len); 1391c87c5fbaSopenharmony_ci cert_mem = read_file_mem(cert_file, &cert_mem_len); 1392c87c5fbaSopenharmony_ci key_mem = read_file_mem(key_file, &key_mem_len); 1393c87c5fbaSopenharmony_ci } 1394c87c5fbaSopenharmony_ci dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF; 1395c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem_buf.ca_cert = ca_mem; 1396c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem_buf.public_cert = cert_mem; 1397c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem_buf.private_key = key_mem ? key_mem : cert_mem; 1398c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem_buf.ca_cert_len = ca_mem_len; 1399c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem_buf.public_cert_len = cert_mem_len; 1400c87c5fbaSopenharmony_ci dtls_pki.pki_key.key.pem_buf.private_key_len = key_mem ? 1401c87c5fbaSopenharmony_ci key_mem_len : cert_mem_len; 1402c87c5fbaSopenharmony_ci } 1403c87c5fbaSopenharmony_ci return &dtls_pki; 1404c87c5fbaSopenharmony_ci} 1405c87c5fbaSopenharmony_ci 1406c87c5fbaSopenharmony_cistatic coap_dtls_cpsk_t * 1407c87c5fbaSopenharmony_cisetup_psk(const uint8_t *identity, 1408c87c5fbaSopenharmony_ci size_t identity_len, 1409c87c5fbaSopenharmony_ci const uint8_t *key, 1410c87c5fbaSopenharmony_ci size_t key_len) { 1411c87c5fbaSopenharmony_ci static coap_dtls_cpsk_t dtls_psk; 1412c87c5fbaSopenharmony_ci static char client_sni[256]; 1413c87c5fbaSopenharmony_ci 1414c87c5fbaSopenharmony_ci memset(client_sni, 0, sizeof(client_sni)); 1415c87c5fbaSopenharmony_ci memset(&dtls_psk, 0, sizeof(dtls_psk)); 1416c87c5fbaSopenharmony_ci dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; 1417c87c5fbaSopenharmony_ci dtls_psk.validate_ih_call_back = verify_ih_callback; 1418c87c5fbaSopenharmony_ci dtls_psk.ih_call_back_arg = &dtls_psk.psk_info; 1419c87c5fbaSopenharmony_ci if (uri.host.length) 1420c87c5fbaSopenharmony_ci memcpy(client_sni, uri.host.s, 1421c87c5fbaSopenharmony_ci min(uri.host.length, sizeof(client_sni) - 1)); 1422c87c5fbaSopenharmony_ci else 1423c87c5fbaSopenharmony_ci memcpy(client_sni, "localhost", 9); 1424c87c5fbaSopenharmony_ci dtls_psk.client_sni = client_sni; 1425c87c5fbaSopenharmony_ci dtls_psk.psk_info.identity.s = identity; 1426c87c5fbaSopenharmony_ci dtls_psk.psk_info.identity.length = identity_len; 1427c87c5fbaSopenharmony_ci dtls_psk.psk_info.key.s = key; 1428c87c5fbaSopenharmony_ci dtls_psk.psk_info.key.length = key_len; 1429c87c5fbaSopenharmony_ci return &dtls_psk; 1430c87c5fbaSopenharmony_ci} 1431c87c5fbaSopenharmony_ci 1432c87c5fbaSopenharmony_cistatic coap_session_t * 1433c87c5fbaSopenharmony_ciopen_session(coap_context_t *ctx, 1434c87c5fbaSopenharmony_ci coap_proto_t proto, 1435c87c5fbaSopenharmony_ci coap_address_t *bind_addr, 1436c87c5fbaSopenharmony_ci coap_address_t *dst, 1437c87c5fbaSopenharmony_ci const uint8_t *identity, 1438c87c5fbaSopenharmony_ci size_t identity_len, 1439c87c5fbaSopenharmony_ci const uint8_t *key, 1440c87c5fbaSopenharmony_ci size_t key_len) { 1441c87c5fbaSopenharmony_ci coap_session_t *session; 1442c87c5fbaSopenharmony_ci 1443c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS || 1444c87c5fbaSopenharmony_ci proto == COAP_PROTO_WSS) { 1445c87c5fbaSopenharmony_ci /* Encrypted session */ 1446c87c5fbaSopenharmony_ci if (root_ca_file || ca_file || cert_file) { 1447c87c5fbaSopenharmony_ci /* Setup PKI session */ 1448c87c5fbaSopenharmony_ci coap_dtls_pki_t *dtls_pki = setup_pki(ctx); 1449c87c5fbaSopenharmony_ci if (doing_oscore) { 1450c87c5fbaSopenharmony_ci session = coap_new_client_session_oscore_pki(ctx, bind_addr, dst, 1451c87c5fbaSopenharmony_ci proto, dtls_pki, 1452c87c5fbaSopenharmony_ci oscore_conf); 1453c87c5fbaSopenharmony_ci } else 1454c87c5fbaSopenharmony_ci session = coap_new_client_session_pki(ctx, bind_addr, dst, proto, 1455c87c5fbaSopenharmony_ci dtls_pki); 1456c87c5fbaSopenharmony_ci } else if (identity || key) { 1457c87c5fbaSopenharmony_ci /* Setup PSK session */ 1458c87c5fbaSopenharmony_ci coap_dtls_cpsk_t *dtls_psk = setup_psk(identity, identity_len, 1459c87c5fbaSopenharmony_ci key, key_len); 1460c87c5fbaSopenharmony_ci if (doing_oscore) { 1461c87c5fbaSopenharmony_ci session = coap_new_client_session_oscore_psk(ctx, bind_addr, dst, 1462c87c5fbaSopenharmony_ci proto, dtls_psk, 1463c87c5fbaSopenharmony_ci oscore_conf); 1464c87c5fbaSopenharmony_ci } else 1465c87c5fbaSopenharmony_ci session = coap_new_client_session_psk2(ctx, bind_addr, dst, proto, 1466c87c5fbaSopenharmony_ci dtls_psk); 1467c87c5fbaSopenharmony_ci } else { 1468c87c5fbaSopenharmony_ci /* No PKI or PSK defined, as encrypted, use PKI */ 1469c87c5fbaSopenharmony_ci coap_dtls_pki_t *dtls_pki = setup_pki(ctx); 1470c87c5fbaSopenharmony_ci if (doing_oscore) { 1471c87c5fbaSopenharmony_ci session = coap_new_client_session_oscore_pki(ctx, bind_addr, dst, 1472c87c5fbaSopenharmony_ci proto, dtls_pki, 1473c87c5fbaSopenharmony_ci oscore_conf); 1474c87c5fbaSopenharmony_ci } else 1475c87c5fbaSopenharmony_ci session = coap_new_client_session_pki(ctx, bind_addr, dst, proto, 1476c87c5fbaSopenharmony_ci dtls_pki); 1477c87c5fbaSopenharmony_ci } 1478c87c5fbaSopenharmony_ci } else { 1479c87c5fbaSopenharmony_ci /* Non-encrypted session */ 1480c87c5fbaSopenharmony_ci if (doing_oscore) { 1481c87c5fbaSopenharmony_ci session = coap_new_client_session_oscore(ctx, bind_addr, dst, proto, 1482c87c5fbaSopenharmony_ci oscore_conf); 1483c87c5fbaSopenharmony_ci } else 1484c87c5fbaSopenharmony_ci session = coap_new_client_session(ctx, bind_addr, dst, proto); 1485c87c5fbaSopenharmony_ci } 1486c87c5fbaSopenharmony_ci if (session && (proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS)) { 1487c87c5fbaSopenharmony_ci coap_ws_set_host_request(session, &uri.host); 1488c87c5fbaSopenharmony_ci } 1489c87c5fbaSopenharmony_ci return session; 1490c87c5fbaSopenharmony_ci} 1491c87c5fbaSopenharmony_ci 1492c87c5fbaSopenharmony_cistatic coap_session_t * 1493c87c5fbaSopenharmony_ciget_session(coap_context_t *ctx, 1494c87c5fbaSopenharmony_ci const char *local_addr, 1495c87c5fbaSopenharmony_ci const char *local_port, 1496c87c5fbaSopenharmony_ci coap_uri_scheme_t scheme, 1497c87c5fbaSopenharmony_ci coap_proto_t proto, 1498c87c5fbaSopenharmony_ci coap_address_t *dst, 1499c87c5fbaSopenharmony_ci const uint8_t *identity, 1500c87c5fbaSopenharmony_ci size_t identity_len, 1501c87c5fbaSopenharmony_ci const uint8_t *key, 1502c87c5fbaSopenharmony_ci size_t key_len) { 1503c87c5fbaSopenharmony_ci coap_session_t *session = NULL; 1504c87c5fbaSopenharmony_ci 1505c87c5fbaSopenharmony_ci is_mcast = coap_is_mcast(dst); 1506c87c5fbaSopenharmony_ci if (local_addr || coap_is_af_unix(dst)) { 1507c87c5fbaSopenharmony_ci if (coap_is_af_unix(dst)) { 1508c87c5fbaSopenharmony_ci coap_address_t bind_addr; 1509c87c5fbaSopenharmony_ci 1510c87c5fbaSopenharmony_ci if (local_addr) { 1511c87c5fbaSopenharmony_ci if (!coap_address_set_unix_domain(&bind_addr, 1512c87c5fbaSopenharmony_ci (const uint8_t *)local_addr, 1513c87c5fbaSopenharmony_ci strlen(local_addr))) { 1514c87c5fbaSopenharmony_ci fprintf(stderr, "coap_address_set_unix_domain: %s: failed\n", 1515c87c5fbaSopenharmony_ci local_addr); 1516c87c5fbaSopenharmony_ci return NULL; 1517c87c5fbaSopenharmony_ci } 1518c87c5fbaSopenharmony_ci } else { 1519c87c5fbaSopenharmony_ci char buf[COAP_UNIX_PATH_MAX]; 1520c87c5fbaSopenharmony_ci 1521c87c5fbaSopenharmony_ci /* Need a unique address */ 1522c87c5fbaSopenharmony_ci snprintf(buf, COAP_UNIX_PATH_MAX, 1523c87c5fbaSopenharmony_ci "/tmp/coap-client.%d", (int)getpid()); 1524c87c5fbaSopenharmony_ci if (!coap_address_set_unix_domain(&bind_addr, (const uint8_t *)buf, 1525c87c5fbaSopenharmony_ci strlen(buf))) { 1526c87c5fbaSopenharmony_ci fprintf(stderr, "coap_address_set_unix_domain: %s: failed\n", 1527c87c5fbaSopenharmony_ci buf); 1528c87c5fbaSopenharmony_ci remove(buf); 1529c87c5fbaSopenharmony_ci return NULL; 1530c87c5fbaSopenharmony_ci } 1531c87c5fbaSopenharmony_ci (void)remove(buf); 1532c87c5fbaSopenharmony_ci } 1533c87c5fbaSopenharmony_ci session = open_session(ctx, proto, &bind_addr, dst, 1534c87c5fbaSopenharmony_ci identity, identity_len, key, key_len); 1535c87c5fbaSopenharmony_ci } else { 1536c87c5fbaSopenharmony_ci coap_addr_info_t *info_list = NULL; 1537c87c5fbaSopenharmony_ci coap_addr_info_t *info; 1538c87c5fbaSopenharmony_ci coap_str_const_t local; 1539c87c5fbaSopenharmony_ci uint16_t port = local_port ? atoi(local_port) : 0; 1540c87c5fbaSopenharmony_ci 1541c87c5fbaSopenharmony_ci local.s = (const uint8_t *)local_addr; 1542c87c5fbaSopenharmony_ci local.length = strlen(local_addr); 1543c87c5fbaSopenharmony_ci /* resolve local address where data should be sent from */ 1544c87c5fbaSopenharmony_ci info_list = coap_resolve_address_info(&local, port, port, port, port, 1545c87c5fbaSopenharmony_ci AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL, 1546c87c5fbaSopenharmony_ci 1 << scheme, 1547c87c5fbaSopenharmony_ci COAP_RESOLVE_TYPE_LOCAL); 1548c87c5fbaSopenharmony_ci if (!info_list) { 1549c87c5fbaSopenharmony_ci fprintf(stderr, "coap_resolve_address_info: %s: failed\n", local_addr); 1550c87c5fbaSopenharmony_ci return NULL; 1551c87c5fbaSopenharmony_ci } 1552c87c5fbaSopenharmony_ci 1553c87c5fbaSopenharmony_ci /* iterate through results until success */ 1554c87c5fbaSopenharmony_ci for (info = info_list; info != NULL; info = info->next) { 1555c87c5fbaSopenharmony_ci session = open_session(ctx, proto, &info->addr, dst, 1556c87c5fbaSopenharmony_ci identity, identity_len, key, key_len); 1557c87c5fbaSopenharmony_ci if (session) 1558c87c5fbaSopenharmony_ci break; 1559c87c5fbaSopenharmony_ci } 1560c87c5fbaSopenharmony_ci coap_free_address_info(info_list); 1561c87c5fbaSopenharmony_ci } 1562c87c5fbaSopenharmony_ci } else if (local_port) { 1563c87c5fbaSopenharmony_ci coap_address_t bind_addr; 1564c87c5fbaSopenharmony_ci 1565c87c5fbaSopenharmony_ci coap_address_init(&bind_addr); 1566c87c5fbaSopenharmony_ci bind_addr.size = dst->size; 1567c87c5fbaSopenharmony_ci bind_addr.addr.sa.sa_family = dst->addr.sa.sa_family; 1568c87c5fbaSopenharmony_ci coap_address_set_port(&bind_addr, atoi(local_port)); 1569c87c5fbaSopenharmony_ci session = open_session(ctx, proto, &bind_addr, dst, 1570c87c5fbaSopenharmony_ci identity, identity_len, key, key_len); 1571c87c5fbaSopenharmony_ci } else { 1572c87c5fbaSopenharmony_ci session = open_session(ctx, proto, NULL, dst, 1573c87c5fbaSopenharmony_ci identity, identity_len, key, key_len); 1574c87c5fbaSopenharmony_ci } 1575c87c5fbaSopenharmony_ci return session; 1576c87c5fbaSopenharmony_ci} 1577c87c5fbaSopenharmony_ci 1578c87c5fbaSopenharmony_ciint 1579c87c5fbaSopenharmony_cimain(int argc, char **argv) { 1580c87c5fbaSopenharmony_ci coap_context_t *ctx = NULL; 1581c87c5fbaSopenharmony_ci coap_session_t *session = NULL; 1582c87c5fbaSopenharmony_ci coap_address_t dst; 1583c87c5fbaSopenharmony_ci int result = -1; 1584c87c5fbaSopenharmony_ci int exit_code = 0; 1585c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 1586c87c5fbaSopenharmony_ci static coap_str_const_t server; 1587c87c5fbaSopenharmony_ci uint16_t port = COAP_DEFAULT_PORT; 1588c87c5fbaSopenharmony_ci char port_str[NI_MAXSERV] = ""; 1589c87c5fbaSopenharmony_ci char node_str[NI_MAXHOST] = ""; 1590c87c5fbaSopenharmony_ci int opt; 1591c87c5fbaSopenharmony_ci coap_log_t log_level = COAP_LOG_WARN; 1592c87c5fbaSopenharmony_ci coap_log_t dtls_log_level = COAP_LOG_ERR; 1593c87c5fbaSopenharmony_ci unsigned char *user = NULL, *key = NULL; 1594c87c5fbaSopenharmony_ci ssize_t user_length = -1, key_length = 0; 1595c87c5fbaSopenharmony_ci int create_uri_opts = 1; 1596c87c5fbaSopenharmony_ci size_t i; 1597c87c5fbaSopenharmony_ci coap_uri_scheme_t scheme; 1598c87c5fbaSopenharmony_ci coap_proto_t proto; 1599c87c5fbaSopenharmony_ci uint32_t repeat_ms = REPEAT_DELAY_MS; 1600c87c5fbaSopenharmony_ci uint8_t *data = NULL; 1601c87c5fbaSopenharmony_ci size_t data_len = 0; 1602c87c5fbaSopenharmony_ci coap_addr_info_t *info_list = NULL; 1603c87c5fbaSopenharmony_ci#define BUFSIZE 100 1604c87c5fbaSopenharmony_ci static unsigned char buf[BUFSIZE]; 1605c87c5fbaSopenharmony_ci#ifndef _WIN32 1606c87c5fbaSopenharmony_ci struct sigaction sa; 1607c87c5fbaSopenharmony_ci#endif 1608c87c5fbaSopenharmony_ci 1609c87c5fbaSopenharmony_ci /* Initialize libcoap library */ 1610c87c5fbaSopenharmony_ci coap_startup(); 1611c87c5fbaSopenharmony_ci 1612c87c5fbaSopenharmony_ci while ((opt = getopt(argc, argv, 1613c87c5fbaSopenharmony_ci "a:b:c:e:f:h:j:k:l:m:no:p:rs:t:u:v:wA:B:C:E:G:H:J:K:L:M:NO:P:R:T:UV:X:")) != -1) { 1614c87c5fbaSopenharmony_ci switch (opt) { 1615c87c5fbaSopenharmony_ci case 'a': 1616c87c5fbaSopenharmony_ci strncpy(node_str, optarg, NI_MAXHOST - 1); 1617c87c5fbaSopenharmony_ci node_str[NI_MAXHOST - 1] = '\0'; 1618c87c5fbaSopenharmony_ci break; 1619c87c5fbaSopenharmony_ci case 'b': 1620c87c5fbaSopenharmony_ci cmdline_blocksize(optarg); 1621c87c5fbaSopenharmony_ci break; 1622c87c5fbaSopenharmony_ci case 'B': 1623c87c5fbaSopenharmony_ci wait_seconds = atoi(optarg); 1624c87c5fbaSopenharmony_ci break; 1625c87c5fbaSopenharmony_ci case 'c': 1626c87c5fbaSopenharmony_ci cert_file = optarg; 1627c87c5fbaSopenharmony_ci break; 1628c87c5fbaSopenharmony_ci case 'C': 1629c87c5fbaSopenharmony_ci ca_file = optarg; 1630c87c5fbaSopenharmony_ci break; 1631c87c5fbaSopenharmony_ci case 'R': 1632c87c5fbaSopenharmony_ci root_ca_file = optarg; 1633c87c5fbaSopenharmony_ci break; 1634c87c5fbaSopenharmony_ci case 'e': 1635c87c5fbaSopenharmony_ci if (!cmdline_input(optarg, &payload)) 1636c87c5fbaSopenharmony_ci payload.length = 0; 1637c87c5fbaSopenharmony_ci break; 1638c87c5fbaSopenharmony_ci case 'f': 1639c87c5fbaSopenharmony_ci if (!cmdline_input_from_file(optarg, &payload)) 1640c87c5fbaSopenharmony_ci payload.length = 0; 1641c87c5fbaSopenharmony_ci break; 1642c87c5fbaSopenharmony_ci case 'j' : 1643c87c5fbaSopenharmony_ci key_file = optarg; 1644c87c5fbaSopenharmony_ci break; 1645c87c5fbaSopenharmony_ci case 'J' : 1646c87c5fbaSopenharmony_ci pkcs11_pin = optarg; 1647c87c5fbaSopenharmony_ci break; 1648c87c5fbaSopenharmony_ci case 'k': 1649c87c5fbaSopenharmony_ci key_length = cmdline_read_key(optarg, &key, MAX_KEY); 1650c87c5fbaSopenharmony_ci break; 1651c87c5fbaSopenharmony_ci case 'L': 1652c87c5fbaSopenharmony_ci block_mode = strtoul(optarg, NULL, 0); 1653c87c5fbaSopenharmony_ci if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) { 1654c87c5fbaSopenharmony_ci fprintf(stderr, "Block mode must include COAP_BLOCK_USE_LIBCOAP (1)\n"); 1655c87c5fbaSopenharmony_ci goto failed; 1656c87c5fbaSopenharmony_ci } 1657c87c5fbaSopenharmony_ci break; 1658c87c5fbaSopenharmony_ci case 'p': 1659c87c5fbaSopenharmony_ci strncpy(port_str, optarg, NI_MAXSERV - 1); 1660c87c5fbaSopenharmony_ci port_str[NI_MAXSERV - 1] = '\0'; 1661c87c5fbaSopenharmony_ci break; 1662c87c5fbaSopenharmony_ci case 'm': 1663c87c5fbaSopenharmony_ci method = cmdline_method(optarg); 1664c87c5fbaSopenharmony_ci break; 1665c87c5fbaSopenharmony_ci case 'w': 1666c87c5fbaSopenharmony_ci add_nl = 1; 1667c87c5fbaSopenharmony_ci break; 1668c87c5fbaSopenharmony_ci case 'N': 1669c87c5fbaSopenharmony_ci msgtype = COAP_MESSAGE_NON; 1670c87c5fbaSopenharmony_ci break; 1671c87c5fbaSopenharmony_ci case 's': 1672c87c5fbaSopenharmony_ci cmdline_subscribe(optarg); 1673c87c5fbaSopenharmony_ci break; 1674c87c5fbaSopenharmony_ci case 'o': 1675c87c5fbaSopenharmony_ci output_file.length = strlen(optarg); 1676c87c5fbaSopenharmony_ci output_file.s = (unsigned char *)coap_malloc(output_file.length + 1); 1677c87c5fbaSopenharmony_ci 1678c87c5fbaSopenharmony_ci if (!output_file.s) { 1679c87c5fbaSopenharmony_ci fprintf(stderr, "cannot set output file: insufficient memory\n"); 1680c87c5fbaSopenharmony_ci goto failed; 1681c87c5fbaSopenharmony_ci } else { 1682c87c5fbaSopenharmony_ci /* copy filename including trailing zero */ 1683c87c5fbaSopenharmony_ci memcpy(output_file.s, optarg, output_file.length + 1); 1684c87c5fbaSopenharmony_ci } 1685c87c5fbaSopenharmony_ci break; 1686c87c5fbaSopenharmony_ci case 'A': 1687c87c5fbaSopenharmony_ci cmdline_content_type(optarg, COAP_OPTION_ACCEPT); 1688c87c5fbaSopenharmony_ci break; 1689c87c5fbaSopenharmony_ci case 't': 1690c87c5fbaSopenharmony_ci cmdline_content_type(optarg, COAP_OPTION_CONTENT_TYPE); 1691c87c5fbaSopenharmony_ci break; 1692c87c5fbaSopenharmony_ci case 'M': 1693c87c5fbaSopenharmony_ci cert_file = optarg; 1694c87c5fbaSopenharmony_ci is_rpk_not_cert = 1; 1695c87c5fbaSopenharmony_ci break; 1696c87c5fbaSopenharmony_ci case 'O': 1697c87c5fbaSopenharmony_ci cmdline_option(optarg); 1698c87c5fbaSopenharmony_ci break; 1699c87c5fbaSopenharmony_ci case 'P': 1700c87c5fbaSopenharmony_ci if (!cmdline_proxy(optarg)) { 1701c87c5fbaSopenharmony_ci fprintf(stderr, "error specifying proxy address\n"); 1702c87c5fbaSopenharmony_ci goto failed; 1703c87c5fbaSopenharmony_ci } 1704c87c5fbaSopenharmony_ci break; 1705c87c5fbaSopenharmony_ci case 'T': 1706c87c5fbaSopenharmony_ci cmdline_token(optarg); 1707c87c5fbaSopenharmony_ci break; 1708c87c5fbaSopenharmony_ci case 'u': 1709c87c5fbaSopenharmony_ci user_length = cmdline_read_user(optarg, &user, MAX_USER); 1710c87c5fbaSopenharmony_ci break; 1711c87c5fbaSopenharmony_ci case 'U': 1712c87c5fbaSopenharmony_ci create_uri_opts = 0; 1713c87c5fbaSopenharmony_ci break; 1714c87c5fbaSopenharmony_ci case 'v': 1715c87c5fbaSopenharmony_ci log_level = strtol(optarg, NULL, 10); 1716c87c5fbaSopenharmony_ci break; 1717c87c5fbaSopenharmony_ci case 'V': 1718c87c5fbaSopenharmony_ci dtls_log_level = strtol(optarg, NULL, 10); 1719c87c5fbaSopenharmony_ci break; 1720c87c5fbaSopenharmony_ci case 'l': 1721c87c5fbaSopenharmony_ci if (!coap_debug_set_packet_loss(optarg)) { 1722c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 1723c87c5fbaSopenharmony_ci goto failed; 1724c87c5fbaSopenharmony_ci } 1725c87c5fbaSopenharmony_ci break; 1726c87c5fbaSopenharmony_ci case 'r': 1727c87c5fbaSopenharmony_ci reliable = coap_tcp_is_supported(); 1728c87c5fbaSopenharmony_ci break; 1729c87c5fbaSopenharmony_ci case 'K': 1730c87c5fbaSopenharmony_ci ping_seconds = atoi(optarg); 1731c87c5fbaSopenharmony_ci break; 1732c87c5fbaSopenharmony_ci case 'h': 1733c87c5fbaSopenharmony_ci if (!cmdline_read_hint_check(optarg)) { 1734c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 1735c87c5fbaSopenharmony_ci goto failed; 1736c87c5fbaSopenharmony_ci } 1737c87c5fbaSopenharmony_ci break; 1738c87c5fbaSopenharmony_ci case 'H': 1739c87c5fbaSopenharmony_ci if (!cmdline_hop_limit(optarg)) 1740c87c5fbaSopenharmony_ci fprintf(stderr, "Hop Limit has to be > 0 and < 256\n"); 1741c87c5fbaSopenharmony_ci break; 1742c87c5fbaSopenharmony_ci case 'n': 1743c87c5fbaSopenharmony_ci verify_peer_cert = 0; 1744c87c5fbaSopenharmony_ci break; 1745c87c5fbaSopenharmony_ci case 'G': 1746c87c5fbaSopenharmony_ci repeat_count = atoi(optarg); 1747c87c5fbaSopenharmony_ci if (!repeat_count || repeat_count > 255) { 1748c87c5fbaSopenharmony_ci fprintf(stderr, "'-G count' has to be > 0 and < 256\n"); 1749c87c5fbaSopenharmony_ci repeat_count = 1; 1750c87c5fbaSopenharmony_ci } 1751c87c5fbaSopenharmony_ci break; 1752c87c5fbaSopenharmony_ci case 'X': 1753c87c5fbaSopenharmony_ci csm_max_message_size = strtol(optarg, NULL, 10); 1754c87c5fbaSopenharmony_ci break; 1755c87c5fbaSopenharmony_ci case 'E': 1756c87c5fbaSopenharmony_ci doing_oscore = cmdline_oscore(optarg); 1757c87c5fbaSopenharmony_ci if (!doing_oscore) { 1758c87c5fbaSopenharmony_ci goto failed; 1759c87c5fbaSopenharmony_ci } 1760c87c5fbaSopenharmony_ci break; 1761c87c5fbaSopenharmony_ci default: 1762c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 1763c87c5fbaSopenharmony_ci goto failed; 1764c87c5fbaSopenharmony_ci } 1765c87c5fbaSopenharmony_ci } 1766c87c5fbaSopenharmony_ci 1767c87c5fbaSopenharmony_ci#ifdef _WIN32 1768c87c5fbaSopenharmony_ci signal(SIGINT, handle_sigint); 1769c87c5fbaSopenharmony_ci#else 1770c87c5fbaSopenharmony_ci memset(&sa, 0, sizeof(sa)); 1771c87c5fbaSopenharmony_ci sigemptyset(&sa.sa_mask); 1772c87c5fbaSopenharmony_ci sa.sa_handler = handle_sigint; 1773c87c5fbaSopenharmony_ci sa.sa_flags = 0; 1774c87c5fbaSopenharmony_ci sigaction(SIGINT, &sa, NULL); 1775c87c5fbaSopenharmony_ci sigaction(SIGTERM, &sa, NULL); 1776c87c5fbaSopenharmony_ci /* So we do not exit on a SIGPIPE */ 1777c87c5fbaSopenharmony_ci sa.sa_handler = SIG_IGN; 1778c87c5fbaSopenharmony_ci sigaction(SIGPIPE, &sa, NULL); 1779c87c5fbaSopenharmony_ci#endif 1780c87c5fbaSopenharmony_ci 1781c87c5fbaSopenharmony_ci coap_set_log_level(log_level); 1782c87c5fbaSopenharmony_ci coap_dtls_set_log_level(dtls_log_level); 1783c87c5fbaSopenharmony_ci 1784c87c5fbaSopenharmony_ci if (optind < argc) { 1785c87c5fbaSopenharmony_ci if (cmdline_uri(argv[optind]) < 0) { 1786c87c5fbaSopenharmony_ci goto failed; 1787c87c5fbaSopenharmony_ci } 1788c87c5fbaSopenharmony_ci } else { 1789c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 1790c87c5fbaSopenharmony_ci goto failed; 1791c87c5fbaSopenharmony_ci } 1792c87c5fbaSopenharmony_ci 1793c87c5fbaSopenharmony_ci if (key_length < 0) { 1794c87c5fbaSopenharmony_ci coap_log_crit("Invalid pre-shared key specified\n"); 1795c87c5fbaSopenharmony_ci goto failed; 1796c87c5fbaSopenharmony_ci } 1797c87c5fbaSopenharmony_ci 1798c87c5fbaSopenharmony_ci if (proxy.host.length) { 1799c87c5fbaSopenharmony_ci server = proxy.host; 1800c87c5fbaSopenharmony_ci port = proxy.port; 1801c87c5fbaSopenharmony_ci scheme = proxy.scheme; 1802c87c5fbaSopenharmony_ci } else { 1803c87c5fbaSopenharmony_ci server = uri.host; 1804c87c5fbaSopenharmony_ci port = proxy_scheme_option ? proxy.port : uri.port; 1805c87c5fbaSopenharmony_ci scheme = proxy_scheme_option ? proxy.scheme : uri.scheme; 1806c87c5fbaSopenharmony_ci } 1807c87c5fbaSopenharmony_ci 1808c87c5fbaSopenharmony_ci /* resolve destination address where data should be sent */ 1809c87c5fbaSopenharmony_ci info_list = coap_resolve_address_info(&server, port, port, port, port, 1810c87c5fbaSopenharmony_ci 0, 1811c87c5fbaSopenharmony_ci 1 << scheme, 1812c87c5fbaSopenharmony_ci COAP_RESOLVE_TYPE_REMOTE); 1813c87c5fbaSopenharmony_ci 1814c87c5fbaSopenharmony_ci if (info_list == NULL) { 1815c87c5fbaSopenharmony_ci coap_log_err("failed to resolve address\n"); 1816c87c5fbaSopenharmony_ci goto failed; 1817c87c5fbaSopenharmony_ci } 1818c87c5fbaSopenharmony_ci proto = info_list->proto; 1819c87c5fbaSopenharmony_ci memcpy(&dst, &info_list->addr, sizeof(dst)); 1820c87c5fbaSopenharmony_ci coap_free_address_info(info_list); 1821c87c5fbaSopenharmony_ci 1822c87c5fbaSopenharmony_ci ctx = coap_new_context(NULL); 1823c87c5fbaSopenharmony_ci if (!ctx) { 1824c87c5fbaSopenharmony_ci coap_log_emerg("cannot create context\n"); 1825c87c5fbaSopenharmony_ci goto failed; 1826c87c5fbaSopenharmony_ci } 1827c87c5fbaSopenharmony_ci 1828c87c5fbaSopenharmony_ci if (doing_oscore) { 1829c87c5fbaSopenharmony_ci if (get_oscore_conf() == NULL) 1830c87c5fbaSopenharmony_ci goto failed; 1831c87c5fbaSopenharmony_ci } 1832c87c5fbaSopenharmony_ci 1833c87c5fbaSopenharmony_ci coap_context_set_keepalive(ctx, ping_seconds); 1834c87c5fbaSopenharmony_ci coap_context_set_block_mode(ctx, block_mode); 1835c87c5fbaSopenharmony_ci if (csm_max_message_size) 1836c87c5fbaSopenharmony_ci coap_context_set_csm_max_message_size(ctx, csm_max_message_size); 1837c87c5fbaSopenharmony_ci coap_register_response_handler(ctx, message_handler); 1838c87c5fbaSopenharmony_ci coap_register_event_handler(ctx, event_handler); 1839c87c5fbaSopenharmony_ci coap_register_nack_handler(ctx, nack_handler); 1840c87c5fbaSopenharmony_ci if (the_token.length > COAP_TOKEN_DEFAULT_MAX) 1841c87c5fbaSopenharmony_ci coap_context_set_max_token_size(ctx, the_token.length); 1842c87c5fbaSopenharmony_ci 1843c87c5fbaSopenharmony_ci session = get_session(ctx, 1844c87c5fbaSopenharmony_ci node_str[0] ? node_str : NULL, 1845c87c5fbaSopenharmony_ci port_str[0] ? port_str : NULL, 1846c87c5fbaSopenharmony_ci scheme, 1847c87c5fbaSopenharmony_ci proto, 1848c87c5fbaSopenharmony_ci &dst, 1849c87c5fbaSopenharmony_ci user_length >= 0 ? user : NULL, 1850c87c5fbaSopenharmony_ci user_length >= 0 ? user_length : 0, 1851c87c5fbaSopenharmony_ci key_length > 0 ? key : NULL, 1852c87c5fbaSopenharmony_ci key_length > 0 ? key_length : 0 1853c87c5fbaSopenharmony_ci ); 1854c87c5fbaSopenharmony_ci 1855c87c5fbaSopenharmony_ci if (!session) { 1856c87c5fbaSopenharmony_ci coap_log_err("cannot create client session\n"); 1857c87c5fbaSopenharmony_ci goto failed; 1858c87c5fbaSopenharmony_ci } 1859c87c5fbaSopenharmony_ci /* 1860c87c5fbaSopenharmony_ci * Prime the base token value, which coap_session_new_token() will increment 1861c87c5fbaSopenharmony_ci * every time it is called to get an unique token. 1862c87c5fbaSopenharmony_ci * [Option '-T token' is used to seed a different value] 1863c87c5fbaSopenharmony_ci * Note that only the first 8 bytes of the token are used as the prime. 1864c87c5fbaSopenharmony_ci */ 1865c87c5fbaSopenharmony_ci coap_session_init_token(session, the_token.length, the_token.s); 1866c87c5fbaSopenharmony_ci 1867c87c5fbaSopenharmony_ci /* Convert provided uri into CoAP options */ 1868c87c5fbaSopenharmony_ci if (coap_uri_into_options(&uri, !uri_host_option && !proxy.host.length ? 1869c87c5fbaSopenharmony_ci &dst : NULL, 1870c87c5fbaSopenharmony_ci &optlist, create_uri_opts, 1871c87c5fbaSopenharmony_ci buf, sizeof(buf)) < 0) { 1872c87c5fbaSopenharmony_ci coap_log_err("Failed to create options for URI\n"); 1873c87c5fbaSopenharmony_ci goto failed; 1874c87c5fbaSopenharmony_ci } 1875c87c5fbaSopenharmony_ci 1876c87c5fbaSopenharmony_ci /* set block option if requested at commandline */ 1877c87c5fbaSopenharmony_ci if (flags & FLAGS_BLOCK) 1878c87c5fbaSopenharmony_ci set_blocksize(); 1879c87c5fbaSopenharmony_ci 1880c87c5fbaSopenharmony_ci /* Send the first (and may be only PDU) */ 1881c87c5fbaSopenharmony_ci if (payload.length) { 1882c87c5fbaSopenharmony_ci /* Create some new data to use for this iteration */ 1883c87c5fbaSopenharmony_ci data = coap_malloc(payload.length); 1884c87c5fbaSopenharmony_ci if (data == NULL) 1885c87c5fbaSopenharmony_ci goto failed; 1886c87c5fbaSopenharmony_ci memcpy(data, payload.s, payload.length); 1887c87c5fbaSopenharmony_ci data_len = payload.length; 1888c87c5fbaSopenharmony_ci } 1889c87c5fbaSopenharmony_ci if (!(pdu = coap_new_request(ctx, session, method, &optlist, data, 1890c87c5fbaSopenharmony_ci data_len))) { 1891c87c5fbaSopenharmony_ci goto failed; 1892c87c5fbaSopenharmony_ci } 1893c87c5fbaSopenharmony_ci 1894c87c5fbaSopenharmony_ci if (is_mcast && wait_seconds == DEFAULT_WAIT_TIME) 1895c87c5fbaSopenharmony_ci /* Allow for other servers to respond within DEFAULT_LEISURE RFC7252 8.2 */ 1896c87c5fbaSopenharmony_ci wait_seconds = coap_session_get_default_leisure(session).integer_part + 1; 1897c87c5fbaSopenharmony_ci 1898c87c5fbaSopenharmony_ci wait_ms = wait_seconds * 1000; 1899c87c5fbaSopenharmony_ci coap_log_debug("timeout is set to %u seconds\n", wait_seconds); 1900c87c5fbaSopenharmony_ci 1901c87c5fbaSopenharmony_ci coap_log_debug("sending CoAP request:\n"); 1902c87c5fbaSopenharmony_ci if (coap_get_log_level() < COAP_LOG_DEBUG) 1903c87c5fbaSopenharmony_ci coap_show_pdu(COAP_LOG_INFO, pdu); 1904c87c5fbaSopenharmony_ci 1905c87c5fbaSopenharmony_ci if (coap_send(session, pdu) == COAP_INVALID_MID) { 1906c87c5fbaSopenharmony_ci coap_log_err("cannot send CoAP pdu\n"); 1907c87c5fbaSopenharmony_ci quit = 1; 1908c87c5fbaSopenharmony_ci } 1909c87c5fbaSopenharmony_ci repeat_count--; 1910c87c5fbaSopenharmony_ci 1911c87c5fbaSopenharmony_ci while (!quit && /* immediate quit not required .. and .. */ 1912c87c5fbaSopenharmony_ci (tracked_tokens_count || /* token not responded to or still observe */ 1913c87c5fbaSopenharmony_ci is_mcast || /* mcast active */ 1914c87c5fbaSopenharmony_ci repeat_count || /* more repeat transmissions to go */ 1915c87c5fbaSopenharmony_ci coap_io_pending(ctx))) { /* i/o not yet complete */ 1916c87c5fbaSopenharmony_ci uint32_t timeout_ms; 1917c87c5fbaSopenharmony_ci /* 1918c87c5fbaSopenharmony_ci * 3 factors determine how long to wait in coap_io_process() 1919c87c5fbaSopenharmony_ci * Remaining overall wait time (wait_ms) 1920c87c5fbaSopenharmony_ci * Remaining overall observe unsolicited response time (obs_ms) 1921c87c5fbaSopenharmony_ci * Delay of up to one second before sending off the next request 1922c87c5fbaSopenharmony_ci */ 1923c87c5fbaSopenharmony_ci if (obs_ms) { 1924c87c5fbaSopenharmony_ci timeout_ms = min(wait_ms, obs_ms); 1925c87c5fbaSopenharmony_ci } else { 1926c87c5fbaSopenharmony_ci timeout_ms = wait_ms; 1927c87c5fbaSopenharmony_ci } 1928c87c5fbaSopenharmony_ci if (repeat_count) { 1929c87c5fbaSopenharmony_ci timeout_ms = min(timeout_ms, repeat_ms); 1930c87c5fbaSopenharmony_ci } 1931c87c5fbaSopenharmony_ci 1932c87c5fbaSopenharmony_ci result = coap_io_process(ctx, timeout_ms); 1933c87c5fbaSopenharmony_ci 1934c87c5fbaSopenharmony_ci if (result >= 0) { 1935c87c5fbaSopenharmony_ci if (wait_ms > 0) { 1936c87c5fbaSopenharmony_ci if ((unsigned)result >= wait_ms) { 1937c87c5fbaSopenharmony_ci coap_log_info("timeout\n"); 1938c87c5fbaSopenharmony_ci break; 1939c87c5fbaSopenharmony_ci } else { 1940c87c5fbaSopenharmony_ci wait_ms -= result; 1941c87c5fbaSopenharmony_ci } 1942c87c5fbaSopenharmony_ci } 1943c87c5fbaSopenharmony_ci if (obs_ms > 0 && !obs_ms_reset) { 1944c87c5fbaSopenharmony_ci if ((unsigned)result >= obs_ms) { 1945c87c5fbaSopenharmony_ci coap_log_debug("clear observation relationship\n"); 1946c87c5fbaSopenharmony_ci for (i = 0; i < tracked_tokens_count; i++) { 1947c87c5fbaSopenharmony_ci if (tracked_tokens[i].observe) { 1948c87c5fbaSopenharmony_ci coap_cancel_observe(session, tracked_tokens[i].token, msgtype); 1949c87c5fbaSopenharmony_ci tracked_tokens[i].observe = 0; 1950c87c5fbaSopenharmony_ci coap_io_process(ctx, COAP_IO_NO_WAIT); 1951c87c5fbaSopenharmony_ci } 1952c87c5fbaSopenharmony_ci } 1953c87c5fbaSopenharmony_ci doing_observe = 0; 1954c87c5fbaSopenharmony_ci 1955c87c5fbaSopenharmony_ci /* make sure that the obs timer does not fire again */ 1956c87c5fbaSopenharmony_ci obs_ms = 0; 1957c87c5fbaSopenharmony_ci obs_seconds = 0; 1958c87c5fbaSopenharmony_ci } else { 1959c87c5fbaSopenharmony_ci obs_ms -= result; 1960c87c5fbaSopenharmony_ci } 1961c87c5fbaSopenharmony_ci } 1962c87c5fbaSopenharmony_ci if (ready && repeat_count) { 1963c87c5fbaSopenharmony_ci /* Send off next request if appropriate */ 1964c87c5fbaSopenharmony_ci if (repeat_ms > (unsigned)result) { 1965c87c5fbaSopenharmony_ci repeat_ms -= (unsigned)result; 1966c87c5fbaSopenharmony_ci } else { 1967c87c5fbaSopenharmony_ci /* Doing this once a second */ 1968c87c5fbaSopenharmony_ci repeat_ms = REPEAT_DELAY_MS; 1969c87c5fbaSopenharmony_ci if (payload.length) { 1970c87c5fbaSopenharmony_ci /* Create some new data to use for this iteration */ 1971c87c5fbaSopenharmony_ci data = coap_malloc(payload.length); 1972c87c5fbaSopenharmony_ci if (data == NULL) 1973c87c5fbaSopenharmony_ci goto failed; 1974c87c5fbaSopenharmony_ci memcpy(data, payload.s, payload.length); 1975c87c5fbaSopenharmony_ci data_len = payload.length; 1976c87c5fbaSopenharmony_ci } 1977c87c5fbaSopenharmony_ci if (!(pdu = coap_new_request(ctx, session, method, &optlist, 1978c87c5fbaSopenharmony_ci data, data_len))) { 1979c87c5fbaSopenharmony_ci goto failed; 1980c87c5fbaSopenharmony_ci } 1981c87c5fbaSopenharmony_ci coap_log_debug("sending CoAP request:\n"); 1982c87c5fbaSopenharmony_ci if (coap_get_log_level() < COAP_LOG_DEBUG) 1983c87c5fbaSopenharmony_ci coap_show_pdu(COAP_LOG_INFO, pdu); 1984c87c5fbaSopenharmony_ci 1985c87c5fbaSopenharmony_ci ready = 0; 1986c87c5fbaSopenharmony_ci if (coap_send(session, pdu) == COAP_INVALID_MID) { 1987c87c5fbaSopenharmony_ci coap_log_err("cannot send CoAP pdu\n"); 1988c87c5fbaSopenharmony_ci quit = 1; 1989c87c5fbaSopenharmony_ci } 1990c87c5fbaSopenharmony_ci repeat_count--; 1991c87c5fbaSopenharmony_ci } 1992c87c5fbaSopenharmony_ci } 1993c87c5fbaSopenharmony_ci obs_ms_reset = 0; 1994c87c5fbaSopenharmony_ci } 1995c87c5fbaSopenharmony_ci } 1996c87c5fbaSopenharmony_ci 1997c87c5fbaSopenharmony_ci exit_code = 0; 1998c87c5fbaSopenharmony_ci 1999c87c5fbaSopenharmony_cifinish: 2000c87c5fbaSopenharmony_ci 2001c87c5fbaSopenharmony_ci /* Clean up library usage */ 2002c87c5fbaSopenharmony_ci coap_session_release(session); 2003c87c5fbaSopenharmony_ci coap_free_context(ctx); 2004c87c5fbaSopenharmony_ci coap_cleanup(); 2005c87c5fbaSopenharmony_ci 2006c87c5fbaSopenharmony_ci /* Clean up local usage */ 2007c87c5fbaSopenharmony_ci coap_free(ca_mem); 2008c87c5fbaSopenharmony_ci coap_free(cert_mem); 2009c87c5fbaSopenharmony_ci coap_free(key_mem); 2010c87c5fbaSopenharmony_ci coap_free(payload.s); 2011c87c5fbaSopenharmony_ci 2012c87c5fbaSopenharmony_ci for (i = 0; i < valid_ihs.count; i++) { 2013c87c5fbaSopenharmony_ci free(valid_ihs.ih_list[i].hint_match); 2014c87c5fbaSopenharmony_ci coap_delete_bin_const(valid_ihs.ih_list[i].new_identity); 2015c87c5fbaSopenharmony_ci coap_delete_bin_const(valid_ihs.ih_list[i].new_key); 2016c87c5fbaSopenharmony_ci } 2017c87c5fbaSopenharmony_ci if (valid_ihs.count) 2018c87c5fbaSopenharmony_ci free(valid_ihs.ih_list); 2019c87c5fbaSopenharmony_ci 2020c87c5fbaSopenharmony_ci for (i = 0; i < tracked_tokens_count; i++) { 2021c87c5fbaSopenharmony_ci coap_delete_binary(tracked_tokens[i].token); 2022c87c5fbaSopenharmony_ci } 2023c87c5fbaSopenharmony_ci free(tracked_tokens); 2024c87c5fbaSopenharmony_ci 2025c87c5fbaSopenharmony_ci coap_delete_optlist(optlist); 2026c87c5fbaSopenharmony_ci if (oscore_seq_num_fp) 2027c87c5fbaSopenharmony_ci fclose(oscore_seq_num_fp); 2028c87c5fbaSopenharmony_ci close_output(); 2029c87c5fbaSopenharmony_ci 2030c87c5fbaSopenharmony_ci return exit_code; 2031c87c5fbaSopenharmony_ci 2032c87c5fbaSopenharmony_cifailed: 2033c87c5fbaSopenharmony_ci exit_code = 1; 2034c87c5fbaSopenharmony_ci goto finish; 2035c87c5fbaSopenharmony_ci} 2036