Date: Wed, 03 Jun 2026 12:47:04 +0000 From: Renato Botelho <garga@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: 5d154bfea96e - main - net-mgmt/iprange: Backport fix for 32-bit platforms Message-ID: <6a202248.256d0.5f955116@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by garga: URL: https://cgit.FreeBSD.org/ports/commit/?id=5d154bfea96e26773ce19e8aa7103c338d128424 commit 5d154bfea96e26773ce19e8aa7103c338d128424 Author: Renato Botelho <garga@FreeBSD.org> AuthorDate: 2026-06-03 12:42:56 +0000 Commit: Renato Botelho <garga@FreeBSD.org> CommitDate: 2026-06-03 12:46:59 +0000 net-mgmt/iprange: Backport fix for 32-bit platforms I've added it as a local patch instead of using PATCHFILES because upstream patch touches CMakeLists.txt, which is not present on release tarball for some unknown reason. Obtained from: upstream 268d7d8794f3f8a6c2d6f08dc4351e767990e683 Sponsored by: Rubicon Communications, LLC ("Netgate") --- net-mgmt/iprange/Makefile | 7 +- .../patch-268d7d8794f3f8a6c2d6f08dc4351e767990e683 | 1083 ++++++++++++++++++++ 2 files changed, 1087 insertions(+), 3 deletions(-) diff --git a/net-mgmt/iprange/Makefile b/net-mgmt/iprange/Makefile index c25b60bdf246..bd912c6e6489 100644 --- a/net-mgmt/iprange/Makefile +++ b/net-mgmt/iprange/Makefile @@ -1,5 +1,6 @@ PORTNAME= iprange PORTVERSION= 2.0.0 +PORTREVISION= 1 CATEGORIES= net-mgmt MASTER_SITES= https://github.com/firehol/iprange/releases/download/v${PORTVERSION}/ @@ -10,13 +11,13 @@ WWW= https://github.com/firehol/iprange LICENSE= GPLv2+ LICENSE_FILE= ${WRKSRC}/COPYING -USES= tar:xz - -IGNORE_i386= __uint128_t is not available on i386 and is required for mandatory IPv6 support +USES= autoreconf tar:xz GNU_CONFIGURE= yes GNU_CONFIGURE_MANPREFIX= ${PREFIX}/share +PATCH_STRIP= -p1 + PLIST_FILES= bin/iprange \ share/man/man1/iprange.1.gz diff --git a/net-mgmt/iprange/files/patch-268d7d8794f3f8a6c2d6f08dc4351e767990e683 b/net-mgmt/iprange/files/patch-268d7d8794f3f8a6c2d6f08dc4351e767990e683 new file mode 100644 index 000000000000..1006dfafebf6 --- /dev/null +++ b/net-mgmt/iprange/files/patch-268d7d8794f3f8a6c2d6f08dc4351e767990e683 @@ -0,0 +1,1083 @@ +From 268d7d8794f3f8a6c2d6f08dc4351e767990e683 Mon Sep 17 00:00:00 2001 +From: "R. Christian McDonald" <rcm@rcm.sh> +Date: Tue, 2 Jun 2026 11:57:11 -0400 +Subject: [PATCH] ipv6: support 32-bit platforms without __uint128_t + +IPv6 support (2.0.0) relied on the __uint128_t builtin, which i386 and +armv7 lack, so the build hard-errored there. + +Add src/uint128.h: on 64-bit it typedefs __uint128_t and inlines the bare +operators (unchanged codegen); on 32-bit it falls back to a portable +{hi, lo} struct with explicit arithmetic. +--- + Makefile.am | 1 + + configure.ac | 5 +- + src/iprange6.h | 53 +++++----- + src/iprange6_main.c | 24 ++--- + src/ipset6.c | 4 +- + src/ipset6.h | 20 ++-- + src/ipset6_binary.c | 36 +++---- + src/ipset6_common.c | 8 +- + src/ipset6_diff.c | 24 ++--- + src/ipset6_exclude.c | 16 +-- + src/ipset6_load.c | 12 +-- + src/ipset6_optimize.c | 16 +-- + src/ipset6_print.c | 22 ++-- + src/uint128.h | 230 ++++++++++++++++++++++++++++++++++++++++++ + 15 files changed, 356 insertions(+), 121 deletions(-) + create mode 100644 src/uint128.h + +diff --git a/Makefile.am b/Makefile.am +index 64353db..fa9043f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -34,6 +34,7 @@ iprange_SOURCES = \ + src/iprange.c \ + src/iprange.h \ + src/iprange6.h \ ++ src/uint128.h \ + src/iprange6_main.c \ + src/ipset.c \ + src/ipset.h \ +diff --git a/configure.ac b/configure.ac +index 0015482..992b67b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -73,8 +73,9 @@ CC="${PTHREAD_CC}" + AC_TYPE_UINT32_T + AC_C_INLINE + +-AC_CHECK_TYPE([__uint128_t], [], +- [AC_MSG_ERROR([Your compiler does not support __uint128_t, required for IPv6 support.])], ++AC_CHECK_TYPE([__uint128_t], ++ [AC_MSG_NOTICE([Native __uint128_t detected — using hardware 128-bit integers for IPv6])], ++ [AC_MSG_NOTICE([__uint128_t not available — using portable 128-bit arithmetic for IPv6])], + [/* no includes needed */]) + + test "${with_compare_with_common}" = "yes" && AC_DEFINE([COMPARE_WITH_COMMON], [1], [compare settings]) +diff --git a/src/iprange6.h b/src/iprange6.h +index 2bf0871..448f28c 100644 +--- a/src/iprange6.h ++++ b/src/iprange6.h +@@ -2,10 +2,11 @@ + #define IPRANGE_IPRANGE6_H + + #include "iprange.h" ++#include "uint128.h" + #include <string.h> + + /* IPv6 address type: 128-bit unsigned integer in host byte order */ +-typedef __uint128_t ipv6_addr_t; ++typedef uint128_t ipv6_addr_t; + + /* IPv6 network address type: one field for the net address, one for broadcast */ + typedef struct network_addr6 { +@@ -14,11 +15,11 @@ typedef struct network_addr6 { + } network_addr6_t; + + /* Maximum IPv6 address */ +-#define IPV6_ADDR_MAX ((ipv6_addr_t)((__uint128_t)(-1))) ++#define IPV6_ADDR_MAX U128_MAX + + /* IPv4-mapped IPv6 prefix: ::ffff:0:0/96 */ +-#define IPV6_MAPPED_PREFIX ((ipv6_addr_t)0xFFFF00000000ULL) +-#define IPV6_MAPPED_MASK ((ipv6_addr_t)0xFFFFFFFFULL) ++#define IPV6_MAPPED_PREFIX (u128_from_u64(0xFFFF00000000ULL)) ++#define IPV6_MAPPED_MASK (u128_from_u64(0xFFFFFFFFULL)) + + #define IP6STR_MAX_LEN 46 + +@@ -28,18 +29,18 @@ typedef struct network_addr6 { + /*----------------------------------------------------------------------*/ + + static inline ipv6_addr_t in6_addr_to_ipv6(const struct in6_addr *in6) { +- ipv6_addr_t result = 0; ++ ipv6_addr_t result = U128_ZERO; + int i; + for(i = 0; i < 16; i++) +- result = (result << 8) | in6->s6_addr[i]; ++ result = u128_or(u128_shl(result, 8), u128_from_u64(in6->s6_addr[i])); + return result; + } + + static inline void ipv6_to_in6_addr(ipv6_addr_t addr, struct in6_addr *in6) { + int i; + for(i = 15; i >= 0; i--) { +- in6->s6_addr[i] = (uint8_t)(addr & 0xFF); +- addr >>= 8; ++ in6->s6_addr[i] = (uint8_t)u128_lo64(addr); ++ addr = u128_shr(addr, 8); + } + } + +@@ -48,24 +49,24 @@ static inline void ipv6_to_in6_addr(ipv6_addr_t addr, struct in6_addr *in6) { + /*----------------------------------------------*/ + static inline ipv6_addr_t netmask6(int prefix) { + if(prefix == 0) +- return (ipv6_addr_t)0; ++ return U128_ZERO; + if(prefix >= 128) + return IPV6_ADDR_MAX; +- return IPV6_ADDR_MAX << (128 - prefix); ++ return u128_shl(U128_MAX, 128 - prefix); + } + + /*----------------------------------------------------*/ + /* Compute broadcast address given address and prefix */ + /*----------------------------------------------------*/ + static inline ipv6_addr_t broadcast6(ipv6_addr_t addr, int prefix) { +- return addr | ~netmask6(prefix); ++ return u128_or(addr, u128_not(netmask6(prefix))); + } + + /*--------------------------------------------------*/ + /* Compute network address given address and prefix */ + /*--------------------------------------------------*/ + static inline ipv6_addr_t network6(ipv6_addr_t addr, int prefix) { +- return addr & netmask6(prefix); ++ return u128_and(addr, netmask6(prefix)); + } + + /*------------------------------------------------------------------*/ +@@ -73,9 +74,9 @@ static inline ipv6_addr_t network6(ipv6_addr_t addr, int prefix) { + /*------------------------------------------------------------------*/ + static inline ipv6_addr_t set_bit6(ipv6_addr_t addr, int bitno, int val) { + if(val) +- return addr | ((__uint128_t)1 << (128 - bitno)); ++ return u128_or(addr, u128_shl(U128_ONE, 128 - bitno)); + else +- return addr & ~((__uint128_t)1 << (128 - bitno)); ++ return u128_and(addr, u128_not(u128_shl(U128_ONE, 128 - bitno))); + } + + /*-----------------------------------------------------------*/ +@@ -121,8 +122,8 @@ static inline network_addr6_t str2netaddr6(char *ipstr, int *err) { + || parsed_prefix < 0 || parsed_prefix > 128)) { + if(err) (*err)++; + fprintf(stderr, "%s: Invalid IPv6 prefix /%s\n", PROG, prefixstr); +- netaddr.addr = 0; +- netaddr.broadcast = 0; ++ netaddr.addr = U128_ZERO; ++ netaddr.broadcast = U128_ZERO; + return netaddr; + } + prefix = (int)parsed_prefix; +@@ -131,8 +132,8 @@ static inline network_addr6_t str2netaddr6(char *ipstr, int *err) { + if(!str_to_ipv6(ipstr, &addr)) { + if(err) (*err)++; + fprintf(stderr, "%s: Invalid IPv6 address %s\n", PROG, ipstr); +- netaddr.addr = 0; +- netaddr.broadcast = 0; ++ netaddr.addr = U128_ZERO; ++ netaddr.broadcast = U128_ZERO; + return netaddr; + } + +@@ -149,21 +150,21 @@ static inline network_addr6_t str2netaddr6(char *ipstr, int *err) { + /* Check if an IPv6 address is IPv4-mapped (::ffff:x.x.x.x) */ + /*-----------------------------------------------------------*/ + static inline int is_ipv4_mapped(ipv6_addr_t addr) { +- return (addr >> 32) == 0xFFFF; ++ return u128_eq(u128_shr(addr, 32), u128_from_u64(0xFFFF)); + } + + /*-----------------------------------------------------------*/ + /* Convert IPv4 to IPv4-mapped IPv6 */ + /*-----------------------------------------------------------*/ + static inline ipv6_addr_t ipv4_to_mapped6(in_addr_t ipv4) { +- return IPV6_MAPPED_PREFIX | (ipv6_addr_t)ipv4; ++ return u128_or(IPV6_MAPPED_PREFIX, u128_from_u64(ipv4)); + } + + /*-----------------------------------------------------------*/ + /* Extract IPv4 from IPv4-mapped IPv6 */ + /*-----------------------------------------------------------*/ + static inline in_addr_t mapped6_to_ipv4(ipv6_addr_t addr) { +- return (in_addr_t)(addr & IPV6_MAPPED_MASK); ++ return (in_addr_t)u128_lo64(u128_and(addr, IPV6_MAPPED_MASK)); + } + + /*-----------------------------------------------------------*/ +@@ -171,18 +172,18 @@ static inline in_addr_t mapped6_to_ipv4(ipv6_addr_t addr) { + /* Returns pointer to start of number within buf */ + /* buf must be at least 40 bytes */ + /*-----------------------------------------------------------*/ +-static inline char *u128_to_dec(char *buf, size_t buflen, __uint128_t val) { ++static inline char *u128_to_dec(char *buf, size_t buflen, uint128_t val) { + char *p = buf + buflen - 1; + *p = '\0'; + +- if(val == 0) { ++ if(u128_is_zero(val)) { + *(--p) = '0'; + return p; + } + +- while(val > 0) { +- *(--p) = '0' + (char)(val % 10); +- val /= 10; ++ while(!u128_is_zero(val)) { ++ *(--p) = '0' + (char)u128_mod10(val); ++ val = u128_div10(val); + } + return p; + } +diff --git a/src/iprange6_main.c b/src/iprange6_main.c +index 0484406..07c9e8d 100644 +--- a/src/iprange6_main.c ++++ b/src/iprange6_main.c +@@ -42,9 +42,9 @@ static void free_pathnames6(char **files, size_t entries) + free(files); + } + +-static __uint128_t ipset6_report_unique_ips(ipset6 *ips, size_t *entries) ++static uint128_t ipset6_report_unique_ips(ipset6 *ips, size_t *entries) + { +- __uint128_t unique_ips = ipset6_unique_ips(ips); ++ uint128_t unique_ips = ipset6_unique_ips(ips); + if(entries) *entries = ips->entries; + return unique_ips; + } +@@ -337,7 +337,7 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + if(mode == MODE_COMBINE) + ipset6_print(root, print); + else if(mode == MODE_COUNT_UNIQUE_MERGED) { +- __uint128_t unique_ips = ipset6_report_unique_ips(root, NULL); ++ uint128_t unique_ips = ipset6_report_unique_ips(root, NULL); + if(unlikely(header)) printf("entries,unique_ips\n"); + printf("%zu,%s\n", root->entries, u128_to_dec(u128buf, sizeof(u128buf), unique_ips)); + } +@@ -381,7 +381,7 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + ips6 = ipset6_diff(root, second); + if(!quiet) ipset6_print(ips6, print); + +- if(ips6->unique_ips) ret = 1; ++ if(!u128_is_zero(ips6->unique_ips)) ret = 1; + else ret = 0; + } + else if(mode == MODE_COMPARE) { +@@ -400,8 +400,8 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + for(ips2 = ips6; ips2; ips2 = ips2->next) { + ipset6 *comips; + size_t entries1, entries2; +- __uint128_t unique1 = ipset6_report_unique_ips(ips6, &entries1); +- __uint128_t unique2 = ipset6_report_unique_ips(ips2, &entries2); ++ uint128_t unique1 = ipset6_report_unique_ips(ips6, &entries1); ++ uint128_t unique2 = ipset6_report_unique_ips(ips2, &entries2); + + if(ips6 == ips2) continue; + +@@ -416,7 +416,7 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + u128_to_dec(u128buf, sizeof(u128buf), unique1)); + printf("%s,", u128_to_dec(u128buf, sizeof(u128buf), unique2)); + printf("%s,", u128_to_dec(u128buf, sizeof(u128buf), comips->unique_ips)); +- printf("%s\n", u128_to_dec(u128buf, sizeof(u128buf), unique1 + unique2 - comips->unique_ips)); ++ printf("%s\n", u128_to_dec(u128buf, sizeof(u128buf), u128_sub(u128_add(unique1, unique2), comips->unique_ips))); + ipset6_free(comips); + } + } +@@ -437,8 +437,8 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + for(ips6 = root; ips6; ips6 = ips6->next) { + for(ips2 = second; ips2; ips2 = ips2->next) { + size_t entries1, entries2; +- __uint128_t unique1 = ipset6_report_unique_ips(ips6, &entries1); +- __uint128_t unique2 = ipset6_report_unique_ips(ips2, &entries2); ++ uint128_t unique1 = ipset6_report_unique_ips(ips6, &entries1); ++ uint128_t unique2 = ipset6_report_unique_ips(ips2, &entries2); + + ipset6 *combined = ipset6_combine(ips6, ips2); + if(!combined) { +@@ -451,7 +451,7 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + u128_to_dec(u128buf, sizeof(u128buf), unique1)); + printf("%s,", u128_to_dec(u128buf, sizeof(u128buf), unique2)); + printf("%s,", u128_to_dec(u128buf, sizeof(u128buf), combined->unique_ips)); +- printf("%s\n", u128_to_dec(u128buf, sizeof(u128buf), unique1 + unique2 - combined->unique_ips)); ++ printf("%s\n", u128_to_dec(u128buf, sizeof(u128buf), u128_sub(u128_add(unique1, unique2), combined->unique_ips))); + ipset6_free(combined); + } + } +@@ -468,7 +468,7 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + + for(ips6 = root; ips6; ips6 = ips6->next) { + size_t entries; +- __uint128_t unique_ips = ipset6_report_unique_ips(ips6, &entries); ++ uint128_t unique_ips = ipset6_report_unique_ips(ips6, &entries); + + if(ips6 == first) continue; + +@@ -481,7 +481,7 @@ int iprange6_run(int argc, char **argv, int mode, IPSET_PRINT_CMD print, + ipset6_optimize(comips); + printf("%s,%zu,%s,", ips6->filename, entries, + u128_to_dec(u128buf, sizeof(u128buf), unique_ips)); +- printf("%s\n", u128_to_dec(u128buf, sizeof(u128buf), unique_ips + first->unique_ips - comips->unique_ips)); ++ printf("%s\n", u128_to_dec(u128buf, sizeof(u128buf), u128_sub(u128_add(unique_ips, first->unique_ips), comips->unique_ips))); + ipset6_free(comips); + } + } +diff --git a/src/ipset6.c b/src/ipset6.c +index a34833d..79aa360 100644 +--- a/src/ipset6.c ++++ b/src/ipset6.c +@@ -24,7 +24,7 @@ ipset6 *ipset6_create(const char *filename, size_t entries) { + ips->lines = 0; + ips->entries = 0; + ips->entries_max = entries; +- ips->unique_ips = 0; ++ ips->unique_ips = U128_ZERO; + ips->next = NULL; + ips->prev = NULL; + ips->flags = 0; +@@ -87,7 +87,7 @@ void ipset6_grow_internal(ipset6 *ips, size_t free_entries_needed) { + } + } + +-inline __uint128_t ipset6_unique_ips(ipset6 *ips) { ++inline uint128_t ipset6_unique_ips(ipset6 *ips) { + if(unlikely(!(ips->flags & IPSET_FLAG_OPTIMIZED))) + ipset6_optimize(ips); + +diff --git a/src/ipset6.h b/src/ipset6.h +index aa9c9c5..c4cd11e 100644 +--- a/src/ipset6.h ++++ b/src/ipset6.h +@@ -9,7 +9,7 @@ typedef struct ipset6 { + size_t lines; + size_t entries; + size_t entries_max; +- __uint128_t unique_ips; ++ uint128_t unique_ips; + + uint32_t flags; + +@@ -25,7 +25,7 @@ extern void ipset6_free_all(ipset6 *ips); + + extern size_t prefix6_counters[129]; + +-extern __uint128_t ipset6_unique_ips(ipset6 *ips); ++extern uint128_t ipset6_unique_ips(ipset6 *ips); + + static inline int ipset6_entries_allocation_overflows(size_t entries) { + return (entries > (SIZE_MAX / sizeof(network_addr6_t))); +@@ -56,26 +56,26 @@ static inline void ipset6_added_entry(ipset6 *ips) { + + ips->lines++; + +- /* overflow-safe unique_ips: 2^128 doesn't fit in __uint128_t, saturate at max */ +- if(lo == 0 && hi == IPV6_ADDR_MAX) ++ /* overflow-safe unique_ips: 2^128 doesn't fit in uint128_t, saturate at max */ ++ if(u128_is_zero(lo) && u128_eq(hi, IPV6_ADDR_MAX)) + ips->unique_ips = IPV6_ADDR_MAX; + else { +- __uint128_t size = hi - lo + 1; +- if(ips->unique_ips > IPV6_ADDR_MAX - size) ++ uint128_t size = u128_add(u128_sub(hi, lo), U128_ONE); ++ if(u128_gt(ips->unique_ips, u128_sub(IPV6_ADDR_MAX, size))) + ips->unique_ips = IPV6_ADDR_MAX; + else +- ips->unique_ips += size; ++ ips->unique_ips = u128_add(ips->unique_ips, size); + } + + if(likely(ips->flags & IPSET_FLAG_OPTIMIZED && entries > 0)) { + /* overflow-safe adjacency: broadcast + 1 wraps at IPV6_ADDR_MAX */ +- if(unlikely(ips->netaddrs[entries - 1].broadcast != IPV6_ADDR_MAX && +- lo == (ips->netaddrs[entries - 1].broadcast + 1))) { ++ if(unlikely(!u128_eq(ips->netaddrs[entries - 1].broadcast, IPV6_ADDR_MAX) && ++ u128_eq(lo, u128_inc(ips->netaddrs[entries - 1].broadcast)))) { + ips->netaddrs[entries - 1].broadcast = hi; + return; + } + +- if(likely(lo > ips->netaddrs[entries - 1].broadcast)) { ++ if(likely(u128_gt(lo, ips->netaddrs[entries - 1].broadcast))) { + ips->entries++; + return; + } +diff --git a/src/ipset6_binary.c b/src/ipset6_binary.c +index bc6caa9..c23a3e2 100644 +--- a/src/ipset6_binary.c ++++ b/src/ipset6_binary.c +@@ -10,15 +10,15 @@ static void binary6_write_failed(void) { + exit(1); + } + +-static int binary6_validate_payload(ipset6 *ips, int header_optimized, size_t entries, __uint128_t expected_unique_ips, int *payload_is_optimized) ++static int binary6_validate_payload(ipset6 *ips, int header_optimized, size_t entries, uint128_t expected_unique_ips, int *payload_is_optimized) + { + size_t i; +- __uint128_t actual_unique_ips = 0; ++ uint128_t actual_unique_ips = U128_ZERO; + + *payload_is_optimized = 1; + + if(!entries) { +- if(unlikely(expected_unique_ips != 0)) { ++ if(unlikely(!u128_is_zero(expected_unique_ips))) { + fprintf(stderr, "%s: %s: unique IPs do not match the binary payload\n", PROG, ips->filename); + return 1; + } +@@ -26,7 +26,7 @@ static int binary6_validate_payload(ipset6 *ips, int header_optimized, size_t en + } + + for(i = 0; i < entries; i++) { +- if(unlikely(ips->netaddrs[ips->entries + i].addr > ips->netaddrs[ips->entries + i].broadcast)) { ++ if(unlikely(u128_gt(ips->netaddrs[ips->entries + i].addr, ips->netaddrs[ips->entries + i].broadcast))) { + fprintf(stderr, "%s: %s: invalid binary record %zu has addr > broadcast\n", PROG, ips->filename, i + 1); + return 1; + } +@@ -36,9 +36,9 @@ static int binary6_validate_payload(ipset6 *ips, int header_optimized, size_t en + network_addr6_t *prev = &ips->netaddrs[ips->entries + i - 1]; + network_addr6_t *curr = &ips->netaddrs[ips->entries + i]; + +- if(curr->addr < prev->addr +- || curr->addr <= prev->broadcast +- || (prev->broadcast != IPV6_ADDR_MAX && curr->addr == (prev->broadcast + 1))) { ++ if(u128_lt(curr->addr, prev->addr) ++ || u128_le(curr->addr, prev->broadcast) ++ || (!u128_eq(prev->broadcast, IPV6_ADDR_MAX) && u128_eq(curr->addr, u128_inc(prev->broadcast)))) { + *payload_is_optimized = 0; + break; + } +@@ -46,8 +46,8 @@ static int binary6_validate_payload(ipset6 *ips, int header_optimized, size_t en + + if(*payload_is_optimized) { + for(i = 0; i < entries; i++) { +- __uint128_t size = ips->netaddrs[ips->entries + i].broadcast - ips->netaddrs[ips->entries + i].addr + 1; +- actual_unique_ips += size; ++ uint128_t size = u128_add(u128_sub(ips->netaddrs[ips->entries + i].broadcast, ips->netaddrs[ips->entries + i].addr), U128_ONE); ++ actual_unique_ips = u128_add(actual_unique_ips, size); + } + } + else { +@@ -57,7 +57,7 @@ static int binary6_validate_payload(ipset6 *ips, int header_optimized, size_t en + actual_unique_ips = expected_unique_ips; + } + +- if(unlikely(expected_unique_ips != actual_unique_ips)) { ++ if(unlikely(!u128_eq(expected_unique_ips, actual_unique_ips))) { + fprintf(stderr, "%s: %s: unique IPs do not match the binary payload\n", PROG, ips->filename); + return 1; + } +@@ -91,9 +91,9 @@ static int parse_binary6_size_field(ipset6 *ips, const char *field, const char * + return 0; + } + +-static int parse_binary6_u128_field(ipset6 *ips, const char *field, const char *value, __uint128_t *parsed_value) ++static int parse_binary6_u128_field(ipset6 *ips, const char *field, const char *value, uint128_t *parsed_value) + { +- __uint128_t result = 0; ++ uint128_t result = U128_ZERO; + const char *s = value; + + if(!s || *s < '0' || *s > '9') { +@@ -102,9 +102,9 @@ static int parse_binary6_u128_field(ipset6 *ips, const char *field, const char * + } + + while(*s >= '0' && *s <= '9') { +- __uint128_t prev = result; +- result = result * 10 + (*s - '0'); +- if(unlikely(result < prev)) { ++ uint128_t prev = result; ++ result = u128_add(u128_mul_u64(result, 10), u128_from_u64(*s - '0')); ++ if(unlikely(u128_lt(result, prev))) { + fprintf(stderr, "%s: %s: %s value overflow\n", PROG, ips->filename, field); + return 1; + } +@@ -123,7 +123,7 @@ static int parse_binary6_u128_field(ipset6 *ips, const char *field, const char * + int ipset6_load_binary_v20(FILE *fp, ipset6 *ips, int first_line_missing) { + char buffer[MAX_LINE + 1], *s; + size_t entries, bytes, lines, expected_bytes, record_size; +- __uint128_t unique_ips; ++ uint128_t unique_ips; + uint32_t endian; + size_t loaded; + int header_optimized = 0; +@@ -230,7 +230,7 @@ int ipset6_load_binary_v20(FILE *fp, ipset6 *ips, int first_line_missing) { + return 1; + } + +- if(unique_ips < entries && unique_ips != 0) { ++ if(u128_lt(unique_ips, u128_from_u64(entries)) && !u128_is_zero(unique_ips)) { + fprintf(stderr, "%s: %s: unique IPs cannot be less than entries (%zu)\n", PROG, ips->filename, entries); + return 1; + } +@@ -263,7 +263,7 @@ int ipset6_load_binary_v20(FILE *fp, ipset6 *ips, int first_line_missing) { + + ips->entries += loaded; + ips->lines += lines; +- ips->unique_ips += unique_ips; ++ ips->unique_ips = u128_add(ips->unique_ips, unique_ips); + ips->flags &= ~IPSET_FLAG_OPTIMIZED; + if(header_optimized && payload_is_optimized) ips->flags |= IPSET_FLAG_OPTIMIZED; + +diff --git a/src/ipset6_common.c b/src/ipset6_common.c +index f284144..d84cf1a 100644 +--- a/src/ipset6_common.c ++++ b/src/ipset6_common.c +@@ -33,7 +33,7 @@ inline ipset6 *ipset6_common(ipset6 *ips1, ipset6 *ips2) { + hi2 = ips2->netaddrs[0].broadcast; + + while(i1 < n1 && i2 < n2) { +- if(lo1 > hi2) { ++ if(u128_gt(lo1, hi2)) { + i2++; + if(i2 < n2) { + lo2 = ips2->netaddrs[i2].addr; +@@ -42,7 +42,7 @@ inline ipset6 *ipset6_common(ipset6 *ips1, ipset6 *ips2) { + continue; + } + +- if(lo2 > hi1) { ++ if(u128_gt(lo2, hi1)) { + i1++; + if(i1 < n1) { + lo1 = ips1->netaddrs[i1].addr; +@@ -51,9 +51,9 @@ inline ipset6 *ipset6_common(ipset6 *ips1, ipset6 *ips2) { + continue; + } + +- lo = (lo1 > lo2) ? lo1 : lo2; ++ lo = u128_gt(lo1, lo2) ? lo1 : lo2; + +- if(hi1 < hi2) { ++ if(u128_lt(hi1, hi2)) { + hi = hi1; + i1++; + if(i1 < n1) { +diff --git a/src/ipset6_diff.c b/src/ipset6_diff.c +index f629ae3..7f07d9c 100644 +--- a/src/ipset6_diff.c ++++ b/src/ipset6_diff.c +@@ -53,7 +53,7 @@ inline ipset6 *ipset6_diff(ipset6 *ips1, ipset6 *ips2) { + hi2 = ips2->netaddrs[0].broadcast; + + while(i1 < n1 && i2 < n2) { +- if(lo1 > hi2) { ++ if(u128_gt(lo1, hi2)) { + ipset6_add_ip_range(ips, lo2, hi2); + i2++; + if(i2 < n2) { +@@ -62,7 +62,7 @@ inline ipset6 *ipset6_diff(ipset6 *ips1, ipset6 *ips2) { + } + continue; + } +- if(lo2 > hi1) { ++ if(u128_gt(lo2, hi1)) { + ipset6_add_ip_range(ips, lo1, hi1); + i1++; + if(i1 < n1) { +@@ -72,14 +72,14 @@ inline ipset6 *ipset6_diff(ipset6 *ips1, ipset6 *ips2) { + continue; + } + +- if(lo1 > lo2) +- ipset6_add_ip_range(ips, lo2, lo1 - 1); +- else if(lo2 > lo1) +- ipset6_add_ip_range(ips, lo1, lo2 - 1); ++ if(u128_gt(lo1, lo2)) ++ ipset6_add_ip_range(ips, lo2, u128_dec(lo1)); ++ else if(u128_gt(lo2, lo1)) ++ ipset6_add_ip_range(ips, lo1, u128_dec(lo2)); + +- if(hi1 > hi2) { +- if(hi2 == IPV6_ADDR_MAX) { i1++; i2++; } +- else { lo1 = hi2 + 1; i2++; } ++ if(u128_gt(hi1, hi2)) { ++ if(u128_eq(hi2, IPV6_ADDR_MAX)) { i1++; i2++; } ++ else { lo1 = u128_inc(hi2); i2++; } + if(i2 < n2) { + lo2 = ips2->netaddrs[i2].addr; + hi2 = ips2->netaddrs[i2].broadcast; +@@ -90,9 +90,9 @@ inline ipset6 *ipset6_diff(ipset6 *ips1, ipset6 *ips2) { + } + continue; + } +- else if(hi2 > hi1) { +- if(hi1 == IPV6_ADDR_MAX) { i1++; i2++; } +- else { lo2 = hi1 + 1; i1++; } ++ else if(u128_gt(hi2, hi1)) { ++ if(u128_eq(hi1, IPV6_ADDR_MAX)) { i1++; i2++; } ++ else { lo2 = u128_inc(hi1); i1++; } + if(i1 < n1) { + lo1 = ips1->netaddrs[i1].addr; + hi1 = ips1->netaddrs[i1].broadcast; +diff --git a/src/ipset6_exclude.c b/src/ipset6_exclude.c +index c7bb969..75dbaaf 100644 +--- a/src/ipset6_exclude.c ++++ b/src/ipset6_exclude.c +@@ -43,7 +43,7 @@ inline ipset6 *ipset6_exclude(ipset6 *ips1, ipset6 *ips2) { + hi2 = ips2->netaddrs[0].broadcast; + + while(i1 < n1 && i2 < n2) { +- if(lo1 > hi2) { ++ if(u128_gt(lo1, hi2)) { + i2++; + if(i2 < n2) { + lo2 = ips2->netaddrs[i2].addr; +@@ -52,7 +52,7 @@ inline ipset6 *ipset6_exclude(ipset6 *ips1, ipset6 *ips2) { + continue; + } + +- if(lo2 > hi1) { ++ if(u128_gt(lo2, hi1)) { + ipset6_add_ip_range(ips, lo1, hi1); + i1++; + if(i1 < n1) { +@@ -62,12 +62,12 @@ inline ipset6 *ipset6_exclude(ipset6 *ips1, ipset6 *ips2) { + continue; + } + +- if(lo1 < lo2) { +- ipset6_add_ip_range(ips, lo1, lo2 - 1); ++ if(u128_lt(lo1, lo2)) { ++ ipset6_add_ip_range(ips, lo1, u128_dec(lo2)); + lo1 = lo2; + } + +- if(hi1 == hi2) { ++ if(u128_eq(hi1, hi2)) { + i1++; + if(i1 < n1) { + lo1 = ips1->netaddrs[i1].addr; +@@ -79,7 +79,7 @@ inline ipset6 *ipset6_exclude(ipset6 *ips1, ipset6 *ips2) { + hi2 = ips2->netaddrs[i2].broadcast; + } + } +- else if(hi1 < hi2) { ++ else if(u128_lt(hi1, hi2)) { + i1++; + if(i1 < n1) { + lo1 = ips1->netaddrs[i1].addr; +@@ -89,7 +89,7 @@ inline ipset6 *ipset6_exclude(ipset6 *ips1, ipset6 *ips2) { + else { + /* hi2 + 1 would overflow if hi2 == IPV6_ADDR_MAX, but that means + * ips2 covers everything from lo1..max, so nothing remains in ips1 */ +- if(hi2 == IPV6_ADDR_MAX) { ++ if(u128_eq(hi2, IPV6_ADDR_MAX)) { + i1++; + if(i1 < n1) { + lo1 = ips1->netaddrs[i1].addr; +@@ -97,7 +97,7 @@ inline ipset6 *ipset6_exclude(ipset6 *ips1, ipset6 *ips2) { + } + } + else { +- lo1 = hi2 + 1; ++ lo1 = u128_inc(hi2); + } + i2++; + if(i2 < n2) { +diff --git a/src/ipset6_load.c b/src/ipset6_load.c +index 6295ef2..b64ca9f 100644 +--- a/src/ipset6_load.c ++++ b/src/ipset6_load.c +@@ -152,8 +152,8 @@ static network_addr6_t parse_address6(char *ipstr, int *err) { + else if(addr_class == 4) { + network_addr_t v4 = str2netaddr(ipstr, err); + if(*err) { +- netaddr.addr = 0; +- netaddr.broadcast = 0; ++ netaddr.addr = U128_ZERO; ++ netaddr.broadcast = U128_ZERO; + return netaddr; + } + +@@ -164,8 +164,8 @@ static network_addr6_t parse_address6(char *ipstr, int *err) { + + if(err) (*err)++; + fprintf(stderr, "%s: Cannot parse address: %s\n", PROG, ipstr); +- netaddr.addr = 0; +- netaddr.broadcast = 0; ++ netaddr.addr = U128_ZERO; ++ netaddr.broadcast = U128_ZERO; + return netaddr; + } + +@@ -275,8 +275,8 @@ ipset6 *ipset6_load(const char *filename) { + continue; + } + +- ipv6_addr_t lo = (net1.addr < net2.addr) ? net1.addr : net2.addr; +- ipv6_addr_t hi = (net1.broadcast > net2.broadcast) ? net1.broadcast : net2.broadcast; ++ ipv6_addr_t lo = u128_lt(net1.addr, net2.addr) ? net1.addr : net2.addr; ++ ipv6_addr_t hi = u128_gt(net1.broadcast, net2.broadcast) ? net1.broadcast : net2.broadcast; + ipset6_add_ip_range(ips, lo, hi); + } + break; +diff --git a/src/ipset6_optimize.c b/src/ipset6_optimize.c +index f11a7d4..d0c1734 100644 +--- a/src/ipset6_optimize.c ++++ b/src/ipset6_optimize.c +@@ -6,10 +6,10 @@ static int compar_netaddr6(const void *p1, const void *p2) { + const network_addr6_t *na1 = (const network_addr6_t *)p1; + const network_addr6_t *na2 = (const network_addr6_t *)p2; + +- if(na1->addr < na2->addr) return -1; +- if(na1->addr > na2->addr) return 1; +- if(na1->broadcast > na2->broadcast) return -1; +- if(na1->broadcast < na2->broadcast) return 1; ++ if(u128_lt(na1->addr, na2->addr)) return -1; ++ if(u128_gt(na1->addr, na2->addr)) return 1; ++ if(u128_gt(na1->broadcast, na2->broadcast)) return -1; ++ if(u128_lt(na1->broadcast, na2->broadcast)) return 1; + return 0; + } + +@@ -25,7 +25,7 @@ inline void ipset6_optimize(ipset6 *ips) { + + if(unlikely(n == 0)) { + ips->flags |= IPSET_FLAG_OPTIMIZED; +- ips->unique_ips = 0; ++ ips->unique_ips = U128_ZERO; + return; + } + +@@ -39,17 +39,17 @@ inline void ipset6_optimize(ipset6 *ips) { + + ips->netaddrs = naddrs; + ips->entries = 0; +- ips->unique_ips = 0; ++ ips->unique_ips = U128_ZERO; + ips->lines = 0; + + lo = oaddrs[0].addr; + hi = oaddrs[0].broadcast; + for(i = 1; i < n; i++) { +- if(oaddrs[i].broadcast <= hi) ++ if(u128_le(oaddrs[i].broadcast, hi)) + continue; + + /* overflow-safe adjacency check: hi + 1 would overflow if hi == max */ +- if(oaddrs[i].addr <= hi || (hi != IPV6_ADDR_MAX && oaddrs[i].addr == hi + 1)) { ++ if(u128_le(oaddrs[i].addr, hi) || (!u128_eq(hi, IPV6_ADDR_MAX) && u128_eq(oaddrs[i].addr, u128_inc(hi)))) { + hi = oaddrs[i].broadcast; + continue; + } +diff --git a/src/ipset6_print.c b/src/ipset6_print.c +index 32794b0..0dafe25 100644 +--- a/src/ipset6_print.c ++++ b/src/ipset6_print.c +@@ -41,7 +41,7 @@ inline void print_addr6(ipv6_addr_t addr, int prefix) { + inline void print_addr6_range(ipv6_addr_t lo, ipv6_addr_t hi) { + char buf[IP6STR_MAX_LEN + 1]; + +- if(unlikely(lo > hi)) { ++ if(unlikely(u128_gt(lo, hi))) { + ipv6_addr_t t = hi; + fprintf(stderr, "%s: WARNING: invalid range reversed start=%s", PROG, ip6str_r(buf, lo)); + fprintf(stderr, " end=%s\n", ip6str_r(buf, hi)); +@@ -49,7 +49,7 @@ inline void print_addr6_range(ipv6_addr_t lo, ipv6_addr_t hi) { + lo = t; + } + +- if(lo == hi) { ++ if(u128_eq(lo, hi)) { + printf("%s%s-", print_prefix_ips, ip6str_r(buf, lo)); + printf("%s%s\n", ip6str_r(buf, hi), print_suffix_ips); + } +@@ -72,7 +72,7 @@ inline void print_addr6_single(ipv6_addr_t x) { + inline int split_range6(ipv6_addr_t addr, int prefix, ipv6_addr_t lo, ipv6_addr_t hi, void (*print)(ipv6_addr_t, int)) { + ipv6_addr_t bc, lower_half, upper_half; + +- if(unlikely(lo > hi)) { ++ if(unlikely(u128_gt(lo, hi))) { + ipv6_addr_t t = hi; + char buf[IP6STR_MAX_LEN + 1]; + fprintf(stderr, "%s: WARNING: invalid range reversed start=%s", PROG, ip6str_r(buf, lo)); +@@ -88,13 +88,13 @@ inline int split_range6(ipv6_addr_t addr, int prefix, ipv6_addr_t lo, ipv6_addr_ + + bc = broadcast6(addr, prefix); + +- if(unlikely(lo < addr || hi > bc)) { ++ if(unlikely(u128_lt(lo, addr) || u128_gt(hi, bc))) { + char buf[IP6STR_MAX_LEN + 1]; + fprintf(stderr, "%s: Out of range limits for IPv6 network %s/%d\n", PROG, ip6str_r(buf, addr), prefix); + return 0; + } + +- if(lo == addr && hi == bc && prefix6_enabled[prefix]) { ++ if(u128_eq(lo, addr) && u128_eq(hi, bc) && prefix6_enabled[prefix]) { + print(addr, prefix); + return 1; + } +@@ -103,9 +103,9 @@ inline int split_range6(ipv6_addr_t addr, int prefix, ipv6_addr_t lo, ipv6_addr_ + lower_half = addr; + upper_half = set_bit6(addr, prefix, 1); + +- if(hi < upper_half) ++ if(u128_lt(hi, upper_half)) + return split_range6(lower_half, prefix, lo, hi, print); +- else if(lo >= upper_half) ++ else if(u128_ge(lo, upper_half)) + return split_range6(upper_half, prefix, lo, hi, print); + else + return ( +@@ -136,7 +136,7 @@ void ipset6_print(ipset6 *ips, IPSET_PRINT_CMD print) { + + n = ips->entries; + for(i = 0; i < n; i++) +- total += split_range6((__uint128_t)0, 0, ips->netaddrs[i].addr, ips->netaddrs[i].broadcast, print_addr6); ++ total += split_range6(U128_ZERO, 0, ips->netaddrs[i].addr, ips->netaddrs[i].broadcast, print_addr6); + break; + + case PRINT_SINGLE_IPS: +@@ -146,7 +146,7 @@ void ipset6_print(ipset6 *ips, IPSET_PRINT_CMD print) { + ipv6_addr_t end = ips->netaddrs[i].broadcast; + ipv6_addr_t x; + +- if(unlikely(start > end)) { ++ if(unlikely(u128_gt(start, end))) { + char buf[IP6STR_MAX_LEN + 1]; + fprintf(stderr, "%s: WARNING: invalid range reversed start=%s", PROG, ip6str_r(buf, start)); + fprintf(stderr, " end=%s\n", ip6str_r(buf, end)); +@@ -154,13 +154,13 @@ void ipset6_print(ipset6 *ips, IPSET_PRINT_CMD print) { + end = start; + start = x; + } +- if(unlikely(end - start > IPV6_SINGLE_IP_CAP)) { ++ if(unlikely(u128_gt(u128_sub(end, start), u128_from_u64(IPV6_SINGLE_IP_CAP)))) { + char buf[IP6STR_MAX_LEN + 1]; + fprintf(stderr, "%s: too big range eliminated start=%s", PROG, ip6str_r(buf, start)); + fprintf(stderr, " end=%s\n", ip6str_r(buf, end)); + continue; + } +- for(x = start; x >= start && x <= end; x++) { ++ for(x = start; u128_ge(x, start) && u128_le(x, end); x = u128_inc(x)) { + print_addr6_single(x); + total++; + } +diff --git a/src/uint128.h b/src/uint128.h +new file mode 100644 +index 0000000..0da5873 +--- /dev/null ++++ b/src/uint128.h +@@ -0,0 +1,230 @@ ++#ifndef IPRANGE_UINT128_H ++#define IPRANGE_UINT128_H ++ ++#include <stdint.h> ++ ++/* Define IPRANGE_FORCE_PORTABLE_U128 to compile the portable (struct-based) ++ * 128-bit path even on platforms that have native __uint128_t. This lets the ++ * 32-bit code path be exercised by the test suite on a 64-bit host. */ ++#if defined(__SIZEOF_INT128__) && !defined(IPRANGE_FORCE_PORTABLE_U128) ++ ++/* ================================================================ ++ * Native 128-bit path (64-bit platforms with compiler support). ++ * Every function compiles to the native operator — zero overhead. ++ * ================================================================ */ ++ ++typedef __uint128_t uint128_t; ++ ++#define U128_ZERO ((uint128_t)0) ++#define U128_ONE ((uint128_t)1) ++#define U128_MAX ((uint128_t)((__uint128_t)(-1))) ++ ++static inline uint128_t u128_from_u64(uint64_t v) { return (uint128_t)v; } ++static inline uint128_t u128_from_u32(uint32_t v) { return (uint128_t)v; } ++ ++static inline uint64_t u128_hi64(uint128_t a) { return (uint64_t)(a >> 64); } ++static inline uint64_t u128_lo64(uint128_t a) { return (uint64_t)a; } ++ ++static inline int u128_is_zero(uint128_t a) { return a == 0; } ++static inline int u128_eq(uint128_t a, uint128_t b) { return a == b; } ++static inline int u128_lt(uint128_t a, uint128_t b) { return a < b; } ++static inline int u128_gt(uint128_t a, uint128_t b) { return a > b; } ++static inline int u128_le(uint128_t a, uint128_t b) { return a <= b; } ++static inline int u128_ge(uint128_t a, uint128_t b) { return a >= b; } ++ ++static inline uint128_t u128_add(uint128_t a, uint128_t b) { return a + b; } ++static inline uint128_t u128_sub(uint128_t a, uint128_t b) { return a - b; } ++static inline uint128_t u128_inc(uint128_t a) { return a + 1; } ++static inline uint128_t u128_dec(uint128_t a) { return a - 1; } ++ ++static inline uint128_t u128_and(uint128_t a, uint128_t b) { return a & b; } ++static inline uint128_t u128_or(uint128_t a, uint128_t b) { return a | b; } ++static inline uint128_t u128_not(uint128_t a) { return ~a; } ++static inline uint128_t u128_shl(uint128_t a, int n) { return a << n; } ++static inline uint128_t u128_shr(uint128_t a, int n) { return a >> n; } ++ ++static inline uint128_t u128_mul_u64(uint128_t a, uint64_t b) { return a * b; } ++static inline uint128_t u128_div10(uint128_t a) { return a / 10; } ++static inline int u128_mod10(uint128_t a) { return (int)(a % 10); } ++ ++#else /* !__SIZEOF_INT128__ */ ++ ++/* ================================================================ ++ * Portable 128-bit path (32-bit platforms without __uint128_t). ++ * Uses a struct of two uint64_t with explicit arithmetic. ++ * ================================================================ */ ++ ++/* Field order matches the byte layout of a native __uint128_t on the same ++ * endianness, so that an array of these structs is binary-compatible with one ++ * of native __uint128_t. This lets binary ipset files written by a 64-bit ++ * (native) build load correctly on a 32-bit (portable) build of the same ++ * endianness, and vice versa. All code refers to the fields by name, so the ++ * order is irrelevant to arithmetic; only the in-memory layout changes. */ ++#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++typedef struct { uint64_t hi; uint64_t lo; } uint128_t; ++#else ++typedef struct { uint64_t lo; uint64_t hi; } uint128_t; ++#endif ++ ++#define U128_ZERO ((uint128_t){ .hi = 0, .lo = 0 }) ++#define U128_ONE ((uint128_t){ .hi = 0, .lo = 1 }) ++#define U128_MAX ((uint128_t){ .hi = UINT64_MAX, .lo = UINT64_MAX }) ++ ++static inline uint128_t u128_from_u64(uint64_t v) { ++ uint128_t r = { .hi = 0, .lo = v }; ++ return r; ++} ++ *** 153 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a202248.256d0.5f955116>
