1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

Merge branch 'warmcat:main' into main

This commit is contained in:
GuzhavinAleksey 2023-11-13 16:21:29 +03:00 committed by GitHub
commit a2d51ba952
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 633 additions and 105 deletions

View file

@ -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 <malloc.h>\nvoid main(void) { while(1) ; } voi
CHECK_C_SOURCE_COMPILES("#include <pthread.h>\nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_PTHREAD_H)
CHECK_C_SOURCE_COMPILES("#include <inttypes.h>\nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_INTTYPES_H)
CHECK_C_SOURCE_COMPILES("#include <sys/resource.h>\nvoid main(void) { while(1) ; } void xxexit(void){}" LWS_HAVE_SYS_RESOURCE_H)
CHECK_C_SOURCE_COMPILES("#include <linux/ipv6.h>\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)

View file

@ -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

View file

@ -146,7 +146,7 @@ typedef int suseconds_t;
#include <sys/capability.h>
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__QNX__) || defined(__OpenBSD__)
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__QNX__) || defined(__OpenBSD__) || defined(__NuttX__)
#include <sys/socket.h>
#include <netinet/in.h>
#endif

View file

@ -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.

View file

@ -24,6 +24,9 @@
* lws display_list and display_list objects (dlo)
*/
#if !defined(__LWS_DLO_H__)
#define __LWS_DLO_H__
#include <stdint.h>
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

View file

@ -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);

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2023 Andy Green <andy@warmcat.com>
*
* 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);
///@}

View file

@ -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)

View file

@ -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

View file

@ -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;
}

84
lib/core-net/wol.c Normal file
View file

@ -0,0 +1,84 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2023 Andy Green <andy@warmcat.com>
*
* 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;
}

View file

@ -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 */

View file

@ -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

View file

@ -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;

View file

@ -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 <syslog.h>
#if defined(__ANDROID__)

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2023 Andy Green <andy@warmcat.com>
*
* 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 <linux/ipv6.h>
#endif
#include <sys/ioctl.h>
#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;
}

View file

@ -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;

View file

@ -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;
/*

View file

@ -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);

View file

@ -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
)

View file

@ -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;
}

View file

@ -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;
}
}
}
}

View file

@ -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 */

View file

@ -401,7 +401,8 @@ if (LWS_WITH_MBEDTLS)
else()
CHECK_C_SOURCE_COMPILES("#include <mbedtls/x509_crt.h>\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 <mbedtls/ssl.h>\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 <mbedtls/ssl.h>\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)

View file

@ -124,6 +124,7 @@ include_directories(wrapper/include wrapper/include/internal)
# old mbedtls has everything in mbedtls/net.h
CHECK_C_SOURCE_COMPILES("#include <mbedtls/net_sockets.h>\nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS)
CHECK_C_SOURCE_COMPILES("#include <mbedtls/ssl.h>\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 <mbedtls/net_sockets.h>\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)

View file

@ -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

View file

@ -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");

View file

@ -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

View file

@ -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 ||

View file

@ -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

View file

@ -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()

View file

@ -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
$
```

View file

@ -0,0 +1,52 @@
/*
* lws-minimal-raw-wol
*
* Written in 2010-2023 by Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* This demonstrates using lws_wol()
*/
#include <libwebsockets.h>
#include <net/if.h>
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;
}