1/*
2 * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*-
30 * Copyright 2001 Wasabi Systems, Inc.
31 * All rights reserved.
32 *
33 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 *    must display the following acknowledgement:
45 *	This product includes software developed for the NetBSD Project by
46 *	Wasabi Systems, Inc.
47 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
48 *    or promote products derived from this software without specific prior
49 *    written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
62 */
63
64#include <sys/param.h>
65#include <sys/ioctl.h>
66#include <sys/socket.h>
67#include <sys/sockio.h>
68
69#include <stdlib.h>
70#include <unistd.h>
71
72#include <net/ethernet.h>
73#include <net/if.h>
74#include <net/if_bridgevar.h>
75#include <net/route.h>
76
77#include <ctype.h>
78#include <stdio.h>
79#include <string.h>
80#include <stdlib.h>
81#include <unistd.h>
82#include <err.h>
83#include <errno.h>
84
85#include "ifconfig.h"
86
87#define PV2ID(pv, epri, eaddr)  do {		\
88		epri     = pv >> 48;		\
89		eaddr[0] = pv >> 40;		\
90		eaddr[1] = pv >> 32;		\
91		eaddr[2] = pv >> 24;		\
92		eaddr[3] = pv >> 16;		\
93		eaddr[4] = pv >> 8;		\
94		eaddr[5] = pv >> 0;		\
95} while (0)
96
97static const char *stpstates[] = {
98	"disabled",
99	"listening",
100	"learning",
101	"forwarding",
102	"blocking",
103	"discarding"
104};
105static const char *stpproto[] = {
106	"stp",
107	"-",
108	"rstp"
109};
110static const char *stproles[] = {
111	"disabled",
112	"root",
113	"designated",
114	"alternate",
115	"backup"
116};
117
118static int
119get_val(const char *cp, u_long *valp)
120{
121	char *endptr;
122	u_long val;
123
124	errno = 0;
125	val = strtoul(cp, &endptr, 0);
126	if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
127		return (-1);
128
129	*valp = val;
130	return (0);
131}
132
133static int
134do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
135{
136	struct ifdrv ifd;
137
138	memset(&ifd, 0, sizeof(ifd));
139
140	strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
141	ifd.ifd_cmd = op;
142	ifd.ifd_len = argsize;
143	ifd.ifd_data = arg;
144
145	return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
146}
147
148static void
149do_bridgeflag(int sock, const char *ifs, int flag, int set)
150{
151	struct ifbreq req;
152
153	strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname));
154
155	if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0)
156		err(1, "unable to get bridge flags");
157
158	if (set)
159		req.ifbr_ifsflags |= flag;
160	else
161		req.ifbr_ifsflags &= ~flag;
162
163	if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0)
164		err(1, "unable to set bridge flags");
165}
166
167static void
168bridge_interfaces(int s, const char *prefix)
169{
170	struct ifbifconf bifc;
171	struct ifbreq *req;
172	char *inbuf = NULL, *ninbuf;
173	char *p, *pad;
174	int i, len = 8192;
175
176	pad = strdup(prefix);
177	if (pad == NULL)
178		err(1, "strdup");
179	/* replace the prefix with whitespace */
180	for (p = pad; *p != '\0'; p++) {
181		if(isprint(*p))
182			*p = ' ';
183	}
184
185	for (;;) {
186		ninbuf = realloc(inbuf, len);
187		if (ninbuf == NULL)
188			err(1, "unable to allocate interface buffer");
189		bifc.ifbic_len = len;
190		bifc.ifbic_buf = inbuf = ninbuf;
191		if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0)
192			err(1, "unable to get interface list");
193		if ((bifc.ifbic_len + sizeof(*req)) < len)
194			break;
195		len *= 2;
196	}
197
198	for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) {
199		req = bifc.ifbic_req + i;
200		printf("%s%s ", prefix, req->ifbr_ifsname);
201		printb("flags", req->ifbr_ifsflags, IFBIFBITS);
202		printf("\n");
203
204		printf("%s", pad);
205		printf("ifmaxaddr %u", req->ifbr_addrmax);
206		printf(" port %u priority %u", req->ifbr_portno,
207		    req->ifbr_priority);
208		printf(" path cost %u", req->ifbr_path_cost);
209
210		if (req->ifbr_ifsflags & IFBIF_STP) {
211			if (req->ifbr_proto <
212			    sizeof(stpproto) / sizeof(stpproto[0]))
213				printf(" proto %s", stpproto[req->ifbr_proto]);
214			else
215				printf(" <unknown proto %d>",
216				    req->ifbr_proto);
217
218			printf("\n%s", pad);
219			if (req->ifbr_role <
220			    sizeof(stproles) / sizeof(stproles[0]))
221				printf("role %s", stproles[req->ifbr_role]);
222			else
223				printf("<unknown role %d>",
224				    req->ifbr_role);
225			if (req->ifbr_state <
226			    sizeof(stpstates) / sizeof(stpstates[0]))
227				printf(" state %s", stpstates[req->ifbr_state]);
228			else
229				printf(" <unknown state %d>",
230				    req->ifbr_state);
231		}
232		printf("\n");
233	}
234
235	free(inbuf);
236}
237
238static void
239bridge_addresses(int s, const char *prefix)
240{
241	struct ifbaconf ifbac;
242	struct ifbareq *ifba;
243	char *inbuf = NULL, *ninbuf;
244	int i, len = 8192;
245	struct ether_addr ea;
246
247	for (;;) {
248		ninbuf = realloc(inbuf, len);
249		if (ninbuf == NULL)
250			err(1, "unable to allocate address buffer");
251		ifbac.ifbac_len = len;
252		ifbac.ifbac_buf = inbuf = ninbuf;
253		if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0)
254			err(1, "unable to get address cache");
255		if ((ifbac.ifbac_len + sizeof(*ifba)) < len)
256			break;
257		len *= 2;
258	}
259
260	for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
261		ifba = ifbac.ifbac_req + i;
262		memcpy(ea.octet, ifba->ifba_dst,
263		    sizeof(ea.octet));
264		printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea),
265		    ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire);
266		printb("flags", ifba->ifba_flags, IFBAFBITS);
267		printf("\n");
268	}
269
270	free(inbuf);
271}
272
273static void
274bridge_status(int s)
275{
276	struct ifbropreq ifbp;
277	struct ifbrparam param;
278	u_int16_t pri;
279	u_int8_t ht, fd, ma, hc, pro;
280	u_int8_t lladdr[ETHER_ADDR_LEN];
281	u_int16_t bprio;
282	u_int32_t csize, ctime;
283	u_int32_t ipfflags;
284
285	if (do_cmd(s, BRDGGCACHE, &param, sizeof(param), 0) < 0)
286		return;
287	csize = param.ifbrp_csize;
288	if (do_cmd(s, BRDGGTO, &param, sizeof(param), 0) < 0)
289		return;
290	ctime = param.ifbrp_ctime;
291	if (do_cmd(s, BRDGGFILT, &param, sizeof(param), 0) < 0)
292		return;
293	ipfflags = param.ifbrp_filter;
294	if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0)
295		return;
296	pri = ifbp.ifbop_priority;
297	pro = ifbp.ifbop_protocol;
298	ht = ifbp.ifbop_hellotime;
299	fd = ifbp.ifbop_fwddelay;
300	hc = ifbp.ifbop_holdcount;
301	ma = ifbp.ifbop_maxage;
302
303	printf("\tConfiguration:\n");
304	PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr);
305	printf("\t\tid %s priority %u hellotime %u fwddelay %u\n",
306	    ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd);
307	printf("\t\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n",
308	    ma, hc, stpproto[pro], csize, ctime);
309
310	PV2ID(ifbp.ifbop_designated_root, bprio, lladdr);
311	printf("\t\troot id %s priority %d ifcost %u port %u\n",
312	    ether_ntoa((struct ether_addr *)lladdr), bprio,
313	    ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff);
314
315	printf("\t\tipfilter %s flags 0x%x\n",
316	   (ipfflags & IFBF_FILT_USEIPF) ? "enabled" : "disabled", ipfflags);
317
318	bridge_interfaces(s, "\tmember: ");
319
320	if (!all || verbose > 1) {
321		printf("\tAddress cache:\n");
322		bridge_addresses(s, "\t\t");
323	}
324	return;
325
326}
327
328static void
329setbridge_add(const char *val, int d, int s, const struct afswtch *afp)
330{
331	struct ifbreq req;
332
333	memset(&req, 0, sizeof(req));
334	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
335	if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0)
336		err(1, "BRDGADD %s",  val);
337}
338
339static void
340setbridge_delete(const char *val, int d, int s, const struct afswtch *afp)
341{
342	struct ifbreq req;
343
344	memset(&req, 0, sizeof(req));
345	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
346	if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0)
347		err(1, "BRDGDEL %s",  val);
348}
349
350static void
351setbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
352{
353
354	do_bridgeflag(s, val, IFBIF_DISCOVER, 1);
355}
356
357static void
358unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
359{
360
361	do_bridgeflag(s, val, IFBIF_DISCOVER, 0);
362}
363
364static void
365setbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
366{
367
368	do_bridgeflag(s, val, IFBIF_LEARNING,  1);
369}
370
371static void
372unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
373{
374
375	do_bridgeflag(s, val, IFBIF_LEARNING,  0);
376}
377
378#ifdef notdef
379static void
380setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
381{
382
383	do_bridgeflag(s, val, IFBIF_STICKY,  1);
384}
385
386static void
387unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
388{
389
390	do_bridgeflag(s, val, IFBIF_STICKY,  0);
391}
392
393static void
394setbridge_span(const char *val, int d, int s, const struct afswtch *afp)
395{
396	struct ifbreq req;
397
398	memset(&req, 0, sizeof(req));
399	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
400	if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0)
401		err(1, "BRDGADDS %s",  val);
402}
403
404static void
405unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp)
406{
407	struct ifbreq req;
408
409	memset(&req, 0, sizeof(req));
410	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
411	if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0)
412		err(1, "BRDGDELS %s",  val);
413}
414#endif
415
416static void
417setbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
418{
419
420	do_bridgeflag(s, val, IFBIF_STP, 1);
421}
422
423static void
424unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
425{
426
427	do_bridgeflag(s, val, IFBIF_STP, 0);
428}
429
430#ifdef notdef
431static void
432setbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
433{
434	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
435}
436
437static void
438unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
439{
440	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
441}
442
443static void
444setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
445{
446	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
447}
448
449static void
450unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
451{
452	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
453}
454
455static void
456setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
457{
458	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1);
459}
460
461static void
462unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
463{
464	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0);
465}
466
467static void
468setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
469{
470	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1);
471}
472
473static void
474unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
475{
476	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0);
477}
478#endif
479
480static void
481setbridge_flush(const char *val, int d, int s, const struct afswtch *afp)
482{
483	struct ifbreq req;
484
485	memset(&req, 0, sizeof(req));
486	req.ifbr_ifsflags = IFBF_FLUSHDYN;
487	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
488		err(1, "BRDGFLUSH");
489}
490
491static void
492setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp)
493{
494	struct ifbreq req;
495
496	memset(&req, 0, sizeof(req));
497	req.ifbr_ifsflags = IFBF_FLUSHALL;
498	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
499		err(1, "BRDGFLUSH");
500}
501
502static void
503setbridge_static(const char *val, const char *mac, int s,
504    const struct afswtch *afp)
505{
506	struct ifbareq req;
507	struct ether_addr *ea;
508
509	memset(&req, 0, sizeof(req));
510	strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname));
511
512	ea = ether_aton(mac);
513	if (ea == NULL)
514		errx(1, "%s: invalid address: %s", val, mac);
515
516	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
517	req.ifba_flags = IFBAF_STATIC;
518	req.ifba_vlan = 1; /* XXX allow user to specify */
519
520	if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0)
521		err(1, "BRDGSADDR %s",  val);
522}
523
524static void
525setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp)
526{
527	struct ifbareq req;
528	struct ether_addr *ea;
529
530	memset(&req, 0, sizeof(req));
531
532	ea = ether_aton(val);
533	if (ea == NULL)
534		errx(1, "invalid address: %s",  val);
535
536	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
537
538	if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0)
539		err(1, "BRDGDADDR %s",  val);
540}
541
542static void
543setbridge_addr(const char *val, int d, int s, const struct afswtch *afp)
544{
545
546	bridge_addresses(s, "");
547}
548
549static void
550setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
551{
552	struct ifbrparam param;
553	u_long val;
554
555	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
556		errx(1, "invalid value: %s",  arg);
557
558	param.ifbrp_csize = val & 0xffffffff;
559
560	if (do_cmd(s, BRDGSCACHE, &param, sizeof(param), 1) < 0)
561		err(1, "BRDGSCACHE %s",  arg);
562}
563
564static void
565setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
566{
567	struct ifbrparam param;
568	u_long val;
569
570	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
571		errx(1, "invalid value: %s",  arg);
572
573	param.ifbrp_hellotime = val & 0xff;
574
575	if (do_cmd(s, BRDGSHT, &param, sizeof(param), 1) < 0)
576		err(1, "BRDGSHT %s",  arg);
577}
578
579static void
580setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
581{
582	struct ifbrparam param;
583	u_long val;
584
585	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
586		errx(1, "invalid value: %s",  arg);
587
588	param.ifbrp_fwddelay = val & 0xff;
589
590	if (do_cmd(s, BRDGSFD, &param, sizeof(param), 1) < 0)
591		err(1, "BRDGSFD %s",  arg);
592}
593
594static void
595setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
596{
597	struct ifbrparam param;
598	u_long val;
599
600	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
601		errx(1, "invalid value: %s",  arg);
602
603	param.ifbrp_maxage = val & 0xff;
604
605	if (do_cmd(s, BRDGSMA, &param, sizeof(param), 1) < 0)
606		err(1, "BRDGSMA %s",  arg);
607}
608
609static void
610setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
611{
612	struct ifbrparam param;
613	u_long val;
614
615	if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0)
616		errx(1, "invalid value: %s",  arg);
617
618	param.ifbrp_prio = val & 0xffff;
619
620	if (do_cmd(s, BRDGSPRI, &param, sizeof(param), 1) < 0)
621		err(1, "BRDGSPRI %s",  arg);
622}
623
624#ifdef notdef
625static void
626setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
627{
628	struct ifbrparam param;
629
630	if (strcasecmp(arg, "stp") == 0) {
631		param.ifbrp_proto = 0;
632	} else if (strcasecmp(arg, "rstp") == 0) {
633		param.ifbrp_proto = 2;
634	} else {
635		errx(1, "unknown stp protocol");
636	}
637
638	if (do_cmd(s, BRDGSPROTO, &param, sizeof(param), 1) < 0)
639		err(1, "BRDGSPROTO %s",  arg);
640}
641
642static void
643setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
644{
645	struct ifbrparam param;
646	u_long val;
647
648	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
649		errx(1, "invalid value: %s",  arg);
650
651	param.ifbrp_txhc = val & 0xff;
652
653	if (do_cmd(s, BRDGSTXHC, &param, sizeof(param), 1) < 0)
654		err(1, "BRDGSTXHC %s",  arg);
655}
656#endif
657
658static void
659setbridge_ifpriority(const char *ifn, const char *pri, int s,
660    const struct afswtch *afp)
661{
662	struct ifbreq req;
663	u_long val;
664
665	memset(&req, 0, sizeof(req));
666
667	if (get_val(pri, &val) < 0 || (val & ~0xff) != 0)
668		errx(1, "invalid value: %s",  pri);
669
670	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
671	req.ifbr_priority = val & 0xff;
672
673	if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
674		err(1, "BRDGSIFPRIO %s",  pri);
675}
676
677static void
678setbridge_ifpathcost(const char *ifn, const char *cost, int s,
679    const struct afswtch *afp)
680{
681	struct ifbreq req;
682	u_long val;
683
684	memset(&req, 0, sizeof(req));
685
686	if (get_val(cost, &val) < 0)
687		errx(1, "invalid value: %s",  cost);
688
689	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
690	req.ifbr_path_cost = val;
691
692	if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
693		err(1, "BRDGSIFCOST %s",  cost);
694}
695
696#ifdef notdef
697static void
698setbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
699    const struct afswtch *afp)
700{
701	struct ifbreq req;
702	u_long val;
703
704	memset(&req, 0, sizeof(req));
705
706	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
707		errx(1, "invalid value: %s",  arg);
708
709	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
710	req.ifbr_addrmax = val & 0xffffffff;
711
712	if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
713		err(1, "BRDGSIFAMAX %s",  arg);
714}
715#endif
716
717static void
718setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
719{
720	struct ifbrparam param;
721	u_long val;
722
723	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
724		errx(1, "invalid value: %s",  arg);
725
726	param.ifbrp_ctime = val & 0xffffffff;
727
728	if (do_cmd(s, BRDGSTO, &param, sizeof(param), 1) < 0)
729		err(1, "BRDGSTO %s",  arg);
730}
731
732#ifdef notdef
733static void
734setbridge_private(const char *val, int d, int s, const struct afswtch *afp)
735{
736
737	do_bridgeflag(s, val, IFBIF_PRIVATE, 1);
738}
739
740static void
741unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
742{
743
744	do_bridgeflag(s, val, IFBIF_PRIVATE, 0);
745}
746#endif
747
748static struct cmd bridge_cmds[] = {
749	DEF_CMD_ARG("addm",		setbridge_add),
750	DEF_CMD_ARG("deletem",		setbridge_delete),
751	DEF_CMD_ARG("discover",		setbridge_discover),
752	DEF_CMD_ARG("-discover",	unsetbridge_discover),
753	DEF_CMD_ARG("learn",		setbridge_learn),
754	DEF_CMD_ARG("-learn",		unsetbridge_learn),
755#ifdef notdef
756	DEF_CMD_ARG("sticky",		setbridge_sticky),
757	DEF_CMD_ARG("-sticky",		unsetbridge_sticky),
758	DEF_CMD_ARG("span",		setbridge_span),
759	DEF_CMD_ARG("-span",		unsetbridge_span),
760#endif
761	DEF_CMD_ARG("stp",		setbridge_stp),
762	DEF_CMD_ARG("-stp",		unsetbridge_stp),
763#ifdef notdef
764	DEF_CMD_ARG("edge",		setbridge_edge),
765	DEF_CMD_ARG("-edge",		unsetbridge_edge),
766	DEF_CMD_ARG("autoedge",		setbridge_autoedge),
767	DEF_CMD_ARG("-autoedge",	unsetbridge_autoedge),
768	DEF_CMD_ARG("ptp",		setbridge_ptp),
769	DEF_CMD_ARG("-ptp",		unsetbridge_ptp),
770	DEF_CMD_ARG("autoptp",		setbridge_autoptp),
771	DEF_CMD_ARG("-autoptp",		unsetbridge_autoptp),
772#endif
773	DEF_CMD("flush", 0,		setbridge_flush),
774	DEF_CMD("flushall", 0,		setbridge_flushall),
775	DEF_CMD_ARG2("static",		setbridge_static),
776	DEF_CMD_ARG("deladdr",		setbridge_deladdr),
777	DEF_CMD("addr",	 1,		setbridge_addr),
778	DEF_CMD_ARG("maxaddr",		setbridge_maxaddr),
779	DEF_CMD_ARG("hellotime",	setbridge_hellotime),
780	DEF_CMD_ARG("fwddelay",		setbridge_fwddelay),
781	DEF_CMD_ARG("maxage",		setbridge_maxage),
782	DEF_CMD_ARG("priority",		setbridge_priority),
783#ifdef notdef
784	DEF_CMD_ARG("proto",		setbridge_protocol),
785	DEF_CMD_ARG("holdcnt",		setbridge_holdcount),
786#endif
787	DEF_CMD_ARG2("ifpriority",	setbridge_ifpriority),
788	DEF_CMD_ARG2("ifpathcost",	setbridge_ifpathcost),
789#ifdef notdef
790	DEF_CMD_ARG2("ifmaxaddr",	setbridge_ifmaxaddr),
791#endif
792	DEF_CMD_ARG("timeout",		setbridge_timeout),
793#ifdef notdef
794	DEF_CMD_ARG("private",		setbridge_private),
795	DEF_CMD_ARG("-private",		unsetbridge_private),
796#endif
797};
798static struct afswtch af_bridge = {
799	.af_name	= "af_bridge",
800	.af_af		= AF_UNSPEC,
801	.af_other_status = bridge_status,
802};
803
804static __constructor void
805bridge_ctor(void)
806{
807#define	N(a)	(sizeof(a) / sizeof(a[0]))
808	int i;
809
810	for (i = 0; i < N(bridge_cmds);  i++)
811		cmd_register(&bridge_cmds[i]);
812	af_register(&af_bridge);
813#undef N
814}
815