diff --git a/CMakeLists.txt b/CMakeLists.txt index 321c5bd6e..c3ef2d784 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,7 @@ option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include option(LWS_WITH_SUL_DEBUGGING "Enable zombie lws_sul checking on object deletion" OFF) option(LWS_WITH_PLUGINS_API "Build generic lws_plugins apis (see LWS_WITH_PLUGINS to also build protocol plugins)" OFF) option(LWS_WITH_CONMON "Collect introspectable connection latency stats on individual client connections" ON) +option(LWS_WITH_WOL "Wake On Lan support" ON) option(LWS_WITHOUT_EVENTFD "Force using pipe instead of eventfd" OFF) if (UNIX OR WIN32) option(LWS_WITH_CACHE_NSCOOKIEJAR "Build file-backed lws-cache-ttl that uses netscape cookie jar format (linux-only)" ON) @@ -658,6 +659,7 @@ CHECK_C_SOURCE_COMPILES("#include \nvoid main(void) { while(1) ; } voi CHECK_C_SOURCE_COMPILES("#include \nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_PTHREAD_H) CHECK_C_SOURCE_COMPILES("#include \nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_INTTYPES_H) CHECK_C_SOURCE_COMPILES("#include \nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_SYS_RESOURCE_H) +CHECK_C_SOURCE_COMPILES("#include \nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_LINUX_IPV6_H) if (LWS_EXT_PTHREAD_INCLUDE_DIR) set(LWS_HAVE_PTHREAD_H 1) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 5a9e1a2ff..f99aee0e4 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -79,6 +79,7 @@ #cmakedefine LWS_HAVE_mbedtls_ssl_set_verify #cmakedefine LWS_HAVE_mbedtls_x509_crt_parse_file #cmakedefine LWS_HAVE_MBEDTLS_NET_SOCKETS +#cmakedefine LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET #cmakedefine LWS_HAVE_MBEDTLS_AUTH_KEY_ID #cmakedefine LWS_HAVE_NEW_UV_VERSION_H #cmakedefine LWS_HAVE_OPENSSL_ECDH_H @@ -258,4 +259,4 @@ #cmakedefine LWS_WITH_PLUGINS_API #cmakedefine LWS_HAVE_RTA_PREF #cmakedefine PICO_SDK_PATH - +#cmakedefine LWS_HAVE_LINUX_IPV6_H diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 87ff28088..05ede8de9 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -146,7 +146,7 @@ typedef int suseconds_t; #include #endif -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__QNX__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__QNX__) || defined(__OpenBSD__) || defined(__NuttX__) #include #include #endif diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index a0c390d2a..dd474a9cf 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -56,6 +56,11 @@ enum lws_client_connect_ssl_connection_flags { * then it is not possible to bind to this port for any local address */ + LCCSCF_IPV6_PREFER_PUBLIC_ADDR = (1 << 15), + /**< RFC5014 - For IPv6 systems with SLAAC config, allow for preference + * to bind a socket to public address vs temporary private address + */ + LCCSCF_PIPELINE = (1 << 16), /**< Serialize / pipeline multiple client connections * on a single connection where possible. diff --git a/include/libwebsockets/lws-dlo.h b/include/libwebsockets/lws-dlo.h index f19aac4cc..57767faa4 100644 --- a/include/libwebsockets/lws-dlo.h +++ b/include/libwebsockets/lws-dlo.h @@ -24,6 +24,9 @@ * lws display_list and display_list objects (dlo) */ +#if !defined(__LWS_DLO_H__) +#define __LWS_DLO_H__ + #include struct lws_display_render_state; @@ -267,8 +270,6 @@ typedef struct { char failed; } lws_dlo_image_t; -typedef struct lws_display_state lws_display_state_t; - typedef struct lws_displaylist { lws_dll2_owner_t dl; struct lws_display_state *ds; @@ -287,7 +288,7 @@ typedef struct lws_display_render_stack { typedef struct lws_display_render_state { lws_sorted_usec_list_t sul; /* return to event loop statefully */ - lws_display_state_t *lds; /* optional, if using lws_display */ + struct lws_display_state *lds; /* optional, if using lws_display */ lws_dll2_owner_t ids; @@ -460,13 +461,11 @@ typedef struct { LWS_VISIBLE LWS_EXTERN int lws_dlo_ss_create(lws_dlo_ss_create_info_t *i, lws_dlo_t **pdlo); -typedef struct lhp_ctx lhp_ctx_t; - LWS_VISIBLE LWS_EXTERN int lws_dlo_ss_find(struct lws_context *cx, const char *url, lws_dlo_image_t *u); LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t -lhp_displaylist_layout(lhp_ctx_t *ctx, char reason); +lhp_displaylist_layout(struct lhp_ctx *ctx, char reason); #define lws_dlo_image_width(_u) ((_u)->failed ? -1 : \ ((_u)->type == LWSDLOSS_TYPE_JPEG ? \ @@ -522,3 +521,4 @@ LWS_VISIBLE LWS_EXTERN void lws_dlo_file_destroy(struct lws_context *cx); LWS_VISIBLE extern const struct lws_plat_file_ops lws_dlo_fops; +#endif diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index b988c0f08..7812b5ec8 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -1250,3 +1250,15 @@ lws_minilex_parse(const uint8_t *lex, int16_t *ps, const uint8_t c, LWS_VISIBLE LWS_EXTERN unsigned int lws_sigbits(uintptr_t u); + +/** + * lws_wol() - broadcast a magic WOL packet to MAC, optionally binding to if IP + * + * \p ctx: The lws context + * \p ip_or_NULL: The IP address to bind to at the client side, to send the + * magic packet on. If NULL, the system chooses, probably the + * interface with the default route. + * \p mac_6_bytes: Points to a 6-byte MAC address to direct the magic packet to + */ +LWS_VISIBLE LWS_EXTERN int +lws_wol(struct lws_context *ctx, const char *ip_or_NULL, uint8_t *mac_6_bytes); diff --git a/include/libwebsockets/lws-network-helper.h b/include/libwebsockets/lws-network-helper.h index 09308b8b2..eb3f58766 100644 --- a/include/libwebsockets/lws-network-helper.h +++ b/include/libwebsockets/lws-network-helper.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2020 Andy Green + * Copyright (C) 2010 - 2023 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -246,4 +246,16 @@ lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len); LWS_VISIBLE LWS_EXTERN int lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len); +/** + * lws_parse_mac() - convert XX:XX:XX:XX:XX:XX to 6-byte MAC address + * + * \param ads: mac address as XX:XX:XX:XX:XX:XX string + * \param result_6_bytes: result buffer to take 6 bytes + * + * Converts a string representation of a 6-byte hex mac address to a 6-byte + * array. + */ +LWS_VISIBLE LWS_EXTERN int +lws_parse_mac(const char *ads, uint8_t *result_6_bytes); + ///@} diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8d21c1240..dcbd4053f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -371,6 +371,8 @@ if (DEFINED LWS_PLAT_UNIX) endif() endif() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols ${LWS_HAVE_mbedtls_ssl_conf_alpn_protocols} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) diff --git a/lib/core-net/CMakeLists.txt b/lib/core-net/CMakeLists.txt index 43a47ca14..3bd636fee 100644 --- a/lib/core-net/CMakeLists.txt +++ b/lib/core-net/CMakeLists.txt @@ -56,6 +56,11 @@ if (LWS_WITH_LWS_DSH) core-net/lws-dsh.c) endif() +if (LWS_WITH_WOL) + list(APPEND SOURCES + core-net/wol.c) +endif() + if (LWS_WITH_CLIENT) list(APPEND SOURCES core-net/client/client.c diff --git a/lib/core-net/network.c b/lib/core-net/network.c index f276a28dd..8e2303d62 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -1104,3 +1104,62 @@ lws_system_get_state_manager(struct lws_context *context) return &context->mgr_system; } #endif + +int +lws_parse_mac(const char *ads, uint8_t *result_6_bytes) +{ + uint8_t *p = result_6_bytes; + struct lws_tokenize ts; + char t[3]; + size_t n; + long u; + + lws_tokenize_init(&ts, ads, LWS_TOKENIZE_F_NO_INTEGERS | + LWS_TOKENIZE_F_MINUS_NONTERM); + ts.len = strlen(ads); + + do { + ts.e = (int8_t)lws_tokenize(&ts); + switch (ts.e) { + case LWS_TOKZE_TOKEN: + if (ts.token_len != 2) + return -1; + if (p - result_6_bytes == 6) + return -2; + t[0] = ts.token[0]; + t[1] = ts.token[1]; + t[2] = '\0'; + for (n = 0; n < 2; n++) + if (t[n] < '0' || t[n] > 'f' || + (t[n] > '9' && t[n] < 'A') || + (t[n] > 'F' && t[n] < 'a')) + return -1; + u = strtol(t, NULL, 16); + if (u > 0xff) + return -5; + *p++ = (uint8_t)u; + break; + + case LWS_TOKZE_DELIMITER: + if (*ts.token != ':') + return -10; + if (p - result_6_bytes > 5) + return -11; + break; + + case LWS_TOKZE_ENDED: + if (p - result_6_bytes != 6) + return -12; + return 0; + + default: + lwsl_err("%s: malformed mac\n", __func__); + + return -13; + } + } while (ts.e > 0); + + lwsl_err("%s: ended on e %d\n", __func__, ts.e); + + return -14; +} diff --git a/lib/core-net/wol.c b/lib/core-net/wol.c new file mode 100644 index 000000000..e3a045f82 --- /dev/null +++ b/lib/core-net/wol.c @@ -0,0 +1,84 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2023 Andy Green + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "private-lib-core.h" + +int +lws_wol(struct lws_context *ctx, const char *ip_or_NULL, uint8_t *mac_6_bytes) +{ + int n, m, ofs = 0, fd, optval = 1, ret = 1; + uint8_t pkt[17 * IFHWADDRLEN]; + struct sockaddr_in addr; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + lwsl_cx_err(ctx, "failed to open UDP, errno %d\n", errno); + goto bail; + } + + if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, + (char *)&optval, sizeof(optval)) < 0) { + lwsl_cx_err(ctx, "failed to set broadcast, errno %d\n", errno); + goto bail; + } + + /* + * Lay out the magic packet + */ + + for (n = 0; n < IFHWADDRLEN; n++) + pkt[ofs++] = 0xff; + for (m = 0; m < 16; m++) + for (n = 0; n < IFHWADDRLEN; n++) + pkt[ofs++] = mac_6_bytes[n]; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(9); + + if (!inet_aton(ip_or_NULL ? ip_or_NULL : "255.255.255.255", + &addr.sin_addr)) { + lwsl_cx_err(ctx, "failed to convert broadcast ads, errno %d\n", + errno); + goto bail; + } + + lwsl_cx_notice(ctx, "Sending WOL to %02X:%02X:%02X:%02X:%02X:%02X %s\n", + mac_6_bytes[0], mac_6_bytes[1], mac_6_bytes[2], mac_6_bytes[3], + mac_6_bytes[4], mac_6_bytes[5], ip_or_NULL ? ip_or_NULL : ""); + + if (sendto(fd, pkt, sizeof(pkt), 0, (struct sockaddr *)&addr, + sizeof(addr)) < 0) { + lwsl_cx_err(ctx, "failed to sendto broadcast ads, errno %d\n", + errno); + goto bail; + } + + ret = 0; + +bail: + close(fd); + + return ret; +} diff --git a/lib/core/buflist.c b/lib/core/buflist.c index dbe544e5c..4b50f92b0 100644 --- a/lib/core/buflist.c +++ b/lib/core/buflist.c @@ -39,7 +39,9 @@ lws_buflist_append_segment(struct lws_buflist **head, const uint8_t *buf, void *p = *head; int sanity = 1024; - assert(buf); + if (!buf) + return -1; + assert(len); /* append at the tail */ diff --git a/lib/core/context.c b/lib/core/context.c index 98e70d8e3..70aafed97 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -347,10 +347,6 @@ static const char * const opts_str = #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) "SSPROX " #endif - -#if defined(LWS_WITH_MBEDTLS) - "MbedTLS " -#endif #if defined(LWS_WITH_CONMON) "ConMon " #endif @@ -410,6 +406,9 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) struct lws_cache_creation_info ci; #endif +#if defined(LWS_WITH_MBEDTLS) + char mbedtls_version[32]; +#endif #if defined(__ANDROID__) struct rlimit rt; @@ -809,7 +808,16 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ +#if defined(LWS_WITH_MBEDTLS) + mbedtls_version_get_string(mbedtls_version); +#endif + +#if defined(LWS_WITH_MBEDTLS) + lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); +#else lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); +#endif + #if defined(LWS_WITH_NETWORK) lwsl_cx_info(context, "Event loop: %s", plev->ops->name); #endif @@ -963,7 +971,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->options = info->options; -#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) && !defined(WIN32) && !defined(LWS_PLAT_BAREMETAL) +#if defined(LWS_HAVE_SYS_RESOURCE_H) && !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) && !defined(WIN32) && !defined(LWS_PLAT_BAREMETAL) /* * If asked, try to set the rlimit / ulimit for process sockets / files. * We read the effective limit in a moment, so we will find out the diff --git a/lib/misc/base64-decode.c b/lib/misc/base64-decode.c index 458a6600d..8f0a735da 100644 --- a/lib/misc/base64-decode.c +++ b/lib/misc/base64-decode.c @@ -114,7 +114,7 @@ lws_b64_decode_stateful(struct lws_b64state *s, const char *in, size_t *in_len, uint8_t *orig_out = out, *end_out = out + *out_size; int equals = 0; - while (in < end_in && *in && out + 4 < end_out) { + while (in < end_in && *in && out + 3 <= end_out) { for (; s->i < 4 && in < end_in && *in; s->i++) { uint8_t v; diff --git a/lib/plat/unix/private-lib-plat-unix.h b/lib/plat/unix/private-lib-plat-unix.h index 1aa9e8079..7f84e6cb1 100644 --- a/lib/plat/unix/private-lib-plat-unix.h +++ b/lib/plat/unix/private-lib-plat-unix.h @@ -123,7 +123,7 @@ typedef pthread_mutex_t lws_mutex_t; #endif -#if defined (__sun) || defined(__HAIKU__) || defined(__QNX__) || defined(__ANDROID__) +#if defined (__sun) || defined(__HAIKU__) || defined(__QNX__) || defined(__ANDROID__) || defined(__NuttX__) #include #if defined(__ANDROID__) diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 47ad6a85e..e06e83b3b 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2023 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -27,6 +27,10 @@ #endif #include "private-lib-core.h" +#if defined(LWS_HAVE_LINUX_IPV6_H) +#include +#endif + #include #if !defined(LWS_DETECTED_PLAT_IOS) @@ -171,7 +175,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt) /* Disable Nagle */ optval = 1; -#if defined (__sun) || defined(__QNX__) +#if defined (__sun) || defined(__QNX__) || defined(__NuttX__) if (!unix_skt && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0) return 1; #elif !defined(__APPLE__) && \ @@ -190,6 +194,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt) return lws_plat_set_nonblocking(fd); } +#if !defined(__NuttX__) static const int ip_opt_lws_flags[] = { LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT, LCCSCF_IP_HIGH_RELIABILITY @@ -210,6 +215,7 @@ static const char *ip_opt_names[] = { #endif }; #endif +#endif int lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) @@ -237,7 +243,8 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) !defined(__sun) && \ !defined(__HAIKU__) && \ !defined(__CYGWIN__) && \ - !defined(__QNX__) + !defined(__QNX__) && \ + !defined(__NuttX__) /* the BSDs don't have SO_PRIORITY */ @@ -270,6 +277,27 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) } + if (lws_flags & LCCSCF_IPV6_PREFER_PUBLIC_ADDR) { +#if defined(LWS_WITH_IPV6) && defined(IPV6_PREFER_SRC_PUBLIC) + optval = IPV6_PREFER_SRC_PUBLIC; + + if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, + (const void *)&optval, optlen) < 0) { + #if (_LWS_ENABLED_LOGS & LLL_WARN) + en = errno; + lwsl_warn("%s: unable to set IPV6_PREFER_SRC_PUBLIC: errno %d\n", + __func__, en); + #endif + ret = 1; + } else + lwsl_notice("%s: set IPV6_PREFER_SRC_PUBLIC\n", __func__); +#else + lwsl_err("%s: IPV6_PREFER_SRC_PUBLIC UNIMPLEMENTED on this platform\n", __func__); +#endif + } + + +#if !defined(__NuttX__) for (n = 0; n < 4; n++) { if (!(lws_flags & ip_opt_lws_flags[n])) continue; @@ -287,6 +315,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) lwsl_notice("%s: set ip flag %s\n", __func__, ip_opt_names[n]); } +#endif return ret; } diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index 9e8ce2656..0099d2f06 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -193,6 +193,16 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) } else lwsl_notice("%s: set use exclusive addresses\n", __func__); } + + +#if defined(LWS_WITH_IPV6) + /* I do not believe Microsoft supports RFC5014 + * Instead, you must set lws_client_connect_info::iface */ + if (lws_flags & LCCSCF_IPV6_PREFER_PUBLIC_ADDR) { + lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); + } +#endif + return ret; diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 50cdccec4..16d10729b 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -534,7 +534,7 @@ lws_h2_settings(struct lws *wsi, struct http2_settings *settings, case H2SET_INITIAL_WINDOW_SIZE: if (b > 0x7fffffff) { lws_h2_goaway(nwsi, H2_ERR_FLOW_CONTROL_ERROR, - "Inital Window beyond max"); + "Initial Window beyond max"); return 1; } @@ -1618,7 +1618,7 @@ lws_h2_parse_end_of_frame(struct lws *wsi) if (!h2n->swsi->h2.END_HEADERS) { /* we are not finished yet */ - lwsl_info("witholding http action for continuation\n"); + lwsl_info("withholding http action for continuation\n"); h2n->cont_exp_sid = h2n->sid; h2n->cont_exp = 1; break; @@ -2816,7 +2816,6 @@ int lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len) { unsigned char *oldbuf = buf; - lws_filepos_t body_chunk_len; // lwsl_notice("%s: h2 path: wsistate 0x%x len %d\n", __func__, // wsi->wsistate, (int)len); @@ -2832,6 +2831,7 @@ lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len) * case. */ while (len) { + lws_filepos_t body_chunk_len = 0; int m; /* diff --git a/lib/roles/netlink/ops-netlink.c b/lib/roles/netlink/ops-netlink.c index fa3bf29a2..f81619d98 100644 --- a/lib/roles/netlink/ops-netlink.c +++ b/lib/roles/netlink/ops-netlink.c @@ -41,7 +41,8 @@ #define RTA_ALIGNTO 4U //#define lwsl_netlink lwsl_notice -#define lwsl_cx_netlink lwsl_cx_info +#define lwsl_cx_netlink lwsl_cx_info +#define lwsl_cx_netlink_debug lwsl_cx_debug static void lws_netlink_coldplug_done_cb(lws_sorted_usec_list_t *sul) @@ -69,11 +70,11 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, #endif ; struct sockaddr_nl nladdr; - lws_route_t robj, *rou, *rmat; + lws_route_t robj, *rou; struct nlmsghdr *h; struct msghdr msg; struct iovec iov; - unsigned int n; + unsigned int n, removed; char buf[72]; if (!(pollfd->revents & LWS_POLLIN)) @@ -190,8 +191,50 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, ra_len = (unsigned int)IFA_PAYLOAD(h); lwsl_cx_netlink(cx, "%s", - h->nlmsg_type == RTM_NEWADDR ? - "NEWADDR" : "DELADDR"); + h->nlmsg_type == RTM_NEWADDR ? "NEWADDR" : "DELADDR"); + + // Parse attributes. + for ( ; RTA_OK(ra, ra_len); ra = RTA_NEXT(ra, ra_len)) { + //lwsl_cx_netlink_debug(cx, "%s: IFA %d\n", __func__, ra->rta_type); + switch (ra->rta_type) { + case IFA_LOCAL: + // Local address + lws_sa46_copy_address(&robj.src, RTA_DATA(ra), rm->rtm_family); + robj.src_len = rm->rtm_src_len; + lws_sa46_write_numeric_address(&robj.src, buf, sizeof(buf)); + lwsl_cx_netlink_debug(cx, "IFA_LOCAL: %s/%d", buf, robj.src_len); + break; + case IFA_ADDRESS: + // Prefix address, not local interface. + lws_sa46_copy_address(&robj.dest, RTA_DATA(ra), rm->rtm_family); + robj.dest_len = rm->rtm_dst_len; + lws_sa46_write_numeric_address(&robj.dest, buf, sizeof(buf)); + lwsl_cx_netlink_debug(cx, "IFA_ADDRESS: %s/%d", buf, robj.dest_len); + break; + case IFA_FLAGS: + lwsl_cx_netlink_debug(cx, "IFA_FLAGS: 0x%x (not handled)", + *(unsigned int*)RTA_DATA(ra)); + break; + case IFA_BROADCAST: + lwsl_cx_netlink_debug(cx, "IFA_BROADCAST (not handled)"); + break; + case IFA_ANYCAST: + lwsl_cx_netlink_debug(cx, "IFA_ANYCAST (not handled)"); + break; + case IFA_CACHEINFO: + lwsl_cx_netlink_debug(cx, "IFA_CACHEINFO (not handled)"); + break; + case IFA_LABEL: + strncpy(buf, RTA_DATA(ra), sizeof(buf)); + buf[sizeof(buf)-1] = '\0'; + lwsl_cx_netlink_debug(cx, "IFA_LABEL: %s (not used)", buf); + break; + default: + lwsl_cx_netlink_debug(cx, "unknown IFA attr type %d", ra->rta_type); + break; + } + //lwsl_cx_debug(cx, "rta payload length: %ld", RTA_PAYLOAD(ra)); + } /* for */ /* * almost nothing interesting within IFA_* attributes: @@ -256,7 +299,10 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, rm->rtm_family); robj.src_len = rm->rtm_src_len; lws_sa46_write_numeric_address(&robj.src, buf, sizeof(buf)); - lwsl_cx_netlink(cx, "RTA_SRC: %s", buf); + if (ra->rta_type == RTA_SRC) + lwsl_cx_netlink_debug(cx, "RTA_SRC: %s/%d", buf, robj.src_len); + else + lwsl_cx_netlink_debug(cx, "RTA_PREFSRC: %s/%d", buf, robj.src_len); break; case RTA_DST: /* check if is local addr -> considering it as src addr too */ @@ -265,19 +311,21 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, (rm->rtm_family == AF_INET6 && rm->rtm_dst_len == 128))) { lws_sa46_copy_address(&robj.src, RTA_DATA(ra), rm->rtm_family); - lwsl_cx_netlink(cx, "Local addr: RTA_DST -> added to RTA_SRC"); + lwsl_cx_netlink_debug(cx, "Local addr: RTA_DST -> added to RTA_SRC"); } lws_sa46_copy_address(&robj.dest, RTA_DATA(ra), - rm->rtm_family); + rm->rtm_family); robj.dest_len = rm->rtm_dst_len; lws_sa46_write_numeric_address(&robj.dest, buf, sizeof(buf)); - lwsl_cx_netlink(cx, "RTA_DST: %s", buf); + lwsl_cx_netlink_debug(cx, "RTA_DST: %s/%d", buf, robj.dest_len); break; case RTA_GATEWAY: - lws_sa46_copy_address(&robj.gateway, - RTA_DATA(ra), + lws_sa46_copy_address(&robj.gateway, RTA_DATA(ra), rm->rtm_family); + + lws_sa46_write_numeric_address(&robj.gateway, buf, sizeof(buf)); + lwsl_cx_netlink_debug(cx, "RTA_GATEWAY: %s", buf); #if defined(LWS_WITH_SYS_SMD) gateway_change = 1; #endif @@ -285,27 +333,31 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, case RTA_IIF: /* int: input interface index */ case RTA_OIF: /* int: output interface index */ robj.if_idx = *(int *)RTA_DATA(ra); - lwsl_cx_netlink(cx, "ifidx %d", robj.if_idx); + lwsl_cx_netlink_debug(cx, "RTA_IIF/RTA_OIF: %d", robj.if_idx); break; case RTA_PRIORITY: /* int: priority of route */ p = RTA_DATA(ra); robj.priority = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; + lwsl_cx_netlink_debug(cx, "RTA_PRIORITY: %d", robj.priority); break; case RTA_CACHEINFO: /* struct rta_cacheinfo */ + lwsl_cx_netlink_debug(cx, "RTA_CACHEINFO (not handled)"); break; #if defined(LWS_HAVE_RTA_PREF) case RTA_PREF: /* char: RFC4191 v6 router preference */ + lwsl_cx_netlink_debug(cx, "RTA_PREF (not handled)"); break; #endif case RTA_TABLE: /* int */ + lwsl_cx_netlink_debug(cx, "RTA_TABLE (not handled)"); break; default: - lwsl_cx_info(cx, "unknown attr type %d", - ra->rta_type); + lwsl_cx_netlink_debug(cx, "unknown attr type %d", ra->rta_type); break; } + //lwsl_cx_debug(cx, "rta payload length: %ld", RTA_PAYLOAD(ra)); } /* for */ /* @@ -327,83 +379,80 @@ second_half: case RTM_NEWROUTE: - lwsl_cx_netlink(cx, "NEWROUTE rtm_type %d", - rm->rtm_type); - /* * We don't want any routing debris like /32 or broadcast * in our routing table... we will collect source addresses * bound to interfaces via NEWADDR */ - - if (rm->rtm_type != RTN_UNICAST && - rm->rtm_type != RTN_LOCAL) + if (rm->rtm_type != RTN_UNICAST + && rm->rtm_type != RTN_LOCAL) { + lwsl_cx_netlink(cx, "NEWROUTE: IGNORED (%s)", + rm->rtm_type == RTN_BROADCAST ? "broadcast" : + rm->rtm_type == RTN_ANYCAST ? "anycast" : + rm->rtm_type == RTN_MULTICAST ? "multicast" : + rm->rtm_type == RTN_UNREACHABLE ? "unreachable" : + rm->rtm_type == RTN_NAT ? "nat" : + rm->rtm_type == RTN_UNSPEC ? "unspecified" : + "other"); break; + } - if (rm->rtm_flags & RTM_F_CLONED) + if (rm->rtm_flags & RTM_F_CLONED) { + lwsl_cx_netlink(cx, "NEWROUTE: IGNORED (cloned)"); break; + } - goto ana; + lwsl_cx_netlink(cx, "NEWROUTE: ACCEPTED (if_idx %d)", + robj.if_idx); - case RTM_DELADDR: - lwsl_cx_notice(cx, "DELADDR"); #if defined(_DEBUG) _lws_routing_entry_dump(cx, &robj); #endif + + /* + * 1. Allocate new route for linked-list. + * (robj is on stack, do NOT use) + */ + rou = lws_malloc(sizeof(*rou), __func__); + if (!rou) { + lwsl_cx_err(cx, "oom"); + return LWS_HPI_RET_HANDLED; + } + *rou = robj; + + // 2. Remove duplicates and add route (both under a lock). lws_pt_lock(pt, __func__); - _lws_route_remove(pt, &robj, LRR_MATCH_SRC | LRR_IGNORE_PRI); - _lws_route_pt_close_unroutable(pt); - lws_pt_unlock(pt); - break; - - case RTM_NEWADDR: - - lwsl_cx_netlink(cx, "NEWADDR"); -ana: /* * Is robj a dupe in the routing table already? * * match on pri ignore == set pri and skip * no match == add + * + * returns zero ALWAYS + * + * We could be adding a route to the same destination with + * a higher or lower priority from a different source, so why + * all existing routes? Only remove if its the same source and + * destination, effectively a change in priority. */ + _lws_route_remove(pt, &robj, + LRR_MATCH_DST | LRR_MATCH_SRC | LRR_IGNORE_PRI); - lws_pt_lock(pt, __func__); - - /* returns zero on match already in table */ - rmat = _lws_route_remove(pt, &robj, h->nlmsg_type == RTM_NEWROUTE ? - LRR_MATCH_DST : LRR_MATCH_SRC | LRR_IGNORE_PRI); - lws_pt_unlock(pt); - - if (rmat) { - rmat->priority = robj.priority; - break; - } - - rou = lws_malloc(sizeof(*rou), __func__); - if (!rou) { - lwsl_cx_err(cx, "oom"); - return LWS_HPI_RET_HANDLED; - } - - *rou = robj; - - lws_pt_lock(pt, __func__); - - /* - * We lock the pt before getting the uidx, so it - * cannot race - */ - + /* add route to linked-list */ rou->uidx = _lws_route_get_uidx(cx); lws_dll2_add_tail(&rou->list, &cx->routing_table); - lwsl_cx_info(cx, "route list size %u", - cx->routing_table.count); - - _lws_route_pt_close_unroutable(pt); - lws_pt_unlock(pt); + lwsl_cx_netlink_debug(cx, "route list size %u", + cx->routing_table.count); + + /* + * 3. Close anyything we cant reach anymore due to the removal. + * (don't need to or want to do this under lock) + */ + _lws_route_pt_close_unroutable(pt); + inform: #if defined(_DEBUG) route_change = 1; @@ -416,12 +465,39 @@ inform: */ (void)lws_smd_msg_printf(cx, LWSSMDCL_NETWORK, "{\"rt\":\"%s\"}\n", - (h->nlmsg_type == RTM_DELROUTE) ? - "del" : "add"); + (h->nlmsg_type == RTM_NEWROUTE) ? + "add" : "del"); #endif break; + case RTM_DELADDR: + lwsl_cx_notice(cx, "DELADDR"); +#if defined(_DEBUG) + _lws_routing_entry_dump(cx, &robj); +#endif + lws_pt_lock(pt, __func__); + removed = cx->routing_table.count; + _lws_route_remove(pt, &robj, LRR_MATCH_SRC | LRR_IGNORE_PRI); + removed -= cx->routing_table.count; + lws_pt_unlock(pt); + _lws_route_pt_close_unroutable(pt); + if (removed > 0) + goto inform; + break; + + case RTM_NEWADDR: + lwsl_cx_netlink(cx, "NEWADDR (nothing to do)"); +#if defined(_DEBUG) + _lws_routing_entry_dump(cx, &robj); +#endif + /* + * An address alone does not provide new routes. + * NEWADDR will happen when the DHCP lease is being + * renewed, and will likely not change any routes. + */ + break; + default: // lwsl_info("%s: unknown msg type %d\n", __func__, // h->nlmsg_type); diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c index f569532ec..f67927b2a 100644 --- a/lib/roles/ws/client-parser-ws.c +++ b/lib/roles/ws/client-parser-ws.c @@ -637,6 +637,7 @@ utf8_fail: if (n == PMDR_DID_NOTHING #if !defined(LWS_WITHOUT_EXTENSIONS) + || n == PMDR_NOTHING_WE_SHOULD_DO || n == PMDR_UNKNOWN #endif ) diff --git a/lib/roles/ws/client-ws.c b/lib/roles/ws/client-ws.c index bc2a84682..750aea96f 100644 --- a/lib/roles/ws/client-ws.c +++ b/lib/roles/ws/client-ws.c @@ -257,15 +257,15 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } if (wsi->http.ah->http_response == 401) { - lwsl_wsi_warn(wsi, "got bad HTTP response '%d'", - wsi->http.ah->http_response); + lwsl_wsi_warn(wsi, "got bad HTTP response '%ld'", + (long)wsi->http.ah->http_response); *cce = "HS: ws upgrade unauthorized"; goto bail3; } if (wsi->http.ah->http_response != 101) { - lwsl_wsi_warn(wsi, "got bad HTTP response '%d'", - wsi->http.ah->http_response); + lwsl_wsi_warn(wsi, "got bad HTTP response '%ld'", + (long)wsi->http.ah->http_response); *cce = "HS: ws upgrade response not 101"; goto bail3; } diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 8bf622b01..ac760be67 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -248,12 +248,13 @@ lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, } /* - * Content-length on POST / PUT if we have the length information + * Content-length on POST / PUT / PATCH if we have the length information */ if (h->policy->u.http.method && ( (!strcmp(h->policy->u.http.method, "POST") || - !strcmp(h->policy->u.http.method, "PUT"))) && + !strcmp(h->policy->u.http.method, "PATCH") || + !strcmp(h->policy->u.http.method, "PUT"))) && wsi->http.writeable_len) { if (!(h->policy->flags & LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) { @@ -840,6 +841,7 @@ malformed: h->policy->protocol == LWSSSP_H2) && h->being_serialized && ( !strcmp(h->policy->u.http.method, "PUT") || + !strcmp(h->policy->u.http.method, "PATCH") || !strcmp(h->policy->u.http.method, "POST"))) { wsi->client_suppress_CONNECTION_ERROR = 1; @@ -1105,6 +1107,16 @@ malformed: return -1; if (lws_ss_alloc_set_metadata(h, "method", "POST", 4)) return -1; + } else { + m = lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI); + if (m) { + if (lws_ss_alloc_set_metadata(h, "path", + lws_hdr_simple_ptr(wsi, + WSI_TOKEN_PATCH_URI), (unsigned int)m)) + return -1; + if (lws_ss_alloc_set_metadata(h, "method", "PATCH", 5)) + return -1; + } } } } diff --git a/lib/secure-streams/system/auth-sigv4/sign.c b/lib/secure-streams/system/auth-sigv4/sign.c index 93f96db55..b797e157b 100644 --- a/lib/secure-streams/system/auth-sigv4/sign.c +++ b/lib/secure-streams/system/auth-sigv4/sign.c @@ -464,7 +464,7 @@ lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx, #if defined(__linux__) || defined(__APPLE__) || defined(WIN32) || \ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__ANDROID__) || \ - defined(__sun) || defined(__OpenBSD__) + defined(__sun) || defined(__OpenBSD__) || defined(__NuttX__) /* ie, if we have filesystem ops */ diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index a2b78c252..8572699ee 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -401,7 +401,8 @@ if (LWS_WITH_MBEDTLS) else() CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID) CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_set_verify; return !!v; }\n" LWS_HAVE_mbedtls_ssl_set_verify) - CHECK_SYMBOL_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_conf_alpn_protocols; return !!v; }\n" LWS_HAVE_mbedtls_ssl_conf_alpn_protocols) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE) CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE) CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE) @@ -570,6 +571,8 @@ endif() exports_to_parent_scope() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols ${LWS_HAVE_mbedtls_ssl_conf_alpn_protocols} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) diff --git a/lib/tls/mbedtls/CMakeLists.txt b/lib/tls/mbedtls/CMakeLists.txt index e34151724..6208f182a 100644 --- a/lib/tls/mbedtls/CMakeLists.txt +++ b/lib/tls/mbedtls/CMakeLists.txt @@ -124,6 +124,7 @@ include_directories(wrapper/include wrapper/include/internal) # old mbedtls has everything in mbedtls/net.h CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return MBEDTLS_SSL_NEW_SESSION_TICKET;}\n" LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET) # # Keep explicit parent scope exports at end @@ -131,3 +132,4 @@ CHECK_C_SOURCE_COMPILES("#include \nint main(void) { retu exports_to_parent_scope() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 7b378fa80..196c9219d 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -183,7 +183,12 @@ int ssl_pm_new(SSL *ssl) mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version); } else { mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); +#else mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, 1); +#endif } mbedtls_ssl_conf_rng(&ssl_pm->conf, mbedtls_ctr_drbg_random, &ssl_pm->ctr_drbg); @@ -251,9 +256,9 @@ static int ssl_pm_reload_crt(SSL *ssl) struct x509_pm *crt_pm = (struct x509_pm *)ssl->cert->x509->x509_pm; if (ssl->verify_mode == SSL_VERIFY_PEER) - mode = MBEDTLS_SSL_VERIFY_REQUIRED; - else if (ssl->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + else if (ssl->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + mode = MBEDTLS_SSL_VERIFY_REQUIRED; else if (ssl->verify_mode == SSL_VERIFY_CLIENT_ONCE) mode = MBEDTLS_SSL_VERIFY_UNSET; else @@ -549,7 +554,11 @@ OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: state = TLS_ST_SR_KEY_EXCH; break; +#if defined(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET) + case MBEDTLS_SSL_NEW_SESSION_TICKET: +#else case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: +#endif state = TLS_ST_SW_SESSION_TICKET; break; case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: @@ -761,8 +770,13 @@ int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len) mbedtls_pk_init(pkey_pm->pkey); #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03050000 + ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len, NULL, 0, + mbedtls_ctr_drbg_random, pkey_pm->rngctx); +#else ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len + 1, NULL, 0, mbedtls_ctr_drbg_random, pkey_pm->rngctx); +#endif #else ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len + 1, NULL, 0); #endif diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index b4181721d..da72ecba2 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -517,6 +517,7 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) unsigned int len; #endif int m, n, en; + unsigned long l; #if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_HAVE_SSL_SESSION_set_time) SSL_SESSION *sess; #endif @@ -541,9 +542,10 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) } if (m == SSL_ERROR_SSL) { + l = ERR_get_error(); n = lws_snprintf(errbuf, elen, "tls: %s", wsi->tls.err_helper); if (!wsi->tls.err_helper[0]) - ERR_error_string_n((unsigned int)m, errbuf + n, (elen - (unsigned int)n)); + ERR_error_string_n((unsigned int)l, errbuf + n, (elen - (unsigned int)n)); return LWS_SSL_CAPABLE_ERROR; } @@ -922,6 +924,10 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } + SSL_CTX_set_ex_data(vh->tls.ssl_client_ctx, + openssl_SSL_CTX_private_data_index, + (char *)vh->context); + lws_plat_vhost_tls_client_ctx_init(vh); tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr"); diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 43d65e030..1fc819293 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -706,7 +706,7 @@ lws_tls_server_abort_connection(struct lws *wsi) SSL_shutdown(wsi->tls.ssl); SSL_free(wsi->tls.ssl); - return 0; + return LWS_SSL_CAPABLE_DONE; } enum lws_ssl_capable_status diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index cf4d2b8c6..11e9b49fa 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -57,8 +57,6 @@ int lws_ssl_get_error(struct lws *wsi, int n) m = SSL_get_error(wsi->tls.ssl, n); lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, LWS_ERRNO); - if (m == SSL_ERROR_SSL) - lws_tls_err_describe_clear(); // assert (LWS_ERRNO != 9); @@ -250,6 +248,9 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */ goto do_err; + if (m == SSL_ERROR_SSL) + lws_tls_err_describe_clear(); + /* hm not retryable.. could be 0 size pkt or error */ if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL || diff --git a/minimal-examples-lowlevel/api-tests/api-test-async-dns/main.c b/minimal-examples-lowlevel/api-tests/api-test-async-dns/main.c index ff61e07f0..fa223ea75 100644 --- a/minimal-examples-lowlevel/api-tests/api-test-async-dns/main.c +++ b/minimal-examples-lowlevel/api-tests/api-test-async-dns/main.c @@ -69,7 +69,7 @@ static const struct ipparser_tests { #define TEST_FLAG_NOCHECK_RESULT_IP 0x100000 -static const struct async_dns_tests { +static struct async_dns_tests { const char *dns_name; int recordtype; int addrlen; @@ -390,13 +390,52 @@ void sigint_handler(int sig) interrupted = 1; } +int +fixup(int idx) +{ + struct addrinfo hints, *ai; + int m; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + m = getaddrinfo(adt[idx].dns_name, "80", &hints, &ai); + if (m) { + lwsl_err("Unable to look up %s: %s", adt[0].dns_name, + gai_strerror(m)); + return 1; + } + adt[idx].ads[0] = (uint8_t)((struct sockaddr *)ai->ai_addr)->sa_data[2]; + adt[idx].ads[1] = (uint8_t)((struct sockaddr *)ai->ai_addr)->sa_data[3]; + adt[idx].ads[2] = (uint8_t)((struct sockaddr *)ai->ai_addr)->sa_data[4]; + adt[idx].ads[3] = (uint8_t)((struct sockaddr *)ai->ai_addr)->sa_data[5]; + + freeaddrinfo(ai); + + lwsl_notice("%s: %u.%u.%u.%u\n", __func__, + adt[idx].ads[0], adt[idx].ads[1], adt[idx].ads[2], adt[idx].ads[3]); + + return 0; +} + int main(int argc, const char **argv) { int n = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; struct lws_context_creation_info info; + uint8_t mac[6]; const char *p; + /* fixup dynamic target addresses we're testing against */ + + fixup(0); + fixup(1); + fixup(2); + fixup(5); + fixup(6); + /* the normal lws init */ signal(SIGINT, sigint_handler); @@ -479,6 +518,40 @@ main(int argc, const char **argv) ok++; } + /* mac address parser tests */ + + if (lws_parse_mac("11:ff:ce:CE:22:33", mac)) { + lwsl_err("%s: mac fail 1\n", __func__); + lwsl_hexdump_notice(mac, 6); + fail++; + } else + if (mac[0] != 0x11 || mac[1] != 0xff || mac[2] != 0xce || + mac[3] != 0xce || mac[4] != 0x22 || mac[5] != 0x33) { + lwsl_err("%s: mac fail 2\n", __func__); + lwsl_hexdump_notice(mac, 6); + fail++; + } + if (!lws_parse_mac("11:ff:ce:CE:22:3", mac)) { + lwsl_err("%s: mac fail 3\n", __func__); + lwsl_hexdump_notice(mac, 6); + fail++; + } + if (!lws_parse_mac("11:ff:ce:CE:22", mac)) { + lwsl_err("%s: mac fail 4\n", __func__); + lwsl_hexdump_notice(mac, 6); + fail++; + } + if (!lws_parse_mac("11:ff:ce:CE:22:", mac)) { + lwsl_err("%s: mac fail 5\n", __func__); + lwsl_hexdump_notice(mac, 6); + fail++; + } + if (!lws_parse_mac("11:ff:ce:CE22", mac)) { + lwsl_err("%s: mac fail 6\n", __func__); + lwsl_hexdump_notice(mac, 6); + fail++; + } + #if !defined(LWS_WITH_IPV6) _exp -= 2; #endif diff --git a/minimal-examples-lowlevel/raw/minimal-raw-wol/CMakeLists.txt b/minimal-examples-lowlevel/raw/minimal-raw-wol/CMakeLists.txt new file mode 100644 index 000000000..b00a47734 --- /dev/null +++ b/minimal-examples-lowlevel/raw/minimal-raw-wol/CMakeLists.txt @@ -0,0 +1,23 @@ +project(lws-minimal-raw-wol C) +cmake_minimum_required(VERSION 3.6) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-raw-wol) +set(SRCS minimal-raw-wol.c) + +set(requirements 1) +require_lws_config(LWS_WITH_WOL 1 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff --git a/minimal-examples-lowlevel/raw/minimal-raw-wol/README.md b/minimal-examples-lowlevel/raw/minimal-raw-wol/README.md new file mode 100644 index 000000000..b2ed87eee --- /dev/null +++ b/minimal-examples-lowlevel/raw/minimal-raw-wol/README.md @@ -0,0 +1,34 @@ +# lws minimal raw wol + +This example shows how to send a Wake On Lan magic packet to a given mac. + +## build + +``` + $ cmake . && make +``` + +## usage + +``` +$ bin/lws-minimal-raw-wol b4:2e:99:a9:22:90 +[2023/11/09 12:25:24:2255] N: lws_create_context: LWS: 4.3.99-v4.3.0-295-g60d671c7, NET CLI SRV H1 H2 WS SS-JSON-POL ConMon ASYNC_DNS IPv6-absent +[2023/11/09 12:25:24:2256] N: __lws_lc_tag: ++ [wsi|0|pipe] (1) +[2023/11/09 12:25:24:2256] N: __lws_lc_tag: ++ [vh|0|netlink] (1) +[2023/11/09 12:25:24:2256] N: __lws_lc_tag: ++ [vh|1|system||-1] (2) +[2023/11/09 12:25:24:2257] N: __lws_lc_tag: ++ [wsisrv|0|system|asyncdns] (1) +[2023/11/09 12:25:24:2257] N: __lws_lc_tag: ++ [wsisrv|1|system|asyncdns] (2) +[2023/11/09 12:25:24:2257] N: __lws_lc_tag: ++ [vh|2|default||0] (3) +[2023/11/09 12:25:24:2257] N: [vh|2|default||0]: lws_socket_bind: source ads 0.0.0.0 +[2023/11/09 12:25:24:2257] N: __lws_lc_tag: ++ [wsi|1|listen|default||33749] (2) +[2023/11/09 12:25:24:2257] N: lws_wol: Sending WOL to B4:2E:99:A9:22:90 +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [wsi|0|pipe] (1) 190μs +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [wsi|1|listen|default||33749] (0) 80μs +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [wsisrv|1|system|asyncdns] (1) 118μs +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [wsisrv|0|system|asyncdns] (0) 155μs +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [vh|0|netlink] (2) 198μs +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [vh|1|system||-1] (1) 182μs +[2023/11/09 12:25:24:2258] N: __lws_lc_untag: -- [vh|2|default||0] (0) 125μs + +$ +``` \ No newline at end of file diff --git a/minimal-examples-lowlevel/raw/minimal-raw-wol/minimal-raw-wol.c b/minimal-examples-lowlevel/raw/minimal-raw-wol/minimal-raw-wol.c new file mode 100644 index 000000000..a9b813600 --- /dev/null +++ b/minimal-examples-lowlevel/raw/minimal-raw-wol/minimal-raw-wol.c @@ -0,0 +1,52 @@ +/* + * lws-minimal-raw-wol + * + * Written in 2010-2023 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates using lws_wol() + */ + +#include +#include + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *ctx; + const char *p, *ip = NULL; + uint8_t mac[IFHWADDRLEN]; + int ret = 1; + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + if ((p = lws_cmdline_option(argc, argv, "-ip"))) + ip = p; + + if (argc < 2) { + lwsl_user("lws-minimal-raw-wol XX:XX:XX:XX:XX:XX [-ip interface IP]\n"); + goto bail1; + } + + if (lws_parse_mac(argv[1], mac)) { + lwsl_user("Failed to parse mac '%s'\n", argv[1]); + goto bail1; + } + + ctx = lws_create_context(&info); + if (!ctx) { + lwsl_err("lws init failed\n"); + goto bail1; + } + + if (!lws_wol(ctx, ip, mac)) + ret = 0; + + lws_context_destroy(ctx); + +bail1: + return ret; +}