1146985Sthompsa/*-
2330449Seadler * SPDX-License-Identifier: BSD-4-Clause
3330449Seadler *
4146985Sthompsa * Copyright 2001 Wasabi Systems, Inc.
5146985Sthompsa * All rights reserved.
6146985Sthompsa *
7146985Sthompsa * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8146985Sthompsa *
9146985Sthompsa * Redistribution and use in source and binary forms, with or without
10146985Sthompsa * modification, are permitted provided that the following conditions
11146985Sthompsa * are met:
12146985Sthompsa * 1. Redistributions of source code must retain the above copyright
13146985Sthompsa *    notice, this list of conditions and the following disclaimer.
14146985Sthompsa * 2. Redistributions in binary form must reproduce the above copyright
15146985Sthompsa *    notice, this list of conditions and the following disclaimer in the
16146985Sthompsa *    documentation and/or other materials provided with the distribution.
17146985Sthompsa * 3. All advertising materials mentioning features or use of this software
18146985Sthompsa *    must display the following acknowledgement:
19146985Sthompsa *	This product includes software developed for the NetBSD Project by
20146985Sthompsa *	Wasabi Systems, Inc.
21146985Sthompsa * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22146985Sthompsa *    or promote products derived from this software without specific prior
23146985Sthompsa *    written permission.
24146985Sthompsa *
25146985Sthompsa * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26146985Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27146985Sthompsa * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28146985Sthompsa * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29146985Sthompsa * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30146985Sthompsa * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31146985Sthompsa * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32146985Sthompsa * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33146985Sthompsa * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34146985Sthompsa * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35146985Sthompsa * POSSIBILITY OF SUCH DAMAGE.
36146985Sthompsa */
37146985Sthompsa
38146985Sthompsa#ifndef lint
39146985Sthompsastatic const char rcsid[] =
40146985Sthompsa  "$FreeBSD: stable/11/sbin/ifconfig/ifbridge.c 330469 2018-03-05 08:33:29Z eadler $";
41146985Sthompsa#endif /* not lint */
42146985Sthompsa
43146985Sthompsa#include <sys/param.h>
44146985Sthompsa#include <sys/ioctl.h>
45146985Sthompsa#include <sys/socket.h>
46146985Sthompsa#include <sys/sockio.h>
47146985Sthompsa
48146985Sthompsa#include <stdlib.h>
49146985Sthompsa#include <unistd.h>
50146985Sthompsa
51146985Sthompsa#include <net/ethernet.h>
52146985Sthompsa#include <net/if.h>
53146985Sthompsa#include <net/if_bridgevar.h>
54146985Sthompsa#include <net/route.h>
55146985Sthompsa
56146985Sthompsa#include <ctype.h>
57146985Sthompsa#include <stdio.h>
58146985Sthompsa#include <string.h>
59146985Sthompsa#include <stdlib.h>
60146985Sthompsa#include <unistd.h>
61146985Sthompsa#include <err.h>
62146985Sthompsa#include <errno.h>
63146985Sthompsa
64146985Sthompsa#include "ifconfig.h"
65146985Sthompsa
66164653Sthompsa#define PV2ID(pv, epri, eaddr)  do {		\
67164653Sthompsa		epri     = pv >> 48;		\
68164653Sthompsa		eaddr[0] = pv >> 40;		\
69164653Sthompsa		eaddr[1] = pv >> 32;		\
70164653Sthompsa		eaddr[2] = pv >> 24;		\
71164653Sthompsa		eaddr[3] = pv >> 16;		\
72164653Sthompsa		eaddr[4] = pv >> 8;		\
73164653Sthompsa		eaddr[5] = pv >> 0;		\
74164653Sthompsa} while (0)
75164653Sthompsa
76163863Sthompsastatic const char *stpstates[] = {
77163863Sthompsa	"disabled",
78163863Sthompsa	"listening",
79163863Sthompsa	"learning",
80163863Sthompsa	"forwarding",
81163863Sthompsa	"blocking",
82163863Sthompsa	"discarding"
83163863Sthompsa};
84163863Sthompsastatic const char *stpproto[] = {
85163863Sthompsa	"stp",
86163863Sthompsa	"-",
87163863Sthompsa	"rstp"
88163863Sthompsa};
89163863Sthompsastatic const char *stproles[] = {
90163863Sthompsa	"disabled",
91163863Sthompsa	"root",
92163863Sthompsa	"designated",
93163863Sthompsa	"alternate",
94163863Sthompsa	"backup"
95163863Sthompsa};
96163863Sthompsa
97146985Sthompsastatic int
98146985Sthompsaget_val(const char *cp, u_long *valp)
99146985Sthompsa{
100146985Sthompsa	char *endptr;
101146985Sthompsa	u_long val;
102146985Sthompsa
103146985Sthompsa	errno = 0;
104146985Sthompsa	val = strtoul(cp, &endptr, 0);
105146985Sthompsa	if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
106146985Sthompsa		return (-1);
107146985Sthompsa
108146985Sthompsa	*valp = val;
109146985Sthompsa	return (0);
110146985Sthompsa}
111146985Sthompsa
112146985Sthompsastatic int
113146985Sthompsado_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
114146985Sthompsa{
115146985Sthompsa	struct ifdrv ifd;
116146985Sthompsa
117146985Sthompsa	memset(&ifd, 0, sizeof(ifd));
118146985Sthompsa
119146985Sthompsa	strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
120146985Sthompsa	ifd.ifd_cmd = op;
121146985Sthompsa	ifd.ifd_len = argsize;
122146985Sthompsa	ifd.ifd_data = arg;
123146985Sthompsa
124146985Sthompsa	return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
125146985Sthompsa}
126146985Sthompsa
127146985Sthompsastatic void
128146985Sthompsado_bridgeflag(int sock, const char *ifs, int flag, int set)
129146985Sthompsa{
130146985Sthompsa	struct ifbreq req;
131146985Sthompsa
132146985Sthompsa	strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname));
133146985Sthompsa
134146985Sthompsa	if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0)
135146985Sthompsa		err(1, "unable to get bridge flags");
136146985Sthompsa
137146985Sthompsa	if (set)
138146985Sthompsa		req.ifbr_ifsflags |= flag;
139146985Sthompsa	else
140146985Sthompsa		req.ifbr_ifsflags &= ~flag;
141146985Sthompsa
142146985Sthompsa	if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0)
143146985Sthompsa		err(1, "unable to set bridge flags");
144146985Sthompsa}
145146985Sthompsa
146146985Sthompsastatic void
147151040Sthompsabridge_interfaces(int s, const char *prefix)
148146985Sthompsa{
149146985Sthompsa	struct ifbifconf bifc;
150146985Sthompsa	struct ifbreq *req;
151146985Sthompsa	char *inbuf = NULL, *ninbuf;
152151040Sthompsa	char *p, *pad;
153146985Sthompsa	int i, len = 8192;
154146985Sthompsa
155151040Sthompsa	pad = strdup(prefix);
156151040Sthompsa	if (pad == NULL)
157151040Sthompsa		err(1, "strdup");
158151040Sthompsa	/* replace the prefix with whitespace */
159151040Sthompsa	for (p = pad; *p != '\0'; p++) {
160151040Sthompsa		if(isprint(*p))
161151040Sthompsa			*p = ' ';
162151040Sthompsa	}
163151040Sthompsa
164146985Sthompsa	for (;;) {
165146985Sthompsa		ninbuf = realloc(inbuf, len);
166146985Sthompsa		if (ninbuf == NULL)
167146985Sthompsa			err(1, "unable to allocate interface buffer");
168146985Sthompsa		bifc.ifbic_len = len;
169146985Sthompsa		bifc.ifbic_buf = inbuf = ninbuf;
170146985Sthompsa		if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0)
171146985Sthompsa			err(1, "unable to get interface list");
172146985Sthompsa		if ((bifc.ifbic_len + sizeof(*req)) < len)
173146985Sthompsa			break;
174146985Sthompsa		len *= 2;
175146985Sthompsa	}
176146985Sthompsa
177146985Sthompsa	for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) {
178146985Sthompsa		req = bifc.ifbic_req + i;
179146985Sthompsa		printf("%s%s ", prefix, req->ifbr_ifsname);
180146985Sthompsa		printb("flags", req->ifbr_ifsflags, IFBIFBITS);
181146985Sthompsa		printf("\n");
182173320Sthompsa
183173320Sthompsa		printf("%s", pad);
184173320Sthompsa		printf("ifmaxaddr %u", req->ifbr_addrmax);
185173320Sthompsa		printf(" port %u priority %u", req->ifbr_portno,
186173320Sthompsa		    req->ifbr_priority);
187173320Sthompsa		printf(" path cost %u", req->ifbr_path_cost);
188173320Sthompsa
189146985Sthompsa		if (req->ifbr_ifsflags & IFBIF_STP) {
190298246Saraujo			if (req->ifbr_proto < nitems(stpproto))
191163863Sthompsa				printf(" proto %s", stpproto[req->ifbr_proto]);
192163863Sthompsa			else
193163863Sthompsa				printf(" <unknown proto %d>",
194163863Sthompsa				    req->ifbr_proto);
195163863Sthompsa
196163863Sthompsa			printf("\n%s", pad);
197298246Saraujo			if (req->ifbr_role < nitems(stproles))
198163863Sthompsa				printf("role %s", stproles[req->ifbr_role]);
199163863Sthompsa			else
200163863Sthompsa				printf("<unknown role %d>",
201163863Sthompsa				    req->ifbr_role);
202298246Saraujo			if (req->ifbr_state < nitems(stpstates))
203163863Sthompsa				printf(" state %s", stpstates[req->ifbr_state]);
204146985Sthompsa			else
205146985Sthompsa				printf(" <unknown state %d>",
206146985Sthompsa				    req->ifbr_state);
207146985Sthompsa		}
208173320Sthompsa		printf("\n");
209146985Sthompsa	}
210330469Seadler	free(pad);
211146985Sthompsa	free(inbuf);
212146985Sthompsa}
213146985Sthompsa
214146985Sthompsastatic void
215146985Sthompsabridge_addresses(int s, const char *prefix)
216146985Sthompsa{
217146985Sthompsa	struct ifbaconf ifbac;
218146985Sthompsa	struct ifbareq *ifba;
219146985Sthompsa	char *inbuf = NULL, *ninbuf;
220146985Sthompsa	int i, len = 8192;
221146985Sthompsa	struct ether_addr ea;
222146985Sthompsa
223146985Sthompsa	for (;;) {
224146985Sthompsa		ninbuf = realloc(inbuf, len);
225146985Sthompsa		if (ninbuf == NULL)
226146985Sthompsa			err(1, "unable to allocate address buffer");
227146985Sthompsa		ifbac.ifbac_len = len;
228146985Sthompsa		ifbac.ifbac_buf = inbuf = ninbuf;
229146985Sthompsa		if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0)
230146985Sthompsa			err(1, "unable to get address cache");
231146985Sthompsa		if ((ifbac.ifbac_len + sizeof(*ifba)) < len)
232146985Sthompsa			break;
233146985Sthompsa		len *= 2;
234146985Sthompsa	}
235146985Sthompsa
236146985Sthompsa	for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
237146985Sthompsa		ifba = ifbac.ifbac_req + i;
238146985Sthompsa		memcpy(ea.octet, ifba->ifba_dst,
239146985Sthompsa		    sizeof(ea.octet));
240170681Sthompsa		printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea),
241170681Sthompsa		    ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire);
242146985Sthompsa		printb("flags", ifba->ifba_flags, IFBAFBITS);
243146985Sthompsa		printf("\n");
244146985Sthompsa	}
245146985Sthompsa
246146985Sthompsa	free(inbuf);
247146985Sthompsa}
248146985Sthompsa
249146985Sthompsastatic void
250146985Sthompsabridge_status(int s)
251146985Sthompsa{
252164691Sthompsa	struct ifbropreq ifbp;
253164691Sthompsa	struct ifbrparam param;
254146985Sthompsa	u_int16_t pri;
255163863Sthompsa	u_int8_t ht, fd, ma, hc, pro;
256164653Sthompsa	u_int8_t lladdr[ETHER_ADDR_LEN];
257164653Sthompsa	u_int16_t bprio;
258164691Sthompsa	u_int32_t csize, ctime;
259146985Sthompsa
260164691Sthompsa	if (do_cmd(s, BRDGGCACHE, &param, sizeof(param), 0) < 0)
261146985Sthompsa		return;
262164691Sthompsa	csize = param.ifbrp_csize;
263164691Sthompsa	if (do_cmd(s, BRDGGTO, &param, sizeof(param), 0) < 0)
264164691Sthompsa		return;
265164691Sthompsa	ctime = param.ifbrp_ctime;
266164691Sthompsa	if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0)
267164691Sthompsa		return;
268164691Sthompsa	pri = ifbp.ifbop_priority;
269164691Sthompsa	pro = ifbp.ifbop_protocol;
270164691Sthompsa	ht = ifbp.ifbop_hellotime;
271164691Sthompsa	fd = ifbp.ifbop_fwddelay;
272164691Sthompsa	hc = ifbp.ifbop_holdcount;
273164691Sthompsa	ma = ifbp.ifbop_maxage;
274146985Sthompsa
275164691Sthompsa	PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr);
276164653Sthompsa	printf("\tid %s priority %u hellotime %u fwddelay %u\n",
277164653Sthompsa	    ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd);
278164691Sthompsa	printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n",
279164691Sthompsa	    ma, hc, stpproto[pro], csize, ctime);
280146985Sthompsa
281164691Sthompsa	PV2ID(ifbp.ifbop_designated_root, bprio, lladdr);
282164653Sthompsa	printf("\troot id %s priority %d ifcost %u port %u\n",
283164653Sthompsa	    ether_ntoa((struct ether_addr *)lladdr), bprio,
284164691Sthompsa	    ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff);
285164653Sthompsa
286151040Sthompsa	bridge_interfaces(s, "\tmember: ");
287146985Sthompsa
288146985Sthompsa	return;
289146985Sthompsa
290146985Sthompsa}
291146985Sthompsa
292146985Sthompsastatic void
293146985Sthompsasetbridge_add(const char *val, int d, int s, const struct afswtch *afp)
294146985Sthompsa{
295146985Sthompsa	struct ifbreq req;
296146985Sthompsa
297146985Sthompsa	memset(&req, 0, sizeof(req));
298146985Sthompsa	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
299146985Sthompsa	if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0)
300146985Sthompsa		err(1, "BRDGADD %s",  val);
301146985Sthompsa}
302146985Sthompsa
303146985Sthompsastatic void
304146985Sthompsasetbridge_delete(const char *val, int d, int s, const struct afswtch *afp)
305146985Sthompsa{
306146985Sthompsa	struct ifbreq req;
307146985Sthompsa
308146985Sthompsa	memset(&req, 0, sizeof(req));
309146985Sthompsa	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
310146985Sthompsa	if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0)
311146985Sthompsa		err(1, "BRDGDEL %s",  val);
312146985Sthompsa}
313146985Sthompsa
314146985Sthompsastatic void
315146985Sthompsasetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
316146985Sthompsa{
317146985Sthompsa
318146985Sthompsa	do_bridgeflag(s, val, IFBIF_DISCOVER, 1);
319146985Sthompsa}
320146985Sthompsa
321146985Sthompsastatic void
322146985Sthompsaunsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
323146985Sthompsa{
324146985Sthompsa
325146985Sthompsa	do_bridgeflag(s, val, IFBIF_DISCOVER, 0);
326146985Sthompsa}
327146985Sthompsa
328146985Sthompsastatic void
329146985Sthompsasetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
330146985Sthompsa{
331146985Sthompsa
332146985Sthompsa	do_bridgeflag(s, val, IFBIF_LEARNING,  1);
333146985Sthompsa}
334146985Sthompsa
335146985Sthompsastatic void
336146985Sthompsaunsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
337146985Sthompsa{
338146985Sthompsa
339146985Sthompsa	do_bridgeflag(s, val, IFBIF_LEARNING,  0);
340146985Sthompsa}
341146985Sthompsa
342146985Sthompsastatic void
343164112Sthompsasetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
344164112Sthompsa{
345164112Sthompsa
346164112Sthompsa	do_bridgeflag(s, val, IFBIF_STICKY,  1);
347164112Sthompsa}
348164112Sthompsa
349164112Sthompsastatic void
350164112Sthompsaunsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
351164112Sthompsa{
352164112Sthompsa
353164112Sthompsa	do_bridgeflag(s, val, IFBIF_STICKY,  0);
354164112Sthompsa}
355164112Sthompsa
356164112Sthompsastatic void
357153408Sthompsasetbridge_span(const char *val, int d, int s, const struct afswtch *afp)
358153408Sthompsa{
359153408Sthompsa	struct ifbreq req;
360153408Sthompsa
361153408Sthompsa	memset(&req, 0, sizeof(req));
362153408Sthompsa	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
363153408Sthompsa	if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0)
364153408Sthompsa		err(1, "BRDGADDS %s",  val);
365153408Sthompsa}
366153408Sthompsa
367153408Sthompsastatic void
368153408Sthompsaunsetbridge_span(const char *val, int d, int s, const struct afswtch *afp)
369153408Sthompsa{
370153408Sthompsa	struct ifbreq req;
371153408Sthompsa
372153408Sthompsa	memset(&req, 0, sizeof(req));
373153408Sthompsa	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
374153408Sthompsa	if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0)
375153408Sthompsa		err(1, "BRDGDELS %s",  val);
376153408Sthompsa}
377153408Sthompsa
378153408Sthompsastatic void
379146985Sthompsasetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
380146985Sthompsa{
381146985Sthompsa
382146985Sthompsa	do_bridgeflag(s, val, IFBIF_STP, 1);
383146985Sthompsa}
384146985Sthompsa
385146985Sthompsastatic void
386146985Sthompsaunsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
387146985Sthompsa{
388146985Sthompsa
389146985Sthompsa	do_bridgeflag(s, val, IFBIF_STP, 0);
390146985Sthompsa}
391146985Sthompsa
392146985Sthompsastatic void
393163863Sthompsasetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
394163863Sthompsa{
395164653Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
396163863Sthompsa}
397163863Sthompsa
398163863Sthompsastatic void
399163863Sthompsaunsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
400163863Sthompsa{
401164653Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
402163863Sthompsa}
403163863Sthompsa
404163863Sthompsastatic void
405163863Sthompsasetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
406163863Sthompsa{
407164653Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
408163863Sthompsa}
409163863Sthompsa
410163863Sthompsastatic void
411163863Sthompsaunsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
412163863Sthompsa{
413164653Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
414164653Sthompsa}
415163863Sthompsa
416164653Sthompsastatic void
417165105Sthompsasetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
418164653Sthompsa{
419165105Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1);
420163863Sthompsa}
421163863Sthompsa
422163863Sthompsastatic void
423165105Sthompsaunsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
424164653Sthompsa{
425165105Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0);
426164653Sthompsa}
427164653Sthompsa
428164653Sthompsastatic void
429165105Sthompsasetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
430164653Sthompsa{
431165105Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1);
432164653Sthompsa}
433164653Sthompsa
434164653Sthompsastatic void
435165105Sthompsaunsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
436164653Sthompsa{
437165105Sthompsa	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0);
438164653Sthompsa}
439164653Sthompsa
440164653Sthompsastatic void
441146985Sthompsasetbridge_flush(const char *val, int d, int s, const struct afswtch *afp)
442146985Sthompsa{
443146985Sthompsa	struct ifbreq req;
444146985Sthompsa
445146985Sthompsa	memset(&req, 0, sizeof(req));
446146985Sthompsa	req.ifbr_ifsflags = IFBF_FLUSHDYN;
447146985Sthompsa	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
448146985Sthompsa		err(1, "BRDGFLUSH");
449146985Sthompsa}
450146985Sthompsa
451146985Sthompsastatic void
452146985Sthompsasetbridge_flushall(const char *val, int d, int s, const struct afswtch *afp)
453146985Sthompsa{
454146985Sthompsa	struct ifbreq req;
455146985Sthompsa
456146985Sthompsa	memset(&req, 0, sizeof(req));
457146985Sthompsa	req.ifbr_ifsflags = IFBF_FLUSHALL;
458146985Sthompsa	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
459146985Sthompsa		err(1, "BRDGFLUSH");
460146985Sthompsa}
461146985Sthompsa
462146985Sthompsastatic void
463146985Sthompsasetbridge_static(const char *val, const char *mac, int s,
464146985Sthompsa    const struct afswtch *afp)
465146985Sthompsa{
466146985Sthompsa	struct ifbareq req;
467146985Sthompsa	struct ether_addr *ea;
468146985Sthompsa
469146985Sthompsa	memset(&req, 0, sizeof(req));
470146985Sthompsa	strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname));
471146985Sthompsa
472146985Sthompsa	ea = ether_aton(mac);
473146985Sthompsa	if (ea == NULL)
474146985Sthompsa		errx(1, "%s: invalid address: %s", val, mac);
475146985Sthompsa
476146985Sthompsa	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
477146985Sthompsa	req.ifba_flags = IFBAF_STATIC;
478170681Sthompsa	req.ifba_vlan = 1; /* XXX allow user to specify */
479146985Sthompsa
480146985Sthompsa	if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0)
481146985Sthompsa		err(1, "BRDGSADDR %s",  val);
482146985Sthompsa}
483146985Sthompsa
484146985Sthompsastatic void
485146985Sthompsasetbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp)
486146985Sthompsa{
487146985Sthompsa	struct ifbareq req;
488146985Sthompsa	struct ether_addr *ea;
489146985Sthompsa
490146985Sthompsa	memset(&req, 0, sizeof(req));
491146985Sthompsa
492146985Sthompsa	ea = ether_aton(val);
493146985Sthompsa	if (ea == NULL)
494146985Sthompsa		errx(1, "invalid address: %s",  val);
495146985Sthompsa
496146985Sthompsa	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
497146985Sthompsa
498146985Sthompsa	if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0)
499146985Sthompsa		err(1, "BRDGDADDR %s",  val);
500146985Sthompsa}
501146985Sthompsa
502146985Sthompsastatic void
503146985Sthompsasetbridge_addr(const char *val, int d, int s, const struct afswtch *afp)
504146985Sthompsa{
505146985Sthompsa
506146985Sthompsa	bridge_addresses(s, "");
507146985Sthompsa}
508146985Sthompsa
509146985Sthompsastatic void
510146985Sthompsasetbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
511146985Sthompsa{
512146985Sthompsa	struct ifbrparam param;
513146985Sthompsa	u_long val;
514146985Sthompsa
515146985Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
516146985Sthompsa		errx(1, "invalid value: %s",  arg);
517146985Sthompsa
518146985Sthompsa	param.ifbrp_csize = val & 0xffffffff;
519146985Sthompsa
520146985Sthompsa	if (do_cmd(s, BRDGSCACHE, &param, sizeof(param), 1) < 0)
521146985Sthompsa		err(1, "BRDGSCACHE %s",  arg);
522146985Sthompsa}
523146985Sthompsa
524146985Sthompsastatic void
525146985Sthompsasetbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
526146985Sthompsa{
527146985Sthompsa	struct ifbrparam param;
528146985Sthompsa	u_long val;
529146985Sthompsa
530146985Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
531146985Sthompsa		errx(1, "invalid value: %s",  arg);
532146985Sthompsa
533146985Sthompsa	param.ifbrp_hellotime = val & 0xff;
534146985Sthompsa
535146985Sthompsa	if (do_cmd(s, BRDGSHT, &param, sizeof(param), 1) < 0)
536146985Sthompsa		err(1, "BRDGSHT %s",  arg);
537146985Sthompsa}
538146985Sthompsa
539146985Sthompsastatic void
540146985Sthompsasetbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
541146985Sthompsa{
542146985Sthompsa	struct ifbrparam param;
543146985Sthompsa	u_long val;
544146985Sthompsa
545146985Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
546146985Sthompsa		errx(1, "invalid value: %s",  arg);
547146985Sthompsa
548146985Sthompsa	param.ifbrp_fwddelay = val & 0xff;
549146985Sthompsa
550146985Sthompsa	if (do_cmd(s, BRDGSFD, &param, sizeof(param), 1) < 0)
551146985Sthompsa		err(1, "BRDGSFD %s",  arg);
552146985Sthompsa}
553146985Sthompsa
554146985Sthompsastatic void
555146985Sthompsasetbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
556146985Sthompsa{
557146985Sthompsa	struct ifbrparam param;
558146985Sthompsa	u_long val;
559146985Sthompsa
560146985Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
561146985Sthompsa		errx(1, "invalid value: %s",  arg);
562146985Sthompsa
563146985Sthompsa	param.ifbrp_maxage = val & 0xff;
564146985Sthompsa
565146985Sthompsa	if (do_cmd(s, BRDGSMA, &param, sizeof(param), 1) < 0)
566146985Sthompsa		err(1, "BRDGSMA %s",  arg);
567146985Sthompsa}
568146985Sthompsa
569146985Sthompsastatic void
570146985Sthompsasetbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
571146985Sthompsa{
572146985Sthompsa	struct ifbrparam param;
573146985Sthompsa	u_long val;
574146985Sthompsa
575146985Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0)
576146985Sthompsa		errx(1, "invalid value: %s",  arg);
577146985Sthompsa
578146985Sthompsa	param.ifbrp_prio = val & 0xffff;
579146985Sthompsa
580146985Sthompsa	if (do_cmd(s, BRDGSPRI, &param, sizeof(param), 1) < 0)
581146985Sthompsa		err(1, "BRDGSPRI %s",  arg);
582146985Sthompsa}
583146985Sthompsa
584146985Sthompsastatic void
585163863Sthompsasetbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
586163863Sthompsa{
587163863Sthompsa	struct ifbrparam param;
588163863Sthompsa
589163863Sthompsa	if (strcasecmp(arg, "stp") == 0) {
590163863Sthompsa		param.ifbrp_proto = 0;
591163863Sthompsa	} else if (strcasecmp(arg, "rstp") == 0) {
592163863Sthompsa		param.ifbrp_proto = 2;
593163863Sthompsa	} else {
594163863Sthompsa		errx(1, "unknown stp protocol");
595163863Sthompsa	}
596163863Sthompsa
597163863Sthompsa	if (do_cmd(s, BRDGSPROTO, &param, sizeof(param), 1) < 0)
598163863Sthompsa		err(1, "BRDGSPROTO %s",  arg);
599163863Sthompsa}
600163863Sthompsa
601163863Sthompsastatic void
602163863Sthompsasetbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
603163863Sthompsa{
604163863Sthompsa	struct ifbrparam param;
605163863Sthompsa	u_long val;
606163863Sthompsa
607163863Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
608163863Sthompsa		errx(1, "invalid value: %s",  arg);
609163863Sthompsa
610163863Sthompsa	param.ifbrp_txhc = val & 0xff;
611163863Sthompsa
612163863Sthompsa	if (do_cmd(s, BRDGSTXHC, &param, sizeof(param), 1) < 0)
613163863Sthompsa		err(1, "BRDGSTXHC %s",  arg);
614163863Sthompsa}
615163863Sthompsa
616163863Sthompsastatic void
617146985Sthompsasetbridge_ifpriority(const char *ifn, const char *pri, int s,
618146985Sthompsa    const struct afswtch *afp)
619146985Sthompsa{
620146985Sthompsa	struct ifbreq req;
621146985Sthompsa	u_long val;
622146985Sthompsa
623146985Sthompsa	memset(&req, 0, sizeof(req));
624146985Sthompsa
625146985Sthompsa	if (get_val(pri, &val) < 0 || (val & ~0xff) != 0)
626146985Sthompsa		errx(1, "invalid value: %s",  pri);
627146985Sthompsa
628146985Sthompsa	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
629146985Sthompsa	req.ifbr_priority = val & 0xff;
630146985Sthompsa
631146985Sthompsa	if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
632146985Sthompsa		err(1, "BRDGSIFPRIO %s",  pri);
633146985Sthompsa}
634146985Sthompsa
635146985Sthompsastatic void
636146985Sthompsasetbridge_ifpathcost(const char *ifn, const char *cost, int s,
637146985Sthompsa    const struct afswtch *afp)
638146985Sthompsa{
639146985Sthompsa	struct ifbreq req;
640146985Sthompsa	u_long val;
641146985Sthompsa
642146985Sthompsa	memset(&req, 0, sizeof(req));
643146985Sthompsa
644163863Sthompsa	if (get_val(cost, &val) < 0)
645146985Sthompsa		errx(1, "invalid value: %s",  cost);
646146985Sthompsa
647146985Sthompsa	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
648163863Sthompsa	req.ifbr_path_cost = val;
649146985Sthompsa
650146985Sthompsa	if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
651146985Sthompsa		err(1, "BRDGSIFCOST %s",  cost);
652146985Sthompsa}
653146985Sthompsa
654146985Sthompsastatic void
655173320Sthompsasetbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
656173320Sthompsa    const struct afswtch *afp)
657173320Sthompsa{
658173320Sthompsa	struct ifbreq req;
659173320Sthompsa	u_long val;
660173320Sthompsa
661173320Sthompsa	memset(&req, 0, sizeof(req));
662173320Sthompsa
663173320Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
664173320Sthompsa		errx(1, "invalid value: %s",  arg);
665173320Sthompsa
666173320Sthompsa	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
667173320Sthompsa	req.ifbr_addrmax = val & 0xffffffff;
668173320Sthompsa
669173320Sthompsa	if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
670173320Sthompsa		err(1, "BRDGSIFAMAX %s",  arg);
671173320Sthompsa}
672173320Sthompsa
673173320Sthompsastatic void
674146985Sthompsasetbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
675146985Sthompsa{
676146985Sthompsa	struct ifbrparam param;
677146985Sthompsa	u_long val;
678146985Sthompsa
679146985Sthompsa	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
680146985Sthompsa		errx(1, "invalid value: %s",  arg);
681146985Sthompsa
682146985Sthompsa	param.ifbrp_ctime = val & 0xffffffff;
683146985Sthompsa
684146985Sthompsa	if (do_cmd(s, BRDGSTO, &param, sizeof(param), 1) < 0)
685146985Sthompsa		err(1, "BRDGSTO %s",  arg);
686146985Sthompsa}
687146985Sthompsa
688171678Sthompsastatic void
689171678Sthompsasetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
690171678Sthompsa{
691171678Sthompsa
692171678Sthompsa	do_bridgeflag(s, val, IFBIF_PRIVATE, 1);
693171678Sthompsa}
694171678Sthompsa
695171678Sthompsastatic void
696171678Sthompsaunsetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
697171678Sthompsa{
698171678Sthompsa
699171678Sthompsa	do_bridgeflag(s, val, IFBIF_PRIVATE, 0);
700171678Sthompsa}
701171678Sthompsa
702146985Sthompsastatic struct cmd bridge_cmds[] = {
703146985Sthompsa	DEF_CMD_ARG("addm",		setbridge_add),
704146985Sthompsa	DEF_CMD_ARG("deletem",		setbridge_delete),
705146985Sthompsa	DEF_CMD_ARG("discover",		setbridge_discover),
706146985Sthompsa	DEF_CMD_ARG("-discover",	unsetbridge_discover),
707146985Sthompsa	DEF_CMD_ARG("learn",		setbridge_learn),
708146985Sthompsa	DEF_CMD_ARG("-learn",		unsetbridge_learn),
709164112Sthompsa	DEF_CMD_ARG("sticky",		setbridge_sticky),
710164112Sthompsa	DEF_CMD_ARG("-sticky",		unsetbridge_sticky),
711153408Sthompsa	DEF_CMD_ARG("span",		setbridge_span),
712153408Sthompsa	DEF_CMD_ARG("-span",		unsetbridge_span),
713146985Sthompsa	DEF_CMD_ARG("stp",		setbridge_stp),
714146985Sthompsa	DEF_CMD_ARG("-stp",		unsetbridge_stp),
715163863Sthompsa	DEF_CMD_ARG("edge",		setbridge_edge),
716163863Sthompsa	DEF_CMD_ARG("-edge",		unsetbridge_edge),
717163863Sthompsa	DEF_CMD_ARG("autoedge",		setbridge_autoedge),
718163863Sthompsa	DEF_CMD_ARG("-autoedge",	unsetbridge_autoedge),
719165105Sthompsa	DEF_CMD_ARG("ptp",		setbridge_ptp),
720165105Sthompsa	DEF_CMD_ARG("-ptp",		unsetbridge_ptp),
721165105Sthompsa	DEF_CMD_ARG("autoptp",		setbridge_autoptp),
722165105Sthompsa	DEF_CMD_ARG("-autoptp",		unsetbridge_autoptp),
723146985Sthompsa	DEF_CMD("flush", 0,		setbridge_flush),
724146985Sthompsa	DEF_CMD("flushall", 0,		setbridge_flushall),
725146985Sthompsa	DEF_CMD_ARG2("static",		setbridge_static),
726146985Sthompsa	DEF_CMD_ARG("deladdr",		setbridge_deladdr),
727146985Sthompsa	DEF_CMD("addr",	 1,		setbridge_addr),
728146985Sthompsa	DEF_CMD_ARG("maxaddr",		setbridge_maxaddr),
729146985Sthompsa	DEF_CMD_ARG("hellotime",	setbridge_hellotime),
730146985Sthompsa	DEF_CMD_ARG("fwddelay",		setbridge_fwddelay),
731146985Sthompsa	DEF_CMD_ARG("maxage",		setbridge_maxage),
732146985Sthompsa	DEF_CMD_ARG("priority",		setbridge_priority),
733163863Sthompsa	DEF_CMD_ARG("proto",		setbridge_protocol),
734164688Sthompsa	DEF_CMD_ARG("holdcnt",		setbridge_holdcount),
735146985Sthompsa	DEF_CMD_ARG2("ifpriority",	setbridge_ifpriority),
736146985Sthompsa	DEF_CMD_ARG2("ifpathcost",	setbridge_ifpathcost),
737173320Sthompsa	DEF_CMD_ARG2("ifmaxaddr",	setbridge_ifmaxaddr),
738146985Sthompsa	DEF_CMD_ARG("timeout",		setbridge_timeout),
739171678Sthompsa	DEF_CMD_ARG("private",		setbridge_private),
740171678Sthompsa	DEF_CMD_ARG("-private",		unsetbridge_private),
741146985Sthompsa};
742146985Sthompsastatic struct afswtch af_bridge = {
743146985Sthompsa	.af_name	= "af_bridge",
744146985Sthompsa	.af_af		= AF_UNSPEC,
745146985Sthompsa	.af_other_status = bridge_status,
746146985Sthompsa};
747146985Sthompsa
748146985Sthompsastatic __constructor void
749146985Sthompsabridge_ctor(void)
750146985Sthompsa{
751146985Sthompsa	int i;
752146985Sthompsa
753288305Sngie	for (i = 0; i < nitems(bridge_cmds);  i++)
754146985Sthompsa		cmd_register(&bridge_cmds[i]);
755146985Sthompsa	af_register(&af_bridge);
756146985Sthompsa}
757