From f9d1f25abe896b9fa1de780e4a5cb41116926a29 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 14 Jun 2023 07:14:23 +0100 Subject: [PATCH 01/23] openssl-server: enum vs int disagreement https://github.com/warmcat/libwebsockets/issues/2907 --- lib/tls/openssl/openssl-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index f2e77324f..1fc819293 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -699,14 +699,14 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) return 0; } -int +enum lws_ssl_capable_status lws_tls_server_abort_connection(struct lws *wsi) { if (wsi->tls.use_ssl) SSL_shutdown(wsi->tls.ssl); SSL_free(wsi->tls.ssl); - return 0; + return LWS_SSL_CAPABLE_DONE; } enum lws_ssl_capable_status From a6a7fa646e9c04f1322dbaae611f17529439d157 Mon Sep 17 00:00:00 2001 From: Philippe Coval Date: Sat, 8 Jul 2023 11:29:29 +0200 Subject: [PATCH 02/23] fix: l/r/h/http2.c: Fix spelling mistake Fix spelling mistake it was found while packaging mosquito for debian: I: mosquitto: spelling-error-in-binary Inital Initial [usr/sbin/mosquitto] I: mosquitto: spelling-error-in-binary witholding withholding [usr/sbin/mosquitto] Forwarded: https://github.com/warmcat/libwebsockets/pull/2927 Signed-off-by: Philippe Coval --- lib/roles/h2/http2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 50cdccec4..15e9ef610 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; From 07778789f4af037721174cfbe1f336dbb059e6c7 Mon Sep 17 00:00:00 2001 From: wangyingdong Date: Tue, 19 Sep 2023 15:58:38 +0800 Subject: [PATCH 03/23] Introducing libwebsockets support for nuttx Signed-off-by: wangyingdong --- include/libwebsockets.h | 2 +- lib/plat/unix/private-lib-plat-unix.h | 2 +- lib/plat/unix/unix-sockets.c | 9 +++++++-- lib/roles/ws/client-ws.c | 8 ++++---- lib/secure-streams/system/auth-sigv4/sign.c | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) 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/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..2a3069b54 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -171,7 +171,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 +190,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 +211,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 +239,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 +273,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) } +#if !defined(__NuttX__) for (n = 0; n < 4; n++) { if (!(lws_flags & ip_opt_lws_flags[n])) continue; @@ -287,6 +291,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/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/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 */ From 7ef2065fdf38f74d196238ebc618b7009e25e408 Mon Sep 17 00:00:00 2001 From: Mark Butowski Date: Sat, 23 Sep 2023 06:35:07 +0000 Subject: [PATCH 04/23] netlink: fix errant route delete on NEWADDR NEWADDR was errantly deleting route entities, specifically it happend to delete IPv6 route entries causing a disconnect of all IPv6 clients. NEWADDR can be issued on a DHCP lease renew, which does not change any of the routes. Code was also cleaned up a bit, and added some helpful logging. --- lib/roles/netlink/ops-netlink.c | 210 ++++++++++++++++++++++---------- 1 file changed, 143 insertions(+), 67 deletions(-) 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); From 4144c1e61bfc69b08f52e727f687430026ebb608 Mon Sep 17 00:00:00 2001 From: Daniel Danzberger Date: Mon, 5 Jun 2023 21:24:59 +0200 Subject: [PATCH 05/23] mbedtls-server: Fix broken client verification This fixes clients being able to connect with a certicate that was not signed by the configured CA when SSL_VERIFY_FAIL_IF_NO_PEER_CERT is set. The issue only appeared when a client connects via IP address directly and not use a hostname. When the hostname was used to connect, the SNI 'callback lws_mbedtls_sni_cb' overwrote the invalid verfiy mode of MBEDTLS_SSL_VERIFY_OPTIONAL with MBEDTLS_SSL_VERIFY_REQUIRED by calling SSL_set_SSL_CTX. Signed-off-by: Daniel Danzberger --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 7b378fa80..d7e7c399c 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -251,9 +251,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 From 18fdb0d6ecfd7ec8090ed7164fd6e4895a89e12b Mon Sep 17 00:00:00 2001 From: Dylan Taft Date: Sat, 14 Oct 2023 16:52:25 -0400 Subject: [PATCH 06/23] ipv6: Add support for RFC5014 for Linux Linux has a sockopt flag defined by RFC5014 that informs IPv6 systems with SLAAC config to prefer to bind the socket to a public address instead of any temporary private address. This patch adds a client info flag LCCSCF_IPV6_PREFER_PUBLIC_ADDR that lets the user indicate the client socket should be prepared with the public address binding preference. Currently it's only implemented on Linux. --- CMakeLists.txt | 1 + cmake/lws_config.h.in | 2 +- include/libwebsockets/lws-client.h | 5 +++++ lib/plat/unix/unix-sockets.c | 26 +++++++++++++++++++++++++- lib/plat/windows/windows-sockets.c | 10 ++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 321c5bd6e..802e2a2ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -658,6 +658,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..041cd8719 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -258,4 +258,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/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/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 2a3069b54..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) @@ -273,6 +277,26 @@ 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])) 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; From 573678639119efba312438738b86e874ee75b96c Mon Sep 17 00:00:00 2001 From: Audric Schiltknecht Date: Fri, 20 Oct 2023 17:42:35 -0400 Subject: [PATCH 07/23] openssl: Properly report OpenSSL error in lws_tls_client_connect In case of an SSL_ERROR_SSL in lws_tls_client_connect, the lws_ssl_get_error call was calling lws_tls_err_describe_clear which cleared the OpenSSL error from the stack. Thus, the tls.err_helper attribute was set to the default value from ERR_error_string_n, masking the actual OpenSSL error message from client code. --- lib/tls/openssl/openssl-client.c | 4 +++- lib/tls/openssl/openssl-ssl.c | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index b4181721d..a46083a0d 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; } 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 || From a1cbc02aeb28303a22781f3a37730fefbf2d6fce Mon Sep 17 00:00:00 2001 From: zoraaver Date: Tue, 7 Feb 2023 15:59:26 +0000 Subject: [PATCH 08/23] Add guard for setrlimit LWS_HAVE_SYS_RESOURCE_H is correctly set by lws to prevent including sys/resource.h. However there is no corresponding guard for setrlimit (a function from that header). This causes a build failure on platforms which don't have sys/resource.h available. --- lib/core/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/context.c b/lib/core/context.c index 98e70d8e3..dc0e5933a 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -963,7 +963,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 From d4c9158d88502041d0e9375cd51ad109ca8ff35d Mon Sep 17 00:00:00 2001 From: Nate Karstens Date: Fri, 20 Oct 2023 13:25:09 -0500 Subject: [PATCH 09/23] openssl: Add lws ctx ref to client vhost's SSL_CTX Adds a reference to the libwebsockets context to the OpenSSL context used by the client vhost. This allows SSL info callbacks to work correctly for clients, like it currently does for servers. Co-authored-by: Marty Flickinger Signed-off-by: Marty Flickinger Signed-off-by: Nate Karstens --- lib/tls/openssl/openssl-client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index a46083a0d..da72ecba2 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -924,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"); From 816544f1d6d05cfa5d9fa5875f38e218c56285b3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 27 Oct 2023 05:50:26 +0100 Subject: [PATCH 10/23] ss: http: support PATCH https://github.com/warmcat/libwebsockets/issues/2989 --- lib/secure-streams/protocols/ss-h1.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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; + } } } } From e71398c02ac2db15e28f38367491af8600867bca Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 31 Oct 2023 10:50:40 +0000 Subject: [PATCH 11/23] mbedtls: auto adapt to changed session constant --- cmake/lws_config.h.in | 1 + lib/CMakeLists.txt | 1 + lib/tls/CMakeLists.txt | 1 + lib/tls/mbedtls/CMakeLists.txt | 2 ++ lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 4 ++++ 5 files changed, 9 insertions(+) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 041cd8719..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 diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8d21c1240..332df318c 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -371,6 +371,7 @@ 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(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/CMakeLists.txt b/lib/tls/CMakeLists.txt index a2b78c252..c7425e154 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -570,6 +570,7 @@ 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(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 d7e7c399c..aab9eff73 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -549,7 +549,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: From 05e08a511add353f1b81d4548fcf1cb2e4ee39ce Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Nov 2023 08:06:50 +0000 Subject: [PATCH 12/23] mbedtls: print library version --- lib/core/context.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index dc0e5933a..3bee0de98 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,17 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ - lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); +#if defined(LWS_WITH_MBEDTLS) + mbedtls_version_get_string(mbedtls_version); +#endif + + lwsl_cx_notice(context, +#if defined(LWS_WITH_MBEDTLS) + "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); +#else + "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 From 2da771b129cd813e58a15da544501657be94acaa Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Nov 2023 09:54:49 +0000 Subject: [PATCH 13/23] cmake: mbedtls: mbedtls_ssl_conf_alpn_protocols check --- lib/CMakeLists.txt | 1 + lib/tls/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 332df318c..dcbd4053f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -372,6 +372,7 @@ if (DEFINED LWS_PLAT_UNIX) 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/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index c7425e154..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) @@ -571,6 +572,7 @@ 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) From 407f88615fc53cc86c436fb28737d3f82fcc91c7 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Nov 2023 09:56:20 +0000 Subject: [PATCH 14/23] mbedtls: if we have tls1.2 only accept exactly that --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index aab9eff73..6d646e189 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); From 26c3f9a01bb41d75126dc6817459b7c4a3491431 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 5 Nov 2023 08:25:33 +0000 Subject: [PATCH 15/23] tls: mbedtls-3.5.0: correct privkey size --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 6d646e189..196c9219d 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -770,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 From 65f977c7dee092662045c84662b403960c0f3e86 Mon Sep 17 00:00:00 2001 From: Ogre Transporter Date: Tue, 7 Nov 2023 06:30:25 +0000 Subject: [PATCH 16/23] msvc: avoid error about mixed ellipsis and cond https://github.com/warmcat/libwebsockets/issues/3001 --- lib/core/context.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index 3bee0de98..70aafed97 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -812,11 +812,10 @@ lws_create_context(const struct lws_context_creation_info *info) mbedtls_version_get_string(mbedtls_version); #endif - lwsl_cx_notice(context, #if defined(LWS_WITH_MBEDTLS) - "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); + lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); #else - "LWS: %s, %s%s", library_version, opts_str, s); + lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); #endif #if defined(LWS_WITH_NETWORK) From 48e09ddf51ea014a60d666f8eb780cd801c0d4b5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 8 Nov 2023 07:26:32 +0000 Subject: [PATCH 17/23] clean: pedantic: remove repeated typedefs https://github.com/warmcat/libwebsockets/issues/3002 --- include/libwebsockets/lws-dlo.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 From 3454cd1f8aade94264b04047b41fb61a215f3bda Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 9 Nov 2023 12:02:47 +0000 Subject: [PATCH 18/23] test: async dns: handle dynamic ads on warmcat We use warmcat dns for testing, but for a while it has become dynamic breaking the tests. Fix up the affected tests with IPv4 addresses from getaddrinfo() so they pass when they match these results. --- .../api-tests/api-test-async-dns/main.c | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) 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..6a9a32f46 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,6 +390,36 @@ 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) { @@ -397,6 +427,14 @@ main(int argc, const char **argv) struct lws_context_creation_info info; 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); From 5bcc5ac655b0656906ed92c432ff2d59b0da3dd2 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 9 Nov 2023 12:00:36 +0000 Subject: [PATCH 19/23] net: lws_wol() and lws_parse_mac() Introduce a LWS_WITH_WOL and an api to wake a mac address, optionally with an address bind to the local interface to go out on. Add a helper to parse ascii mac addresses well, and add tests. --- CMakeLists.txt | 1 + include/libwebsockets/lws-misc.h | 12 +++ include/libwebsockets/lws-network-helper.h | 14 +++- lib/core-net/CMakeLists.txt | 5 ++ lib/core-net/network.c | 59 +++++++++++++ lib/core-net/wol.c | 84 +++++++++++++++++++ .../api-tests/api-test-async-dns/main.c | 35 ++++++++ .../raw/minimal-raw-wol/CMakeLists.txt | 23 +++++ .../raw/minimal-raw-wol/README.md | 34 ++++++++ .../raw/minimal-raw-wol/minimal-raw-wol.c | 52 ++++++++++++ 10 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 lib/core-net/wol.c create mode 100644 minimal-examples-lowlevel/raw/minimal-raw-wol/CMakeLists.txt create mode 100644 minimal-examples-lowlevel/raw/minimal-raw-wol/README.md create mode 100644 minimal-examples-lowlevel/raw/minimal-raw-wol/minimal-raw-wol.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 802e2a2ac..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) 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/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/minimal-examples-lowlevel/api-tests/api-test-async-dns/main.c b/minimal-examples-lowlevel/api-tests/api-test-async-dns/main.c index 6a9a32f46..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 @@ -425,6 +425,7 @@ 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 */ @@ -517,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; +} From bfce9f86187b0846c3eab359591e64ed4fa4bb0a Mon Sep 17 00:00:00 2001 From: Carsten Schuette Date: Fri, 10 Nov 2023 11:13:24 +0000 Subject: [PATCH 20/23] clean: gcc13 false positive uninitialized https://github.com/warmcat/libwebsockets/issues/3004 --- lib/roles/h2/http2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 15e9ef610..16d10729b 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -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; /* From 288f36fc8178e2664614b78322d2d05a70b9ac0a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 11 Nov 2023 07:37:40 +0000 Subject: [PATCH 21/23] buflist: append: treat NULL additional buf as error not assert Very very occasionally on server we try to add a NULL buffer to a buflist. Let's try dealing with that by failing (caller must always be able to handle failure from OOM) rather than asserting. --- lib/core/buflist.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 */ From 0586d0167872ab83abbb31edadcff778daf3cbbe Mon Sep 17 00:00:00 2001 From: Daren Hayward <54070183+darhaywa@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:36:02 +0000 Subject: [PATCH 22/23] b64: lws_b64_decode_stateful truncates response Addresses issue #2855 by allowing the parsing of the final byte when there are at least 3 bytes remaining in the buffer. For every 4 bytes of input, a maximum of 3 bytes of output are generated when decoding the base64 string. The buffer space, therefore, only requires an additional 3 bytes of space. The code checks for space in the buffer before adding null termination. --- lib/misc/base64-decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From a99b9545e8f667a1332c33091effcda5684084ad Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Mon, 24 Apr 2023 14:23:49 +0800 Subject: [PATCH 23/23] pmd: fix ws parser for non pmd packet with pmd ext enabled --- lib/roles/ws/client-parser-ws.c | 1 + 1 file changed, 1 insertion(+) 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 )