1c87c5fbaSopenharmony_ci/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2c87c5fbaSopenharmony_ci 3c87c5fbaSopenharmony_ci/* coap -- simple implementation of the Constrained Application Protocol (CoAP) 4c87c5fbaSopenharmony_ci * as defined in RFC 7252 5c87c5fbaSopenharmony_ci * 6c87c5fbaSopenharmony_ci * Copyright (C) 2010--2023 Olaf Bergmann <bergmann@tzi.org> and others 7c87c5fbaSopenharmony_ci * 8c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 9c87c5fbaSopenharmony_ci * 10c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see README for terms 11c87c5fbaSopenharmony_ci * of use. 12c87c5fbaSopenharmony_ci */ 13c87c5fbaSopenharmony_ci 14c87c5fbaSopenharmony_ci#include <string.h> 15c87c5fbaSopenharmony_ci#include <stdlib.h> 16c87c5fbaSopenharmony_ci#include <stdio.h> 17c87c5fbaSopenharmony_ci#include <ctype.h> 18c87c5fbaSopenharmony_ci#include <inttypes.h> 19c87c5fbaSopenharmony_ci#include <sys/types.h> 20c87c5fbaSopenharmony_ci#include <sys/stat.h> 21c87c5fbaSopenharmony_ci#include <errno.h> 22c87c5fbaSopenharmony_ci#include <signal.h> 23c87c5fbaSopenharmony_ci#ifdef _WIN32 24c87c5fbaSopenharmony_ci#define strcasecmp _stricmp 25c87c5fbaSopenharmony_ci#define strncasecmp _strnicmp 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_ci#ifndef R_OK 31c87c5fbaSopenharmony_ci#define R_OK 4 32c87c5fbaSopenharmony_ci#endif 33c87c5fbaSopenharmony_cichar *strndup(const char *s1, size_t n); 34c87c5fbaSopenharmony_cichar * 35c87c5fbaSopenharmony_cistrndup(const char *s1, size_t n) { 36c87c5fbaSopenharmony_ci char *copy = (char *)malloc(n + 1); 37c87c5fbaSopenharmony_ci if (copy) { 38c87c5fbaSopenharmony_ci memcpy(copy, s1, n); 39c87c5fbaSopenharmony_ci copy[n] = 0; 40c87c5fbaSopenharmony_ci } 41c87c5fbaSopenharmony_ci return copy; 42c87c5fbaSopenharmony_ci} 43c87c5fbaSopenharmony_ci#include <io.h> 44c87c5fbaSopenharmony_ci#define access _access 45c87c5fbaSopenharmony_ci#define fileno _fileno 46c87c5fbaSopenharmony_ci#else 47c87c5fbaSopenharmony_ci#include <unistd.h> 48c87c5fbaSopenharmony_ci#include <sys/select.h> 49c87c5fbaSopenharmony_ci#include <sys/socket.h> 50c87c5fbaSopenharmony_ci#include <netinet/in.h> 51c87c5fbaSopenharmony_ci#include <arpa/inet.h> 52c87c5fbaSopenharmony_ci#include <netdb.h> 53c87c5fbaSopenharmony_ci#include <dirent.h> 54c87c5fbaSopenharmony_ci#include <syslog.h> 55c87c5fbaSopenharmony_ci#endif 56c87c5fbaSopenharmony_ci 57c87c5fbaSopenharmony_ci/* 58c87c5fbaSopenharmony_ci * SERVER_CAN_PROXY=0 can be set by build system if 59c87c5fbaSopenharmony_ci * "./configure --disable-client-mode" is used. 60c87c5fbaSopenharmony_ci */ 61c87c5fbaSopenharmony_ci#ifndef SERVER_CAN_PROXY 62c87c5fbaSopenharmony_ci#define SERVER_CAN_PROXY 1 63c87c5fbaSopenharmony_ci#endif 64c87c5fbaSopenharmony_ci 65c87c5fbaSopenharmony_ci/* Need to refresh time once per sec */ 66c87c5fbaSopenharmony_ci#define COAP_RESOURCE_CHECK_TIME 1 67c87c5fbaSopenharmony_ci 68c87c5fbaSopenharmony_ci#include <coap3/coap.h> 69c87c5fbaSopenharmony_ci 70c87c5fbaSopenharmony_ci#ifndef min 71c87c5fbaSopenharmony_ci#define min(a,b) ((a) < (b) ? (a) : (b)) 72c87c5fbaSopenharmony_ci#endif 73c87c5fbaSopenharmony_ci 74c87c5fbaSopenharmony_cistatic coap_oscore_conf_t *oscore_conf; 75c87c5fbaSopenharmony_cistatic int doing_oscore = 0; 76c87c5fbaSopenharmony_ci 77c87c5fbaSopenharmony_ci/* set to 1 to request clean server shutdown */ 78c87c5fbaSopenharmony_cistatic int quit = 0; 79c87c5fbaSopenharmony_ci 80c87c5fbaSopenharmony_ci/* set to 1 if persist information is to be kept on server shutdown */ 81c87c5fbaSopenharmony_cistatic int keep_persist = 0; 82c87c5fbaSopenharmony_ci 83c87c5fbaSopenharmony_ci/* changeable clock base (see handle_put_time()) */ 84c87c5fbaSopenharmony_cistatic time_t clock_offset; 85c87c5fbaSopenharmony_cistatic time_t my_clock_base = 0; 86c87c5fbaSopenharmony_ci 87c87c5fbaSopenharmony_cicoap_resource_t *time_resource = NULL; 88c87c5fbaSopenharmony_ci 89c87c5fbaSopenharmony_cistatic int resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_CON; 90c87c5fbaSopenharmony_cistatic int track_observes = 0; 91c87c5fbaSopenharmony_ci 92c87c5fbaSopenharmony_ci/* 93c87c5fbaSopenharmony_ci * For PKI, if one or more of cert_file, key_file and ca_file is in PKCS11 URI 94c87c5fbaSopenharmony_ci * format, then the remainder of cert_file, key_file and ca_file are treated 95c87c5fbaSopenharmony_ci * as being in DER format to provide consistency across the underlying (D)TLS 96c87c5fbaSopenharmony_ci * libraries. 97c87c5fbaSopenharmony_ci */ 98c87c5fbaSopenharmony_cistatic char *cert_file = NULL; /* certificate and optional private key in PEM, 99c87c5fbaSopenharmony_ci or PKCS11 URI*/ 100c87c5fbaSopenharmony_cistatic char *key_file = NULL; /* private key in PEM, DER or PKCS11 URI */ 101c87c5fbaSopenharmony_cistatic char *pkcs11_pin = NULL; /* PKCS11 pin to unlock access to token */ 102c87c5fbaSopenharmony_cistatic char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM, 103c87c5fbaSopenharmony_ci DER or PKCS11 URI */ 104c87c5fbaSopenharmony_cistatic char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */ 105c87c5fbaSopenharmony_cistatic int use_pem_buf = 0; /* Map these cert/key files into memory to test 106c87c5fbaSopenharmony_ci PEM_BUF logic if set */ 107c87c5fbaSopenharmony_cistatic int is_rpk_not_cert = 0; /* Cert is RPK if set */ 108c87c5fbaSopenharmony_ci/* Used to hold initial PEM_BUF setup */ 109c87c5fbaSopenharmony_cistatic uint8_t *cert_mem_base = NULL; /* certificate and private key in PEM_BUF */ 110c87c5fbaSopenharmony_cistatic uint8_t *key_mem_base = NULL; /* private key in PEM_BUF */ 111c87c5fbaSopenharmony_cistatic uint8_t *ca_mem_base = NULL; /* CA for cert checking in PEM_BUF */ 112c87c5fbaSopenharmony_ci/* Used for verify_pki_sni_callback PEM_BUF temporary holding */ 113c87c5fbaSopenharmony_cistatic uint8_t *cert_mem = NULL; /* certificate and private key in PEM_BUF */ 114c87c5fbaSopenharmony_cistatic uint8_t *key_mem = NULL; /* private key in PEM_BUF */ 115c87c5fbaSopenharmony_cistatic uint8_t *ca_mem = NULL; /* CA for cert checking in PEM_BUF */ 116c87c5fbaSopenharmony_cistatic size_t cert_mem_len = 0; 117c87c5fbaSopenharmony_cistatic size_t key_mem_len = 0; 118c87c5fbaSopenharmony_cistatic size_t ca_mem_len = 0; 119c87c5fbaSopenharmony_cistatic int verify_peer_cert = 1; /* PKI granularity - by default set */ 120c87c5fbaSopenharmony_ci#define MAX_KEY 64 /* Maximum length of a pre-shared key in bytes. */ 121c87c5fbaSopenharmony_cistatic uint8_t *key = NULL; 122c87c5fbaSopenharmony_cistatic ssize_t key_length = 0; 123c87c5fbaSopenharmony_ciint key_defined = 0; 124c87c5fbaSopenharmony_cistatic const char *hint = "CoAP"; 125c87c5fbaSopenharmony_cistatic int support_dynamic = 0; 126c87c5fbaSopenharmony_cistatic uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP; 127c87c5fbaSopenharmony_cistatic int echo_back = 0; 128c87c5fbaSopenharmony_cistatic uint32_t csm_max_message_size = 0; 129c87c5fbaSopenharmony_cistatic size_t extended_token_size = COAP_TOKEN_DEFAULT_MAX; 130c87c5fbaSopenharmony_cistatic coap_proto_t use_unix_proto = COAP_PROTO_NONE; 131c87c5fbaSopenharmony_cistatic int enable_ws = 0; 132c87c5fbaSopenharmony_cistatic int ws_port = 80; 133c87c5fbaSopenharmony_cistatic int wss_port = 443; 134c87c5fbaSopenharmony_ci 135c87c5fbaSopenharmony_cistatic coap_dtls_pki_t *setup_pki(coap_context_t *ctx, coap_dtls_role_t role, char *sni); 136c87c5fbaSopenharmony_ci 137c87c5fbaSopenharmony_citypedef struct psk_sni_def_t { 138c87c5fbaSopenharmony_ci char *sni_match; 139c87c5fbaSopenharmony_ci coap_bin_const_t *new_key; 140c87c5fbaSopenharmony_ci coap_bin_const_t *new_hint; 141c87c5fbaSopenharmony_ci} psk_sni_def_t; 142c87c5fbaSopenharmony_ci 143c87c5fbaSopenharmony_citypedef struct valid_psk_snis_t { 144c87c5fbaSopenharmony_ci size_t count; 145c87c5fbaSopenharmony_ci psk_sni_def_t *psk_sni_list; 146c87c5fbaSopenharmony_ci} valid_psk_snis_t; 147c87c5fbaSopenharmony_ci 148c87c5fbaSopenharmony_cistatic valid_psk_snis_t valid_psk_snis = {0, NULL}; 149c87c5fbaSopenharmony_ci 150c87c5fbaSopenharmony_citypedef struct id_def_t { 151c87c5fbaSopenharmony_ci char *hint_match; 152c87c5fbaSopenharmony_ci coap_bin_const_t *identity_match; 153c87c5fbaSopenharmony_ci coap_bin_const_t *new_key; 154c87c5fbaSopenharmony_ci} id_def_t; 155c87c5fbaSopenharmony_ci 156c87c5fbaSopenharmony_citypedef struct valid_ids_t { 157c87c5fbaSopenharmony_ci size_t count; 158c87c5fbaSopenharmony_ci id_def_t *id_list; 159c87c5fbaSopenharmony_ci} valid_ids_t; 160c87c5fbaSopenharmony_ci 161c87c5fbaSopenharmony_cistatic valid_ids_t valid_ids = {0, NULL}; 162c87c5fbaSopenharmony_citypedef struct pki_sni_def_t { 163c87c5fbaSopenharmony_ci char *sni_match; 164c87c5fbaSopenharmony_ci char *new_cert; 165c87c5fbaSopenharmony_ci char *new_ca; 166c87c5fbaSopenharmony_ci} pki_sni_def_t; 167c87c5fbaSopenharmony_ci 168c87c5fbaSopenharmony_citypedef struct valid_pki_snis_t { 169c87c5fbaSopenharmony_ci size_t count; 170c87c5fbaSopenharmony_ci pki_sni_def_t *pki_sni_list; 171c87c5fbaSopenharmony_ci} valid_pki_snis_t; 172c87c5fbaSopenharmony_ci 173c87c5fbaSopenharmony_cistatic valid_pki_snis_t valid_pki_snis = {0, NULL}; 174c87c5fbaSopenharmony_ci 175c87c5fbaSopenharmony_citypedef struct transient_value_t { 176c87c5fbaSopenharmony_ci coap_binary_t *value; 177c87c5fbaSopenharmony_ci size_t ref_cnt; 178c87c5fbaSopenharmony_ci} transient_value_t; 179c87c5fbaSopenharmony_ci 180c87c5fbaSopenharmony_ci/* temporary storage for dynamic resource representations */ 181c87c5fbaSopenharmony_cistatic transient_value_t *example_data_value = NULL; 182c87c5fbaSopenharmony_cistatic int example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN; 183c87c5fbaSopenharmony_ci 184c87c5fbaSopenharmony_ci/* SIGINT handler: set quit to 1 for graceful termination */ 185c87c5fbaSopenharmony_cistatic void 186c87c5fbaSopenharmony_cihandle_sigint(int signum COAP_UNUSED) { 187c87c5fbaSopenharmony_ci quit = 1; 188c87c5fbaSopenharmony_ci} 189c87c5fbaSopenharmony_ci 190c87c5fbaSopenharmony_ci#ifndef _WIN32 191c87c5fbaSopenharmony_ci/* 192c87c5fbaSopenharmony_ci * SIGUSR2 handler: set quit to 1 for graceful termination 193c87c5fbaSopenharmony_ci * Disable sending out 4.04 for any active observations. 194c87c5fbaSopenharmony_ci * Note: coap_*() functions should not be called at sig interrupt. 195c87c5fbaSopenharmony_ci */ 196c87c5fbaSopenharmony_cistatic void 197c87c5fbaSopenharmony_cihandle_sigusr2(int signum COAP_UNUSED) { 198c87c5fbaSopenharmony_ci quit = 1; 199c87c5fbaSopenharmony_ci keep_persist = 1; 200c87c5fbaSopenharmony_ci} 201c87c5fbaSopenharmony_ci#endif /* ! _WIN32 */ 202c87c5fbaSopenharmony_ci 203c87c5fbaSopenharmony_ci/* 204c87c5fbaSopenharmony_ci * This will return a correctly formed transient_value_t *, or NULL. 205c87c5fbaSopenharmony_ci * If an error, the passed in coap_binary_t * will get deleted. 206c87c5fbaSopenharmony_ci * Note: transient_value->value will never be returned as NULL. 207c87c5fbaSopenharmony_ci */ 208c87c5fbaSopenharmony_cistatic transient_value_t * 209c87c5fbaSopenharmony_cialloc_resource_data(coap_binary_t *value) { 210c87c5fbaSopenharmony_ci transient_value_t *transient_value; 211c87c5fbaSopenharmony_ci if (!value) 212c87c5fbaSopenharmony_ci return NULL; 213c87c5fbaSopenharmony_ci transient_value = coap_malloc(sizeof(transient_value_t)); 214c87c5fbaSopenharmony_ci if (!transient_value) { 215c87c5fbaSopenharmony_ci coap_delete_binary(value); 216c87c5fbaSopenharmony_ci return NULL; 217c87c5fbaSopenharmony_ci } 218c87c5fbaSopenharmony_ci transient_value->ref_cnt = 1; 219c87c5fbaSopenharmony_ci transient_value->value = value; 220c87c5fbaSopenharmony_ci return transient_value; 221c87c5fbaSopenharmony_ci} 222c87c5fbaSopenharmony_ci 223c87c5fbaSopenharmony_ci/* 224c87c5fbaSopenharmony_ci * Need to handle race conditions of data being updated (by PUT) and 225c87c5fbaSopenharmony_ci * being read by a blocked response to GET. 226c87c5fbaSopenharmony_ci */ 227c87c5fbaSopenharmony_cistatic void 228c87c5fbaSopenharmony_cirelease_resource_data(coap_session_t *session COAP_UNUSED, 229c87c5fbaSopenharmony_ci void *app_ptr) { 230c87c5fbaSopenharmony_ci transient_value_t *transient_value = (transient_value_t *)app_ptr; 231c87c5fbaSopenharmony_ci 232c87c5fbaSopenharmony_ci if (!transient_value) 233c87c5fbaSopenharmony_ci return; 234c87c5fbaSopenharmony_ci 235c87c5fbaSopenharmony_ci if (--transient_value->ref_cnt > 0) 236c87c5fbaSopenharmony_ci return; 237c87c5fbaSopenharmony_ci coap_delete_binary(transient_value->value); 238c87c5fbaSopenharmony_ci coap_free(transient_value); 239c87c5fbaSopenharmony_ci} 240c87c5fbaSopenharmony_ci 241c87c5fbaSopenharmony_ci/* 242c87c5fbaSopenharmony_ci * Bump the reference count and return reference to data 243c87c5fbaSopenharmony_ci */ 244c87c5fbaSopenharmony_cistatic coap_binary_t 245c87c5fbaSopenharmony_cireference_resource_data(transient_value_t *entry) { 246c87c5fbaSopenharmony_ci coap_binary_t body; 247c87c5fbaSopenharmony_ci if (entry) { 248c87c5fbaSopenharmony_ci /* Bump reference so not removed elsewhere */ 249c87c5fbaSopenharmony_ci entry->ref_cnt++; 250c87c5fbaSopenharmony_ci assert(entry->value); 251c87c5fbaSopenharmony_ci body.length = entry->value->length; 252c87c5fbaSopenharmony_ci body.s = entry->value->s; 253c87c5fbaSopenharmony_ci } else { 254c87c5fbaSopenharmony_ci body.length = 0; 255c87c5fbaSopenharmony_ci body.s = NULL; 256c87c5fbaSopenharmony_ci } 257c87c5fbaSopenharmony_ci return body; 258c87c5fbaSopenharmony_ci} 259c87c5fbaSopenharmony_ci 260c87c5fbaSopenharmony_ci#define INDEX "This is a test server made with libcoap (see https://libcoap.net)\n" \ 261c87c5fbaSopenharmony_ci "Copyright (C) 2010--2023 Olaf Bergmann <bergmann@tzi.org> and others\n\n" 262c87c5fbaSopenharmony_ci 263c87c5fbaSopenharmony_cistatic void 264c87c5fbaSopenharmony_cihnd_get_index(coap_resource_t *resource, 265c87c5fbaSopenharmony_ci coap_session_t *session, 266c87c5fbaSopenharmony_ci const coap_pdu_t *request, 267c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 268c87c5fbaSopenharmony_ci coap_pdu_t *response) { 269c87c5fbaSopenharmony_ci 270c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 271c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 272c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 273c87c5fbaSopenharmony_ci 0x2ffff, 0, strlen(INDEX), 274c87c5fbaSopenharmony_ci (const uint8_t *)INDEX, NULL, NULL); 275c87c5fbaSopenharmony_ci} 276c87c5fbaSopenharmony_ci 277c87c5fbaSopenharmony_cistatic void 278c87c5fbaSopenharmony_cihnd_get_fetch_time(coap_resource_t *resource, 279c87c5fbaSopenharmony_ci coap_session_t *session, 280c87c5fbaSopenharmony_ci const coap_pdu_t *request, 281c87c5fbaSopenharmony_ci const coap_string_t *query, 282c87c5fbaSopenharmony_ci coap_pdu_t *response) { 283c87c5fbaSopenharmony_ci unsigned char buf[40]; 284c87c5fbaSopenharmony_ci size_t len; 285c87c5fbaSopenharmony_ci time_t now; 286c87c5fbaSopenharmony_ci coap_tick_t t; 287c87c5fbaSopenharmony_ci (void)request; 288c87c5fbaSopenharmony_ci coap_pdu_code_t code = coap_pdu_get_code(request); 289c87c5fbaSopenharmony_ci size_t size; 290c87c5fbaSopenharmony_ci const uint8_t *data; 291c87c5fbaSopenharmony_ci coap_str_const_t *ticks = coap_make_str_const("ticks"); 292c87c5fbaSopenharmony_ci 293c87c5fbaSopenharmony_ci if (my_clock_base) { 294c87c5fbaSopenharmony_ci 295c87c5fbaSopenharmony_ci /* calculate current time */ 296c87c5fbaSopenharmony_ci coap_ticks(&t); 297c87c5fbaSopenharmony_ci now = my_clock_base + (t / COAP_TICKS_PER_SECOND); 298c87c5fbaSopenharmony_ci 299c87c5fbaSopenharmony_ci /* coap_get_data() sets size to 0 on error */ 300c87c5fbaSopenharmony_ci (void)coap_get_data(request, &size, &data); 301c87c5fbaSopenharmony_ci 302c87c5fbaSopenharmony_ci if (code == COAP_REQUEST_CODE_GET && query != NULL && 303c87c5fbaSopenharmony_ci coap_string_equal(query, ticks)) { 304c87c5fbaSopenharmony_ci /* parameter is in query, output ticks */ 305c87c5fbaSopenharmony_ci len = snprintf((char *)buf, sizeof(buf), "%" PRIi64, (int64_t)now); 306c87c5fbaSopenharmony_ci } else if (code == COAP_REQUEST_CODE_FETCH && size == ticks->length && 307c87c5fbaSopenharmony_ci memcmp(data, ticks->s, ticks->length) == 0) { 308c87c5fbaSopenharmony_ci /* parameter is in data, output ticks */ 309c87c5fbaSopenharmony_ci len = snprintf((char *)buf, sizeof(buf), "%" PRIi64, (int64_t)now); 310c87c5fbaSopenharmony_ci } else { /* output human-readable time */ 311c87c5fbaSopenharmony_ci struct tm *tmp; 312c87c5fbaSopenharmony_ci tmp = gmtime(&now); 313c87c5fbaSopenharmony_ci if (!tmp) { 314c87c5fbaSopenharmony_ci /* If 'now' is not valid */ 315c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 316c87c5fbaSopenharmony_ci return; 317c87c5fbaSopenharmony_ci } else { 318c87c5fbaSopenharmony_ci len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); 319c87c5fbaSopenharmony_ci } 320c87c5fbaSopenharmony_ci } 321c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 322c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 323c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, 324c87c5fbaSopenharmony_ci len, 325c87c5fbaSopenharmony_ci buf, NULL, NULL); 326c87c5fbaSopenharmony_ci } else { 327c87c5fbaSopenharmony_ci /* if my_clock_base was deleted, we pretend to have no such resource */ 328c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 329c87c5fbaSopenharmony_ci } 330c87c5fbaSopenharmony_ci} 331c87c5fbaSopenharmony_ci 332c87c5fbaSopenharmony_cistatic void 333c87c5fbaSopenharmony_cihnd_put_time(coap_resource_t *resource, 334c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 335c87c5fbaSopenharmony_ci const coap_pdu_t *request, 336c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 337c87c5fbaSopenharmony_ci coap_pdu_t *response) { 338c87c5fbaSopenharmony_ci coap_tick_t t; 339c87c5fbaSopenharmony_ci size_t size; 340c87c5fbaSopenharmony_ci const uint8_t *data; 341c87c5fbaSopenharmony_ci 342c87c5fbaSopenharmony_ci /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0 343c87c5fbaSopenharmony_ci * and request is empty. When not empty, set to value in request payload 344c87c5fbaSopenharmony_ci * (insist on query ?ticks). Return Created or Ok. 345c87c5fbaSopenharmony_ci */ 346c87c5fbaSopenharmony_ci 347c87c5fbaSopenharmony_ci /* if my_clock_base was deleted, we pretend to have no such resource */ 348c87c5fbaSopenharmony_ci coap_pdu_set_code(response, my_clock_base ? COAP_RESPONSE_CODE_CHANGED : 349c87c5fbaSopenharmony_ci COAP_RESPONSE_CODE_CREATED); 350c87c5fbaSopenharmony_ci 351c87c5fbaSopenharmony_ci coap_resource_notify_observers(resource, NULL); 352c87c5fbaSopenharmony_ci 353c87c5fbaSopenharmony_ci /* coap_get_data() sets size to 0 on error */ 354c87c5fbaSopenharmony_ci (void)coap_get_data(request, &size, &data); 355c87c5fbaSopenharmony_ci 356c87c5fbaSopenharmony_ci if (size == 0) { /* re-init */ 357c87c5fbaSopenharmony_ci my_clock_base = clock_offset; 358c87c5fbaSopenharmony_ci } else { 359c87c5fbaSopenharmony_ci my_clock_base = 0; 360c87c5fbaSopenharmony_ci coap_ticks(&t); 361c87c5fbaSopenharmony_ci while (size--) 362c87c5fbaSopenharmony_ci my_clock_base = my_clock_base * 10 + *data++; 363c87c5fbaSopenharmony_ci my_clock_base -= t / COAP_TICKS_PER_SECOND; 364c87c5fbaSopenharmony_ci 365c87c5fbaSopenharmony_ci /* Sanity check input value */ 366c87c5fbaSopenharmony_ci if (!gmtime(&my_clock_base)) { 367c87c5fbaSopenharmony_ci unsigned char buf[3]; 368c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); 369c87c5fbaSopenharmony_ci coap_add_option(response, 370c87c5fbaSopenharmony_ci COAP_OPTION_CONTENT_FORMAT, 371c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 372c87c5fbaSopenharmony_ci COAP_MEDIATYPE_TEXT_PLAIN), buf); 373c87c5fbaSopenharmony_ci coap_add_data(response, 22, (const uint8_t *)"Invalid set time value"); 374c87c5fbaSopenharmony_ci /* re-init as value is bad */ 375c87c5fbaSopenharmony_ci my_clock_base = clock_offset; 376c87c5fbaSopenharmony_ci } 377c87c5fbaSopenharmony_ci } 378c87c5fbaSopenharmony_ci} 379c87c5fbaSopenharmony_ci 380c87c5fbaSopenharmony_cistatic void 381c87c5fbaSopenharmony_cihnd_delete_time(coap_resource_t *resource COAP_UNUSED, 382c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 383c87c5fbaSopenharmony_ci const coap_pdu_t *request COAP_UNUSED, 384c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 385c87c5fbaSopenharmony_ci coap_pdu_t *response COAP_UNUSED) { 386c87c5fbaSopenharmony_ci my_clock_base = 0; /* mark clock as "deleted" */ 387c87c5fbaSopenharmony_ci 388c87c5fbaSopenharmony_ci /* type = request->hdr->type == COAP_MESSAGE_CON */ 389c87c5fbaSopenharmony_ci /* ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; */ 390c87c5fbaSopenharmony_ci} 391c87c5fbaSopenharmony_ci 392c87c5fbaSopenharmony_ci/* 393c87c5fbaSopenharmony_ci * This logic is used to test out that the client correctly handles a 394c87c5fbaSopenharmony_ci * "separate" response (empty ACK followed by data response at a later stage). 395c87c5fbaSopenharmony_ci */ 396c87c5fbaSopenharmony_cistatic void 397c87c5fbaSopenharmony_cihnd_get_async(coap_resource_t *resource, 398c87c5fbaSopenharmony_ci coap_session_t *session, 399c87c5fbaSopenharmony_ci const coap_pdu_t *request, 400c87c5fbaSopenharmony_ci const coap_string_t *query, 401c87c5fbaSopenharmony_ci coap_pdu_t *response) { 402c87c5fbaSopenharmony_ci unsigned long delay = 4; /* Less than COAP_DEFAULT_LEISURE */ 403c87c5fbaSopenharmony_ci size_t size; 404c87c5fbaSopenharmony_ci coap_async_t *async; 405c87c5fbaSopenharmony_ci coap_bin_const_t token = coap_pdu_get_token(request); 406c87c5fbaSopenharmony_ci 407c87c5fbaSopenharmony_ci /* 408c87c5fbaSopenharmony_ci * See if this is the initial, or delayed request 409c87c5fbaSopenharmony_ci */ 410c87c5fbaSopenharmony_ci 411c87c5fbaSopenharmony_ci async = coap_find_async(session, token); 412c87c5fbaSopenharmony_ci if (!async) { 413c87c5fbaSopenharmony_ci /* Set up an async request to trigger delay in the future */ 414c87c5fbaSopenharmony_ci if (query) { 415c87c5fbaSopenharmony_ci /* Expect the query to just be the number of seconds to delay */ 416c87c5fbaSopenharmony_ci const uint8_t *p = query->s; 417c87c5fbaSopenharmony_ci 418c87c5fbaSopenharmony_ci if (isdigit(*p)) { 419c87c5fbaSopenharmony_ci delay = 0; 420c87c5fbaSopenharmony_ci for (size = query->length; size; --size, ++p) { 421c87c5fbaSopenharmony_ci if (!isdigit(*p)) 422c87c5fbaSopenharmony_ci break; 423c87c5fbaSopenharmony_ci delay = delay * 10 + (*p - '0'); 424c87c5fbaSopenharmony_ci } 425c87c5fbaSopenharmony_ci } else { 426c87c5fbaSopenharmony_ci coap_log_debug("async: query is just a number of seconds to alter delay\n"); 427c87c5fbaSopenharmony_ci } 428c87c5fbaSopenharmony_ci if (delay == 0) { 429c87c5fbaSopenharmony_ci coap_log_info("async: delay of 0 not supported\n"); 430c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); 431c87c5fbaSopenharmony_ci return; 432c87c5fbaSopenharmony_ci } 433c87c5fbaSopenharmony_ci } 434c87c5fbaSopenharmony_ci async = coap_register_async(session, 435c87c5fbaSopenharmony_ci request, 436c87c5fbaSopenharmony_ci COAP_TICKS_PER_SECOND * delay); 437c87c5fbaSopenharmony_ci if (async == NULL) { 438c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE); 439c87c5fbaSopenharmony_ci return; 440c87c5fbaSopenharmony_ci } 441c87c5fbaSopenharmony_ci /* 442c87c5fbaSopenharmony_ci * Not setting response code will cause empty ACK to be sent 443c87c5fbaSopenharmony_ci * if Confirmable 444c87c5fbaSopenharmony_ci */ 445c87c5fbaSopenharmony_ci return; 446c87c5fbaSopenharmony_ci } 447c87c5fbaSopenharmony_ci /* no request (observe) or async set up, so this is the delayed request */ 448c87c5fbaSopenharmony_ci 449c87c5fbaSopenharmony_ci /* Send back the appropriate data */ 450c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 451c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, -1, 0, 4, 452c87c5fbaSopenharmony_ci (const uint8_t *)"done", NULL, NULL); 453c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 454c87c5fbaSopenharmony_ci 455c87c5fbaSopenharmony_ci /* async is automatically removed by libcoap on return from this handler */ 456c87c5fbaSopenharmony_ci} 457c87c5fbaSopenharmony_ci 458c87c5fbaSopenharmony_ci/* 459c87c5fbaSopenharmony_ci * Large Data GET handler 460c87c5fbaSopenharmony_ci */ 461c87c5fbaSopenharmony_ci 462c87c5fbaSopenharmony_ci#ifndef INITIAL_EXAMPLE_SIZE 463c87c5fbaSopenharmony_ci#define INITIAL_EXAMPLE_SIZE 1500 464c87c5fbaSopenharmony_ci#endif 465c87c5fbaSopenharmony_cistatic void 466c87c5fbaSopenharmony_cihnd_get_example_data(coap_resource_t *resource, 467c87c5fbaSopenharmony_ci coap_session_t *session, 468c87c5fbaSopenharmony_ci const coap_pdu_t *request, 469c87c5fbaSopenharmony_ci const coap_string_t *query, 470c87c5fbaSopenharmony_ci coap_pdu_t *response) { 471c87c5fbaSopenharmony_ci coap_binary_t body; 472c87c5fbaSopenharmony_ci if (!example_data_value) { 473c87c5fbaSopenharmony_ci /* Initialise for the first time */ 474c87c5fbaSopenharmony_ci int i; 475c87c5fbaSopenharmony_ci coap_binary_t *value = coap_new_binary(INITIAL_EXAMPLE_SIZE); 476c87c5fbaSopenharmony_ci if (value) { 477c87c5fbaSopenharmony_ci for (i = 0; i < INITIAL_EXAMPLE_SIZE; i++) { 478c87c5fbaSopenharmony_ci if ((i % 10) == 0) { 479c87c5fbaSopenharmony_ci value->s[i] = 'a' + (i/10) % 26; 480c87c5fbaSopenharmony_ci } else { 481c87c5fbaSopenharmony_ci value->s[i] = '0' + i%10; 482c87c5fbaSopenharmony_ci } 483c87c5fbaSopenharmony_ci } 484c87c5fbaSopenharmony_ci } 485c87c5fbaSopenharmony_ci example_data_value = alloc_resource_data(value); 486c87c5fbaSopenharmony_ci } 487c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 488c87c5fbaSopenharmony_ci body = reference_resource_data(example_data_value); 489c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 490c87c5fbaSopenharmony_ci query, example_data_media_type, -1, 0, 491c87c5fbaSopenharmony_ci body.length, 492c87c5fbaSopenharmony_ci body.s, 493c87c5fbaSopenharmony_ci release_resource_data, example_data_value); 494c87c5fbaSopenharmony_ci} 495c87c5fbaSopenharmony_ci 496c87c5fbaSopenharmony_cistatic void 497c87c5fbaSopenharmony_cicache_free_app_data(void *data) { 498c87c5fbaSopenharmony_ci coap_binary_t *bdata = (coap_binary_t *)data; 499c87c5fbaSopenharmony_ci coap_delete_binary(bdata); 500c87c5fbaSopenharmony_ci} 501c87c5fbaSopenharmony_ci 502c87c5fbaSopenharmony_ci/* 503c87c5fbaSopenharmony_ci * Large Data PUT handler 504c87c5fbaSopenharmony_ci */ 505c87c5fbaSopenharmony_ci 506c87c5fbaSopenharmony_cistatic void 507c87c5fbaSopenharmony_cihnd_put_example_data(coap_resource_t *resource, 508c87c5fbaSopenharmony_ci coap_session_t *session, 509c87c5fbaSopenharmony_ci const coap_pdu_t *request, 510c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 511c87c5fbaSopenharmony_ci coap_pdu_t *response) { 512c87c5fbaSopenharmony_ci size_t size; 513c87c5fbaSopenharmony_ci const uint8_t *data; 514c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 515c87c5fbaSopenharmony_ci coap_opt_t *option; 516c87c5fbaSopenharmony_ci size_t offset; 517c87c5fbaSopenharmony_ci size_t total; 518c87c5fbaSopenharmony_ci coap_binary_t *data_so_far; 519c87c5fbaSopenharmony_ci 520c87c5fbaSopenharmony_ci if (coap_get_data_large(request, &size, &data, &offset, &total) && 521c87c5fbaSopenharmony_ci size != total) { 522c87c5fbaSopenharmony_ci /* 523c87c5fbaSopenharmony_ci * A part of the data has been received (COAP_BLOCK_SINGLE_BODY not set). 524c87c5fbaSopenharmony_ci * However, total unfortunately is only an indication, so it is not safe to 525c87c5fbaSopenharmony_ci * allocate a block based on total. As per 526c87c5fbaSopenharmony_ci * https://rfc-editor.org/rfc/rfc7959#section-4 527c87c5fbaSopenharmony_ci * o In a request carrying a Block1 Option, to indicate the current 528c87c5fbaSopenharmony_ci * estimate the client has of the total size of the resource 529c87c5fbaSopenharmony_ci * representation, measured in bytes ("size indication"). 530c87c5fbaSopenharmony_ci * 531c87c5fbaSopenharmony_ci * coap_cache_ignore_options() must have previously been called with at 532c87c5fbaSopenharmony_ci * least COAP_OPTION_BLOCK1 set as the option value will change per block. 533c87c5fbaSopenharmony_ci */ 534c87c5fbaSopenharmony_ci coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session, 535c87c5fbaSopenharmony_ci request, 536c87c5fbaSopenharmony_ci COAP_CACHE_IS_SESSION_BASED); 537c87c5fbaSopenharmony_ci 538c87c5fbaSopenharmony_ci if (offset == 0) { 539c87c5fbaSopenharmony_ci if (!cache_entry) { 540c87c5fbaSopenharmony_ci /* 541c87c5fbaSopenharmony_ci * Set idle_timeout parameter to COAP_MAX_TRANSMIT_WAIT if you want 542c87c5fbaSopenharmony_ci * early removal on transmission failure. 0 means only delete when 543c87c5fbaSopenharmony_ci * the session is deleted as session_based is set here. 544c87c5fbaSopenharmony_ci */ 545c87c5fbaSopenharmony_ci cache_entry = coap_new_cache_entry(session, request, 546c87c5fbaSopenharmony_ci COAP_CACHE_NOT_RECORD_PDU, 547c87c5fbaSopenharmony_ci COAP_CACHE_IS_SESSION_BASED, 0); 548c87c5fbaSopenharmony_ci } else { 549c87c5fbaSopenharmony_ci data_so_far = coap_cache_get_app_data(cache_entry); 550c87c5fbaSopenharmony_ci if (data_so_far) { 551c87c5fbaSopenharmony_ci coap_delete_binary(data_so_far); 552c87c5fbaSopenharmony_ci data_so_far = NULL; 553c87c5fbaSopenharmony_ci } 554c87c5fbaSopenharmony_ci coap_cache_set_app_data(cache_entry, NULL, NULL); 555c87c5fbaSopenharmony_ci } 556c87c5fbaSopenharmony_ci } 557c87c5fbaSopenharmony_ci if (!cache_entry) { 558c87c5fbaSopenharmony_ci if (offset == 0) { 559c87c5fbaSopenharmony_ci coap_log_warn("Unable to create a new cache entry\n"); 560c87c5fbaSopenharmony_ci } else { 561c87c5fbaSopenharmony_ci coap_log_warn("No cache entry available for the non-first BLOCK\n"); 562c87c5fbaSopenharmony_ci } 563c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 564c87c5fbaSopenharmony_ci return; 565c87c5fbaSopenharmony_ci } 566c87c5fbaSopenharmony_ci 567c87c5fbaSopenharmony_ci if (size) { 568c87c5fbaSopenharmony_ci /* Add in the new data to cache entry */ 569c87c5fbaSopenharmony_ci data_so_far = coap_cache_get_app_data(cache_entry); 570c87c5fbaSopenharmony_ci data_so_far = coap_block_build_body(data_so_far, size, data, 571c87c5fbaSopenharmony_ci offset, total); 572c87c5fbaSopenharmony_ci /* Yes, data_so_far can be NULL if error */ 573c87c5fbaSopenharmony_ci coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data); 574c87c5fbaSopenharmony_ci } 575c87c5fbaSopenharmony_ci if (offset + size == total) { 576c87c5fbaSopenharmony_ci /* All the data is now in */ 577c87c5fbaSopenharmony_ci data_so_far = coap_cache_get_app_data(cache_entry); 578c87c5fbaSopenharmony_ci coap_cache_set_app_data(cache_entry, NULL, NULL); 579c87c5fbaSopenharmony_ci } else { 580c87c5fbaSopenharmony_ci /* Give us the next block response */ 581c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE); 582c87c5fbaSopenharmony_ci return; 583c87c5fbaSopenharmony_ci } 584c87c5fbaSopenharmony_ci } else { 585c87c5fbaSopenharmony_ci /* single body of data received */ 586c87c5fbaSopenharmony_ci data_so_far = coap_new_binary(size); 587c87c5fbaSopenharmony_ci if (data_so_far) { 588c87c5fbaSopenharmony_ci memcpy(data_so_far->s, data, size); 589c87c5fbaSopenharmony_ci } 590c87c5fbaSopenharmony_ci } 591c87c5fbaSopenharmony_ci 592c87c5fbaSopenharmony_ci if (example_data_value) { 593c87c5fbaSopenharmony_ci /* pre-existed response */ 594c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); 595c87c5fbaSopenharmony_ci /* Need to de-reference as value may be in use elsewhere */ 596c87c5fbaSopenharmony_ci release_resource_data(session, example_data_value); 597c87c5fbaSopenharmony_ci } else 598c87c5fbaSopenharmony_ci /* just generated response */ 599c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); 600c87c5fbaSopenharmony_ci 601c87c5fbaSopenharmony_ci example_data_value = alloc_resource_data(data_so_far); 602c87c5fbaSopenharmony_ci if (!example_data_value) { 603c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 604c87c5fbaSopenharmony_ci return; 605c87c5fbaSopenharmony_ci } 606c87c5fbaSopenharmony_ci if ((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, 607c87c5fbaSopenharmony_ci &opt_iter)) != NULL) { 608c87c5fbaSopenharmony_ci example_data_media_type = 609c87c5fbaSopenharmony_ci coap_decode_var_bytes(coap_opt_value(option), 610c87c5fbaSopenharmony_ci coap_opt_length(option)); 611c87c5fbaSopenharmony_ci } else { 612c87c5fbaSopenharmony_ci example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN; 613c87c5fbaSopenharmony_ci } 614c87c5fbaSopenharmony_ci 615c87c5fbaSopenharmony_ci coap_resource_notify_observers(resource, NULL); 616c87c5fbaSopenharmony_ci if (echo_back) { 617c87c5fbaSopenharmony_ci coap_binary_t body; 618c87c5fbaSopenharmony_ci 619c87c5fbaSopenharmony_ci body = reference_resource_data(example_data_value); 620c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 621c87c5fbaSopenharmony_ci query, example_data_media_type, -1, 0, 622c87c5fbaSopenharmony_ci body.length, 623c87c5fbaSopenharmony_ci body.s, 624c87c5fbaSopenharmony_ci release_resource_data, example_data_value); 625c87c5fbaSopenharmony_ci } 626c87c5fbaSopenharmony_ci} 627c87c5fbaSopenharmony_ci 628c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 629c87c5fbaSopenharmony_ci 630c87c5fbaSopenharmony_ci#define MAX_USER 128 /* Maximum length of a user name (i.e., PSK 631c87c5fbaSopenharmony_ci * identity) in bytes. */ 632c87c5fbaSopenharmony_cistatic unsigned char *user = NULL; 633c87c5fbaSopenharmony_cistatic ssize_t user_length = -1; 634c87c5fbaSopenharmony_ci 635c87c5fbaSopenharmony_cistatic coap_uri_t proxy = { {0, NULL}, 0, {0, NULL}, {0, NULL}, 0 }; 636c87c5fbaSopenharmony_cistatic size_t proxy_host_name_count = 0; 637c87c5fbaSopenharmony_cistatic const char **proxy_host_name_list = NULL; 638c87c5fbaSopenharmony_ci 639c87c5fbaSopenharmony_citypedef struct proxy_list_t { 640c87c5fbaSopenharmony_ci coap_session_t *ongoing; /* Ongoing session */ 641c87c5fbaSopenharmony_ci coap_session_t *incoming; /* Incoming session */ 642c87c5fbaSopenharmony_ci coap_binary_t *token; /* Incoming token */ 643c87c5fbaSopenharmony_ci coap_string_t *query; /* Incoming query */ 644c87c5fbaSopenharmony_ci coap_pdu_code_t req_code; /* Incoming request code */ 645c87c5fbaSopenharmony_ci coap_pdu_type_t req_type; /* Incoming request type */ 646c87c5fbaSopenharmony_ci} proxy_list_t; 647c87c5fbaSopenharmony_ci 648c87c5fbaSopenharmony_cistatic proxy_list_t *proxy_list = NULL; 649c87c5fbaSopenharmony_cistatic size_t proxy_list_count = 0; 650c87c5fbaSopenharmony_cistatic coap_resource_t *proxy_resource = NULL; 651c87c5fbaSopenharmony_ci 652c87c5fbaSopenharmony_cistatic int 653c87c5fbaSopenharmony_ciget_uri_proxy_scheme_info(const coap_pdu_t *request, 654c87c5fbaSopenharmony_ci coap_opt_t *opt, 655c87c5fbaSopenharmony_ci coap_uri_t *uri, 656c87c5fbaSopenharmony_ci coap_string_t **uri_path, 657c87c5fbaSopenharmony_ci coap_string_t **uri_query) { 658c87c5fbaSopenharmony_ci 659c87c5fbaSopenharmony_ci const char *opt_val = (const char *)coap_opt_value(opt); 660c87c5fbaSopenharmony_ci int opt_len = coap_opt_length(opt); 661c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 662c87c5fbaSopenharmony_ci 663c87c5fbaSopenharmony_ci if (opt_len == 9 && 664c87c5fbaSopenharmony_ci strncasecmp(opt_val, "coaps+tcp", 9) == 0) { 665c87c5fbaSopenharmony_ci uri->scheme = COAP_URI_SCHEME_COAPS_TCP; 666c87c5fbaSopenharmony_ci uri->port = COAPS_DEFAULT_PORT; 667c87c5fbaSopenharmony_ci } else if (opt_len == 8 && 668c87c5fbaSopenharmony_ci strncasecmp(opt_val, "coap+tcp", 8) == 0) { 669c87c5fbaSopenharmony_ci uri->scheme = COAP_URI_SCHEME_COAP_TCP; 670c87c5fbaSopenharmony_ci uri->port = COAP_DEFAULT_PORT; 671c87c5fbaSopenharmony_ci } else if (opt_len == 5 && 672c87c5fbaSopenharmony_ci strncasecmp(opt_val, "coaps", 5) == 0) { 673c87c5fbaSopenharmony_ci uri->scheme = COAP_URI_SCHEME_COAPS; 674c87c5fbaSopenharmony_ci uri->port = COAPS_DEFAULT_PORT; 675c87c5fbaSopenharmony_ci } else if (opt_len == 4 && 676c87c5fbaSopenharmony_ci strncasecmp(opt_val, "coap", 4) == 0) { 677c87c5fbaSopenharmony_ci uri->scheme = COAP_URI_SCHEME_COAP; 678c87c5fbaSopenharmony_ci uri->port = COAP_DEFAULT_PORT; 679c87c5fbaSopenharmony_ci } else { 680c87c5fbaSopenharmony_ci coap_log_warn("Unsupported Proxy Scheme '%*.*s'\n", 681c87c5fbaSopenharmony_ci opt_len, opt_len, opt_val); 682c87c5fbaSopenharmony_ci return 0; 683c87c5fbaSopenharmony_ci } 684c87c5fbaSopenharmony_ci 685c87c5fbaSopenharmony_ci opt = coap_check_option(request, COAP_OPTION_URI_HOST, &opt_iter); 686c87c5fbaSopenharmony_ci if (opt) { 687c87c5fbaSopenharmony_ci uri->host.length = coap_opt_length(opt); 688c87c5fbaSopenharmony_ci uri->host.s = coap_opt_value(opt); 689c87c5fbaSopenharmony_ci } else { 690c87c5fbaSopenharmony_ci coap_log_warn("Proxy Scheme requires Uri-Host\n"); 691c87c5fbaSopenharmony_ci return 0; 692c87c5fbaSopenharmony_ci } 693c87c5fbaSopenharmony_ci opt = coap_check_option(request, COAP_OPTION_URI_PORT, &opt_iter); 694c87c5fbaSopenharmony_ci if (opt) { 695c87c5fbaSopenharmony_ci uri->port = 696c87c5fbaSopenharmony_ci coap_decode_var_bytes(coap_opt_value(opt), 697c87c5fbaSopenharmony_ci coap_opt_length(opt)); 698c87c5fbaSopenharmony_ci } 699c87c5fbaSopenharmony_ci *uri_path = coap_get_uri_path(request); 700c87c5fbaSopenharmony_ci if (*uri_path) { 701c87c5fbaSopenharmony_ci uri->path.s = (*uri_path)->s; 702c87c5fbaSopenharmony_ci uri->path.length = (*uri_path)->length; 703c87c5fbaSopenharmony_ci } 704c87c5fbaSopenharmony_ci *uri_query = coap_get_query(request); 705c87c5fbaSopenharmony_ci if (*uri_query) { 706c87c5fbaSopenharmony_ci uri->query.s = (*uri_query)->s; 707c87c5fbaSopenharmony_ci uri->query.length = (*uri_query)->length; 708c87c5fbaSopenharmony_ci } 709c87c5fbaSopenharmony_ci return 1; 710c87c5fbaSopenharmony_ci} 711c87c5fbaSopenharmony_ci 712c87c5fbaSopenharmony_cistatic int 713c87c5fbaSopenharmony_civerify_proxy_scheme_supported(coap_uri_scheme_t scheme) { 714c87c5fbaSopenharmony_ci 715c87c5fbaSopenharmony_ci /* Sanity check that the connection can be forwarded on */ 716c87c5fbaSopenharmony_ci switch (scheme) { 717c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_HTTP: 718c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_HTTPS: 719c87c5fbaSopenharmony_ci coap_log_warn("Proxy URI http or https not supported\n"); 720c87c5fbaSopenharmony_ci return 0; 721c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAP: 722c87c5fbaSopenharmony_ci break; 723c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAPS: 724c87c5fbaSopenharmony_ci if (!coap_dtls_is_supported()) { 725c87c5fbaSopenharmony_ci coap_log_warn("coaps URI scheme not supported for proxy\n"); 726c87c5fbaSopenharmony_ci return 0; 727c87c5fbaSopenharmony_ci } 728c87c5fbaSopenharmony_ci break; 729c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAP_TCP: 730c87c5fbaSopenharmony_ci if (!coap_tcp_is_supported()) { 731c87c5fbaSopenharmony_ci coap_log_warn("coap+tcp URI scheme not supported for proxy\n"); 732c87c5fbaSopenharmony_ci return 0; 733c87c5fbaSopenharmony_ci } 734c87c5fbaSopenharmony_ci break; 735c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAPS_TCP: 736c87c5fbaSopenharmony_ci if (!coap_tls_is_supported()) { 737c87c5fbaSopenharmony_ci coap_log_warn("coaps+tcp URI scheme not supported for proxy\n"); 738c87c5fbaSopenharmony_ci return 0; 739c87c5fbaSopenharmony_ci } 740c87c5fbaSopenharmony_ci break; 741c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAP_WS: 742c87c5fbaSopenharmony_ci if (!coap_ws_is_supported()) { 743c87c5fbaSopenharmony_ci coap_log_warn("coap+ws URI scheme not supported for proxy\n"); 744c87c5fbaSopenharmony_ci return 0; 745c87c5fbaSopenharmony_ci } 746c87c5fbaSopenharmony_ci break; 747c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAPS_WS: 748c87c5fbaSopenharmony_ci if (!coap_wss_is_supported()) { 749c87c5fbaSopenharmony_ci coap_log_warn("coaps+ws URI scheme not supported for proxy\n"); 750c87c5fbaSopenharmony_ci return 0; 751c87c5fbaSopenharmony_ci } 752c87c5fbaSopenharmony_ci break; 753c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_LAST: 754c87c5fbaSopenharmony_ci default: 755c87c5fbaSopenharmony_ci coap_log_warn("%d URI scheme not supported\n", scheme); 756c87c5fbaSopenharmony_ci break; 757c87c5fbaSopenharmony_ci } 758c87c5fbaSopenharmony_ci return 1; 759c87c5fbaSopenharmony_ci} 760c87c5fbaSopenharmony_ci 761c87c5fbaSopenharmony_cistatic coap_dtls_cpsk_t * 762c87c5fbaSopenharmony_cisetup_cpsk(char *client_sni) { 763c87c5fbaSopenharmony_ci static coap_dtls_cpsk_t dtls_cpsk; 764c87c5fbaSopenharmony_ci 765c87c5fbaSopenharmony_ci memset(&dtls_cpsk, 0, sizeof(dtls_cpsk)); 766c87c5fbaSopenharmony_ci dtls_cpsk.version = COAP_DTLS_CPSK_SETUP_VERSION; 767c87c5fbaSopenharmony_ci dtls_cpsk.client_sni = client_sni; 768c87c5fbaSopenharmony_ci dtls_cpsk.psk_info.identity.s = user; 769c87c5fbaSopenharmony_ci dtls_cpsk.psk_info.identity.length = user_length; 770c87c5fbaSopenharmony_ci dtls_cpsk.psk_info.key.s = key; 771c87c5fbaSopenharmony_ci dtls_cpsk.psk_info.key.length = key_length; 772c87c5fbaSopenharmony_ci return &dtls_cpsk; 773c87c5fbaSopenharmony_ci} 774c87c5fbaSopenharmony_ci 775c87c5fbaSopenharmony_cistatic proxy_list_t * 776c87c5fbaSopenharmony_ciget_proxy_session(coap_session_t *session, coap_pdu_t *response, 777c87c5fbaSopenharmony_ci const coap_bin_const_t *token, const coap_string_t *query, 778c87c5fbaSopenharmony_ci coap_pdu_code_t req_code, coap_pdu_type_t req_type) { 779c87c5fbaSopenharmony_ci 780c87c5fbaSopenharmony_ci size_t i; 781c87c5fbaSopenharmony_ci proxy_list_t *new_proxy_list; 782c87c5fbaSopenharmony_ci 783c87c5fbaSopenharmony_ci /* Locate existing forwarding relationship */ 784c87c5fbaSopenharmony_ci for (i = 0; i < proxy_list_count; i++) { 785c87c5fbaSopenharmony_ci if (proxy_list[i].incoming == session) { 786c87c5fbaSopenharmony_ci return &proxy_list[i]; 787c87c5fbaSopenharmony_ci } 788c87c5fbaSopenharmony_ci } 789c87c5fbaSopenharmony_ci 790c87c5fbaSopenharmony_ci /* Need to create a new forwarding mapping */ 791c87c5fbaSopenharmony_ci new_proxy_list = realloc(proxy_list, (i+1)*sizeof(proxy_list[0])); 792c87c5fbaSopenharmony_ci 793c87c5fbaSopenharmony_ci if (new_proxy_list == NULL) { 794c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 795c87c5fbaSopenharmony_ci return NULL; 796c87c5fbaSopenharmony_ci } 797c87c5fbaSopenharmony_ci proxy_list = new_proxy_list; 798c87c5fbaSopenharmony_ci proxy_list[i].incoming = session; 799c87c5fbaSopenharmony_ci if (token) { 800c87c5fbaSopenharmony_ci proxy_list[i].token = coap_new_binary(token->length); 801c87c5fbaSopenharmony_ci if (!proxy_list[i].token) { 802c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 803c87c5fbaSopenharmony_ci return NULL; 804c87c5fbaSopenharmony_ci } 805c87c5fbaSopenharmony_ci memcpy(proxy_list[i].token->s, token->s, token->length); 806c87c5fbaSopenharmony_ci } else 807c87c5fbaSopenharmony_ci proxy_list[i].token = NULL; 808c87c5fbaSopenharmony_ci 809c87c5fbaSopenharmony_ci if (query) { 810c87c5fbaSopenharmony_ci proxy_list[i].query = coap_new_string(query->length); 811c87c5fbaSopenharmony_ci if (!proxy_list[i].query) { 812c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 813c87c5fbaSopenharmony_ci return NULL; 814c87c5fbaSopenharmony_ci } 815c87c5fbaSopenharmony_ci memcpy(proxy_list[i].query->s, query->s, query->length); 816c87c5fbaSopenharmony_ci } else 817c87c5fbaSopenharmony_ci proxy_list[i].query = NULL; 818c87c5fbaSopenharmony_ci 819c87c5fbaSopenharmony_ci proxy_list[i].ongoing = NULL; 820c87c5fbaSopenharmony_ci proxy_list[i].req_code = req_code; 821c87c5fbaSopenharmony_ci proxy_list[i].req_type = req_type; 822c87c5fbaSopenharmony_ci proxy_list_count++; 823c87c5fbaSopenharmony_ci return &proxy_list[i]; 824c87c5fbaSopenharmony_ci} 825c87c5fbaSopenharmony_ci 826c87c5fbaSopenharmony_cistatic void 827c87c5fbaSopenharmony_ciremove_proxy_association(coap_session_t *session, int send_failure) { 828c87c5fbaSopenharmony_ci 829c87c5fbaSopenharmony_ci size_t i; 830c87c5fbaSopenharmony_ci 831c87c5fbaSopenharmony_ci for (i = 0; i < proxy_list_count; i++) { 832c87c5fbaSopenharmony_ci if (proxy_list[i].incoming == session) { 833c87c5fbaSopenharmony_ci coap_session_release(proxy_list[i].ongoing); 834c87c5fbaSopenharmony_ci break; 835c87c5fbaSopenharmony_ci } 836c87c5fbaSopenharmony_ci if (proxy_list[i].ongoing == session && send_failure) { 837c87c5fbaSopenharmony_ci coap_pdu_t *response; 838c87c5fbaSopenharmony_ci 839c87c5fbaSopenharmony_ci coap_session_release(proxy_list[i].ongoing); 840c87c5fbaSopenharmony_ci 841c87c5fbaSopenharmony_ci /* Need to send back a gateway failure */ 842c87c5fbaSopenharmony_ci response = coap_pdu_init(proxy_list[i].req_type, 843c87c5fbaSopenharmony_ci COAP_RESPONSE_CODE_BAD_GATEWAY, 844c87c5fbaSopenharmony_ci coap_new_message_id(proxy_list[i].incoming), 845c87c5fbaSopenharmony_ci coap_session_max_pdu_size(proxy_list[i].incoming)); 846c87c5fbaSopenharmony_ci if (!response) { 847c87c5fbaSopenharmony_ci coap_log_info("PDU creation issue\n"); 848c87c5fbaSopenharmony_ci return; 849c87c5fbaSopenharmony_ci } 850c87c5fbaSopenharmony_ci 851c87c5fbaSopenharmony_ci if (proxy_list[i].token && 852c87c5fbaSopenharmony_ci !coap_add_token(response, proxy_list[i].token->length, 853c87c5fbaSopenharmony_ci proxy_list[i].token->s)) { 854c87c5fbaSopenharmony_ci coap_log_debug("Cannot add token to incoming proxy response PDU\n"); 855c87c5fbaSopenharmony_ci } 856c87c5fbaSopenharmony_ci 857c87c5fbaSopenharmony_ci if (coap_send(proxy_list[i].incoming, response) == 858c87c5fbaSopenharmony_ci COAP_INVALID_MID) { 859c87c5fbaSopenharmony_ci coap_log_info("Failed to send PDU with 5.02 gateway issue\n"); 860c87c5fbaSopenharmony_ci } 861c87c5fbaSopenharmony_ci break; 862c87c5fbaSopenharmony_ci } 863c87c5fbaSopenharmony_ci } 864c87c5fbaSopenharmony_ci if (i != proxy_list_count) { 865c87c5fbaSopenharmony_ci coap_delete_binary(proxy_list[i].token); 866c87c5fbaSopenharmony_ci coap_delete_string(proxy_list[i].query); 867c87c5fbaSopenharmony_ci if (proxy_list_count-i > 1) { 868c87c5fbaSopenharmony_ci memmove(&proxy_list[i], 869c87c5fbaSopenharmony_ci &proxy_list[i+1], 870c87c5fbaSopenharmony_ci (proxy_list_count-i-1) * sizeof(proxy_list[0])); 871c87c5fbaSopenharmony_ci } 872c87c5fbaSopenharmony_ci proxy_list_count--; 873c87c5fbaSopenharmony_ci } 874c87c5fbaSopenharmony_ci} 875c87c5fbaSopenharmony_ci 876c87c5fbaSopenharmony_ci 877c87c5fbaSopenharmony_cistatic coap_session_t * 878c87c5fbaSopenharmony_ciget_ongoing_proxy_session(coap_session_t *session, 879c87c5fbaSopenharmony_ci coap_pdu_t *response, const coap_bin_const_t *token, 880c87c5fbaSopenharmony_ci const coap_string_t *query, coap_pdu_code_t req_code, 881c87c5fbaSopenharmony_ci coap_pdu_type_t req_type, const coap_uri_t *uri) { 882c87c5fbaSopenharmony_ci 883c87c5fbaSopenharmony_ci coap_address_t dst; 884c87c5fbaSopenharmony_ci coap_uri_scheme_t scheme; 885c87c5fbaSopenharmony_ci coap_proto_t proto; 886c87c5fbaSopenharmony_ci static char client_sni[256]; 887c87c5fbaSopenharmony_ci coap_str_const_t server; 888c87c5fbaSopenharmony_ci uint16_t port; 889c87c5fbaSopenharmony_ci coap_addr_info_t *info_list = NULL; 890c87c5fbaSopenharmony_ci proxy_list_t *new_proxy_list; 891c87c5fbaSopenharmony_ci coap_context_t *context = coap_session_get_context(session); 892c87c5fbaSopenharmony_ci 893c87c5fbaSopenharmony_ci new_proxy_list = get_proxy_session(session, response, token, query, req_code, 894c87c5fbaSopenharmony_ci req_type); 895c87c5fbaSopenharmony_ci if (!new_proxy_list) 896c87c5fbaSopenharmony_ci return NULL; 897c87c5fbaSopenharmony_ci 898c87c5fbaSopenharmony_ci if (new_proxy_list->ongoing) 899c87c5fbaSopenharmony_ci return new_proxy_list->ongoing; 900c87c5fbaSopenharmony_ci 901c87c5fbaSopenharmony_ci if (proxy.host.length) { 902c87c5fbaSopenharmony_ci server = proxy.host; 903c87c5fbaSopenharmony_ci port = proxy.port; 904c87c5fbaSopenharmony_ci scheme = proxy.scheme; 905c87c5fbaSopenharmony_ci } else { 906c87c5fbaSopenharmony_ci server = uri->host; 907c87c5fbaSopenharmony_ci port = uri->port; 908c87c5fbaSopenharmony_ci scheme = uri->scheme; 909c87c5fbaSopenharmony_ci } 910c87c5fbaSopenharmony_ci 911c87c5fbaSopenharmony_ci /* resolve destination address where data should be sent */ 912c87c5fbaSopenharmony_ci info_list = coap_resolve_address_info(&server, port, port, port, port, 913c87c5fbaSopenharmony_ci 0, 914c87c5fbaSopenharmony_ci 1 << scheme, 915c87c5fbaSopenharmony_ci COAP_RESOLVE_TYPE_REMOTE); 916c87c5fbaSopenharmony_ci 917c87c5fbaSopenharmony_ci if (info_list == NULL) { 918c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_GATEWAY); 919c87c5fbaSopenharmony_ci remove_proxy_association(session, 0); 920c87c5fbaSopenharmony_ci return NULL; 921c87c5fbaSopenharmony_ci } 922c87c5fbaSopenharmony_ci proto = info_list->proto; 923c87c5fbaSopenharmony_ci memcpy(&dst, &info_list->addr, sizeof(dst)); 924c87c5fbaSopenharmony_ci coap_free_address_info(info_list); 925c87c5fbaSopenharmony_ci 926c87c5fbaSopenharmony_ci switch (scheme) { 927c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAP: 928c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAP_TCP: 929c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAP_WS: 930c87c5fbaSopenharmony_ci new_proxy_list->ongoing = 931c87c5fbaSopenharmony_ci coap_new_client_session(context, NULL, &dst, proto); 932c87c5fbaSopenharmony_ci break; 933c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAPS: 934c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAPS_TCP: 935c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_COAPS_WS: 936c87c5fbaSopenharmony_ci memset(client_sni, 0, sizeof(client_sni)); 937c87c5fbaSopenharmony_ci if ((server.length == 3 && memcmp(server.s, "::1", 3) != 0) || 938c87c5fbaSopenharmony_ci (server.length == 9 && memcmp(server.s, "127.0.0.1", 9) != 0)) 939c87c5fbaSopenharmony_ci memcpy(client_sni, server.s, min(server.length, sizeof(client_sni)-1)); 940c87c5fbaSopenharmony_ci else 941c87c5fbaSopenharmony_ci memcpy(client_sni, "localhost", 9); 942c87c5fbaSopenharmony_ci 943c87c5fbaSopenharmony_ci if (!key_defined) { 944c87c5fbaSopenharmony_ci /* Use our defined PKI certs (or NULL) */ 945c87c5fbaSopenharmony_ci coap_dtls_pki_t *dtls_pki = setup_pki(context, COAP_DTLS_ROLE_CLIENT, 946c87c5fbaSopenharmony_ci client_sni); 947c87c5fbaSopenharmony_ci new_proxy_list->ongoing = 948c87c5fbaSopenharmony_ci coap_new_client_session_pki(context, NULL, &dst, proto, dtls_pki); 949c87c5fbaSopenharmony_ci } else { 950c87c5fbaSopenharmony_ci /* Use our defined PSK */ 951c87c5fbaSopenharmony_ci coap_dtls_cpsk_t *dtls_cpsk = setup_cpsk(client_sni); 952c87c5fbaSopenharmony_ci 953c87c5fbaSopenharmony_ci new_proxy_list->ongoing = 954c87c5fbaSopenharmony_ci coap_new_client_session_psk2(context, NULL, &dst, proto, dtls_cpsk); 955c87c5fbaSopenharmony_ci } 956c87c5fbaSopenharmony_ci break; 957c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_HTTP: 958c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_HTTPS: 959c87c5fbaSopenharmony_ci case COAP_URI_SCHEME_LAST: 960c87c5fbaSopenharmony_ci default: 961c87c5fbaSopenharmony_ci assert(0); 962c87c5fbaSopenharmony_ci break; 963c87c5fbaSopenharmony_ci } 964c87c5fbaSopenharmony_ci if (new_proxy_list->ongoing == NULL) { 965c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); 966c87c5fbaSopenharmony_ci remove_proxy_association(session, 0); 967c87c5fbaSopenharmony_ci return NULL; 968c87c5fbaSopenharmony_ci } 969c87c5fbaSopenharmony_ci return new_proxy_list->ongoing; 970c87c5fbaSopenharmony_ci} 971c87c5fbaSopenharmony_ci 972c87c5fbaSopenharmony_cistatic void 973c87c5fbaSopenharmony_cirelease_proxy_body_data(coap_session_t *session COAP_UNUSED, 974c87c5fbaSopenharmony_ci void *app_ptr) { 975c87c5fbaSopenharmony_ci coap_delete_binary(app_ptr); 976c87c5fbaSopenharmony_ci} 977c87c5fbaSopenharmony_ci 978c87c5fbaSopenharmony_cistatic void 979c87c5fbaSopenharmony_cihnd_proxy_uri(coap_resource_t *resource COAP_UNUSED, 980c87c5fbaSopenharmony_ci coap_session_t *session, 981c87c5fbaSopenharmony_ci const coap_pdu_t *request, 982c87c5fbaSopenharmony_ci const coap_string_t *query, 983c87c5fbaSopenharmony_ci coap_pdu_t *response) { 984c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 985c87c5fbaSopenharmony_ci coap_opt_t *opt; 986c87c5fbaSopenharmony_ci coap_opt_t *proxy_uri; 987c87c5fbaSopenharmony_ci int proxy_scheme_option = 0; 988c87c5fbaSopenharmony_ci coap_uri_t uri; 989c87c5fbaSopenharmony_ci coap_string_t *uri_path = NULL; 990c87c5fbaSopenharmony_ci coap_string_t *uri_query = NULL; 991c87c5fbaSopenharmony_ci coap_session_t *ongoing = NULL; 992c87c5fbaSopenharmony_ci size_t size; 993c87c5fbaSopenharmony_ci size_t offset; 994c87c5fbaSopenharmony_ci size_t total; 995c87c5fbaSopenharmony_ci coap_binary_t *body_data = NULL; 996c87c5fbaSopenharmony_ci const uint8_t *data; 997c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 998c87c5fbaSopenharmony_ci coap_optlist_t *optlist = NULL; 999c87c5fbaSopenharmony_ci coap_opt_t *option; 1000c87c5fbaSopenharmony_ci#define BUFSIZE 100 1001c87c5fbaSopenharmony_ci unsigned char buf[BUFSIZE]; 1002c87c5fbaSopenharmony_ci coap_bin_const_t token = coap_pdu_get_token(request); 1003c87c5fbaSopenharmony_ci 1004c87c5fbaSopenharmony_ci memset(&uri, 0, sizeof(uri)); 1005c87c5fbaSopenharmony_ci /* 1006c87c5fbaSopenharmony_ci * See if Proxy-Scheme 1007c87c5fbaSopenharmony_ci */ 1008c87c5fbaSopenharmony_ci opt = coap_check_option(request, COAP_OPTION_PROXY_SCHEME, &opt_iter); 1009c87c5fbaSopenharmony_ci if (opt) { 1010c87c5fbaSopenharmony_ci if (!get_uri_proxy_scheme_info(request, opt, &uri, &uri_path, 1011c87c5fbaSopenharmony_ci &uri_query)) { 1012c87c5fbaSopenharmony_ci coap_pdu_set_code(response, 1013c87c5fbaSopenharmony_ci COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); 1014c87c5fbaSopenharmony_ci goto cleanup; 1015c87c5fbaSopenharmony_ci } 1016c87c5fbaSopenharmony_ci proxy_scheme_option = 1; 1017c87c5fbaSopenharmony_ci } 1018c87c5fbaSopenharmony_ci /* 1019c87c5fbaSopenharmony_ci * See if Proxy-Uri 1020c87c5fbaSopenharmony_ci */ 1021c87c5fbaSopenharmony_ci proxy_uri = coap_check_option(request, COAP_OPTION_PROXY_URI, &opt_iter); 1022c87c5fbaSopenharmony_ci if (proxy_uri) { 1023c87c5fbaSopenharmony_ci coap_log_info("Proxy URI '%.*s'\n", 1024c87c5fbaSopenharmony_ci coap_opt_length(proxy_uri), 1025c87c5fbaSopenharmony_ci (const char *)coap_opt_value(proxy_uri)); 1026c87c5fbaSopenharmony_ci if (coap_split_proxy_uri(coap_opt_value(proxy_uri), 1027c87c5fbaSopenharmony_ci coap_opt_length(proxy_uri), 1028c87c5fbaSopenharmony_ci &uri) < 0) { 1029c87c5fbaSopenharmony_ci /* Need to return a 5.05 RFC7252 Section 5.7.2 */ 1030c87c5fbaSopenharmony_ci coap_log_warn("Proxy URI not decodable\n"); 1031c87c5fbaSopenharmony_ci coap_pdu_set_code(response, 1032c87c5fbaSopenharmony_ci COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); 1033c87c5fbaSopenharmony_ci goto cleanup; 1034c87c5fbaSopenharmony_ci } 1035c87c5fbaSopenharmony_ci } 1036c87c5fbaSopenharmony_ci 1037c87c5fbaSopenharmony_ci if (!(proxy_scheme_option || proxy_uri)) { 1038c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 1039c87c5fbaSopenharmony_ci goto cleanup; 1040c87c5fbaSopenharmony_ci } 1041c87c5fbaSopenharmony_ci 1042c87c5fbaSopenharmony_ci if (uri.host.length == 0) { 1043c87c5fbaSopenharmony_ci /* Ongoing connection not well formed */ 1044c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); 1045c87c5fbaSopenharmony_ci goto cleanup; 1046c87c5fbaSopenharmony_ci } 1047c87c5fbaSopenharmony_ci 1048c87c5fbaSopenharmony_ci if (!verify_proxy_scheme_supported(uri.scheme)) { 1049c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); 1050c87c5fbaSopenharmony_ci goto cleanup; 1051c87c5fbaSopenharmony_ci } 1052c87c5fbaSopenharmony_ci 1053c87c5fbaSopenharmony_ci /* Handle the CoAP forwarding mapping */ 1054c87c5fbaSopenharmony_ci if (uri.scheme == COAP_URI_SCHEME_COAP || 1055c87c5fbaSopenharmony_ci uri.scheme == COAP_URI_SCHEME_COAPS || 1056c87c5fbaSopenharmony_ci uri.scheme == COAP_URI_SCHEME_COAP_TCP || 1057c87c5fbaSopenharmony_ci uri.scheme == COAP_URI_SCHEME_COAPS_TCP) { 1058c87c5fbaSopenharmony_ci coap_pdu_code_t req_code = coap_pdu_get_code(request); 1059c87c5fbaSopenharmony_ci coap_pdu_type_t req_type = coap_pdu_get_type(request); 1060c87c5fbaSopenharmony_ci 1061c87c5fbaSopenharmony_ci if (!get_proxy_session(session, response, &token, query, req_code, req_type)) 1062c87c5fbaSopenharmony_ci goto cleanup; 1063c87c5fbaSopenharmony_ci 1064c87c5fbaSopenharmony_ci if (coap_get_data_large(request, &size, &data, &offset, &total)) { 1065c87c5fbaSopenharmony_ci /* COAP_BLOCK_SINGLE_BODY is set, so single body should be given */ 1066c87c5fbaSopenharmony_ci assert(size == total); 1067c87c5fbaSopenharmony_ci body_data = coap_new_binary(total); 1068c87c5fbaSopenharmony_ci if (!body_data) { 1069c87c5fbaSopenharmony_ci coap_log_debug("body build memory error\n"); 1070c87c5fbaSopenharmony_ci goto cleanup; 1071c87c5fbaSopenharmony_ci } 1072c87c5fbaSopenharmony_ci memcpy(body_data->s, data, size); 1073c87c5fbaSopenharmony_ci data = body_data->s; 1074c87c5fbaSopenharmony_ci } 1075c87c5fbaSopenharmony_ci 1076c87c5fbaSopenharmony_ci /* Send data on (opening session if appropriate) */ 1077c87c5fbaSopenharmony_ci 1078c87c5fbaSopenharmony_ci ongoing = get_ongoing_proxy_session(session, response, &token, 1079c87c5fbaSopenharmony_ci query, req_code, req_type, &uri); 1080c87c5fbaSopenharmony_ci if (!ongoing) 1081c87c5fbaSopenharmony_ci goto cleanup; 1082c87c5fbaSopenharmony_ci /* 1083c87c5fbaSopenharmony_ci * Build up the ongoing PDU that we are going to send 1084c87c5fbaSopenharmony_ci */ 1085c87c5fbaSopenharmony_ci pdu = coap_pdu_init(req_type, req_code, 1086c87c5fbaSopenharmony_ci coap_new_message_id(ongoing), 1087c87c5fbaSopenharmony_ci coap_session_max_pdu_size(ongoing)); 1088c87c5fbaSopenharmony_ci if (!pdu) { 1089c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 1090c87c5fbaSopenharmony_ci goto cleanup; 1091c87c5fbaSopenharmony_ci } 1092c87c5fbaSopenharmony_ci 1093c87c5fbaSopenharmony_ci if (!coap_add_token(pdu, token.length, token.s)) { 1094c87c5fbaSopenharmony_ci coap_log_debug("cannot add token to proxy request\n"); 1095c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 1096c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 1097c87c5fbaSopenharmony_ci goto cleanup; 1098c87c5fbaSopenharmony_ci } 1099c87c5fbaSopenharmony_ci 1100c87c5fbaSopenharmony_ci if (proxy.host.length == 0) { 1101c87c5fbaSopenharmony_ci /* Use Uri-Path and Uri-Query - direct session */ 1102c87c5fbaSopenharmony_ci proxy_uri = NULL; 1103c87c5fbaSopenharmony_ci proxy_scheme_option = 0; 1104c87c5fbaSopenharmony_ci const coap_address_t *dst = coap_session_get_addr_remote(ongoing); 1105c87c5fbaSopenharmony_ci 1106c87c5fbaSopenharmony_ci if (coap_uri_into_options(&uri, dst, &optlist, 1, 1107c87c5fbaSopenharmony_ci buf, sizeof(buf)) < 0) { 1108c87c5fbaSopenharmony_ci coap_log_err("Failed to create options for URI\n"); 1109c87c5fbaSopenharmony_ci goto cleanup; 1110c87c5fbaSopenharmony_ci } 1111c87c5fbaSopenharmony_ci } 1112c87c5fbaSopenharmony_ci 1113c87c5fbaSopenharmony_ci /* Copy the remaining options across */ 1114c87c5fbaSopenharmony_ci coap_option_iterator_init(request, &opt_iter, COAP_OPT_ALL); 1115c87c5fbaSopenharmony_ci while ((option = coap_option_next(&opt_iter))) { 1116c87c5fbaSopenharmony_ci switch (opt_iter.number) { 1117c87c5fbaSopenharmony_ci case COAP_OPTION_PROXY_URI: 1118c87c5fbaSopenharmony_ci if (proxy_uri) { 1119c87c5fbaSopenharmony_ci /* Need to add back in */ 1120c87c5fbaSopenharmony_ci goto add_in; 1121c87c5fbaSopenharmony_ci } 1122c87c5fbaSopenharmony_ci break; 1123c87c5fbaSopenharmony_ci case COAP_OPTION_PROXY_SCHEME: 1124c87c5fbaSopenharmony_ci case COAP_OPTION_URI_PATH: 1125c87c5fbaSopenharmony_ci case COAP_OPTION_URI_PORT: 1126c87c5fbaSopenharmony_ci case COAP_OPTION_URI_QUERY: 1127c87c5fbaSopenharmony_ci if (proxy_scheme_option) { 1128c87c5fbaSopenharmony_ci /* Need to add back in */ 1129c87c5fbaSopenharmony_ci goto add_in; 1130c87c5fbaSopenharmony_ci } 1131c87c5fbaSopenharmony_ci break; 1132c87c5fbaSopenharmony_ci case COAP_OPTION_BLOCK1: 1133c87c5fbaSopenharmony_ci case COAP_OPTION_BLOCK2: 1134c87c5fbaSopenharmony_ci case COAP_OPTION_Q_BLOCK1: 1135c87c5fbaSopenharmony_ci case COAP_OPTION_Q_BLOCK2: 1136c87c5fbaSopenharmony_ci /* These are not passed on */ 1137c87c5fbaSopenharmony_ci break; 1138c87c5fbaSopenharmony_ci default: 1139c87c5fbaSopenharmony_ciadd_in: 1140c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, 1141c87c5fbaSopenharmony_ci coap_new_optlist(opt_iter.number, 1142c87c5fbaSopenharmony_ci coap_opt_length(option), 1143c87c5fbaSopenharmony_ci coap_opt_value(option))); 1144c87c5fbaSopenharmony_ci break; 1145c87c5fbaSopenharmony_ci } 1146c87c5fbaSopenharmony_ci } 1147c87c5fbaSopenharmony_ci 1148c87c5fbaSopenharmony_ci /* Update pdu with options */ 1149c87c5fbaSopenharmony_ci coap_add_optlist_pdu(pdu, &optlist); 1150c87c5fbaSopenharmony_ci coap_delete_optlist(optlist); 1151c87c5fbaSopenharmony_ci 1152c87c5fbaSopenharmony_ci if (size) { 1153c87c5fbaSopenharmony_ci if (!coap_add_data_large_request(ongoing, pdu, size, data, 1154c87c5fbaSopenharmony_ci release_proxy_body_data, body_data)) { 1155c87c5fbaSopenharmony_ci coap_log_debug("cannot add data to proxy request\n"); 1156c87c5fbaSopenharmony_ci } else { 1157c87c5fbaSopenharmony_ci body_data = NULL; 1158c87c5fbaSopenharmony_ci } 1159c87c5fbaSopenharmony_ci } 1160c87c5fbaSopenharmony_ci 1161c87c5fbaSopenharmony_ci if (coap_get_log_level() < COAP_LOG_DEBUG) 1162c87c5fbaSopenharmony_ci coap_show_pdu(COAP_LOG_INFO, pdu); 1163c87c5fbaSopenharmony_ci 1164c87c5fbaSopenharmony_ci coap_send(ongoing, pdu); 1165c87c5fbaSopenharmony_ci /* 1166c87c5fbaSopenharmony_ci * Do not update with response code (hence empty ACK) as will be sending 1167c87c5fbaSopenharmony_ci * separate response when response comes back from upstream server 1168c87c5fbaSopenharmony_ci */ 1169c87c5fbaSopenharmony_ci goto cleanup; 1170c87c5fbaSopenharmony_ci } else { 1171c87c5fbaSopenharmony_ci /* TODO http & https */ 1172c87c5fbaSopenharmony_ci coap_log_err("Proxy-Uri scheme %d unknown\n", uri.scheme); 1173c87c5fbaSopenharmony_ci } 1174c87c5fbaSopenharmony_cicleanup: 1175c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 1176c87c5fbaSopenharmony_ci coap_delete_string(uri_query); 1177c87c5fbaSopenharmony_ci coap_delete_binary(body_data); 1178c87c5fbaSopenharmony_ci} 1179c87c5fbaSopenharmony_ci 1180c87c5fbaSopenharmony_ci#endif /* SERVER_CAN_PROXY */ 1181c87c5fbaSopenharmony_ci 1182c87c5fbaSopenharmony_citypedef struct dynamic_resource_t { 1183c87c5fbaSopenharmony_ci coap_string_t *uri_path; 1184c87c5fbaSopenharmony_ci transient_value_t *value; 1185c87c5fbaSopenharmony_ci coap_resource_t *resource; 1186c87c5fbaSopenharmony_ci int created; 1187c87c5fbaSopenharmony_ci uint16_t media_type; 1188c87c5fbaSopenharmony_ci} dynamic_resource_t; 1189c87c5fbaSopenharmony_ci 1190c87c5fbaSopenharmony_cistatic int dynamic_count = 0; 1191c87c5fbaSopenharmony_cistatic dynamic_resource_t *dynamic_entry = NULL; 1192c87c5fbaSopenharmony_ci 1193c87c5fbaSopenharmony_ci/* 1194c87c5fbaSopenharmony_ci * Regular DELETE handler - used by resources created by the 1195c87c5fbaSopenharmony_ci * Unknown Resource PUT handler 1196c87c5fbaSopenharmony_ci */ 1197c87c5fbaSopenharmony_ci 1198c87c5fbaSopenharmony_cistatic void 1199c87c5fbaSopenharmony_cihnd_delete(coap_resource_t *resource, 1200c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 1201c87c5fbaSopenharmony_ci const coap_pdu_t *request, 1202c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 1203c87c5fbaSopenharmony_ci coap_pdu_t *response) { 1204c87c5fbaSopenharmony_ci int i; 1205c87c5fbaSopenharmony_ci coap_string_t *uri_path; 1206c87c5fbaSopenharmony_ci 1207c87c5fbaSopenharmony_ci /* get the uri_path */ 1208c87c5fbaSopenharmony_ci uri_path = coap_get_uri_path(request); 1209c87c5fbaSopenharmony_ci if (!uri_path) { 1210c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 1211c87c5fbaSopenharmony_ci return; 1212c87c5fbaSopenharmony_ci } 1213c87c5fbaSopenharmony_ci 1214c87c5fbaSopenharmony_ci for (i = 0; i < dynamic_count; i++) { 1215c87c5fbaSopenharmony_ci if (coap_string_equal(uri_path, dynamic_entry[i].uri_path)) { 1216c87c5fbaSopenharmony_ci /* Dynamic entry no longer required - delete it */ 1217c87c5fbaSopenharmony_ci release_resource_data(session, dynamic_entry[i].value); 1218c87c5fbaSopenharmony_ci coap_delete_string(dynamic_entry[i].uri_path); 1219c87c5fbaSopenharmony_ci if (dynamic_count-i > 1) { 1220c87c5fbaSopenharmony_ci memmove(&dynamic_entry[i], 1221c87c5fbaSopenharmony_ci &dynamic_entry[i+1], 1222c87c5fbaSopenharmony_ci (dynamic_count-i-1) * sizeof(dynamic_entry[0])); 1223c87c5fbaSopenharmony_ci } 1224c87c5fbaSopenharmony_ci dynamic_count--; 1225c87c5fbaSopenharmony_ci break; 1226c87c5fbaSopenharmony_ci } 1227c87c5fbaSopenharmony_ci } 1228c87c5fbaSopenharmony_ci 1229c87c5fbaSopenharmony_ci /* Dynamic resource no longer required - delete it */ 1230c87c5fbaSopenharmony_ci coap_delete_resource(NULL, resource); 1231c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 1232c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); 1233c87c5fbaSopenharmony_ci} 1234c87c5fbaSopenharmony_ci 1235c87c5fbaSopenharmony_ci/* 1236c87c5fbaSopenharmony_ci * Regular GET handler - used by resources created by the 1237c87c5fbaSopenharmony_ci * Unknown Resource PUT handler 1238c87c5fbaSopenharmony_ci */ 1239c87c5fbaSopenharmony_ci 1240c87c5fbaSopenharmony_cistatic void 1241c87c5fbaSopenharmony_cihnd_get(coap_resource_t *resource, 1242c87c5fbaSopenharmony_ci coap_session_t *session, 1243c87c5fbaSopenharmony_ci const coap_pdu_t *request, 1244c87c5fbaSopenharmony_ci const coap_string_t *query, 1245c87c5fbaSopenharmony_ci coap_pdu_t *response) { 1246c87c5fbaSopenharmony_ci coap_str_const_t *uri_path; 1247c87c5fbaSopenharmony_ci int i; 1248c87c5fbaSopenharmony_ci dynamic_resource_t *resource_entry = NULL; 1249c87c5fbaSopenharmony_ci coap_binary_t body; 1250c87c5fbaSopenharmony_ci /* 1251c87c5fbaSopenharmony_ci * request will be NULL if an Observe triggered request, so the uri_path, 1252c87c5fbaSopenharmony_ci * if needed, must be abstracted from the resource. 1253c87c5fbaSopenharmony_ci * The uri_path string is a const pointer 1254c87c5fbaSopenharmony_ci */ 1255c87c5fbaSopenharmony_ci 1256c87c5fbaSopenharmony_ci uri_path = coap_resource_get_uri_path(resource); 1257c87c5fbaSopenharmony_ci if (!uri_path) { 1258c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 1259c87c5fbaSopenharmony_ci return; 1260c87c5fbaSopenharmony_ci } 1261c87c5fbaSopenharmony_ci 1262c87c5fbaSopenharmony_ci for (i = 0; i < dynamic_count; i++) { 1263c87c5fbaSopenharmony_ci if (coap_string_equal(uri_path, dynamic_entry[i].uri_path)) { 1264c87c5fbaSopenharmony_ci break; 1265c87c5fbaSopenharmony_ci } 1266c87c5fbaSopenharmony_ci } 1267c87c5fbaSopenharmony_ci if (i == dynamic_count) { 1268c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 1269c87c5fbaSopenharmony_ci return; 1270c87c5fbaSopenharmony_ci } 1271c87c5fbaSopenharmony_ci 1272c87c5fbaSopenharmony_ci resource_entry = &dynamic_entry[i]; 1273c87c5fbaSopenharmony_ci 1274c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 1275c87c5fbaSopenharmony_ci body = reference_resource_data(resource_entry->value); 1276c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 1277c87c5fbaSopenharmony_ci query, resource_entry->media_type, -1, 0, 1278c87c5fbaSopenharmony_ci body.length, 1279c87c5fbaSopenharmony_ci body.s, 1280c87c5fbaSopenharmony_ci release_resource_data, resource_entry->value); 1281c87c5fbaSopenharmony_ci} 1282c87c5fbaSopenharmony_ci 1283c87c5fbaSopenharmony_ci/* 1284c87c5fbaSopenharmony_ci * Regular PUT or POST handler - used by resources created by the 1285c87c5fbaSopenharmony_ci * Unknown Resource PUT/POST handler 1286c87c5fbaSopenharmony_ci */ 1287c87c5fbaSopenharmony_ci 1288c87c5fbaSopenharmony_cistatic void 1289c87c5fbaSopenharmony_cihnd_put_post(coap_resource_t *resource, 1290c87c5fbaSopenharmony_ci coap_session_t *session, 1291c87c5fbaSopenharmony_ci const coap_pdu_t *request, 1292c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 1293c87c5fbaSopenharmony_ci coap_pdu_t *response) { 1294c87c5fbaSopenharmony_ci coap_string_t *uri_path; 1295c87c5fbaSopenharmony_ci int i; 1296c87c5fbaSopenharmony_ci size_t size; 1297c87c5fbaSopenharmony_ci const uint8_t *data; 1298c87c5fbaSopenharmony_ci size_t offset; 1299c87c5fbaSopenharmony_ci size_t total; 1300c87c5fbaSopenharmony_ci dynamic_resource_t *resource_entry = NULL; 1301c87c5fbaSopenharmony_ci unsigned char buf[6]; /* space to hold encoded/decoded uints */ 1302c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 1303c87c5fbaSopenharmony_ci coap_opt_t *option; 1304c87c5fbaSopenharmony_ci coap_binary_t *data_so_far; 1305c87c5fbaSopenharmony_ci transient_value_t *transient_value; 1306c87c5fbaSopenharmony_ci 1307c87c5fbaSopenharmony_ci /* get the uri_path */ 1308c87c5fbaSopenharmony_ci uri_path = coap_get_uri_path(request); 1309c87c5fbaSopenharmony_ci if (!uri_path) { 1310c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 1311c87c5fbaSopenharmony_ci return; 1312c87c5fbaSopenharmony_ci } 1313c87c5fbaSopenharmony_ci 1314c87c5fbaSopenharmony_ci /* 1315c87c5fbaSopenharmony_ci * Locate the correct dynamic block for this request 1316c87c5fbaSopenharmony_ci */ 1317c87c5fbaSopenharmony_ci for (i = 0; i < dynamic_count; i++) { 1318c87c5fbaSopenharmony_ci if (coap_string_equal(uri_path, dynamic_entry[i].uri_path)) { 1319c87c5fbaSopenharmony_ci break; 1320c87c5fbaSopenharmony_ci } 1321c87c5fbaSopenharmony_ci } 1322c87c5fbaSopenharmony_ci if (i == dynamic_count) { 1323c87c5fbaSopenharmony_ci if (dynamic_count >= support_dynamic) { 1324c87c5fbaSopenharmony_ci /* Should have been caught hnd_put_post_unknown() */ 1325c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_ACCEPTABLE); 1326c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 1327c87c5fbaSopenharmony_ci return; 1328c87c5fbaSopenharmony_ci } 1329c87c5fbaSopenharmony_ci dynamic_count++; 1330c87c5fbaSopenharmony_ci dynamic_entry = realloc(dynamic_entry, 1331c87c5fbaSopenharmony_ci dynamic_count * sizeof(dynamic_entry[0])); 1332c87c5fbaSopenharmony_ci if (dynamic_entry) { 1333c87c5fbaSopenharmony_ci dynamic_entry[i].uri_path = uri_path; 1334c87c5fbaSopenharmony_ci dynamic_entry[i].value = NULL; 1335c87c5fbaSopenharmony_ci dynamic_entry[i].resource = resource; 1336c87c5fbaSopenharmony_ci dynamic_entry[i].created = 1; 1337c87c5fbaSopenharmony_ci if ((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, 1338c87c5fbaSopenharmony_ci &opt_iter)) != NULL) { 1339c87c5fbaSopenharmony_ci dynamic_entry[i].media_type = 1340c87c5fbaSopenharmony_ci coap_decode_var_bytes(coap_opt_value(option), 1341c87c5fbaSopenharmony_ci coap_opt_length(option)); 1342c87c5fbaSopenharmony_ci } else { 1343c87c5fbaSopenharmony_ci dynamic_entry[i].media_type = COAP_MEDIATYPE_TEXT_PLAIN; 1344c87c5fbaSopenharmony_ci } 1345c87c5fbaSopenharmony_ci /* Store media type of new resource in ct. We can use buf here 1346c87c5fbaSopenharmony_ci * as coap_add_attr() will copy the passed string. */ 1347c87c5fbaSopenharmony_ci memset(buf, 0, sizeof(buf)); 1348c87c5fbaSopenharmony_ci snprintf((char *)buf, sizeof(buf), "%d", dynamic_entry[i].media_type); 1349c87c5fbaSopenharmony_ci /* ensure that buf is always zero-terminated */ 1350c87c5fbaSopenharmony_ci assert(buf[sizeof(buf) - 1] == '\0'); 1351c87c5fbaSopenharmony_ci buf[sizeof(buf) - 1] = '\0'; 1352c87c5fbaSopenharmony_ci coap_add_attr(resource, 1353c87c5fbaSopenharmony_ci coap_make_str_const("ct"), 1354c87c5fbaSopenharmony_ci coap_make_str_const((char *)buf), 1355c87c5fbaSopenharmony_ci 0); 1356c87c5fbaSopenharmony_ci } else { 1357c87c5fbaSopenharmony_ci dynamic_count--; 1358c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 1359c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 1360c87c5fbaSopenharmony_ci return; 1361c87c5fbaSopenharmony_ci } 1362c87c5fbaSopenharmony_ci } else { 1363c87c5fbaSopenharmony_ci /* Need to do this as coap_get_uri_path() created it */ 1364c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 1365c87c5fbaSopenharmony_ci } 1366c87c5fbaSopenharmony_ci 1367c87c5fbaSopenharmony_ci resource_entry = &dynamic_entry[i]; 1368c87c5fbaSopenharmony_ci 1369c87c5fbaSopenharmony_ci if (coap_get_data_large(request, &size, &data, &offset, &total) && 1370c87c5fbaSopenharmony_ci size != total) { 1371c87c5fbaSopenharmony_ci /* 1372c87c5fbaSopenharmony_ci * A part of the data has been received (COAP_BLOCK_SINGLE_BODY not set). 1373c87c5fbaSopenharmony_ci * However, total unfortunately is only an indication, so it is not safe to 1374c87c5fbaSopenharmony_ci * allocate a block based on total. As per 1375c87c5fbaSopenharmony_ci * https://rfc-editor.org/rfc/rfc7959#section-4 1376c87c5fbaSopenharmony_ci * o In a request carrying a Block1 Option, to indicate the current 1377c87c5fbaSopenharmony_ci * estimate the client has of the total size of the resource 1378c87c5fbaSopenharmony_ci * representation, measured in bytes ("size indication"). 1379c87c5fbaSopenharmony_ci * 1380c87c5fbaSopenharmony_ci * coap_cache_ignore_options() must have previously been called with at 1381c87c5fbaSopenharmony_ci * least COAP_OPTION_BLOCK1 set as the option value will change per block. 1382c87c5fbaSopenharmony_ci */ 1383c87c5fbaSopenharmony_ci coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session, 1384c87c5fbaSopenharmony_ci request, 1385c87c5fbaSopenharmony_ci COAP_CACHE_IS_SESSION_BASED); 1386c87c5fbaSopenharmony_ci 1387c87c5fbaSopenharmony_ci if (offset == 0) { 1388c87c5fbaSopenharmony_ci if (!cache_entry) { 1389c87c5fbaSopenharmony_ci cache_entry = coap_new_cache_entry(session, request, 1390c87c5fbaSopenharmony_ci COAP_CACHE_NOT_RECORD_PDU, 1391c87c5fbaSopenharmony_ci COAP_CACHE_IS_SESSION_BASED, 0); 1392c87c5fbaSopenharmony_ci } else { 1393c87c5fbaSopenharmony_ci data_so_far = coap_cache_get_app_data(cache_entry); 1394c87c5fbaSopenharmony_ci if (data_so_far) { 1395c87c5fbaSopenharmony_ci coap_delete_binary(data_so_far); 1396c87c5fbaSopenharmony_ci data_so_far = NULL; 1397c87c5fbaSopenharmony_ci } 1398c87c5fbaSopenharmony_ci coap_cache_set_app_data(cache_entry, NULL, NULL); 1399c87c5fbaSopenharmony_ci } 1400c87c5fbaSopenharmony_ci } 1401c87c5fbaSopenharmony_ci if (!cache_entry) { 1402c87c5fbaSopenharmony_ci if (offset == 0) { 1403c87c5fbaSopenharmony_ci coap_log_warn("Unable to create a new cache entry\n"); 1404c87c5fbaSopenharmony_ci } else { 1405c87c5fbaSopenharmony_ci coap_log_warn("No cache entry available for the non-first BLOCK\n"); 1406c87c5fbaSopenharmony_ci } 1407c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 1408c87c5fbaSopenharmony_ci return; 1409c87c5fbaSopenharmony_ci } 1410c87c5fbaSopenharmony_ci 1411c87c5fbaSopenharmony_ci if (size) { 1412c87c5fbaSopenharmony_ci /* Add in the new data to cache entry */ 1413c87c5fbaSopenharmony_ci data_so_far = coap_cache_get_app_data(cache_entry); 1414c87c5fbaSopenharmony_ci if (!data_so_far) { 1415c87c5fbaSopenharmony_ci data_so_far = coap_new_binary(size); 1416c87c5fbaSopenharmony_ci if (data_so_far) 1417c87c5fbaSopenharmony_ci memcpy(data_so_far->s, data, size); 1418c87c5fbaSopenharmony_ci } else { 1419c87c5fbaSopenharmony_ci /* Add in new block to end of current data */ 1420c87c5fbaSopenharmony_ci coap_binary_t *new = coap_resize_binary(data_so_far, offset + size); 1421c87c5fbaSopenharmony_ci 1422c87c5fbaSopenharmony_ci if (new) { 1423c87c5fbaSopenharmony_ci data_so_far = new; 1424c87c5fbaSopenharmony_ci memcpy(&data_so_far->s[offset], data, size); 1425c87c5fbaSopenharmony_ci } else { 1426c87c5fbaSopenharmony_ci /* Insufficient space to extend data_so_far */ 1427c87c5fbaSopenharmony_ci coap_delete_binary(data_so_far); 1428c87c5fbaSopenharmony_ci data_so_far = NULL; 1429c87c5fbaSopenharmony_ci } 1430c87c5fbaSopenharmony_ci } 1431c87c5fbaSopenharmony_ci /* Yes, data_so_far can be NULL */ 1432c87c5fbaSopenharmony_ci coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data); 1433c87c5fbaSopenharmony_ci } 1434c87c5fbaSopenharmony_ci if (offset + size == total) { 1435c87c5fbaSopenharmony_ci /* All the data is now in */ 1436c87c5fbaSopenharmony_ci data_so_far = coap_cache_get_app_data(cache_entry); 1437c87c5fbaSopenharmony_ci coap_cache_set_app_data(cache_entry, NULL, NULL); 1438c87c5fbaSopenharmony_ci } else { 1439c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE); 1440c87c5fbaSopenharmony_ci return; 1441c87c5fbaSopenharmony_ci } 1442c87c5fbaSopenharmony_ci } else { 1443c87c5fbaSopenharmony_ci /* single body of data received */ 1444c87c5fbaSopenharmony_ci data_so_far = coap_new_binary(size); 1445c87c5fbaSopenharmony_ci if (data_so_far && size) { 1446c87c5fbaSopenharmony_ci memcpy(data_so_far->s, data, size); 1447c87c5fbaSopenharmony_ci } 1448c87c5fbaSopenharmony_ci } 1449c87c5fbaSopenharmony_ci /* Need to de-reference as value may be in use elsewhere */ 1450c87c5fbaSopenharmony_ci release_resource_data(session, resource_entry->value); 1451c87c5fbaSopenharmony_ci resource_entry->value = NULL; 1452c87c5fbaSopenharmony_ci transient_value = alloc_resource_data(data_so_far); 1453c87c5fbaSopenharmony_ci if (!transient_value) { 1454c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 1455c87c5fbaSopenharmony_ci return; 1456c87c5fbaSopenharmony_ci } 1457c87c5fbaSopenharmony_ci resource_entry->value = transient_value; 1458c87c5fbaSopenharmony_ci 1459c87c5fbaSopenharmony_ci if (resource_entry->created) { 1460c87c5fbaSopenharmony_ci coap_pdu_code_t code = coap_pdu_get_code(request); 1461c87c5fbaSopenharmony_ci 1462c87c5fbaSopenharmony_ci resource_entry->created = 0; 1463c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); 1464c87c5fbaSopenharmony_ci if (code == COAP_REQUEST_CODE_POST) { 1465c87c5fbaSopenharmony_ci /* Add in Location-Path / Location-Query Options */ 1466c87c5fbaSopenharmony_ci coap_option_iterator_init(request, &opt_iter, COAP_OPT_ALL); 1467c87c5fbaSopenharmony_ci while ((option = coap_option_next(&opt_iter))) { 1468c87c5fbaSopenharmony_ci switch (opt_iter.number) { 1469c87c5fbaSopenharmony_ci case COAP_OPTION_URI_PATH: 1470c87c5fbaSopenharmony_ci if (!coap_add_option(response, COAP_OPTION_LOCATION_PATH, 1471c87c5fbaSopenharmony_ci coap_opt_length(option), 1472c87c5fbaSopenharmony_ci coap_opt_value(option))) 1473c87c5fbaSopenharmony_ci goto fail; 1474c87c5fbaSopenharmony_ci break; 1475c87c5fbaSopenharmony_ci case COAP_OPTION_URI_QUERY: 1476c87c5fbaSopenharmony_ci if (!coap_add_option(response, COAP_OPTION_LOCATION_QUERY, 1477c87c5fbaSopenharmony_ci coap_opt_length(option), 1478c87c5fbaSopenharmony_ci coap_opt_value(option))) 1479c87c5fbaSopenharmony_ci goto fail; 1480c87c5fbaSopenharmony_ci break; 1481c87c5fbaSopenharmony_ci default: 1482c87c5fbaSopenharmony_ci break; 1483c87c5fbaSopenharmony_ci } 1484c87c5fbaSopenharmony_ci } 1485c87c5fbaSopenharmony_ci } 1486c87c5fbaSopenharmony_ci } else { 1487c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); 1488c87c5fbaSopenharmony_ci coap_resource_notify_observers(resource_entry->resource, NULL); 1489c87c5fbaSopenharmony_ci } 1490c87c5fbaSopenharmony_ci 1491c87c5fbaSopenharmony_ci if (echo_back) { 1492c87c5fbaSopenharmony_ci coap_binary_t body; 1493c87c5fbaSopenharmony_ci 1494c87c5fbaSopenharmony_ci body = reference_resource_data(resource_entry->value); 1495c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 1496c87c5fbaSopenharmony_ci query, resource_entry->media_type, -1, 0, 1497c87c5fbaSopenharmony_ci body.length, 1498c87c5fbaSopenharmony_ci body.s, 1499c87c5fbaSopenharmony_ci release_resource_data, resource_entry->value); 1500c87c5fbaSopenharmony_ci } 1501c87c5fbaSopenharmony_ci return; 1502c87c5fbaSopenharmony_ci 1503c87c5fbaSopenharmony_cifail: 1504c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 1505c87c5fbaSopenharmony_ci return; 1506c87c5fbaSopenharmony_ci} 1507c87c5fbaSopenharmony_ci 1508c87c5fbaSopenharmony_ci/* 1509c87c5fbaSopenharmony_ci * Unknown Resource PUT handler 1510c87c5fbaSopenharmony_ci */ 1511c87c5fbaSopenharmony_ci 1512c87c5fbaSopenharmony_cistatic void 1513c87c5fbaSopenharmony_cihnd_put_post_unknown(coap_resource_t *resource COAP_UNUSED, 1514c87c5fbaSopenharmony_ci coap_session_t *session, 1515c87c5fbaSopenharmony_ci const coap_pdu_t *request, 1516c87c5fbaSopenharmony_ci const coap_string_t *query, 1517c87c5fbaSopenharmony_ci coap_pdu_t *response) { 1518c87c5fbaSopenharmony_ci coap_resource_t *r; 1519c87c5fbaSopenharmony_ci coap_string_t *uri_path; 1520c87c5fbaSopenharmony_ci 1521c87c5fbaSopenharmony_ci /* check if creating a new resource is allowed */ 1522c87c5fbaSopenharmony_ci if (dynamic_count >= support_dynamic) { 1523c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_ACCEPTABLE); 1524c87c5fbaSopenharmony_ci return; 1525c87c5fbaSopenharmony_ci } 1526c87c5fbaSopenharmony_ci 1527c87c5fbaSopenharmony_ci /* get the uri_path - will get used by coap_resource_init() */ 1528c87c5fbaSopenharmony_ci uri_path = coap_get_uri_path(request); 1529c87c5fbaSopenharmony_ci if (!uri_path) { 1530c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 1531c87c5fbaSopenharmony_ci return; 1532c87c5fbaSopenharmony_ci } 1533c87c5fbaSopenharmony_ci 1534c87c5fbaSopenharmony_ci /* 1535c87c5fbaSopenharmony_ci * Create a resource to handle the new URI 1536c87c5fbaSopenharmony_ci * uri_path will get deleted when the resource is removed 1537c87c5fbaSopenharmony_ci */ 1538c87c5fbaSopenharmony_ci r = coap_resource_init((coap_str_const_t *)uri_path, 1539c87c5fbaSopenharmony_ci COAP_RESOURCE_FLAGS_RELEASE_URI | resource_flags); 1540c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Dynamic\""), 0); 1541c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_post); 1542c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_POST, hnd_put_post); 1543c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete); 1544c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_FETCH, hnd_get); 1545c87c5fbaSopenharmony_ci /* We possibly want to Observe the GETs */ 1546c87c5fbaSopenharmony_ci coap_resource_set_get_observable(r, 1); 1547c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get); 1548c87c5fbaSopenharmony_ci coap_add_resource(coap_session_get_context(session), r); 1549c87c5fbaSopenharmony_ci 1550c87c5fbaSopenharmony_ci /* Do the PUT/POST for this first call */ 1551c87c5fbaSopenharmony_ci hnd_put_post(r, session, request, query, response); 1552c87c5fbaSopenharmony_ci} 1553c87c5fbaSopenharmony_ci 1554c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 1555c87c5fbaSopenharmony_cistatic int 1556c87c5fbaSopenharmony_ciproxy_event_handler(coap_session_t *session, 1557c87c5fbaSopenharmony_ci coap_event_t event) { 1558c87c5fbaSopenharmony_ci 1559c87c5fbaSopenharmony_ci switch (event) { 1560c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_CLOSED: 1561c87c5fbaSopenharmony_ci case COAP_EVENT_TCP_CLOSED: 1562c87c5fbaSopenharmony_ci case COAP_EVENT_SESSION_CLOSED: 1563c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_DECRYPTION_FAILURE: 1564c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_NOT_ENABLED: 1565c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD: 1566c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_NO_SECURITY: 1567c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_INTERNAL_ERROR: 1568c87c5fbaSopenharmony_ci case COAP_EVENT_OSCORE_DECODE_ERROR: 1569c87c5fbaSopenharmony_ci case COAP_EVENT_WS_PACKET_SIZE: 1570c87c5fbaSopenharmony_ci case COAP_EVENT_WS_CLOSED: 1571c87c5fbaSopenharmony_ci /* Need to remove any proxy associations */ 1572c87c5fbaSopenharmony_ci remove_proxy_association(session, 0); 1573c87c5fbaSopenharmony_ci break; 1574c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_CONNECTED: 1575c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_RENEGOTIATE: 1576c87c5fbaSopenharmony_ci case COAP_EVENT_DTLS_ERROR: 1577c87c5fbaSopenharmony_ci case COAP_EVENT_TCP_CONNECTED: 1578c87c5fbaSopenharmony_ci case COAP_EVENT_TCP_FAILED: 1579c87c5fbaSopenharmony_ci case COAP_EVENT_SESSION_CONNECTED: 1580c87c5fbaSopenharmony_ci case COAP_EVENT_SESSION_FAILED: 1581c87c5fbaSopenharmony_ci case COAP_EVENT_PARTIAL_BLOCK: 1582c87c5fbaSopenharmony_ci case COAP_EVENT_XMIT_BLOCK_FAIL: 1583c87c5fbaSopenharmony_ci case COAP_EVENT_SERVER_SESSION_NEW: 1584c87c5fbaSopenharmony_ci case COAP_EVENT_SERVER_SESSION_DEL: 1585c87c5fbaSopenharmony_ci case COAP_EVENT_BAD_PACKET: 1586c87c5fbaSopenharmony_ci case COAP_EVENT_MSG_RETRANSMITTED: 1587c87c5fbaSopenharmony_ci case COAP_EVENT_WS_CONNECTED: 1588c87c5fbaSopenharmony_ci case COAP_EVENT_KEEPALIVE_FAILURE: 1589c87c5fbaSopenharmony_ci default: 1590c87c5fbaSopenharmony_ci break; 1591c87c5fbaSopenharmony_ci } 1592c87c5fbaSopenharmony_ci return 0; 1593c87c5fbaSopenharmony_ci} 1594c87c5fbaSopenharmony_ci 1595c87c5fbaSopenharmony_cistatic coap_response_t 1596c87c5fbaSopenharmony_ciproxy_response_handler(coap_session_t *session, 1597c87c5fbaSopenharmony_ci const coap_pdu_t *sent COAP_UNUSED, 1598c87c5fbaSopenharmony_ci const coap_pdu_t *received, 1599c87c5fbaSopenharmony_ci const coap_mid_t id COAP_UNUSED) { 1600c87c5fbaSopenharmony_ci 1601c87c5fbaSopenharmony_ci coap_pdu_t *pdu = NULL; 1602c87c5fbaSopenharmony_ci coap_session_t *incoming = NULL; 1603c87c5fbaSopenharmony_ci size_t i; 1604c87c5fbaSopenharmony_ci size_t size; 1605c87c5fbaSopenharmony_ci const uint8_t *data; 1606c87c5fbaSopenharmony_ci coap_optlist_t *optlist = NULL; 1607c87c5fbaSopenharmony_ci coap_opt_t *option; 1608c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 1609c87c5fbaSopenharmony_ci size_t offset; 1610c87c5fbaSopenharmony_ci size_t total; 1611c87c5fbaSopenharmony_ci proxy_list_t *proxy_entry = NULL; 1612c87c5fbaSopenharmony_ci uint16_t media_type = COAP_MEDIATYPE_TEXT_PLAIN; 1613c87c5fbaSopenharmony_ci int maxage = -1; 1614c87c5fbaSopenharmony_ci uint64_t etag = 0; 1615c87c5fbaSopenharmony_ci coap_pdu_code_t rcv_code = coap_pdu_get_code(received); 1616c87c5fbaSopenharmony_ci coap_bin_const_t rcv_token = coap_pdu_get_token(received); 1617c87c5fbaSopenharmony_ci coap_binary_t *body_data = NULL; 1618c87c5fbaSopenharmony_ci 1619c87c5fbaSopenharmony_ci for (i = 0; i < proxy_list_count; i++) { 1620c87c5fbaSopenharmony_ci if (proxy_list[i].ongoing == session) { 1621c87c5fbaSopenharmony_ci proxy_entry = &proxy_list[i]; 1622c87c5fbaSopenharmony_ci incoming = proxy_entry->incoming; 1623c87c5fbaSopenharmony_ci break; 1624c87c5fbaSopenharmony_ci } 1625c87c5fbaSopenharmony_ci } 1626c87c5fbaSopenharmony_ci if (i == proxy_list_count) { 1627c87c5fbaSopenharmony_ci coap_log_debug("Unknown proxy ongoing session response received\n"); 1628c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 1629c87c5fbaSopenharmony_ci } 1630c87c5fbaSopenharmony_ci 1631c87c5fbaSopenharmony_ci coap_log_debug("** process upstream incoming %d.%02d response:\n", 1632c87c5fbaSopenharmony_ci COAP_RESPONSE_CLASS(rcv_code), rcv_code & 0x1F); 1633c87c5fbaSopenharmony_ci if (coap_get_log_level() < COAP_LOG_DEBUG) 1634c87c5fbaSopenharmony_ci coap_show_pdu(COAP_LOG_INFO, received); 1635c87c5fbaSopenharmony_ci 1636c87c5fbaSopenharmony_ci if (coap_get_data_large(received, &size, &data, &offset, &total)) { 1637c87c5fbaSopenharmony_ci /* COAP_BLOCK_SINGLE_BODY is set, so single body should be given */ 1638c87c5fbaSopenharmony_ci assert(size == total); 1639c87c5fbaSopenharmony_ci body_data = coap_new_binary(total); 1640c87c5fbaSopenharmony_ci if (!body_data) { 1641c87c5fbaSopenharmony_ci coap_log_debug("body build memory error\n"); 1642c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 1643c87c5fbaSopenharmony_ci } 1644c87c5fbaSopenharmony_ci memcpy(body_data->s, data, size); 1645c87c5fbaSopenharmony_ci data = body_data->s; 1646c87c5fbaSopenharmony_ci } 1647c87c5fbaSopenharmony_ci 1648c87c5fbaSopenharmony_ci /* 1649c87c5fbaSopenharmony_ci * Build up the ongoing PDU that we are going to send to proxy originator 1650c87c5fbaSopenharmony_ci * as separate response 1651c87c5fbaSopenharmony_ci */ 1652c87c5fbaSopenharmony_ci pdu = coap_pdu_init(proxy_entry->req_type, rcv_code, 1653c87c5fbaSopenharmony_ci coap_new_message_id(incoming), 1654c87c5fbaSopenharmony_ci coap_session_max_pdu_size(incoming)); 1655c87c5fbaSopenharmony_ci if (!pdu) { 1656c87c5fbaSopenharmony_ci coap_log_debug("Failed to create ongoing proxy response PDU\n"); 1657c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 1658c87c5fbaSopenharmony_ci } 1659c87c5fbaSopenharmony_ci 1660c87c5fbaSopenharmony_ci if (!coap_add_token(pdu, rcv_token.length, rcv_token.s)) { 1661c87c5fbaSopenharmony_ci coap_log_debug("cannot add token to ongoing proxy response PDU\n"); 1662c87c5fbaSopenharmony_ci } 1663c87c5fbaSopenharmony_ci 1664c87c5fbaSopenharmony_ci /* 1665c87c5fbaSopenharmony_ci * Copy the options across, skipping those needed for 1666c87c5fbaSopenharmony_ci * coap_add_data_response_large() 1667c87c5fbaSopenharmony_ci */ 1668c87c5fbaSopenharmony_ci coap_option_iterator_init(received, &opt_iter, COAP_OPT_ALL); 1669c87c5fbaSopenharmony_ci while ((option = coap_option_next(&opt_iter))) { 1670c87c5fbaSopenharmony_ci switch (opt_iter.number) { 1671c87c5fbaSopenharmony_ci case COAP_OPTION_CONTENT_FORMAT: 1672c87c5fbaSopenharmony_ci media_type = coap_decode_var_bytes(coap_opt_value(option), 1673c87c5fbaSopenharmony_ci coap_opt_length(option)); 1674c87c5fbaSopenharmony_ci break; 1675c87c5fbaSopenharmony_ci case COAP_OPTION_MAXAGE: 1676c87c5fbaSopenharmony_ci maxage = coap_decode_var_bytes(coap_opt_value(option), 1677c87c5fbaSopenharmony_ci coap_opt_length(option)); 1678c87c5fbaSopenharmony_ci break; 1679c87c5fbaSopenharmony_ci case COAP_OPTION_ETAG: 1680c87c5fbaSopenharmony_ci etag = coap_decode_var_bytes8(coap_opt_value(option), 1681c87c5fbaSopenharmony_ci coap_opt_length(option)); 1682c87c5fbaSopenharmony_ci break; 1683c87c5fbaSopenharmony_ci case COAP_OPTION_BLOCK2: 1684c87c5fbaSopenharmony_ci case COAP_OPTION_Q_BLOCK2: 1685c87c5fbaSopenharmony_ci case COAP_OPTION_SIZE2: 1686c87c5fbaSopenharmony_ci break; 1687c87c5fbaSopenharmony_ci default: 1688c87c5fbaSopenharmony_ci coap_insert_optlist(&optlist, 1689c87c5fbaSopenharmony_ci coap_new_optlist(opt_iter.number, 1690c87c5fbaSopenharmony_ci coap_opt_length(option), 1691c87c5fbaSopenharmony_ci coap_opt_value(option))); 1692c87c5fbaSopenharmony_ci break; 1693c87c5fbaSopenharmony_ci } 1694c87c5fbaSopenharmony_ci } 1695c87c5fbaSopenharmony_ci coap_add_optlist_pdu(pdu, &optlist); 1696c87c5fbaSopenharmony_ci coap_delete_optlist(optlist); 1697c87c5fbaSopenharmony_ci 1698c87c5fbaSopenharmony_ci if (size > 0) { 1699c87c5fbaSopenharmony_ci coap_pdu_t *dummy_pdu = coap_pdu_init(proxy_entry->req_type, 1700c87c5fbaSopenharmony_ci proxy_entry->req_code, 0, 1701c87c5fbaSopenharmony_ci coap_session_max_pdu_size(incoming)); 1702c87c5fbaSopenharmony_ci 1703c87c5fbaSopenharmony_ci coap_add_data_large_response(proxy_resource, incoming, dummy_pdu, pdu, 1704c87c5fbaSopenharmony_ci proxy_entry->query, 1705c87c5fbaSopenharmony_ci media_type, maxage, etag, size, data, 1706c87c5fbaSopenharmony_ci release_proxy_body_data, 1707c87c5fbaSopenharmony_ci body_data); 1708c87c5fbaSopenharmony_ci coap_delete_pdu(dummy_pdu); 1709c87c5fbaSopenharmony_ci } 1710c87c5fbaSopenharmony_ci 1711c87c5fbaSopenharmony_ci if (coap_get_log_level() < COAP_LOG_DEBUG) 1712c87c5fbaSopenharmony_ci coap_show_pdu(COAP_LOG_INFO, pdu); 1713c87c5fbaSopenharmony_ci 1714c87c5fbaSopenharmony_ci coap_send(incoming, pdu); 1715c87c5fbaSopenharmony_ci return COAP_RESPONSE_OK; 1716c87c5fbaSopenharmony_ci} 1717c87c5fbaSopenharmony_ci 1718c87c5fbaSopenharmony_cistatic void 1719c87c5fbaSopenharmony_ciproxy_nack_handler(coap_session_t *session, 1720c87c5fbaSopenharmony_ci const coap_pdu_t *sent COAP_UNUSED, 1721c87c5fbaSopenharmony_ci const coap_nack_reason_t reason, 1722c87c5fbaSopenharmony_ci const coap_mid_t mid COAP_UNUSED) { 1723c87c5fbaSopenharmony_ci 1724c87c5fbaSopenharmony_ci switch (reason) { 1725c87c5fbaSopenharmony_ci case COAP_NACK_TOO_MANY_RETRIES: 1726c87c5fbaSopenharmony_ci case COAP_NACK_NOT_DELIVERABLE: 1727c87c5fbaSopenharmony_ci case COAP_NACK_RST: 1728c87c5fbaSopenharmony_ci case COAP_NACK_TLS_FAILED: 1729c87c5fbaSopenharmony_ci case COAP_NACK_WS_FAILED: 1730c87c5fbaSopenharmony_ci case COAP_NACK_TLS_LAYER_FAILED: 1731c87c5fbaSopenharmony_ci case COAP_NACK_WS_LAYER_FAILED: 1732c87c5fbaSopenharmony_ci /* Need to remove any proxy associations */ 1733c87c5fbaSopenharmony_ci remove_proxy_association(session, 1); 1734c87c5fbaSopenharmony_ci break; 1735c87c5fbaSopenharmony_ci case COAP_NACK_ICMP_ISSUE: 1736c87c5fbaSopenharmony_ci case COAP_NACK_BAD_RESPONSE: 1737c87c5fbaSopenharmony_ci default: 1738c87c5fbaSopenharmony_ci break; 1739c87c5fbaSopenharmony_ci } 1740c87c5fbaSopenharmony_ci return; 1741c87c5fbaSopenharmony_ci} 1742c87c5fbaSopenharmony_ci 1743c87c5fbaSopenharmony_ci#endif /* SERVER_CAN_PROXY */ 1744c87c5fbaSopenharmony_ci 1745c87c5fbaSopenharmony_cistatic void 1746c87c5fbaSopenharmony_ciinit_resources(coap_context_t *ctx) { 1747c87c5fbaSopenharmony_ci coap_resource_t *r; 1748c87c5fbaSopenharmony_ci 1749c87c5fbaSopenharmony_ci r = coap_resource_init(NULL, COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT); 1750c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_index); 1751c87c5fbaSopenharmony_ci 1752c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 1753c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"General Info\""), 0); 1754c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 1755c87c5fbaSopenharmony_ci 1756c87c5fbaSopenharmony_ci /* store clock base to use in /time */ 1757c87c5fbaSopenharmony_ci my_clock_base = clock_offset; 1758c87c5fbaSopenharmony_ci 1759c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("time"), resource_flags); 1760c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_fetch_time); 1761c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_FETCH, hnd_get_fetch_time); 1762c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_time); 1763c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); 1764c87c5fbaSopenharmony_ci coap_resource_set_get_observable(r, 1); 1765c87c5fbaSopenharmony_ci 1766c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 1767c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Internal Clock\""), 0); 1768c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"ticks\""), 0); 1769c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), 0); 1770c87c5fbaSopenharmony_ci 1771c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 1772c87c5fbaSopenharmony_ci time_resource = r; 1773c87c5fbaSopenharmony_ci 1774c87c5fbaSopenharmony_ci if (support_dynamic > 0) { 1775c87c5fbaSopenharmony_ci /* Create a resource to handle PUTs to unknown URIs */ 1776c87c5fbaSopenharmony_ci r = coap_resource_unknown_init2(hnd_put_post_unknown, 0); 1777c87c5fbaSopenharmony_ci /* Add in handling POST as well */ 1778c87c5fbaSopenharmony_ci coap_register_handler(r, COAP_REQUEST_POST, hnd_put_post_unknown); 1779c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 1780c87c5fbaSopenharmony_ci } 1781c87c5fbaSopenharmony_ci 1782c87c5fbaSopenharmony_ci if (coap_async_is_supported()) { 1783c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("async"), 1784c87c5fbaSopenharmony_ci resource_flags | 1785c87c5fbaSopenharmony_ci COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT | 1786c87c5fbaSopenharmony_ci COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS); 1787c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_async); 1788c87c5fbaSopenharmony_ci 1789c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 1790c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 1791c87c5fbaSopenharmony_ci } 1792c87c5fbaSopenharmony_ci 1793c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("example_data"), resource_flags); 1794c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_example_data); 1795c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_example_data); 1796c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_FETCH, hnd_get_example_data); 1797c87c5fbaSopenharmony_ci coap_resource_set_get_observable(r, 1); 1798c87c5fbaSopenharmony_ci 1799c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 1800c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Example Data\""), 0); 1801c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 1802c87c5fbaSopenharmony_ci 1803c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 1804c87c5fbaSopenharmony_ci if (proxy_host_name_count) { 1805c87c5fbaSopenharmony_ci r = coap_resource_proxy_uri_init2(hnd_proxy_uri, proxy_host_name_count, 1806c87c5fbaSopenharmony_ci proxy_host_name_list, 0); 1807c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 1808c87c5fbaSopenharmony_ci coap_register_event_handler(ctx, proxy_event_handler); 1809c87c5fbaSopenharmony_ci coap_register_response_handler(ctx, proxy_response_handler); 1810c87c5fbaSopenharmony_ci coap_register_nack_handler(ctx, proxy_nack_handler); 1811c87c5fbaSopenharmony_ci proxy_resource = r; 1812c87c5fbaSopenharmony_ci } 1813c87c5fbaSopenharmony_ci#endif /* SERVER_CAN_PROXY */ 1814c87c5fbaSopenharmony_ci} 1815c87c5fbaSopenharmony_ci 1816c87c5fbaSopenharmony_cistatic int 1817c87c5fbaSopenharmony_civerify_cn_callback(const char *cn, 1818c87c5fbaSopenharmony_ci const uint8_t *asn1_public_cert COAP_UNUSED, 1819c87c5fbaSopenharmony_ci size_t asn1_length COAP_UNUSED, 1820c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 1821c87c5fbaSopenharmony_ci unsigned depth, 1822c87c5fbaSopenharmony_ci int validated COAP_UNUSED, 1823c87c5fbaSopenharmony_ci void *arg) { 1824c87c5fbaSopenharmony_ci union { 1825c87c5fbaSopenharmony_ci coap_dtls_role_t r; 1826c87c5fbaSopenharmony_ci void *v; 1827c87c5fbaSopenharmony_ci } role = { .v = arg }; 1828c87c5fbaSopenharmony_ci 1829c87c5fbaSopenharmony_ci coap_log_info("CN '%s' presented by %s (%s)\n", 1830c87c5fbaSopenharmony_ci cn, role.r == COAP_DTLS_ROLE_SERVER ? "client" : "server", 1831c87c5fbaSopenharmony_ci depth ? "CA" : "Certificate"); 1832c87c5fbaSopenharmony_ci return 1; 1833c87c5fbaSopenharmony_ci} 1834c87c5fbaSopenharmony_ci 1835c87c5fbaSopenharmony_cistatic uint8_t * 1836c87c5fbaSopenharmony_ciread_file_mem(const char *file, size_t *length) { 1837c87c5fbaSopenharmony_ci FILE *f; 1838c87c5fbaSopenharmony_ci uint8_t *buf; 1839c87c5fbaSopenharmony_ci struct stat statbuf; 1840c87c5fbaSopenharmony_ci 1841c87c5fbaSopenharmony_ci *length = 0; 1842c87c5fbaSopenharmony_ci if (!file || !(f = fopen(file, "r"))) 1843c87c5fbaSopenharmony_ci return NULL; 1844c87c5fbaSopenharmony_ci 1845c87c5fbaSopenharmony_ci if (fstat(fileno(f), &statbuf) == -1) { 1846c87c5fbaSopenharmony_ci fclose(f); 1847c87c5fbaSopenharmony_ci return NULL; 1848c87c5fbaSopenharmony_ci } 1849c87c5fbaSopenharmony_ci 1850c87c5fbaSopenharmony_ci buf = coap_malloc(statbuf.st_size+1); 1851c87c5fbaSopenharmony_ci if (!buf) { 1852c87c5fbaSopenharmony_ci fclose(f); 1853c87c5fbaSopenharmony_ci return NULL; 1854c87c5fbaSopenharmony_ci } 1855c87c5fbaSopenharmony_ci 1856c87c5fbaSopenharmony_ci if (fread(buf, 1, statbuf.st_size, f) != (size_t)statbuf.st_size) { 1857c87c5fbaSopenharmony_ci fclose(f); 1858c87c5fbaSopenharmony_ci coap_free(buf); 1859c87c5fbaSopenharmony_ci return NULL; 1860c87c5fbaSopenharmony_ci } 1861c87c5fbaSopenharmony_ci buf[statbuf.st_size] = '\000'; 1862c87c5fbaSopenharmony_ci *length = (size_t)(statbuf.st_size + 1); 1863c87c5fbaSopenharmony_ci fclose(f); 1864c87c5fbaSopenharmony_ci return buf; 1865c87c5fbaSopenharmony_ci} 1866c87c5fbaSopenharmony_ci 1867c87c5fbaSopenharmony_cistatic void 1868c87c5fbaSopenharmony_ciupdate_pki_key(coap_dtls_key_t *dtls_key, const char *key_name, 1869c87c5fbaSopenharmony_ci const char *cert_name, const char *ca_name) { 1870c87c5fbaSopenharmony_ci memset(dtls_key, 0, sizeof(*dtls_key)); 1871c87c5fbaSopenharmony_ci if ((key_name && strncasecmp(key_name, "pkcs11:", 7) == 0) || 1872c87c5fbaSopenharmony_ci (cert_name && strncasecmp(cert_name, "pkcs11:", 7) == 0) || 1873c87c5fbaSopenharmony_ci (ca_name && strncasecmp(ca_name, "pkcs11:", 7) == 0)) { 1874c87c5fbaSopenharmony_ci dtls_key->key_type = COAP_PKI_KEY_PKCS11; 1875c87c5fbaSopenharmony_ci dtls_key->key.pkcs11.public_cert = cert_name; 1876c87c5fbaSopenharmony_ci dtls_key->key.pkcs11.private_key = key_name ? key_name : cert_name; 1877c87c5fbaSopenharmony_ci dtls_key->key.pkcs11.ca = ca_name; 1878c87c5fbaSopenharmony_ci dtls_key->key.pkcs11.user_pin = pkcs11_pin; 1879c87c5fbaSopenharmony_ci } else if (!use_pem_buf && !is_rpk_not_cert) { 1880c87c5fbaSopenharmony_ci dtls_key->key_type = COAP_PKI_KEY_PEM; 1881c87c5fbaSopenharmony_ci dtls_key->key.pem.public_cert = cert_name; 1882c87c5fbaSopenharmony_ci dtls_key->key.pem.private_key = key_name ? key_name : cert_name; 1883c87c5fbaSopenharmony_ci dtls_key->key.pem.ca_file = ca_name; 1884c87c5fbaSopenharmony_ci } else { 1885c87c5fbaSopenharmony_ci /* Map file into memory */ 1886c87c5fbaSopenharmony_ci coap_free(ca_mem); 1887c87c5fbaSopenharmony_ci coap_free(cert_mem); 1888c87c5fbaSopenharmony_ci coap_free(key_mem); 1889c87c5fbaSopenharmony_ci ca_mem = read_file_mem(ca_name, &ca_mem_len); 1890c87c5fbaSopenharmony_ci cert_mem = read_file_mem(cert_name, &cert_mem_len); 1891c87c5fbaSopenharmony_ci key_mem = read_file_mem(key_name, &key_mem_len); 1892c87c5fbaSopenharmony_ci 1893c87c5fbaSopenharmony_ci dtls_key->key_type = COAP_PKI_KEY_PEM_BUF; 1894c87c5fbaSopenharmony_ci dtls_key->key.pem_buf.ca_cert = ca_mem; 1895c87c5fbaSopenharmony_ci dtls_key->key.pem_buf.public_cert = cert_mem; 1896c87c5fbaSopenharmony_ci dtls_key->key.pem_buf.private_key = key_mem ? key_mem : cert_mem; 1897c87c5fbaSopenharmony_ci dtls_key->key.pem_buf.ca_cert_len = ca_mem_len; 1898c87c5fbaSopenharmony_ci dtls_key->key.pem_buf.public_cert_len = cert_mem_len; 1899c87c5fbaSopenharmony_ci dtls_key->key.pem_buf.private_key_len = key_mem ? 1900c87c5fbaSopenharmony_ci key_mem_len : cert_mem_len; 1901c87c5fbaSopenharmony_ci } 1902c87c5fbaSopenharmony_ci} 1903c87c5fbaSopenharmony_ci 1904c87c5fbaSopenharmony_cistatic coap_dtls_key_t * 1905c87c5fbaSopenharmony_civerify_pki_sni_callback(const char *sni, 1906c87c5fbaSopenharmony_ci void *arg COAP_UNUSED) { 1907c87c5fbaSopenharmony_ci static coap_dtls_key_t dtls_key; 1908c87c5fbaSopenharmony_ci 1909c87c5fbaSopenharmony_ci update_pki_key(&dtls_key, key_file, cert_file, ca_file); 1910c87c5fbaSopenharmony_ci 1911c87c5fbaSopenharmony_ci if (sni[0]) { 1912c87c5fbaSopenharmony_ci size_t i; 1913c87c5fbaSopenharmony_ci coap_log_info("SNI '%s' requested\n", sni); 1914c87c5fbaSopenharmony_ci for (i = 0; i < valid_pki_snis.count; i++) { 1915c87c5fbaSopenharmony_ci /* Test for SNI to change cert + ca */ 1916c87c5fbaSopenharmony_ci if (strcasecmp(sni, valid_pki_snis.pki_sni_list[i].sni_match) == 0) { 1917c87c5fbaSopenharmony_ci coap_log_info("Switching to using cert '%s' + ca '%s'\n", 1918c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[i].new_cert, 1919c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[i].new_ca); 1920c87c5fbaSopenharmony_ci update_pki_key(&dtls_key, valid_pki_snis.pki_sni_list[i].new_cert, 1921c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[i].new_cert, 1922c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[i].new_ca); 1923c87c5fbaSopenharmony_ci break; 1924c87c5fbaSopenharmony_ci } 1925c87c5fbaSopenharmony_ci } 1926c87c5fbaSopenharmony_ci } else { 1927c87c5fbaSopenharmony_ci coap_log_debug("SNI not requested\n"); 1928c87c5fbaSopenharmony_ci } 1929c87c5fbaSopenharmony_ci return &dtls_key; 1930c87c5fbaSopenharmony_ci} 1931c87c5fbaSopenharmony_ci 1932c87c5fbaSopenharmony_cistatic const coap_dtls_spsk_info_t * 1933c87c5fbaSopenharmony_civerify_psk_sni_callback(const char *sni, 1934c87c5fbaSopenharmony_ci coap_session_t *c_session COAP_UNUSED, 1935c87c5fbaSopenharmony_ci void *arg COAP_UNUSED) { 1936c87c5fbaSopenharmony_ci static coap_dtls_spsk_info_t psk_info; 1937c87c5fbaSopenharmony_ci 1938c87c5fbaSopenharmony_ci /* Preset with the defined keys */ 1939c87c5fbaSopenharmony_ci memset(&psk_info, 0, sizeof(psk_info)); 1940c87c5fbaSopenharmony_ci psk_info.hint.s = (const uint8_t *)hint; 1941c87c5fbaSopenharmony_ci psk_info.hint.length = hint ? strlen(hint) : 0; 1942c87c5fbaSopenharmony_ci psk_info.key.s = key; 1943c87c5fbaSopenharmony_ci psk_info.key.length = key_length; 1944c87c5fbaSopenharmony_ci if (sni) { 1945c87c5fbaSopenharmony_ci size_t i; 1946c87c5fbaSopenharmony_ci coap_log_info("SNI '%s' requested\n", sni); 1947c87c5fbaSopenharmony_ci for (i = 0; i < valid_psk_snis.count; i++) { 1948c87c5fbaSopenharmony_ci /* Test for identity match to change key */ 1949c87c5fbaSopenharmony_ci if (strcasecmp(sni, 1950c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list[i].sni_match) == 0) { 1951c87c5fbaSopenharmony_ci coap_log_info("Switching to using '%.*s' hint + '%.*s' key\n", 1952c87c5fbaSopenharmony_ci (int)valid_psk_snis.psk_sni_list[i].new_hint->length, 1953c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list[i].new_hint->s, 1954c87c5fbaSopenharmony_ci (int)valid_psk_snis.psk_sni_list[i].new_key->length, 1955c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list[i].new_key->s); 1956c87c5fbaSopenharmony_ci psk_info.hint = *valid_psk_snis.psk_sni_list[i].new_hint; 1957c87c5fbaSopenharmony_ci psk_info.key = *valid_psk_snis.psk_sni_list[i].new_key; 1958c87c5fbaSopenharmony_ci break; 1959c87c5fbaSopenharmony_ci } 1960c87c5fbaSopenharmony_ci } 1961c87c5fbaSopenharmony_ci } else { 1962c87c5fbaSopenharmony_ci coap_log_debug("SNI not requested\n"); 1963c87c5fbaSopenharmony_ci } 1964c87c5fbaSopenharmony_ci return &psk_info; 1965c87c5fbaSopenharmony_ci} 1966c87c5fbaSopenharmony_ci 1967c87c5fbaSopenharmony_cistatic const coap_bin_const_t * 1968c87c5fbaSopenharmony_civerify_id_callback(coap_bin_const_t *identity, 1969c87c5fbaSopenharmony_ci coap_session_t *c_session, 1970c87c5fbaSopenharmony_ci void *arg COAP_UNUSED) { 1971c87c5fbaSopenharmony_ci static coap_bin_const_t psk_key; 1972c87c5fbaSopenharmony_ci const coap_bin_const_t *s_psk_hint = coap_session_get_psk_hint(c_session); 1973c87c5fbaSopenharmony_ci const coap_bin_const_t *s_psk_key; 1974c87c5fbaSopenharmony_ci size_t i; 1975c87c5fbaSopenharmony_ci 1976c87c5fbaSopenharmony_ci coap_log_info("Identity '%.*s' requested, current hint '%.*s'\n", (int)identity->length, 1977c87c5fbaSopenharmony_ci identity->s, 1978c87c5fbaSopenharmony_ci s_psk_hint ? (int)s_psk_hint->length : 0, 1979c87c5fbaSopenharmony_ci s_psk_hint ? (const char *)s_psk_hint->s : ""); 1980c87c5fbaSopenharmony_ci 1981c87c5fbaSopenharmony_ci for (i = 0; i < valid_ids.count; i++) { 1982c87c5fbaSopenharmony_ci /* Check for hint match */ 1983c87c5fbaSopenharmony_ci if (s_psk_hint && 1984c87c5fbaSopenharmony_ci strcmp((const char *)s_psk_hint->s, 1985c87c5fbaSopenharmony_ci valid_ids.id_list[i].hint_match)) { 1986c87c5fbaSopenharmony_ci continue; 1987c87c5fbaSopenharmony_ci } 1988c87c5fbaSopenharmony_ci /* Test for identity match to change key */ 1989c87c5fbaSopenharmony_ci if (coap_binary_equal(identity, valid_ids.id_list[i].identity_match)) { 1990c87c5fbaSopenharmony_ci coap_log_info("Switching to using '%.*s' key\n", 1991c87c5fbaSopenharmony_ci (int)valid_ids.id_list[i].new_key->length, 1992c87c5fbaSopenharmony_ci valid_ids.id_list[i].new_key->s); 1993c87c5fbaSopenharmony_ci return valid_ids.id_list[i].new_key; 1994c87c5fbaSopenharmony_ci } 1995c87c5fbaSopenharmony_ci } 1996c87c5fbaSopenharmony_ci 1997c87c5fbaSopenharmony_ci s_psk_key = coap_session_get_psk_key(c_session); 1998c87c5fbaSopenharmony_ci if (s_psk_key) { 1999c87c5fbaSopenharmony_ci /* Been updated by SNI callback */ 2000c87c5fbaSopenharmony_ci psk_key = *s_psk_key; 2001c87c5fbaSopenharmony_ci return &psk_key; 2002c87c5fbaSopenharmony_ci } 2003c87c5fbaSopenharmony_ci 2004c87c5fbaSopenharmony_ci /* Just use the defined key for now */ 2005c87c5fbaSopenharmony_ci psk_key.s = key; 2006c87c5fbaSopenharmony_ci psk_key.length = key_length; 2007c87c5fbaSopenharmony_ci return &psk_key; 2008c87c5fbaSopenharmony_ci} 2009c87c5fbaSopenharmony_ci 2010c87c5fbaSopenharmony_cistatic coap_dtls_pki_t * 2011c87c5fbaSopenharmony_cisetup_pki(coap_context_t *ctx, coap_dtls_role_t role, char *client_sni) { 2012c87c5fbaSopenharmony_ci static coap_dtls_pki_t dtls_pki; 2013c87c5fbaSopenharmony_ci 2014c87c5fbaSopenharmony_ci /* If general root CAs are defined */ 2015c87c5fbaSopenharmony_ci if (role == COAP_DTLS_ROLE_SERVER && root_ca_file) { 2016c87c5fbaSopenharmony_ci struct stat stbuf; 2017c87c5fbaSopenharmony_ci if ((stat(root_ca_file, &stbuf) == 0) && S_ISDIR(stbuf.st_mode)) { 2018c87c5fbaSopenharmony_ci coap_context_set_pki_root_cas(ctx, NULL, root_ca_file); 2019c87c5fbaSopenharmony_ci } else { 2020c87c5fbaSopenharmony_ci coap_context_set_pki_root_cas(ctx, root_ca_file, NULL); 2021c87c5fbaSopenharmony_ci } 2022c87c5fbaSopenharmony_ci } 2023c87c5fbaSopenharmony_ci 2024c87c5fbaSopenharmony_ci memset(&dtls_pki, 0, sizeof(dtls_pki)); 2025c87c5fbaSopenharmony_ci dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; 2026c87c5fbaSopenharmony_ci if (ca_file || root_ca_file) { 2027c87c5fbaSopenharmony_ci /* 2028c87c5fbaSopenharmony_ci * Add in additional certificate checking. 2029c87c5fbaSopenharmony_ci * This list of enabled can be tuned for the specific 2030c87c5fbaSopenharmony_ci * requirements - see 'man coap_encryption'. 2031c87c5fbaSopenharmony_ci * 2032c87c5fbaSopenharmony_ci * Note: root_ca_file is setup separately using 2033c87c5fbaSopenharmony_ci * coap_context_set_pki_root_cas(), but this is used to define what 2034c87c5fbaSopenharmony_ci * checking actually takes place. 2035c87c5fbaSopenharmony_ci */ 2036c87c5fbaSopenharmony_ci dtls_pki.verify_peer_cert = verify_peer_cert; 2037c87c5fbaSopenharmony_ci dtls_pki.check_common_ca = !root_ca_file; 2038c87c5fbaSopenharmony_ci dtls_pki.allow_self_signed = 1; 2039c87c5fbaSopenharmony_ci dtls_pki.allow_expired_certs = 1; 2040c87c5fbaSopenharmony_ci dtls_pki.cert_chain_validation = 1; 2041c87c5fbaSopenharmony_ci dtls_pki.cert_chain_verify_depth = 2; 2042c87c5fbaSopenharmony_ci dtls_pki.check_cert_revocation = 1; 2043c87c5fbaSopenharmony_ci dtls_pki.allow_no_crl = 1; 2044c87c5fbaSopenharmony_ci dtls_pki.allow_expired_crl = 1; 2045c87c5fbaSopenharmony_ci } else if (is_rpk_not_cert) { 2046c87c5fbaSopenharmony_ci dtls_pki.verify_peer_cert = verify_peer_cert; 2047c87c5fbaSopenharmony_ci } 2048c87c5fbaSopenharmony_ci dtls_pki.is_rpk_not_cert = is_rpk_not_cert; 2049c87c5fbaSopenharmony_ci dtls_pki.validate_cn_call_back = verify_cn_callback; 2050c87c5fbaSopenharmony_ci dtls_pki.cn_call_back_arg = (void *)role; 2051c87c5fbaSopenharmony_ci dtls_pki.validate_sni_call_back = role == COAP_DTLS_ROLE_SERVER ? 2052c87c5fbaSopenharmony_ci verify_pki_sni_callback : NULL; 2053c87c5fbaSopenharmony_ci dtls_pki.sni_call_back_arg = NULL; 2054c87c5fbaSopenharmony_ci 2055c87c5fbaSopenharmony_ci if (role == COAP_DTLS_ROLE_CLIENT) { 2056c87c5fbaSopenharmony_ci dtls_pki.client_sni = client_sni; 2057c87c5fbaSopenharmony_ci } 2058c87c5fbaSopenharmony_ci 2059c87c5fbaSopenharmony_ci update_pki_key(&dtls_pki.pki_key, key_file, cert_file, ca_file); 2060c87c5fbaSopenharmony_ci /* Need to keep base initialization copies of any COAP_PKI_KEY_PEM_BUF */ 2061c87c5fbaSopenharmony_ci ca_mem_base = ca_mem; 2062c87c5fbaSopenharmony_ci cert_mem_base = cert_mem; 2063c87c5fbaSopenharmony_ci key_mem_base = key_mem; 2064c87c5fbaSopenharmony_ci ca_mem = NULL; 2065c87c5fbaSopenharmony_ci cert_mem = NULL; 2066c87c5fbaSopenharmony_ci key_mem = NULL; 2067c87c5fbaSopenharmony_ci return &dtls_pki; 2068c87c5fbaSopenharmony_ci} 2069c87c5fbaSopenharmony_ci 2070c87c5fbaSopenharmony_cistatic coap_dtls_spsk_t * 2071c87c5fbaSopenharmony_cisetup_spsk(void) { 2072c87c5fbaSopenharmony_ci static coap_dtls_spsk_t dtls_spsk; 2073c87c5fbaSopenharmony_ci 2074c87c5fbaSopenharmony_ci memset(&dtls_spsk, 0, sizeof(dtls_spsk)); 2075c87c5fbaSopenharmony_ci dtls_spsk.version = COAP_DTLS_SPSK_SETUP_VERSION; 2076c87c5fbaSopenharmony_ci dtls_spsk.validate_id_call_back = valid_ids.count ? 2077c87c5fbaSopenharmony_ci verify_id_callback : NULL; 2078c87c5fbaSopenharmony_ci dtls_spsk.validate_sni_call_back = valid_psk_snis.count ? 2079c87c5fbaSopenharmony_ci verify_psk_sni_callback : NULL; 2080c87c5fbaSopenharmony_ci dtls_spsk.psk_info.hint.s = (const uint8_t *)hint; 2081c87c5fbaSopenharmony_ci dtls_spsk.psk_info.hint.length = hint ? strlen(hint) : 0; 2082c87c5fbaSopenharmony_ci dtls_spsk.psk_info.key.s = key; 2083c87c5fbaSopenharmony_ci dtls_spsk.psk_info.key.length = key_length; 2084c87c5fbaSopenharmony_ci return &dtls_spsk; 2085c87c5fbaSopenharmony_ci} 2086c87c5fbaSopenharmony_ci 2087c87c5fbaSopenharmony_cistatic void 2088c87c5fbaSopenharmony_cifill_keystore(coap_context_t *ctx) { 2089c87c5fbaSopenharmony_ci 2090c87c5fbaSopenharmony_ci if (cert_file == NULL && key_defined == 0) { 2091c87c5fbaSopenharmony_ci if (coap_dtls_is_supported() || coap_tls_is_supported()) { 2092c87c5fbaSopenharmony_ci coap_log_debug("(D)TLS not enabled as none of -k, -c or -M options specified\n"); 2093c87c5fbaSopenharmony_ci } 2094c87c5fbaSopenharmony_ci return; 2095c87c5fbaSopenharmony_ci } 2096c87c5fbaSopenharmony_ci if (cert_file) { 2097c87c5fbaSopenharmony_ci coap_dtls_pki_t *dtls_pki = setup_pki(ctx, 2098c87c5fbaSopenharmony_ci COAP_DTLS_ROLE_SERVER, NULL); 2099c87c5fbaSopenharmony_ci if (!coap_context_set_pki(ctx, dtls_pki)) { 2100c87c5fbaSopenharmony_ci coap_log_info("Unable to set up %s keys\n", 2101c87c5fbaSopenharmony_ci is_rpk_not_cert ? "RPK" : "PKI"); 2102c87c5fbaSopenharmony_ci /* So we do not set up DTLS */ 2103c87c5fbaSopenharmony_ci cert_file = NULL; 2104c87c5fbaSopenharmony_ci } 2105c87c5fbaSopenharmony_ci } 2106c87c5fbaSopenharmony_ci if (key_defined) { 2107c87c5fbaSopenharmony_ci coap_dtls_spsk_t *dtls_spsk = setup_spsk(); 2108c87c5fbaSopenharmony_ci 2109c87c5fbaSopenharmony_ci if (!coap_context_set_psk2(ctx, dtls_spsk)) { 2110c87c5fbaSopenharmony_ci coap_log_info("Unable to set up PSK\n"); 2111c87c5fbaSopenharmony_ci /* So we do not set up DTLS */ 2112c87c5fbaSopenharmony_ci key_defined = 0; 2113c87c5fbaSopenharmony_ci } 2114c87c5fbaSopenharmony_ci } 2115c87c5fbaSopenharmony_ci} 2116c87c5fbaSopenharmony_ci 2117c87c5fbaSopenharmony_cistatic void 2118c87c5fbaSopenharmony_ciusage(const char *program, const char *version) { 2119c87c5fbaSopenharmony_ci const char *p; 2120c87c5fbaSopenharmony_ci char buffer[120]; 2121c87c5fbaSopenharmony_ci const char *lib_build = coap_package_build(); 2122c87c5fbaSopenharmony_ci 2123c87c5fbaSopenharmony_ci p = strrchr(program, '/'); 2124c87c5fbaSopenharmony_ci if (p) 2125c87c5fbaSopenharmony_ci program = ++p; 2126c87c5fbaSopenharmony_ci 2127c87c5fbaSopenharmony_ci fprintf(stderr, "%s v%s -- a small CoAP implementation\n" 2128c87c5fbaSopenharmony_ci "(c) 2010,2011,2015-2023 Olaf Bergmann <bergmann@tzi.org> and others\n\n" 2129c87c5fbaSopenharmony_ci "Build: %s\n" 2130c87c5fbaSopenharmony_ci "%s\n" 2131c87c5fbaSopenharmony_ci , program, version, lib_build, 2132c87c5fbaSopenharmony_ci coap_string_tls_version(buffer, sizeof(buffer))); 2133c87c5fbaSopenharmony_ci fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); 2134c87c5fbaSopenharmony_ci fprintf(stderr, "\n" 2135c87c5fbaSopenharmony_ci "Usage: %s [-d max] [-e] [-g group] [-l loss] [-p port] [-r] [-v num]\n" 2136c87c5fbaSopenharmony_ci "\t\t[-w [port][,secure_port]] [-A address]\n" 2137c87c5fbaSopenharmony_ci "\t\t[-E oscore_conf_file[,seq_file]] [-G group_if] [-L value] [-N]\n" 2138c87c5fbaSopenharmony_ci "\t\t[-P scheme://address[:port],[name1[,name2..]]]\n" 2139c87c5fbaSopenharmony_ci "\t\t[-T max_token_size] [-U type] [-V num] [-X size]\n" 2140c87c5fbaSopenharmony_ci "\t\t[[-h hint] [-i match_identity_file] [-k key]\n" 2141c87c5fbaSopenharmony_ci "\t\t[-s match_psk_sni_file] [-u user]]\n" 2142c87c5fbaSopenharmony_ci "\t\t[[-c certfile] [-j keyfile] [-m] [-n] [-C cafile]\n" 2143c87c5fbaSopenharmony_ci "\t\t[-J pkcs11_pin] [-M rpk_file] [-R trust_casfile]\n" 2144c87c5fbaSopenharmony_ci "\t\t[-S match_pki_sni_file]]\n" 2145c87c5fbaSopenharmony_ci "General Options\n" 2146c87c5fbaSopenharmony_ci "\t-d max \t\tAllow dynamic creation of up to a total of max\n" 2147c87c5fbaSopenharmony_ci "\t \t\tresources. If max is reached, a 4.06 code is returned\n" 2148c87c5fbaSopenharmony_ci "\t \t\tuntil one of the dynamic resources has been deleted\n" 2149c87c5fbaSopenharmony_ci "\t-e \t\tEcho back the data sent with a PUT\n" 2150c87c5fbaSopenharmony_ci "\t-g group\tJoin the given multicast group\n" 2151c87c5fbaSopenharmony_ci "\t \t\tNote: DTLS over multicast is not currently supported\n" 2152c87c5fbaSopenharmony_ci "\t-l list\t\tFail to send some datagrams specified by a comma\n" 2153c87c5fbaSopenharmony_ci "\t \t\tseparated list of numbers or number ranges\n" 2154c87c5fbaSopenharmony_ci "\t \t\t(for debugging only)\n" 2155c87c5fbaSopenharmony_ci "\t-l loss%%\tRandomly fail to send datagrams with the specified\n" 2156c87c5fbaSopenharmony_ci "\t \t\tprobability - 100%% all datagrams, 0%% no datagrams\n" 2157c87c5fbaSopenharmony_ci "\t \t\t(for debugging only)\n" 2158c87c5fbaSopenharmony_ci "\t-p port\t\tListen on specified port for UDP and TCP. If (D)TLS is\n" 2159c87c5fbaSopenharmony_ci "\t \t\tenabled, then the coap-server will also listen on\n" 2160c87c5fbaSopenharmony_ci "\t \t\t'port'+1 for DTLS and TLS. The default port is 5683\n" 2161c87c5fbaSopenharmony_ci "\t-r \t\tEnable multicast per resource support. If enabled,\n" 2162c87c5fbaSopenharmony_ci "\t \t\tonly '/', '/async' and '/.well-known/core' are enabled\n" 2163c87c5fbaSopenharmony_ci "\t \t\tfor multicast requests support, otherwise all\n" 2164c87c5fbaSopenharmony_ci "\t \t\tresources are enabled\n" 2165c87c5fbaSopenharmony_ci "\t-t \t\tTrack resource's observe values so observe\n" 2166c87c5fbaSopenharmony_ci "\t \t\tsubscriptions can be maintained over a server restart.\n" 2167c87c5fbaSopenharmony_ci "\t \t\tNote: Use 'kill SIGUSR2 <pid>' for controlled shutdown\n" 2168c87c5fbaSopenharmony_ci "\t-v num \t\tVerbosity level (default 4, maximum is 8) for general\n" 2169c87c5fbaSopenharmony_ci "\t \t\tCoAP logging\n" 2170c87c5fbaSopenharmony_ci "\t-w [port][,secure_port]\n" 2171c87c5fbaSopenharmony_ci "\t \t\tEnable WebSockets support on port (WS) and/or secure_port\n" 2172c87c5fbaSopenharmony_ci "\t \t\t(WSS), comma separated\n" 2173c87c5fbaSopenharmony_ci "\t-A address\tInterface address to bind to\n" 2174c87c5fbaSopenharmony_ci "\t-E oscore_conf_file[,seq_file]\n" 2175c87c5fbaSopenharmony_ci "\t \t\toscore_conf_file contains OSCORE configuration. See\n" 2176c87c5fbaSopenharmony_ci "\t \t\tcoap-oscore-conf(5) for definitions.\n" 2177c87c5fbaSopenharmony_ci "\t \t\tOptional seq_file is used to save the current transmit\n" 2178c87c5fbaSopenharmony_ci "\t \t\tsequence number, so on restart sequence numbers continue\n" 2179c87c5fbaSopenharmony_ci "\t-G group_if\tUse this interface for listening for the multicast\n" 2180c87c5fbaSopenharmony_ci "\t \t\tgroup. This can be different from the implied interface\n" 2181c87c5fbaSopenharmony_ci "\t \t\tif the -A option is used\n" 2182c87c5fbaSopenharmony_ci "\t-L value\tSum of one or more COAP_BLOCK_* flag valuess for block\n" 2183c87c5fbaSopenharmony_ci "\t \t\thandling methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP)\n" 2184c87c5fbaSopenharmony_ci "\t \t\t(Sum of one or more of 1,2 and 4)\n" 2185c87c5fbaSopenharmony_ci "\t-N \t\tMake \"observe\" responses NON-confirmable. Even if set\n" 2186c87c5fbaSopenharmony_ci "\t \t\tevery fifth response will still be sent as a confirmable\n" 2187c87c5fbaSopenharmony_ci "\t \t\tresponse (RFC 7641 requirement)\n" 2188c87c5fbaSopenharmony_ci , program); 2189c87c5fbaSopenharmony_ci fprintf(stderr, 2190c87c5fbaSopenharmony_ci "\t-P scheme://address[:port],[name1[,name2[,name3..]]]\n" 2191c87c5fbaSopenharmony_ci "\t \t\tScheme, address, optional port of how to connect to the\n" 2192c87c5fbaSopenharmony_ci "\t \t\tnext proxy server and zero or more names (comma\n" 2193c87c5fbaSopenharmony_ci "\t \t\tseparated) that this proxy server is known by. The\n" 2194c87c5fbaSopenharmony_ci "\t \t\t, (comma) is required. If there is no name1 or if the\n" 2195c87c5fbaSopenharmony_ci "\t \t\thostname of the incoming proxy request matches one of\n" 2196c87c5fbaSopenharmony_ci "\t \t\tthese names, then this server is considered to be the\n" 2197c87c5fbaSopenharmony_ci "\t \t\tfinal endpoint. If scheme://address[:port] is not\n" 2198c87c5fbaSopenharmony_ci "\t \t\tdefined before the leading , (comma) of the first name,\n" 2199c87c5fbaSopenharmony_ci "\t \t\tthen the ongoing connection will be a direct connection.\n" 2200c87c5fbaSopenharmony_ci "\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n" 2201c87c5fbaSopenharmony_ci "\t-T max_token_length\tSet the maximum token length (8-65804)\n" 2202c87c5fbaSopenharmony_ci "\t-U type\t\tTreat address defined by -A as a Unix socket address.\n" 2203c87c5fbaSopenharmony_ci "\t \t\ttype is 'coap', 'coaps', 'coap+tcp' or 'coaps+tcp'\n" 2204c87c5fbaSopenharmony_ci "\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n" 2205c87c5fbaSopenharmony_ci "\t \t\tlibrary logging\n" 2206c87c5fbaSopenharmony_ci "\t-X size\t\tMaximum message size to use for TCP based connections\n" 2207c87c5fbaSopenharmony_ci "\t \t\t(default is 8388864). Maximum value of 2^32 -1\n" 2208c87c5fbaSopenharmony_ci "PSK Options (if supported by underlying (D)TLS library)\n" 2209c87c5fbaSopenharmony_ci "\t-h hint\t\tIdentity Hint to send. Default is CoAP. Zero length is\n" 2210c87c5fbaSopenharmony_ci "\t \t\tno hint\n" 2211c87c5fbaSopenharmony_ci "\t-i match_identity_file\n" 2212c87c5fbaSopenharmony_ci "\t \t\tThis is a file that contains one or more lines of\n" 2213c87c5fbaSopenharmony_ci "\t \t\tIdentity Hints and (user) Identities to match for\n" 2214c87c5fbaSopenharmony_ci "\t \t\ta different new Pre-Shared Key (PSK) (comma separated)\n" 2215c87c5fbaSopenharmony_ci "\t \t\tto be used. E.g., per line\n" 2216c87c5fbaSopenharmony_ci "\t \t\t hint_to_match,identity_to_match,use_key\n" 2217c87c5fbaSopenharmony_ci "\t \t\tNote: -k still needs to be defined for the default case\n" 2218c87c5fbaSopenharmony_ci "\t \t\tNote: A match using the -s option may mean that the\n" 2219c87c5fbaSopenharmony_ci "\t \t\tcurrent Identity Hint is different to that defined by -h\n" 2220c87c5fbaSopenharmony_ci "\t-k key \t\tPre-Shared Key. This argument requires (D)TLS with PSK\n" 2221c87c5fbaSopenharmony_ci "\t \t\tto be available. This cannot be empty if defined.\n" 2222c87c5fbaSopenharmony_ci "\t \t\tNote that both -c and -k need to be defined for both\n" 2223c87c5fbaSopenharmony_ci "\t \t\tPSK and PKI to be concurrently supported\n" 2224c87c5fbaSopenharmony_ci "\t-s match_psk_sni_file\n" 2225c87c5fbaSopenharmony_ci "\t \t\tThis is a file that contains one or more lines of\n" 2226c87c5fbaSopenharmony_ci "\t \t\treceived Subject Name Identifier (SNI) to match to use\n" 2227c87c5fbaSopenharmony_ci "\t \t\ta different Identity Hint and associated Pre-Shared Key\n" 2228c87c5fbaSopenharmony_ci "\t \t\t(PSK) (comma separated) instead of the '-h hint' and\n" 2229c87c5fbaSopenharmony_ci "\t \t\t'-k key' options. E.g., per line\n" 2230c87c5fbaSopenharmony_ci "\t \t\t sni_to_match,use_hint,with_key\n" 2231c87c5fbaSopenharmony_ci "\t \t\tNote: -k still needs to be defined for the default case\n" 2232c87c5fbaSopenharmony_ci "\t \t\tif there is not a match\n" 2233c87c5fbaSopenharmony_ci "\t \t\tNote: The associated Pre-Shared Key will get updated if\n" 2234c87c5fbaSopenharmony_ci "\t \t\tthere is also a -i match. The update checking order is\n" 2235c87c5fbaSopenharmony_ci "\t \t\t-s followed by -i\n" 2236c87c5fbaSopenharmony_ci "\t-u user\t\tUser identity for pre-shared key mode (only used if\n" 2237c87c5fbaSopenharmony_ci "\t \t\toption -P is set)\n" 2238c87c5fbaSopenharmony_ci ); 2239c87c5fbaSopenharmony_ci fprintf(stderr, 2240c87c5fbaSopenharmony_ci "PKI Options (if supported by underlying (D)TLS library)\n" 2241c87c5fbaSopenharmony_ci "\tNote: If any one of '-c certfile', '-j keyfile' or '-C cafile' is in\n" 2242c87c5fbaSopenharmony_ci "\tPKCS11 URI naming format (pkcs11: prefix), then any remaining non\n" 2243c87c5fbaSopenharmony_ci "\tPKCS11 URI file definitions have to be in DER, not PEM, format.\n" 2244c87c5fbaSopenharmony_ci "\tOtherwise all of '-c certfile', '-j keyfile' or '-C cafile' are in\n" 2245c87c5fbaSopenharmony_ci "\tPEM format.\n\n" 2246c87c5fbaSopenharmony_ci "\t-c certfile\tPEM file or PKCS11 URI for the certificate. The private\n" 2247c87c5fbaSopenharmony_ci "\t \t\tkey can also be in the PEM file, or has the same PKCS11\n" 2248c87c5fbaSopenharmony_ci "\t \t\tURI. If not, the private key is defined by '-j keyfile'.\n" 2249c87c5fbaSopenharmony_ci "\t \t\tNote that both -c and -k need to be defined for both\n" 2250c87c5fbaSopenharmony_ci "\t \t\tPSK and PKI to be concurrently supported\n" 2251c87c5fbaSopenharmony_ci "\t-j keyfile\tPEM file or PKCS11 URI for the private key for the\n" 2252c87c5fbaSopenharmony_ci "\t \t\tcertificate in '-c certfile' if the parameter is\n" 2253c87c5fbaSopenharmony_ci "\t \t\tdifferent from certfile in '-c certfile'\n" 2254c87c5fbaSopenharmony_ci "\t-m \t\tUse COAP_PKI_KEY_PEM_BUF instead of COAP_PKI_KEY_PEM i/f\n" 2255c87c5fbaSopenharmony_ci "\t \t\tby reading into memory the Cert / CA file (for testing)\n" 2256c87c5fbaSopenharmony_ci "\t-n \t\tDisable remote peer certificate checking. This gives\n" 2257c87c5fbaSopenharmony_ci "\t \t\tclients the ability to use PKI, but without any defined\n" 2258c87c5fbaSopenharmony_ci "\t \t\tcertificates\n" 2259c87c5fbaSopenharmony_ci "\t-C cafile\tPEM file or PKCS11 URI that contains a list of one or\n" 2260c87c5fbaSopenharmony_ci "\t \t\tmore CAs that are to be passed to the client for the\n" 2261c87c5fbaSopenharmony_ci "\t \t\tclient to determine what client certificate to use.\n" 2262c87c5fbaSopenharmony_ci "\t \t\tNormally, this list of CAs would be the root CA and and\n" 2263c87c5fbaSopenharmony_ci "\t \t\tany intermediate CAs. Ideally the server certificate\n" 2264c87c5fbaSopenharmony_ci "\t \t\tshould be signed by the same CA so that mutual\n" 2265c87c5fbaSopenharmony_ci "\t \t\tauthentication can take place. The contents of cafile\n" 2266c87c5fbaSopenharmony_ci "\t \t\tare added to the trusted store of root CAs.\n" 2267c87c5fbaSopenharmony_ci "\t \t\tUsing the -C or -R options will will trigger the\n" 2268c87c5fbaSopenharmony_ci "\t \t\tvalidation of the client certificate unless overridden\n" 2269c87c5fbaSopenharmony_ci "\t \t\tby the -n option\n" 2270c87c5fbaSopenharmony_ci "\t-J pkcs11_pin\tThe user pin to unlock access to the PKCS11 token\n" 2271c87c5fbaSopenharmony_ci "\t-M rpk_file\tRaw Public Key (RPK) PEM file or PKCS11 URI that\n" 2272c87c5fbaSopenharmony_ci "\t \t\tcontains both PUBLIC KEY and PRIVATE KEY or just\n" 2273c87c5fbaSopenharmony_ci "\t \t\tEC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support only).\n" 2274c87c5fbaSopenharmony_ci "\t \t\t'-C cafile' or '-R trust_casfile' are not required\n" 2275c87c5fbaSopenharmony_ci "\t-R trust_casfile\n" 2276c87c5fbaSopenharmony_ci "\t \t\tPEM file containing the set of trusted root CAs\n" 2277c87c5fbaSopenharmony_ci "\t \t\tthat are to be used to validate the client certificate.\n" 2278c87c5fbaSopenharmony_ci "\t \t\tAlternatively, this can point to a directory containing\n" 2279c87c5fbaSopenharmony_ci "\t \t\ta set of CA PEM files.\n" 2280c87c5fbaSopenharmony_ci "\t \t\tUsing '-R trust_casfile' disables common CA mutual\n" 2281c87c5fbaSopenharmony_ci "\t \t\tauthentication which can only be done by using\n" 2282c87c5fbaSopenharmony_ci "\t \t\t'-C cafile'.\n" 2283c87c5fbaSopenharmony_ci "\t \t\tUsing the -C or -R options will will trigger the\n" 2284c87c5fbaSopenharmony_ci "\t \t\tvalidation of the client certificate unless overridden\n" 2285c87c5fbaSopenharmony_ci "\t \t\tby the -n option\n" 2286c87c5fbaSopenharmony_ci "\t-S match_pki_sni_file\n" 2287c87c5fbaSopenharmony_ci "\t \t\tThis option denotes a file that contains one or more\n" 2288c87c5fbaSopenharmony_ci "\t \t\tlines of Subject Name Identifier (SNI) to match for new\n" 2289c87c5fbaSopenharmony_ci "\t \t\tCert file and new CA file (comma separated) to be used.\n" 2290c87c5fbaSopenharmony_ci "\t \t\tE.g., per line\n" 2291c87c5fbaSopenharmony_ci "\t \t\t sni_to_match,new_cert_file,new_ca_file\n" 2292c87c5fbaSopenharmony_ci "\t \t\tNote: -c and -C still need to be defined for the default\n" 2293c87c5fbaSopenharmony_ci "\t \t\tcase\n" 2294c87c5fbaSopenharmony_ci ); 2295c87c5fbaSopenharmony_ci} 2296c87c5fbaSopenharmony_ci 2297c87c5fbaSopenharmony_cistatic coap_context_t * 2298c87c5fbaSopenharmony_ciget_context(const char *node, const char *port) { 2299c87c5fbaSopenharmony_ci coap_context_t *ctx = NULL; 2300c87c5fbaSopenharmony_ci coap_addr_info_t *info = NULL; 2301c87c5fbaSopenharmony_ci coap_addr_info_t *info_list = NULL; 2302c87c5fbaSopenharmony_ci coap_str_const_t local; 2303c87c5fbaSopenharmony_ci int have_ep = 0; 2304c87c5fbaSopenharmony_ci uint16_t u_s_port = 0; 2305c87c5fbaSopenharmony_ci uint16_t s_port = 0; 2306c87c5fbaSopenharmony_ci uint32_t scheme_hint_bits = 0; 2307c87c5fbaSopenharmony_ci 2308c87c5fbaSopenharmony_ci ctx = coap_new_context(NULL); 2309c87c5fbaSopenharmony_ci if (!ctx) { 2310c87c5fbaSopenharmony_ci return NULL; 2311c87c5fbaSopenharmony_ci } 2312c87c5fbaSopenharmony_ci 2313c87c5fbaSopenharmony_ci /* Need PKI/RPK/PSK set up before we set up (D)TLS endpoints */ 2314c87c5fbaSopenharmony_ci fill_keystore(ctx); 2315c87c5fbaSopenharmony_ci 2316c87c5fbaSopenharmony_ci if (node) { 2317c87c5fbaSopenharmony_ci local.s = (const uint8_t *)node; 2318c87c5fbaSopenharmony_ci local.length = strlen(node); 2319c87c5fbaSopenharmony_ci } 2320c87c5fbaSopenharmony_ci 2321c87c5fbaSopenharmony_ci if (port) { 2322c87c5fbaSopenharmony_ci u_s_port = atoi(port); 2323c87c5fbaSopenharmony_ci s_port = u_s_port + 1; 2324c87c5fbaSopenharmony_ci } 2325c87c5fbaSopenharmony_ci scheme_hint_bits = 2326c87c5fbaSopenharmony_ci coap_get_available_scheme_hint_bits(cert_file != NULL || key_defined != 0, 2327c87c5fbaSopenharmony_ci enable_ws, use_unix_proto); 2328c87c5fbaSopenharmony_ci info_list = coap_resolve_address_info(node ? &local : NULL, u_s_port, s_port, 2329c87c5fbaSopenharmony_ci ws_port, wss_port, 2330c87c5fbaSopenharmony_ci AI_PASSIVE | AI_NUMERICHOST, 2331c87c5fbaSopenharmony_ci scheme_hint_bits, 2332c87c5fbaSopenharmony_ci COAP_RESOLVE_TYPE_LOCAL); 2333c87c5fbaSopenharmony_ci for (info = info_list; info != NULL; info = info->next) { 2334c87c5fbaSopenharmony_ci coap_endpoint_t *ep; 2335c87c5fbaSopenharmony_ci 2336c87c5fbaSopenharmony_ci ep = coap_new_endpoint(ctx, &info->addr, info->proto); 2337c87c5fbaSopenharmony_ci if (!ep) { 2338c87c5fbaSopenharmony_ci coap_log_warn("cannot create endpoint for proto %u\n", 2339c87c5fbaSopenharmony_ci info->proto); 2340c87c5fbaSopenharmony_ci } else { 2341c87c5fbaSopenharmony_ci have_ep = 1; 2342c87c5fbaSopenharmony_ci } 2343c87c5fbaSopenharmony_ci } 2344c87c5fbaSopenharmony_ci coap_free_address_info(info_list); 2345c87c5fbaSopenharmony_ci if (!have_ep) { 2346c87c5fbaSopenharmony_ci coap_log_err("No context available for interface '%s'\n", node); 2347c87c5fbaSopenharmony_ci coap_free_context(ctx); 2348c87c5fbaSopenharmony_ci return NULL; 2349c87c5fbaSopenharmony_ci } 2350c87c5fbaSopenharmony_ci return ctx; 2351c87c5fbaSopenharmony_ci} 2352c87c5fbaSopenharmony_ci 2353c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 2354c87c5fbaSopenharmony_cistatic int 2355c87c5fbaSopenharmony_cicmdline_proxy(char *arg) { 2356c87c5fbaSopenharmony_ci char *host_start = strchr(arg, ','); 2357c87c5fbaSopenharmony_ci char *next_name = host_start; 2358c87c5fbaSopenharmony_ci size_t ofs; 2359c87c5fbaSopenharmony_ci 2360c87c5fbaSopenharmony_ci if (!host_start) { 2361c87c5fbaSopenharmony_ci coap_log_warn("Zero or more proxy host names not defined\n"); 2362c87c5fbaSopenharmony_ci return 0; 2363c87c5fbaSopenharmony_ci } 2364c87c5fbaSopenharmony_ci *host_start = '\000'; 2365c87c5fbaSopenharmony_ci 2366c87c5fbaSopenharmony_ci if (host_start != arg) { 2367c87c5fbaSopenharmony_ci /* Next upstream proxy is defined */ 2368c87c5fbaSopenharmony_ci if (coap_split_uri((unsigned char *)arg, strlen(arg), &proxy) < 0 || 2369c87c5fbaSopenharmony_ci proxy.path.length != 0 || proxy.query.length != 0) { 2370c87c5fbaSopenharmony_ci coap_log_err("invalid CoAP Proxy definition\n"); 2371c87c5fbaSopenharmony_ci return 0; 2372c87c5fbaSopenharmony_ci } 2373c87c5fbaSopenharmony_ci } 2374c87c5fbaSopenharmony_ci proxy_host_name_count = 0; 2375c87c5fbaSopenharmony_ci while (next_name) { 2376c87c5fbaSopenharmony_ci proxy_host_name_count++; 2377c87c5fbaSopenharmony_ci next_name = strchr(next_name+1, ','); 2378c87c5fbaSopenharmony_ci } 2379c87c5fbaSopenharmony_ci proxy_host_name_list = coap_malloc(proxy_host_name_count * sizeof(char *)); 2380c87c5fbaSopenharmony_ci next_name = host_start; 2381c87c5fbaSopenharmony_ci ofs = 0; 2382c87c5fbaSopenharmony_ci while (next_name) { 2383c87c5fbaSopenharmony_ci proxy_host_name_list[ofs++] = next_name+1; 2384c87c5fbaSopenharmony_ci next_name = strchr(next_name+1, ','); 2385c87c5fbaSopenharmony_ci if (next_name) 2386c87c5fbaSopenharmony_ci *next_name = '\000'; 2387c87c5fbaSopenharmony_ci } 2388c87c5fbaSopenharmony_ci return 1; 2389c87c5fbaSopenharmony_ci} 2390c87c5fbaSopenharmony_ci 2391c87c5fbaSopenharmony_cistatic ssize_t 2392c87c5fbaSopenharmony_cicmdline_read_user(char *arg, unsigned char **buf, size_t maxlen) { 2393c87c5fbaSopenharmony_ci size_t len = strnlen(arg, maxlen); 2394c87c5fbaSopenharmony_ci if (len) { 2395c87c5fbaSopenharmony_ci *buf = (unsigned char *)arg; 2396c87c5fbaSopenharmony_ci /* len is the size or less, so 0 terminate to maxlen */ 2397c87c5fbaSopenharmony_ci (*buf)[len] = '\000'; 2398c87c5fbaSopenharmony_ci } 2399c87c5fbaSopenharmony_ci /* 0 length Identity is valid */ 2400c87c5fbaSopenharmony_ci return len; 2401c87c5fbaSopenharmony_ci} 2402c87c5fbaSopenharmony_ci#endif /* SERVER_CAN_PROXY */ 2403c87c5fbaSopenharmony_ci 2404c87c5fbaSopenharmony_cistatic FILE *oscore_seq_num_fp = NULL; 2405c87c5fbaSopenharmony_cistatic const char *oscore_conf_file = NULL; 2406c87c5fbaSopenharmony_cistatic const char *oscore_seq_save_file = NULL; 2407c87c5fbaSopenharmony_ci 2408c87c5fbaSopenharmony_cistatic int 2409c87c5fbaSopenharmony_cioscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) { 2410c87c5fbaSopenharmony_ci if (oscore_seq_num_fp) { 2411c87c5fbaSopenharmony_ci rewind(oscore_seq_num_fp); 2412c87c5fbaSopenharmony_ci fprintf(oscore_seq_num_fp, "%" PRIu64 "\n", sender_seq_num); 2413c87c5fbaSopenharmony_ci fflush(oscore_seq_num_fp); 2414c87c5fbaSopenharmony_ci } 2415c87c5fbaSopenharmony_ci return 1; 2416c87c5fbaSopenharmony_ci} 2417c87c5fbaSopenharmony_ci 2418c87c5fbaSopenharmony_cistatic coap_oscore_conf_t * 2419c87c5fbaSopenharmony_ciget_oscore_conf(coap_context_t *context) { 2420c87c5fbaSopenharmony_ci uint8_t *buf; 2421c87c5fbaSopenharmony_ci size_t length; 2422c87c5fbaSopenharmony_ci coap_str_const_t file_mem; 2423c87c5fbaSopenharmony_ci uint64_t start_seq_num = 0; 2424c87c5fbaSopenharmony_ci 2425c87c5fbaSopenharmony_ci /* Need a rw var to free off later and file_mem.s is a const */ 2426c87c5fbaSopenharmony_ci buf = read_file_mem(oscore_conf_file, &length); 2427c87c5fbaSopenharmony_ci if (buf == NULL) { 2428c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE configuration file error: %s\n", oscore_conf_file); 2429c87c5fbaSopenharmony_ci return NULL; 2430c87c5fbaSopenharmony_ci } 2431c87c5fbaSopenharmony_ci file_mem.s = buf; 2432c87c5fbaSopenharmony_ci file_mem.length = length; 2433c87c5fbaSopenharmony_ci if (oscore_seq_save_file) { 2434c87c5fbaSopenharmony_ci oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+"); 2435c87c5fbaSopenharmony_ci if (oscore_seq_num_fp == NULL) { 2436c87c5fbaSopenharmony_ci /* Try creating it */ 2437c87c5fbaSopenharmony_ci oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+"); 2438c87c5fbaSopenharmony_ci if (oscore_seq_num_fp == NULL) { 2439c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE save restart info file error: %s\n", 2440c87c5fbaSopenharmony_ci oscore_seq_save_file); 2441c87c5fbaSopenharmony_ci return NULL; 2442c87c5fbaSopenharmony_ci } 2443c87c5fbaSopenharmony_ci } 2444c87c5fbaSopenharmony_ci if (fscanf(oscore_seq_num_fp, "%" PRIu64, &start_seq_num) != 1) { 2445c87c5fbaSopenharmony_ci /* Must be empty */ 2446c87c5fbaSopenharmony_ci start_seq_num = 0; 2447c87c5fbaSopenharmony_ci } 2448c87c5fbaSopenharmony_ci } 2449c87c5fbaSopenharmony_ci oscore_conf = coap_new_oscore_conf(file_mem, 2450c87c5fbaSopenharmony_ci oscore_save_seq_num, 2451c87c5fbaSopenharmony_ci NULL, start_seq_num); 2452c87c5fbaSopenharmony_ci coap_free(buf); 2453c87c5fbaSopenharmony_ci if (oscore_conf == NULL) { 2454c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE configuration file error: %s\n", oscore_conf_file); 2455c87c5fbaSopenharmony_ci return NULL; 2456c87c5fbaSopenharmony_ci } 2457c87c5fbaSopenharmony_ci coap_context_oscore_server(context, oscore_conf); 2458c87c5fbaSopenharmony_ci return oscore_conf; 2459c87c5fbaSopenharmony_ci} 2460c87c5fbaSopenharmony_ci 2461c87c5fbaSopenharmony_cistatic int 2462c87c5fbaSopenharmony_cicmdline_oscore(char *arg) { 2463c87c5fbaSopenharmony_ci if (coap_oscore_is_supported()) { 2464c87c5fbaSopenharmony_ci char *sep = strchr(arg, ','); 2465c87c5fbaSopenharmony_ci 2466c87c5fbaSopenharmony_ci if (sep) 2467c87c5fbaSopenharmony_ci *sep = '\000'; 2468c87c5fbaSopenharmony_ci oscore_conf_file = arg; 2469c87c5fbaSopenharmony_ci 2470c87c5fbaSopenharmony_ci if (sep) { 2471c87c5fbaSopenharmony_ci sep++; 2472c87c5fbaSopenharmony_ci oscore_seq_save_file = sep; 2473c87c5fbaSopenharmony_ci } 2474c87c5fbaSopenharmony_ci return 1; 2475c87c5fbaSopenharmony_ci } 2476c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE support not enabled\n"); 2477c87c5fbaSopenharmony_ci return 0; 2478c87c5fbaSopenharmony_ci} 2479c87c5fbaSopenharmony_ci 2480c87c5fbaSopenharmony_cistatic ssize_t 2481c87c5fbaSopenharmony_cicmdline_read_key(char *arg, unsigned char **buf, size_t maxlen) { 2482c87c5fbaSopenharmony_ci size_t len = strnlen(arg, maxlen); 2483c87c5fbaSopenharmony_ci if (len) { 2484c87c5fbaSopenharmony_ci *buf = (unsigned char *)arg; 2485c87c5fbaSopenharmony_ci return len; 2486c87c5fbaSopenharmony_ci } 2487c87c5fbaSopenharmony_ci /* Need at least one byte for the pre-shared key */ 2488c87c5fbaSopenharmony_ci coap_log_crit("Invalid Pre-Shared Key specified\n"); 2489c87c5fbaSopenharmony_ci return -1; 2490c87c5fbaSopenharmony_ci} 2491c87c5fbaSopenharmony_ci 2492c87c5fbaSopenharmony_cistatic int 2493c87c5fbaSopenharmony_cicmdline_read_psk_sni_check(char *arg) { 2494c87c5fbaSopenharmony_ci FILE *fp = fopen(arg, "r"); 2495c87c5fbaSopenharmony_ci static char tmpbuf[256]; 2496c87c5fbaSopenharmony_ci if (fp == NULL) { 2497c87c5fbaSopenharmony_ci coap_log_err("SNI file: %s: Unable to open\n", arg); 2498c87c5fbaSopenharmony_ci return 0; 2499c87c5fbaSopenharmony_ci } 2500c87c5fbaSopenharmony_ci while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { 2501c87c5fbaSopenharmony_ci char *cp = tmpbuf; 2502c87c5fbaSopenharmony_ci char *tcp = strchr(cp, '\n'); 2503c87c5fbaSopenharmony_ci 2504c87c5fbaSopenharmony_ci if (tmpbuf[0] == '#') 2505c87c5fbaSopenharmony_ci continue; 2506c87c5fbaSopenharmony_ci if (tcp) 2507c87c5fbaSopenharmony_ci *tcp = '\000'; 2508c87c5fbaSopenharmony_ci 2509c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 2510c87c5fbaSopenharmony_ci if (tcp) { 2511c87c5fbaSopenharmony_ci psk_sni_def_t *new_psk_sni_list; 2512c87c5fbaSopenharmony_ci new_psk_sni_list = realloc(valid_psk_snis.psk_sni_list, 2513c87c5fbaSopenharmony_ci (valid_psk_snis.count + 1)*sizeof(valid_psk_snis.psk_sni_list[0])); 2514c87c5fbaSopenharmony_ci if (new_psk_sni_list == NULL) { 2515c87c5fbaSopenharmony_ci break; 2516c87c5fbaSopenharmony_ci } 2517c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list = new_psk_sni_list; 2518c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list[valid_psk_snis.count].sni_match = strndup(cp, tcp-cp); 2519c87c5fbaSopenharmony_ci cp = tcp+1; 2520c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 2521c87c5fbaSopenharmony_ci if (tcp) { 2522c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list[valid_psk_snis.count].new_hint = 2523c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)cp, tcp-cp); 2524c87c5fbaSopenharmony_ci cp = tcp+1; 2525c87c5fbaSopenharmony_ci valid_psk_snis.psk_sni_list[valid_psk_snis.count].new_key = 2526c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)cp, strlen(cp)); 2527c87c5fbaSopenharmony_ci valid_psk_snis.count++; 2528c87c5fbaSopenharmony_ci } else { 2529c87c5fbaSopenharmony_ci free(valid_psk_snis.psk_sni_list[valid_psk_snis.count].sni_match); 2530c87c5fbaSopenharmony_ci } 2531c87c5fbaSopenharmony_ci } 2532c87c5fbaSopenharmony_ci } 2533c87c5fbaSopenharmony_ci fclose(fp); 2534c87c5fbaSopenharmony_ci return valid_psk_snis.count > 0; 2535c87c5fbaSopenharmony_ci} 2536c87c5fbaSopenharmony_ci 2537c87c5fbaSopenharmony_cistatic int 2538c87c5fbaSopenharmony_cicmdline_read_identity_check(char *arg) { 2539c87c5fbaSopenharmony_ci FILE *fp = fopen(arg, "r"); 2540c87c5fbaSopenharmony_ci static char tmpbuf[256]; 2541c87c5fbaSopenharmony_ci if (fp == NULL) { 2542c87c5fbaSopenharmony_ci coap_log_err("Identity file: %s: Unable to open\n", arg); 2543c87c5fbaSopenharmony_ci return 0; 2544c87c5fbaSopenharmony_ci } 2545c87c5fbaSopenharmony_ci while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { 2546c87c5fbaSopenharmony_ci char *cp = tmpbuf; 2547c87c5fbaSopenharmony_ci char *tcp = strchr(cp, '\n'); 2548c87c5fbaSopenharmony_ci 2549c87c5fbaSopenharmony_ci if (tmpbuf[0] == '#') 2550c87c5fbaSopenharmony_ci continue; 2551c87c5fbaSopenharmony_ci if (tcp) 2552c87c5fbaSopenharmony_ci *tcp = '\000'; 2553c87c5fbaSopenharmony_ci 2554c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 2555c87c5fbaSopenharmony_ci if (tcp) { 2556c87c5fbaSopenharmony_ci id_def_t *new_id_list; 2557c87c5fbaSopenharmony_ci new_id_list = realloc(valid_ids.id_list, 2558c87c5fbaSopenharmony_ci (valid_ids.count + 1)*sizeof(valid_ids.id_list[0])); 2559c87c5fbaSopenharmony_ci if (new_id_list == NULL) { 2560c87c5fbaSopenharmony_ci break; 2561c87c5fbaSopenharmony_ci } 2562c87c5fbaSopenharmony_ci valid_ids.id_list = new_id_list; 2563c87c5fbaSopenharmony_ci valid_ids.id_list[valid_ids.count].hint_match = strndup(cp, tcp-cp); 2564c87c5fbaSopenharmony_ci cp = tcp+1; 2565c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 2566c87c5fbaSopenharmony_ci if (tcp) { 2567c87c5fbaSopenharmony_ci valid_ids.id_list[valid_ids.count].identity_match = 2568c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)cp, tcp-cp); 2569c87c5fbaSopenharmony_ci cp = tcp+1; 2570c87c5fbaSopenharmony_ci valid_ids.id_list[valid_ids.count].new_key = 2571c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)cp, strlen(cp)); 2572c87c5fbaSopenharmony_ci valid_ids.count++; 2573c87c5fbaSopenharmony_ci } else { 2574c87c5fbaSopenharmony_ci free(valid_ids.id_list[valid_ids.count].hint_match); 2575c87c5fbaSopenharmony_ci } 2576c87c5fbaSopenharmony_ci } 2577c87c5fbaSopenharmony_ci } 2578c87c5fbaSopenharmony_ci fclose(fp); 2579c87c5fbaSopenharmony_ci return valid_ids.count > 0; 2580c87c5fbaSopenharmony_ci} 2581c87c5fbaSopenharmony_ci 2582c87c5fbaSopenharmony_cistatic int 2583c87c5fbaSopenharmony_cicmdline_unix(char *arg) { 2584c87c5fbaSopenharmony_ci if (!strcmp("coap", arg)) { 2585c87c5fbaSopenharmony_ci use_unix_proto = COAP_PROTO_UDP; 2586c87c5fbaSopenharmony_ci return 1; 2587c87c5fbaSopenharmony_ci } else if (!strcmp("coaps", arg)) { 2588c87c5fbaSopenharmony_ci if (!coap_dtls_is_supported()) { 2589c87c5fbaSopenharmony_ci coap_log_err("unix with dtls is not supported\n"); 2590c87c5fbaSopenharmony_ci return 0; 2591c87c5fbaSopenharmony_ci } 2592c87c5fbaSopenharmony_ci use_unix_proto = COAP_PROTO_DTLS; 2593c87c5fbaSopenharmony_ci return 1; 2594c87c5fbaSopenharmony_ci } else if (!strcmp("coap+tcp", arg)) { 2595c87c5fbaSopenharmony_ci if (!coap_tcp_is_supported()) { 2596c87c5fbaSopenharmony_ci coap_log_err("unix with stream is not supported\n"); 2597c87c5fbaSopenharmony_ci return 0; 2598c87c5fbaSopenharmony_ci } 2599c87c5fbaSopenharmony_ci use_unix_proto = COAP_PROTO_TCP; 2600c87c5fbaSopenharmony_ci return 1; 2601c87c5fbaSopenharmony_ci } else if (!strcmp("coaps+tcp", arg)) { 2602c87c5fbaSopenharmony_ci if (!coap_tls_is_supported()) { 2603c87c5fbaSopenharmony_ci coap_log_err("unix with tls is not supported\n"); 2604c87c5fbaSopenharmony_ci return 0; 2605c87c5fbaSopenharmony_ci } 2606c87c5fbaSopenharmony_ci use_unix_proto = COAP_PROTO_TLS; 2607c87c5fbaSopenharmony_ci return 1; 2608c87c5fbaSopenharmony_ci } 2609c87c5fbaSopenharmony_ci return 0; 2610c87c5fbaSopenharmony_ci} 2611c87c5fbaSopenharmony_ci 2612c87c5fbaSopenharmony_cistatic int 2613c87c5fbaSopenharmony_cicmdline_ws(char *arg) { 2614c87c5fbaSopenharmony_ci char *cp = strchr(arg, ','); 2615c87c5fbaSopenharmony_ci 2616c87c5fbaSopenharmony_ci if (cp) { 2617c87c5fbaSopenharmony_ci if (cp != arg) 2618c87c5fbaSopenharmony_ci ws_port = atoi(arg); 2619c87c5fbaSopenharmony_ci cp++; 2620c87c5fbaSopenharmony_ci if (*cp != '\000') 2621c87c5fbaSopenharmony_ci wss_port = atoi(cp); 2622c87c5fbaSopenharmony_ci } else { 2623c87c5fbaSopenharmony_ci ws_port = atoi(arg); 2624c87c5fbaSopenharmony_ci } 2625c87c5fbaSopenharmony_ci return 1; 2626c87c5fbaSopenharmony_ci} 2627c87c5fbaSopenharmony_ci 2628c87c5fbaSopenharmony_cistatic int 2629c87c5fbaSopenharmony_cicmdline_read_pki_sni_check(char *arg) { 2630c87c5fbaSopenharmony_ci FILE *fp = fopen(arg, "r"); 2631c87c5fbaSopenharmony_ci static char tmpbuf[256]; 2632c87c5fbaSopenharmony_ci if (fp == NULL) { 2633c87c5fbaSopenharmony_ci coap_log_err("SNI file: %s: Unable to open\n", arg); 2634c87c5fbaSopenharmony_ci return 0; 2635c87c5fbaSopenharmony_ci } 2636c87c5fbaSopenharmony_ci while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { 2637c87c5fbaSopenharmony_ci char *cp = tmpbuf; 2638c87c5fbaSopenharmony_ci char *tcp = strchr(cp, '\n'); 2639c87c5fbaSopenharmony_ci 2640c87c5fbaSopenharmony_ci if (tmpbuf[0] == '#') 2641c87c5fbaSopenharmony_ci continue; 2642c87c5fbaSopenharmony_ci if (tcp) 2643c87c5fbaSopenharmony_ci *tcp = '\000'; 2644c87c5fbaSopenharmony_ci 2645c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 2646c87c5fbaSopenharmony_ci if (tcp) { 2647c87c5fbaSopenharmony_ci pki_sni_def_t *new_pki_sni_list; 2648c87c5fbaSopenharmony_ci new_pki_sni_list = realloc(valid_pki_snis.pki_sni_list, 2649c87c5fbaSopenharmony_ci (valid_pki_snis.count + 1)*sizeof(valid_pki_snis.pki_sni_list[0])); 2650c87c5fbaSopenharmony_ci if (new_pki_sni_list == NULL) { 2651c87c5fbaSopenharmony_ci break; 2652c87c5fbaSopenharmony_ci } 2653c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list = new_pki_sni_list; 2654c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[valid_pki_snis.count].sni_match = 2655c87c5fbaSopenharmony_ci strndup(cp, tcp-cp); 2656c87c5fbaSopenharmony_ci cp = tcp+1; 2657c87c5fbaSopenharmony_ci tcp = strchr(cp, ','); 2658c87c5fbaSopenharmony_ci if (tcp) { 2659c87c5fbaSopenharmony_ci int fail = 0; 2660c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert = 2661c87c5fbaSopenharmony_ci strndup(cp, tcp-cp); 2662c87c5fbaSopenharmony_ci cp = tcp+1; 2663c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca = 2664c87c5fbaSopenharmony_ci strndup(cp, strlen(cp)); 2665c87c5fbaSopenharmony_ci if (access(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert, 2666c87c5fbaSopenharmony_ci R_OK)) { 2667c87c5fbaSopenharmony_ci coap_log_err("SNI file: Cert File: %s: Unable to access\n", 2668c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert); 2669c87c5fbaSopenharmony_ci fail = 1; 2670c87c5fbaSopenharmony_ci } 2671c87c5fbaSopenharmony_ci if (access(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca, 2672c87c5fbaSopenharmony_ci R_OK)) { 2673c87c5fbaSopenharmony_ci coap_log_err("SNI file: CA File: %s: Unable to access\n", 2674c87c5fbaSopenharmony_ci valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca); 2675c87c5fbaSopenharmony_ci fail = 1; 2676c87c5fbaSopenharmony_ci } 2677c87c5fbaSopenharmony_ci if (fail) { 2678c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].sni_match); 2679c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert); 2680c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca); 2681c87c5fbaSopenharmony_ci } else { 2682c87c5fbaSopenharmony_ci valid_pki_snis.count++; 2683c87c5fbaSopenharmony_ci } 2684c87c5fbaSopenharmony_ci } else { 2685c87c5fbaSopenharmony_ci coap_log_err("SNI file: SNI_match,Use_Cert_file,Use_CA_file not defined\n"); 2686c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].sni_match); 2687c87c5fbaSopenharmony_ci } 2688c87c5fbaSopenharmony_ci } 2689c87c5fbaSopenharmony_ci } 2690c87c5fbaSopenharmony_ci fclose(fp); 2691c87c5fbaSopenharmony_ci return valid_pki_snis.count > 0; 2692c87c5fbaSopenharmony_ci} 2693c87c5fbaSopenharmony_ci 2694c87c5fbaSopenharmony_cistatic int 2695c87c5fbaSopenharmony_cicmdline_read_extended_token_size(char *arg) { 2696c87c5fbaSopenharmony_ci extended_token_size = strtoul(arg, NULL, 0); 2697c87c5fbaSopenharmony_ci if (extended_token_size < COAP_TOKEN_DEFAULT_MAX) { 2698c87c5fbaSopenharmony_ci coap_log_err("Extended Token Length must be 8 or greater\n"); 2699c87c5fbaSopenharmony_ci return 0; 2700c87c5fbaSopenharmony_ci } else if (extended_token_size > COAP_TOKEN_EXT_MAX) { 2701c87c5fbaSopenharmony_ci coap_log_err("Extended Token Length must be 65804 or less\n"); 2702c87c5fbaSopenharmony_ci return 0; 2703c87c5fbaSopenharmony_ci } 2704c87c5fbaSopenharmony_ci return 1; 2705c87c5fbaSopenharmony_ci} 2706c87c5fbaSopenharmony_ci 2707c87c5fbaSopenharmony_ciint 2708c87c5fbaSopenharmony_cimain(int argc, char **argv) { 2709c87c5fbaSopenharmony_ci coap_context_t *ctx = NULL; 2710c87c5fbaSopenharmony_ci char *group = NULL; 2711c87c5fbaSopenharmony_ci char *group_if = NULL; 2712c87c5fbaSopenharmony_ci coap_tick_t now; 2713c87c5fbaSopenharmony_ci char addr_str[NI_MAXHOST] = "::"; 2714c87c5fbaSopenharmony_ci char *port_str = NULL; 2715c87c5fbaSopenharmony_ci int opt; 2716c87c5fbaSopenharmony_ci int mcast_per_resource = 0; 2717c87c5fbaSopenharmony_ci coap_log_t log_level = COAP_LOG_WARN; 2718c87c5fbaSopenharmony_ci coap_log_t dtls_log_level = COAP_LOG_ERR; 2719c87c5fbaSopenharmony_ci unsigned wait_ms; 2720c87c5fbaSopenharmony_ci coap_time_t t_last = 0; 2721c87c5fbaSopenharmony_ci int coap_fd; 2722c87c5fbaSopenharmony_ci fd_set m_readfds; 2723c87c5fbaSopenharmony_ci int nfds = 0; 2724c87c5fbaSopenharmony_ci size_t i; 2725c87c5fbaSopenharmony_ci int exit_code = 0; 2726c87c5fbaSopenharmony_ci uint16_t cache_ignore_options[] = { COAP_OPTION_BLOCK1, 2727c87c5fbaSopenharmony_ci COAP_OPTION_BLOCK2, 2728c87c5fbaSopenharmony_ci /* See https://rfc-editor.org/rfc/rfc7959#section-2.10 */ 2729c87c5fbaSopenharmony_ci COAP_OPTION_MAXAGE, 2730c87c5fbaSopenharmony_ci /* See https://rfc-editor.org/rfc/rfc7959#section-2.10 */ 2731c87c5fbaSopenharmony_ci COAP_OPTION_IF_NONE_MATCH 2732c87c5fbaSopenharmony_ci }; 2733c87c5fbaSopenharmony_ci#ifndef _WIN32 2734c87c5fbaSopenharmony_ci struct sigaction sa; 2735c87c5fbaSopenharmony_ci#endif 2736c87c5fbaSopenharmony_ci 2737c87c5fbaSopenharmony_ci /* Initialize libcoap library */ 2738c87c5fbaSopenharmony_ci coap_startup(); 2739c87c5fbaSopenharmony_ci 2740c87c5fbaSopenharmony_ci clock_offset = time(NULL); 2741c87c5fbaSopenharmony_ci 2742c87c5fbaSopenharmony_ci while ((opt = getopt(argc, argv, 2743c87c5fbaSopenharmony_ci "c:d:eg:G:h:i:j:J:k:l:mnp:rs:tu:v:w:A:C:E:L:M:NP:R:S:T:U:V:X:")) != -1) { 2744c87c5fbaSopenharmony_ci switch (opt) { 2745c87c5fbaSopenharmony_ci case 'A' : 2746c87c5fbaSopenharmony_ci strncpy(addr_str, optarg, NI_MAXHOST-1); 2747c87c5fbaSopenharmony_ci addr_str[NI_MAXHOST - 1] = '\0'; 2748c87c5fbaSopenharmony_ci break; 2749c87c5fbaSopenharmony_ci case 'c' : 2750c87c5fbaSopenharmony_ci cert_file = optarg; 2751c87c5fbaSopenharmony_ci break; 2752c87c5fbaSopenharmony_ci case 'C' : 2753c87c5fbaSopenharmony_ci ca_file = optarg; 2754c87c5fbaSopenharmony_ci break; 2755c87c5fbaSopenharmony_ci case 'd' : 2756c87c5fbaSopenharmony_ci support_dynamic = atoi(optarg); 2757c87c5fbaSopenharmony_ci break; 2758c87c5fbaSopenharmony_ci case 'e': 2759c87c5fbaSopenharmony_ci echo_back = 1; 2760c87c5fbaSopenharmony_ci break; 2761c87c5fbaSopenharmony_ci case 'E': 2762c87c5fbaSopenharmony_ci doing_oscore = cmdline_oscore(optarg); 2763c87c5fbaSopenharmony_ci if (!doing_oscore) { 2764c87c5fbaSopenharmony_ci goto failed; 2765c87c5fbaSopenharmony_ci } 2766c87c5fbaSopenharmony_ci break; 2767c87c5fbaSopenharmony_ci case 'g' : 2768c87c5fbaSopenharmony_ci group = optarg; 2769c87c5fbaSopenharmony_ci break; 2770c87c5fbaSopenharmony_ci case 'G' : 2771c87c5fbaSopenharmony_ci group_if = optarg; 2772c87c5fbaSopenharmony_ci break; 2773c87c5fbaSopenharmony_ci case 'h' : 2774c87c5fbaSopenharmony_ci if (!optarg[0]) { 2775c87c5fbaSopenharmony_ci hint = NULL; 2776c87c5fbaSopenharmony_ci break; 2777c87c5fbaSopenharmony_ci } 2778c87c5fbaSopenharmony_ci hint = optarg; 2779c87c5fbaSopenharmony_ci break; 2780c87c5fbaSopenharmony_ci case 'i': 2781c87c5fbaSopenharmony_ci if (!cmdline_read_identity_check(optarg)) { 2782c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 2783c87c5fbaSopenharmony_ci goto failed; 2784c87c5fbaSopenharmony_ci } 2785c87c5fbaSopenharmony_ci break; 2786c87c5fbaSopenharmony_ci case 'j' : 2787c87c5fbaSopenharmony_ci key_file = optarg; 2788c87c5fbaSopenharmony_ci break; 2789c87c5fbaSopenharmony_ci case 'J' : 2790c87c5fbaSopenharmony_ci pkcs11_pin = optarg; 2791c87c5fbaSopenharmony_ci break; 2792c87c5fbaSopenharmony_ci case 'k' : 2793c87c5fbaSopenharmony_ci key_length = cmdline_read_key(optarg, &key, MAX_KEY); 2794c87c5fbaSopenharmony_ci if (key_length < 0) { 2795c87c5fbaSopenharmony_ci break; 2796c87c5fbaSopenharmony_ci } 2797c87c5fbaSopenharmony_ci key_defined = 1; 2798c87c5fbaSopenharmony_ci break; 2799c87c5fbaSopenharmony_ci case 'l': 2800c87c5fbaSopenharmony_ci if (!coap_debug_set_packet_loss(optarg)) { 2801c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 2802c87c5fbaSopenharmony_ci goto failed; 2803c87c5fbaSopenharmony_ci } 2804c87c5fbaSopenharmony_ci break; 2805c87c5fbaSopenharmony_ci case 'L': 2806c87c5fbaSopenharmony_ci block_mode = strtoul(optarg, NULL, 0); 2807c87c5fbaSopenharmony_ci if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) { 2808c87c5fbaSopenharmony_ci fprintf(stderr, "Block mode must include COAP_BLOCK_USE_LIBCOAP (1)\n"); 2809c87c5fbaSopenharmony_ci goto failed; 2810c87c5fbaSopenharmony_ci } 2811c87c5fbaSopenharmony_ci break; 2812c87c5fbaSopenharmony_ci case 'm': 2813c87c5fbaSopenharmony_ci use_pem_buf = 1; 2814c87c5fbaSopenharmony_ci break; 2815c87c5fbaSopenharmony_ci case 'M': 2816c87c5fbaSopenharmony_ci cert_file = optarg; 2817c87c5fbaSopenharmony_ci is_rpk_not_cert = 1; 2818c87c5fbaSopenharmony_ci break; 2819c87c5fbaSopenharmony_ci case 'n': 2820c87c5fbaSopenharmony_ci verify_peer_cert = 0; 2821c87c5fbaSopenharmony_ci break; 2822c87c5fbaSopenharmony_ci case 'N': 2823c87c5fbaSopenharmony_ci resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_NON; 2824c87c5fbaSopenharmony_ci break; 2825c87c5fbaSopenharmony_ci case 'p' : 2826c87c5fbaSopenharmony_ci port_str = optarg; 2827c87c5fbaSopenharmony_ci break; 2828c87c5fbaSopenharmony_ci case 'P': 2829c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 2830c87c5fbaSopenharmony_ci if (!cmdline_proxy(optarg)) { 2831c87c5fbaSopenharmony_ci fprintf(stderr, "error specifying proxy address or host names\n"); 2832c87c5fbaSopenharmony_ci goto failed; 2833c87c5fbaSopenharmony_ci } 2834c87c5fbaSopenharmony_ci block_mode |= COAP_BLOCK_SINGLE_BODY; 2835c87c5fbaSopenharmony_ci#else /* ! SERVER_CAN_PROXY */ 2836c87c5fbaSopenharmony_ci fprintf(stderr, "Proxy support not available as no Client mode code\n"); 2837c87c5fbaSopenharmony_ci goto failed; 2838c87c5fbaSopenharmony_ci#endif /* ! SERVER_CAN_PROXY */ 2839c87c5fbaSopenharmony_ci break; 2840c87c5fbaSopenharmony_ci case 'r' : 2841c87c5fbaSopenharmony_ci mcast_per_resource = 1; 2842c87c5fbaSopenharmony_ci break; 2843c87c5fbaSopenharmony_ci case 'R' : 2844c87c5fbaSopenharmony_ci root_ca_file = optarg; 2845c87c5fbaSopenharmony_ci break; 2846c87c5fbaSopenharmony_ci case 's': 2847c87c5fbaSopenharmony_ci if (!cmdline_read_psk_sni_check(optarg)) { 2848c87c5fbaSopenharmony_ci goto failed; 2849c87c5fbaSopenharmony_ci } 2850c87c5fbaSopenharmony_ci break; 2851c87c5fbaSopenharmony_ci case 'S': 2852c87c5fbaSopenharmony_ci if (!cmdline_read_pki_sni_check(optarg)) { 2853c87c5fbaSopenharmony_ci goto failed; 2854c87c5fbaSopenharmony_ci } 2855c87c5fbaSopenharmony_ci break; 2856c87c5fbaSopenharmony_ci case 'T': 2857c87c5fbaSopenharmony_ci if (!cmdline_read_extended_token_size(optarg)) { 2858c87c5fbaSopenharmony_ci goto failed; 2859c87c5fbaSopenharmony_ci } 2860c87c5fbaSopenharmony_ci break; 2861c87c5fbaSopenharmony_ci case 't': 2862c87c5fbaSopenharmony_ci track_observes = 1; 2863c87c5fbaSopenharmony_ci break; 2864c87c5fbaSopenharmony_ci case 'u': 2865c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 2866c87c5fbaSopenharmony_ci user_length = cmdline_read_user(optarg, &user, MAX_USER); 2867c87c5fbaSopenharmony_ci#else /* ! SERVER_CAN_PROXY */ 2868c87c5fbaSopenharmony_ci fprintf(stderr, "Proxy support not available as no Client mode code\n"); 2869c87c5fbaSopenharmony_ci goto failed; 2870c87c5fbaSopenharmony_ci#endif /* ! SERVER_CAN_PROXY */ 2871c87c5fbaSopenharmony_ci break; 2872c87c5fbaSopenharmony_ci case 'U': 2873c87c5fbaSopenharmony_ci if (!cmdline_unix(optarg)) { 2874c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 2875c87c5fbaSopenharmony_ci goto failed; 2876c87c5fbaSopenharmony_ci } 2877c87c5fbaSopenharmony_ci break; 2878c87c5fbaSopenharmony_ci case 'v' : 2879c87c5fbaSopenharmony_ci log_level = strtol(optarg, NULL, 10); 2880c87c5fbaSopenharmony_ci break; 2881c87c5fbaSopenharmony_ci case 'V': 2882c87c5fbaSopenharmony_ci dtls_log_level = strtol(optarg, NULL, 10); 2883c87c5fbaSopenharmony_ci break; 2884c87c5fbaSopenharmony_ci case 'w': 2885c87c5fbaSopenharmony_ci if (!coap_ws_is_supported() || !cmdline_ws(optarg)) { 2886c87c5fbaSopenharmony_ci fprintf(stderr, "WebSockets not enabled in libcoap\n"); 2887c87c5fbaSopenharmony_ci exit(1); 2888c87c5fbaSopenharmony_ci } 2889c87c5fbaSopenharmony_ci enable_ws = 1; 2890c87c5fbaSopenharmony_ci break; 2891c87c5fbaSopenharmony_ci case 'X': 2892c87c5fbaSopenharmony_ci csm_max_message_size = strtol(optarg, NULL, 10); 2893c87c5fbaSopenharmony_ci break; 2894c87c5fbaSopenharmony_ci default: 2895c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 2896c87c5fbaSopenharmony_ci goto failed; 2897c87c5fbaSopenharmony_ci } 2898c87c5fbaSopenharmony_ci } 2899c87c5fbaSopenharmony_ci 2900c87c5fbaSopenharmony_ci#ifdef _WIN32 2901c87c5fbaSopenharmony_ci signal(SIGINT, handle_sigint); 2902c87c5fbaSopenharmony_ci#else 2903c87c5fbaSopenharmony_ci memset(&sa, 0, sizeof(sa)); 2904c87c5fbaSopenharmony_ci sigemptyset(&sa.sa_mask); 2905c87c5fbaSopenharmony_ci sa.sa_handler = handle_sigint; 2906c87c5fbaSopenharmony_ci sa.sa_flags = 0; 2907c87c5fbaSopenharmony_ci sigaction(SIGINT, &sa, NULL); 2908c87c5fbaSopenharmony_ci sigaction(SIGTERM, &sa, NULL); 2909c87c5fbaSopenharmony_ci sa.sa_handler = handle_sigusr2; 2910c87c5fbaSopenharmony_ci sigaction(SIGUSR2, &sa, NULL); 2911c87c5fbaSopenharmony_ci /* So we do not exit on a SIGPIPE */ 2912c87c5fbaSopenharmony_ci sa.sa_handler = SIG_IGN; 2913c87c5fbaSopenharmony_ci sigaction(SIGPIPE, &sa, NULL); 2914c87c5fbaSopenharmony_ci#endif 2915c87c5fbaSopenharmony_ci 2916c87c5fbaSopenharmony_ci coap_set_log_level(log_level); 2917c87c5fbaSopenharmony_ci coap_dtls_set_log_level(dtls_log_level); 2918c87c5fbaSopenharmony_ci 2919c87c5fbaSopenharmony_ci ctx = get_context(addr_str, port_str); 2920c87c5fbaSopenharmony_ci if (!ctx) 2921c87c5fbaSopenharmony_ci return -1; 2922c87c5fbaSopenharmony_ci 2923c87c5fbaSopenharmony_ci init_resources(ctx); 2924c87c5fbaSopenharmony_ci if (mcast_per_resource) 2925c87c5fbaSopenharmony_ci coap_mcast_per_resource(ctx); 2926c87c5fbaSopenharmony_ci coap_context_set_block_mode(ctx, block_mode); 2927c87c5fbaSopenharmony_ci if (csm_max_message_size) 2928c87c5fbaSopenharmony_ci coap_context_set_csm_max_message_size(ctx, csm_max_message_size); 2929c87c5fbaSopenharmony_ci if (doing_oscore) { 2930c87c5fbaSopenharmony_ci if (get_oscore_conf(ctx) == NULL) 2931c87c5fbaSopenharmony_ci goto failed; 2932c87c5fbaSopenharmony_ci } 2933c87c5fbaSopenharmony_ci if (extended_token_size > COAP_TOKEN_DEFAULT_MAX) 2934c87c5fbaSopenharmony_ci coap_context_set_max_token_size(ctx, extended_token_size); 2935c87c5fbaSopenharmony_ci 2936c87c5fbaSopenharmony_ci /* Define the options to ignore when setting up cache-keys */ 2937c87c5fbaSopenharmony_ci coap_cache_ignore_options(ctx, cache_ignore_options, 2938c87c5fbaSopenharmony_ci sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0])); 2939c87c5fbaSopenharmony_ci /* join multicast group if requested at command line */ 2940c87c5fbaSopenharmony_ci if (group) 2941c87c5fbaSopenharmony_ci coap_join_mcast_group_intf(ctx, group, group_if); 2942c87c5fbaSopenharmony_ci 2943c87c5fbaSopenharmony_ci if (track_observes) { 2944c87c5fbaSopenharmony_ci /* 2945c87c5fbaSopenharmony_ci * Read in and set up appropriate persist information. 2946c87c5fbaSopenharmony_ci * Note that this should be done after ctx is properly set up. 2947c87c5fbaSopenharmony_ci */ 2948c87c5fbaSopenharmony_ci if (!coap_persist_startup(ctx, 2949c87c5fbaSopenharmony_ci "/tmp/coap_dyn_resource_save_file", 2950c87c5fbaSopenharmony_ci "/tmp/coap_observe_save_file", 2951c87c5fbaSopenharmony_ci "/tmp/coap_obs_cnt_save_file", 10)) { 2952c87c5fbaSopenharmony_ci fprintf(stderr, "Unable to set up persist logic\n"); 2953c87c5fbaSopenharmony_ci goto finish; 2954c87c5fbaSopenharmony_ci } 2955c87c5fbaSopenharmony_ci } 2956c87c5fbaSopenharmony_ci 2957c87c5fbaSopenharmony_ci coap_fd = coap_context_get_coap_fd(ctx); 2958c87c5fbaSopenharmony_ci if (coap_fd != -1) { 2959c87c5fbaSopenharmony_ci /* if coap_fd is -1, then epoll is not supported within libcoap */ 2960c87c5fbaSopenharmony_ci FD_ZERO(&m_readfds); 2961c87c5fbaSopenharmony_ci FD_SET(coap_fd, &m_readfds); 2962c87c5fbaSopenharmony_ci nfds = coap_fd + 1; 2963c87c5fbaSopenharmony_ci } 2964c87c5fbaSopenharmony_ci 2965c87c5fbaSopenharmony_ci wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; 2966c87c5fbaSopenharmony_ci 2967c87c5fbaSopenharmony_ci while (!quit) { 2968c87c5fbaSopenharmony_ci int result; 2969c87c5fbaSopenharmony_ci 2970c87c5fbaSopenharmony_ci if (coap_fd != -1) { 2971c87c5fbaSopenharmony_ci /* 2972c87c5fbaSopenharmony_ci * Using epoll. It is more usual to call coap_io_process() with wait_ms 2973c87c5fbaSopenharmony_ci * (as in the non-epoll branch), but doing it this way gives the 2974c87c5fbaSopenharmony_ci * flexibility of potentially working with other file descriptors that 2975c87c5fbaSopenharmony_ci * are not a part of libcoap. 2976c87c5fbaSopenharmony_ci */ 2977c87c5fbaSopenharmony_ci fd_set readfds = m_readfds; 2978c87c5fbaSopenharmony_ci struct timeval tv; 2979c87c5fbaSopenharmony_ci coap_tick_t begin, end; 2980c87c5fbaSopenharmony_ci 2981c87c5fbaSopenharmony_ci coap_ticks(&begin); 2982c87c5fbaSopenharmony_ci 2983c87c5fbaSopenharmony_ci tv.tv_sec = wait_ms / 1000; 2984c87c5fbaSopenharmony_ci tv.tv_usec = (wait_ms % 1000) * 1000; 2985c87c5fbaSopenharmony_ci /* Wait until any i/o takes place or timeout */ 2986c87c5fbaSopenharmony_ci result = select(nfds, &readfds, NULL, NULL, &tv); 2987c87c5fbaSopenharmony_ci if (result == -1) { 2988c87c5fbaSopenharmony_ci if (errno != EAGAIN) { 2989c87c5fbaSopenharmony_ci coap_log_debug("select: %s (%d)\n", coap_socket_strerror(), errno); 2990c87c5fbaSopenharmony_ci break; 2991c87c5fbaSopenharmony_ci } 2992c87c5fbaSopenharmony_ci } 2993c87c5fbaSopenharmony_ci if (result > 0) { 2994c87c5fbaSopenharmony_ci if (FD_ISSET(coap_fd, &readfds)) { 2995c87c5fbaSopenharmony_ci result = coap_io_process(ctx, COAP_IO_NO_WAIT); 2996c87c5fbaSopenharmony_ci } 2997c87c5fbaSopenharmony_ci } 2998c87c5fbaSopenharmony_ci if (result >= 0) { 2999c87c5fbaSopenharmony_ci coap_ticks(&end); 3000c87c5fbaSopenharmony_ci /* Track the overall time spent in select() and coap_io_process() */ 3001c87c5fbaSopenharmony_ci result = (int)(end - begin); 3002c87c5fbaSopenharmony_ci } 3003c87c5fbaSopenharmony_ci } else { 3004c87c5fbaSopenharmony_ci /* 3005c87c5fbaSopenharmony_ci * epoll is not supported within libcoap 3006c87c5fbaSopenharmony_ci * 3007c87c5fbaSopenharmony_ci * result is time spent in coap_io_process() 3008c87c5fbaSopenharmony_ci */ 3009c87c5fbaSopenharmony_ci result = coap_io_process(ctx, wait_ms); 3010c87c5fbaSopenharmony_ci } 3011c87c5fbaSopenharmony_ci if (result < 0) { 3012c87c5fbaSopenharmony_ci break; 3013c87c5fbaSopenharmony_ci } else if (result && (unsigned)result < wait_ms) { 3014c87c5fbaSopenharmony_ci /* decrement if there is a result wait time returned */ 3015c87c5fbaSopenharmony_ci wait_ms -= result; 3016c87c5fbaSopenharmony_ci } else { 3017c87c5fbaSopenharmony_ci /* 3018c87c5fbaSopenharmony_ci * result == 0, or result >= wait_ms 3019c87c5fbaSopenharmony_ci * (wait_ms could have decremented to a small value, below 3020c87c5fbaSopenharmony_ci * the granularity of the timer in coap_io_process() and hence 3021c87c5fbaSopenharmony_ci * result == 0) 3022c87c5fbaSopenharmony_ci */ 3023c87c5fbaSopenharmony_ci wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; 3024c87c5fbaSopenharmony_ci } 3025c87c5fbaSopenharmony_ci if (time_resource) { 3026c87c5fbaSopenharmony_ci coap_time_t t_now; 3027c87c5fbaSopenharmony_ci unsigned int next_sec_ms; 3028c87c5fbaSopenharmony_ci 3029c87c5fbaSopenharmony_ci coap_ticks(&now); 3030c87c5fbaSopenharmony_ci t_now = coap_ticks_to_rt(now); 3031c87c5fbaSopenharmony_ci if (t_last != t_now) { 3032c87c5fbaSopenharmony_ci /* Happens once per second */ 3033c87c5fbaSopenharmony_ci t_last = t_now; 3034c87c5fbaSopenharmony_ci coap_resource_notify_observers(time_resource, NULL); 3035c87c5fbaSopenharmony_ci } 3036c87c5fbaSopenharmony_ci /* need to wait until next second starts if wait_ms is too large */ 3037c87c5fbaSopenharmony_ci next_sec_ms = 1000 - (now % COAP_TICKS_PER_SECOND) * 3038c87c5fbaSopenharmony_ci 1000 / COAP_TICKS_PER_SECOND; 3039c87c5fbaSopenharmony_ci if (next_sec_ms && next_sec_ms < wait_ms) 3040c87c5fbaSopenharmony_ci wait_ms = next_sec_ms; 3041c87c5fbaSopenharmony_ci } 3042c87c5fbaSopenharmony_ci } 3043c87c5fbaSopenharmony_ci exit_code = 0; 3044c87c5fbaSopenharmony_ci 3045c87c5fbaSopenharmony_cifinish: 3046c87c5fbaSopenharmony_ci /* Clean up local usage */ 3047c87c5fbaSopenharmony_ci if (keep_persist) 3048c87c5fbaSopenharmony_ci coap_persist_stop(ctx); 3049c87c5fbaSopenharmony_ci 3050c87c5fbaSopenharmony_ci coap_free(ca_mem); 3051c87c5fbaSopenharmony_ci coap_free(cert_mem); 3052c87c5fbaSopenharmony_ci coap_free(key_mem); 3053c87c5fbaSopenharmony_ci coap_free(ca_mem_base); 3054c87c5fbaSopenharmony_ci coap_free(cert_mem_base); 3055c87c5fbaSopenharmony_ci coap_free(key_mem_base); 3056c87c5fbaSopenharmony_ci for (i = 0; i < valid_psk_snis.count; i++) { 3057c87c5fbaSopenharmony_ci free(valid_psk_snis.psk_sni_list[i].sni_match); 3058c87c5fbaSopenharmony_ci coap_delete_bin_const(valid_psk_snis.psk_sni_list[i].new_hint); 3059c87c5fbaSopenharmony_ci coap_delete_bin_const(valid_psk_snis.psk_sni_list[i].new_key); 3060c87c5fbaSopenharmony_ci } 3061c87c5fbaSopenharmony_ci if (valid_psk_snis.count) 3062c87c5fbaSopenharmony_ci free(valid_psk_snis.psk_sni_list); 3063c87c5fbaSopenharmony_ci 3064c87c5fbaSopenharmony_ci for (i = 0; i < valid_ids.count; i++) { 3065c87c5fbaSopenharmony_ci free(valid_ids.id_list[i].hint_match); 3066c87c5fbaSopenharmony_ci coap_delete_bin_const(valid_ids.id_list[i].identity_match); 3067c87c5fbaSopenharmony_ci coap_delete_bin_const(valid_ids.id_list[i].new_key); 3068c87c5fbaSopenharmony_ci } 3069c87c5fbaSopenharmony_ci if (valid_ids.count) 3070c87c5fbaSopenharmony_ci free(valid_ids.id_list); 3071c87c5fbaSopenharmony_ci 3072c87c5fbaSopenharmony_ci for (i = 0; i < valid_pki_snis.count; i++) { 3073c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[i].sni_match); 3074c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[i].new_cert); 3075c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list[i].new_ca); 3076c87c5fbaSopenharmony_ci } 3077c87c5fbaSopenharmony_ci if (valid_pki_snis.count) 3078c87c5fbaSopenharmony_ci free(valid_pki_snis.pki_sni_list); 3079c87c5fbaSopenharmony_ci 3080c87c5fbaSopenharmony_ci for (i = 0; i < (size_t)dynamic_count; i++) { 3081c87c5fbaSopenharmony_ci coap_delete_string(dynamic_entry[i].uri_path); 3082c87c5fbaSopenharmony_ci release_resource_data(NULL, dynamic_entry[i].value); 3083c87c5fbaSopenharmony_ci } 3084c87c5fbaSopenharmony_ci free(dynamic_entry); 3085c87c5fbaSopenharmony_ci release_resource_data(NULL, example_data_value); 3086c87c5fbaSopenharmony_ci#if SERVER_CAN_PROXY 3087c87c5fbaSopenharmony_ci for (i = 0; i < proxy_list_count; i++) { 3088c87c5fbaSopenharmony_ci coap_delete_binary(proxy_list[i].token); 3089c87c5fbaSopenharmony_ci coap_delete_string(proxy_list[i].query); 3090c87c5fbaSopenharmony_ci } 3091c87c5fbaSopenharmony_ci free(proxy_list); 3092c87c5fbaSopenharmony_ci proxy_list = NULL; 3093c87c5fbaSopenharmony_ci proxy_list_count = 0; 3094c87c5fbaSopenharmony_ci#if defined(_WIN32) && !defined(__MINGW32__) 3095c87c5fbaSopenharmony_ci#pragma warning( disable : 4090 ) 3096c87c5fbaSopenharmony_ci#endif 3097c87c5fbaSopenharmony_ci coap_free(proxy_host_name_list); 3098c87c5fbaSopenharmony_ci#endif /* SERVER_CAN_PROXY */ 3099c87c5fbaSopenharmony_ci if (oscore_seq_num_fp) 3100c87c5fbaSopenharmony_ci fclose(oscore_seq_num_fp); 3101c87c5fbaSopenharmony_ci 3102c87c5fbaSopenharmony_ci /* Clean up library usage */ 3103c87c5fbaSopenharmony_ci coap_free_context(ctx); 3104c87c5fbaSopenharmony_ci coap_cleanup(); 3105c87c5fbaSopenharmony_ci 3106c87c5fbaSopenharmony_ci return exit_code; 3107c87c5fbaSopenharmony_ci 3108c87c5fbaSopenharmony_cifailed: 3109c87c5fbaSopenharmony_ci exit_code = 1; 3110c87c5fbaSopenharmony_ci goto finish; 3111c87c5fbaSopenharmony_ci} 3112