2 * Copyright 2001 Wasabi Systems, Inc.
5 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project by
18 * Wasabi Systems, Inc.
19 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
20 * or promote products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * $FreeBSD: src/sbin/ifconfig/ifbridge.c,v 1.1.2.2 2005/12/28 04:12:58 thompsa Exp $
38 #include <sys/param.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
41 #include <sys/sockio.h>
46 #include <net/ethernet.h>
48 #include <net/bridge/if_bridgevar.h>
49 #include <net/route.h>
60 get_val(const char *cp
, u_long
*valp
)
66 val
= strtoul(cp
, &endptr
, 0);
67 if (cp
[0] == '\0' || endptr
[0] != '\0' || errno
== ERANGE
)
75 do_cmd(int sock
, u_long op
, void *arg
, size_t argsize
, int set
)
79 memset(&ifd
, 0, sizeof(ifd
));
81 strlcpy(ifd
.ifd_name
, ifr
.ifr_name
, sizeof(ifd
.ifd_name
));
83 ifd
.ifd_len
= argsize
;
86 return (ioctl(sock
, set
? SIOCSDRVSPEC
: SIOCGDRVSPEC
, &ifd
));
90 do_bridgeflag(int sock
, const char *ifs
, int flag
, int set
)
94 strlcpy(req
.ifbr_ifsname
, ifs
, sizeof(req
.ifbr_ifsname
));
96 if (do_cmd(sock
, BRDGGIFFLGS
, &req
, sizeof(req
), 0) < 0)
97 err(1, "unable to get bridge flags");
100 req
.ifbr_ifsflags
|= flag
;
102 req
.ifbr_ifsflags
&= ~flag
;
104 if (do_cmd(sock
, BRDGSIFFLGS
, &req
, sizeof(req
), 1) < 0)
105 err(1, "unable to set bridge flags");
109 bridge_interfaces(int s
, const char *prefix
)
111 static const char *stpstates
[] = {
120 struct ifbifconf bifc
;
122 char *inbuf
= NULL
, *ninbuf
;
126 pad
= strdup(prefix
);
129 /* replace the prefix with whitespace */
130 for (p
= pad
; *p
!= '\0'; p
++) {
136 ninbuf
= realloc(inbuf
, len
);
138 err(1, "unable to allocate interface buffer");
139 bifc
.ifbic_len
= len
;
140 bifc
.ifbic_buf
= inbuf
= ninbuf
;
141 if (do_cmd(s
, BRDGGIFS
, &bifc
, sizeof(bifc
), 0) < 0)
142 err(1, "unable to get interface list");
143 if ((bifc
.ifbic_len
+ sizeof(*req
)) < len
)
148 for (i
= 0; i
< bifc
.ifbic_len
/ sizeof(*req
); i
++) {
149 req
= bifc
.ifbic_req
+ i
;
150 printf("%s%s ", prefix
, req
->ifbr_ifsname
);
151 printb("flags", req
->ifbr_ifsflags
, IFBIFBITS
);
154 if (req
->ifbr_ifsflags
& IFBIF_STP
) {
156 printf("port %u priority %u",
157 req
->ifbr_portno
, req
->ifbr_priority
);
158 printf(" pathcost %u", req
->ifbr_path_cost
);
159 if (req
->ifbr_state
< NELEM(stpstates
))
160 printf(" %s", stpstates
[req
->ifbr_state
]);
162 printf(" <unknown state %d>",
165 printf("%sbondweight %u\n",
166 pad
, req
->ifbr_bond_weight
);
167 printf("%sdesignated root: %016jx\n",
168 pad
, (intmax_t)req
->ifbr_designated_root
);
169 printf("%sdesignated bridge: %016jx\n",
170 pad
, (intmax_t)req
->ifbr_designated_bridge
);
171 printf("%sdesignated cost: %u\n",
172 pad
, req
->ifbr_designated_cost
);
173 printf("%sdesignated port: %u\n",
174 pad
, req
->ifbr_designated_port
);
176 printf("%speer root: %016jx\n",
177 pad
, (intmax_t)req
->ifbr_peer_root
);
178 printf("%speer bridge: %016jx\n",
179 pad
, (intmax_t)req
->ifbr_peer_bridge
);
180 printf("%speer cost: %u\n",
181 pad
, req
->ifbr_peer_cost
);
182 printf("%speer port: %u\n",
183 pad
, req
->ifbr_peer_port
);
192 bridge_addresses(int s
, const char *prefix
)
194 struct ifbaconf ifbac
;
195 struct ifbareq
*ifba
;
196 char *inbuf
= NULL
, *ninbuf
;
198 struct ether_addr ea
;
201 ninbuf
= realloc(inbuf
, len
);
203 err(1, "unable to allocate address buffer");
204 ifbac
.ifbac_len
= len
;
205 ifbac
.ifbac_buf
= inbuf
= ninbuf
;
206 if (do_cmd(s
, BRDGRTS
, &ifbac
, sizeof(ifbac
), 0) < 0)
207 err(1, "unable to get address cache");
208 if ((ifbac
.ifbac_len
+ sizeof(*ifba
)) < len
)
213 for (i
= 0; i
< ifbac
.ifbac_len
/ sizeof(*ifba
); i
++) {
214 ifba
= ifbac
.ifbac_req
+ i
;
215 memcpy(ea
.octet
, ifba
->ifba_dst
,
217 printf("%s%s %s %lu ", prefix
, ether_ntoa(&ea
),
218 ifba
->ifba_ifsname
, ifba
->ifba_expire
);
219 printb("flags", ifba
->ifba_flags
, IFBAFBITS
);
229 struct ifbrparam param
;
233 if (do_cmd(s
, BRDGGPRI
, ¶m
, sizeof(param
), 0) < 0)
235 pri
= param
.ifbrp_prio
;
237 if (do_cmd(s
, BRDGGHT
, ¶m
, sizeof(param
), 0) < 0)
239 ht
= param
.ifbrp_hellotime
;
241 if (do_cmd(s
, BRDGGFD
, ¶m
, sizeof(param
), 0) < 0)
243 fd
= param
.ifbrp_fwddelay
;
245 if (do_cmd(s
, BRDGGMA
, ¶m
, sizeof(param
), 0) < 0)
247 ma
= param
.ifbrp_maxage
;
249 printf("\tpriority %u hellotime %u fwddelay %u maxage %u\n",
252 bridge_interfaces(s
, "\tmember: ");
259 setbridge_add(const char *val
, int d
, int s
, const struct afswtch
*afp
)
263 memset(&req
, 0, sizeof(req
));
264 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
265 if (do_cmd(s
, BRDGADD
, &req
, sizeof(req
), 1) < 0)
266 err(1, "BRDGADD %s", val
);
270 setbridge_delete(const char *val
, int d
, int s
, const struct afswtch
*afp
)
274 memset(&req
, 0, sizeof(req
));
275 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
276 if (do_cmd(s
, BRDGDEL
, &req
, sizeof(req
), 1) < 0)
277 err(1, "BRDGDEL %s", val
);
281 setbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
284 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 1);
288 unsetbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
291 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 0);
295 setbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
298 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 1);
302 unsetbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
305 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 0);
309 setbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
313 memset(&req
, 0, sizeof(req
));
314 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
315 if (do_cmd(s
, BRDGADDS
, &req
, sizeof(req
), 1) < 0)
316 err(1, "BRDGADDS %s", val
);
320 unsetbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
324 memset(&req
, 0, sizeof(req
));
325 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
326 if (do_cmd(s
, BRDGDELS
, &req
, sizeof(req
), 1) < 0)
327 err(1, "BRDGDELS %s", val
);
331 setbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
334 do_bridgeflag(s
, val
, IFBIF_STP
, 1);
338 unsetbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
341 do_bridgeflag(s
, val
, IFBIF_STP
, 0);
345 setbridge_flush(const char *val
, int d
, int s
, const struct afswtch
*afp
)
349 memset(&req
, 0, sizeof(req
));
350 req
.ifbr_ifsflags
= IFBF_FLUSHDYN
;
351 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
356 setbridge_flushall(const char *val
, int d
, int s
, const struct afswtch
*afp
)
360 memset(&req
, 0, sizeof(req
));
361 req
.ifbr_ifsflags
= IFBF_FLUSHALL
;
362 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
367 setbridge_static(const char *val
, const char *mac
, int s
,
368 const struct afswtch
*afp
)
371 struct ether_addr
*ea
;
373 memset(&req
, 0, sizeof(req
));
374 strlcpy(req
.ifba_ifsname
, val
, sizeof(req
.ifba_ifsname
));
376 ea
= ether_aton(mac
);
378 errx(1, "%s: invalid address: %s", val
, mac
);
380 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
381 req
.ifba_flags
= IFBAF_STATIC
;
383 if (do_cmd(s
, BRDGSADDR
, &req
, sizeof(req
), 1) < 0)
384 err(1, "BRDGSADDR %s", val
);
388 setbridge_deladdr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
391 struct ether_addr
*ea
;
393 memset(&req
, 0, sizeof(req
));
395 ea
= ether_aton(val
);
397 errx(1, "invalid address: %s", val
);
399 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
401 if (do_cmd(s
, BRDGDADDR
, &req
, sizeof(req
), 1) < 0)
402 err(1, "BRDGDADDR %s", val
);
406 getbridge_addr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
408 bridge_addresses(s
, "");
412 setbridge_maxaddr(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
414 struct ifbrparam param
;
417 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
418 errx(1, "invalid value: %s", arg
);
420 param
.ifbrp_csize
= val
& 0xffffffff;
422 if (do_cmd(s
, BRDGSCACHE
, ¶m
, sizeof(param
), 1) < 0)
423 err(1, "BRDGSCACHE %s", arg
);
427 setbridge_hellotime(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
429 struct ifbrparam param
;
432 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
433 errx(1, "invalid value: %s", arg
);
435 param
.ifbrp_hellotime
= val
& 0xff;
437 if (do_cmd(s
, BRDGSHT
, ¶m
, sizeof(param
), 1) < 0)
438 err(1, "BRDGSHT %s", arg
);
442 setbridge_fwddelay(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
444 struct ifbrparam param
;
447 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
448 errx(1, "invalid value: %s", arg
);
450 param
.ifbrp_fwddelay
= val
& 0xff;
452 if (do_cmd(s
, BRDGSFD
, ¶m
, sizeof(param
), 1) < 0)
453 err(1, "BRDGSFD %s", arg
);
457 setbridge_maxage(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
459 struct ifbrparam param
;
462 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
463 errx(1, "invalid value: %s", arg
);
465 param
.ifbrp_maxage
= val
& 0xff;
467 if (do_cmd(s
, BRDGSMA
, ¶m
, sizeof(param
), 1) < 0)
468 err(1, "BRDGSMA %s", arg
);
472 setbridge_priority(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
474 struct ifbrparam param
;
477 if (get_val(arg
, &val
) < 0 || (val
& ~0xffff) != 0)
478 errx(1, "invalid value: %s", arg
);
480 param
.ifbrp_prio
= val
& 0xffff;
482 if (do_cmd(s
, BRDGSPRI
, ¶m
, sizeof(param
), 1) < 0)
483 err(1, "BRDGSPRI %s", arg
);
487 setbridge_ifpriority(const char *ifn
, const char *pri
, int s
,
488 const struct afswtch
*afp
)
493 memset(&req
, 0, sizeof(req
));
495 if (get_val(pri
, &val
) < 0 || (val
& ~0xff) != 0)
496 errx(1, "invalid value: %s", pri
);
498 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
499 req
.ifbr_priority
= val
& 0xff;
501 if (do_cmd(s
, BRDGSIFPRIO
, &req
, sizeof(req
), 1) < 0)
502 err(1, "BRDGSIFPRIO %s", pri
);
506 setbridge_ifpathcost(const char *ifn
, const char *cost
, int s
,
507 const struct afswtch
*afp
)
512 memset(&req
, 0, sizeof(req
));
514 if (get_val(cost
, &val
) < 0 || (val
& ~0xff) != 0)
515 errx(1, "invalid value: %s", cost
);
517 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
518 req
.ifbr_path_cost
= val
& 0xffff;
520 if (do_cmd(s
, BRDGSIFCOST
, &req
, sizeof(req
), 1) < 0)
521 err(1, "BRDGSIFCOST %s", cost
);
525 setbridge_ifbondweight(const char *ifn
, const char *cost
, int s
,
526 const struct afswtch
*afp
)
531 memset(&req
, 0, sizeof(req
));
533 if (get_val(cost
, &val
) < 0 || (val
& ~0xff) != 0)
534 errx(1, "invalid value: %s", cost
);
536 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
539 req
.ifbr_bond_weight
= (uint16_t)val
;
541 if (do_cmd(s
, BRDGSBONDWGHT
, &req
, sizeof(req
), 1) < 0)
542 err(1, "BRDGSBONDWGHT %s", cost
);
546 setbridge_timeout(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
548 struct ifbrparam param
;
551 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
552 errx(1, "invalid value: %s", arg
);
554 param
.ifbrp_ctime
= val
& 0xffffffff;
556 if (do_cmd(s
, BRDGSTO
, ¶m
, sizeof(param
), 1) < 0)
557 err(1, "BRDGSTO %s", arg
);
560 static struct cmd bridge_cmds
[] = {
561 DEF_CMD_ARG("addm", setbridge_add
),
562 DEF_CMD_ARG("deletem", setbridge_delete
),
563 DEF_CMD_ARG("discover", setbridge_discover
),
564 DEF_CMD_ARG("-discover", unsetbridge_discover
),
565 DEF_CMD_ARG("learn", setbridge_learn
),
566 DEF_CMD_ARG("-learn", unsetbridge_learn
),
567 DEF_CMD_ARG("span", setbridge_span
),
568 DEF_CMD_ARG("-span", unsetbridge_span
),
569 DEF_CMD_ARG("stp", setbridge_stp
),
570 DEF_CMD_ARG("-stp", unsetbridge_stp
),
571 DEF_CMD("flush", 0, setbridge_flush
),
572 DEF_CMD("flushall", 0, setbridge_flushall
),
573 DEF_CMD_ARG2("static", setbridge_static
),
574 DEF_CMD_ARG("deladdr", setbridge_deladdr
),
575 DEF_CMD("addr", 1, getbridge_addr
),
576 DEF_CMD_ARG("maxaddr", setbridge_maxaddr
),
577 DEF_CMD_ARG("hellotime", setbridge_hellotime
),
578 DEF_CMD_ARG("fwddelay", setbridge_fwddelay
),
579 DEF_CMD_ARG("maxage", setbridge_maxage
),
580 DEF_CMD_ARG("priority", setbridge_priority
),
581 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority
),
582 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost
),
583 DEF_CMD_ARG2("ifbondweight", setbridge_ifbondweight
),
584 DEF_CMD_ARG("timeout", setbridge_timeout
),
586 static struct afswtch af_bridge
= {
587 .af_name
= "af_bridge",
589 .af_other_status
= bridge_status
,
592 static __constructor(101) void
595 #define N(a) (sizeof(a) / sizeof(a[0]))
598 for (i
= 0; i
< N(bridge_cmds
); i
++)
599 cmd_register(&bridge_cmds
[i
]);
600 af_register(&af_bridge
);