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
<
160 sizeof(stpstates
) / sizeof(stpstates
[0]))
161 printf(" %s", stpstates
[req
->ifbr_state
]);
163 printf(" <unknown state %d>",
166 printf("%sbondweight %u\n",
167 pad
, req
->ifbr_bond_weight
);
168 printf("%sdesignated root: %016jx\n",
169 pad
, (intmax_t)req
->ifbr_designated_root
);
170 printf("%sdesignated bridge: %016jx\n",
171 pad
, (intmax_t)req
->ifbr_designated_bridge
);
172 printf("%sdesignated cost: %u\n",
173 pad
, req
->ifbr_designated_cost
);
174 printf("%sdesignated port: %u\n",
175 pad
, req
->ifbr_designated_port
);
177 printf("%speer root: %016jx\n",
178 pad
, (intmax_t)req
->ifbr_peer_root
);
179 printf("%speer bridge: %016jx\n",
180 pad
, (intmax_t)req
->ifbr_peer_bridge
);
181 printf("%speer cost: %u\n",
182 pad
, req
->ifbr_peer_cost
);
183 printf("%speer port: %u\n",
184 pad
, req
->ifbr_peer_port
);
193 bridge_addresses(int s
, const char *prefix
)
195 struct ifbaconf ifbac
;
196 struct ifbareq
*ifba
;
197 char *inbuf
= NULL
, *ninbuf
;
199 struct ether_addr ea
;
202 ninbuf
= realloc(inbuf
, len
);
204 err(1, "unable to allocate address buffer");
205 ifbac
.ifbac_len
= len
;
206 ifbac
.ifbac_buf
= inbuf
= ninbuf
;
207 if (do_cmd(s
, BRDGRTS
, &ifbac
, sizeof(ifbac
), 0) < 0)
208 err(1, "unable to get address cache");
209 if ((ifbac
.ifbac_len
+ sizeof(*ifba
)) < len
)
214 for (i
= 0; i
< ifbac
.ifbac_len
/ sizeof(*ifba
); i
++) {
215 ifba
= ifbac
.ifbac_req
+ i
;
216 memcpy(ea
.octet
, ifba
->ifba_dst
,
218 printf("%s%s %s %lu ", prefix
, ether_ntoa(&ea
),
219 ifba
->ifba_ifsname
, ifba
->ifba_expire
);
220 printb("flags", ifba
->ifba_flags
, IFBAFBITS
);
230 struct ifbrparam param
;
234 if (do_cmd(s
, BRDGGPRI
, ¶m
, sizeof(param
), 0) < 0)
236 pri
= param
.ifbrp_prio
;
238 if (do_cmd(s
, BRDGGHT
, ¶m
, sizeof(param
), 0) < 0)
240 ht
= param
.ifbrp_hellotime
;
242 if (do_cmd(s
, BRDGGFD
, ¶m
, sizeof(param
), 0) < 0)
244 fd
= param
.ifbrp_fwddelay
;
246 if (do_cmd(s
, BRDGGMA
, ¶m
, sizeof(param
), 0) < 0)
248 ma
= param
.ifbrp_maxage
;
250 printf("\tpriority %u hellotime %u fwddelay %u maxage %u\n",
253 bridge_interfaces(s
, "\tmember: ");
260 setbridge_add(const char *val
, int d
, int s
, const struct afswtch
*afp
)
264 memset(&req
, 0, sizeof(req
));
265 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
266 if (do_cmd(s
, BRDGADD
, &req
, sizeof(req
), 1) < 0)
267 err(1, "BRDGADD %s", val
);
271 setbridge_delete(const char *val
, int d
, int s
, const struct afswtch
*afp
)
275 memset(&req
, 0, sizeof(req
));
276 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
277 if (do_cmd(s
, BRDGDEL
, &req
, sizeof(req
), 1) < 0)
278 err(1, "BRDGDEL %s", val
);
282 setbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
285 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 1);
289 unsetbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
292 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 0);
296 setbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
299 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 1);
303 unsetbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
306 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 0);
310 setbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
314 memset(&req
, 0, sizeof(req
));
315 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
316 if (do_cmd(s
, BRDGADDS
, &req
, sizeof(req
), 1) < 0)
317 err(1, "BRDGADDS %s", val
);
321 unsetbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
325 memset(&req
, 0, sizeof(req
));
326 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
327 if (do_cmd(s
, BRDGDELS
, &req
, sizeof(req
), 1) < 0)
328 err(1, "BRDGDELS %s", val
);
332 setbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
335 do_bridgeflag(s
, val
, IFBIF_STP
, 1);
339 unsetbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
342 do_bridgeflag(s
, val
, IFBIF_STP
, 0);
346 setbridge_flush(const char *val
, int d
, int s
, const struct afswtch
*afp
)
350 memset(&req
, 0, sizeof(req
));
351 req
.ifbr_ifsflags
= IFBF_FLUSHDYN
;
352 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
357 setbridge_flushall(const char *val
, int d
, int s
, const struct afswtch
*afp
)
361 memset(&req
, 0, sizeof(req
));
362 req
.ifbr_ifsflags
= IFBF_FLUSHALL
;
363 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
368 setbridge_static(const char *val
, const char *mac
, int s
,
369 const struct afswtch
*afp
)
372 struct ether_addr
*ea
;
374 memset(&req
, 0, sizeof(req
));
375 strlcpy(req
.ifba_ifsname
, val
, sizeof(req
.ifba_ifsname
));
377 ea
= ether_aton(mac
);
379 errx(1, "%s: invalid address: %s", val
, mac
);
381 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
382 req
.ifba_flags
= IFBAF_STATIC
;
384 if (do_cmd(s
, BRDGSADDR
, &req
, sizeof(req
), 1) < 0)
385 err(1, "BRDGSADDR %s", val
);
389 setbridge_deladdr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
392 struct ether_addr
*ea
;
394 memset(&req
, 0, sizeof(req
));
396 ea
= ether_aton(val
);
398 errx(1, "invalid address: %s", val
);
400 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
402 if (do_cmd(s
, BRDGDADDR
, &req
, sizeof(req
), 1) < 0)
403 err(1, "BRDGDADDR %s", val
);
407 getbridge_addr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
409 bridge_addresses(s
, "");
413 setbridge_maxaddr(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
415 struct ifbrparam param
;
418 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
419 errx(1, "invalid value: %s", arg
);
421 param
.ifbrp_csize
= val
& 0xffffffff;
423 if (do_cmd(s
, BRDGSCACHE
, ¶m
, sizeof(param
), 1) < 0)
424 err(1, "BRDGSCACHE %s", arg
);
428 setbridge_hellotime(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
430 struct ifbrparam param
;
433 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
434 errx(1, "invalid value: %s", arg
);
436 param
.ifbrp_hellotime
= val
& 0xff;
438 if (do_cmd(s
, BRDGSHT
, ¶m
, sizeof(param
), 1) < 0)
439 err(1, "BRDGSHT %s", arg
);
443 setbridge_fwddelay(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
445 struct ifbrparam param
;
448 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
449 errx(1, "invalid value: %s", arg
);
451 param
.ifbrp_fwddelay
= val
& 0xff;
453 if (do_cmd(s
, BRDGSFD
, ¶m
, sizeof(param
), 1) < 0)
454 err(1, "BRDGSFD %s", arg
);
458 setbridge_maxage(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
460 struct ifbrparam param
;
463 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
464 errx(1, "invalid value: %s", arg
);
466 param
.ifbrp_maxage
= val
& 0xff;
468 if (do_cmd(s
, BRDGSMA
, ¶m
, sizeof(param
), 1) < 0)
469 err(1, "BRDGSMA %s", arg
);
473 setbridge_priority(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
475 struct ifbrparam param
;
478 if (get_val(arg
, &val
) < 0 || (val
& ~0xffff) != 0)
479 errx(1, "invalid value: %s", arg
);
481 param
.ifbrp_prio
= val
& 0xffff;
483 if (do_cmd(s
, BRDGSPRI
, ¶m
, sizeof(param
), 1) < 0)
484 err(1, "BRDGSPRI %s", arg
);
488 setbridge_ifpriority(const char *ifn
, const char *pri
, int s
,
489 const struct afswtch
*afp
)
494 memset(&req
, 0, sizeof(req
));
496 if (get_val(pri
, &val
) < 0 || (val
& ~0xff) != 0)
497 errx(1, "invalid value: %s", pri
);
499 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
500 req
.ifbr_priority
= val
& 0xff;
502 if (do_cmd(s
, BRDGSIFPRIO
, &req
, sizeof(req
), 1) < 0)
503 err(1, "BRDGSIFPRIO %s", pri
);
507 setbridge_ifpathcost(const char *ifn
, const char *cost
, int s
,
508 const struct afswtch
*afp
)
513 memset(&req
, 0, sizeof(req
));
515 if (get_val(cost
, &val
) < 0 || (val
& ~0xff) != 0)
516 errx(1, "invalid value: %s", cost
);
518 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
519 req
.ifbr_path_cost
= val
& 0xffff;
521 if (do_cmd(s
, BRDGSIFCOST
, &req
, sizeof(req
), 1) < 0)
522 err(1, "BRDGSIFCOST %s", cost
);
526 setbridge_ifbondweight(const char *ifn
, const char *cost
, int s
,
527 const struct afswtch
*afp
)
532 memset(&req
, 0, sizeof(req
));
534 if (get_val(cost
, &val
) < 0 || (val
& ~0xff) != 0)
535 errx(1, "invalid value: %s", cost
);
537 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
540 req
.ifbr_bond_weight
= (uint16_t)val
;
542 if (do_cmd(s
, BRDGSBONDWGHT
, &req
, sizeof(req
), 1) < 0)
543 err(1, "BRDGSBONDWGHT %s", cost
);
547 setbridge_timeout(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
549 struct ifbrparam param
;
552 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
553 errx(1, "invalid value: %s", arg
);
555 param
.ifbrp_ctime
= val
& 0xffffffff;
557 if (do_cmd(s
, BRDGSTO
, ¶m
, sizeof(param
), 1) < 0)
558 err(1, "BRDGSTO %s", arg
);
561 static struct cmd bridge_cmds
[] = {
562 DEF_CMD_ARG("addm", setbridge_add
),
563 DEF_CMD_ARG("deletem", setbridge_delete
),
564 DEF_CMD_ARG("discover", setbridge_discover
),
565 DEF_CMD_ARG("-discover", unsetbridge_discover
),
566 DEF_CMD_ARG("learn", setbridge_learn
),
567 DEF_CMD_ARG("-learn", unsetbridge_learn
),
568 DEF_CMD_ARG("span", setbridge_span
),
569 DEF_CMD_ARG("-span", unsetbridge_span
),
570 DEF_CMD_ARG("stp", setbridge_stp
),
571 DEF_CMD_ARG("-stp", unsetbridge_stp
),
572 DEF_CMD("flush", 0, setbridge_flush
),
573 DEF_CMD("flushall", 0, setbridge_flushall
),
574 DEF_CMD_ARG2("static", setbridge_static
),
575 DEF_CMD_ARG("deladdr", setbridge_deladdr
),
576 DEF_CMD("addr", 1, getbridge_addr
),
577 DEF_CMD_ARG("maxaddr", setbridge_maxaddr
),
578 DEF_CMD_ARG("hellotime", setbridge_hellotime
),
579 DEF_CMD_ARG("fwddelay", setbridge_fwddelay
),
580 DEF_CMD_ARG("maxage", setbridge_maxage
),
581 DEF_CMD_ARG("priority", setbridge_priority
),
582 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority
),
583 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost
),
584 DEF_CMD_ARG2("ifbondweight", setbridge_ifbondweight
),
585 DEF_CMD_ARG("timeout", setbridge_timeout
),
587 static struct afswtch af_bridge
= {
588 .af_name
= "af_bridge",
590 .af_other_status
= bridge_status
,
593 static __constructor(101) void
596 #define N(a) (sizeof(a) / sizeof(a[0]))
599 for (i
= 0; i
< N(bridge_cmds
); i
++)
600 cmd_register(&bridge_cmds
[i
]);
601 af_register(&af_bridge
);