diff options
Diffstat (limited to 'release/src/router/bridge')
40 files changed, 3612 insertions, 0 deletions
diff --git a/release/src/router/bridge/AUTHORS b/release/src/router/bridge/AUTHORS new file mode 100644 index 00000000..14f6fc81 --- /dev/null +++ b/release/src/router/bridge/AUTHORS @@ -0,0 +1 @@ +Lennert Buytenhek <buytenh@gnu.org> diff --git a/release/src/router/bridge/COPYING b/release/src/router/bridge/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/release/src/router/bridge/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/release/src/router/bridge/Makefile b/release/src/router/bridge/Makefile new file mode 100644 index 00000000..d6e7d58c --- /dev/null +++ b/release/src/router/bridge/Makefile @@ -0,0 +1,26 @@ +# $Id: Makefile,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +all: brctl/brctl brctl/brctld misc/bidi misc/tap + +clean: + $(MAKE) -C brctl clean + $(MAKE) -C doc clean + $(MAKE) -C libbridge clean + $(MAKE) -C misc clean + rcsclean * + rm -f *~ + +brctl/brctl: brctl/brctl.c brctl/brctl.h brctl/brctl_cmd.c brctl/brctl_disp.c libbridge/libbridge.a libbridge/libbridge.h + $(MAKE) -C brctl + +brctl/brctld: brctl/brctld.c brctl/brctl.h brctl/brctl_cmd.c brctl/brctl_disp.c libbridge/libbridge.a libbridge/libbridge.h + $(MAKE) -C brctl + +libbridge/libbridge.a: libbridge/if_index.c libbridge/libbridge.h libbridge/libbridge_compat.c libbridge/libbridge_devif.c libbridge/libbridge_if.c libbridge/libbridge_init.c libbridge/libbridge_misc.c libbridge/libbridge_private.h + $(MAKE) -C libbridge + +misc/bidi: misc/bidi.c + $(MAKE) -C misc + +misc/tap: misc/tap.c + $(MAKE) -C misc diff --git a/release/src/router/bridge/README b/release/src/router/bridge/README new file mode 100644 index 00000000..fbba2c28 --- /dev/null +++ b/release/src/router/bridge/README @@ -0,0 +1,68 @@ +$Id: README,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + + +Hi there! + +In this package you'll find the new-and-improved linux ethernet +bridging code. I (Lennert Buytenhek) rewrote the linux bridging code +over the last few months because the old code was a big mess and +nonextensible. + +Snapshots of the new code are published at: +http://openrock.net/bridge and +ftp://openrock.net/bridge + + + +Advantages of the new code are: +- Support for multiple bridge port groups (i.e. multiple independent + bridges in one machine). +- Each bridge is seen as a logical device, which allows you to do + firewalling between port groups for example. +- Everything is dynamic; bridges are created dynamically using the + userspace configuration tool, ports are 'enslaved' dynamically, etc. +- It is being actively maintained. +- It uses a hash table for MAC addresses, not an AVL tree. +- It's small (currently 4 pages of i386 code) and modular. +- The source isn't a mess. +- It works as a module. + + +If you have any comments, questions or suggestions, please visit +http://openrock.net and look for the bridge mailing list. Or +mail me directly at buytenh@openrock.net. + + + +Have fun! +Lennert Buytenhek +<buytenh@openrock.net> + + + + +Files in this package: + +AUTHORS Authors of this package + +COPYING The GNU General Public License. + +Makefile Recursive Makefile. + +README This file. + +brctl/ The new-and-improved userspace bridge configuration + tool. + +bridge-utils.spec + A .spec file for Red Hat package building. "rpm -tb + <tar.gz file>" ought to give you a .RPM file. + +doc/ Some documentation files. + +libbridge/ The bridge configuration interface library. + +misc/ Miscellaneous utilities. + +scripts/ A directory containing some shell scripts for setting + up bridge configurations that I use for testing. diff --git a/release/src/router/bridge/THANKS b/release/src/router/bridge/THANKS new file mode 100644 index 00000000..8c8ec88b --- /dev/null +++ b/release/src/router/bridge/THANKS @@ -0,0 +1,43 @@ +$Id: THANKS,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Thanks go to: + +F. Nicolaas Benders <benders@pinpoint.com> +Lars Bohn <lars-erik-christian.bohn@student.uni-ulm.de> +Jim Chapman <jim.chapman@iname.com> +Robert Collier <rob@lspace.org> +Steven Dewinter <steven@zeus.rug.ac.be> +Arne Fitzenreiter <arne.fitzenreiter@gmx.de> +Alejando Garcia <alexgc@edu.aytolacoruna.es> +Matthew Grant <grantma@anathoth.gen.nz> +Mark Hahn <hahn@coffee.psychology.mcmaster.ca> +Oskari Jaaskelainen <osi@fyslab.hut.fi> +Joshua Jensen <joshua@redhat.com> +Jason Lambert <jlambert@lambert-comm.net> +Christoph Lameter <christoph@lameter.com> +Miles Lane <miles@amazon.com> +Janne Liimatainen <liimjann@trade.hamkk.fi> +Benoit Locher <themagpie@wanadoo.fr> +Daniel Lopez <daniel@rawbyte.com> +Stuart Lynne <sdjl@fireplug.net> +Andrew McRory <amacc@iron-bridge.net> +David S. Miller <davem@redhat.com> +Philippe Moutarlier <philippe@kscable.com> +Petr Novopashenniy <pety@au.ru> +Monte Ohrt <monte@ispi.net> +Joachim Ott <ott@ardala.han.de> +Kristian Rietveld <kristian@planet.nl> +Jacob Schroeder <jacob@quantec.de> +Heikki Vatiainen <hessu@cs.tut.fi> +Ernest Yik <ernestyik@cuhk.edu.hk> + + + + +I would also like to thank: + +Jacobine Bakker <jbakker@math.leidenuniv.nl> +Annelies Hafkenscheid <haf@math.leidenuniv.nl> +Jasper de Koning <jdekonin@math.leidenuniv.nl> +Margaret Suda <ps@is.usmo.com> +Marloes van der Valk <keesvalk@kabelfoon.nl> diff --git a/release/src/router/bridge/brctl/Makefile b/release/src/router/bridge/brctl/Makefile new file mode 100644 index 00000000..9d15ea39 --- /dev/null +++ b/release/src/router/bridge/brctl/Makefile @@ -0,0 +1,36 @@ +# +# $Id: Makefile,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +CFLAGS = -Wall -g -O2 -I../libbridge +LDFLAGS = -g +ifeq ($(strip $(DOSTATIC)),true) + LDFLAGS += --static +endif + +all: brctl brctld + +brctl: brctl.o brctl_cmd.o brctl_disp.o ../libbridge/libbridge.a + $(CC) $(LDFLAGS) -o brctl brctl.o brctl_cmd.o brctl_disp.o ../libbridge/libbridge.a + +brctld: brctld.o brctl_cmd.o brctl_disp.o ../libbridge/libbridge.a + $(CC) $(LDFLAGS) -o brctld brctld.o brctl_cmd.o brctl_disp.o ../libbridge/libbridge.a + +clean: + rcsclean * + rm -f *~ + rm -f *.o + rm -f brctl + rm -f brctld + rm -f core + +brctl.o: brctl.c brctl.h + $(CC) $(CFLAGS) -c -o brctl.o brctl.c + +brctld.o: brctld.c brctl.h + $(CC) $(CFLAGS) -c -o brctld.o brctld.c + +brctl_cmd.o: brctl_cmd.c brctl.h + $(CC) $(CFLAGS) -c -o brctl_cmd.o brctl_cmd.c + +brctl_disp.o: brctl_disp.c brctl.h + $(CC) $(CFLAGS) -c -o brctl_disp.o brctl_disp.c diff --git a/release/src/router/bridge/brctl/brctl.c b/release/src/router/bridge/brctl/brctl.c new file mode 100644 index 00000000..5af7ac31 --- /dev/null +++ b/release/src/router/bridge/brctl/brctl.c @@ -0,0 +1,95 @@ +/* + * $Id: brctl.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <asm/param.h> +#include "libbridge.h" +#include "brctl.h" + +char *help_message = +"commands:\n" +"\taddbr\t\t<bridge>\t\tadd bridge\n" +"\taddif\t\t<bridge> <device>\tadd interface to bridge\n" +"\tdelbr\t\t<bridge>\t\tdelete bridge\n" +"\tdelif\t\t<bridge> <device>\tdelete interface from bridge\n" +"\tshow\t\t\t\t\tshow a list of bridges\n" +"\tshowbr\t\t<bridge>\t\tshow bridge info\n" +"\tshowmacs\t<bridge>\t\tshow a list of mac addrs\n" +"\n" +"\tsetageing\t<bridge> <time>\t\tset ageing time\n" +"\tsetbridgeprio\t<bridge> <prio>\t\tset bridge priority\n" +"\tsetfd\t\t<bridge> <time>\t\tset bridge forward delay\n" +"\tsetgcint\t<bridge> <time>\t\tset garbage collection interval\n" +"\tsethello\t<bridge> <time>\t\tset hello time\n" +"\tsetmaxage\t<bridge> <time>\t\tset max message age\n" +"\tsetpathcost\t<bridge> <port> <cost>\tset path cost\n" +"\tsetportprio\t<bridge> <port> <prio>\tset port priority\n" +"\tstp\t\t<bridge> <state>\t{dis,en}able stp\n"; + +void help() +{ + fprintf(stderr, help_message); +} + +int main(int argc, char *argv[]) +{ + int argindex; + struct bridge *br; + struct command *cmd; + + br_init(); + + if (argc < 2) + goto help; + + if ((cmd = br_command_lookup(argv[1])) == NULL) { + fprintf(stderr, "never heard of command [%s]\n", argv[1]); + goto help; + } + + argindex = 2; + br = NULL; + if (cmd->needs_bridge_argument) { + if (argindex >= argc) { + fprintf(stderr, "this option requires a bridge name as argument\n"); + return 1; + } + + br = br_find_bridge(argv[argindex]); + + if (br == NULL) { + fprintf(stderr, "bridge %s doesn't exist!\n", argv[argindex]); + return 1; + } + + argindex++; + } + + cmd->func(br, argv[argindex], argv[argindex+1]); + + return 0; + +help: + help(); + return 1; +} diff --git a/release/src/router/bridge/brctl/brctl.h b/release/src/router/bridge/brctl/brctl.h new file mode 100644 index 00000000..11be2b74 --- /dev/null +++ b/release/src/router/bridge/brctl/brctl.h @@ -0,0 +1,37 @@ +/* + * $Id: brctl.h,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _BRCTL_H +#define _BRCTL_H + +struct command +{ + int needs_bridge_argument; + char *name; + void (*func)(struct bridge *br, char *arg0, char *arg1); +}; + +struct command *br_command_lookup(char *cmd); +void br_dump_bridge_id(unsigned char *x); +void br_show_timer(struct timeval *tv); +void br_dump_port_info(struct port *p); +void br_dump_info(struct bridge *br); + +#endif diff --git a/release/src/router/bridge/brctl/brctl_cmd.c b/release/src/router/bridge/brctl/brctl_cmd.c new file mode 100644 index 00000000..9cda5ed8 --- /dev/null +++ b/release/src/router/bridge/brctl/brctl_cmd.c @@ -0,0 +1,322 @@ +/* + * $Id: brctl_cmd.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <errno.h> +#include <asm/param.h> +#include "libbridge.h" +#include "brctl.h" + +void br_cmd_addbr(struct bridge *br, char *brname, char *arg1) +{ + int err; + + if ((err = br_add_bridge(brname)) == 0) + return; + + switch (err) { + case EEXIST: + fprintf(stderr, "device %s already exists; can't create " + "bridge with the same name\n", brname); + break; + + default: + perror("br_add_bridge"); + break; + } +} + +void br_cmd_delbr(struct bridge *br, char *brname, char *arg1) +{ + int err; + + if ((err = br_del_bridge(brname)) == 0) + return; + + switch (err) { + case ENXIO: + fprintf(stderr, "bridge %s doesn't exist; can't delete it\n", + brname); + break; + + case EBUSY: + fprintf(stderr, "bridge %s is still up; can't delete it\n", + brname); + break; + + default: + perror("br_del_bridge"); + break; + } +} + +void br_cmd_addif(struct bridge *br, char *ifname, char *arg1) +{ + int err; + int ifindex; + + ifindex = if_nametoindex(ifname); + if (!ifindex) { + fprintf(stderr, "interface %s does not exist!\n", ifname); + return; + } + + if ((err = br_add_interface(br, ifindex)) == 0) + return; + + switch (err) { + case EBUSY: + fprintf(stderr, "device %s is already a member of a bridge; " + "can't enslave it to bridge %s.\n", ifname, + br->ifname); + break; + + default: + perror("br_add_interface"); + break; + } +} + +void br_cmd_delif(struct bridge *br, char *ifname, char *arg1) +{ + int err; + int ifindex; + + ifindex = if_nametoindex(ifname); + if (!ifindex) { + fprintf(stderr, "interface %s does not exist!\n", ifname); + return; + } + + if ((err = br_del_interface(br, ifindex)) == 0) + return; + + switch (err) { + case EINVAL: + fprintf(stderr, "device %s is not a slave of %s\n", + ifname, br->ifname); + break; + + default: + perror("br_del_interface"); + break; + } +} + +void br_cmd_setageing(struct bridge *br, char *time, char *arg1) +{ + double secs; + struct timeval tv; + + sscanf(time, "%lf", &secs); + tv.tv_sec = secs; + tv.tv_usec = 1000000 * (secs - tv.tv_sec); + br_set_ageing_time(br, &tv); +} + +void br_cmd_setbridgeprio(struct bridge *br, char *_prio, char *arg1) +{ + int prio; + + sscanf(_prio, "%i", &prio); + br_set_bridge_priority(br, prio); +} + +void br_cmd_setfd(struct bridge *br, char *time, char *arg1) +{ + double secs; + struct timeval tv; + + sscanf(time, "%lf", &secs); + tv.tv_sec = secs; + tv.tv_usec = 1000000 * (secs - tv.tv_sec); + br_set_bridge_forward_delay(br, &tv); +} + +void br_cmd_setgcint(struct bridge *br, char *time, char *arg1) +{ + double secs; + struct timeval tv; + + sscanf(time, "%lf", &secs); + tv.tv_sec = secs; + tv.tv_usec = 1000000 * (secs - tv.tv_sec); + br_set_gc_interval(br, &tv); +} + +void br_cmd_sethello(struct bridge *br, char *time, char *arg1) +{ + double secs; + struct timeval tv; + + sscanf(time, "%lf", &secs); + tv.tv_sec = secs; + tv.tv_usec = 1000000 * (secs - tv.tv_sec); + br_set_bridge_hello_time(br, &tv); +} + +void br_cmd_setmaxage(struct bridge *br, char *time, char *arg1) +{ + double secs; + struct timeval tv; + + sscanf(time, "%lf", &secs); + tv.tv_sec = secs; + tv.tv_usec = 1000000 * (secs - tv.tv_sec); + br_set_bridge_max_age(br, &tv); +} + +void br_cmd_setpathcost(struct bridge *br, char *arg0, char *arg1) +{ + int cost; + struct port *p; + + if ((p = br_find_port(br, arg0)) == NULL) { + fprintf(stderr, "can't find port %s in bridge %s\n", arg0, br->ifname); + return; + } + + sscanf(arg1, "%i", &cost); + br_set_path_cost(p, cost); +} + +void br_cmd_setportprio(struct bridge *br, char *arg0, char *arg1) +{ + int cost; + struct port *p; + + if ((p = br_find_port(br, arg0)) == NULL) { + fprintf(stderr, "can't find port %s in bridge %s\n", arg0, br->ifname); + return; + } + + sscanf(arg1, "%i", &cost); + br_set_port_priority(p, cost); +} + +void br_cmd_stp(struct bridge *br, char *arg0, char *arg1) +{ + int stp; + + stp = 0; + if (!strcmp(arg0, "on") || !strcmp(arg0, "yes") || !strcmp(arg0, "1")) + stp = 1; + + br_set_stp_state(br, stp); +} + +void br_cmd_showbr(struct bridge *br, char *arg0, char *arg1) +{ + br_dump_info(br); +} + +void br_cmd_show(struct bridge *br, char *arg0, char *arg1) +{ + printf("bridge name\tbridge id\t\tSTP enabled\n"); + br = bridge_list; + while (br != NULL) { + printf("%s\t\t", br->ifname); + br_dump_bridge_id((unsigned char *)&br->info.bridge_id); + printf("\t%s\n", br->info.stp_enabled?"yes":"no"); + + br = br->next; + } +} + +static int compare_fdbs(const void *_f0, const void *_f1) +{ + const struct fdb_entry *f0 = _f0; + const struct fdb_entry *f1 = _f1; + + + return memcmp(f0->mac_addr, f1->mac_addr, 6); +} + +void __dump_fdb_entry(struct fdb_entry *f) +{ + printf("%3i\t", f->port_no); + printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t", + f->mac_addr[0], f->mac_addr[1], f->mac_addr[2], + f->mac_addr[3], f->mac_addr[4], f->mac_addr[5]); + printf("%s\t\t", f->is_local?"yes":"no"); + br_show_timer(&f->ageing_timer_value); + printf("\n"); +} + +void br_cmd_showmacs(struct bridge *br, char *arg0, char *arg1) +{ + struct fdb_entry fdb[1024]; + int offset; + + printf("port no\tmac addr\t\tis local?\tageing timer\n"); + + offset = 0; + while (1) { + int i; + int num; + + num = br_read_fdb(br, fdb, offset, 1024); + if (!num) + break; + + qsort(fdb, num, sizeof(struct fdb_entry), compare_fdbs); + + for (i=0;i<num;i++) + __dump_fdb_entry(fdb+i); + + offset += num; + } +} + +static struct command commands[] = { + {0, "addbr", br_cmd_addbr}, + {1, "addif", br_cmd_addif}, + {0, "delbr", br_cmd_delbr}, + {1, "delif", br_cmd_delif}, + {1, "setageing", br_cmd_setageing}, + {1, "setbridgeprio", br_cmd_setbridgeprio}, + {1, "setfd", br_cmd_setfd}, + {1, "setgcint", br_cmd_setgcint}, + {1, "sethello", br_cmd_sethello}, + {1, "setmaxage", br_cmd_setmaxage}, + {1, "setpathcost", br_cmd_setpathcost}, + {1, "setportprio", br_cmd_setportprio}, + {0, "show", br_cmd_show}, + {1, "showbr", br_cmd_showbr}, + {1, "showmacs", br_cmd_showmacs}, + {1, "stp", br_cmd_stp}, +}; + +struct command *br_command_lookup(char *cmd) +{ + int i; + int numcommands; + + numcommands = sizeof(commands)/sizeof(commands[0]); + + for (i=0;i<numcommands;i++) + if (!strcmp(cmd, commands[i].name)) + return &commands[i]; + + return NULL; +} diff --git a/release/src/router/bridge/brctl/brctl_disp.c b/release/src/router/bridge/brctl/brctl_disp.c new file mode 100644 index 00000000..53d10b41 --- /dev/null +++ b/release/src/router/bridge/brctl/brctl_disp.c @@ -0,0 +1,128 @@ +/* + * $Id: brctl_disp.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include "libbridge.h" +#include "brctl.h" + +void br_dump_bridge_id(unsigned char *x) +{ + printf("%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x", x[0], x[1], x[2], x[3], + x[4], x[5], x[6], x[7]); +} + +void br_show_timer(struct timeval *tv) +{ + printf("%4i.%.2i", (int)tv->tv_sec, (int)tv->tv_usec/10000); +} + +void br_dump_port_info(struct port *p) +{ + char ifname[IFNAMSIZ]; + struct port_info *pi; + + pi = &p->info; + + printf("%s (%i)\n", if_indextoname(p->ifindex, ifname), p->index); + printf(" port id\t\t%.4x\t\t\t", pi->port_id); + printf("state\t\t\t%s\n", br_get_state_name(pi->state)); + printf(" designated root\t"); + br_dump_bridge_id((unsigned char *)&pi->designated_root); + printf("\tpath cost\t\t%4i\n", pi->path_cost); + + printf(" designated bridge\t"); + br_dump_bridge_id((unsigned char *)&pi->designated_bridge); + printf("\tmessage age timer\t"); + br_show_timer(&pi->message_age_timer_value); + printf("\n designated port\t%.4x", pi->designated_port); + printf("\t\t\tforward delay timer\t"); + br_show_timer(&pi->forward_delay_timer_value); + printf("\n designated cost\t%4i", pi->designated_cost); + printf("\t\t\thold timer\t\t"); + br_show_timer(&pi->hold_timer_value); + printf("\n flags\t\t\t"); + if (pi->config_pending) + printf("CONFIG_PENDING "); + if (pi->top_change_ack) + printf("TOPOLOGY_CHANGE_ACK "); + printf("\n"); + printf("\n"); +} + +void br_dump_info(struct bridge *br) +{ + struct bridge_info *bri; + struct port *p; + + bri = &br->info; + + printf("%s\n", br->ifname); + if (!bri->stp_enabled) { + printf("\tSTP disabled\n"); + return; + } + + printf(" bridge id\t\t"); + br_dump_bridge_id((unsigned char *)&bri->bridge_id); + printf("\n designated root\t"); + br_dump_bridge_id((unsigned char *)&bri->designated_root); + printf("\n root port\t\t%4i\t\t\t", bri->root_port); + printf("path cost\t\t%4i\n", bri->root_path_cost); + printf(" max age\t\t"); + br_show_timer(&bri->max_age); + printf("\t\t\tbridge max age\t\t"); + br_show_timer(&bri->bridge_max_age); + printf("\n hello time\t\t"); + br_show_timer(&bri->hello_time); + printf("\t\t\tbridge hello time\t"); + br_show_timer(&bri->bridge_hello_time); + printf("\n forward delay\t\t"); + br_show_timer(&bri->forward_delay); + printf("\t\t\tbridge forward delay\t"); + br_show_timer(&bri->bridge_forward_delay); + printf("\n ageing time\t\t"); + br_show_timer(&bri->ageing_time); + printf("\t\t\tgc interval\t\t"); + br_show_timer(&bri->gc_interval); + printf("\n hello timer\t\t"); + br_show_timer(&bri->hello_timer_value); + printf("\t\t\ttcn timer\t\t"); + br_show_timer(&bri->tcn_timer_value); + printf("\n topology change timer\t"); + br_show_timer(&bri->topology_change_timer_value); + printf("\t\t\tgc timer\t\t"); + br_show_timer(&bri->gc_timer_value); + printf("\n flags\t\t\t"); + if (bri->topology_change) + printf("TOPOLOGY_CHANGE "); + if (bri->topology_change_detected) + printf("TOPOLOGY_CHANGE_DETECTED "); + printf("\n"); + printf("\n"); + printf("\n"); + + p = br->firstport; + while (p != NULL) { + br_dump_port_info(p); + p = p->next; + } +} diff --git a/release/src/router/bridge/brctl/brctld.c b/release/src/router/bridge/brctl/brctld.c new file mode 100644 index 00000000..2f300c2e --- /dev/null +++ b/release/src/router/bridge/brctl/brctld.c @@ -0,0 +1,210 @@ +/* + * $Id: brctld.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> +#include <signal.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <asm/param.h> +#include "libbridge.h" +#include "brctl.h" + +char *help_message = +"addbr\t\t\t\t\tadd bridge\n" +"addif\t\t\t<device>\tadd interface to bridge\n" +"bridge\t\t\t<bridge>\tselect bridge to work in\n" +"delbr\t\t\t\t\tdelete bridge\n" +"delif\t\t\t<device>\tdelete interface from bridge\n" +"setageing\t\t<time>\t\tset ageing time\n" +"setbridgeprio\t\t<prio>\t\tset bridge priority\n" +"setfd\t\t\t<time>\t\tset bridge forward delay\n" +"setgcint\t\t<time>\t\tset garbage collection interval\n" +"sethello\t\t<time>\t\tset hello time\n" +"setmaxage\t\t<time>\t\tset max message age\n" +"setpathcost\t\t<port> <cost>\tset path cost\n" +"setportprio\t\t<port> <prio>\tset port priority\n" +"show\t\t\t\t\tshow a list of bridges\n" +"showbr\t\t\t\t\tshow bridge info\n" +"showmacs\t\t\t\tshow a list of mac addrs\n" +"stp\t\t\t<state>\t\t{dis,en}able stp\n" +"quit\t\t\t\t\texit this session\n" +"\n"; + +void help() +{ + fprintf(stderr, help_message); +} + +struct bridge *br = NULL; + +int forkaway() +{ + int f; + + f = fork(); + if (f < 0) { + perror("fork"); + exit(-1); + } + + return f; +} + +void runchild(int sock) +{ + char hostname[128]; + + if (forkaway()) + return; + + /* Hack. */ + close(0); dup(sock); + close(1); dup(sock); + close(2); dup(sock); + + br_init(); + gethostname(hostname, 128); + + printf("\n\n\n\n"); + printf("brctld\t\tCopyright (C) 2000 Lennert Buytenhek <buytenh@gnu.org>\n"); + printf("======================================================================"); + printf("\n\n\n\n"); + + while (1) { + char arg0[128]; + char arg1[128]; + char cmd[128]; + struct command *cmdptr; + char line[1024]; + int numcmd; + + printf("<%s> ", hostname); + fflush(stdout); + line[1023] = 0; + fgets(line, 1023, stdin); + while (strlen(line) > 0 && + (line[strlen(line)-1] == '\r' || + line[strlen(line)-1] == '\n')) + line[strlen(line)-1] = 0; + + numcmd = sscanf(line, "%s %s %s", cmd, arg0, arg1); + + if (!strcmp(cmd, "help")) { + help(); + continue; + } else if (!strcmp(cmd, "bridge")) { + if (numcmd != 2) { + fprintf(stderr, "invalid number of arguments\n"); + continue; + } + + br = br_find_bridge(arg0); + if (br != NULL) + printf("now using bridge %s\n\n", arg0); + else + printf("can't find bridge %s\n\n", arg0); + continue; + } else if (!strcmp(cmd, "quit")) { + break; + } + + if ((cmdptr = br_command_lookup(cmd)) == NULL) { + printf("unknown command '%s'\n\n", line); + continue; + } + + if (cmdptr->needs_bridge_argument && br == NULL) { + printf("this command needs a bridge\n\n"); + continue; + } + + br_refresh(); + cmdptr->func(br, arg0, arg1); + printf("\n"); + } + + shutdown(sock, 2); + exit(0); +} + +void sigchild(int sig) +{ + int status; + + wait3(&status, WNOHANG, NULL); +} + +int main(int argc, char *argv[]) +{ + struct sockaddr_in addr; + int sock; + int x; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + return 1; + } + + x = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0) { + perror("setsockopt"); + return 1; + } + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(31338); + if (bind(sock, &addr, sizeof(addr)) < 0) { + perror("bind"); + return 1; + } + + if (listen(sock, 1) < 0) { + perror("listen"); + return 1; + } + + if (forkaway()) + return 0; + + setsid(); + signal(SIGCHLD, sigchild); + + while (1) { + int len; + int newsock; + + len = sizeof(addr); + if ((newsock = accept(sock, &addr, &len)) < 0) { + perror("accept"); + return 1; + } + + runchild(newsock); + } + + return 0; +} diff --git a/release/src/router/bridge/bridge-utils.spec b/release/src/router/bridge/bridge-utils.spec new file mode 100644 index 00000000..484ceba5 --- /dev/null +++ b/release/src/router/bridge/bridge-utils.spec @@ -0,0 +1,68 @@ +# $Id: bridge-utils.spec,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Summary: Utilities for configuring the linux ethernet bridge. +Name: bridge-utils +Version: 0.9.1 +Release: 1 +Copyright: GPL +Group: Applications/System +Source0: ftp://openrock.net/bridge/bridge-utils-%{PACKAGE_VERSION}.tar.gz +BuildRoot: /var/tmp/%{name}-root + +%description +This package contains utilities for configuring the linux ethernet +bridge. The linux ethernet bridge can be used for connecting multiple +ethernet devices together. The connecting is fully transparent: hosts +connected to one ethernet device see hosts connected to the other +ethernet devices directly. + +Install bridge-utils if you want to use the linux ethernet bridge. + +%package -n bridge-utils-devel +Summary: Utilities for configuring the linux ethernet bridge. +Group: Development/Libraries + +%description -n bridge-utils-devel +The bridge-utils-devel package contains the header and object files +necessary for developing programs which use 'libbridge.a', the +interface to the linux kernel ethernet bridge. If you are developing +programs which need to configure the linux ethernet bridge, your +system needs to have these standard header and object files available +in order to create the executables. + +Install bridge-utils-devel if you are going to develop programs which +will use the linux ethernet bridge interface library. + +%prep +%setup -n bridge + +%build +make + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p ${RPM_BUILD_ROOT} +mkdir -p ${RPM_BUILD_ROOT}/sbin +mkdir -p ${RPM_BUILD_ROOT}/usr/include +mkdir -p ${RPM_BUILD_ROOT}/usr/lib +mkdir -p ${RPM_BUILD_ROOT}/usr/man/man8 +mkdir -p ${RPM_BUILD_ROOT}/usr/sbin +strip brctl/brctl +cp brctl/brctl ${RPM_BUILD_ROOT}/sbin +cp doc/brctl.8 ${RPM_BUILD_ROOT}/usr/man/man8 +cp libbridge/libbridge.h ${RPM_BUILD_ROOT}/usr/include +cp libbridge/libbridge.a ${RPM_BUILD_ROOT}/usr/lib + +%clean +rm -rf ${RPM_BUILD_ROOT} + +%files +%defattr (-,root,root) +%doc AUTHORS COPYING doc/FAQ doc/HOWTO doc/RPM-GPG-KEY +/sbin/brctl +/usr/man/man8/brctl.8 + +%files -n bridge-utils-devel +%defattr (-,root,root) +/usr/include/libbridge.h +/usr/lib/libbridge.a diff --git a/release/src/router/bridge/doc/FAQ b/release/src/router/bridge/doc/FAQ new file mode 100644 index 00000000..f70839ce --- /dev/null +++ b/release/src/router/bridge/doc/FAQ @@ -0,0 +1,76 @@ +$Id: FAQ,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +If you have still unanswered questions after reading the HOWTO and the +FAQ, you have found a bug. Please report bugs to bridge@openrock.net +or buytenh@openrock.net. + +Lennert Buytenhek + + + +Questions that were Asked Frequently enough to get listed here +============================================================== + + + +What does a bridge do? +---------------------- + A bridge transparently relays traffic between multiple network + interfaces. In plain English this means that a bridge connects two + or more physical ethernets together to form one bigger (logical) + ethernet. + + +Is it protocol independent? +--------------------------- + Yes. The bridge knows nothing about protocols, it only sees ethernet + frames. As such, the bridging functionality is protocol independent, + and there should be no trouble relaying IPX, NetBEUI, IP, IPv6, etc. + + +How is this bridging stuff different from a so-called 'switch'? +--------------------------------------------------------------- + It isn't. + + +Why is your code better than a switch? +-------------------------------------- + It's more flexible. It allows you to have all kinds of bizarre port + combinations for example (I have actually set up a bridging linux + box with 1 100baseT and 5 10base2 ports in a production + environment. A 10/100Mbit switch plus 5 media converters would have + been way more expensive.) Also, it allows you to set up multiple + bridge port groups. And the standard linux network filtering can be + applied to bridge forwarding (As of Feb 5 this is still a beta + add-on patch, albeit a rock solid one.) + + <digress> + At home, I have joined eth0,eth1,tap0 on my server together into one + bridge (br0). My laptop connects to my server via plip (I haven't + bought a PCMCIA network card yet). tap0 on my laptop is connected to + tap0 on my server via the plip link. This way my laptop is + transparently visible in my home network. No more mucking with proxy + arp et al. It works great. + </digress> + + +My bridge does not show up in traceroute! +----------------------------------------- + It is supposed not to. The operation of a bridge is (supposed to be) + fully transparent to the network, the networks that a bridge + connects together are actually to be viewed as one big + network. That's why the bridge does not show up in traceroute; the + packets do not feel like they are crossing a subnet boundary. + + With routers, this is different. Routers are supposed to show up in + traceroute, because...... [FINISH ME] + + +Are there plans for MAC address filtering? +------------------------------------------ + No. + + However, there is IP filtering (as an add-on patch), maybe this is + what you want? You can find the patch in patches/, filename + bridge-ipchains-*.diff. Apply it on top of the ordinary patch. See + the file FIREWALL in the distribution for more details. diff --git a/release/src/router/bridge/doc/FIREWALL b/release/src/router/bridge/doc/FIREWALL new file mode 100644 index 00000000..5a90832e --- /dev/null +++ b/release/src/router/bridge/doc/FIREWALL @@ -0,0 +1,38 @@ +$Id: FIREWALL,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + + +Several people have asked me for ipchains firewalling on bridge +forwarding. Although this is a violation of the OSI model it turns out +to be very useful, and it was very easy to implement, so I did it. + +Now how does it work? + +First of all, if you want to use bridge firewalling, you'll have to +apply the extra patch bridge-ipchains.diff in the bridge-utils +distribution to your (already patched with the bridge patch) kernel +tree. Recompile the kernel. + +Now if you boot this kernel, the bridging code will check each +to-be-forwarded packet against the ipchains chain which has the same +name as the bridge. So.. if a packet on eth0 is to be forwarded to +eth1, and those interfaces are both part of the bridge group br0, the +bridging code will check the packet against the chain called 'br0'. + +If the chain does not exist, the packet will be forwarded. So if you +want to do firewalling, you'll have to create the chain yourself. This +is important! + + + +Example: +# brctl addbr br0 +# brctl addif br0 eth0 +# brctl addif br0 eth1 +# ifconfig br0 10.0.0.254 +# ipchains -N br0 +# ipchains -A br0 -s 10.0.0.1/8 -i eth0 -j DENY + + + +Lennert Buytenhek +<buytenh@openrock.net> diff --git a/release/src/router/bridge/doc/HOWTO b/release/src/router/bridge/doc/HOWTO new file mode 100644 index 00000000..1e142a0f --- /dev/null +++ b/release/src/router/bridge/doc/HOWTO @@ -0,0 +1,112 @@ +$Id: HOWTO,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Hello everybody, + +Although there is a man page which documents most of the actual +commands, there is still a 'gap' concerning what bridges are, and how +to set them up. This document attempts to fill this gap. + +In fact, this document is a 15-min hack, so feel free to {complain +about,improve on} it. Especially if this document (or the FAQ) does +not tell you what you want to know; I would consider that to be a bug. + + +Have fun! +Lennert Buytenhek + + +<================= CUT HERE AND DAMAGE YOUR SCREEN =================> + + + +1. The basics +------------- + +What does a bridge actually do? In plain English, a bridge connects +two or more different physical ethernets together to form one large +(logical) ethernet. The physical ethernets being connected together +correspond to network interfaces in your linux box. The bigger +(logical) ethernet corresponds to a virtual network interface in linux +(often called br0, br1, br2, etc.) + +Let's say we want to tie eth0 and eth1 together, turning those +networks into one larger network. What do we do? Well, we need to +create an instance of the bridge first. + + # brctl addbr br0 + +(You can check that this gives you a network interface called br0.) +Now we want to enslave eth0 and eth1 to this bridge. + + # brctl addif br0 eth0 + # brctl addif br0 eth1 + +And now... because we connected the two ethernets together, they now +form one large subnet. We are actually only on only one subnet, namely +br0. We can forget about the fact that br0 is actually eth[01] in +disguise; we will only deal with br0 from now on. Because we are only +on one subnet, we only need one IP address for the bridge. This +address we assign to br0. eth0 and eth1 should not have IP addresses +allocated to them. + + # ifconfig eth0 0.0.0.0 + # ifconfig eth1 0.0.0.0 + # ifconfig br0 my.ip.address.here + +The last command also puts the interface br0 into the 'up' state. This +will activate the forwarding of packets, which in plain English means +that from that point on, eth0 and eth1 will be 'joined' +together. Hosts on eth0 should 'see' hosts on eth1 and vice versa. + +The bridge will also (automatically) activate the Spanning Tree +Protocol: this is a network protocol spoken by switches for (roughly +speaking) calculating the shortest distances and eliminating loops in +the topology of the network. You can disable the stp if you really +want/need to; see brctl(8) for details. + + + +2. More complicated setups +-------------------------- + +We can create multiple bridge port groups and do filtering/NATting +between them, just like we can do that with ordinary network +interfaces. + +For example: on a quadport network card, dedicate two ports to a LAN +on which we have IP 10.16.0.254, and the other two ports to a LAN on +which we have IP 192.168.10.1 (this is an actual setup) + + # brctl addbr br_10 + # brctl addif br_10 eth0 + # brctl addif br_10 eth1 + # ifconfig br_10 10.16.0.254 + + # brctl addbr br_192 + # brctl addif br_192 eth2 + # brctl addif br_192 eth3 + # ifconfig br_192 192.168.10.1 + +You now have logical network interfaces br_10 and br_192, which will +act just like ordinary interfaces. The only difference is that they +each correspond to two physical network interfaces, but nobody cares +about that. + +So.. for example, if 192.168.10.2 is the only host on the 192.* +network that is allowed to access the 10.* network, we would do: + +ipchains -P forward REJECT +ipchains -A forward -s 192.168.10.2/32 -d 10.0.0.0/8 -i br_10 -j ACCEPT + +(just like you were used to). + + + + + +Hope this helped. If not, send a cry for help to the mailing list (see +http://openrock.net/mailman/listinfo/bridge for more information), or +send me an email at buytenh@openrock.net + + +That's all folks! diff --git a/release/src/router/bridge/doc/Makefile b/release/src/router/bridge/doc/Makefile new file mode 100644 index 00000000..67e38bb5 --- /dev/null +++ b/release/src/router/bridge/doc/Makefile @@ -0,0 +1,5 @@ +all: FAQ HOWTO PROJECTS RPM-GPG-KEY TODO + +clean: + rcsclean * + rm -f *~ diff --git a/release/src/router/bridge/doc/PROJECTS b/release/src/router/bridge/doc/PROJECTS new file mode 100644 index 00000000..108039d6 --- /dev/null +++ b/release/src/router/bridge/doc/PROJECTS @@ -0,0 +1,4 @@ +$Id: PROJECTS,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +- Kristian Rietveld <kristian@planet.nl> is working on a GNOME + interface. diff --git a/release/src/router/bridge/doc/RPM-GPG-KEY b/release/src/router/bridge/doc/RPM-GPG-KEY new file mode 100644 index 00000000..3f2e7f43 --- /dev/null +++ b/release/src/router/bridge/doc/RPM-GPG-KEY @@ -0,0 +1,32 @@ +$Id: RPM-GPG-KEY,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Hi, + +This public key is the GPG public key I use to sign the bridge-utils +and bridge-utils-devel RPM packages. You can use this key to verify +the integrity of those packages. + +Lennert Buytenhek +<buytenh@gnu.org> + + + + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.0.1 (GNU/Linux) +Comment: For info see http://www.gnupg.org + +mQGiBDiT6YIRBADbn6OduygntL0gYcBD3333gje45DSWl0PVghw9CtJQUZRZSBFp +Z1CgkxI1F3kza4gJwIj/fgtuC8PWi1200rOwCLL8kLkFIH9Zy0VEuXskoXLeDU/f +V14e+9GVtoVLQ5Bx2bTez3+2dEU7N0axKH5MJQsyWZx+U863unNk/qGO1wCgjYZ5 +zKhTuvWnR51tYjdwbfXyq0sD/iflTEUFkQ0MEQc/eJ+RU9kL55GyhT7f227CR6XZ +/d2LCUkdaCdihAsJLXEL66gS7MOUd5I6dolPXG0vG0wQMBqt/jcKr2JRZsSf2Zjg +IxTvlv+6h6LyaHBiq45yCAE1KC2ka2ebtdK0BubdRjKlxDMmGJMrMTeK6RsLbDej +SEhqBACTtgUO9gOAFB53TAAjpftMW91mTOiokg1znKxqunbJ/4Ndo9Z9KI1m4wH8 +RsyGJBEkwlR5PNjnLZbE0ET2hk01RLFWX8yDXORXDx1bkcW/NJgMkyUua3A2QaTV +D1SdIfnMLB2vg4FzjUdo9QXS+zNQ24jS7G6tDq8McvVM2DSwp7Q3TGVubmVydCBC +dXl0ZW5oZWsgKFJQTSBzaWduYXR1cmUga2V5KSA8YnV5dGVuaEBnbnUub3JnPohW +BBMRAgAWBQI4k+mCBAsKBAMDFQMCAxYCAQIXgAAKCRD/CxH2tC7NLt6pAKCGnrIT +EfdFTc5S/Fz+LAYokMWKTwCfU7DQG4bkaOJTcv5fRUOD4UZ2MTk= +=om8h +-----END PGP PUBLIC KEY BLOCK----- diff --git a/release/src/router/bridge/doc/SMPNOTES b/release/src/router/bridge/doc/SMPNOTES new file mode 100644 index 00000000..42ddb698 --- /dev/null +++ b/release/src/router/bridge/doc/SMPNOTES @@ -0,0 +1,23 @@ +$Id: SMPNOTES,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Notes on the (20000210) SMP-ization of the bridging code: + +Each bridge has a hash table of MAC addresses. This table is protected +by a rwlock hash_lock. The entries are refcounted; 'getting' an entry +is done in the usual way: read_lock the table, find the entry, +increment it's refcount and unlock the table. Bottom half context +acquires this lock in read as well as write mode, therefore we always +need to locally disable BHs when acquiring this lock. + +Each bridge also has an rwlock called lock. This slightly misnamed +lock protects the bridge's port_list. All stp code acquires this lock +in read mode, the only piece of code that acquires this lock in write +mode is the ioctl code (br_ioctl.c). Bottom halves never acquire this +lock in write mode, therefore we can use read_lock instead of +read_lock_bh in all cases. + +All ioctls are globally serialized by the semaphore ioctl_mutex. All +code which acquires the bridge lock in write mode also acquires +ioctl_mutex. Therefore, if we have already grabbed ioctl_mutex we +don't need to read_lock the bridge lock anymore; the ioctl_mutex will +protect against concurrent writers. diff --git a/release/src/router/bridge/doc/TODO b/release/src/router/bridge/doc/TODO new file mode 100644 index 00000000..83ce2091 --- /dev/null +++ b/release/src/router/bridge/doc/TODO @@ -0,0 +1,31 @@ +$Id: TODO,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Longer term: + +- We have a tiny deviation from IEEE 802.1d: we don't kill the awaiting-tx + skb queue when a port leaves the FORWARDING state. Not that anyone + should care. But it's there. + +- For the firewall add-on patch: + - Firewalling on input or output interface? + - How do we sort out the module vs. non-module stuff? We can have: + - bridge compiled in, firewall disabled + - bridge compiled in, firewall compiled in + - bridge compiled in, firewall module + - bridge module, firewall disabled + - bridge module, firewall module + +- RH initscripts for setting up bridge interfaces automatically. Right + now, on my home machines, I kludge a bit. Things ought to be + transparent, just like the bonding stuff. + +- The telnet server thingy (brctld) is too limited: it does not do + authentication (should be easy with PAM though), but more + importantly: it does not allow setting up/down of devices and + configuring of IP addresses. Without these, it is essentially useless. + +- Improve documentation: + * man page + * FAQ + * HOWTO + rewrite bridging howtos and update Configure.help to reflect that diff --git a/release/src/router/bridge/doc/WISHLIST b/release/src/router/bridge/doc/WISHLIST new file mode 100644 index 00000000..867c4b48 --- /dev/null +++ b/release/src/router/bridge/doc/WISHLIST @@ -0,0 +1,30 @@ +$Id: WISHLIST,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +Would be nice if: + +- Get the 802.1d tcpdump patch merged into Alexey's version. + +- Kernel driver (a la ipip and ip_gre) which encapsulates raw ethernet + frames in raw IP (proto 97) or UDP/IP packets. + +- Add address learning limiting (hard limit at a fixed # of + addresses? or maybe using rate markers?). There is a nasty DoS in + here. + +- Add fdb entry port # change limiting. For example: if one MAC + address switches port more than once in the same second, there is + something wrong (somebody trying to spoof?), so print a warning. + +- Faster port state cycling; currently it takes 30 seconds for ports + to cycle to the forwarding state. + +- Detect port speed and adjust path cost accordingly? + +- Use MII ioctls for detecting link beat lost quickly? + +- Keep the IEEE 802.1d-mandated statistics (counters, mostly). + +- Maybe integrate Kristian's GNOME frontend (see PROJECTS) once it + stabilises. It looks nice. + +- A cgi bridge configurer (a la Samba's SWAT, yummy....) diff --git a/release/src/router/bridge/doc/brctl.8 b/release/src/router/bridge/doc/brctl.8 new file mode 100644 index 00000000..34ff080c --- /dev/null +++ b/release/src/router/bridge/doc/brctl.8 @@ -0,0 +1,172 @@ +.\" +.\" $Id: brctl.8,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.\" +.TH BRCTL 8 "January 22, 2000" "" "" +.SH NAME +brctl \- ethernet bridge administration +.SH SYNOPSIS +.BR "brctl [command]" +.SH DESCRIPTION +.B brctl +is used to set up, maintain, and inspect the ethernet bridge +configuration in the linux kernel. + +An ethernet bridge is a device commonly used to connect different +networks of ethernets together, so that these ethernets will appear as +one ethernet to the participants. + +Each of the ethernets being connected corresponds to one physical +interface in the bridge. These individual ethernets are bundled into +one bigger ('logical') ethernet, this bigger ethernet corresponds to +the bridge network interface. + + +.SH INSTANCES +The command +.B brctl addbr <name> +creates a new instance of the ethernet bridge. The network interface +corresponding to the bridge will be called <name>. + +The command +.B brctl delbr <name> +deletes the instance <name> of the ethernet bridge. The network +interface corresponding to the bridge must be down before it can be +deleted! + +The command +.B brctl show +shows all current instances of the ethernet bridge. + + +.SH PORTS +Each bridge has a number of ports attached to it. Network traffic +coming in on any of these ports will be forwarded to the other ports +transparently, so that the bridge is invisible to the rest of the +network (i.e. it will not show up in +.IR traceroute(8) +). + +The command +.B brctl addif <brname> <ifname> +will make the interface <ifname> a port of the bridge <brname>. This +means that all frames received on <ifname> will be processed as if +destined for the bridge. Also, when sending frames on <brname>, +<ifname> will be considered as a potential output interface. + +The command +.B brctl delif <brname> <ifname> +will detach the interface <ifname> from the bridge <brname>. + +The command +.B brctl show <brname> +will show some information on the bridge and it's attached ports. + + +.SH AGEING +The bridge keeps track of ethernet addresses seen on each port. When +it needs to forward a frame, and it happens to know on which port the +destination ethernet address (specified in the frame) is located, it +can 'cheat' by forwarding the frame to that port only, thus saving a +lot of redundant copies and transmits. + +However, the ethernet address location data is not static +data. Machines can move to other ports, network cards can be replaced +(which changes the machine's ethernet address), etc. + +.B brctl showmacs <brname> +shows a list of learned MAC addresses for this bridge. + +.B brctl setageingtime <brname> <time> +sets the ethernet (MAC) address ageing time, in seconds. After <time> +seconds of not having seen a frame coming from a certain address, the +bridge will time out (delete) that address from the Forwarding +DataBase (fdb). + +.B brctl setgcint <brname> <time> +sets the garbage collection interval for the bridge <brname> to <time> +seconds. This means that the bridge will check the forwarding database +for timed out entries every <time> seconds. + + +.SH SPANNING TREE PROTOCOL +Multiple ethernet bridges can work together to create even larger +networks of ethernets using the IEEE 802.1d spanning tree +protocol. This protocol is used for finding the shortest path between +two ethernets, and for eliminating loops from the topology. As this +protocol is a standard, linux bridges will interwork properly with +other third party bridge products. Bridges communicate with eachother +by sending and receiving BPDUs (Bridge Protocol Data Units). These +BPDUs can be recognised by an ethernet destination address of +01:80:c2:00:00:00. + +The spanning tree protocol can also be turned off (for those +situations where it just doesn't make sense, for example when this +linux box is the only bridge on the LAN, or when you know that there +are no loops in the topology.) + +.IR brctl(8) +can be used for configuring certain spanning tree protocol +parameters. For an explanation of these parameters, see the IEEE +802.1d specification (or send me an email). The default values should +be just fine. If you don't know what these parameters mean, you +probably won't feel the desire to tweak them. + +.B brctl stp <bridge> <state> +controls this bridge instance's participation in the spanning tree +protocol. When turned off, the bridge will not send or receive BPDUs, +and will thus not participate in the spanning tree protocol. If your +bridge isn't the only bridge on the LAN, or if there are loops in the +LAN's topology, DO NOT turn this option off. If you turn this option +off, please know what you are doing. + + +.B brctl setbridgeprio <bridge> <priority> +sets the bridge's priority to <priority>. The priority value is an +unsigned 16-bit quantity (a number between 0 and 65535), and has no +dimension. Lower priority values are 'better'. The bridge with the +lowest priority will be elected 'root bridge'. + +.B brctl setfd <bridge> <time> +sets the bridge's 'bridge forward delay' to <time> seconds. + +.B brctl sethello <bridge> <time> +sets the bridge's 'bridge hello time' to <time> seconds. + +.B brctl setmaxage <bridge> <time> +sets the bridge's 'maximum message age' to <time> seconds. + +.B brctl setpathcost <bridge> <port> <cost> +sets the port cost of the port <port> to <cost>. This is a +dimensionless metric. + +.B brctl setportprio <bridge> <port> <priority> +sets the port <port>'s priority to <priority>. The priority value is +an unsigned 8-bit quantity (a number between 0 and 255), and has no +dimension. This metric is used in the designated port and root port +selection algorithms. + + +.SH NOTES +.BR brctl(8) +replaces the older brcfg tool. + +.SH SEE ALSO +.BR ipchains(8) + +.SH AUTHOR +Lennert Buytenhek <buytenh@gnu.org> diff --git a/release/src/router/bridge/libbridge/Makefile b/release/src/router/bridge/libbridge/Makefile new file mode 100644 index 00000000..acaf0eb4 --- /dev/null +++ b/release/src/router/bridge/libbridge/Makefile @@ -0,0 +1,28 @@ +CC := $(CC) -Wall -c -g + +all: libbridge.a + +clean: + rcsclean * + rm -f *~ + rm -f *.o + rm -f libbridge.a + +libbridge.a: libbridge_compat.o libbridge_devif.o libbridge_if.o libbridge_init.o libbridge_misc.o + $(AR) rcs libbridge.a libbridge_compat.o libbridge_devif.o libbridge_if.o libbridge_init.o libbridge_misc.o + $(RANLIB) libbridge.a + +libbridge_compat.o: libbridge_compat.c if_index.c + $(CC) -o libbridge_compat.o libbridge_compat.c + +libbridge_devif.o: libbridge_devif.c libbridge.h libbridge_private.h + $(CC) -o libbridge_devif.o libbridge_devif.c + +libbridge_if.o: libbridge_if.c libbridge.h libbridge_private.h + $(CC) -o libbridge_if.o libbridge_if.c + +libbridge_init.o: libbridge_init.c libbridge.h libbridge_private.h + $(CC) -o libbridge_init.o libbridge_init.c + +libbridge_misc.o: libbridge_misc.c libbridge.h libbridge_private.h + $(CC) -o libbridge_misc.o libbridge_misc.c diff --git a/release/src/router/bridge/libbridge/bits/libc-lock.h b/release/src/router/bridge/libbridge/bits/libc-lock.h new file mode 100644 index 00000000..2c1d1627 --- /dev/null +++ b/release/src/router/bridge/libbridge/bits/libc-lock.h @@ -0,0 +1,327 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include <pthread.h> + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#define __libc_lock_init(NAME) \ + (__pthread_mutex_init != NULL ? __pthread_mutex_init (&(NAME), NULL) : 0); +#define __libc_rwlock_init(NAME) \ + (__pthread_rwlock_init != NULL ? __pthread_rwlock_init (&(NAME), NULL) : 0); + +/* Same as last but this time we initialize a recursive mutex. */ +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__pthread_mutex_destroy != NULL ? __pthread_mutex_destroy (&(NAME)) : 0); +#define __libc_rwlock_fini(NAME) \ + (__pthread_rwlock_destroy != NULL ? __pthread_rwlock_destroy (&(NAME)) : 0); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__pthread_mutex_lock != NULL ? __pthread_mutex_lock (&(NAME)) : 0); +#define __libc_rwlock_rdlock(NAME) \ + (__pthread_rwlock_rdlock != NULL ? __pthread_rwlock_rdlock (&(NAME)) : 0); +#define __libc_rwlock_wrlock(NAME) \ + (__pthread_rwlock_wrlock != NULL ? __pthread_rwlock_wrlock (&(NAME)) : 0); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__pthread_mutex_trylock != NULL ? __pthread_mutex_trylock (&(NAME)) : 0) +#define __libc_rwlock_tryrdlock(NAME) \ + (__pthread_rwlock_tryrdlock != NULL \ + ? __pthread_rwlock_tryrdlock (&(NAME)) : 0) +#define __libc_rwlock_trywrlock(NAME) \ + (__pthread_rwlock_trywrlock != NULL \ + ? __pthread_rwlock_trywrlock (&(NAME)) : 0) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__pthread_mutex_unlock != NULL ? __pthread_mutex_unlock (&(NAME)) : 0); +#define __libc_rwlock_unlock(NAME) \ + (__pthread_rwlock_unlock != NULL ? __pthread_rwlock_unlock (&(NAME)) : 0); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__pthread_key_create != NULL ? __pthread_key_create (KEY, DESTRUCTOR) : 1) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__pthread_getspecific != NULL ? __pthread_getspecific (KEY) : NULL) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__pthread_setspecific != NULL ? __pthread_setspecific (KEY, VALUE) : 0) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__pthread_atfork != NULL ? __pthread_atfork (PREPARE, PARENT, CHILD) : 0) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# if _LIBC +# include <bp-sym.h> +# else +# define BP_SYM (sym) sym +# endif +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# endif +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/release/src/router/bridge/libbridge/if_index.c b/release/src/router/bridge/libbridge/if_index.c new file mode 100644 index 00000000..54ced95c --- /dev/null +++ b/release/src/router/bridge/libbridge/if_index.c @@ -0,0 +1,263 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <net/if.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#if __GLIBC_MINOR__ < 1 +#include <libc-lock.h> +#else +#include "bits/libc-lock.h" +#endif + +/* Try to get a socket to talk to the kernel. */ +#if defined SIOCGIFINDEX || defined SIOCGIFNAME +static int +internal_function +opensock (void) +{ + /* Cache the last AF that worked, to avoid many redundant calls to + socket(). */ + static int sock_af = -1; + int fd = -1; + __libc_lock_define_initialized (static, lock); + + if (sock_af != -1) + { + fd = __socket (sock_af, SOCK_DGRAM, 0); + if (fd != -1) + return fd; + } + + __libc_lock_lock (lock); + + if (sock_af != -1) + fd = __socket (sock_af, SOCK_DGRAM, 0); + + if (fd == -1) + { + fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0); + if (fd < 0) + fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0); + if (fd < 0) + fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0); + if (fd < 0) + fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0); + } + + __libc_lock_unlock (lock); + return fd; +} +#endif + +unsigned int +if_nametoindex (const char *ifname) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return 0; +#else + struct ifreq ifr; + int fd = opensock (); + + if (fd < 0) + return 0; + + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; + close (fd); + if (saved_errno == EINVAL) + __set_errno (ENOSYS); + return 0; + } + close (fd); + return ifr.ifr_ifindex; +#endif +} + +void +if_freenameindex (struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + if (ptr->if_name) + free (ptr->if_name); + ++ptr; + } + free (ifn); +} + +struct if_nameindex * +if_nameindex (void) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else + int fd = opensock (); + struct ifconf ifc; + unsigned int nifs, i; + int rq_len; + struct if_nameindex *idx = NULL; + static int old_siocgifconf; +#define RQ_IFS 4 + + if (fd < 0) + return NULL; + + ifc.ifc_buf = NULL; + + /* We may be able to get the needed buffer size directly, rather than + guessing. */ + if (! old_siocgifconf) + { + ifc.ifc_buf = NULL; + ifc.ifc_len = 0; + if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0) + { + old_siocgifconf = 1; + rq_len = RQ_IFS * sizeof (struct ifreq); + } + else + rq_len = ifc.ifc_len; + } + else + rq_len = RQ_IFS * sizeof (struct ifreq); + + /* Read all the interfaces out of the kernel. */ + do + { + ifc.ifc_buf = alloca (ifc.ifc_len = rq_len); + if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0) + { + close (fd); + return NULL; + } + rq_len *= 2; + } + while (ifc.ifc_len == rq_len && old_siocgifconf); + + nifs = ifc.ifc_len / sizeof (struct ifreq); + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + close (fd); + return NULL; + } + + for (i = 0; i < nifs; ++i) + { + struct ifreq *ifr = &ifc.ifc_req[i]; + idx[i].if_name = strdup (ifr->ifr_name); + if (idx[i].if_name == NULL + || __ioctl (fd, SIOCGIFINDEX, ifr) < 0) + { + int saved_errno = errno; + unsigned int j; + + for (j = 0; j < i; ++j) + free (idx[j].if_name); + free (idx); + close (fd); + if (saved_errno == EINVAL) + __set_errno (ENOSYS); + return NULL; + } + idx[i].if_index = ifr->ifr_ifindex; + } + + idx[i].if_index = 0; + idx[i].if_name = NULL; + + close (fd); + return idx; +#endif +} + +char * +if_indextoname (unsigned int ifindex, char *ifname) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else + struct if_nameindex *idx; + struct if_nameindex *p; + char *result = NULL; + +#ifdef SIOCGIFNAME + /* We may be able to do the conversion directly, rather than searching a + list. This ioctl is not present in kernels before version 2.1.50. */ + struct ifreq ifr; + int fd; + static int siocgifname_works_not; + + if (!siocgifname_works_not) + { + int serrno = errno; + + fd = opensock (); + + if (fd < 0) + return NULL; + + ifr.ifr_ifindex = ifindex; + if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0) + { + if (errno == EINVAL) + siocgifname_works_not = 1; /* Don't make the same mistake twice. */ + } + else + { + close (fd); + return strncpy (ifname, ifr.ifr_name, IFNAMSIZ); + } + + close (fd); + + __set_errno (serrno); + } +#endif + + idx = if_nameindex (); + + if (idx != NULL) + { + for (p = idx; p->if_index || p->if_name; ++p) + if (p->if_index == ifindex) + { + result = strncpy (ifname, p->if_name, IFNAMSIZ); + break; + } + + if_freenameindex (idx); + } + return result; +#endif +} diff --git a/release/src/router/bridge/libbridge/libbridge.h b/release/src/router/bridge/libbridge/libbridge.h new file mode 100644 index 00000000..393a4477 --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge.h @@ -0,0 +1,135 @@ +/* + * $Id: libbridge.h,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LIBBRIDGE_H +#define _LIBBRIDGE_H + +#include <net/if.h> +#include <asm/types.h> +#include <linux/if_bridge.h> + +struct bridge; +struct bridge_info; +struct fdb_entry; +struct port; +struct port_info; + +struct bridge_id +{ + unsigned char prio[2]; + unsigned char addr[6]; +}; + +struct bridge_info +{ + struct bridge_id designated_root; + struct bridge_id bridge_id; + int root_path_cost; + struct timeval max_age; + struct timeval hello_time; + struct timeval forward_delay; + struct timeval bridge_max_age; + struct timeval bridge_hello_time; + struct timeval bridge_forward_delay; + unsigned topology_change:1; + unsigned topology_change_detected:1; + int root_port; + unsigned stp_enabled:1; + struct timeval ageing_time; + struct timeval gc_interval; + struct timeval hello_timer_value; + struct timeval tcn_timer_value; + struct timeval topology_change_timer_value; + struct timeval gc_timer_value; +}; + +struct bridge +{ + struct bridge *next; + + int ifindex; + char ifname[IFNAMSIZ]; + struct port *firstport; + struct port *ports[256]; + struct bridge_info info; +}; + +struct fdb_entry +{ + u_int8_t mac_addr[6]; + int port_no; + unsigned is_local:1; + struct timeval ageing_timer_value; +}; + +struct port_info +{ + struct bridge_id designated_root; + struct bridge_id designated_bridge; + u_int16_t port_id; + u_int16_t designated_port; + int path_cost; + int designated_cost; + int state; + unsigned top_change_ack:1; + unsigned config_pending:1; + struct timeval message_age_timer_value; + struct timeval forward_delay_timer_value; + struct timeval hold_timer_value; +}; + +struct port +{ + struct port *next; + + int index; + int ifindex; + struct bridge *parent; + struct port_info info; +}; + +extern struct bridge *bridge_list; + +int br_init(void); +int br_refresh(void); +struct bridge *br_find_bridge(char *brname); +struct port *br_find_port(struct bridge *br, char *portname); +char *br_get_state_name(int state); + +int br_add_bridge(char *brname); +int br_del_bridge(char *brname); +int br_add_interface(struct bridge *br, int ifindex); +int br_del_interface(struct bridge *br, int ifindex); +int br_set_bridge_forward_delay(struct bridge *br, struct timeval *tv); +int br_set_bridge_hello_time(struct bridge *br, struct timeval *tv); +int br_set_bridge_max_age(struct bridge *br, struct timeval *tv); +int br_set_ageing_time(struct bridge *br, struct timeval *tv); +int br_set_gc_interval(struct bridge *br, struct timeval *tv); +int br_set_stp_state(struct bridge *br, int stp_state); +int br_set_bridge_priority(struct bridge *br, int bridge_priority); +int br_set_port_priority(struct port *p, int port_priority); +int br_set_path_cost(struct port *p, int path_cost); +int br_read_fdb(struct bridge *br, struct fdb_entry *fdbs, int offset, int num); + +/* libc5 combatability */ +char *if_indextoname(unsigned int __ifindex, char *__ifname); +unsigned int if_nametoindex(const char *__ifname); + +#endif diff --git a/release/src/router/bridge/libbridge/libbridge_compat.c b/release/src/router/bridge/libbridge/libbridge_compat.c new file mode 100644 index 00000000..c2d6794a --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge_compat.c @@ -0,0 +1,30 @@ +/* + * Compatability glue for systems lacking the if_nametoindex and + * if_indextoname functions. + * + * The file 'if_index.c' was taken verbatimly from the GNU C Library + * version 2.1 (990920) and is Copyright (C) 1997, 1998, 1999 Free + * Software Foundation, Inc. + */ + +#define _BITS_LIBC_LOCK_H 1 +#define __libc_lock_define_initialized(a,b) +#define __libc_lock_lock(a) +#define __libc_lock_unlock(a) +#define __ioctl ioctl +#define __set_errno(a) {errno = (a);} +#define __socket socket +#define internal_function + +#include <features.h> +#if __GLIBC_MINOR__ < 1 +/* Return a list of all interfaces and their indices. */ + +struct if_nameindex + { + unsigned int if_index; /* 1, 2, ... */ + char *if_name; /* null terminated name: "eth0", ... */ + }; +#endif + +#include "if_index.c" diff --git a/release/src/router/bridge/libbridge/libbridge_devif.c b/release/src/router/bridge/libbridge/libbridge_devif.c new file mode 100644 index 00000000..6fabbf99 --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge_devif.c @@ -0,0 +1,172 @@ +/* + * $Id: libbridge_devif.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "libbridge.h" +#include "libbridge_private.h" + +int br_device_ioctl(struct bridge *br, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3) +{ + unsigned long args[4]; + struct ifreq ifr; + + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = arg3; + + memcpy(ifr.ifr_name, br->ifname, IFNAMSIZ); + ((unsigned long *)(&ifr.ifr_data))[0] = (unsigned long)args; + + return ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); +} + +int br_add_interface(struct bridge *br, int ifindex) +{ + if (br_device_ioctl(br, BRCTL_ADD_IF, ifindex, 0, 0) < 0) + return errno; + + return 0; +} + +int br_del_interface(struct bridge *br, int ifindex) +{ + if (br_device_ioctl(br, BRCTL_DEL_IF, ifindex, 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_bridge_forward_delay(struct bridge *br, struct timeval *tv) +{ + unsigned long jif = __tv_to_jiffies(tv); + + if (br_device_ioctl(br, BRCTL_SET_BRIDGE_FORWARD_DELAY, + jif, 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_bridge_hello_time(struct bridge *br, struct timeval *tv) +{ + unsigned long jif = __tv_to_jiffies(tv); + + if (br_device_ioctl(br, BRCTL_SET_BRIDGE_HELLO_TIME, jif, 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_bridge_max_age(struct bridge *br, struct timeval *tv) +{ + unsigned long jif = __tv_to_jiffies(tv); + + if (br_device_ioctl(br, BRCTL_SET_BRIDGE_MAX_AGE, jif, 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_ageing_time(struct bridge *br, struct timeval *tv) +{ + unsigned long jif = __tv_to_jiffies(tv); + + if (br_device_ioctl(br, BRCTL_SET_AGEING_TIME, jif, 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_gc_interval(struct bridge *br, struct timeval *tv) +{ + unsigned long jif = __tv_to_jiffies(tv); + + if (br_device_ioctl(br, BRCTL_SET_GC_INTERVAL, jif, 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_stp_state(struct bridge *br, int stp_state) +{ + if (br_device_ioctl(br, BRCTL_SET_BRIDGE_STP_STATE, stp_state, + 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_bridge_priority(struct bridge *br, int bridge_priority) +{ + if (br_device_ioctl(br, BRCTL_SET_BRIDGE_PRIORITY, bridge_priority, + 0, 0) < 0) + return errno; + + return 0; +} + +int br_set_port_priority(struct port *p, int port_priority) +{ + if (br_device_ioctl(p->parent, BRCTL_SET_PORT_PRIORITY, p->index, + port_priority, 0) < 0) + return errno; + + return 0; +} + +int br_set_path_cost(struct port *p, int path_cost) +{ + if (br_device_ioctl(p->parent, BRCTL_SET_PATH_COST, p->index, + path_cost, 0) < 0) + return errno; + + return 0; +} + +void __copy_fdb(struct fdb_entry *ent, struct __fdb_entry *f) +{ + memcpy(ent->mac_addr, f->mac_addr, 6); + ent->port_no = f->port_no; + ent->is_local = f->is_local; + __jiffies_to_tv(&ent->ageing_timer_value, f->ageing_timer_value); +} + +int br_read_fdb(struct bridge *br, struct fdb_entry *fdbs, int offset, int num) +{ + struct __fdb_entry f[num]; + int i; + int numread; + + if ((numread = br_device_ioctl(br, BRCTL_GET_FDB_ENTRIES, + (unsigned long)f, num, offset)) < 0) + return errno; + + for (i=0;i<numread;i++) + __copy_fdb(fdbs+i, f+i); + + return numread; +} diff --git a/release/src/router/bridge/libbridge/libbridge_if.c b/release/src/router/bridge/libbridge/libbridge_if.c new file mode 100644 index 00000000..bac04fd2 --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge_if.c @@ -0,0 +1,66 @@ +/* + * $Id: libbridge_if.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "libbridge.h" +#include "libbridge_private.h" + +int br_ioctl(unsigned long arg0, unsigned long arg1, unsigned long arg2) +{ + unsigned long arg[3]; + + arg[0] = arg0; + arg[1] = arg1; + arg[2] = arg2; + + return ioctl(br_socket_fd, SIOCGIFBR, arg); +} + +int br_get_version() +{ + return br_ioctl(BRCTL_GET_VERSION, 0, 0); +} + +int br_add_bridge(char *brname) +{ + char _br[IFNAMSIZ]; + + memcpy(_br, brname, IFNAMSIZ); + if (br_ioctl(BRCTL_ADD_BRIDGE, (unsigned long)_br, 0) < 0) + return errno; + + return 0; +} + +int br_del_bridge(char *brname) +{ + char _br[IFNAMSIZ]; + + memcpy(_br, brname, IFNAMSIZ); + if (br_ioctl(BRCTL_DEL_BRIDGE, (unsigned long)_br, 0) < 0) + return errno; + + return 0; +} diff --git a/release/src/router/bridge/libbridge/libbridge_init.c b/release/src/router/bridge/libbridge/libbridge_init.c new file mode 100644 index 00000000..787c467f --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge_init.c @@ -0,0 +1,226 @@ +/* + * $Id: libbridge_init.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "libbridge.h" +#include "libbridge_private.h" + +int br_socket_fd; +struct bridge *bridge_list; + +static void __bridge_info_copy(struct bridge_info *info, struct __bridge_info *i) +{ + memcpy(&info->designated_root, &i->designated_root, 8); + memcpy(&info->bridge_id, &i->bridge_id, 8); + info->root_path_cost = i->root_path_cost; + info->topology_change = i->topology_change; + info->topology_change_detected = i->topology_change_detected; + info->root_port = i->root_port; + info->stp_enabled = i->stp_enabled; + __jiffies_to_tv(&info->max_age, i->max_age); + __jiffies_to_tv(&info->hello_time, i->hello_time); + __jiffies_to_tv(&info->forward_delay, i->forward_delay); + __jiffies_to_tv(&info->bridge_max_age, i->bridge_max_age); + __jiffies_to_tv(&info->bridge_hello_time, i->bridge_hello_time); + __jiffies_to_tv(&info->bridge_forward_delay, i->bridge_forward_delay); + __jiffies_to_tv(&info->ageing_time, i->ageing_time); + __jiffies_to_tv(&info->gc_interval, i->gc_interval); + __jiffies_to_tv(&info->hello_timer_value, i->hello_timer_value); + __jiffies_to_tv(&info->tcn_timer_value, i->tcn_timer_value); + __jiffies_to_tv(&info->topology_change_timer_value, + i->topology_change_timer_value); + __jiffies_to_tv(&info->gc_timer_value, i->gc_timer_value); +} + +static void __port_info_copy(struct port_info *info, struct __port_info *i) +{ + memcpy(&info->designated_root, &i->designated_root, 8); + memcpy(&info->designated_bridge, &i->designated_bridge, 8); + info->port_id = i->port_id; + info->designated_port = i->designated_port; + info->path_cost = i->path_cost; + info->designated_cost = i->designated_cost; + info->state = i->state; + info->top_change_ack = i->top_change_ack; + info->config_pending = i->config_pending; + __jiffies_to_tv(&info->message_age_timer_value, + i->message_age_timer_value); + __jiffies_to_tv(&info->forward_delay_timer_value, + i->forward_delay_timer_value); + __jiffies_to_tv(&info->hold_timer_value, + i->hold_timer_value); +} + +int br_read_info(struct bridge *br) +{ + struct __bridge_info i; + + if (if_indextoname(br->ifindex, br->ifname) == NULL) + return 1; + + if (br_device_ioctl(br, BRCTL_GET_BRIDGE_INFO, + (unsigned long)&i, 0, 0) < 0) + return 1; + + __bridge_info_copy(&br->info, &i); + return 0; +} + +int br_read_port_info(struct port *p) +{ + struct __port_info i; + + if (br_device_ioctl(p->parent, BRCTL_GET_PORT_INFO, + (unsigned long)&i, p->index, 0) < 0) + return errno; + + __port_info_copy(&p->info, &i); + return 0; +} + +void br_nuke_bridge(struct bridge *b) +{ + struct port *p; + + p = b->firstport; + while (p != NULL) { + struct port *pnext; + + pnext = p->next; + free(p); + p = pnext; + } + + free(b); +} + +int br_make_port_list(struct bridge *br) +{ + int err; + int i; + int ifindices[256]; + + if (br_device_ioctl(br, BRCTL_GET_PORT_LIST, (unsigned long)ifindices, + 0, 0) < 0) + return errno; + + for (i=255;i>=0;i--) { + struct port *p; + + if (!ifindices[i]) + continue; + + p = malloc(sizeof(struct port)); + p->index = i; + p->ifindex = ifindices[i]; + p->parent = br; + br->ports[i] = p; + p->next = br->firstport; + br->firstport = p; + if ((err = br_read_port_info(p)) != 0) + goto error_out; + } + + return 0; + + error_out: + while (++i < 256) + free(br->ports[i]); + + return err; +} + +int br_make_bridge_list() +{ + int err; + int i; + int ifindices[32]; + int num; + + num = br_ioctl(BRCTL_GET_BRIDGES, (unsigned long)ifindices, 32); + if (num < 0) + return errno; + + bridge_list = NULL; + for (i=0;i<num;i++) { + struct bridge *br; + + br = malloc(sizeof(struct bridge)); + memset(br, 0, sizeof(struct bridge)); + br->ifindex = ifindices[i]; + br->firstport = NULL; + br->next = bridge_list; + bridge_list = br; + if ((err = br_read_info(br)) != 0) + goto error_out; + if ((err = br_make_port_list(br)) != 0) + goto error_out; + } + + return 0; + + error_out: + while (bridge_list != NULL) { + struct bridge *nxt; + + nxt = bridge_list->next; + br_nuke_bridge(bridge_list); + bridge_list = nxt; + } + + return err; +} + +int br_init() +{ + int err; + + if ((br_socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return errno; + + if (br_get_version() != BRCTL_VERSION) + return 12345; + + if ((err = br_make_bridge_list()) != 0) + return err; + + return 0; +} + +int br_refresh() +{ + struct bridge *b; + + b = bridge_list; + while (b != NULL) { + struct bridge *bnext; + + bnext = b->next; + br_nuke_bridge(b); + b = bnext; + } + + return br_make_bridge_list(); +} diff --git a/release/src/router/bridge/libbridge/libbridge_misc.c b/release/src/router/bridge/libbridge/libbridge_misc.c new file mode 100644 index 00000000..554c8729 --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge_misc.c @@ -0,0 +1,88 @@ +/* + * $Id: libbridge_misc.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <asm/param.h> +#include "libbridge.h" +#include "libbridge_private.h" + +unsigned long __tv_to_jiffies(struct timeval *tv) +{ + unsigned long jif; + + jif = 1000000 * tv->tv_sec + tv->tv_usec; + + return (HZ*jif)/1000000; +} + +void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies) +{ + unsigned long tvusec; + + tvusec = (1000000*jiffies)/HZ; + tv->tv_sec = tvusec/1000000; + tv->tv_usec = tvusec - 1000000 * tv->tv_sec; +} + +static char *state_names[5] = {"disabled", "listening", "learning", "forwarding", "blocking"}; + +char *br_get_state_name(int state) +{ + if (state >= 0 && state <= 4) + return state_names[state]; + + return "<INVALID STATE>"; +} + +struct bridge *br_find_bridge(char *brname) +{ + struct bridge *b; + + b = bridge_list; + while (b != NULL) { + if (!strcmp(b->ifname, brname)) + return b; + + b = b->next; + } + + return NULL; +} + +struct port *br_find_port(struct bridge *br, char *portname) +{ + char index; + struct port *p; + + if (!(index = if_nametoindex(portname))) + return NULL; + + p = br->firstport; + while (p != NULL) { + if (p->ifindex == index) + return p; + + p = p->next; + } + + return NULL; +} diff --git a/release/src/router/bridge/libbridge/libbridge_private.h b/release/src/router/bridge/libbridge/libbridge_private.h new file mode 100644 index 00000000..aad9bf4f --- /dev/null +++ b/release/src/router/bridge/libbridge/libbridge_private.h @@ -0,0 +1,43 @@ +/* + * $Id: libbridge_private.h,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * Copyright (C) 2000 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LIBBRIDGE_PRIVATE_H +#define _LIBBRIDGE_PRIVATE_H + +#include <asm/param.h> + +int br_socket_fd; + +unsigned long __tv_to_jiffies(struct timeval *tv); +void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies); + +int br_device_ioctl(struct bridge *br, + unsigned long arg0, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3); +int br_get_version(void); +int br_ioctl(unsigned long arg0, unsigned long arg1, unsigned long arg2); +int br_make_bridge_list(void); +int br_make_port_list(struct bridge *br); +int br_read_info(struct bridge *br); +int br_read_port_info(struct port *p); + +#endif diff --git a/release/src/router/bridge/misc/Makefile b/release/src/router/bridge/misc/Makefile new file mode 100644 index 00000000..795afd57 --- /dev/null +++ b/release/src/router/bridge/misc/Makefile @@ -0,0 +1,21 @@ +# $Id: Makefile,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + +CFLAGS = -Wall -g -O2 +ifeq ($(strip $(DOSTATIC)),true) + CFLAGS += --static +endif + + +all: bidi tap + +clean: + rcsclean * + rm -f *~ + rm -f bidi + rm -f tap + +bidi: bidi.c + $(CC) $(CFLAGS) -o bidi bidi.c + +tap: tap.c + $(CC) $(CFLAGS) -o tap tap.c diff --git a/release/src/router/bridge/misc/README b/release/src/router/bridge/misc/README new file mode 100644 index 00000000..902596ce --- /dev/null +++ b/release/src/router/bridge/misc/README @@ -0,0 +1,29 @@ +$Id: README,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + + + +Files in this directory: + +bidi.c A quick-and-dirty hack that allows you to 'connect' + multiple file descriptors together (everything + received on one fd will be sent out to all the other + fds). Works great for tying ethertaps together (for + testing stp protocol interaction et al.). + + The command-line arguments are the names of the + ethertaps to be connected together. + + +tap.c Another quick-and-dirty hack which will let you + connect different machine's ethertaps together over + the network. This program works over raw IP, protocol + number 97. RFC 1700 lists IP proto 97 as ethernet + encapsulation; I have never seen the standard for + this, I'm just guessing at the encapsulation being + performed. So this program is potentially in violation + of a standard; USE ONLY FOR TESTING! + + The first command-line argument is the name of the + ethertap to use, the following command-line arguments + are the hostnames of the machines to forward frames + to. diff --git a/release/src/router/bridge/misc/bidi.c b/release/src/router/bridge/misc/bidi.c new file mode 100644 index 00000000..d84ae195 --- /dev/null +++ b/release/src/router/bridge/misc/bidi.c @@ -0,0 +1,99 @@ +/* + * $Id: bidi.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/poll.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +char *names[1024]; +int numfds; +struct pollfd pfd[1024]; + +void rcvd_packet(int index, unsigned char *buf, int len) +{ + int i; + int dmp; + + printf("%s: %i\n", names[index], len); + dmp = (len + 15) >> 4; + if (dmp > 8) + dmp = 8; + + for (i=0;i<dmp;i++) { + int j; + + for (j=0;j<16;j++) + printf("%.2x ", buf[(i<<4)|j]); + + printf("\n"); + } + + printf("\n"); +} + +void loop() +{ + while (1) { + int i; + + if (poll(pfd, numfds, -1) < 0) { + perror("poll"); + break; + } + + for (i=0;i<numfds;i++) { + unsigned char buf[2048]; + int j; + int len; + + if (!(pfd[i].revents & POLLIN)) + continue; + + if ((len = read(pfd[i].fd, buf, 2048)) < 0) + continue; + + rcvd_packet(i, buf, len); + for (j=0;j<numfds;j++) + if (i != j) + write(pfd[j].fd, buf, len); + } + } +} + +void openfds(int argc, char *argv[]) +{ + int i; + + numfds = 0; + for (i=1;i<argc;i++) { + int fd; + + if ((fd = open(argv[i], O_RDWR)) < 0) { + perror("open"); + continue; + } + + names[numfds] = argv[i]; + pfd[numfds].fd = fd; + pfd[numfds].events = POLLIN; + numfds++; + } +} + +int main(int argc, char *argv[]) +{ + openfds(argc, argv); + loop(); + + return 0; +} diff --git a/release/src/router/bridge/misc/tap.c b/release/src/router/bridge/misc/tap.c new file mode 100644 index 00000000..3fdfe7b3 --- /dev/null +++ b/release/src/router/bridge/misc/tap.c @@ -0,0 +1,146 @@ +/* + * $Id: tap.c,v 1.1.1.4 2003/10/14 08:09:37 sparq Exp $ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#define MAXREMOTE 128 + +struct sockaddr_in6 localaddr; +int numremote; +struct sockaddr_in6 remoteaddr[MAXREMOTE]; +int sock; +int tap; +char *tapdevice; + + + +int getaddr(const char *hostname, struct sockaddr_in6 *in) +{ + struct hostent *he; + + in->sin6_port = 0; + + if ((he = gethostbyname2(hostname, AF_INET6)) != NULL) { + in->sin6_family = he->h_addrtype; + memcpy(in->sin6_addr.s6_addr, he->h_addr_list[0], he->h_length); + return 0; + } + + if ((he = gethostbyname2(hostname, AF_INET)) != NULL) { + in->sin6_family = AF_INET6; + memset(in->sin6_addr.s6_addr, 0, 10); + in->sin6_addr.s6_addr[10] = 0; + in->sin6_addr.s6_addr[11] = 0; + memcpy(in->sin6_addr.s6_addr + 12, he->h_addr_list[0], he->h_length); + return 0; + } + + return 1; +} + +void handle() +{ + struct pollfd pfd[2]; + + pfd[0].fd = tap; + pfd[0].events = POLLIN; + pfd[1].fd = sock; + pfd[1].events = POLLIN; + + while (1) { + unsigned char buf[2048]; + int len; + + if (poll(pfd, 2, -1) <= 0) { + perror("poll"); + break; + } + + if (pfd[0].revents & POLLIN) { + int i; + + if ((len = read(pfd[0].fd, buf, 2048)) < 0) { + perror("read"); + break; + } + for (i=0;i<numremote;i++) + if (sendto(pfd[1].fd, buf+2, len-2, 0, + &remoteaddr[i], + sizeof(remoteaddr[i])) < 0) { + perror("sendto"); + break; + } + } + + if (pfd[1].revents & POLLIN) { + if ((len = read(pfd[1].fd, buf+2, 2046)) < 0) { + perror("read"); + break; + } + if (write(pfd[0].fd, buf, len+2) < 0) { + perror("write"); + break; + } + } + } + + shutdown(sock, 2); +} + +int main(int argc, char *argv[]) +{ + int i; + + if (argc < 3) { + fprintf(stderr, "syntax: %s <tapdevice> <remotename>\n", argv[0]); + return 1; + } + + tapdevice = argv[1]; + + numremote = argc - 2; + for (i=2;i<argc;i++) + if (getaddr(argv[i], &remoteaddr[i-2])) { + fprintf(stderr, + "can't resolve hostname %s\n", + argv[i]); + return 1; + } + + if ((tap = open(tapdevice, O_RDWR)) < 0) { + perror("open"); + return 1; + } + + if ((sock = socket(AF_INET6, SOCK_RAW, 97)) < 0) { + perror("socket"); + return 1; + } + + localaddr.sin6_family = AF_INET6; + localaddr.sin6_addr = in6addr_any; + localaddr.sin6_port = 0; + if (bind(sock, &localaddr, sizeof(localaddr)) < 0) { + perror("bind"); + return 1; + } + + handle(); + + return 0; +} diff --git a/release/src/router/bridge/scripts/setdown b/release/src/router/bridge/scripts/setdown new file mode 100755 index 00000000..9082b9b8 --- /dev/null +++ b/release/src/router/bridge/scripts/setdown @@ -0,0 +1,5 @@ +#!/bin/sh + +ifconfig br0 down +brctl delbr br0 +rmmod bridge diff --git a/release/src/router/bridge/scripts/setdown2 b/release/src/router/bridge/scripts/setdown2 new file mode 100755 index 00000000..82a18ee9 --- /dev/null +++ b/release/src/router/bridge/scripts/setdown2 @@ -0,0 +1,9 @@ +#!/bin/sh + +ifconfig br2 down +ifconfig br1 down +ifconfig br0 down +brctl delbr br2 +brctl delbr br1 +brctl delbr br0 +rmmod bridge diff --git a/release/src/router/bridge/scripts/setup b/release/src/router/bridge/scripts/setup new file mode 100755 index 00000000..3e6f42db --- /dev/null +++ b/release/src/router/bridge/scripts/setup @@ -0,0 +1,10 @@ +#!/bin/sh + +insmod bridge +brctl addbr br0 +brctl setfd br0 2 +brctl addif br0 tap0 +brctl addif br0 tap1 +brctl addif br0 tap2 +brctl addif br0 tap3 +ifconfig br0 192.168.253.1 up diff --git a/release/src/router/bridge/scripts/setup2 b/release/src/router/bridge/scripts/setup2 new file mode 100755 index 00000000..83babf67 --- /dev/null +++ b/release/src/router/bridge/scripts/setup2 @@ -0,0 +1,18 @@ +#!/bin/sh + +insmod bridge +brctl addbr br0 +brctl addbr br1 +brctl addbr br2 +brctl addif br0 tap0 +brctl addif br0 tap1 +brctl addif br0 tap2 +brctl addif br1 tap3 +brctl addif br1 tap4 +brctl addif br1 tap5 +brctl addif br2 tap6 +brctl addif br2 tap7 +brctl addif br2 tap8 +ifconfig br0 up +ifconfig br1 up +ifconfig br2 up |