Allow specifying multiple addresses per family with -a/--address.
The first address of each family is used for DHCP/DHCPv6 assignment.
Signed-off-by: Jon Maloy
---
v2: - Adapted to previous code changes
v3: - Adapted to single-array strategy
- Changes according to feedback from S. Brivio and D. Gibson.
v4: - Stripped down and adapted after feedback from David G.
v6: - Adapted to previous changes in series
- Removed the "one address" limitation for -n option
v7: - Updated man page.
---
conf.c | 7 ++++---
fwd.c | 4 +---
passt.1 | 7 +++----
pasta.c | 14 ++++++++------
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/conf.c b/conf.c
index 591f561..8b4a7a0 100644
--- a/conf.c
+++ b/conf.c
@@ -939,9 +939,11 @@ static void usage(const char *name, FILE *f, int status)
" default: 65520: maximum 802.3 MTU minus 802.3 header\n"
" length, rounded to 32 bits (IPv4 words)\n"
" -a, --address ADDR Assign IPv4 or IPv6 address ADDR[/PREFIXLEN]\n"
- " can be specified zero to two times (for IPv4 and IPv6)\n"
+ " can be specified up to a maximum of %d times\n"
" default: use addresses from interface with default route\n"
- " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n"
+ " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n",
+ MAX_GUEST_ADDRS);
+ FPRINTF(f,
" default: netmask from matching address on the host\n"
" -M, --mac-addr ADDR Use source MAC address ADDR\n"
" default: 9a:55:9a:55:9a:55 (locally administered)\n"
@@ -1898,7 +1900,6 @@ void conf(struct ctx *c, int argc, char **argv)
IN6_IS_ADDR_V4COMPAT(&addr.a6))
die("Invalid address: %s", optarg);
- /* Legacy behaviour: replace existing address if any */
fwd_set_addr(c, &addr, CONF_ADDR_USER, prefix_len);
if (inany_v4(&addr))
c->ip4.no_copy_addrs = true;
diff --git a/fwd.c b/fwd.c
index e676c18..d3f576a 100644
--- a/fwd.c
+++ b/fwd.c
@@ -250,14 +250,12 @@ void fwd_neigh_table_init(const struct ctx *c)
}
/**
- * fwd_set_addr() - Add or update an address in the unified address array
+ * fwd_set_addr() - Update address entry, adding one if needed
* @c: Execution context
* @addr: Address to add (IPv4-mapped or IPv6)
* @flags: CONF_ADDR_* flags for this address
* @prefix_len: Prefix length in IPv6 or IPv4 format
*
- * Find the first existing entry of the same address family and
- * overwrite it, or create a new one if none exists
*/
void fwd_set_addr(struct ctx *c, const union inany_addr *addr,
uint8_t flags, int prefix_len)
diff --git a/passt.1 b/passt.1
index 13e8df9..12ec857 100644
--- a/passt.1
+++ b/passt.1
@@ -164,16 +164,13 @@ An optional /\fIprefix_len\fR (0-32 for IPv4, 0-128 for IPv6) can be
appended in CIDR notation (e.g. 192.0.2.1/24). This is an alternative to
using the \fB-n\fR, \fB--netmask\fR option. Mixing CIDR notation with
\fB-n\fR results in an error.
-If a prefix length is assigned to an IPv6 address using this method, it will
-in the current code version be overridden by the default value of 64.
-This option can be specified zero (for defaults) to two times (once for IPv4,
-once for IPv6).
By default, assigned IPv4 and IPv6 addresses are taken from the host interfaces
with the first default route, if any, for the corresponding IP version. If no
default routes are available and there is any interface with any route for a
given IP version, the first of these interfaces will be chosen instead. If no
such interface exists for a given IP version, the link-local address 169.254.2.1
is assigned for IPv4, and no additional address will be assigned for IPv6.
+This option can be given multiple times, indicating multiple different addresses.
.TP
.BR \-n ", " \-\-netmask " " \fImask
@@ -181,6 +178,8 @@ Assign IPv4 netmask \fImask\fR, expressed as dot-decimal or number of bits, via
DHCP (option 1). Alternatively, the prefix length can be specified using CIDR
notation with the \fB-a\fR, \fB--address\fR option (e.g. \fB-a\fR 192.0.2.1/24).
Mixing \fB-n\fR with CIDR notation results in an error.
+When indicated, this option sets the prefix length of the first configured
+IPv4 address only.
If no address is indicated, the netmask associated with the adopted host address,
if any, is used. If an address is indicated, but without a prefix length, the
netmask is determined based on the corresponding network class. In all other
diff --git a/pasta.c b/pasta.c
index c51e4cd..b3936f5 100644
--- a/pasta.c
+++ b/pasta.c
@@ -343,14 +343,15 @@ void pasta_ns_conf(struct ctx *c)
if (c->ifi4) {
if (c->ip4.no_copy_addrs) {
- a = fwd_get_addr(c, AF_INET, 0, 0);
- if (a) {
+ for_each_addr(a, c->addrs, c->addr_count, AF_INET) {
plen = inany_prefix_len(&a->addr,
a->prefix_len);
rc = nl_addr_set(nl_sock_ns,
c->pasta_ifi, AF_INET,
inany_v4(&a->addr),
plen);
+ if (rc < 0)
+ break;
}
} else {
rc = nl_addr_dup(nl_sock, c->ifi4,
@@ -404,13 +405,14 @@ ipv4_done:
0, IFF_NOARP);
if (c->ip6.no_copy_addrs) {
- a = fwd_get_addr(c, AF_INET6, 0, 0);
- if (a)
+ for_each_addr(a, c->addrs, c->addr_count, AF_INET6) {
rc = nl_addr_set(nl_sock_ns,
c->pasta_ifi,
- AF_INET6,
- &a->addr.a6,
+ AF_INET6, &a->addr.a6,
a->prefix_len);
+ if (rc < 0)
+ break;
+ }
} else {
rc = nl_addr_dup(nl_sock, c->ifi6,
nl_sock_ns, c->pasta_ifi,
--
2.52.0