]>
git.saurik.com Git - apple/network_cmds.git/blob - ifconfig.tproj/ifbridge.c
2 * Copyright (c) 2009-2014 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
);
305 struct ifbropreq ifbp
;
306 struct ifbrparam param
;
308 u_int8_t ht
, fd
, ma
, hc
, pro
;
309 u_int8_t lladdr
[ETHER_ADDR_LEN
];
311 u_int32_t csize
, ctime
;
314 if (do_cmd(s
, BRDGGCACHE
, ¶m
, sizeof(param
), 0) < 0)
316 csize
= param
.ifbrp_csize
;
317 if (do_cmd(s
, BRDGGTO
, ¶m
, sizeof(param
), 0) < 0)
319 ctime
= param
.ifbrp_ctime
;
320 if (do_cmd(s
, BRDGGFILT
, ¶m
, sizeof(param
), 0) < 0)
322 ipfflags
= param
.ifbrp_filter
;
323 if (do_cmd(s
, BRDGPARAM
, &ifbp
, sizeof(ifbp
), 0) < 0)
325 pri
= ifbp
.ifbop_priority
;
326 pro
= ifbp
.ifbop_protocol
;
327 ht
= ifbp
.ifbop_hellotime
;
328 fd
= ifbp
.ifbop_fwddelay
;
329 hc
= ifbp
.ifbop_holdcount
;
330 ma
= ifbp
.ifbop_maxage
;
332 printf("\tConfiguration:\n");
333 PV2ID(ifbp
.ifbop_bridgeid
, bprio
, lladdr
);
334 printf("\t\tid %s priority %u hellotime %u fwddelay %u\n",
335 ether_ntoa((struct ether_addr
*)lladdr
), pri
, ht
, fd
);
336 printf("\t\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n",
337 ma
, hc
, stpproto
[pro
], csize
, ctime
);
339 PV2ID(ifbp
.ifbop_designated_root
, bprio
, lladdr
);
340 printf("\t\troot id %s priority %d ifcost %u port %u\n",
341 ether_ntoa((struct ether_addr
*)lladdr
), bprio
,
342 ifbp
.ifbop_root_path_cost
, ifbp
.ifbop_root_port
& 0xfff);
344 printf("\t\tipfilter %s flags 0x%x\n",
345 (ipfflags
& IFBF_FILT_USEIPF
) ? "enabled" : "disabled", ipfflags
);
347 bridge_interfaces(s
, "\tmember: ");
349 if (!all
|| verbose
> 1) {
350 printf("\tAddress cache:\n");
351 bridge_addresses(s
, "\t\t");
358 setbridge_add(const char *val
, int d
, int s
, const struct afswtch
*afp
)
362 memset(&req
, 0, sizeof(req
));
363 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
364 if (do_cmd(s
, BRDGADD
, &req
, sizeof(req
), 1) < 0)
365 err(1, "BRDGADD %s", val
);
369 setbridge_delete(const char *val
, int d
, int s
, const struct afswtch
*afp
)
373 memset(&req
, 0, sizeof(req
));
374 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
375 if (do_cmd(s
, BRDGDEL
, &req
, sizeof(req
), 1) < 0)
376 err(1, "BRDGDEL %s", val
);
380 setbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
383 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 1);
387 unsetbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
390 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 0);
394 setbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
397 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 1);
401 unsetbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
404 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 0);
409 setbridge_sticky(const char *val
, int d
, int s
, const struct afswtch
*afp
)
412 do_bridgeflag(s
, val
, IFBIF_STICKY
, 1);
416 unsetbridge_sticky(const char *val
, int d
, int s
, const struct afswtch
*afp
)
419 do_bridgeflag(s
, val
, IFBIF_STICKY
, 0);
423 setbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
427 memset(&req
, 0, sizeof(req
));
428 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
429 if (do_cmd(s
, BRDGADDS
, &req
, sizeof(req
), 1) < 0)
430 err(1, "BRDGADDS %s", val
);
434 unsetbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
438 memset(&req
, 0, sizeof(req
));
439 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
440 if (do_cmd(s
, BRDGDELS
, &req
, sizeof(req
), 1) < 0)
441 err(1, "BRDGDELS %s", val
);
446 setbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
449 do_bridgeflag(s
, val
, IFBIF_STP
, 1);
453 unsetbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
456 do_bridgeflag(s
, val
, IFBIF_STP
, 0);
461 setbridge_edge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
463 do_bridgeflag(s
, val
, IFBIF_BSTP_EDGE
, 1);
467 unsetbridge_edge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
469 do_bridgeflag(s
, val
, IFBIF_BSTP_EDGE
, 0);
473 setbridge_autoedge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
475 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOEDGE
, 1);
479 unsetbridge_autoedge(const char *val
, int d
, int s
, const struct afswtch
*afp
)
481 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOEDGE
, 0);
485 setbridge_ptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
487 do_bridgeflag(s
, val
, IFBIF_BSTP_PTP
, 1);
491 unsetbridge_ptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
493 do_bridgeflag(s
, val
, IFBIF_BSTP_PTP
, 0);
497 setbridge_autoptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
499 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOPTP
, 1);
503 unsetbridge_autoptp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
505 do_bridgeflag(s
, val
, IFBIF_BSTP_AUTOPTP
, 0);
510 setbridge_flush(const char *val
, int d
, int s
, const struct afswtch
*afp
)
514 memset(&req
, 0, sizeof(req
));
515 req
.ifbr_ifsflags
= IFBF_FLUSHDYN
;
516 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
521 setbridge_flushall(const char *val
, int d
, int s
, const struct afswtch
*afp
)
525 memset(&req
, 0, sizeof(req
));
526 req
.ifbr_ifsflags
= IFBF_FLUSHALL
;
527 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
532 setbridge_static(const char *val
, const char *mac
, int s
,
533 const struct afswtch
*afp
)
536 struct ether_addr
*ea
;
538 memset(&req
, 0, sizeof(req
));
539 strlcpy(req
.ifba_ifsname
, val
, sizeof(req
.ifba_ifsname
));
541 ea
= ether_aton(mac
);
543 errx(1, "%s: invalid address: %s", val
, mac
);
545 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
546 req
.ifba_flags
= IFBAF_STATIC
;
547 req
.ifba_vlan
= 1; /* XXX allow user to specify */
549 if (do_cmd(s
, BRDGSADDR
, &req
, sizeof(req
), 1) < 0)
550 err(1, "BRDGSADDR %s", val
);
554 setbridge_deladdr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
557 struct ether_addr
*ea
;
559 memset(&req
, 0, sizeof(req
));
561 ea
= ether_aton(val
);
563 errx(1, "invalid address: %s", val
);
565 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
567 if (do_cmd(s
, BRDGDADDR
, &req
, sizeof(req
), 1) < 0)
568 err(1, "BRDGDADDR %s", val
);
572 setbridge_addr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
575 bridge_addresses(s
, "");
579 setbridge_maxaddr(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
581 struct ifbrparam param
;
584 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
585 errx(1, "invalid value: %s", arg
);
587 param
.ifbrp_csize
= val
& 0xffffffff;
589 if (do_cmd(s
, BRDGSCACHE
, ¶m
, sizeof(param
), 1) < 0)
590 err(1, "BRDGSCACHE %s", arg
);
594 setbridge_hellotime(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
596 struct ifbrparam param
;
599 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
600 errx(1, "invalid value: %s", arg
);
602 param
.ifbrp_hellotime
= val
& 0xff;
604 if (do_cmd(s
, BRDGSHT
, ¶m
, sizeof(param
), 1) < 0)
605 err(1, "BRDGSHT %s", arg
);
609 setbridge_fwddelay(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
611 struct ifbrparam param
;
614 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
615 errx(1, "invalid value: %s", arg
);
617 param
.ifbrp_fwddelay
= val
& 0xff;
619 if (do_cmd(s
, BRDGSFD
, ¶m
, sizeof(param
), 1) < 0)
620 err(1, "BRDGSFD %s", arg
);
624 setbridge_maxage(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
626 struct ifbrparam param
;
629 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
630 errx(1, "invalid value: %s", arg
);
632 param
.ifbrp_maxage
= val
& 0xff;
634 if (do_cmd(s
, BRDGSMA
, ¶m
, sizeof(param
), 1) < 0)
635 err(1, "BRDGSMA %s", arg
);
639 setbridge_priority(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
641 struct ifbrparam param
;
644 if (get_val(arg
, &val
) < 0 || (val
& ~0xffff) != 0)
645 errx(1, "invalid value: %s", arg
);
647 param
.ifbrp_prio
= val
& 0xffff;
649 if (do_cmd(s
, BRDGSPRI
, ¶m
, sizeof(param
), 1) < 0)
650 err(1, "BRDGSPRI %s", arg
);
655 setbridge_protocol(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
657 struct ifbrparam param
;
659 if (strcasecmp(arg
, "stp") == 0) {
660 param
.ifbrp_proto
= 0;
661 } else if (strcasecmp(arg
, "rstp") == 0) {
662 param
.ifbrp_proto
= 2;
664 errx(1, "unknown stp protocol");
667 if (do_cmd(s
, BRDGSPROTO
, ¶m
, sizeof(param
), 1) < 0)
668 err(1, "BRDGSPROTO %s", arg
);
672 setbridge_holdcount(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
674 struct ifbrparam param
;
677 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
678 errx(1, "invalid value: %s", arg
);
680 param
.ifbrp_txhc
= val
& 0xff;
682 if (do_cmd(s
, BRDGSTXHC
, ¶m
, sizeof(param
), 1) < 0)
683 err(1, "BRDGSTXHC %s", arg
);
688 setbridge_ifpriority(const char *ifn
, const char *pri
, int s
,
689 const struct afswtch
*afp
)
694 memset(&req
, 0, sizeof(req
));
696 if (get_val(pri
, &val
) < 0 || (val
& ~0xff) != 0)
697 errx(1, "invalid value: %s", pri
);
699 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
700 req
.ifbr_priority
= val
& 0xff;
702 if (do_cmd(s
, BRDGSIFPRIO
, &req
, sizeof(req
), 1) < 0)
703 err(1, "BRDGSIFPRIO %s", pri
);
707 setbridge_ifpathcost(const char *ifn
, const char *cost
, int s
,
708 const struct afswtch
*afp
)
713 memset(&req
, 0, sizeof(req
));
715 if (get_val(cost
, &val
) < 0)
716 errx(1, "invalid value: %s", cost
);
718 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
719 req
.ifbr_path_cost
= val
;
721 if (do_cmd(s
, BRDGSIFCOST
, &req
, sizeof(req
), 1) < 0)
722 err(1, "BRDGSIFCOST %s", cost
);
727 setbridge_ifmaxaddr(const char *ifn
, const char *arg
, int s
,
728 const struct afswtch
*afp
)
733 memset(&req
, 0, sizeof(req
));
735 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
736 errx(1, "invalid value: %s", arg
);
738 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
739 req
.ifbr_addrmax
= val
& 0xffffffff;
741 if (do_cmd(s
, BRDGSIFAMAX
, &req
, sizeof(req
), 1) < 0)
742 err(1, "BRDGSIFAMAX %s", arg
);
747 setbridge_timeout(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
749 struct ifbrparam param
;
752 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
753 errx(1, "invalid value: %s", arg
);
755 param
.ifbrp_ctime
= val
& 0xffffffff;
757 if (do_cmd(s
, BRDGSTO
, ¶m
, sizeof(param
), 1) < 0)
758 err(1, "BRDGSTO %s", arg
);
763 setbridge_private(const char *val
, int d
, int s
, const struct afswtch
*afp
)
766 do_bridgeflag(s
, val
, IFBIF_PRIVATE
, 1);
770 unsetbridge_private(const char *val
, int d
, int s
, const struct afswtch
*afp
)
773 do_bridgeflag(s
, val
, IFBIF_PRIVATE
, 0);
779 setbridge_hostfilter(const char *ifn
, const char *addr
, int s
,
780 const struct afswtch
*afp
)
782 struct ifbrhostfilter req
;
783 struct ether_addr
*ea
;
786 memset(&req
, 0, sizeof(req
));
787 req
.ifbrhf_flags
= IFBRHF_ENABLED
;
789 strlcpy(req
.ifbrhf_ifsname
, ifn
, sizeof(req
.ifbrhf_ifsname
));
791 ea
= ether_aton(addr
);
793 req
.ifbrhf_flags
|= IFBRHF_HWSRC
;
794 bcopy(ea
, req
.ifbrhf_hwsrca
, sizeof(req
.ifbrhf_hwsrca
));
795 } else if (inet_aton(addr
, &in
) != 0) {
796 req
.ifbrhf_flags
|= IFBRHF_IPSRC
;
797 req
.ifbrhf_ipsrc
= in
.s_addr
;
799 errx(1, "invalid address: %s", addr
);
801 if (do_cmd(s
, BRDGSHOSTFILTER
, &req
, sizeof(req
), 1) < 0)
802 err(1, "BRDGSHOSTFILTER %s %s", ifn
, addr
);
806 unsetbridge_hostfilter(const char *ifn
, int d
, int s
, const struct afswtch
*afp
)
808 struct ifbrhostfilter req
;
810 memset(&req
, 0, sizeof(req
));
811 strlcpy(req
.ifbrhf_ifsname
, ifn
, sizeof(req
.ifbrhf_ifsname
));
813 if (do_cmd(s
, BRDGSHOSTFILTER
, &req
, sizeof(req
), 1) < 0)
814 err(1, "BRDGSHOSTFILTER");
817 static struct cmd bridge_cmds
[] = {
818 DEF_CMD_ARG("addm", setbridge_add
),
819 DEF_CMD_ARG("deletem", setbridge_delete
),
820 DEF_CMD_ARG("discover", setbridge_discover
),
821 DEF_CMD_ARG("-discover", unsetbridge_discover
),
822 DEF_CMD_ARG("learn", setbridge_learn
),
823 DEF_CMD_ARG("-learn", unsetbridge_learn
),
825 DEF_CMD_ARG("sticky", setbridge_sticky
),
826 DEF_CMD_ARG("-sticky", unsetbridge_sticky
),
827 DEF_CMD_ARG("span", setbridge_span
),
828 DEF_CMD_ARG("-span", unsetbridge_span
),
830 DEF_CMD_ARG("stp", setbridge_stp
),
831 DEF_CMD_ARG("-stp", unsetbridge_stp
),
833 DEF_CMD_ARG("edge", setbridge_edge
),
834 DEF_CMD_ARG("-edge", unsetbridge_edge
),
835 DEF_CMD_ARG("autoedge", setbridge_autoedge
),
836 DEF_CMD_ARG("-autoedge", unsetbridge_autoedge
),
837 DEF_CMD_ARG("ptp", setbridge_ptp
),
838 DEF_CMD_ARG("-ptp", unsetbridge_ptp
),
839 DEF_CMD_ARG("autoptp", setbridge_autoptp
),
840 DEF_CMD_ARG("-autoptp", unsetbridge_autoptp
),
842 DEF_CMD("flush", 0, setbridge_flush
),
843 DEF_CMD("flushall", 0, setbridge_flushall
),
844 DEF_CMD_ARG2("static", setbridge_static
),
845 DEF_CMD_ARG("deladdr", setbridge_deladdr
),
846 DEF_CMD("addr", 1, setbridge_addr
),
847 DEF_CMD_ARG("maxaddr", setbridge_maxaddr
),
848 DEF_CMD_ARG("hellotime", setbridge_hellotime
),
849 DEF_CMD_ARG("fwddelay", setbridge_fwddelay
),
850 DEF_CMD_ARG("maxage", setbridge_maxage
),
851 DEF_CMD_ARG("priority", setbridge_priority
),
853 DEF_CMD_ARG("proto", setbridge_protocol
),
854 DEF_CMD_ARG("holdcnt", setbridge_holdcount
),
856 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority
),
857 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost
),
859 DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr
),
861 DEF_CMD_ARG("timeout", setbridge_timeout
),
863 DEF_CMD_ARG("private", setbridge_private
),
864 DEF_CMD_ARG("-private", unsetbridge_private
),
866 DEF_CMD_ARG2("hostfilter", setbridge_hostfilter
),
867 DEF_CMD_ARG("-hostfilter", unsetbridge_hostfilter
),
869 static struct afswtch af_bridge
= {
870 .af_name
= "af_bridge",
872 .af_other_status
= bridge_status
,
875 static __constructor
void
878 #define N(a) (sizeof(a) / sizeof(a[0]))
881 for (i
= 0; i
< N(bridge_cmds
); i
++)
882 cmd_register(&bridge_cmds
[i
]);
883 af_register(&af_bridge
);