Page MenuHomeFreeBSD

D51243.id159444.diff
No OneTemporary

D51243.id159444.diff

diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -435,43 +435,80 @@
err(1, "BRDGFLUSH");
}
-static void
-setbridge_static(if_ctx *ctx, const char *val, const char *mac)
+static int
+setbridge_static(if_ctx *ctx, int argc, const char *const *argv)
{
struct ifbareq req;
struct ether_addr *ea;
+ int arg;
+
+ if (argc < 2)
+ errx(1, "usage: static <interface> <address> [vlan <id>]");
+ arg = 0;
memset(&req, 0, sizeof(req));
- strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname));
+ req.ifba_flags = IFBAF_STATIC;
- ea = ether_aton(mac);
- if (ea == NULL)
- errx(1, "%s: invalid address: %s", val, mac);
+ strlcpy(req.ifba_ifsname, argv[arg], sizeof(req.ifba_ifsname));
+ ++arg;
+ ea = ether_aton(argv[arg]);
+ if (ea == NULL)
+ errx(1, "invalid address: %s", argv[arg]);
memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
- req.ifba_flags = IFBAF_STATIC;
- req.ifba_vlan = 0; /* XXX allow user to specify */
+ ++arg;
+
+ req.ifba_vlan = 0;
+ if (argc > 2 && strcmp(argv[arg], "vlan") == 0) {
+ if (argc < 3)
+ errx(1, "usage: static <interface> <address> "
+ "[vlan <id>]");
+ ++arg;
+
+ if (get_vlan_id(argv[arg], &req.ifba_vlan) < 0)
+ errx(1, "invalid vlan id: %s", argv[arg]);
+ ++arg;
+ }
if (do_cmd(ctx, BRDGSADDR, &req, sizeof(req), 1) < 0)
- err(1, "BRDGSADDR %s", val);
+ err(1, "BRDGSADDR");
+ return arg;
}
-static void
-setbridge_deladdr(if_ctx *ctx, const char *val, int dummy __unused)
+static int
+setbridge_deladdr(if_ctx *ctx, int argc, const char *const *argv)
{
struct ifbareq req;
struct ether_addr *ea;
+ int arg;
+
+ if (argc < 1)
+ errx(1, "usage: deladdr <address> [vlan <id>]");
+ arg = 0;
memset(&req, 0, sizeof(req));
- ea = ether_aton(val);
+ ea = ether_aton(argv[arg]);
if (ea == NULL)
- errx(1, "invalid address: %s", val);
-
+ errx(1, "invalid address: %s", argv[arg]);
memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
+ ++arg;
+
+ req.ifba_vlan = 0;
+ if (argc >= 2 && strcmp(argv[arg], "vlan") == 0) {
+ if (argc < 3)
+ errx(1, "usage: deladdr <address> [vlan <id>]");
+ ++arg;
+
+ if (get_vlan_id(argv[arg], &req.ifba_vlan) < 0)
+ errx(1, "invalid vlan id: %s", argv[arg]);
+ ++arg;
+ }
if (do_cmd(ctx, BRDGDADDR, &req, sizeof(req), 1) < 0)
- err(1, "BRDGDADDR %s", val);
+ err(1, "BRDGDADDR");
+
+ return arg;
}
static void
@@ -824,8 +861,8 @@
DEF_CMD_ARG("-autoptp", unsetbridge_autoptp),
DEF_CMD("flush", 0, setbridge_flush),
DEF_CMD("flushall", 0, setbridge_flushall),
- DEF_CMD_ARG2("static", setbridge_static),
- DEF_CMD_ARG("deladdr", setbridge_deladdr),
+ DEF_CMD_VARG("static", setbridge_static),
+ DEF_CMD_VARG("deladdr", setbridge_deladdr),
DEF_CMD("addr", 1, setbridge_addr),
DEF_CMD_ARG("maxaddr", setbridge_maxaddr),
DEF_CMD_ARG("hellotime", setbridge_hellotime),
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -67,6 +67,7 @@
typedef void c_func(if_ctx *ctx, const char *cmd, int arg);
typedef void c_func2(if_ctx *ctx, const char *arg1, const char *arg2);
typedef void c_func3(if_ctx *ctx, const char *cmd, const char *arg);
+typedef int c_funcv(if_ctx *ctx, int argc, const char *const *argv);
struct cmd {
const char *c_name;
@@ -75,11 +76,13 @@
#define NEXTARG2 0xfffffe /* has 2 following args */
#define OPTARG 0xfffffd /* has optional following arg */
#define SPARAM 0xfffffc /* parameter is string c_sparameter */
+#define ARGVECTOR 0xfffffb /* takes argument vector */
const char *c_sparameter;
union {
c_func *c_func;
c_func2 *c_func2;
c_func3 *c_func3;
+ c_funcv *c_funcv;
} c_u;
int c_iscloneop;
struct cmd *c_next;
@@ -121,6 +124,13 @@
.c_iscloneop = 0, \
.c_next = NULL, \
}
+#define DEF_CMD_VARG(name, func) { \
+ .c_name = (name), \
+ .c_parameter = ARGVECTOR, \
+ .c_u = { .c_funcv = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
#define DEF_CMD_SARG(name, sparam, func) { \
.c_name = (name), \
.c_parameter = SPARAM, \
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 14, 2025
+.Dd July 30, 2025
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -2520,15 +2520,23 @@
The default is 1200 seconds.
.It Cm addr
Display the addresses that have been learned by the bridge.
-.It Cm static Ar interface-name Ar address
-Add a static entry into the address cache pointing to
+.It Cm static Ar interface-name Ar address Op Cm vlan Ar vlan-id
+Add a static entry into the address cache for pointing to
.Ar interface-name .
+If
+.Ar vlan-id
+is specified, the entry is added for that VLAN, otherwise it is added
+for VLAN 0.
+.Pp
Static entries are never aged out of the cache or re-placed, even if the
address is seen on a different interface.
-.It Cm deladdr Ar address
+.It Cm deladdr Ar address Op Cm vlan Ar vlan-id
Delete
.Ar address
-from the address cache.
+from the address cache. If
+.Ar vlan-id
+is specified, the entry is deleted from that VLAN's address table,
+otherwise it is deleted from the VLAN 0 address table.
.It Cm flush
Delete all dynamically-learned addresses from the address cache.
.It Cm flushall
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1209,6 +1209,13 @@
argc -= 2, argv += 2;
} else if (p->c_parameter == SPARAM && p->c_u.c_func3) {
p->c_u.c_func3(ctx, *argv, p->c_sparameter);
+ } else if (p->c_parameter == ARGVECTOR && p->c_u.c_funcv) {
+ int argsdone;
+
+ argsdone = p->c_u.c_funcv(ctx, argc - 1,
+ (const char *const *)argv + 1);
+ argc -= argsdone;
+ argv += argsdone;
} else if (p->c_u.c_func)
p->c_u.c_func(ctx, *argv, p->c_parameter);
argc--, argv++;
diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh
--- a/tests/sys/net/if_bridge_test.sh
+++ b/tests/sys/net/if_bridge_test.sh
@@ -245,7 +245,8 @@
jexec one ifconfig ${bridge} static ${epair}a 00:01:02:03:04:05
# List addresses
- atf_check -s exit:0 -o ignore \
+ atf_check -s exit:0 \
+ -o match:"00:01:02:03:04:05 Vlan0 ${epair}a 0 flags=1<STATIC>" \
jexec one ifconfig ${bridge} addr
# Delete with bad address format
@@ -266,6 +267,72 @@
vnet_cleanup
}
+atf_test_case "vstatic" "cleanup"
+vstatic_head()
+{
+ atf_set descr 'Bridge VLAN static address test'
+ atf_set require.user root
+}
+
+vstatic_body()
+{
+ vnet_init
+ vnet_init_bridge
+
+ epair=$(vnet_mkepair)
+ bridge=$(vnet_mkbridge)
+
+ vnet_mkjail one ${bridge} ${epair}a
+
+ ifconfig ${epair}b up
+
+ jexec one ifconfig ${bridge} up
+ jexec one ifconfig ${epair}a up
+ jexec one ifconfig ${bridge} addm ${epair}a
+
+ # Wrong interface
+ atf_check -s exit:1 -o ignore -e ignore jexec one \
+ ifconfig ${bridge} static ${epair}b 00:01:02:03:04:05 vlan 10
+
+ # Bad address format
+ atf_check -s exit:1 -o ignore -e ignore jexec one \
+ ifconfig ${bridge} static ${epair}a 00:01:02:03:04 vlan 10
+
+ # Invalid VLAN ID
+ atf_check -s exit:1 -o ignore -e ignore jexec one \
+ ifconfig ${bridge} static ${epair}a 00:01:02:03:04:05 vlan 5000
+
+ # Correct add
+ atf_check -s exit:0 -o ignore jexec one \
+ ifconfig ${bridge} static ${epair}a 00:01:02:03:04:05 vlan 10
+
+ # List addresses
+ atf_check -s exit:0 \
+ -o match:"00:01:02:03:04:05 Vlan10 ${epair}a 0 flags=1<STATIC>" \
+ jexec one ifconfig ${bridge} addr
+
+ # Delete with bad address format
+ atf_check -s exit:1 -o ignore -e ignore jexec one \
+ ifconfig ${bridge} deladdr 00:01:02:03:04 vlan 10
+
+ # Delete with unlisted address
+ atf_check -s exit:1 -o ignore -e ignore jexec one \
+ ifconfig ${bridge} deladdr 00:01:02:03:04:06 vlan 10
+
+ # Delete with wrong vlan id
+ atf_check -s exit:1 -o ignore -e ignore jexec one \
+ ifconfig ${bridge} deladdr 00:01:02:03:04:05 vlan 20
+
+ # Correct delete
+ atf_check -s exit:0 -o ignore jexec one \
+ ifconfig ${bridge} deladdr 00:01:02:03:04:05 vlan 10
+}
+
+vstatic_cleanup()
+{
+ vnet_cleanup
+}
+
atf_test_case "span" "cleanup"
span_head()
{
@@ -1250,6 +1317,7 @@
atf_add_test_case "stp"
atf_add_test_case "stp_vlan"
atf_add_test_case "static"
+ atf_add_test_case "vstatic"
atf_add_test_case "span"
atf_add_test_case "inherit_mac"
atf_add_test_case "delete_with_members"

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 17, 9:44 AM (6 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27688065
Default Alt Text
D51243.id159444.diff (8 KB)

Event Timeline