#include "firewall-util-private.h"
#include "in-addr-util.h"
#include "macro.h"
-#include "memory-util.h"
#include "socket-util.h"
#include "time-util.h"
#define UDP_DPORT_OFFSET 2
-void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
- struct in6_addr *start, struct in6_addr *end);
-
static int nfnl_netlink_sendv(sd_netlink *nfnl,
sd_netlink_message *messages[],
size_t msgcount) {
return 0;
}
-void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
- struct in6_addr *ret_start, struct in6_addr *ret_end) {
- uint8_t carry = 0;
- int i, j;
-
- assert(prefixlen <= 128);
-
- for (i = 0, j = 15; i < 16; i++) {
- uint8_t nm;
-
- nm = 0xFF;
- if (prefixlen < 8)
- nm = 0xFF << (8 - prefixlen);
-
- ret_start->s6_addr[i] = source->in6.s6_addr[i] & nm;
- if (prefixlen <= 8 && j == 15) {
- carry = 1u << (8 - prefixlen);
- j = i;
- }
-
- if (prefixlen >= 8)
- prefixlen -= 8;
- else
- prefixlen = 0;
- }
- *ret_end = *ret_start;
-
- for (; j >= 0; j--) {
- uint16_t overflow = ret_end->s6_addr[j] + carry;
-
- ret_end->s6_addr[j] = overflow;
- if (overflow <= 0xff)
- break;
- carry = 1;
- }
-
- if (memcmp(ret_start, ret_end, sizeof(*ret_start)) > 0)
- zero(ret_end);
-}
+static int nft_message_add_setelem_ip6range(
+ sd_netlink_message *m,
+ const union in_addr_union *source,
+ unsigned int prefixlen) {
-static int nft_message_add_setelem_ip6range(sd_netlink_message *m,
- const union in_addr_union *source,
- unsigned int prefixlen) {
- struct in6_addr start, end;
+ union in_addr_union start, end;
int r;
- nft_in6addr_to_range(source, prefixlen, &start, &end);
+ r = in_addr_prefix_range(AF_INET6, source, prefixlen, &start, &end);
+ if (r < 0)
+ return r;
- r = sd_nfnl_nft_message_add_setelem(m, 0, &start, sizeof(start), NULL, 0);
+ r = sd_nfnl_nft_message_add_setelem(m, 0, &start.in6, sizeof(start.in6), NULL, 0);
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_nfnl_nft_message_add_setelem(m, 1, &end, sizeof(end), NULL, 0);
+ r = sd_nfnl_nft_message_add_setelem(m, 1, &end.in6, sizeof(end.in6), NULL, 0);
if (r < 0)
return r;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <arpa/inet.h>
-#include <stdlib.h>
#include "firewall-util.h"
#include "log.h"
#include "tests.h"
#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
-
-void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
- struct in6_addr *start, struct in6_addr *end);
-
-static void make_in6_addr_union(const char *addr, union in_addr_union *u) {
- assert_se(inet_pton(AF_INET6, addr, &u->in6) >= 0);
-}
-
-static bool test_in6_eq(const char *addr, const union in_addr_union *u) {
- union in_addr_union tmp;
-
- make_in6_addr_union(addr, &tmp);
-
- return memcmp(&tmp.in6, &u->in6, sizeof(tmp.in6)) == 0;
-}
-
-static void assert_in6_eq(const union in_addr_union *a, const union in_addr_union *b) {
- assert_se(memcmp(&a->in6, &b->in6, sizeof(a->in6)) == 0);
-}
+#define MAKE_IN6_ADDR_UNION(str, u) assert_se(in_addr_from_string(AF_INET6, str, u) >= 0)
static void test_v6(FirewallContext **ctx) {
union in_addr_union u = {}, u2 = {};
uint8_t prefixlen;
int r;
- make_in6_addr_union("dead::beef", &u);
+ MAKE_IN6_ADDR_UNION("dead::beef", &u);
r = fw_add_masquerade(ctx, true, AF_INET6, &u, 128);
if (r < 0)
if (r < 0)
log_error_errno(r, "Failed to modify firewall: %m");
- make_in6_addr_union("1c3::c01d", &u2);
+ MAKE_IN6_ADDR_UNION("1c3::c01d", &u2);
r = fw_add_local_dnat(ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, &u);
if (r < 0)
log_error_errno(r, "Failed to modify firewall: %m");
log_error_errno(r, "Failed to modify ipv6 firewall: %m");
}
-static void test_v6_range(void) {
- unsigned int prefixlen = 64;
- union in_addr_union a, b, s;
-
- make_in6_addr_union("dead:0:0:beef::", &s);
-
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
-
- assert_in6_eq(&s, &a);
- assert_se(test_in6_eq("dead:0:0:bef0::", &b));
-
- make_in6_addr_union("2001::", &s);
- prefixlen = 56;
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
- assert_in6_eq(&s, &a);
- assert_se(test_in6_eq("2001:0:0:0100::", &b));
-
- prefixlen = 48;
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
- assert_in6_eq(&s, &a);
-
- assert_se(test_in6_eq("2001:0:0001::", &b));
-
- prefixlen = 65;
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
- assert_se(test_in6_eq("2001::", &a));
-
- assert_se(test_in6_eq("2001::8000:0:0:0", &b));
-
- prefixlen = 66;
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
- assert_in6_eq(&s, &a);
-
- assert_se(test_in6_eq("2001::4000:0:0:0", &b));
-
- prefixlen = 127;
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
- assert_in6_eq(&s, &a);
- assert_se(test_in6_eq("2001::0002", &b));
-
- make_in6_addr_union("dead:beef::1", &s);
- prefixlen = 64;
- nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
- assert_se(test_in6_eq("dead:beef::", &a));
-}
-
int main(int argc, char *argv[]) {
_cleanup_(fw_ctx_freep) FirewallContext *ctx;
int r;
log_error_errno(r, "Failed to modify firewall: %m");
test_v6(&ctx);
- test_v6_range();
return 0;
}