diff options
author | Stephen Hemminger <sch@sch-laptop.localdomain> | 2006-07-20 13:59:42 -0400 |
---|---|---|
committer | Stephen Hemminger <sch@sch-laptop.localdomain> | 2006-07-20 13:59:42 -0400 |
commit | 39af7c8f2855c3d9cb44e3069cbfeddd8979acae (patch) | |
tree | b601b0e1fefbb362c06c116c48b9fba196ed4109 | |
parent | 4d480f55ae79cd3b3d1b2681a852e8317a23c977 (diff) | |
download | android_external_brctl-39af7c8f2855c3d9cb44e3069cbfeddd8979acae.tar.gz android_external_brctl-39af7c8f2855c3d9cb44e3069cbfeddd8979acae.tar.bz2 android_external_brctl-39af7c8f2855c3d9cb44e3069cbfeddd8979acae.zip |
Add support for bridge port forwarding.
-rw-r--r-- | brctl/brctl_cmd.c | 70 | ||||
-rw-r--r-- | libbridge/libbridge.h | 3 | ||||
-rw-r--r-- | libbridge/libbridge_if.c | 28 |
3 files changed, 101 insertions, 0 deletions
diff --git a/brctl/brctl_cmd.c b/brctl/brctl_cmd.c index a05d5b1..c1f88c8 100644 --- a/brctl/brctl_cmd.c +++ b/brctl/brctl_cmd.c @@ -157,6 +157,71 @@ static int br_cmd_delif(int argc, char *const* argv) return 0; } + +static int br_cmd_addmirror(int argc, char *const* argv) +{ + int err; + const char *brname = argv[1]; + const char *ifname = argv[2]; + + err = br_set_mirror(brname, ifname); + switch(err) { + case 0: + return 0; + + case ENODEV: + if (if_nametoindex(ifname) == 0) + fprintf(stderr, "interface %s does not exist!\n", ifname); + else + fprintf(stderr, "bridge %s does not exist\n", brname); + break; + + case EBUSY: + fprintf(stderr, "device %s is already a member of a bridge or is a mirror\n", + ifname); + break; + + case ELOOP: + fprintf(stderr, "device %s is a bridge device itself\n", brname); + break; + + default: + fprintf(stderr, "can't set %s to mirror bridge %s: %s\n", + ifname, brname, strerror(err)); + } + return 1; + +} + +static int br_cmd_delmirror(int argc, char *const* argv) +{ + int err; + const char *brname = argv[1]; + const char *ifname = argv[2]; + + + err = br_remove_mirror(brname, ifname); + + switch (err) { + case 0: + return 0; + + case ENODEV: + fprintf(stderr, "interface %s does not exist!\n", ifname); + break; + + case EINVAL: + fprintf(stderr, "device %s is not the mirror of %s\n", + ifname, brname); + break; + + default: + fprintf(stderr, "can't delete %s from %s: %s\n", + ifname, brname, strerror(err)); + } + return 1; +} + static int br_cmd_setageing(int argc, char *const* argv) { int err; @@ -421,6 +486,11 @@ static const struct command commands[] = { "<bridge>\t\tshow bridge stp info"}, { 2, "stp", br_cmd_stp, "<bridge> {on|off}\tturn stp on/off" }, + { 2, "addmirror", br_cmd_addmirror, + "<bridge> <device>\tset mirror to bridge" }, + { 2, "delmirror", br_cmd_delmirror, + "<bridge> <device>\tdelete mirror from bridge" }, + }; const struct command *command_lookup(const char *cmd) diff --git a/libbridge/libbridge.h b/libbridge/libbridge.h index 20d5bb5..8ee94cf 100644 --- a/libbridge/libbridge.h +++ b/libbridge/libbridge.h @@ -95,6 +95,9 @@ extern int br_add_bridge(const char *brname); extern int br_del_bridge(const char *brname); extern int br_add_interface(const char *br, const char *dev); extern int br_del_interface(const char *br, const char *dev); +extern int br_set_mirror(const char *bridge, const char *dev); +extern int br_remove_mirror(const char *bridge, const char *dev); + extern int br_set_bridge_forward_delay(const char *br, struct timeval *tv); extern int br_set_bridge_hello_time(const char *br, struct timeval *tv); extern int br_set_bridge_max_age(const char *br, struct timeval *tv); diff --git a/libbridge/libbridge_if.c b/libbridge/libbridge_if.c index 77d3f8a..b184c46 100644 --- a/libbridge/libbridge_if.c +++ b/libbridge/libbridge_if.c @@ -115,3 +115,31 @@ int br_del_interface(const char *bridge, const char *dev) return err < 0 ? errno : 0; } + +int br_set_mirror(const char *bridge, const char *dev) +{ + struct ifreq ifr; + int ifindex = if_nametoindex(dev); + + if (ifindex == 0) + return ENODEV; + + strncpy(ifr.ifr_name, bridge, IFNAMSIZ); + ifr.ifr_ifindex = ifindex; + + return ioctl(br_socket_fd, SIOCBRADDMIRROR, &ifr); +} + +int br_remove_mirror(const char *bridge, const char *dev) +{ + struct ifreq ifr; + int ifindex = if_nametoindex(dev); + + if (ifindex == 0) + return ENODEV; + + strncpy(ifr.ifr_name, bridge, IFNAMSIZ); + ifr.ifr_ifindex = ifindex; + + return ioctl(br_socket_fd, SIOCBRDELMIRROR, &ifr); +} |