]>
git.saurik.com Git - apple/network_cmds.git/blob - ifconfig.tproj/ifbridge.c
2 * Copyright (c) 2009-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright 2001 Wasabi Systems, Inc.
31 * All rights reserved.
33 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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
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.
64 #include <sys/param.h>
65 #include <sys/ioctl.h>
66 #include <sys/socket.h>
67 #include <sys/sockio.h>
72 #include <net/ethernet.h>
74 #include <net/if_bridgevar.h>
75 #include <net/route.h>
85 #include <arpa/inet.h>
89 #define PV2ID(pv, epri, eaddr) do { \
91 eaddr[0] = pv >> 40; \
92 eaddr[1] = pv >> 32; \
93 eaddr[2] = pv >> 24; \
94 eaddr[3] = pv >> 16; \
99 static const char *stpstates
[] = {
107 static const char *stpproto
[] = {
112 static const char *stproles
[] = {
121 get_val(const char *cp
, u_long
*valp
)
127 val
= strtoul(cp
, &endptr
, 0);
128 if (cp
[0] == '\0' || endptr
[0] != '\0' || errno
== ERANGE
)
136 do_cmd(int sock
, u_long op
, void *arg
, size_t argsize
, int set
)
140 memset(&ifd
, 0, sizeof(ifd
));
142 strlcpy(ifd
.ifd_name
, ifr
.ifr_name
, sizeof(ifd
.ifd_name
));
144 ifd
.ifd_len
= argsize
;
147 return (ioctl(sock
, set
? SIOCSDRVSPEC
: SIOCGDRVSPEC
, &ifd
));
151 do_bridgeflag(int sock
, const char *ifs
, int flag
, int set
)
155 strlcpy(req
.ifbr_ifsname
, ifs
, sizeof(req
.ifbr_ifsname
));
157 if (do_cmd(sock
, BRDGGIFFLGS
, &req
, sizeof(req
), 0) < 0)
158 err(1, "unable to get bridge flags");
161 req
.ifbr_ifsflags
|= flag
;
163 req
.ifbr_ifsflags
&= ~flag
;
165 if (do_cmd(sock
, BRDGSIFFLGS
, &req
, sizeof(req
), 1) < 0)
166 err(1, "unable to set bridge flags");
170 bridge_interfaces(int s
, const char *prefix
)
172 struct ifbifconf bifc
;
174 char *inbuf
= NULL
, *ninbuf
;
178 pad
= strdup(prefix
);
181 /* replace the prefix with whitespace */
182 for (p
= pad
; *p
!= '\0'; p
++) {
188 ninbuf
= realloc(inbuf
, len
);
190 err(1, "unable to allocate interface buffer");
191 bifc
.ifbic_len
= len
;
192 bifc
.ifbic_buf
= inbuf
= ninbuf
;
193 if (do_cmd(s
, BRDGGIFS
, &bifc
, sizeof(bifc
), 0) < 0)
194 err(1, "unable to get interface list");
195 if ((bifc
.ifbic_len
+ sizeof(*req
)) < len
)
200 for (i
= 0; i
< bifc
.ifbic_len
/ sizeof(*req
); i
++) {
201 req
= bifc
.ifbic_req
+ i
;
202 printf("%s%s ", prefix
, req
->ifbr_ifsname
);
203 printb("flags", req
->ifbr_ifsflags
, IFBIFBITS
);
207 printf("ifmaxaddr %u", req
->ifbr_addrmax
);
208 printf(" port %u priority %u", req
->ifbr_portno
,
210 printf(" path cost %u", req
->ifbr_path_cost
);
212 if (req
->ifbr_ifsflags
& IFBIF_STP
) {
213 if (req
->ifbr_proto
<
214 sizeof(stpproto
) / sizeof(stpproto
[0]))
215 printf(" proto %s", stpproto
[req
->ifbr_proto
]);
217 printf(" <unknown proto %d>",
222 sizeof(stproles
) / sizeof(stproles
[0]))
223 printf("role %s", stproles
[req
->ifbr_role
]);
225 printf("<unknown role %d>",
227 if (req
->ifbr_state
<
228 sizeof(stpstates
) / sizeof(stpstates
[0]))
229 printf(" state %s", stpstates
[req
->ifbr_state
]);
231 printf(" <unknown state %d>",
237 struct ifbrhostfilter ifbrfh
;
239 struct ether_addr ea
;
241 bzero(&ifbrfh
, sizeof(struct ifbrhostfilter
));
242 strlcpy(ifbrfh
.ifbrhf_ifsname
, req
->ifbr_ifsname
, sizeof(ifbrfh
.ifbrhf_ifsname
));
243 if (do_cmd(s
, BRDGGHOSTFILTER
, &ifbrfh
, sizeof(ifbrfh
), 0) < 0)
244 err(1, "unable to get host filter settings for %s",
245 ifbrfh
.ifbrhf_ifsname
);
247 if (ifbrfh
.ifbrhf_flags
& IFBRHF_ENABLED
) {
248 in
.s_addr
= ifbrfh
.ifbrhf_ipsrc
;
249 bcopy(ifbrfh
.ifbrhf_hwsrca
, ea
.octet
, ETHER_ADDR_LEN
);
251 in
.s_addr
= INADDR_ANY
;
252 bzero(ea
.octet
, ETHER_ADDR_LEN
);
255 printf("hostfilter %d hw: %s ip: %s",
256 ifbrfh
.ifbrhf_flags
& IFBRHF_ENABLED
? 1 : 0,
257 ether_ntoa(&ea
), inet_ntoa(in
));
268 bridge_addresses(int s
, const char *prefix
)
270 struct ifbaconf ifbac
;
271 struct ifbareq
*ifba
;
272 char *inbuf
= NULL
, *ninbuf
;
274 struct ether_addr ea
;
277 ninbuf
= realloc(inbuf
, len
);
279 err(1, "unable to allocate address buffer");
280 ifbac
.ifbac_len
= len
;
281 ifbac
.ifbac_buf
= inbuf
= ninbuf
;
282 if (do_cmd(s
, BRDGRTS
, &ifbac
, sizeof(ifbac
), 0) < 0)
283 err(1, "unable to get address cache");
284 if ((ifbac
.ifbac_len
+ sizeof(*ifba
)) < len
)
289 for (i
= 0; i
< ifbac
.ifbac_len
/ sizeof(*ifba
); i
++) {
290 ifba
= ifbac
.ifbac_req
+ i
;
291 memcpy(ea
.octet
, ifba
->ifba_dst
,
293 printf("%s%s Vlan%d %s %lu ", prefix
, ether_ntoa(&ea
),
294 ifba
->ifba_vlan
, ifba
->ifba_ifsname
, ifba
->ifba_expire
);
295 printb("flags", ifba
->ifba_flags
, IFBAFBITS
);
302 #define MAX_IPv6_STR_LEN INET6_ADDRSTRLEN
304 bridge_mac_nat(int s
, const char *prefix
)
308 struct ether_addr ea
;
310 struct ifbrmnelist mnl
;
313 bzero(&mnl
, sizeof(mnl
));
314 if (do_cmd(s
, BRDGGMACNATLIST
, &mnl
, sizeof(mnl
), 0) < 0) {
315 /* err(1, "unable to get mac nat list"); */
318 if (mnl
.ifbml_len
== 0) {
321 printf("\tMAC NAT list:\n");
322 if (mnl
.ifbml_elsize
== 0) {
323 err(1, "kernel reported zero length element size");
325 if (mnl
.ifbml_elsize
< sizeof(struct ifbrmne
)) {
326 err(1, "struct element size too small, kernel mismatch");
328 buf
= malloc(mnl
.ifbml_len
);
330 err(1, "unable to allocate mac nat list buffer");
333 if (do_cmd(s
, BRDGGMACNATLIST
, &mnl
, sizeof(mnl
), 0) < 0) {
334 err(1, "unable to get mac nat list");
336 count
= mnl
.ifbml_len
/ mnl
.ifbml_elsize
;
337 for (i
= 0, scan
= buf
; i
< count
; i
++, scan
+= mnl
.ifbml_elsize
) {
338 struct ifbrmne
*ifbmne
= (struct ifbrmne
*)scan
;
339 char ntopbuf
[INET6_ADDRSTRLEN
];
341 memcpy(ea
.octet
, ifbmne
->ifbmne_mac
,
343 inet_ntop(ifbmne
->ifbmne_af
, &ifbmne
->ifbmne_ip
,
344 ntopbuf
, sizeof(ntopbuf
));
345 printf("%s%s %s %s %lu\n",
346 prefix
, ifbmne
->ifbmne_ifname
, ntopbuf
, ether_ntoa(&ea
),
347 (unsigned long)ifbmne
->ifbmne_expire
);
355 struct ifbropreq ifbp
;
356 struct ifbrparam param
;
358 u_int8_t ht
, fd
, ma
, hc
, pro
;
359 u_int8_t lladdr
[ETHER_ADDR_LEN
];
361 u_int32_t csize
, ctime
;
364 if (do_cmd(s
, BRDGGCACHE
, ¶m
, sizeof(param
), 0) < 0)
366 csize
= param
.ifbrp_csize
;
367 if (do_cmd(s
, BRDGGTO
, ¶m
, sizeof(param
), 0) < 0)
369 ctime
= param
.ifbrp_ctime
;
370 if (do_cmd(s
, BRDGGFILT
, ¶m
, sizeof(param
), 0) < 0)
372 ipfflags
= param
.ifbrp_filter
;
373 if (do_cmd(s
, BRDGPARAM
, &ifbp
, sizeof(ifbp
), 0) < 0)
375 pri
= ifbp
.ifbop_priority
;
376 pro
= ifbp
.ifbop_protocol
;
377 ht
= ifbp
.ifbop_hellotime
;
378 fd
= ifbp
.ifbop_fwddelay
;
379 hc
= ifbp
.ifbop_holdcount
;
380 ma
= ifbp
.ifbop_maxage
;
382 printf("\tConfiguration:\n");
383 PV2ID(ifbp
.ifbop_bridgeid
, bprio
, lladdr
);
384 printf("\t\tid %s priority %u hellotime %u fwddelay %u\n",
385 ether_ntoa((struct ether_addr
*)lladdr
), pri
, ht
, fd
);
386 printf("\t\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n",
387 ma
, hc
, stpproto
[pro
], csize
, ctime
);
389 PV2ID(ifbp
.ifbop_designated_root
, bprio
, lladdr
);
390 printf("\t\troot id %s priority %d ifcost %u port %u\n",
391 ether_ntoa((struct ether_addr
*)lladdr
), bprio
,
392 ifbp
.ifbop_root_path_cost
, ifbp
.ifbop_root_port
& 0xfff);
394 printf("\t\tipfilter %s flags 0x%x\n",
395 (ipfflags
& IFBF_FILT_USEIPF
) ? "enabled" : "disabled", ipfflags
);
397 bridge_interfaces(s
, "\tmember: ");
399 if (!all
|| verbose
> 1) {
400 printf("\tAddress cache:\n");
401 bridge_addresses(s
, "\t\t");
402 bridge_mac_nat(s
, "\t\t");
409 setbridge_add(const char *val
, int d
, int s
, const struct afswtch
*afp
)
413 memset(&req
, 0, sizeof(req
));
414 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
415 if (do_cmd(s
, BRDGADD
, &req
, sizeof(req
), 1) < 0)
416 err(1, "BRDGADD %s", val
);
420 setbridge_delete(const char *val
, int d
, int s
, const struct afswtch
*afp
)
424 memset(&req
, 0, sizeof(req
));
425 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
426 if (do_cmd(s
, BRDGDEL
, &req
, sizeof(req
), 1) < 0)
427 err(1, "BRDGDEL %s", val
);
431 setbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
434 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 1);
438 unsetbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
441 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 0);
445 setbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
448 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 1);
452 unsetbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
455 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 0);
460 setbridge_sticky(const char *val
, int d
, int s
, const struct afswtch
*afp
)
463 do_bridgeflag(s
, val
, IFBIF_STICKY
, 1);
467 unsetbridge_sticky(const char *val
, int d
, int s
, const struct afswtch
*afp
)
470 do_bridgeflag(s
, val
, IFBIF_STICKY
, 0);
474 setbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
478 memset(&req
, 0, sizeof(req
));
479 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
480 if (do_cmd(s
, BRDGADDS
, &req
, sizeof(req
), 1) < 0)
481 err(1, "BRDGADDS %s", val
);
485 unsetbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
489 memset(&req
, 0, sizeof(req
));
490 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
491 if (do_cmd(s
, BRDGDELS
, &req
, sizeof(req
), 1) < 0)
492 err(1, "BRDGDELS %s", val
);
497 setbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
500 do_bridgeflag(s
, val
, IFBIF_STP
, 1);
504 unsetbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
507 do_bridgeflag(s
, val
, IFBIF_STP
, 0);
512 setbridge_edge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
514 do_bridgeflag(s
, val
, IFBIF_BSTP_EDGE
, 1);
518 unsetbridge_edge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
520 do_bridgeflag(s
, val
, IFBIF_BSTP_EDGE
, 0);
524 setbridge_autoedge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
526 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOEDGE
, 1);
530 unsetbridge_autoedge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
532 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOEDGE
, 0);
536 setbridge_ptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
538 do_bridgeflag(s
, val
, IFBIF_BSTP_PTP
, 1);
542 unsetbridge_ptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
544 do_bridgeflag(s
, val
, IFBIF_BSTP_PTP
, 0);
548 setbridge_autoptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
550 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOPTP
, 1);
554 unsetbridge_autoptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
556 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOPTP
, 0);
561 setbridge_flush(const char *val
, int d
, int s
, const struct afswtch
*afp
)
565 memset(&req
, 0, sizeof(req
));
566 req
.ifbr_ifsflags
= IFBF_FLUSHDYN
;
567 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
572 setbridge_flushall(const char *val
, int d
, int s
, const struct afswtch
*afp
)
576 memset(&req
, 0, sizeof(req
));
577 req
.ifbr_ifsflags
= IFBF_FLUSHALL
;
578 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
583 setbridge_static(const char *val
, const char *mac
, int s
,
584 const struct afswtch
*afp
)
587 struct ether_addr
*ea
;
589 memset(&req
, 0, sizeof(req
));
590 strlcpy(req
.ifba_ifsname
, val
, sizeof(req
.ifba_ifsname
));
592 ea
= ether_aton(mac
);
594 errx(1, "%s: invalid address: %s", val
, mac
);
596 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
597 req
.ifba_flags
= IFBAF_STATIC
;
598 req
.ifba_vlan
= 1; /* XXX allow user to specify */
600 if (do_cmd(s
, BRDGSADDR
, &req
, sizeof(req
), 1) < 0)
601 err(1, "BRDGSADDR %s", val
);
605 setbridge_deladdr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
608 struct ether_addr
*ea
;
610 memset(&req
, 0, sizeof(req
));
612 ea
= ether_aton(val
);
614 errx(1, "invalid address: %s", val
);
616 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
618 if (do_cmd(s
, BRDGDADDR
, &req
, sizeof(req
), 1) < 0)
619 err(1, "BRDGDADDR %s", val
);
623 setbridge_addr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
626 bridge_addresses(s
, "");
630 setbridge_maxaddr(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
632 struct ifbrparam param
;
635 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
636 errx(1, "invalid value: %s", arg
);
638 param
.ifbrp_csize
= val
& 0xffffffff;
640 if (do_cmd(s
, BRDGSCACHE
, ¶m
, sizeof(param
), 1) < 0)
641 err(1, "BRDGSCACHE %s", arg
);
645 setbridge_hellotime(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
647 struct ifbrparam param
;
650 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
651 errx(1, "invalid value: %s", arg
);
653 param
.ifbrp_hellotime
= val
& 0xff;
655 if (do_cmd(s
, BRDGSHT
, ¶m
, sizeof(param
), 1) < 0)
656 err(1, "BRDGSHT %s", arg
);
660 setbridge_fwddelay(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
662 struct ifbrparam param
;
665 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
666 errx(1, "invalid value: %s", arg
);
668 param
.ifbrp_fwddelay
= val
& 0xff;
670 if (do_cmd(s
, BRDGSFD
, ¶m
, sizeof(param
), 1) < 0)
671 err(1, "BRDGSFD %s", arg
);
675 setbridge_maxage(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
677 struct ifbrparam param
;
680 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
681 errx(1, "invalid value: %s", arg
);
683 param
.ifbrp_maxage
= val
& 0xff;
685 if (do_cmd(s
, BRDGSMA
, ¶m
, sizeof(param
), 1) < 0)
686 err(1, "BRDGSMA %s", arg
);
690 setbridge_priority(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
692 struct ifbrparam param
;
695 if (get_val(arg
, &val
) < 0 || (val
& ~0xffff) != 0)
696 errx(1, "invalid value: %s", arg
);
698 param
.ifbrp_prio
= val
& 0xffff;
700 if (do_cmd(s
, BRDGSPRI
, ¶m
, sizeof(param
), 1) < 0)
701 err(1, "BRDGSPRI %s", arg
);
706 setbridge_protocol(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
708 struct ifbrparam param
;
710 if (strcasecmp(arg
, "stp") == 0) {
711 param
.ifbrp_proto
= 0;
712 } else if (strcasecmp(arg
, "rstp") == 0) {
713 param
.ifbrp_proto
= 2;
715 errx(1, "unknown stp protocol");
718 if (do_cmd(s
, BRDGSPROTO
, ¶m
, sizeof(param
), 1) < 0)
719 err(1, "BRDGSPROTO %s", arg
);
723 setbridge_holdcount(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
725 struct ifbrparam param
;
728 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
729 errx(1, "invalid value: %s", arg
);
731 param
.ifbrp_txhc
= val
& 0xff;
733 if (do_cmd(s
, BRDGSTXHC
, ¶m
, sizeof(param
), 1) < 0)
734 err(1, "BRDGSTXHC %s", arg
);
739 setbridge_ifpriority(const char *ifn
, const char *pri
, int s
,
740 const struct afswtch
*afp
)
745 memset(&req
, 0, sizeof(req
));
747 if (get_val(pri
, &val
) < 0 || (val
& ~0xff) != 0)
748 errx(1, "invalid value: %s", pri
);
750 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
751 req
.ifbr_priority
= val
& 0xff;
753 if (do_cmd(s
, BRDGSIFPRIO
, &req
, sizeof(req
), 1) < 0)
754 err(1, "BRDGSIFPRIO %s", pri
);
758 setbridge_ifpathcost(const char *ifn
, const char *cost
, int s
,
759 const struct afswtch
*afp
)
764 memset(&req
, 0, sizeof(req
));
766 if (get_val(cost
, &val
) < 0)
767 errx(1, "invalid value: %s", cost
);
769 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
770 req
.ifbr_path_cost
= val
;
772 if (do_cmd(s
, BRDGSIFCOST
, &req
, sizeof(req
), 1) < 0)
773 err(1, "BRDGSIFCOST %s", cost
);
778 setbridge_ifmaxaddr(const char *ifn
, const char *arg
, int s
,
779 const struct afswtch
*afp
)
784 memset(&req
, 0, sizeof(req
));
786 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
787 errx(1, "invalid value: %s", arg
);
789 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
790 req
.ifbr_addrmax
= val
& 0xffffffff;
792 if (do_cmd(s
, BRDGSIFAMAX
, &req
, sizeof(req
), 1) < 0)
793 err(1, "BRDGSIFAMAX %s", arg
);
798 setbridge_timeout(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
800 struct ifbrparam param
;
803 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
804 errx(1, "invalid value: %s", arg
);
806 param
.ifbrp_ctime
= val
& 0xffffffff;
808 if (do_cmd(s
, BRDGSTO
, ¶m
, sizeof(param
), 1) < 0)
809 err(1, "BRDGSTO %s", arg
);
814 setbridge_private(const char *val
, int d
, int s
, const struct afswtch
*afp
)
817 do_bridgeflag(s
, val
, IFBIF_PRIVATE
, 1);
821 unsetbridge_private(const char *val
, int d
, int s
, const struct afswtch
*afp
)
824 do_bridgeflag(s
, val
, IFBIF_PRIVATE
, 0);
830 setbridge_hostfilter(const char *ifn
, const char *addr
, int s
,
831 const struct afswtch
*afp
)
833 struct ifbrhostfilter req
;
834 struct ether_addr
*ea
;
837 memset(&req
, 0, sizeof(req
));
838 req
.ifbrhf_flags
= IFBRHF_ENABLED
;
840 strlcpy(req
.ifbrhf_ifsname
, ifn
, sizeof(req
.ifbrhf_ifsname
));
842 ea
= ether_aton(addr
);
844 req
.ifbrhf_flags
|= IFBRHF_HWSRC
;
845 bcopy(ea
, req
.ifbrhf_hwsrca
, sizeof(req
.ifbrhf_hwsrca
));
846 } else if (inet_aton(addr
, &in
) != 0) {
847 req
.ifbrhf_flags
|= IFBRHF_IPSRC
;
848 req
.ifbrhf_ipsrc
= in
.s_addr
;
850 errx(1, "invalid address: %s", addr
);
852 if (do_cmd(s
, BRDGSHOSTFILTER
, &req
, sizeof(req
), 1) < 0)
853 err(1, "BRDGSHOSTFILTER %s %s", ifn
, addr
);
857 unsetbridge_hostfilter(const char *ifn
, int d
, int s
, const struct afswtch
*afp
)
859 struct ifbrhostfilter req
;
861 memset(&req
, 0, sizeof(req
));
862 strlcpy(req
.ifbrhf_ifsname
, ifn
, sizeof(req
.ifbrhf_ifsname
));
864 if (do_cmd(s
, BRDGSHOSTFILTER
, &req
, sizeof(req
), 1) < 0)
865 err(1, "BRDGSHOSTFILTER");
869 setbridge_macnat(const char *val
, int d
, int s
, const struct afswtch
*afp
)
872 do_bridgeflag(s
, val
, IFBIF_MAC_NAT
, 1);
876 unsetbridge_macnat(const char *val
, int d
, int s
, const struct afswtch
*afp
)
879 do_bridgeflag(s
, val
, IFBIF_MAC_NAT
, 0);
882 static struct cmd bridge_cmds
[] = {
883 DEF_CMD_ARG("addm", setbridge_add
),
884 DEF_CMD_ARG("deletem", setbridge_delete
),
885 DEF_CMD_ARG("discover", setbridge_discover
),
886 DEF_CMD_ARG("-discover", unsetbridge_discover
),
887 DEF_CMD_ARG("learn", setbridge_learn
),
888 DEF_CMD_ARG("-learn", unsetbridge_learn
),
890 DEF_CMD_ARG("sticky", setbridge_sticky
),
891 DEF_CMD_ARG("-sticky", unsetbridge_sticky
),
892 DEF_CMD_ARG("span", setbridge_span
),
893 DEF_CMD_ARG("-span", unsetbridge_span
),
895 DEF_CMD_ARG("stp", setbridge_stp
),
896 DEF_CMD_ARG("-stp", unsetbridge_stp
),
898 DEF_CMD_ARG("edge", setbridge_edge
),
899 DEF_CMD_ARG("-edge", unsetbridge_edge
),
900 DEF_CMD_ARG("autoedge", setbridge_autoedge
),
901 DEF_CMD_ARG("-autoedge", unsetbridge_autoedge
),
902 DEF_CMD_ARG("ptp", setbridge_ptp
),
903 DEF_CMD_ARG("-ptp", unsetbridge_ptp
),
904 DEF_CMD_ARG("autoptp", setbridge_autoptp
),
905 DEF_CMD_ARG("-autoptp", unsetbridge_autoptp
),
907 DEF_CMD("flush", 0, setbridge_flush
),
908 DEF_CMD("flushall", 0, setbridge_flushall
),
909 DEF_CMD_ARG2("static", setbridge_static
),
910 DEF_CMD_ARG("deladdr", setbridge_deladdr
),
911 DEF_CMD("addr", 1, setbridge_addr
),
912 DEF_CMD_ARG("maxaddr", setbridge_maxaddr
),
913 DEF_CMD_ARG("hellotime", setbridge_hellotime
),
914 DEF_CMD_ARG("fwddelay", setbridge_fwddelay
),
915 DEF_CMD_ARG("maxage", setbridge_maxage
),
916 DEF_CMD_ARG("priority", setbridge_priority
),
918 DEF_CMD_ARG("proto", setbridge_protocol
),
919 DEF_CMD_ARG("holdcnt", setbridge_holdcount
),
921 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority
),
922 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost
),
924 DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr
),
926 DEF_CMD_ARG("timeout", setbridge_timeout
),
928 DEF_CMD_ARG("private", setbridge_private
),
929 DEF_CMD_ARG("-private", unsetbridge_private
),
931 DEF_CMD_ARG2("hostfilter", setbridge_hostfilter
),
932 DEF_CMD_ARG("-hostfilter", unsetbridge_hostfilter
),
933 DEF_CMD_ARG("macnat", setbridge_macnat
),
934 DEF_CMD_ARG("-macnat", unsetbridge_macnat
),
936 static struct afswtch af_bridge
= {
937 .af_name
= "af_bridge",
939 .af_other_status
= bridge_status
,
942 static __constructor
void
945 #define N(a) (sizeof(a) / sizeof(a[0]))
948 for (i
= 0; i
< N(bridge_cmds
); i
++)
949 cmd_register(&bridge_cmds
[i
]);
950 af_register(&af_bridge
);