From 21bd1df95b8e9fcbaa09fa1326513a5ab33ca2a7 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Wed, 31 May 2023 21:20:07 +0100 Subject: [PATCH] examples: Remove references to sockaddr* structures This means that apps need to have no knowledge of what IP support is available. Updates coap_uri_into_options() and coap_resolve_address_info() which have only been recently added to develop branch and are not in any previous release. --- examples/coap-client.c | 77 +++++-------------- examples/coap-rd.c | 46 ++--------- examples/coap-server.c | 9 ++- examples/lwip/client-coap.c | 5 +- examples/lwip/server-coap.c | 3 +- .../examples_libcoap_client/client-coap.c | 5 +- .../examples_libcoap_server/server-coap.c | 3 +- examples/riot/pkg_libcoap/Makefile | 4 +- examples/tiny.c | 2 +- include/coap3/coap_address.h | 36 +++++---- include/coap3/coap_forward_decls.h | 2 + include/coap3/coap_uri.h | 20 +++-- man/Makefile.am | 2 + man/coap-client.txt.in | 2 +- man/coap_address.txt.in | 31 ++++++-- man/coap_logging.txt.in | 28 ++++++- man/coap_uri.txt.in | 15 ++-- src/coap_address.c | 75 ++++++++++-------- src/coap_uri.c | 36 +++++++-- 19 files changed, 220 insertions(+), 181 deletions(-) diff --git a/examples/coap-client.c b/examples/coap-client.c index 2fab0934..a8dd030d 100644 --- a/examples/coap-client.c +++ b/examples/coap-client.c @@ -522,7 +522,7 @@ usage(const char *program, const char *version) { "\t-m method\tRequest method (get|put|post|delete|fetch|patch|ipatch),\n" "\t \t\tdefault is 'get'\n" "\t-o file\t\tOutput received data to this file (use '-' for STDOUT)\n" - "\t-p port\t\tListen on specified port\n" + "\t-p port\t\tSend from the specified port\n" "\t-r \t\tUse reliable protocol (TCP or TLS); requires TCP support\n" "\t-s duration\tSubscribe to / Observe resource for given duration\n" "\t \t\tin seconds\n" @@ -819,9 +819,7 @@ cmdline_oscore(char *arg) { * @return 0 on success, -1 otherwise */ static int -cmdline_uri(char *arg, int create_uri_opts) { -#define BUFSIZE 100 - unsigned char buf[BUFSIZE]; +cmdline_uri(char *arg) { if (!proxy_scheme_option && proxy.host.length) { /* create Proxy-Uri from argument */ @@ -863,13 +861,6 @@ cmdline_uri(char *arg, int create_uri_opts) { uri.scheme = COAP_URI_SCHEME_COAP_TCP; } } - - /* COAP_OPTION_URI_HOST will get done later */ - if (coap_uri_into_options(&uri, &optlist, create_uri_opts, - buf, sizeof(buf)) < 0) { - coap_log_err("Failed to create options for URI\n"); - return -1; - } } return 0; } @@ -1522,7 +1513,7 @@ get_session(coap_context_t *ctx, snprintf(buf, COAP_UNIX_PATH_MAX, "/tmp/coap-client.%d", (int)getpid()); coap_address_set_unix_domain(&bind_addr, (const uint8_t *)buf, strlen(buf)); - remove(bind_addr.addr.cun.sun_path); + remove(buf); } session = open_session(ctx, proto, &bind_addr, dst, identity, identity_len, key, key_len); @@ -1537,7 +1528,8 @@ get_session(coap_context_t *ctx, /* resolve local address where data should be sent from */ info_list = coap_resolve_address_info(&local, port, port, AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL, - 1 << scheme); + 1 << scheme, + COAP_RESOLVE_TYPE_LOCAL); if (!info_list) { fprintf(stderr, "coap_resolve_address_info: %s: failed\n", local_addr); return NULL; @@ -1545,13 +1537,6 @@ get_session(coap_context_t *ctx, /* iterate through results until success */ for (info = info_list; info != NULL; info = info->next ) { - if (!local_port) { - /* Need to reset port back to 0 rather than the default */ - if (info->addr.addr.sa.sa_family == AF_INET) - info->addr.addr.sin.sin_port = htons(port); - else if (info->addr.addr.sa.sa_family == AF_INET6) - info->addr.addr.sin6.sin6_port = htons(port); - } session = open_session(ctx, proto, &info->addr, dst, identity, identity_len, key, key_len); if (session) @@ -1565,8 +1550,7 @@ get_session(coap_context_t *ctx, coap_address_init(&bind_addr); bind_addr.size = dst->size; bind_addr.addr.sa.sa_family = dst->addr.sa.sa_family; - /* port is in same place for IPv4 and IPv6 */ - bind_addr.addr.sin.sin_port = ntohs(atoi(local_port)); + coap_address_set_port(&bind_addr, atoi(local_port)); session = open_session(ctx, proto, &bind_addr, dst, identity, identity_len, key, key_len); } else { @@ -1581,8 +1565,6 @@ main(int argc, char **argv) { coap_context_t *ctx = NULL; coap_session_t *session = NULL; coap_address_t dst; - static char addr[INET6_ADDRSTRLEN]; - void *addrptr = NULL; int result = -1; int exit_code = 0; coap_pdu_t *pdu; @@ -1603,6 +1585,8 @@ main(int argc, char **argv) { uint8_t *data = NULL; size_t data_len = 0; coap_addr_info_t *info_list = NULL; +#define BUFSIZE 100 + static unsigned char buf[BUFSIZE]; #ifndef _WIN32 struct sigaction sa; #endif @@ -1780,7 +1764,7 @@ main(int argc, char **argv) { coap_dtls_set_log_level(dtls_log_level); if (optind < argc) { - if (cmdline_uri(argv[optind], create_uri_opts) < 0) { + if (cmdline_uri(argv[optind]) < 0) { goto failed; } } else { @@ -1806,7 +1790,8 @@ main(int argc, char **argv) { /* resolve destination address where data should be sent */ info_list = coap_resolve_address_info(&server, port, port, 0, - 1 << scheme); + 1 << scheme, + COAP_RESOLVE_TYPE_REMOTE); if (info_list == NULL) { coap_log_err("failed to resolve address\n"); @@ -1861,39 +1846,13 @@ main(int argc, char **argv) { */ coap_session_init_token(session, the_token.length, the_token.s); - /* add Uri-Host if server address differs from uri.host */ - - - /* Add in Uri-Host option if appropriate */ - if (!uri_host_option && dst.addr.sa.sa_family != AF_UNIX && - !proxy.host.length && uri.host.length && create_uri_opts) { - size_t uri_host_len = uri.host.length; - uint8_t* cp = (uint8_t*)strchr((const char*)uri.host.s, '%'); - - if (cp && (size_t)(cp - uri.host.s) < uri_host_len) - /* %iface specified in host name */ - uri_host_len = cp - uri.host.s; - - switch (dst.addr.sa.sa_family) { - case AF_INET: - addrptr = &dst.addr.sin.sin_addr; - break; - case AF_INET6: - addrptr = &dst.addr.sin6.sin6_addr; - break; - default: - ; - } - if (addrptr && - (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0) && - (strlen(addr) != uri_host_len || - memcmp(addr, uri.host.s, uri_host_len) != 0)) { - /* add Uri-Host */ - coap_insert_optlist(&optlist, - coap_new_optlist(COAP_OPTION_URI_HOST, - uri.host.length, - uri.host.s)); - } + /* Convert provided uri into CoAP options */ + if (coap_uri_into_options(&uri, !uri_host_option && !proxy.host.length ? + &dst : NULL, + &optlist, create_uri_opts, + buf, sizeof(buf)) < 0) { + coap_log_err("Failed to create options for URI\n"); + goto failed; } /* set block option if requested at commandline */ diff --git a/examples/coap-rd.c b/examples/coap-rd.c index 4103ab9f..ad98a58c 100644 --- a/examples/coap-rd.c +++ b/examples/coap-rd.c @@ -333,46 +333,9 @@ add_source_address(coap_resource_t *resource, if (!buf) return; - buf[0] = '"'; - - switch(peer->addr.sa.sa_family) { - - case AF_INET: - /* FIXME */ - break; - - case AF_INET6: - n += snprintf(buf + n, BUFSIZE - n, - "[%02x%02x:%02x%02x:%02x%02x:%02x%02x" \ - ":%02x%02x:%02x%02x:%02x%02x:%02x%02x]", - peer->addr.sin6.sin6_addr.s6_addr[0], - peer->addr.sin6.sin6_addr.s6_addr[1], - peer->addr.sin6.sin6_addr.s6_addr[2], - peer->addr.sin6.sin6_addr.s6_addr[3], - peer->addr.sin6.sin6_addr.s6_addr[4], - peer->addr.sin6.sin6_addr.s6_addr[5], - peer->addr.sin6.sin6_addr.s6_addr[6], - peer->addr.sin6.sin6_addr.s6_addr[7], - peer->addr.sin6.sin6_addr.s6_addr[8], - peer->addr.sin6.sin6_addr.s6_addr[9], - peer->addr.sin6.sin6_addr.s6_addr[10], - peer->addr.sin6.sin6_addr.s6_addr[11], - peer->addr.sin6.sin6_addr.s6_addr[12], - peer->addr.sin6.sin6_addr.s6_addr[13], - peer->addr.sin6.sin6_addr.s6_addr[14], - peer->addr.sin6.sin6_addr.s6_addr[15]); - - if (peer->addr.sin6.sin6_port != htons(COAP_DEFAULT_PORT)) { - n += - snprintf(buf + n, BUFSIZE - n, ":%d", peer->addr.sin6.sin6_port); - } - break; - default: - ; - } - - if (n < BUFSIZE) - buf[n++] = '"'; + n = coap_print_addr(peer, (uint8_t *)buf, BUFSIZE); + if (!n) + return; attr_val.s = (const uint8_t *)buf; attr_val.length = n; @@ -753,7 +716,8 @@ get_context(const char *node, const char *port) { enable_ws, COAP_PROTO_NONE); info_list = coap_resolve_address_info(node ? &local : NULL, u_s_port, s_port, AI_PASSIVE | AI_NUMERICHOST, - scheme_hint_bits); + scheme_hint_bits, + COAP_RESOLVE_TYPE_LOCAL); for (info = info_list; info != NULL; info = info->next) { coap_endpoint_t *ep; diff --git a/examples/coap-server.c b/examples/coap-server.c index f3b1c5bc..35d2a75e 100644 --- a/examples/coap-server.c +++ b/examples/coap-server.c @@ -928,7 +928,8 @@ get_ongoing_proxy_session(coap_session_t *session, /* resolve destination address where data should be sent */ info_list = coap_resolve_address_info(&server, port, port, 0, - 1 << scheme); + 1 << scheme, + COAP_RESOLVE_TYPE_REMOTE); if (info_list == NULL) { coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_GATEWAY); @@ -1118,8 +1119,9 @@ hnd_proxy_uri(coap_resource_t *resource COAP_UNUSED, /* Use Uri-Path and Uri-Query - direct session */ proxy_uri = NULL; proxy_scheme_option = 0; + const coap_address_t *dst = coap_session_get_addr_remote(ongoing); - if (coap_uri_into_options(&uri, &optlist, 1, + if (coap_uri_into_options(&uri, dst, &optlist, 1, buf, sizeof(buf)) < 0) { coap_log_err("Failed to create options for URI\n"); goto cleanup; @@ -2344,7 +2346,8 @@ get_context(const char *node, const char *port) { enable_ws, use_unix_proto); info_list = coap_resolve_address_info(node ? &local : NULL, u_s_port, s_port, AI_PASSIVE | AI_NUMERICHOST, - scheme_hint_bits); + scheme_hint_bits, + COAP_RESOLVE_TYPE_LOCAL); for (info = info_list; info != NULL; info = info->next) { coap_endpoint_t *ep; diff --git a/examples/lwip/client-coap.c b/examples/lwip/client-coap.c index 5ca758e4..f494c869 100644 --- a/examples/lwip/client-coap.c +++ b/examples/lwip/client-coap.c @@ -87,7 +87,8 @@ resolve_address(const char *host, const char *service, coap_address_t *dst, str_host.length = strlen(host); addr_info = coap_resolve_address_info(&str_host, port, port, AF_UNSPEC, - scheme_hint_bits); + scheme_hint_bits, + COAP_RESOLVE_TYPE_REMOTE); if (addr_info) { ret = 1; *dst = addr_info->addr; @@ -207,7 +208,7 @@ client_coap_init(coap_lwip_input_wait_handler_t input_wait, void *input_arg, coap_session_max_pdu_size(session)); LWIP_ASSERT("Failed to create PDU", pdu != NULL); - len = coap_uri_into_options(&uri, &optlist, 1, buf, sizeof(buf)); + len = coap_uri_into_options(&uri, &dst, &optlist, 1, buf, sizeof(buf)); LWIP_ASSERT("Failed to create options", len == 0); /* Add option list (which will be sorted) to the PDU */ diff --git a/examples/lwip/server-coap.c b/examples/lwip/server-coap.c index d9612883..847ba725 100644 --- a/examples/lwip/server-coap.c +++ b/examples/lwip/server-coap.c @@ -168,7 +168,8 @@ void server_coap_init(coap_lwip_input_wait_handler_t input_wait, 0, COAP_PROTO_NONE); info_list = coap_resolve_address_info(&node, 0, 0, 0, - scheme_hint_bits); + scheme_hint_bits, + COAP_RESOLVE_TYPE_LOCAL); for (info = info_list; info != NULL; info = info->next) { coap_endpoint_t *ep; diff --git a/examples/riot/examples_libcoap_client/client-coap.c b/examples/riot/examples_libcoap_client/client-coap.c index 01e98800..eab5ac44 100644 --- a/examples/riot/examples_libcoap_client/client-coap.c +++ b/examples/riot/examples_libcoap_client/client-coap.c @@ -106,7 +106,8 @@ resolve_address(const char *host, const char *service, coap_address_t *dst, str_host.s = (const uint8_t *)host; str_host.length = strlen(host); addr_info = coap_resolve_address_info(&str_host, port, port, AF_UNSPEC, - scheme_hint_bits); + scheme_hint_bits, + COAP_RESOLVE_TYPE_REMOTE); if (addr_info) { ret = 1; *dst = addr_info->addr; @@ -212,7 +213,7 @@ client_coap_init(int argc, char **argv) { goto fail; } - len = coap_uri_into_options(&uri, &optlist, 1, buf, sizeof(buf)); + len = coap_uri_into_options(&uri, &dst, &optlist, 1, buf, sizeof(buf)); if (len) { coap_log_warn("Failed to create options\n"); goto fail; diff --git a/examples/riot/examples_libcoap_server/server-coap.c b/examples/riot/examples_libcoap_server/server-coap.c index 3eafe820..7528c195 100644 --- a/examples/riot/examples_libcoap_server/server-coap.c +++ b/examples/riot/examples_libcoap_server/server-coap.c @@ -167,7 +167,8 @@ init_coap_context_endpoints(const char *use_psk) { info_list = coap_resolve_address_info(&local, COAP_DEFAULT_PORT, COAPS_DEFAULT_PORT, 0, - scheme_hint_bits); + scheme_hint_bits, + COAP_RESOLVE_TYPE_REMOTE); for (info = info_list; info != NULL; info = info->next) { coap_endpoint_t *ep; diff --git a/examples/riot/pkg_libcoap/Makefile b/examples/riot/pkg_libcoap/Makefile index 64a84d18..c351e062 100644 --- a/examples/riot/pkg_libcoap/Makefile +++ b/examples/riot/pkg_libcoap/Makefile @@ -1,6 +1,6 @@ PKG_NAME=libcoap -PKG_URL=https://github.com/obgm/libcoap -PKG_VERSION=8d869fff047d34a1c825ffc1bab5d3fde28c75b7 +PKG_URL=https://github.com/mrdeep1/libcoap +PKG_VERSION=317460c3e439fffde730ae4c635728f661fc1f0c PKG_LICENSE=BSD-2-Clause LIBCOAP_BUILD_DIR=$(BINDIR)/pkg/$(PKG_NAME) diff --git a/examples/tiny.c b/examples/tiny.c index 45a2691b..ad48aae5 100644 --- a/examples/tiny.c +++ b/examples/tiny.c @@ -117,7 +117,7 @@ get_session(coap_context_t *ctx, const char *group) { if (!session) continue; - if (IN6_IS_ADDR_MULTICAST(&addr.addr.sin6.sin6_addr) ) { + if (coap_is_mcast(&addr)) { /* set socket options for multicast */ if (!coap_mcast_set_hops(session, hops)) perror("setsockopt: IPV6_MULTICAST_HOPS"); diff --git a/include/coap3/coap_address.h b/include/coap3/coap_address.h index 0570fdbe..9fd7a48b 100644 --- a/include/coap3/coap_address.h +++ b/include/coap3/coap_address.h @@ -29,10 +29,10 @@ #include -typedef struct coap_address_t { +struct coap_address_t { uint16_t port; ip_addr_t addr; -} coap_address_t; +}; /** * Returns the port from @p addr in host byte order. @@ -62,10 +62,10 @@ coap_address_set_port(coap_address_t *addr, uint16_t port) { #include "uip.h" -typedef struct coap_address_t { +struct coap_address_t { uip_ipaddr_t addr; uint16_t port; -} coap_address_t; +}; /** * Returns the port from @p addr in host byte order. @@ -92,7 +92,7 @@ coap_address_set_port(coap_address_t *addr, uint16_t port) { #define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) -#else /* WITH_LWIP || WITH_CONTIKI */ +#else /* ! WITH_LWIP && ! WITH_CONTIKI */ #ifdef _WIN32 #define sa_family_t short @@ -106,7 +106,7 @@ struct coap_sockaddr_un { }; /** Multi-purpose address abstraction */ -typedef struct coap_address_t { +struct coap_address_t { socklen_t size; /**< size of addr */ union { struct sockaddr sa; @@ -114,7 +114,7 @@ typedef struct coap_address_t { struct sockaddr_in6 sin6; struct coap_sockaddr_un cun; /* CoAP shortened special */ } addr; -} coap_address_t; +}; /** * Returns the port from @p addr in host byte order. @@ -176,23 +176,33 @@ uint32_t coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check, coap_proto_t use_unix_proto); /** - * Resolve the specified @p server into a set of coap_address_t that can - * be used to bind() or connect() to. + * coap_resolve_type_t values + */ +typedef enum coap_resolve_type_t { + COAP_RESOLVE_TYPE_LOCAL, /**< local side of session */ + COAP_RESOLVE_TYPE_REMOTE, /**< remote side of session */ +} coap_resolve_type_t; + +/** + * Resolve the specified @p address into a set of coap_address_t that can + * be used to bind() (local) or connect() (remote) to. * - * @param server The Address to resolve. - * @param port The unsecured protocol port to use. + * @param address The Address to resolve. + * @param port The unsecured protocol port to use. * @param secure_port The secured protocol port to use. * @param ai_hints_flags AI_* Hint flags to use for internal getaddrinfo(). * @param scheme_hint_bits Which schemes to return information for. One or * more of COAP_URI_SCHEME_*_BIT or'd together. + * @param type COAP_ADDRESS_TYPE_LOCAL or COAP_ADDRESS_TYPE_REMOTE * * @return One or more linked sets of coap_addr_info_t or @c NULL if error. */ -coap_addr_info_t *coap_resolve_address_info(const coap_str_const_t *server, +coap_addr_info_t *coap_resolve_address_info(const coap_str_const_t *address, uint16_t port, uint16_t secure_port, int ai_hints_flags, - int scheme_hint_bits); + int scheme_hint_bits, + coap_resolve_type_t type); /** * Free off the one or more linked sets of coap_addr_info_t returned from diff --git a/include/coap3/coap_forward_decls.h b/include/coap3/coap_forward_decls.h index 85c77859..dece378a 100644 --- a/include/coap3/coap_forward_decls.h +++ b/include/coap3/coap_forward_decls.h @@ -29,6 +29,8 @@ struct coap_dtls_pki_t; struct coap_str_const_t; struct coap_string_t; +typedef struct coap_address_t coap_address_t; + /* * typedef all the opaque structures that are defined in coap_*_internal.h */ diff --git a/include/coap3/coap_uri.h b/include/coap3/coap_uri.h index 273f8a99..fd79b28b 100644 --- a/include/coap3/coap_uri.h +++ b/include/coap3/coap_uri.h @@ -166,23 +166,29 @@ int coap_split_proxy_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri); /** * Takes a coap_uri_t and then adds CoAP options into the @p optlist_chain. - * If the port is not the default port and create_port_opt is not 0, then - * the Port option is added in. Any path or query are broken down into the - * individual segment Path or Query options and added to the @p optlist_chain. + * If the port is not the default port and create_port_host_opt is not 0, then + * the Port option is added to the @p optlist_chain. + * If the dst defines an address that does not match the host in uri->host and + * is not 0, then the Host option is added to the @p optlist_chain. + * Any path or query are broken down into the individual segment Path or Query + * options and added to the @p optlist_chain. * * @param uri The coap_uri_t object. + * @param dst The destination, or NULL if URI_HOST not to be added. * @param optlist_chain Where to store the chain of options. * @param buf Scratch buffer area (needs to be bigger than * uri->path.length and uri->query.length) * @param buflen Size of scratch buffer. - * @param create_port_opt @c 1 if port option to be added (if non-default) - * else @c 0 + * @param create_port_host_opt @c 1 if port/host option to be added + * (if non-default) else @c 0 * * @return @c 0 on success, or < 0 on error. * */ -int coap_uri_into_options(coap_uri_t *uri, coap_optlist_t **optlist_chain, - int create_port_opt, uint8_t *buf, size_t buflen); +int coap_uri_into_options(const coap_uri_t *uri, const coap_address_t *dst, + coap_optlist_t **optlist_chain, + int create_port_host_opt, + uint8_t *buf, size_t buflen); /** * Splits the given URI path into segments. Each segment is preceded diff --git a/man/Makefile.am b/man/Makefile.am index 69b1367c..94ba64a3 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -124,6 +124,8 @@ install-man: install-man3 install-man5 install-man7 @echo ".so man3/coap_logging.3" > coap_show_pdu.3 @echo ".so man3/coap_logging.3" > coap_endpoint_str.3 @echo ".so man3/coap_logging.3" > coap_session_str.3 + @echo ".so man3/coap_logging.3" > coap_print_addr.3 + @echo ".so man3/coap_logging.3" > coap_print_ip_addr.3 @echo ".so man3/coap_oscore.3" > coap_context_oscore_server.3 @echo ".so man3/coap_pdu_access.3" > coap_option_filter_set.3 @echo ".so man3/coap_pdu_access.3" > coap_option_filter_unset.3 diff --git a/man/coap-client.txt.in b/man/coap-client.txt.in index 768c596c..7d82da2d 100644 --- a/man/coap-client.txt.in +++ b/man/coap-client.txt.in @@ -93,7 +93,7 @@ OPTIONS - General A filename to store data retrieved with GET. *-p* port:: - The port to listen on. + The port to send from. *-r*:: Use reliable protocol (TCP or TLS). diff --git a/man/coap_address.txt.in b/man/coap_address.txt.in index 7a3eeb16..ea9209c9 100644 --- a/man/coap_address.txt.in +++ b/man/coap_address.txt.in @@ -12,7 +12,12 @@ NAME ---- coap_address, coap_address_t, -coap_address_init +coap_address_un, +coap_address_init, +coap_get_available_scheme_hint_bits, +coap_resolve_address_info, +coap_free_address_info, +coap_address_set_unix_domain - Work with CoAP Socket Address Types SYNOPSIS @@ -28,9 +33,9 @@ SYNOPSIS *uint32_t coap_get_available_scheme_hint_bits(int _have_pki_psk_, int _ws_check_, coap_proto_t _use_unix_proto_);* -*coap_addr_info_t *coap_resolve_address_info(const coap_str_const_t *_server_, +*coap_addr_info_t *coap_resolve_address_info(const coap_str_const_t *_address_, uint16_t _port_, uint16_t _secure_port_, int _ai_hints_flags_, -int _scheme_hint_bits_);* +int _scheme_hint_bits_, coap_resolve_type_t _type_);* *void coap_free_address_info(coap_addr_info_t *_info_list_);* @@ -109,6 +114,19 @@ The *coap_sockaddr_un* structure is modeled on the *sockaddr_un* structure *coap_address_t* is not changed by its inclusion. COAP_UNIX_MAX_PATH includes the trailing zero terminator of a domain unix file name. +*Enum coap_resolve_type_t* + +[source, c] +---- +typedef enum coap_resolve_type_t { + COAP_RESOLVE_TYPE_LOCAL, /**< local side of session */ + COAP_RESOLVE_TYPE_REMOTE, /**< remote side of session */ +} coap_resolve_type_t; +---- + +Used when determining how to do an address lookup when calling +*coap_resolve_address_info()*. + FUNCTIONS --------- @@ -133,11 +151,12 @@ protocol to use over a Unix socket. The output is suitable for input for the *Function: coap_resolve_address_info()* -The *coap_resolve_address_info*() function resolves the address _server_ into +The *coap_resolve_address_info*() function resolves the address _address_ into a set of one or more coap_addr_info_t structures. Depending on the scheme as abstracted from _scheme_hint_bits_ either _port_ or _secure_port_ is used to update the addr variable of coap_addr_info_t. If _port_ (or _secure_port_) is -0, then the default port for the scheme is used. _ai_hints_flags_ is used for +0, then the default port for the scheme is used if _type is set to +COAP_RESOLVE_TYPE_LOCAL. _ai_hints_flags_ is used for the internally called getaddrinfo(3) function. _scheme_hint_bits_ is a set of one or more COAP_URI_SCHEME_*_BIT or'd together. _scheme_hint_bits_ can also (for servers) be the output from *coap_get_available_scheme_hint_bits*(). @@ -179,7 +198,7 @@ get_address(coap_uri_t *uri, coap_address_t *dst) { coap_addr_info_t *info_list; info_list = coap_resolve_address_info(&uri->host, uri->port, uri->port, 0, - 1 << uri->scheme); + 1 << uri->scheme, COAP_RESOLVE_TYPE_LOCAL); if (info_list == NULL) return 0; memcpy(dst, &info_list->addr, sizeof(*dst)); diff --git a/man/coap_logging.txt.in b/man/coap_logging.txt.in index 3b874229..bb9bdd53 100644 --- a/man/coap_logging.txt.in +++ b/man/coap_logging.txt.in @@ -33,7 +33,9 @@ coap_package_build, coap_set_show_pdu_output, coap_show_pdu, coap_endpoint_str, -coap_session_str +coap_session_str, +coap_print_addr, +coap_print_ip_addr - Work with CoAP logging SYNOPSIS @@ -86,6 +88,12 @@ SYNOPSIS *const char *coap_session_str(const coap_session_t *_session_);* +*size_t coap_print_addr(const coap_address_t *_address_, +unsigned char *_buffer_, size_t _length_);* + +*const char *coap_print_ip_addr(const coap_address_t *_address_, +char *_buffer_, size_t _length_);* + For specific (D)TLS library support, link with *-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, *-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* @@ -277,6 +285,18 @@ _endpoint_. The *coap_session_str*() function is used to get a string containing the information about the _session_. +*Function: coap_print_addr()* + +The *coap_print_addr*() function returns the length of the description string +containing the IP address and port from _address_, updating _buffer_ which has a +maximum length _length_. + +*Function: coap_print_ip_addr()* + +The *coap_print_ip_addr*() function returns a description string of the +IP address only for _address_. _buffer_ is updated, which has a maximum length of +_length_. + RETURN VALUES ------------- @@ -295,6 +315,12 @@ _endpoint_. The *coap_session_str*() function returns a description string of the _session_. +The *coap_print_addr*() function returns the length of _buffer_ that has been +updated with an ascii readable IP address and port for _address_. + +The *coap_print_ip_addr*() function returns a pointer to the ascii readable +IP address only for _address_. + SEE ALSO -------- *coap_context*(3) and *coap_session*(3) diff --git a/man/coap_uri.txt.in b/man/coap_uri.txt.in index 055d4749..7d459ad6 100644 --- a/man/coap_uri.txt.in +++ b/man/coap_uri.txt.in @@ -35,9 +35,9 @@ coap_uri_t *_uri_);* *void coap_delete_uri(coap_uri_t *_uri_);* -*int coap_uri_into_options(coap_uri_t *_uri_, -coap_optlist_t **_optlist_chain_, int _create_port_opt_, -uint8_t *_buf_, size_t _buflen_);* +*int coap_uri_into_options(const coap_uri_t *_uri_, +const coap_address_t *_dst_, coap_optlist_t **_optlist_chain_, +int _create_port_host_opt_, uint8_t *_buf_, size_t _buflen_);* For specific (D)TLS library support, link with *-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, @@ -122,7 +122,11 @@ The initial _optlist_chain_ entry should be set to NULL before this function is called (unless *coap_insert_optlist*(3) has been previously used). -If the port is not the default port and _create_port_opt_ is not 0, then +If _dst_ is not NULL and _create_port_host_opt_ is not 0, then the Uri-Host +option is added in if the _uri_ host definition is not an exact match with the +ascii readable version of _dst. + +If the port is not the default port and _create_port_host_opt_ is not 0, then the Port option is added to _optlist_chain_. If there is a path, then this is broken down into individual Path options for @@ -163,6 +167,7 @@ parse_and_send_uri(coap_session_t *session, const char *do_uri) { coap_optlist_t *optlist = NULL; coap_pdu_t *pdu; coap_proto_t proto = coap_session_get_proto(session); + const coap_address_t *dst = coap_session_get_addr_remote(session); int res; coap_mid_t mid; #define BUFSIZE 100 @@ -216,7 +221,7 @@ parse_and_send_uri(coap_session_t *session, const char *do_uri) { return 0; /* Create all the necessary options from the URI */ - res = coap_uri_into_options(&uri, &optlist, 1, buf, sizeof(buf)); + res = coap_uri_into_options(&uri, dst, &optlist, 1, buf, sizeof(buf)); if (res != 0) return 0; diff --git a/src/coap_address.c b/src/coap_address.c index c89a4bfa..2d189eb4 100644 --- a/src/coap_address.c +++ b/src/coap_address.c @@ -125,11 +125,6 @@ static struct in_addr b_ipv4[COAP_BCST_CNT]; #include #include - -#ifndef s6_addr32 -#define s6_addr32 __u6_addr.__u6_addr32 -#endif /* s6_addr32 */ - int coap_is_bcast(const coap_address_t *a) { struct in_addr ipv4; @@ -145,7 +140,7 @@ coap_is_bcast(const coap_address_t *a) { break; case AF_INET6: if (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr)) { - ipv4.s_addr = a->addr.sin6.sin6_addr.s6_addr32[3]; + memcpy(&ipv4, &a->addr.sin6.sin6_addr.s6_addr[12], sizeof(ipv4)); break; } /* IPv6 does not support broadcast */ @@ -244,8 +239,10 @@ coap_address_set_unix_domain(coap_address_t *addr, #if !defined(WITH_CONTIKI) static void -update_port(coap_address_t *addr, uint16_t port, uint16_t default_port) { - if (port == 0) +update_port(coap_address_t *addr, uint16_t port, uint16_t default_port, + int update_port0) { + /* Client target port must be set if default of 0 */ + if (port == 0 && update_port0) port = default_port; #if !defined(WITH_LWIP) @@ -324,12 +321,14 @@ coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check, } coap_addr_info_t * -coap_resolve_address_info(const coap_str_const_t *server, +coap_resolve_address_info(const coap_str_const_t *address, uint16_t port, uint16_t secure_port, int ai_hints_flags, - int scheme_hint_bits) { + int scheme_hint_bits, + coap_resolve_type_t type) { #if !defined(RIOT_VERSION) + struct addrinfo *res, *ainfo; struct addrinfo hints; static char addrstr[256]; @@ -341,9 +340,9 @@ coap_resolve_address_info(const coap_str_const_t *server, coap_proto_t proto = 0; #if !defined(WITH_LWIP) - if (server && coap_host_is_unix_domain(server)) { + if (address && coap_host_is_unix_domain(address)) { /* There can only be one unique filename entry for AF_UNIX */ - if (server->length >= COAP_UNIX_PATH_MAX) { + if (address->length >= COAP_UNIX_PATH_MAX) { coap_log_err("Unix Domain host too long\n"); return NULL; } @@ -407,8 +406,8 @@ coap_resolve_address_info(const coap_str_const_t *server, info->scheme = scheme; coap_address_init(&info->addr); - if (!coap_address_set_unix_domain(&info->addr, server->s, - server->length)) { + if (!coap_address_set_unix_domain(&info->addr, address->s, + address->length)) { coap_free_type(COAP_STRING, info); return NULL; } @@ -417,8 +416,8 @@ coap_resolve_address_info(const coap_str_const_t *server, #endif /* ! WITH_LWIP */ memset(addrstr, 0, sizeof(addrstr)); - if (server && server->length) - memcpy(addrstr, server->s, server->length); + if (address && address->length) + memcpy(addrstr, address->s, address->length); else memcpy(addrstr, "localhost", 9); @@ -569,28 +568,36 @@ coap_resolve_address_info(const coap_str_const_t *server, #endif /* WITH_LWIP */ switch (scheme) { case COAP_URI_SCHEME_COAP: - update_port(&info->addr, port, COAP_DEFAULT_PORT); + update_port(&info->addr, port, COAP_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAPS: - update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT); + update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAP_TCP: - update_port(&info->addr, port, COAP_DEFAULT_PORT); + update_port(&info->addr, port, COAP_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAPS_TCP: - update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT); + update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_HTTP: - update_port(&info->addr, port, 80); + update_port(&info->addr, port, 80, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_HTTPS: - update_port(&info->addr, secure_port, 443); + update_port(&info->addr, secure_port, 443, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAP_WS: - update_port(&info->addr, port, 80); + update_port(&info->addr, port, 80, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAPS_WS: - update_port(&info->addr, secure_port, 443); + update_port(&info->addr, secure_port, 443, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_LAST: default: @@ -617,7 +624,7 @@ coap_resolve_address_info(const coap_str_const_t *server, coap_proto_t proto = 0; (void)ai_hints_flags; - if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)server->s) >= 0) { + if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)address->s) >= 0) { for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) { if (scheme_hint_bits & (1 << scheme)) { switch (scheme) { @@ -689,22 +696,28 @@ coap_resolve_address_info(const coap_str_const_t *server, info->addr.addr.sin6.sin6_scope_id = (uint32_t)netif_get_id(netif); switch (scheme) { case COAP_URI_SCHEME_COAP: - update_port(&info->addr, port, COAP_DEFAULT_PORT); + update_port(&info->addr, port, COAP_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAPS: - update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT); + update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAP_TCP: - update_port(&info->addr, port, COAP_DEFAULT_PORT); + update_port(&info->addr, port, COAP_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_COAPS_TCP: - update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT); + update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_HTTP: - update_port(&info->addr, port, 80); + update_port(&info->addr, port, 80, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_HTTPS: - update_port(&info->addr, secure_port, 443); + update_port(&info->addr, secure_port, 443, + type == COAP_RESOLVE_TYPE_LOCAL); break; case COAP_URI_SCHEME_LAST: default: diff --git a/src/coap_uri.c b/src/coap_uri.c index 176020fc..4babec0f 100644 --- a/src/coap_uri.c +++ b/src/coap_uri.c @@ -279,16 +279,42 @@ coap_split_proxy_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri) { } int -coap_uri_into_options(coap_uri_t *uri, - coap_optlist_t **optlist_chain, int create_port_opt, +coap_uri_into_options(const coap_uri_t *uri, const coap_address_t *dst, + coap_optlist_t **optlist_chain, int create_port_host_opt, uint8_t *_buf, size_t _buflen) { int res; unsigned char *buf = _buf; size_t buflen = _buflen; - if (create_port_opt && - !coap_host_is_unix_domain(&uri->host)) { + if (create_port_host_opt && !coap_host_is_unix_domain(&uri->host)) { int add_option = 0; + + if (dst && uri->host.length) { +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) + char addr[INET6_ADDRSTRLEN]; +#else /* WITH_LWIP || WITH_CONTIKI */ + char addr[40]; +#endif /* WITH_LWIP || WITH_CONTIKI */ + + /* Add in UriHost if not match (need to strip off &iface) */ + size_t uri_host_len = uri->host.length; + uint8_t* cp = (uint8_t*)strchr((const char*)uri->host.s, '%'); + + if (cp && (size_t)(cp - uri->host.s) < uri_host_len) + /* %iface specified in host name */ + uri_host_len = cp - uri->host.s; + + if (coap_print_ip_addr(dst, addr, sizeof(addr)) && + (strlen(addr) != uri_host_len || + memcmp(addr, uri->host.s, uri_host_len) != 0)) { + /* add Uri-Host */ + coap_insert_optlist(optlist_chain, + coap_new_optlist(COAP_OPTION_URI_HOST, + uri->host.length, + uri->host.s)); + } + } + /* Add in UriPort if not default */ switch ((int)uri->scheme) { case COAP_URI_SCHEME_HTTP: case COAP_URI_SCHEME_COAP_WS: @@ -302,7 +328,7 @@ coap_uri_into_options(coap_uri_t *uri, break; default: if (uri->port != (coap_uri_scheme_is_secure(uri) ? COAPS_DEFAULT_PORT : - COAP_DEFAULT_PORT)) + COAP_DEFAULT_PORT)) add_option = 1; break; }