Skip to content

Commit

Permalink
ipv6: Add support for RFC5014 for Linux
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dylanetaft authored and lws-team committed Oct 15, 2023
1 parent 4144c1e commit 18fdb0d
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 2 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,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)
Expand Down
2 changes: 1 addition & 1 deletion cmake/lws_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,4 @@
#cmakedefine LWS_WITH_PLUGINS_API
#cmakedefine LWS_HAVE_RTA_PREF
#cmakedefine PICO_SDK_PATH

#cmakedefine LWS_HAVE_LINUX_IPV6_H
5 changes: 5 additions & 0 deletions include/libwebsockets/lws-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
26 changes: 25 additions & 1 deletion lib/plat/unix/unix-sockets.c
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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]))
Expand Down
10 changes: 10 additions & 0 deletions lib/plat/windows/windows-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 18fdb0d

Please sign in to comment.