public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
47d8df1c20a987283a412e2f514e2685c8231558 blob 3673 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
 
// SPDX-License-Identifier: GPL-2.0-or-later

/* PASST - Plug A Simple Socket Transport
 *  for qemu/UNIX domain socket mode
 *
 * PASTA - Pack A Subtle Tap Abstraction
 *  for network namespace/tap device mode
 *
 * PESTO - Programmable Extensible Socket Translation Orchestrator
 *  front-end for passt(1) and pasta(1) forwarding configuration
 *
 * fwd_rule.c - Helpers for working with forwarding rule specifications
 *
 * Copyright Red Hat
 * Author: David Gibson <david@gibson.dropbear.id.au>
 */

#include <stdio.h>

#include "fwd_rule.h"

/**
 * fwd_rule_addr() - Return match address for a rule
 * @rule:	Forwarding rule
 *
 * Return: matching address for rule, NULL if it matches all addresses
 */
const union inany_addr *fwd_rule_addr(const struct fwd_rule *rule)
{
	if (rule->flags & FWD_DUAL_STACK_ANY)
		return NULL;

	return &rule->addr;
}

/**
 * fwd_rule_fmt() - Prettily format forwarding rule as a string
 * @rule:	Rule to format
 * @dst:	Buffer to store output (should have FWD_RULE_STRLEN bytes)
 * @size:	Size of @dst
 */
#if defined(__GNUC__) && __GNUC__ < 15
/* Workaround bug in gcc 12, 13 & 14 (at least) which gives a false positive
 * -Wformat-overflow message if this function is inlined.
 */
__attribute__((noinline))
#endif
const char *fwd_rule_fmt(const struct fwd_rule *rule, char *dst, size_t size)
{
	const char *percent = *rule->ifname ? "%" : "";
	const char *weak = "", *scan = "";
	char addr[INANY_ADDRSTRLEN];
	int len;

	inany_ntop(fwd_rule_addr(rule), addr, sizeof(addr));
	if (rule->flags & FWD_WEAK)
		weak = " (best effort)";
	if (rule->flags & FWD_SCAN)
		scan = " (auto-scan)";

	if (rule->first == rule->last) {
		len = snprintf(dst, size,
			       "%s [%s]%s%s:%hu  =>  %hu %s%s",
			       ipproto_name(rule->proto), addr, percent,
			       rule->ifname, rule->first, rule->to, weak, scan);
	} else {
		in_port_t tolast = rule->last - rule->first + rule->to;
		len = snprintf(dst, size,
			       "%s [%s]%s%s:%hu-%hu  =>  %hu-%hu %s%s",
			       ipproto_name(rule->proto), addr, percent,
			       rule->ifname, rule->first, rule->last,
			       rule->to, tolast, weak, scan);
	}

	if (len < 0 || (size_t)len >= size)
		return NULL;

	return dst;
}

/**
 * fwd_rules_info() - Print forwarding rules for debugging
 * @fwd:	Table to print
 */
void fwd_rules_info(const struct fwd_rule *rules, size_t count)
{
	unsigned i;

	for (i = 0; i < count; i++) {
		char buf[FWD_RULE_STRLEN];

		info("    %s", fwd_rule_fmt(&rules[i], buf, sizeof(buf)));
	}
}

/**
 * fwd_rule_conflicts() - Test if two rules conflict with each other
 * @a, @b:	Rules to test
 */
static bool fwd_rule_conflicts(const struct fwd_rule *a, const struct fwd_rule *b)
{
	if (a->proto != b->proto)
		/* Non-conflicting protocols */
		return false;

	if (!inany_matches(fwd_rule_addr(a), fwd_rule_addr(b)))
		/* Non-conflicting addresses */
		return false;

	assert(a->first <= a->last && b->first <= b->last);
	if (a->last < b->first || b->last < a->first)
		/* Port ranges don't overlap */
		return false;

	return true;
}

/**
 * fwd_rule_conflict_check() - Die if given rule conflicts with any in list
 * @new:	New rule
 * @rules:	Existing rules against which to test
 * @count:	Number of rules in @rules
 */
void fwd_rule_conflict_check(const struct fwd_rule *new,
			     const struct fwd_rule *rules, size_t count)
{
	unsigned i;

	for (i = 0; i < count; i++) {
		char newstr[FWD_RULE_STRLEN], rulestr[FWD_RULE_STRLEN];

		if (!fwd_rule_conflicts(new, &rules[i]))
			continue;

		die("Forwarding configuration conflict: %s versus %s",
		    fwd_rule_fmt(new, newstr, sizeof(newstr)),
		    fwd_rule_fmt(&rules[i], rulestr, sizeof(rulestr)));
	}
}
debug log:

solving 47d8df1c ...
found 47d8df1c in https://archives.passt.top/passt-dev/20260410010309.736855-12-david@gibson.dropbear.id.au/
found 5bc94efe in https://archives.passt.top/passt-dev/20260410010309.736855-11-david@gibson.dropbear.id.au/
found a034d5d1 in https://archives.passt.top/passt-dev/20260410010309.736855-8-david@gibson.dropbear.id.au/

applying [1/3] https://archives.passt.top/passt-dev/20260410010309.736855-8-david@gibson.dropbear.id.au/
diff --git a/fwd_rule.c b/fwd_rule.c
new file mode 100644
index 00000000..a034d5d1


applying [2/3] https://archives.passt.top/passt-dev/20260410010309.736855-11-david@gibson.dropbear.id.au/
diff --git a/fwd_rule.c b/fwd_rule.c
index a034d5d1..5bc94efe 100644


applying [3/3] https://archives.passt.top/passt-dev/20260410010309.736855-12-david@gibson.dropbear.id.au/
diff --git a/fwd_rule.c b/fwd_rule.c
index 5bc94efe..47d8df1c 100644

Checking patch fwd_rule.c...
Applied patch fwd_rule.c cleanly.
Checking patch fwd_rule.c...
Applied patch fwd_rule.c cleanly.
Checking patch fwd_rule.c...
Applied patch fwd_rule.c cleanly.

index at:
100644 47d8df1c20a987283a412e2f514e2685c8231558	fwd_rule.c

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).