summaryrefslogtreecommitdiff
path: root/release/src/router/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'release/src/router/bridge')
-rw-r--r--release/src/router/bridge/AUTHORS1
-rw-r--r--release/src/router/bridge/COPYING340
-rw-r--r--release/src/router/bridge/Makefile26
-rw-r--r--release/src/router/bridge/README68
-rw-r--r--release/src/router/bridge/THANKS43
-rw-r--r--release/src/router/bridge/brctl/Makefile36
-rw-r--r--release/src/router/bridge/brctl/brctl.c95
-rw-r--r--release/src/router/bridge/brctl/brctl.h37
-rw-r--r--release/src/router/bridge/brctl/brctl_cmd.c322
-rw-r--r--release/src/router/bridge/brctl/brctl_disp.c128
-rw-r--r--release/src/router/bridge/brctl/brctld.c210
-rw-r--r--release/src/router/bridge/bridge-utils.spec68
-rw-r--r--release/src/router/bridge/doc/FAQ76
-rw-r--r--release/src/router/bridge/doc/FIREWALL38
-rw-r--r--release/src/router/bridge/doc/HOWTO112
-rw-r--r--release/src/router/bridge/doc/Makefile5
-rw-r--r--release/src/router/bridge/doc/PROJECTS4
-rw-r--r--release/src/router/bridge/doc/RPM-GPG-KEY32
-rw-r--r--release/src/router/bridge/doc/SMPNOTES23
-rw-r--r--release/src/router/bridge/doc/TODO31
-rw-r--r--release/src/router/bridge/doc/WISHLIST30
-rw-r--r--release/src/router/bridge/doc/brctl.8172
-rw-r--r--release/src/router/bridge/libbridge/Makefile28
-rw-r--r--release/src/router/bridge/libbridge/bits/libc-lock.h327
-rw-r--r--release/src/router/bridge/libbridge/if_index.c263
-rw-r--r--release/src/router/bridge/libbridge/libbridge.h135
-rw-r--r--release/src/router/bridge/libbridge/libbridge_compat.c30
-rw-r--r--release/src/router/bridge/libbridge/libbridge_devif.c172
-rw-r--r--release/src/router/bridge/libbridge/libbridge_if.c66
-rw-r--r--release/src/router/bridge/libbridge/libbridge_init.c226
-rw-r--r--release/src/router/bridge/libbridge/libbridge_misc.c88
-rw-r--r--release/src/router/bridge/libbridge/libbridge_private.h43
-rw-r--r--release/src/router/bridge/misc/Makefile21
-rw-r--r--release/src/router/bridge/misc/README29
-rw-r--r--release/src/router/bridge/misc/bidi.c99
-rw-r--r--release/src/router/bridge/misc/tap.c146
-rwxr-xr-xrelease/src/router/bridge/scripts/setdown5
-rwxr-xr-xrelease/src/router/bridge/scripts/setdown29
-rwxr-xr-xrelease/src/router/bridge/scripts/setup10
-rwxr-xr-xrelease/src/router/bridge/scripts/setup218
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