summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Fedoryshchenko <denys.f@collabora.com>2026-07-12 23:11:39 +0300
committerDenys Fedoryshchenko <denys.f@collabora.com>2026-07-12 23:11:39 +0300
commit1c43c26d5c87df722141ad6a37f068968a9a6b5b (patch)
tree4270bcfd09755ad141c2a1c479c17c9306535f24
parentf4014a4a2c9e654646faeb81cd9ac5841b1c9b0f (diff)
downloadaccel-ppp-1c43c26d5c87df722141ad6a37f068968a9a6b5b.tar.gz
accel-ppp-1c43c26d5c87df722141ad6a37f068968a9a6b5b.zip
ipv6cp: fix byte order of default interface-id values
The default fixed interface-ids conf_intf_id_val=1 and conf_peer_intf_id_val=2 were plain host-order integers, while every consumer (build_ip6_addr(), ifcfg.c, nd.c, dhcpv6.c) treats intf_id as an opaque 8-byte value in network byte order and copies it verbatim into the low 64 bits of the IPv6 address. parse_intfid() also produces network byte order, so only the built-in defaults were affected. On little-endian hosts this produced fe80::100:0:0:0 (and ::200:0:0:0 for the peer) instead of the intended fe80::1 / ::2 whenever ipv6-intf-id / ipv6-peer-intf-id were not set in the config. Store the defaults with htobe64() so the resulting addresses are ::1 and ::2 regardless of host endianness. The assignment is done in init() because htobe64() is not a constant expression on all libcs. Note: on little-endian deployments this changes the server link-local address from fe80::100:0:0:0 to fe80::1 when ipv6-intf-id is unset.
-rw-r--r--accel-pppd/ppp/ipv6cp_opt_intfid.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c
index fff74160..cb33f024 100644
--- a/accel-pppd/ppp/ipv6cp_opt_intfid.c
+++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <endian.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
@@ -25,9 +26,16 @@
static int conf_check_exists;
static int conf_intf_id = INTF_ID_FIXED;
-static uint64_t conf_intf_id_val = 1;
+/* Fixed intf-id values are stored in network byte order: the rest of
+ * the code (build_ip6_addr(), ifcfg.c, nd.c, ...) copies them into the
+ * low 8 bytes of the IPv6 address as-is, and parse_intfid() already
+ * produces network byte order. The old host-order defaults (1 and 2)
+ * therefore yielded ::100:0:0:0 / ::200:0:0:0 instead of ::1 / ::2 on
+ * little-endian hosts. Defaults are assigned in init() because
+ * htobe64() is not a constant expression on all libcs (e.g. musl). */
+static uint64_t conf_intf_id_val;
static int conf_peer_intf_id = INTF_ID_FIXED;
-static uint64_t conf_peer_intf_id_val = 2;
+static uint64_t conf_peer_intf_id_val;
static int conf_accept_peer_intf_id;
static struct ipv6cp_option_t *ipaddr_init(struct ppp_ipv6cp_t *ipv6cp);
@@ -354,6 +362,11 @@ static void load_config(void)
static void init()
{
+ /* network byte order, so the resulting addresses are ::1 and ::2
+ * regardless of host endianness */
+ conf_intf_id_val = htobe64(1);
+ conf_peer_intf_id_val = htobe64(2);
+
if (sock6_fd < 0)
return;