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 $
36 * $DragonFly: src/sbin/ifconfig/ifbridge.c,v 1.2 2006/06/30 16:50:01 geekgod Exp $
39 #include <sys/param.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
47 #include <net/ethernet.h>
49 #include <net/bridge/if_bridgevar.h>
50 #include <net/route.h>
63 get_val(const char *cp
, u_long
*valp
)
69 val
= strtoul(cp
, &endptr
, 0);
70 if (cp
[0] == '\0' || endptr
[0] != '\0' || errno
== ERANGE
)
78 do_cmd(int sock
, u_long op
, void *arg
, size_t argsize
, int set
)
82 memset(&ifd
, 0, sizeof(ifd
));
84 strlcpy(ifd
.ifd_name
, ifr
.ifr_name
, sizeof(ifd
.ifd_name
));
86 ifd
.ifd_len
= argsize
;
89 return (ioctl(sock
, set
? SIOCSDRVSPEC
: SIOCGDRVSPEC
, &ifd
));
93 do_bridgeflag(int sock
, const char *ifs
, int flag
, int set
)
97 strlcpy(req
.ifbr_ifsname
, ifs
, sizeof(req
.ifbr_ifsname
));
99 if (do_cmd(sock
, BRDGGIFFLGS
, &req
, sizeof(req
), 0) < 0)
100 err(1, "unable to get bridge flags");
103 req
.ifbr_ifsflags
|= flag
;
105 req
.ifbr_ifsflags
&= ~flag
;
107 if (do_cmd(sock
, BRDGSIFFLGS
, &req
, sizeof(req
), 1) < 0)
108 err(1, "unable to set bridge flags");
112 bridge_interfaces(int s
, const char *prefix
)
114 static const char *stpstates
[] = {
121 struct ifbifconf bifc
;
123 char *inbuf
= NULL
, *ninbuf
;
127 pad
= strdup(prefix
);
130 /* replace the prefix with whitespace */
131 for (p
= pad
; *p
!= '\0'; p
++) {
137 ninbuf
= realloc(inbuf
, len
);
139 err(1, "unable to allocate interface buffer");
140 bifc
.ifbic_len
= len
;
141 bifc
.ifbic_buf
= inbuf
= ninbuf
;
142 if (do_cmd(s
, BRDGGIFS
, &bifc
, sizeof(bifc
), 0) < 0)
143 err(1, "unable to get interface list");
144 if ((bifc
.ifbic_len
+ sizeof(*req
)) < len
)
149 for (i
= 0; i
< bifc
.ifbic_len
/ sizeof(*req
); i
++) {
150 req
= bifc
.ifbic_req
+ i
;
151 printf("%s%s ", prefix
, req
->ifbr_ifsname
);
152 printb("flags", req
->ifbr_ifsflags
, IFBIFBITS
);
155 if (req
->ifbr_ifsflags
& IFBIF_STP
) {
157 printf("port %u priority %u",
158 req
->ifbr_portno
, req
->ifbr_priority
);
159 printf(" path cost %u", req
->ifbr_path_cost
);
160 if (req
->ifbr_state
<
161 sizeof(stpstates
) / sizeof(stpstates
[0]))
162 printf(" %s", stpstates
[req
->ifbr_state
]);
164 printf(" <unknown state %d>",
174 bridge_addresses(int s
, const char *prefix
)
176 struct ifbaconf ifbac
;
177 struct ifbareq
*ifba
;
178 char *inbuf
= NULL
, *ninbuf
;
180 struct ether_addr ea
;
183 ninbuf
= realloc(inbuf
, len
);
185 err(1, "unable to allocate address buffer");
186 ifbac
.ifbac_len
= len
;
187 ifbac
.ifbac_buf
= inbuf
= ninbuf
;
188 if (do_cmd(s
, BRDGRTS
, &ifbac
, sizeof(ifbac
), 0) < 0)
189 err(1, "unable to get address cache");
190 if ((ifbac
.ifbac_len
+ sizeof(*ifba
)) < len
)
195 for (i
= 0; i
< ifbac
.ifbac_len
/ sizeof(*ifba
); i
++) {
196 ifba
= ifbac
.ifbac_req
+ i
;
197 memcpy(ea
.octet
, ifba
->ifba_dst
,
199 printf("%s%s %s %lu ", prefix
, ether_ntoa(&ea
),
200 ifba
->ifba_ifsname
, ifba
->ifba_expire
);
201 printb("flags", ifba
->ifba_flags
, IFBAFBITS
);
211 struct ifbrparam param
;
215 if (do_cmd(s
, BRDGGPRI
, ¶m
, sizeof(param
), 0) < 0)
217 pri
= param
.ifbrp_prio
;
219 if (do_cmd(s
, BRDGGHT
, ¶m
, sizeof(param
), 0) < 0)
221 ht
= param
.ifbrp_hellotime
;
223 if (do_cmd(s
, BRDGGFD
, ¶m
, sizeof(param
), 0) < 0)
225 fd
= param
.ifbrp_fwddelay
;
227 if (do_cmd(s
, BRDGGMA
, ¶m
, sizeof(param
), 0) < 0)
229 ma
= param
.ifbrp_maxage
;
231 printf("\tpriority %u hellotime %u fwddelay %u maxage %u\n",
234 bridge_interfaces(s
, "\tmember: ");
241 setbridge_add(const char *val
, int d
, int s
, const struct afswtch
*afp
)
245 memset(&req
, 0, sizeof(req
));
246 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
247 if (do_cmd(s
, BRDGADD
, &req
, sizeof(req
), 1) < 0)
248 err(1, "BRDGADD %s", val
);
252 setbridge_delete(const char *val
, int d
, int s
, const struct afswtch
*afp
)
256 memset(&req
, 0, sizeof(req
));
257 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
258 if (do_cmd(s
, BRDGDEL
, &req
, sizeof(req
), 1) < 0)
259 err(1, "BRDGDEL %s", val
);
263 setbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
266 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 1);
270 unsetbridge_discover(const char *val
, int d
, int s
, const struct afswtch
*afp
)
273 do_bridgeflag(s
, val
, IFBIF_DISCOVER
, 0);
277 setbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
280 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 1);
284 unsetbridge_learn(const char *val
, int d
, int s
, const struct afswtch
*afp
)
287 do_bridgeflag(s
, val
, IFBIF_LEARNING
, 0);
291 setbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
295 memset(&req
, 0, sizeof(req
));
296 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
297 if (do_cmd(s
, BRDGADDS
, &req
, sizeof(req
), 1) < 0)
298 err(1, "BRDGADDS %s", val
);
302 unsetbridge_span(const char *val
, int d
, int s
, const struct afswtch
*afp
)
306 memset(&req
, 0, sizeof(req
));
307 strlcpy(req
.ifbr_ifsname
, val
, sizeof(req
.ifbr_ifsname
));
308 if (do_cmd(s
, BRDGDELS
, &req
, sizeof(req
), 1) < 0)
309 err(1, "BRDGDELS %s", val
);
313 setbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
316 do_bridgeflag(s
, val
, IFBIF_STP
, 1);
320 unsetbridge_stp(const char *val
, int d
, int s
, const struct afswtch
*afp
)
323 do_bridgeflag(s
, val
, IFBIF_STP
, 0);
327 setbridge_flush(const char *val
, int d
, int s
, const struct afswtch
*afp
)
331 memset(&req
, 0, sizeof(req
));
332 req
.ifbr_ifsflags
= IFBF_FLUSHDYN
;
333 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
338 setbridge_flushall(const char *val
, int d
, int s
, const struct afswtch
*afp
)
342 memset(&req
, 0, sizeof(req
));
343 req
.ifbr_ifsflags
= IFBF_FLUSHALL
;
344 if (do_cmd(s
, BRDGFLUSH
, &req
, sizeof(req
), 1) < 0)
349 setbridge_static(const char *val
, const char *mac
, int s
,
350 const struct afswtch
*afp
)
353 struct ether_addr
*ea
;
355 memset(&req
, 0, sizeof(req
));
356 strlcpy(req
.ifba_ifsname
, val
, sizeof(req
.ifba_ifsname
));
358 ea
= ether_aton(mac
);
360 errx(1, "%s: invalid address: %s", val
, mac
);
362 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
363 req
.ifba_flags
= IFBAF_STATIC
;
365 if (do_cmd(s
, BRDGSADDR
, &req
, sizeof(req
), 1) < 0)
366 err(1, "BRDGSADDR %s", val
);
370 setbridge_deladdr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
373 struct ether_addr
*ea
;
375 memset(&req
, 0, sizeof(req
));
377 ea
= ether_aton(val
);
379 errx(1, "invalid address: %s", val
);
381 memcpy(req
.ifba_dst
, ea
->octet
, sizeof(req
.ifba_dst
));
383 if (do_cmd(s
, BRDGDADDR
, &req
, sizeof(req
), 1) < 0)
384 err(1, "BRDGDADDR %s", val
);
388 getbridge_addr(const char *val
, int d
, int s
, const struct afswtch
*afp
)
390 bridge_addresses(s
, "");
394 setbridge_maxaddr(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
396 struct ifbrparam param
;
399 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
400 errx(1, "invalid value: %s", arg
);
402 param
.ifbrp_csize
= val
& 0xffffffff;
404 if (do_cmd(s
, BRDGSCACHE
, ¶m
, sizeof(param
), 1) < 0)
405 err(1, "BRDGSCACHE %s", arg
);
409 setbridge_hellotime(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
411 struct ifbrparam param
;
414 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
415 errx(1, "invalid value: %s", arg
);
417 param
.ifbrp_hellotime
= val
& 0xff;
419 if (do_cmd(s
, BRDGSHT
, ¶m
, sizeof(param
), 1) < 0)
420 err(1, "BRDGSHT %s", arg
);
424 setbridge_fwddelay(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
426 struct ifbrparam param
;
429 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
430 errx(1, "invalid value: %s", arg
);
432 param
.ifbrp_fwddelay
= val
& 0xff;
434 if (do_cmd(s
, BRDGSFD
, ¶m
, sizeof(param
), 1) < 0)
435 err(1, "BRDGSFD %s", arg
);
439 setbridge_maxage(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
441 struct ifbrparam param
;
444 if (get_val(arg
, &val
) < 0 || (val
& ~0xff) != 0)
445 errx(1, "invalid value: %s", arg
);
447 param
.ifbrp_maxage
= val
& 0xff;
449 if (do_cmd(s
, BRDGSMA
, ¶m
, sizeof(param
), 1) < 0)
450 err(1, "BRDGSMA %s", arg
);
454 setbridge_priority(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
456 struct ifbrparam param
;
459 if (get_val(arg
, &val
) < 0 || (val
& ~0xffff) != 0)
460 errx(1, "invalid value: %s", arg
);
462 param
.ifbrp_prio
= val
& 0xffff;
464 if (do_cmd(s
, BRDGSPRI
, ¶m
, sizeof(param
), 1) < 0)
465 err(1, "BRDGSPRI %s", arg
);
469 setbridge_ifpriority(const char *ifn
, const char *pri
, int s
,
470 const struct afswtch
*afp
)
475 memset(&req
, 0, sizeof(req
));
477 if (get_val(pri
, &val
) < 0 || (val
& ~0xff) != 0)
478 errx(1, "invalid value: %s", pri
);
480 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
481 req
.ifbr_priority
= val
& 0xff;
483 if (do_cmd(s
, BRDGSIFPRIO
, &req
, sizeof(req
), 1) < 0)
484 err(1, "BRDGSIFPRIO %s", pri
);
488 setbridge_ifpathcost(const char *ifn
, const char *cost
, int s
,
489 const struct afswtch
*afp
)
494 memset(&req
, 0, sizeof(req
));
496 if (get_val(cost
, &val
) < 0 || (val
& ~0xff) != 0)
497 errx(1, "invalid value: %s", cost
);
499 strlcpy(req
.ifbr_ifsname
, ifn
, sizeof(req
.ifbr_ifsname
));
500 req
.ifbr_path_cost
= val
& 0xffff;
502 if (do_cmd(s
, BRDGSIFCOST
, &req
, sizeof(req
), 1) < 0)
503 err(1, "BRDGSIFCOST %s", cost
);
507 setbridge_timeout(const char *arg
, int d
, int s
, const struct afswtch
*afp
)
509 struct ifbrparam param
;
512 if (get_val(arg
, &val
) < 0 || (val
& ~0xffffffff) != 0)
513 errx(1, "invalid value: %s", arg
);
515 param
.ifbrp_ctime
= val
& 0xffffffff;
517 if (do_cmd(s
, BRDGSTO
, ¶m
, sizeof(param
), 1) < 0)
518 err(1, "BRDGSTO %s", arg
);
521 static struct cmd bridge_cmds
[] = {
522 DEF_CMD_ARG("addm", setbridge_add
),
523 DEF_CMD_ARG("deletem", setbridge_delete
),
524 DEF_CMD_ARG("discover", setbridge_discover
),
525 DEF_CMD_ARG("-discover", unsetbridge_discover
),
526 DEF_CMD_ARG("learn", setbridge_learn
),
527 DEF_CMD_ARG("-learn", unsetbridge_learn
),
528 DEF_CMD_ARG("span", setbridge_span
),
529 DEF_CMD_ARG("-span", unsetbridge_span
),
530 DEF_CMD_ARG("stp", setbridge_stp
),
531 DEF_CMD_ARG("-stp", unsetbridge_stp
),
532 DEF_CMD("flush", 0, setbridge_flush
),
533 DEF_CMD("flushall", 0, setbridge_flushall
),
534 DEF_CMD_ARG2("static", setbridge_static
),
535 DEF_CMD_ARG("deladdr", setbridge_deladdr
),
536 DEF_CMD("addr", 1, getbridge_addr
),
537 DEF_CMD_ARG("maxaddr", setbridge_maxaddr
),
538 DEF_CMD_ARG("hellotime", setbridge_hellotime
),
539 DEF_CMD_ARG("fwddelay", setbridge_fwddelay
),
540 DEF_CMD_ARG("maxage", setbridge_maxage
),
541 DEF_CMD_ARG("priority", setbridge_priority
),
542 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority
),
543 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost
),
544 DEF_CMD_ARG("timeout", setbridge_timeout
),
546 static struct afswtch af_bridge
= {
547 .af_name
= "af_bridge",
549 .af_other_status
= bridge_status
,
552 static __constructor
void
555 #define N(a) (sizeof(a) / sizeof(a[0]))
558 for (i
= 0; i
< N(bridge_cmds
); i
++)
559 cmd_register(&bridge_cmds
[i
]);
560 af_register(&af_bridge
);