summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Fedoryshchenko <denys.f@collabora.com>2026-07-14 01:07:23 +0300
committerGitHub <noreply@github.com>2026-07-14 01:07:23 +0300
commit3ab711d7b2f48ce05825e568239a6f172e42f079 (patch)
tree93d73d7c4727dc4858a645302f69c230260b3dda
parentf4014a4a2c9e654646faeb81cd9ac5841b1c9b0f (diff)
parentefa4cea1beec1fa758ac94f350dfa7bdfa6d472f (diff)
downloadaccel-ppp-3ab711d7b2f48ce05825e568239a6f172e42f079.tar.gz
accel-ppp-3ab711d7b2f48ce05825e568239a6f172e42f079.zip
Merge pull request #337 from nuclearcat/fix-ipv6-ifid
Fix ipv6 ifid and UB shift
-rw-r--r--accel-pppd/ipdb.c5
-rw-r--r--accel-pppd/ppp/ipv6cp_opt_intfid.c17
2 files changed, 19 insertions, 3 deletions
diff --git a/accel-pppd/ipdb.c b/accel-pppd/ipdb.c
index dd8c61c9..8fc08063 100644
--- a/accel-pppd/ipdb.c
+++ b/accel-pppd/ipdb.c
@@ -83,7 +83,10 @@ void __export build_ip6_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct i
if (a->prefix_len <= 64)
*(uint64_t *)(addr->s6_addr + 8) = intf_id;
else
- *(uint64_t *)(addr->s6_addr + 8) |= intf_id & htobe64((1 << (128 - a->prefix_len)) - 1);
+ /* prefix_len 65..127 means a shift of up to 63 bits: a plain
+ * int literal 1 is undefined behavior for shifts >= 31, so the
+ * host bits mask must be built from a 64-bit constant */
+ *(uint64_t *)(addr->s6_addr + 8) |= intf_id & htobe64((UINT64_C(1) << (128 - a->prefix_len)) - 1);
}
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;